From f3629a30cbc6aec22d00f837a3baa42174928759 Mon Sep 17 00:00:00 2001 From: Shaman <48730089+Arch-Shaman@users.noreply.github.com> Date: Thu, 10 Jul 2025 04:02:01 -0400 Subject: [PATCH 1/2] Sync Commander UI with FW's latest improvements --- ...ommander_upgrade_localization_settings.lua | 26 ++ LuaUI/Widgets/gui_chili_commander_upgrade.lua | 330 ++++++++++++++---- 2 files changed, 293 insertions(+), 63 deletions(-) create mode 100644 LuaUI/Configs/commander_upgrade_localization_settings.lua diff --git a/LuaUI/Configs/commander_upgrade_localization_settings.lua b/LuaUI/Configs/commander_upgrade_localization_settings.lua new file mode 100644 index 0000000000..089ae59dab --- /dev/null +++ b/LuaUI/Configs/commander_upgrade_localization_settings.lua @@ -0,0 +1,26 @@ +-- Nullweapon and Nulladvweapon are both technical junk that users should NOT see. Replace them with default weapons and force them to select a weapon. Beam laser is free IIRC. +local defaultWeapons = { + [1] = "commweapon_beamlaser", -- strike + [2] = "commweapon_beamlaser", -- recon + [3] = "commweapon_beamlaser", -- support + [4] = "commweapon_beamlaser", -- bombard + [5] = "commweapon_beamlaser", -- knight? + [6] = "commweapon_beamlaser", -- knight? +} + +local needsExtraParameters = { + ["module_heavy_armor"] = true, + ["module_fireproofing"] = true, + ["module_high_power_servos_improved"] = true, + ["module_cloakregen"] = true, +} + +local moduleTranslationOverrides = { + ["module_heavyprojector_second"] = "module_heavyprojector", + ["module_shotgunlaser_second"] = "module_shotgunlaser", + ["module_heavyordinance_second"] = "module_heavyordinance", + ["module_heavy_barrel2"] = "module_heavy_barrel", + ["nulladvweapon"] = "nullbasicweapon", +} + +return defaultWeapons, needsExtraParameters, moduleTranslationOverrides diff --git a/LuaUI/Widgets/gui_chili_commander_upgrade.lua b/LuaUI/Widgets/gui_chili_commander_upgrade.lua index 378bd94a8e..ebd610d012 100644 --- a/LuaUI/Widgets/gui_chili_commander_upgrade.lua +++ b/LuaUI/Widgets/gui_chili_commander_upgrade.lua @@ -19,6 +19,9 @@ end include("colors.lua") VFS.Include("LuaRules/Configs/constants.lua") +local defaultWeapons, needsExtraHelp, translationOverrides = VFS.Include("LuaUI/Configs/commander_upgrade_localization_settings.lua") +local CMD_MORPH_UPGRADE_INTERNAL = Spring.Utilities.CMD.MORPH_UPGRADE_INTERNAL +local CMD_UPGRADE_UNIT = Spring.Utilities.CMD.UPGRADE_UNIT local Chili local Button @@ -30,6 +33,18 @@ local LayoutPanel local Image local screen0 +local localization = {} + +local HP_MULT = 1 +if (Spring.GetModOptions) then + local modOptions = Spring.GetModOptions() + if modOptions then + if modOptions.hpmult and modOptions.hpmult ~= 1 then + HP_MULT = modOptions.hpmult + end + end +end + -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- Most things are local to their own code block. These blocks are (in order) @@ -51,8 +66,9 @@ local screen0 -- Module config local moduleDefs, chassisDefs, upgradeUtilities, LEVEL_BOUND, _, moduleDefNames = VFS.Include("LuaRules/Configs/dynamic_comm_defs.lua") - -VFS.Include("LuaRules/Configs/customcmds.h.lua") +WG.ModuleTranslations = {} -- Store these so we can use them in Context Menu as well as the comm upgrade one. +local nullweapon = moduleDefNames["nullbasicweapon"] +local nulladvweapon = moduleDefNames["nulladvweapon"] -- Configurable things, possible to add to Epic Menu later. local BUTTON_SIZE = 55 @@ -61,9 +77,6 @@ local ROW_COUNT = 6 -- Index of module which is selected for the purposes of replacement. local activeSlotIndex --- Current commander cost multiplier -local costMultiplier = 1 - -- Whether already owned modules are shown local alreadyOwnedShown = false @@ -75,6 +88,9 @@ local viewAlreadyOwnedButton local moduleTextColor = {.8,.8,.8,.9} +local damageBooster = 1 +local rangeBooster = 1 + local commanderUnitDefID = {} for i = 1, #UnitDefs do if UnitDefs[i].customParams.dynamic_comm then @@ -92,12 +108,200 @@ local UPGRADE_CMD_DESC = { texture = 'LuaUI/Images/commands/Bold/upgrade.png', } +local weaponTemplate, shieldTemplate, aoeTemplate, waterCapableTemplate +local acceptText, cancelText, viewText + +local function GetWeaponTemplate() + weaponTemplate = "\n\255\255\061\061" .. WG.Translate("interface", "module_weapon_notes") .. ":\n\255\255\255\031- " .. WG.Translate("interface", "stats_range") .. ":\255\255\255\255_range_" + weaponTemplate = weaponTemplate .. "\n\255\255\255\031- " .. WG.Translate("interface", "acronyms_dps") .. ":\255\255\255\255_dps_\n" + shieldTemplate = "\n" .. WG.Translate("interface", "shield_hp") .. ":\255\255\255\255 %shield_hp%\n\255\255\255\031" .. WG.Translate("interface", "regen") .. ":\255\255\255\255 %shieldregen%\n\255\255\255\031" .. WG.Translate("interface", "shield_regencost") .. ": \255\255\255\255 %shieldregencost%" + aoeTemplate = "\n\255\255\255\031- " .. WG.Translate("interface", "stats_aoe") .. ":\255\255\255\255 _aoe_\n" + waterCapableTemplate = "\n\255\255\255\031- \255\031\255\255" .. WG.Translate("interface", "weapon_water_capable") .. "\255\255\255\255" +end + +local function OnLocaleChanged() + acceptText = WG.Translate("interface", "commupgrade_accept") + cancelText = WG.Translate("interface", "commupgrade_cancel") + viewText = WG.Translate("interface", "commupgrade_view") + local cost = WG.Translate("interface", "commodule_cost") + local limit = WG.Translate("interface", "commodule_limit") + local hp = WG.Translate("interface", "acronyms_hp") + local sec = WG.Translate("interface", "acronyms_second") + GetWeaponTemplate() -- reduce the number of translations we need to do. + for internalName, translation in pairs(WG.ModuleTranslations) do + local def = moduleDefs[moduleDefNames[internalName]] + local name + --spring.echo("Translating " .. internalName) + if translationOverrides[internalName] then + name = WG.Translate("interface", translationOverrides[internalName] .. "_name") + --spring.echo("Overriding " .. internalName .. " -> " .. translationOverrides[internalName] .. ": '" .. tostring(name) .. "'") + else + --spring.echo("No override needed") + name = WG.Translate("interface", internalName .. "_name") + end + WG.ModuleTranslations[internalName].name = name + local descStringName = internalName .. "_desc" + local desc = name .. "\n" .. cost .. def.cost .. "\n" + if def.slotType ~= "basic_weapon" and def.slotType ~= "adv_weapon" then + desc = desc .. limit .. ": " + local moduleLimit = def.limit + if moduleLimit then + desc = desc .. moduleLimit .. "\n\n" + else + desc = desc .. "∞\n\n" + end + end + if internalName == "module_detpack" then + desc = desc .. "\n" .. WG.Translate("interface", descStringName, {health = 1000*HP_MULT}) + elseif internalName == "module_autorepair" then + desc = desc .. "\n" .. WG.Translate("interface", descStringName, {health = 20*HP_MULT .. hp .. "/" .. sec}) + elseif internalName == "module_nanorepair_upgrade_regen" then + desc = desc .. "\n" .. WG.Translate("interface", descStringName, {regen_mult = 3 * HP_MULT, max_regen = 30 * HP_MULT, max_health = 500 * HP_MULT}) + elseif internalName == "module_ablative_armor" then + desc = desc .. "\n" .. WG.Translate("interface", descStringName, {health = 1200 * HP_MULT}) + elseif internalName == "module_heavy_armor" then + desc = desc .. "\n" .. WG.Translate("interface", descStringName, {health = 4000 * HP_MULT}) + elseif internalName == "module_fireproofing" then + desc = desc .. "\n" .. WG.Translate("interface", descStringName, {health = 550 * HP_MULT}) + elseif internalName == "module_high_power_servos_improved" then + desc = desc .. "\n" .. WG.Translate("interface", descStringName, {health = 500*HP_MULT}) + elseif internalName == "module_cloakregen" then + desc = desc .. "\n" .. WG.Translate("interface", descStringName, {health = 20*HP_MULT .. " " .. hp .. "/" .. sec}) + else + if translationOverrides[internalName] then + desc = desc .. "\n" .. WG.Translate("interface", translationOverrides[internalName] .. "_desc") + else + desc = desc .. "\n" .. WG.Translate("interface", internalName .. "_desc") + end + end + if def.slotType == "basic_weapon" or def.slotType == "adv_weapon" then -- add stats + local wd + if internalName == "commweapon_heatray_recon" then + wd = WeaponDefNames["0_commweapon_heatray"] + else + wd = WeaponDefNames["0_" .. internalName] + end + desc = desc .. weaponTemplate + if wd then + if not wd.impactOnly then + desc = desc .. "\n" .. aoeTemplate + desc = desc:gsub("_aoe_", wd.damageAreaOfEffect) + end + if wd.waterWeapon then + desc = desc .. waterCapableTemplate + end + else + --spring.echo("Unable to load " .. internalName .. " weaponDef, skipping") + end + elseif internalName:find("shield") then + desc = desc .. shieldTemplate + end + translation.desc = desc + --Spring.Echo("Done. " .. internalName .. " : " .. tostring(desc)) + end + --spring.echo("Finished setting up translation") +end + -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- New Module Selection Button Handling local newButtons = {} +local function GetModuleDescription(moduleData) -- dynamically updated. + local isShield = moduleData.name:find("shield") ~= nil + if moduleData.slotType == "module" and not isShield then + return WG.ModuleTranslations[moduleData.name].desc + else -- dynamically generated. + if not isShield then + local name = moduleData.name + --spring.echo("GetModuleDescription::InternalName: " .. tostring(name)) + + local wd + if name == "commweapon_heatray_recon" then + wd = WeaponDefNames["0_commweapon_heatray"] + else + wd = WeaponDefNames["0_" .. name] + end + local description = WG.ModuleTranslations[name].desc + if wd then + local aoe = wd.damageAreaOfEffect + local reload = wd.reload + local customparams = wd.customParams or wd.customparams or {} + local extradps = "" -- damagemult, rangemult + local dps = "" + local projectiles = wd.projectiles or 1 + local burst = wd.burst or 1 + local damage = wd.damages[1] * burst * projectiles + if customparams.extra_damage_mult then -- emp + --spring.echo("EMP") + local extradmg = tonumber(customparams.extra_damage_mult) or 0 + local empdps = (extradmg * damage * damageBooster) / reload + extradps = extradps .. "\255\51\179\255" .. string.format("%.1f", empdps) .. "P\255\255\255\255" + end + --spring.echo("EMP: " .. extradps) + if customparams.is_capture then + local capture = " \255\153\255\153" .. string.format("%.1f", damage * damageBooster / reload) .. WG.Translate("interface", "acronyms_capture") .. "\255\255\255\255" + if extradps == "" then + extradps = capture + else + extradps = extradps .. " \255\255\255\031+" .. capture + end + end + if customparams.timeslow_damagefactor or customparams.timeslow_onlyslow then + local factor = tonumber(customparams.timeslow_damagefactor) or 0 + if factor * damage > 0 then + local slow = damage * damageBooster * factor + local slowstr = "\255\230\51\255" .. string.format("%.1f", slow) .. WG.Translate("interface", "acronyms_slow") .. "\255\255\255\255" + if extradps == "" then + extradps = slowstr + else + extradps = extradps .. "\255\255\255\031+ " .. slowstr + end + end + end + if customparams.disarmDamageOnly or customparams.disarmdamageonly then + local disarm = "\255\128\128\128" .. string.format("%.1f", damage * damageBooster / reload) .. WG.Translate("interface", "acronyms_disarm") .. "\255\255\255\255" + if extradps ~= "" then + extradps = extradps .. " \255\255\255\031+\255\128\128\128 " .. disarm + else + extradps = disarm + end + end + --spring.echo("Disarm: " .. extradps) + if wd.paralyzeTime == nil and wd.paralyzetime == nil then + if not customparams.disarmDamageOnly and not customparams.disarmdamageonly and not customparams.timeslow_onlyslow then + dps = "\255\255\255\255 " .. string.format("%.1f", damage * damageBooster / reload) + end + else + dps = "\255\51\179\255 " .. string.format("%.1f", damage * damageBooster / reload) .. "P" + end + --spring.echo("Final: " .. extradps) + if extradps ~= "" and dps ~= "" then + description = string.gsub(description, "_dps_", dps .. "(" .. extradps .. ")") + elseif dps == "" then + description = string.gsub(description, "_dps_", extradps) + else + description = string.gsub(description, "_dps_", dps) + end + description = string.gsub(description, "_dps_", extradps .. dps) + description = string.gsub(description, "_range_", wd.range * rangeBooster) + if customparams.setunitsonfire then + local burntime = tonumber(customparams.burntime) or 0 + burntime = burntime / 30 -- convert to seconds + description = description .. "\255\255\77\0 " .. string.format("%.1f", damage * damageBooster / reload) .. " (" .. string.format("%.1f", burntime) .. WG.Translate("interface", "acronyms_second") .. ")" + end + if aoe > 16 and not wd.impactOnly then + description = description:gsub("_aoe_", aoe) + end + return description + else + --spring.echo("Failed to load weapondef for " .. moduleData.name) + end + end + end +end + local function AddNewSelectonButton(buttonIndex, moduleDefID) local moduleData = moduleDefs[moduleDefID] local newButton = Button:New{ @@ -112,7 +316,7 @@ local function AddNewSelectonButton(buttonIndex, moduleDefID) }, backgroundColor = {0.5,0.5,0.5,0.1}, color = {1,1,1,0.1}, - tooltip = moduleData.description + tooltip = GetModuleDescription(moduleData) } Image:New{ @@ -133,7 +337,7 @@ end local function UpdateNewSelectionButton(buttonIndex, moduleDefID) local moduleData = moduleDefs[moduleDefID] local button = newButtons[buttonIndex] - button.tooltip = moduleData.description + button.tooltip = GetModuleDescription(moduleData) button.moduleDefID = moduleDefID button.children[1].file = moduleData.image button.children[1]:Invalidate() @@ -310,6 +514,7 @@ local function GetAlreadyOwned() end local function GetSlotModule(slot, emptyModule) + --spring.echo("EmptyModule: " .. tostring(emptyModule)) return currentModulesBySlot[slot] or emptyModule end @@ -333,6 +538,17 @@ local function ModuleIsValid(level, chassis, slotAllows, slotIndex) return upgradeUtilities.ModuleIsValid(level, chassis, slotAllows, moduleDefID, alreadyOwnedModulesByDefID, currentModulesByDefID) end +local function CountModulesInSet(set, ignoreSlot) + local count = 0 + for i = 1, #set do + local req = set[i] + count = count + (alreadyOwnedModulesByDefID[req] or 0) + + (currentModulesByDefID[req] or 0) + - (currentModulesBySlot[ignoreSlot] == req and 1 or 0) + end + return count +end + local function GetNewReplacementSet(level, chassis, slotAllows, ignoreSlot) local replacementSet = {} local haveEmpty = false @@ -343,43 +559,22 @@ local function GetNewReplacementSet(level, chassis, slotAllows, ignoreSlot) local accepted = true -- Check whether required modules are present, not counting ignored slot - if data.requireOneOf then - local foundRequirement = false - for j = 1, #data.requireOneOf do - local req = data.requireOneOf[j] - if (alreadyOwnedModulesByDefID[req] or - (currentModulesByDefID[req] and - (currentModulesBySlot[ignoreSlot] ~= req or - currentModulesByDefID[req] > 1))) then - - foundRequirement = true - break - end - end - if not foundRequirement then - accepted = false - end + if data.requireOneOf and CountModulesInSet(data.requireOneOf, ignoreSlot) < 1 then + accepted = false + end + if data.requireTwoOf and CountModulesInSet(data.requireTwoOf, ignoreSlot) < 2 then + accepted = false end -- Check whether prohibited modules are present, not counting ignored slot - if accepted and data.prohibitingModules then - for j = 1, #data.prohibitingModules do - local prohibit = data.prohibitingModules[j] - if (alreadyOwnedModulesByDefID[prohibit] or - (currentModulesByDefID[prohibit] and - (currentModulesBySlot[ignoreSlot] ~= prohibit or - currentModulesByDefID[prohibit] > 1))) then - - accepted = false - break - end - end + if accepted and data.prohibitingModules and CountModulesInSet(data.prohibitingModules, ignoreSlot) > 0 then + accepted = false end -- cheapass hack to prevent cremcom dual wielding same weapon (not supported atm) -- proper solution: make the second instance of a weapon apply projectiles x2 or reloadtime x0.5 and get cremcoms unit script to work with that local limit = data.limit - if chassis == 5 and data.slotType == "basic_weapon" and limit == 2 then + if chassis == 6 and data.slotType == "basic_weapon" and limit == 2 then limit = 1 end @@ -404,7 +599,7 @@ local function GetNewReplacementSet(level, chassis, slotAllows, ignoreSlot) end -- Add the module once accepted - if accepted then + if accepted and i ~= nullweapon and i ~= nulladvweapon then replacementSet[#replacementSet + 1] = i end end @@ -481,7 +676,7 @@ local function AddCurrentModuleButton(slotIndex, moduleDefID) CurrentModuleClick(self, slotIndex) end }, - tooltip = moduleData.description + tooltip = GetModuleDescription(moduleData) } Image:New{ @@ -499,7 +694,7 @@ local function AddCurrentModuleButton(slotIndex, moduleDefID) right = 8, bottom = 8, valign = "left", - text = moduleData.humanName, + text = WG.ModuleTranslations[moduleData.name].name, font = {size = 16, outline = true, color = moduleTextColor, outlineWidth = 2, outlineWeight = 2}, parent = newButton, } @@ -513,14 +708,15 @@ end local function ModuleReplacmentWithButton(slotIndex, moduleDefID) local moduleData = moduleDefs[moduleDefID] local button = currentModuleButton[slotIndex] - button.tooltip = moduleData.description + button.tooltip = GetModuleDescription(moduleData) button.children[1].file = moduleData.image button.children[1]:Invalidate() - button.children[2]:SetText(moduleData.humanName) + button.children[2]:SetText(WG.ModuleTranslations[moduleData.name].name) + --spring.echo("SetChild2: " .. WG.ModuleTranslations[moduleData.name].name) UpdateSlotModule(slotIndex, moduleDefID) end -local function GetCurrentModuleButton(moduleDefID, slotIndex, level, chassis, slotAllows, empty) +local function GetCurrentModuleButton(moduleDefID, slotIndex, level, chassis, slotAllows, empty, alreadyOwnedModules) if not currentModuleButton[slotIndex] then AddCurrentModuleButton(slotIndex, moduleDefID) end @@ -531,7 +727,11 @@ local function GetCurrentModuleButton(moduleDefID, slotIndex, level, chassis, sl current.level = level current.chassis = chassis current.slotAllows = slotAllows - current.empty = empty + if empty ~= nullweapon and empty ~= nulladvweapon then + current.empty = empty + else + current.empty = defaultWeapons[chassis] + end current.replacementSet = GetNewReplacementSet(level, chassis, slotAllows, slotIndex) ModuleReplacmentWithButton(slotIndex, moduleDefID) @@ -585,8 +785,8 @@ local mainWindowShown = false local mainWindow, timeLabel, costLabel, morphBuildPower function UpdateMorphCost(newCost) - newCost = ((newCost or 0) + morphBaseCost) - costLabel:SetCaption(math.floor(costMultiplier * newCost)) + newCost = (newCost or 0) + morphBaseCost + costLabel:SetCaption(math.floor(newCost)) timeLabel:SetCaption(math.floor(newCost/morphBuildPower)) end @@ -708,7 +908,7 @@ local function CreateMainWindow() height = 55, padding = {0, 0, 0, 0}, backgroundColor = {0.5,0.5,0.5,0.5}, - tooltip = "Start upgrade", + tooltip = acceptText, OnClick = { function() if mainWindowShown then @@ -727,7 +927,7 @@ local function CreateMainWindow() height = 55, padding = {0, 0, 0, 0}, backgroundColor = {0.5,0.5,0.5,0.5}, - tooltip = "View current modules", + tooltip = viewText, OnClick = { function(self) AlreadyOwnedModuleClick(self) @@ -744,10 +944,10 @@ local function CreateMainWindow() height = 55, padding = {0, 0, 0, 0}, backgroundColor = {0.5,0.5,0.5,0.5}, - tooltip = "Cancel module selection", + tooltip = cancelText, OnClick = { function() - --Spring.Echo("Upgrade UI Debug - Cancel Clicked") + ----spring.echo("Upgrade UI Debug - Cancel Clicked") HideMainWindow() end }, @@ -785,7 +985,7 @@ local function CreateMainWindow() } end -local function ShowModuleListWindow(unitID, slotDefaults, level, chassis, alreadyOwnedModules) +local function ShowModuleListWindow(slotDefaults, level, chassis, alreadyOwnedModules) if not currentModuleList then CreateMainWindow() end @@ -799,9 +999,6 @@ local function ShowModuleListWindow(unitID, slotDefaults, level, chassis, alread morphBuildPower = chassisDefs[chassis].levelDefs[level].morphBuildPower end - if Spring.ValidUnitID(unitID) then - morphBuildPower = morphBuildPower * (Spring.GetGameRulesParam("econ_mult_" .. (Spring.GetUnitAllyTeam(unitID) or "")) or 1) - end local slots = chassisDefs[chassis].levelDefs[level].upgradeSlots if not mainWindowShown then @@ -850,7 +1047,7 @@ local function ShowModuleListWindow(unitID, slotDefaults, level, chassis, alread -- Actually add the default modules and slot data for i = 1, #slots do local slotData = slots[i] - currentModuleList:AddChild(GetCurrentModuleButton(GetSlotModule(i, slotData.empty), i, level, chassis, slotData.slotAllows, slotData.empty)) + currentModuleList:AddChild(GetCurrentModuleButton(GetSlotModule(i, slotData.empty), i, level, chassis, slotData.slotAllows, slotData.empty, alreadyOwnedModules)) end end @@ -906,7 +1103,7 @@ function SendUpgradeCommand(newModules) end -- Remove main window - --Spring.Echo("Upgrade UI Debug - Upgrade Command Sent") + ----spring.echo("Upgrade UI Debug - Upgrade Command Sent") HideMainWindow() end @@ -928,7 +1125,6 @@ local function CreateModuleListWindowFromUnit(unitID) local level = Spring.GetUnitRulesParam(unitID, "comm_level") local chassis = Spring.GetUnitRulesParam(unitID, "comm_chassis") local profileID = Spring.GetUnitRulesParam(unitID, "comm_profileID") - costMultiplier = math.pow(2, (Spring.GetUnitRulesParam(unitID, "tech_level") or 1) - 1) if not (chassisDefs[chassis] and chassisDefs[chassis].levelDefs[math.min(chassisDefs[chassis].maxNormalLevel, level+1)]) then return @@ -942,7 +1138,8 @@ local function CreateModuleListWindowFromUnit(unitID) alreadyOwned[#alreadyOwned + 1] = module end table.sort(alreadyOwned) - + damageBooster = Spring.GetUnitRulesParam(unitID, "comm_damage_mult") or 1 + rangeBooster = Spring.GetUnitRulesParam(unitID, "comm_range_mult") or 1 -- Record the signature of the morphing unit for later application. upgradeSignature.level = level upgradeSignature.chassis = chassis @@ -955,19 +1152,18 @@ local function CreateModuleListWindowFromUnit(unitID) if savedSlotLoadout[profileID] and savedSlotLoadout[profileID][level] then slotDefaults = savedSlotLoadout[profileID][level] else - local chassisModuleDefs = moduleDefNames[(chassisDefs[chassis] or {}).name] or {} local commProfileInfo = WG.ModularCommAPI.GetCommProfileInfo(profileID) if commProfileInfo and commProfileInfo.modules and commProfileInfo.modules[level + 1] then local defData = commProfileInfo.modules[level + 1] for i = 1, #defData do - slotDefaults[i] = chassisModuleDefs[defData[i]] + slotDefaults[i] = moduleDefNames[defData[i]] end end end end -- Create the window - ShowModuleListWindow(unitID, slotDefaults, level + 1, chassis, alreadyOwned) + ShowModuleListWindow(slotDefaults, level + 1, chassis, alreadyOwned) end local function GetCommanderUpgradeAttributes(unitID, cullMorphing) @@ -1019,7 +1215,7 @@ end function widget:CommandsChanged() local units = cachedSelectedUnits or Spring.GetSelectedUnits() if mainWindowShown then - --Spring.Echo("Upgrade UI Debug - Number of units selected", #units) + ----spring.echo("Upgrade UI Debug - Number of units selected", #units) local foundMatchingComm = false for i = 1, #units do local unitID = units[i] @@ -1044,7 +1240,7 @@ function widget:CommandsChanged() local customCommands = widgetHandler.customCommands customCommands[#customCommands+1] = UPGRADE_CMD_DESC else - ----Spring.Echo("Upgrade UI Debug - Commander Deselected") + ------spring.echo("Upgrade UI Debug - Commander Deselected") HideMainWindow() -- Hide window if no commander matching the window is selected end end @@ -1092,11 +1288,19 @@ function widget:Initialize() Image = Chili.Image Progressbar = Chili.Progressbar screen0 = Chili.Screen0 - + for _, modDef in pairs(moduleDefs) do -- preload for translation, translation will occur post loading. + --spring.echo(modDef.name) + if modDef.slotType ~= "decoration" then + --spring.echo("Adding " .. modDef.name) + WG.ModuleTranslations[modDef.name] = {name = modDef.humanName, desc = modDef.description} + end + end + if (not Chili) then widgetHandler:RemoveWidget() return end + WG.InitializeTranslation(OnLocaleChanged, "gui_chili_commander_upgrade") end -------------------------------------------------------------------------------- From 580907db57278fd82f2a40103a1013e468a374c0 Mon Sep 17 00:00:00 2001 From: Shaman <48730089+Arch-Shaman@users.noreply.github.com> Date: Thu, 10 Jul 2025 04:29:49 -0400 Subject: [PATCH 2/2] Context menu localization and improvements FW has changed so much with context menu. TODO: - Remove FW entries. --- LuaUI/Configs/lang/context_menu.de.json | 289 +++ LuaUI/Configs/lang/context_menu.en.json | 292 +++ LuaUI/Configs/lang/context_menu.fr.json | 289 +++ LuaUI/Configs/lang/context_menu.it.json | 289 +++ LuaUI/Configs/lang/context_menu.ja.json | 292 +++ LuaUI/Configs/lang/context_menu.pl.json | 289 +++ LuaUI/Configs/lang/context_menu.pt.json | 289 +++ LuaUI/Configs/lang/context_menu.ru.json | 289 +++ LuaUI/Configs/lang/context_menu.th.json | 289 +++ LuaUI/Configs/lang/context_menu.tr.json | 289 +++ LuaUI/Configs/lang/context_menu.zh.json | 289 +++ LuaUI/Widgets/gui_contextmenu.lua | 2763 +++++++++++++++-------- 12 files changed, 4945 insertions(+), 1003 deletions(-) create mode 100644 LuaUI/Configs/lang/context_menu.de.json create mode 100644 LuaUI/Configs/lang/context_menu.en.json create mode 100644 LuaUI/Configs/lang/context_menu.fr.json create mode 100644 LuaUI/Configs/lang/context_menu.it.json create mode 100644 LuaUI/Configs/lang/context_menu.ja.json create mode 100644 LuaUI/Configs/lang/context_menu.pl.json create mode 100644 LuaUI/Configs/lang/context_menu.pt.json create mode 100644 LuaUI/Configs/lang/context_menu.ru.json create mode 100644 LuaUI/Configs/lang/context_menu.th.json create mode 100644 LuaUI/Configs/lang/context_menu.tr.json create mode 100644 LuaUI/Configs/lang/context_menu.zh.json diff --git a/LuaUI/Configs/lang/context_menu.de.json b/LuaUI/Configs/lang/context_menu.de.json new file mode 100644 index 0000000000..6352576542 --- /dev/null +++ b/LuaUI/Configs/lang/context_menu.de.json @@ -0,0 +1,289 @@ +{ + "edit_behavior" : "Verhalten der Einheit ändern", + "menu_close" : "Schließen", + "target_water_only" : "(nur Wasser)", + "target_manual_fire" : "(manuelles Feuer)", + "target_antiair" : "(nur Luftabwehr)", + "target_guidance" : "(nur Anleitung)", + "shield_hp" : "Schildstärke", + "shield_percost" : "Schildstärke pro Metall", + "shield_regencost" : "Regenerationskosten", + "shield_delay" : "Regenverzögerung", + "shield_nolink" : "Verbindet sich nicht mit anderen Schilden", + "vampirism_heals" : "Heilt sich selbst für", + "vampirism_perhit" : "Gesundheit pro Treffer", + "wolverine_mine" : "Mine", + "stats_damage" : "Schaden", + "stats_duringcloakstrike" : "(während des Tarnangriffs)", + "stats_shielddamage" : "Schildschaden", + "stats_reload" : "Nachladezeit", + "stats_aimtime" : "Zielzeit", + "stats_horizontal_deviation" : "Maximale horizontale Abweichung", + "stats_vertical_deviation" : "Maximale vertikale Abweichung", + "stats_exponential_damage_increase" : "Erhöht sich um", + "stats_exponential_damage_capsat" : "Maximiert bei", + "stats_ignores_shield" : "Ignoriert Schilde", + "stats_stun_time" : "Betäubungszeit", + "stats_burn_time" : "Brenndauer", + "stats_aoe" : "Explosionsradius", + "stats_weapon_speed" : "Projektilgeschwindigkeit", + "stats_force_decloak" : "Erzwingt die Enttarnung für", + "weapon_instant_hit" : "Trifft sofort", + "stats_missile_launch_speed" : "Abschussgeschwindigkeit", + "stats_missile_speed" : "Maximale Geschwindigkeit", + "stats_missile_fuel_time" : "Flugzeit", + "stats_acceleration" : "Beschleunigung", + "explodes_on_timeout" : "Explodiert bei Zeitüberschreitung", + "falls_on_timeout" : "Fällt bei Zeitüberschreitung ab", + "stats_homing" : "Lenkrate", + "stats_cruisemissile" : "Marschflugrakete", + "stats_cruisealtitude" : "Höhe", + "stats_begins_descent" : "Beginnt den Abstieg", + "stats_from_target" : "Elmo vom Ziel", + "stats_tracks_target" : "Verfolgt das Ziel", + "stats_guided_cruise" : "Gelenkter Hohenflug, ungelenkter Abstieg", + "stats_circular_spread" : "Hat eine kreisförmige Ausbreitung (%{size} Radius um das Ziel)", + "stats_cruise_error" : "Schlägt innerhalb von %{radius} elmos um das Ziel ein", + "laser_guided" : "Lasergelenkt", + "needs_guidance" : "(Benötigt externe Zielführung)", + "external_targeter" : "Bietet externe Ziehlführung", + "needs_guidance_for_seconds" : "Benötigt Zielführung für %{seconds}", + "stats_inaccuracy" : "Ungenauigkeit", + "stats_wobble" : "Fluginstabilität", + "stats_wobble_desc" : "bis zu", + "stats_blastwave_only_allies" : "Betrifft nur Verbündete", + "stats_burst_time" : "Schussdauer", + "stats_armor_boost_Friendly_only" : "Verstärkt die Rüstung alliierter Einheiten", + "stats_armor_boost_all" : "Verstärkt die Rüstung aller Einheiten", + "stats_armor_boost" : "Rüstungsbonus", + "duration" : "Dauer", + "stats_armor_boost_doesnt_diminish_duration" : "Die Dauer verringert sich nicht mit der Entfernung", + "stats_armor_boost_doesnt_diminish_effect" : "Der Effekt nimmt nicht mit der Entfernung ab", + "stats_armor_boost_diminishes" : "Effekt und Dauer nehmen mit der Entfernung ab", + "stats_armor_pen" : "Ignoriert Rüstung", + "stats_spawns" : "Erzeugt", + "stats_spawn_duration" : "Selbstzerstörung danach", + "stats_blastwave" : "Erzeugt eine Druckwelle", + "stats_blastwave_startsize" : "Anfangsgröße", + "stats_blastwave_healing_set" : "Heilt bis zu", + "stats_blastwave_initial_healing" : "Erste Heilung", + "stats_blastwave_initial_damage" : "Anfangsschaden", + "stats_overslow_duration" : "Übersättigte Verlangsamung", + "stats_impulse" : "Impuls", + "stats_blastwave_expansion_rate" : "Expansionsrate", + "stats_blastwave_power_loss" : "Schadensabfall", + "stats_blastwave_final_radius" : "Endgültiger Radius", + "stats_slows_down_after_firing" : "Geschwindigkeit verringert sich nach dem Abfeuern", + "weapon_creates_gravity_well" : "Erzeugt ein schwarzes Loch", + "weapon_groundfire" : "Setzt den Boden in Brand", + "weapon_creates_singularity" : "Erstellt eine Singularität", + "weapon_firing_arc" : "Geschossbahn", + "weapon_grid_demand" : "Netzanbindung erforderlich", + "grid_link" : "Netzanschlussbereich", + "grid_needed" : "Erforderliche Netzenergie", + "altitude" : "Höhe", + "altitude_bonus" : "Höhenbonus", + "revealpercent": "Erscheint Feinden, wenn %{percent}%% abgeschlossen ist", + "sight_range" : "Sichtweite", + "singularity_strength" : "Stärke", + "weapon_arcing" : "Krümmung der Geschossbahn", + "weapon_stockpile_time" : "Vorratszeit", + "weapon_stockpile_cost" : "Vorratkosten", + "weapon_smooths_ground" : "Glättet den Boden", + "weapon_moves_structures" : "Glättet unter Strukturen", + "weapon_high_traj" : "Steilfeuer", + "weapon_toggable_traj" : "Umschaltbare Flugbahn", + "weapon_arty_reveal" : "Wird %{time} Sekunden lang angezeigt, während man sich im feindlichen Radar befindet", + "weapon_water_capable" : "Wasserfähig", + "weapon_potential_Friendly_Fire" : "Potenzielles Friendly Fire", + "weapon_no_ground_collide" : "Geht durch den Boden", + "weapon_increased_damage_vs_large" : "Schadenserhöhung gegen große Einheiten", + "weapon_damage_falloff" : "Der Schaden nimmt mit zunehmender Reichweite ab", + "weapon_damage_closeup_falloff" : "Schaden verringert sich auf kurze Distanz", + "weapon_no_friendly_fire" : "Kein Friendly Fire", + "weapon_piercing" : "Durchdringend", + "weapon_shield_drain" : "Kostet Schildladung zum Abfeuern:", + "weapon_shield_drain_desc" : "Ladung pro Schuss", + "weapon_aim_delay" : "Zielverzögerung", + "weapon_inaccuracy_vs_moving" : "Ungenau gegenüber sich bewegenden Zielen", + "weapon_interceptable" : "Kann durch Anti-Atomwaffen abgeschossen werden", + "weapon_cluster_munitions" : "Streumunition", + "weapon_cluster_ttr" : "Verzögerung vor Streuen", + "spooling_weapon" : "Ladende Waffe", + "spooling_weapon_bonus" : "Bonus-Nachladegeschwindigkeit pro Schuss", + "spooling_max_bonus" : "Maximaler Feuerratenbonus", + "spooling_bonus_time_to_max" : "Zeit bis zur maximalen Feuerrate", + "construction" : "Bau", + "starting_buildpower" : "Bauleistung wird gestartet", + "buildpower_increases_use" : "Bauleistung nimmt mit der Nutzung zu", + "max_buildpower" : "Maximale Bauleistung", + "buildpower_diminishes_with_disuse" : "Bauleistung nimmt nach Nichtgebrauch ab", + "decay_rate" : "Verfallrate", + "base_buildpower" : "Basis-Bauleistung", + "recharge_delay" : "Aufladeverzögerung", + "buildpower_regen_rate" : "Regenerationsrate", + "can_resurrect" : "Kann Schrott wiederbeleben", + "only_assists" : "Kann nur helfen", + "vampirism" : "Vampirismus", + "vampirism_kills_increase_hp" : "Erhöht das Maximum bei Kills", + "vampirism_kills_increase_hp_desc" : "%{number} %% der maximalen HP des Opfers", + "armored_unit" : "Gehärtete Rüstung", + "armor_reduction" : "Schadensreduzierung", + "armor_type_1" : "Gilt im geschlossenen Zustand", + "armor_type_2" : "Gilt im gestoppten Zustand", + "forced_closed" : "Bei Schaden gewaltsam geschlossen", + "area_cloak" : "Tarngebiet", + "upkeep" : "Unterhalt", + "recon_pulse" : "Aufklärungsimpuls", + "recon_pulse_desc" : "Blockiert die Tarnung des Feindes. Reichweite: 500", + "recon_pulse_applied" : "Pingt alle 2 Sekunden", + "personal_cloak" : "Persönliche Tarnung", + "upkeep_mobile" : "Unterhalt mobil", + "upkeep_stationary" : "Unterhalt im Stillstand", + "decloak_radius" : "Enttarn-Radius", + "cloakstrike" : "Hinterhaltbonus", + "cloakstrike_lose_advantage" : "Verliert beim Schießen den Multiplikator neben Tarnung", + "unit_no_decloak_on_fire" : "Verliert beim Schießen nicht die Tarnung", + "only_idle" : "Nur im Leerlauf", + "idle_cloak_free" : "Kostenlos und automatisiert", + "cloak_regen" : "Regeneriert sich im getarnten Zustand", + "recloaks_after_seconds" : "Wird nach %{time} Sekunden außerhalb des Gebiettarners erneut getarnt", + "provides_intel" : "Stellt Aufklärung bereit", + "radar" : "Radarreichweite", + "jamming" : "Störsender", + "improves_radar" : "Verbessert die Radargenauigkeit", + "speed" : "Geschwindigkeit", + "movement" : "Bewegungstyp", + "climbs" : "Maximale Neigungstoleranz", + "turn_rate" : "Drehrate", + "metal_income" : "Metalleinkommen", + "energy_income" : "Energieeinkommen", + "unit_info" : "Einheitsinfo", + "mid_air_jump" : "Sprung in der Luft", + "morphing" : "wird aufgewertet", + "morphs_to" : "wertet auf zu", + "cost" : "Kosten", + "bp" : "Baurate", + "rate" : "Rate", + "rank_required" : "Erforderlicher Rang", + "morph_time" : "Zeit", + "not_disabled_morph" : "Während Aufwertung nicht deaktiviert", + "disabled_morph" : "Während Aufwertung deaktiviert", + "improved_regen" : "Verbesserte Regeneration", + "idle_regen" : "Leerlaufregeneration", + "regen_time_to_enable" : "Zeit zum Aktivieren", + "constant_regen" : "Kampfregeneration", + "nano_regen" : "Naniten-Reaktivrüstung", + "base_regen" : "Basisregeneration", + "max_regen" : "Maximale Regeneration", + "max_below" : "Maximaler Bonus unter", + "water_regen" : "Wasserregeneration", + "armor_regen" : "Gepanzerte Regeneration", + "teleporter" : "Teleporter", + "spawns_beacon" : "Erzeugt einen Beacon für den Rückruf in eine Richtung", + "spawn_time" : "Zeit zum Spawnen", + "at_depth" : "In Wassertiefe", + "mass" : "Masse", + "teleport_throughput" : "Durchsatz", + "rearm_repair" : "Flugzeuge bewaffnen und reparieren", + "rearm_pads" : "Pads", + "pad_bp" : "Pad-Bauleistung", + "drone_bound" : "An Besitzer gebunden", + "drone_cannot_direct_control" : "Kann nicht direkt gesteuert werden", + "drone_uses_owners_commands" : "Verwendet die Befehle des Besitzers", + "drone_bound_to_range" : "Muss in Reichweite des Besitzers bleiben", + "drone_dies_on_owner_death" : "Wird sterben, wenn der Besitzer es tut", + "speed_boost" : "Geschwindigkeitsschub", + "wind_gen" : "Erzeugt Energie aus Wind", + "wind_variable_income" : "Variables Einkommen", + "max_generation" : "Maximale Generation", + "wind_100_height" : "Energie pro 100 Höhe", + "grey_goo" : "Grauer Glibber", + "grey_goo_consumption" : "Nutzt Trümmer in der Nähe zur Replikation", + "jump" : "Springen", + "dangerous_reclaim" : "Explodiert beim Versuch, es zurückzubauen", + "floats" : "Floating", + "can_move_to_surface" : "Kann sich vom Meeresboden zur Oberfläche bewegen", + "cannot_move_sideways" : "Kann sich im Wasser nicht seitwärts bewegen", + "sinks_when_stun" : "Sinkt bei Betäubung", + "float_when_stun" : "Bleibt über Wasser, wenn es betäubt wird", + "transportation" : "Transportiert Einheiten", + "transport_type" : "Transporttyp", + "transport_light" : "Leicht", + "transport_heavy" : "Schwer", + "transport_light_speed" : "Geschwindigkeit bei leichter Ladung", + "transport_heavy_speed" : "Schwerlastgeschwindigkeit", + "anti_interception" : "Kann strategische Atomwaffen abfangen", + "combat_slowdown" : "Kampfverlangsamung", + "radar_invisible" : "Unsichtbar für Radar", + "instant_selfd" : "Sofortige Selbstzerstörung", + "requires_geo" : "Zum Bau ist eine thermische Quelle erforderlich", + "extracts_metal" : "Extrahiert Metall", + "fireproof" : "Feuerfest (immun gegen Brandschaden)", + "gravitronic_regulation" : "Gravitronische Regulierung (immun gegen Impulse)", + "storage" : "Speichert Ressourcen", + "shared_to_team" : "Teilt die Metallgewinnung mit dem Team", + "free" : "Kostenlos", + "movetype_immobile" : "Unbeweglich", + "movetype_plane" : "Flugzeug", + "movetype_gunship" : "Gunship", + "movetype_sub" : "U-Boot", + "movetype_waterwalker" : "Schwimmen", + "movetype_hover" : "Hovercraft", + "movetype_amph" : "Amphibisch", + "movetype_spider" : "All-Terrain", + "movetype_bot" : "Bot", + "movetype_veh" : "Fahrzeug", + "movetype_ship" : "Schiff", + "level" : "Level", + "chassis" : "Modeltyp", + "module" : "MODULE", + "death_explosion" : "Todesexplosion", + "builds" : "BAUT", + "weapons" : "WAFFEN", + "abilities" : "FÄHIGKEITEN", + "stats" : "Werte", + "time_to_reach" : "Zeit zum Erreichen", + "speed_while_reloading" : "Bewegungsgeschwindigkeit beim Nachladen", + "drone_max_range" : "Maximale Reichweite der Drohne", + "drone_target_range" : "Erfassungsreichweite der Drohne", + "drone_production_speed" : "Drohnenbaugeschwindigkeit", + "can_be_transported" : "Transportierbar", + "min_output" : "Minimale Ausgabe", + "max_output" : "Maximale Ausgabe", + "output_compounds" : "Die Ausgabe steigt mit der Zeit", + "output_decays" : "Ausgabe nimmt mit der Zeit ab", + "cloaked_speed" : "Getarnte Geschwindigkeit", + "decloaked_speed" : "Enttarnte Geschwindigkeit", + "pull" : "ziehen", + "push" : "push", + "radius" : "Radius", + "stats_range" : "Reichweite", + "regen" : "Regeneration", + "acronyms_hp" : "LP", + "acronyms_second" : "Sek", + "acronyms_dps" : "Schaden/s", + "acronyms_agl" : "AGL", + "acronyms_emp" : "EMP", + "acronyms_slow" : "V", + "acronyms_disarm" : "E", + "acronyms_capture" : "G", + "alliance" : "Team", + "team" : "Kader", + "yes" : "Ja", + "no" : "Nein", + "drone_carrier" : "Drohnenhersteller", + "drone_buildslots" : "Anzahl der automatischen Hersteller", + "cooldown" : "Abkühlen", + "drone_label" : "Drohnen-Ergänzung", + "drones_per_cycle" : "Pro Zyklus wurden Drohnen gestartet", + "drone_build_time" : "Herstellungszeit", + "chainlightning" : "Angriff wird auf Einheiten in der Nähe aufgeteilt:", + "chainlightning_jumps" : "Anzahl der Teilungen", + "chainlightning_extrajumps" : "Zusätzliche Teilungen", + "chainlightning_efficency": "Effizienz", + "sensor_steal" : "Hackt Sensoren für %{seconds} Sekunden", + "sensor_tag": "Zeigt angegriffene Einheiten für %{seconds} Sekunden", + "field_fac" : "Kann Nanoframe-Daten von befreundeten Fabriken herunterladen", + "disrupt_shields" : "Stört die Schildregeneration" +} diff --git a/LuaUI/Configs/lang/context_menu.en.json b/LuaUI/Configs/lang/context_menu.en.json new file mode 100644 index 0000000000..05bca8debf --- /dev/null +++ b/LuaUI/Configs/lang/context_menu.en.json @@ -0,0 +1,292 @@ +{ + "edit_behavior" : "Edit Behaviour", + "menu_close" : "Close", + "target_water_only" : "(aquatic targets only)", + "target_manual_fire" : "(manual fire)", + "target_antiair" : "(anti-air only)", + "target_guidance" : "(guidance only)", + "shield_hp" : "Capacity", + "shield_percost" : "Capacity per metal", + "shield_regencost" : "Regen cost", + "shield_delay" : "Regen delay", + "shield_nolink" : "Does not link with other shields", + "vampirism_heals" : "Heals self for", + "vampirism_perhit" : "health per hit", + "wolverine_mine" : "mine", + "disrupts_shields" : "Shield Disruption", + "stats_damage" : "Damage", + "stats_duringcloakstrike" : "(during cloak strike)", + "stats_shielddamage" : "Shield damage", + "stats_reload" : "Reload time", + "stats_aimtime" : "Aim time", + "stats_horizontal_deviation" : "Max Horizontal deviation", + "stats_vertical_deviation" : "Max Vertical Deviation", + "stats_exponential_damage_increase" : "Increases by", + "stats_exponential_damage_capsat" : "Caps out at", + "stats_ignores_shield" : "Ignores shields", + "stats_stun_time" : "Stun time", + "stats_burn_time" : "Burn time", + "stats_aoe" : "Explosion radius", + "stats_weapon_speed" : "Projectile speed", + "stats_force_decloak" : "Forces decloak for", + "weapon_instant_hit" : "Instantly hits", + "stats_missile_launch_speed" : "Launch speed", + "stats_missile_speed" : "Max speed", + "stats_missile_fuel_time" : "Flight Time", + "stats_acceleration" : "Acceleration", + "explodes_on_timeout" : "Explodes on timeout", + "falls_on_timeout" : "Falls down on timeout", + "stats_homing" : "Guidance Rate", + "stats_cruisemissile" : "Cruise Missile", + "stats_cruisealtitude" : "Altitude", + "stats_begins_descent" : "Begins descent", + "stats_from_target" : "elmo from target", + "stats_tracks_target" : "Tracks target", + "stats_guided_cruise" : "Guided Cruise, unguided descent", + "stats_circular_spread" : "Has circular spread (%{size} radius around the target)", + "stats_cruise_error" : "Strikes within %{radius} elmos of the target", + "laser_guided" : "Laser Guided", + "needs_guidance" : "(Needs external guidance)", + "external_targeter" : "Provides External Guidance", + "needs_guidance_for_seconds" : "Requires guidance for %{seconds}", + "stats_inaccuracy" : "Inaccuracy", + "stats_wobble" : "Flight Instability", + "stats_wobble_desc" : "up to", + "stats_blastwave_only_allies" : "Only affects allies", + "stats_burst_time" : "Burst time", + "stats_armor_boost_friendly_only" : "Boosts Allied Units' Armor", + "stats_armor_boost_all" : "Boosts All Units' Armor", + "stats_armor_boost" : "Armor bonus", + "duration" : "Duration", + "stats_armor_boost_doesnt_diminish_duration" : "Duration does not diminish with distance", + "stats_armor_boost_doesnt_diminish_effect" : "Effect does not diminish with distance", + "stats_armor_boost_diminishes" : "Effect and duration falloff with distance", + "stats_armor_pen" : "Ignores Armor", + "stats_spawns" : "Spawns", + "stats_spawn_duration" : "Self destructs after", + "stats_blastwave" : "Creates a blastwave", + "stats_blastwave_startsize" : "Initial Size", + "stats_blastwave_healing_set" : "Heals up to", + "stats_blastwave_initial_healing" : "Initial Healing", + "stats_blastwave_initial_damage" : "Initial Damage", + "stats_overslow_duration" : "Saturated Slow", + "stats_impulse" : "Impulse", + "stats_blastwave_expansion_rate" : "Expansion rate", + "stats_blastwave_power_loss" : "Power loss", + "stats_blastwave_final_radius" : "Final radius", + "stats_slows_down_after_firing" : "Speed lowers after firing", + "weapon_creates_gravity_well" : "Creates a gravity well", + "weapon_groundfire" : "Sets the ground on fire", + "weapon_creates_singularity" : "Creates a Singularity", + "weapon_firing_arc" : "Firing Arc", + "weapon_grid_demand" : "Grid Needed", + "grid_link" : "Grid Link Range", + "grid_needed" : "Required Grid Energy", + "altitude" : "Altitude", + "altitude_bonus" : "Altitude bonus", + "revealpercent" : "Appears to enemies upon reaching %{percent}%% completion", + "sight_range" : "Sight range", + "singularity_strength" : "Strength", + "weapon_arcing" : "Arcing shot", + "weapon_stockpile_time" : "Stockpile time", + "weapon_stockpile_cost" : "Stockpile cost", + "weapon_smooths_ground" : "Smoothes ground", + "weapon_moves_structures" : "Smoothes under structures", + "weapon_high_traj" : "High Trajectory", + "weapon_toggable_traj" : "Toggable Trajectory", + "weapon_arty_reveal" : "Reveals for %{time} seconds while in enemy radar", + "weapon_water_capable" : "Water capable", + "weapon_potential_friendly_fire" : "Potential Friendly Fire", + "weapon_no_ground_collide" : "Passes through ground", + "weapon_increased_damage_vs_large" : "Damage increase vs large units", + "weapon_damage_falloff" : "Damage falls off with range", + "weapon_damage_closeup_falloff" : "Damage increases with range", + "weapon_no_friendly_fire" : "No friendly fire", + "weapon_piercing" : "Piercing", + "weapon_shield_drain" : "Costs shield to fire:", + "weapon_shield_drain_desc" : "charge per shot", + "weapon_aim_delay" : "Aiming delay", + "weapon_inaccuracy_vs_moving" : "Inaccurate against moving targets", + "weapon_interceptable" : "Can be shot down by antinukes", + "weapon_cluster_munitions" : "Cluster Submunitions", + "weapon_cluster_ttr" : "Time-To-Release", + "spooling_weapon" : "Spooling Weapon", + "spooling_weapon_bonus" : "Bonus reload speed per shot", + "spooling_max_bonus" : "Maximum firerate bonus", + "spooling_bonus_time_to_max" : "Time Until Max Firerate", + "construction" : "Construction", + "starting_buildpower" : "Starting buildpower", + "buildpower_increases_use" : "Buildpower increases with use", + "max_buildpower" : "Maximum buildpower", + "buildpower_diminishes_with_disuse" : "Buildpower decreases after disuse", + "decay_rate" : "Decay rate", + "base_buildpower" : "Base Buildpower", + "recharge_delay" : "Recharge delay", + "buildpower_regen_rate" : "Regeneration rate", + "can_resurrect" : "Can resurrect wreckage", + "only_assists" : "Can only assist", + "vampirism" : "Vampirism", + "vampirism_kills_increase_hp" : "Increases max with kills", + "vampirism_kills_increase_hp_desc" : "%{number}%% of victim's max hp", + "armored_unit" : "Hardened Armor", + "armor_reduction" : "Damage Reduction", + "armor_type_1" : "Applies while closed", + "armor_type_2" : "Applies while stopped", + "forced_closed" : "Forcefully closed on damage", + "area_cloak" : "Area cloak", + "upkeep" : "Upkeep", + "recon_pulse" : "Recon Pulse", + "recon_pulse_desc" : "Jams enemy cloaking. Range: 500", + "recon_pulse_applied" : "Pings every 2 seconds", + "personal_cloak" : "Personal Cloak", + "upkeep_mobile" : "Upkeep while mobile", + "upkeep_stationary" : "Upkeep while stationary", + "decloak_radius" : "Decloak Radius", + "cloakstrike" : "Cloaked Ambush Advantage", + "cloakstrike_lose_advantage" : "Loses multipler alongside cloak when shooting", + "unit_no_decloak_on_fire" : "Doesn't lose cloak upon shooting", + "only_idle" : "Only when idle", + "idle_cloak_free" : "Free and automated", + "cloak_regen" : "Regenerates while cloaked", + "recloaks_after_seconds" : "Recloaks after %{time} seconds outside area cloakers", + "provides_intel" : "Provides intel", + "radar" : "Radar Range", + "jamming" : "Radar Stealth Field", + "improves_radar" : "Improves radar accuracy", + "speed" : "Speed", + "movement" : "Movement Type", + "climbs" : "Maximum Slope Tolerance", + "turn_rate" : "Turn rate", + "metal_income" : "Metal Income", + "energy_income" : "Energy Income", + "unit_info" : "Unit Info", + "mid_air_jump" : "Midair jump", + "morphing" : "Morphing", + "morphs_to" : "Morphs to", + "cost" : "Cost", + "bp" : "Build Rate", + "rate" : "Rate", + "rank_required" : "Required Rank", + "morph_time" : "Time", + "not_disabled_morph" : "Not disabled during morph", + "disabled_morph" : "Disabled during morph", + "improved_regen" : "Improved regeneration", + "idle_regen" : "Idle Regeneration", + "regen_time_to_enable" : "Time to enable", + "constant_regen" : "Combat Regeneration", + "nano_regen" : "Nanite Reactive Armor", + "base_regen" : "Base Regeneration", + "max_regen" : "Max Regeneration", + "max_below" : "Maximum bonus below", + "water_regen" : "Water Regeneration", + "armor_regen" : "Armored Regeneration", + "teleporter" : "Teleporter", + "spawns_beacon" : "Spawns a beacon for one-way recall", + "spawn_time" : "Time to spawn", + "at_depth" : "At depth", + "mass" : "Mass", + "teleport_throughput" : "Throughput", + "rearm_repair" : "Rearms and repairs aircraft", + "rearm_pads" : "Pads", + "pad_bp" : "Pad buildpower", + "drone_bound" : "Bound to owner", + "drone_cannot_direct_control" : "Cannot be directly controlled", + "drone_uses_owners_commands" : "Uses owner's commands", + "drone_bound_to_range" : "Must stay in range of owner", + "drone_dies_on_owner_death" : "Will die if owner does", + "speed_boost" : "Speed boost", + "wind_gen" : "Generates energy from wind", + "wind_variable_income" : "Variable income", + "max_generation" : "Maximum Generation", + "wind_100_height" : "Energy per 100 height", + "grey_goo" : "Grey Goo", + "grey_goo_consumption" : "Uses nearby wreckage for replication", + "jump" : "Jumping", + "dangerous_reclaim" : "Explodes when attempting to reclaim", + "floats" : "Floating", + "can_move_to_surface" : "Can move from seabed to surface", + "cannot_move_sideways" : "Cannot move sideways while afloat", + "sinks_when_stun" : "Sinks when stunned", + "float_when_stun" : "Stays afloat when stunned", + "transportation" : "Transports Units", + "transport_type" : "Transport Type", + "transport_light" : "Light", + "transport_heavy" : "Heavy", + "transport_light_speed" : "Loaded Speed", + "transport_heavy_speed" : "Heavy Load Speed", + "anti_interception" : "Can intercept strategic nukes", + "combat_slowdown" : "Combat slowdown", + "radar_invisible" : "Invisible to Radar", + "instant_selfd" : "Instant self-destruction", + "requires_geo" : "Requires thermal vent to build", + "extracts_metal" : "Extracts metal", + "fireproof" : "Fireproof (Immune to burning damage)", + "gravitronic_regulation" : "Gravitronic Regulation (Immune to impulse)", + "storage" : "Stores Resources", + "shared_to_team" : "Shares metal extraction to team", + "free" : "Free", + "movetype_immobile" : "Immobile", + "movetype_plane" : "Aircraft", + "movetype_gunship" : "Gunship", + "movetype_sub" : "Submarine", + "movetype_waterwalker" : "Swimming", + "movetype_hover" : "Hovercraft", + "movetype_amph" : "Amphibious", + "movetype_spider" : "All-terrain", + "movetype_bot" : "Bot", + "movetype_veh" : "Vehicle", + "movetype_ship" : "Ship", + "level" : "Level", + "chassis" : "Chassis", + "modules" : "MODULES", + "death_explosion" : "Death Explosion", + "builds" : "BUILDS", + "weapons" : "WEAPONS", + "abilities" : "ABILITIES", + "stats" : "STATS", + "time_to_reach" : "Time to reach", + "speed_while_reloading" : "Movement speed while reloading", + "drone_max_range" : "Drone Max Range", + "drone_target_range" : "Drone Acquisition Range", + "drone_controllable" : "Controllable", + "drone_verybigrange" : "Infinite max range", + "drone_production_speed" : "Drone Build Speed", + "can_be_transported" : "Transportable", + "min_output" : "Minimum Output", + "max_output" : "Maximum Output", + "output_compounds" : "Output increases over time", + "output_decays" : "Output decays over time", + "cloaked_speed" : "Cloaked Speed", + "decloaked_speed" : "Decloaked Speed", + "pull" : "pull", + "push" : "push", + "radius" : "Radius", + "stats_range" : "Range", + "regen" : "Regeneration", + "acronyms_hp" : "hp", + "acronyms_second" : "sec", + "acronyms_dps" : "DPS", + "acronyms_agl" : "AGL", + "acronyms_emp" : "EMP", + "acronyms_slow" : "S", + "acronyms_disarm" : "D", + "acronyms_capture" : "C", + "alliance" : "Team", + "team" : "Squad", + "yes" : "Yes", + "no" : "No", + "drone_carrier" : "Drone Manufacturer", + "drone_buildslots" : "Number of Autofabricators", + "cooldown" : "Cooldown", + "drone_label" : "Drone Complement", + "drones_per_cycle" : "Drones started per cycle", + "drone_build_time" : "Manufacture time", + "chainlightning" : "Attack forks to nearby units:", + "chainlightning_jumps" : "Number of forks", + "chainlightning_extrajumps" : "Number of subforks", + "chainlightning_efficency" : "Efficiency", + "sensor_steal" : "Hacks sensors for %{seconds}sec", + "sensor_tag" : "Reveals attacked units for %{seconds}sec", + "field_fac" : "Can download nanoframe data from friendly factories", + "disrupt_shields" : "Disrupts shield regeneration" +} diff --git a/LuaUI/Configs/lang/context_menu.fr.json b/LuaUI/Configs/lang/context_menu.fr.json new file mode 100644 index 0000000000..1d48b117e8 --- /dev/null +++ b/LuaUI/Configs/lang/context_menu.fr.json @@ -0,0 +1,289 @@ +{ + "edit_behavior" : "Modifier le comportement", + "menu_close" : "Fermer", + "target_water_only" : "(cibles aquatiques uniquement)", + "target_manual_fire" : "(tir manuel)", + "target_antiair" : "(anti-aérien uniquement)", + "target_guidance" : "(guidage uniquement)", + "shield_hp" : "Capacité", + "shield_percost" : "Capacité par métal", + "shield_regencost" : "Coût de régénération", + "shield_delay" : "Délai de régénération", + "shield_nolink" : "Ne se lie pas avec d'autres boucliers", + "vampirism_heals" : "Se guérit", + "vampirism_perhit" : "santé par coup", + "wolverine_mine" : "le mien", + "stats_damage" : "Dégâts", + "stats_duringcloakstrike" : "(pendant l'attaque de cape)", + "stats_shielddamage" : "Dégâts du bouclier", + "stats_reload" : "Temps de rechargement", + "stats_aimtime" : "Temps de visée", + "stats_horizontal_deviation" : "Déviation horizontale maximale", + "stats_vertical_deviation" : "Déviation verticale maximale", + "stats_exponential_damage_increase" : "Augmente de", + "stats_exponential_damage_capsat" : "Capsulé à", + "stats_ignores_shield" : "Ignore les boucliers", + "stats_stun_time" : "Durée d'étourdissement", + "stats_burn_time" : "Durée de gravure", + "stats_aoe" : "Rayon d'explosion", + "stats_weapon_speed" : "Vitesse du projectile", + "stats_force_decloak" : "Force le démasquage pour", + "weapon_instant_hit" : "Frappe instantanément", + "stats_missile_launch_speed" : "Vitesse de lancement", + "stats_missile_speed" : "Vitesse maximale", + "stats_missile_fuel_time" : "Temps de vol", + "stats_acceleration" : "Accélération", + "explodes_on_timeout" : "Explose à l'expiration du délai", + "falls_on_timeout" : "Tombe après expiration du délai", + "stats_homing" : "Taux de guidage", + "stats_cruisemissile" : "Missile de croisière", + "stats_cruisealtitude" : "Altitude", + "stats_begins_descent" : "Commence la descente", + "stats_from_target" : "elmo de la cible", + "stats_tracks_target" : "Tracks cible", + "stats_guided_cruise" : "Croisière guidée, descente libre", + "revealpercent" : "Apparaît aux ennemis après avoir atteint %{percent}%% d'achèvement", + "stats_circular_spread" : "A une propagation circulaire (%{size} rayon autour de la cible)", + "stats_cruise_error" : "Frappes à moins de %{radius} elmos de la cible", + "laser_guided" : "Guidé par laser", + "needs_guidance" : "(Besoin de conseils externes)", + "external_targeter" : "Fournit un guidage externe", + "needs_guidance_for_seconds" : "Nécessite un guidage pendant %{seconds}", + "stats_inaccuracy" : "Inexactitude", + "stats_wobble" : "Instabilité du vol", + "stats_wobble_desc" : "jusqu'à", + "stats_blastwave_only_allies" : "Affecte uniquement les alliés", + "stats_burst_time" : "Durée de rafale", + "stats_armor_boost_friendly_only" : "Améliore l'armure des unités alliées", + "stats_armor_boost_all" : "Améliore l'armure de toutes les unités", + "stats_armor_boost" : "Bonus d'armure", + "durée" : "Durée", + "stats_armor_boost_doesnt_diminish_duration" : "La durée ne diminue pas avec la distance", + "stats_armor_boost_doesnt_diminish_effect" : "L'effet ne diminue pas avec la distance", + "stats_armor_boost_diminishes" : "Diminution de l'effet et de la durée avec la distance", + "stats_armor_pen" : "Ignore l'armure", + "stats_spawns" : "Apparitions", + "stats_spawn_duration" : "Autodestruction après", + "stats_blastwave" : "Crée une onde explosive", + "stats_blastwave_startsize" : "Taille initiale", + "stats_blastwave_healing_set" : "Guérit jusqu'à", + "stats_blastwave_initial_healing" : "Guérison initiale", + "stats_blastwave_initial_damage" : "Dégâts initiaux", + "stats_overslow_duration" : "Saturé lent", + "stats_impulse" : "Impulsion", + "stats_blastwave_expansion_rate" : "Taux d'expansion", + "stats_blastwave_power_loss": "Perte de puissance", + "stats_blastwave_final_radius" : "Rayon final", + "stats_slows_down_after_firing" : "La vitesse diminue après le tir", + "weapon_creates_gravity_well" : "Crée un puits de gravité", + "weapon_groundfire" : "Mette le feu au sol", + "weapon_creates_singularity" : "Crée une singularité", + "weapon_firing_arc" : "Arc de tir", + "weapon_grid_demand" : "Grille nécessaire", + "grid_link" : "Plage de liens de grille", + "grid_needed" : "Énergie réseau requise", + "altitude" : "Altitude", + "altitude_bonus" : "Bonus d'altitude", + "sight_range" : "Portée de visée", + "singularity_strength" : "Force", + "weapon_arcing" : "Tir d'arc", + "weapon_stockpile_time" : "Durée de stockage", + "weapon_stockpile_cost" : "Coût du stock", + "weapon_smooths_ground" : "Lisse le sol", + "weapon_moves_structures" : "Lisse sous les structures", + "weapon_high_traj" : "Trajectoire haute", + "weapon_toggable_traj" : "Trajectoire commutable", + "weapon_arty_reveal" : "Révèle pendant %{time} secondes lorsque vous êtes dans le radar ennemi", + "weapon_water_capable" : "Capable pour l'eau", + "weapon_potential_friendly_fire" : "Tir ami potentiel", + "weapon_no_ground_collide" : "Passe à travers le sol", + "weapon_increased_damage_vs_large" : "Augmentation des dégâts contre les grandes unités", + "weapon_damage_falloff" : "Les dégâts diminuent avec la portée", + "weapon_damage_closeup_falloff" : "Les dégâts augmentent avec la portée", + "weapon_no_friendly_fire" : "Pas de tir ami", + "weapon_piercing" : "Perçage", + "weapon_shield_drain" : "Coûte au bouclier pour tirer :", + "weapon_shield_drain_desc" : "charge par tir", + "weapon_aim_delay" : "Délai de visée", + "weapon_inaccuracy_vs_moving" : "Inexact contre les cibles en mouvement", + "weapon_interceptable" : "Peut être abattu par des antinucléaires", + "weapon_cluster_munitions" : "Sous-munitions en grappe", + "weapon_cluster_ttr" : "Délai de sortie", + "spooling_weapon" : "Arme en file d'attente", + "spooling_weapon_bonus" : "Vitesse de rechargement bonus par tir", + "spooling_max_bonus" : "Bonus de cadence de tir maximum", + "spooling_bonus_time_to_max": "Durée jusqu'à la cadence de tir maximale", + "construction" : "Construction", + "starting_buildpower" : "Démarrage de buildpower", + "buildpower_increases_use" : "La puissance augmente avec l'utilisation", + "max_buildpower" : "Puissance de construction maximale", + "buildpower_diminishes_with_disuse" : "La puissance diminue après une inutilisation", + "decay_rate" : "Taux de décroissance", + "base_buildpower" : "Base Buildpower", + "recharge_delay" : "Délai de recharge", + "buildpower_regen_rate" : "Taux de régénération", + "can_resurrect" : "Peut ressusciter une épave", + "only_assistes" : "Peut uniquement aider", + "vampirisme" : "Vampirisme", + "vampirism_kills_increase_hp" : "Augmente le maximum avec les kills", + "vampirism_kills_increase_hp_desc": "%{number}%% des PV max de la victime", + "armored_unit" : "Armure durcie", + "armor_reduction" : "Réduction des dégâts", + "armor_type_1" : "S'applique lorsque fermé", + "armor_type_2" : "S'applique à l'arrêt", + "forced_closed" : "Fermeture forcée en cas de dommage", + "area_cloak" : "Cape de zone", + "entretien" : "Entretien", + "recon_pulse" : "Recon Pulse", + "recon_pulse_desc" : "Bloque la dissimulation de l'ennemi. Portée : 500", + "recon_pulse_applied" : "Pings toutes les 2 secondes", + "personal_cloak" : "Cape personnelle", + "upkeep_mobile" : "Entretien en mobile", + "upkeep_stationary" : "Entretien à l'arrêt", + "decloak_radius" : "Décloak Rayon", + "cloakstrike" : "Avantage de l'embuscade masquée", + "cloakstrike_lose_advantage" : "Perd le multipler avec la cape lors du tir", + "unit_no_decloak_on_fire" : "Ne perd pas sa cape lors du tir", + "only_idle" : "Uniquement en cas d'inactivité", + "idle_cloak_free" : "Gratuit et automatisé", + "cloak_regen" : "Se régénère en étant masqué", + "recloaks_after_seconds" : "Recloaks après %{time} secondes en dehors des dissimulateurs de zone", + "provides_intel" : "Fournit des informations", + "radar" : "Portée radar", + "jamming" : "Champ furtif radar", + "improves_radar" : "Améliore la précision du radar", + "vitesse" : "Vitesse", + "movement" : "Type de mouvement", + "montées" : "Tolérance de pente maximale", + "turn_rate" : "Taux de rotation", + "metal_ Income" : "Revenus métalliques", + "energy_ Income" : "Revenu énergétique", + "unit_info" : "Informations sur l'unité", + "mid_air_jump" : "Saut en l'air", + "morphing" : "Morphing", + "morphs_to" : "Se transforme en", + "cost" : "coût", + "bp" : "Taux de construction", + "tarif" : "Tarif", + "rank_required" : "Rang requis", + "morph_time" : "Temps", + "not_disabled_morph" : "Non désactivé pendant le morph", + "disabled_morph" : "Désactivé pendant le morph", + "improved_regen" : "Régénération améliorée", + "idle_regen" : "Régénération au ralenti", + "regen_time_to_enable" : "Délai d'activation", + "constant_regen" : "Régénération de combat", + "nano_regen" : "Armure réactive Nanite", + "base_regen" : "Régénération de base", + "max_regen" : "Régénération maximale", + "max_below" : "Bonus maximum ci-dessous", + "water_regen" : "Régénération de l'eau", + "armor_regen" : "Régénération blindée", + "teleporter" : "Téléporteur", + "spawns_beacon" : "Génère une balise pour un rappel unidirectionnel", + "spawn_time" : "Il est temps d'apparaître", + "at_degree" : "En profondeur", + "mass" : "Masse", + "teleport_throughput" : "Débit", + "rearm_repair" : "Réarme et répare l'avion", + "rearm_pads" : "Pads", + "pad_bp" : "Pad buildpower", + "drone_bound" : "Lié au propriétaire", + "drone_cannot_direct_control" : "Ne peut pas être contrôlé directement", + "drone_uses_owners_commands" : "Utilise les commandes du propriétaire", + "drone_bound_to_range" : "Doit rester à portée du propriétaire", + "drone_dies_on_owner_death" : "Mourra si le propriétaire le fait", + "speed_boost" : "Augmentation de vitesse", + "wind_gen" : "Génère de l'énergie à partir du vent", + "wind_variable_ Income" : "Revenu variable", + "max_generation" : "Génération maximale", + "wind_100_height" : "Énergie pour 100 hauteurs", + "grey_goo" : "Gris Goo", + "grey_goo_consumption" : "Utilise l'épave à proximité pour la réplication", + "sauter" : "Sauter", + "dangerous_reclaim" : "Explose lors d'une tentative de récupération", + "floats" : "Flottant", + "can_move_to_surface" : "Peut se déplacer du fond marin à la surface", + "cannot_move_sideways" : "Impossible de se déplacer latéralement à flot", + "sinks_when_stun" : "Coule lorsqu'il est étourdi", + "float_when_stun" : "Reste à flot lorsqu'il est étourdi", + "transportation" : "Unités de transport", + "transport_type" : "Type de transport", + "transport_light" : "Lumière", + "transport_heavy" : "Lourd", + "transport_light_speed" : "Vitesse en charge", + "transport_heavy_speed" : "Vitesse de charge lourde", + "anti_interception" : "Peut intercepter des armes nucléaires stratégiques", + "combat_slowdown" : "Ralentissement du combat", + "radar_invisible" : "Invisible au radar", + "instant_selfd" : "Autodestruction instantanée", + "requires_geo" : "Nécessite un évent thermique pour construire", + "extracts_metal" : "Extrait le métal", + "fireproof" : "Fireproof (Immunité aux dommages causés par la brûlure)", + "gravitronic_regulation" : "Régulation gravitronique (immunité aux impulsions)", + "storage" : "Stocke les ressources", + "shared_to_team" : "Partage l'extraction de métaux avec l'équipe", + "free" : "gratuit", + "movetype_immobile" : "Immobile", + "movetype_plane" : "Avion", + "movetype_gunship" : "Vaisseau de combat", + "movetype_sub" : "Sous-marin", + "movetype_waterwalker" : "Natation", + "movetype_hover" : "Aéroglisseur", + "movetype_amph" : "Amphibie", + "movetype_spider" : "Tout-terrain", + "movetype_bot" : "Bot", + "movetype_veh" : "Véhicule", + "movetype_ship" : "Navire", + "niveau" : "Niveau", + "chassis" : "Châssis", + "modules" : "MODULES", + "death_explosion" : "Explosion mortelle", + "builds" : "CONSTRUCTIONS", + "weapons" : "ARMES", + "abilities" : "CAPTITUDES", + "stats" : "STATISTIQUES", + "time_to_reach" : "Délai pour atteindre", + "speed_while_reloading" : "Vitesse de déplacement lors du rechargement", + "drone_max_range" : "Portée maximale du drone", + "drone_target_range" : "Portée d'acquisition de drones", + "drone_production_speed" : "Vitesse de construction du drone", + "can_be_transported" : "Transportable", + "min_output" : "Sortie minimale", + "max_output" : "Sortie maximale", + "output_compounds" : "La sortie augmente avec le temps", + "output_decays" : "La sortie diminue avec le temps", + "cloaked_speed" : "Vitesse masquée", + "decloaked_speed" : "Vitesse décloakée", + "pull" : "tirer", + "push" : "poussez", + "radius" : "Rayon", + "stats_range" : "Plage", + "regen" : "Régénération", + "acronymes_hp" : "hp", + "acronymes_seconde" : "sec", + "acronymes_dps" : "DPS", + "acronymes_agl" : "AGL", + "acronymes_emp" : "EMP", + "acronymes_slow" : "S", + "acronymes_disarm" : "D", + "acronymes_capture" : "C", + "alliance" : "Équipe", + "team" : "Escouade", + "yes" : "oui", + "no" : "non", + "drone_carrier" : "Fabricant de drones", + "drone_buildslots" : "Nombre d'autofabricants", + "cooldown" : "Cooldown", + "drone_label" : "Complément Drone", + "drones_per_cycle" : "Drones démarrés par cycle", + "drone_build_time" : "Délai de fabrication", + "chainlightning" : "L'attaque se divise sur les unités proches :", + "chainlightning_jumps" : "Nombre de splits", + "chainlightning_extrajumps" : "Divisions supplémentaires", + "chainlightning_efficency" : "Efficacité", + "sensor_steal" : "Piratage des capteurs pendant %{seconds} secondes", + "sensor_tag" : "Révèle les unités attaquées pendant %{seconds} secondes", + "field_fac" : "Peut télécharger des données nanoframe depuis des usines amies", + "disrupt_shields" : "Perturbe la régénération du bouclier" +} diff --git a/LuaUI/Configs/lang/context_menu.it.json b/LuaUI/Configs/lang/context_menu.it.json new file mode 100644 index 0000000000..ad8ee40738 --- /dev/null +++ b/LuaUI/Configs/lang/context_menu.it.json @@ -0,0 +1,289 @@ +{ + "edit_behavior" : "Modifica comportamento", + "menu_close" : "Uscita", + "target_water_only" : "(solo bersagli acquatici)", + "target_manual_fire" : "(obiettivo manuale)", + "target_antiair" : "(solo anti-aria)", + "target_guidance" : "(solo guida laser)", + "shield_hp" : "Capacità", + "shield_percost" : "Capacità per metallo", + "shield_regencost" : "Costo rigenerazione", + "shield_delay" : "Ritardo rigenerazione", + "shield_nolink" : "Non si collega con altri scudi", + "vampirism_heals" : "Guarisce se stesso per", + "vampirism_perhit" : "punti salute per colpo", + "wolverine_mine" : "mina", + "stats_damage" : "Danno", + "stats_duringcloakstrike" : "(durante il primo sciopero)", + "stats_shielddamage" : "Danni agli scudi", + "stats_reload" : "Tempo di ricarica", + "stats_aimtime" : "Tempo di mira", + "stats_horizontal_deviation" : "Deviazione orizzontale massima", + "stats_vertical_deviation" : "Deviazione verticale massima", + "stats_exponential_damage_increase" : "Aumenta di", + "stats_exponential_damage_capsat" : "Tappi fuori a", + "stats_ignores_shield" : "Penetra gli scudi", + "stats_stun_time" : "Tempo di stordimento", + "stats_burn_time" : "Brucia il tempo", + "stats_aoe" : "Raggio di esplosione", + "stats_weapon_speed" : "Velocità del proiettile", + "stats_force_decloak" : "Inceppa l'occultamento per", + "weapon_instant_hit" : "Colpisce istantaneamente", + "stats_missile_launch_speed" : "Velocità di lancio", + "stats_missile_speed" : "massima velocità", + "stats_missile_fuel_time" : "Tempo di volo", + "stats_acceleration" : "Accelerazione", + "explodes_on_timeout" : "esplode quando finisce il carburante", + "falls_on_timeout" : "Cade quando finisce il carburante", + "stats_homing" : "Tasso di orientamento", + "stats_cruisemissile" : "Missile da crociera", + "stats_cruisealtitude" : "Altitudine", + "stats_begins_descent" : "Inizia la discesa", + "stats_from_target" : "elmo dal bersaglio", + "stats_tracks_target" : "Segue il bersaglio", + "revealpercent" : "Appare ai nemici dopo aver raggiunto il %{percent}%% di completamento", + "stats_guided_cruise" : "Crociera guidata, discesa non guidata", + "stats_circular_spread" : "Ha una diffusione circolare (%{size} raggio attorno al bersaglio)", + "stats_cruise_error" : "Colpisce entro %{radius} elmos dal bersaglio", + "laser_guided" : "Guida laser", + "needs_guidance" : "(Ha bisogno di una guida esterna)", + "external_targeter" : "Fornisce una guida esterna", + "needs_guidance_for_seconds" : "Richiede indicazioni per %{seconds}", + "stats_inaccuracy" : "Inesattezza", + "stats_wobble" : "Instabilità del volo", + "stats_wobble_desc" : "fino a", + "stats_blastwave_only_allies" : "Colpisce solo gli alleati", + "stats_burst_time" : "Tempo di scoppio", + "stats_armor_boost_friendly_only" : "Aumenta l'armatura delle unità alleate", + "stats_armor_boost_all" : "Aumenta l'armatura di tutte le unità", + "stats_armor_boost" : "Aumento dell'armatura", + "duration" : "Durata", + "stats_armor_boost_doesnt_diminish_duration" : "La durata non diminuisce con la distanza", + "stats_armor_boost_doesnt_diminish_effect" : "L'effetto non diminuisce con la distanza", + "stats_armor_boost_diminishes" : "Effetto e durata diminuiscono con la distanza", + "stats_armor_pen" : "Penetra l'armatura", + "stats_spawns" : "Crea", + "stats_spawn_duration" : "Si autodistrugge dopo", + "stats_blastwave" : "Crea un'onda d'urto", + "stats_blastwave_startsize" : "Dimensione iniziale", + "stats_blastwave_healing_set" : "Guarisce fino a", + "stats_blastwave_initial_healing" : "Guarigione iniziale", + "stats_blastwave_initial_damage" : "Danno iniziale", + "stats_overslow_duration" : "Saturato Lento", + "stats_impulse" : "Impulso", + "stats_blastwave_expansion_rate" : "Tasso di espansione", + "stats_blastwave_power_loss" : "Perdita di potenza", + "stats_blastwave_final_radius" : "Raggio finale", + "stats_slows_down_after_firing" : "La velocità diminuisce dopo aver sparato", + "weapon_creates_gravity_well" : "Crea un pozzo gravitazionale", + "weapon_groundfire" : "Dà fuoco al terreno", + "weapon_creates_singularity" : "Crea un buco nero", + "weapon_firing_arc" : "Arco di fuoco", + "weapon_grid_demand" : "Griglia necessaria", + "grid_link" : "Raggio collegamento griglia", + "grid_needed" : "Energia di rete richiesta", + "altitude" : "Altitudine", + "altitude_bonus" : "Bonus altitudine", + "sight_range" : "Gamma di vista", + "singularity_strength" : "Forza", + "weapon_arcing" : "Spiovente", + "weapon_stockpile_time" : "Tempo di produzione delle munizioni", + "weapon_stockpile_cost" : "Costo delle munizioni", + "weapon_smooths_ground" : "Leviga il terreno", + "weapon_moves_structures" : "Leviga sotto le strutture", + "weapon_high_traj" : "Traiettoria alta", + "weapon_toggable_traj" : "Traiettoria regolabile", + "weapon_arty_reveal" : "Rivela per %{time} secondi mentre si trova nel radar nemico", + "weapon_water_capable" : "Può sparare in acqua", + "weapon_potential_friendly_fire" : "Potenziale fuoco amico", + "weapon_no_ground_collide" : "Attraversa il terreno", + "weapon_increased_damage_vs_large" : "Il danno aumenta contro le unità più grandi", + "weapon_damage_falloff" : "Il danno diminuisce con la portata", + "weapon_damage_closeup_falloff" : "Il danno aumenta con la gittata", + "weapon_no_friendly_fire" : "Nessun fuoco amico", + "weapon_piercing" : "Unità perforanti", + "weapon_shield_drain" : "Costa lo scudo per sparare:", + "weapon_shield_drain_desc" : "carica per colpo", + "weapon_aim_delay" : "Ritardo di mira", + "weapon_inaccuracy_vs_moving" : "Impreciso contro bersagli in movimento", + "weapon_interceptable" : "Può essere abbattuto dagli antinucleari", + "weapon_cluster_munitions" : "Sottomunizioni a grappolo", + "weapon_cluster_ttr" : "Tempo di rilascio", + "spooling_weapon" : "Arma a bobina", + "spooling_weapon_bonus" : "Aumenta la velocità di ricarica per colpo", + "spooling_max_bonus" : "Aumento massimo della cadenza di fuoco", + "spooling_bonus_time_to_max" : "Tempo fino alla massima velocità di fuoco", + "construction" : "Costruzione", + "starting_buildpower" : "Potenza di costruzione iniziale", + "buildpower_increases_use" : "La velocità di costruzione aumenta con l'uso", + "max_buildpower" : "Massima potenza costruttiva", + "buildpower_diminishes_with_disuse" : "Il tasso di costruzione diminuisce dopo l'inutilizzo", + "decay_rate" : "Tasso di decadimento", + "base_buildpower" : "Velocità di costruzione base", + "recharge_delay" : "Ritardo di ricarica", + "buildpower_regen_rate" : "Tasso di rigenerazione", + "can_resurrect" : "Può resuscitare i rottami", + "only_assists" : "Può solo aiutare", + "vampirism" : "Vampirismo", + "vampirism_kills_increase_hp" : "Aumenta il massimo con le uccisioni", + "vampirism_kills_increase_hp_desc" : "%{number}%% della salute massima della vittima", + "armored_unit" : "Armatura Indurita", + "armor_reduction" : "Riduzione del danno", + "armor_type_1" : "Si applica mentre è chiuso", + "armor_type_2" : "Si applica durante l'arresto", + "forced_closed" : "Chiusura forzata in caso di danno", + "area_cloak" : "Mantello di zona", + "upkeep" : "Manutenzione", + "recon_pulse" : "Ondata di ricognizione", + "recon_pulse_desc" : "Blocca l'occultamento del nemico. Portata: 500", + "recon_pulse_applied" : "Ping ogni 2 secondi", + "personal_cloak" : "Mantello personale", + "upkeep_mobile" : "Manutenzione in mobilità", + "upkeep_stationary" : "Mantenimento da fermo", + "decloak_radius" : "Raggio di decollo", + "cloakstrike" : "Vantaggio dell'agguato occultato", + "cloakstrike_lose_advantage" : "Perde il moltiplicatore insieme all'occultamento quando si spara", + "unit_no_decloak_on_fire" : "Non perde l'occultamento quando spara", + "only_idle" : "Solo quando inattivo", + "idle_cloak_free" : "Gratuito e automatizzato", + "cloak_regen" : "Si rigenera mentre è occultato", + "recloaks_after_seconds" : "Si riocculta dopo %{time} secondi al di fuori dell'area di occultamento", + "provides_intel" : "Fornisce informazioni", + "radar" : "Portata radar", + "jamming" : "Campo invisibile radar", + "improves_radar" : "Migliora la precisione del radar", + "speed" : "Velocità", + "movement" : "Tipo di movimento", + "climbs" : "Tolleranza massima pendenza", + "turn_rate" : "Velocità di rotazione", + "metal_income" : "Reddito di metallo", + "energy_income" : "Reddito Energetico", + "unit_info" : "Informazioni unità", + "mid_air_jump" : "Salto a mezz'aria", + "morphing" : "Trasformazioni", + "morphs_to" : "Si trasforma in", + "cost" : "Costo", + "bp" : "Tasso di costruzione", + "rate" : "Tasso", + "rank_required" : "Grado richiesto", + "morph_time" : "Tempo", + "not_disabled_morph" : "Non disabilitato durante la trasformazione", + "disabled_morph" : "Disattivato durante la trasformazione", + "improved_regen" : "Rigenerazione migliorata", + "idle_regen" : "Rigenerazione a vuoto", + "regen_time_to_enable" : "Tempo per abilitare", + "constant_regen" : "Rigenerazione costante", + "nano_regen" : "Armatura reattiva ai naniti", + "base_regen" : "Rigenerazione iniziale", + "max_regen" : "Rigenerazione massima", + "max_below" : "Rigenerazione massima a", + "water_regen" : "Rigenerazione dell'acqua", + "armor_regen" : "Rigenerazione in armatura", + "teleporter" : "Teletrasporto", + "spawns_beacon" : "Crea un segnalatore per il richiamo a senso unico", + "spawn_time" : "Tempo di deposizione delle uova", + "at_depth" : "In profondità", + "mass" : "Massa", + "teleport_throughput" : "Produttività", + "rearm_repair" : "Riarmare e riparare gli aeromobili", + "rearm_pads" : "Piattaforma di atterraggio", + "pad_bp" : "Velocità di riparazione della piattaforma di atterraggio", + "drone_bound" : "Segue il proprietario", + "drone_cannot_direct_control" : "Non può essere controllato direttamente", + "drone_uses_owners_commands" : "Utilizza i comandi del proprietario", + "drone_bound_to_range" : "Deve rimanere nel raggio d'azione del proprietario", + "drone_dies_on_owner_death" : "Morirà se il proprietario lo farà", + "speed_boost" : "Aumento della velocità", + "wind_gen" : "Genera energia dal vento", + "wind_variable_income" : "Reddito variabile", + "max_generation" : "Generazione massima", + "wind_100_height" : "Energia per 100 altezze", + "grey_goo" : "Goo grigio", + "grey_goo_consumption" : "Utilizza i rottami vicini per la replica", + "jump" : "Salto", + "dangerous_reclaim" : "Esplode durante il tentativo di recupero", + "floats" : "Galleggiante", + "can_move_to_surface" : "Può spostarsi dal fondo marino alla superficie", + "cannot_move_sideways" : "Non può muoversi lateralmente mentre è a galla", + "sinks_when_stun" : "Affonda quando viene stordito", + "float_when_stun" : "Rimane a galla quando viene stordito", + "transportation" : "Unità di trasporto", + "transport_type" : "Tipo di trasporto", + "transport_light" : "Luce", + "transport_heavy" : "Pesante", + "transport_light_speed" : "Velocità di carico", + "transport_heavy_speed" : "Velocità di carico pesante", + "anti_interception" : "Può intercettare le testate nucleari strategiche", + "combat_slowdown" : "Rallentamento del combattimento", + "radar_invisible" : "Invisibile ai radar", + "instant_selfd" : "Autodistruzione istantanea", + "requires_geo" : "Richiede uno sfiato termico per la costruzione", + "extracts_metal" : "Estrae il metallo", + "fireproof" : "Ignifugo (Immunità ai danni da fuoco)", + "gravitronic_regulation" : "Regolazione gravitronica (immunità agli impulsi)", + "storage" : "Risorse dei negozi", + "shared_to_team" : "Azioni di estrazione dei metalli ai compagni di squadra", + "free" : "Gratuito", + "movetype_immobile" : "Immobile", + "movetype_plane" : "Aereo", + "movetype_gunship" : "Cannoniera", + "movetype_sub" : "Sottomarino", + "movetype_waterwalker" : "Nuoto", + "movetype_hover" : "Hovercraft", + "movetype_amph" : "Anfibio", + "movetype_spider" : "Tuttoterreno", + "movetype_bot" : "Bot", + "movetype_veh" : "Veicolo", + "movetype_ship" : "Nave", + "level" : "Livello", + "chassis" : "Telaio", + "modules" : "MODULI", + "death_explosion" : "Esplosione di morte", + "builds" : "COSTRUZIONI", + "weapons" : "ARMI", + "abilities" : "ABILITÀ", + "stats" : "STATISTICHE", + "time_to_reach" : "Tempo per raggiungere", + "speed_while_reloading" : "Velocità di movimento durante la ricarica", + "drone_max_range" : "Portata massima del drone", + "drone_target_range" : "Gamma di acquisizione dei droni", + "drone_production_speed" : "Velocità di costruzione del drone", + "can_be_transported" : "Trasportabile", + "min_output" : "Uscita minima", + "max_output" : "Uscita massima", + "output_compounds" : "La produzione aumenta nel tempo", + "output_decays" : "L'uscita decade nel tempo", + "cloaked_speed" : "Velocità di occultamento", + "decloaked_speed" : "Velocità di decollo", + "pull" : "tirare", + "push" : "spingere", + "radius" : "Raggio", + "stats_range" : "Gamma", + "regen" : "Rigenerazione", + "acronyms_hp" : "PV", + "acronyms_second" : "Secondo", + "acronyms_dps" : "DPS", + "acronyms_agl" : "AGGL", + "acronyms_emp" : "EMP", + "acronyms_slow" : "L", + "acronyms_disarm" : "D", + "acronyms_capture" : "C", + "alliance" : "Gruppo", + "team" : "Squadra", + "yes" : "Sì", + "no" : "No", + "drone_carrier" : "Produttore di droni", + "drone_buildslots" : "Numero di autofabbricatori", + "cooldown" : "Raffreddare", + "drone_label" : "Complemento Drone", + "drones_per_cycle" : "I droni sono iniziati per ciclo", + "drone_build_time" : "Tempo di produzione", + "chainlightning": "L'attacco si divide tra le unità vicine:", + "chainlightning_jumps": "Numero di divisioni", + "chainlightning_extrajumps": "Divisioni extra", + "chainlightning_efficency": "Efficienza", + "sensor_steal": "Hackera i sensori per %{seconds} secondi", + "sensor_tag": "Rivela le unità attaccate per %{seconds} secondi", + "field_fac": "Può scaricare dati nanoframe da fabbriche amichevoli", + "disrupt_shields" : "Interrompe la rigenerazione dello scudo" +} diff --git a/LuaUI/Configs/lang/context_menu.ja.json b/LuaUI/Configs/lang/context_menu.ja.json new file mode 100644 index 0000000000..a1f546262d --- /dev/null +++ b/LuaUI/Configs/lang/context_menu.ja.json @@ -0,0 +1,292 @@ +{ + "edit_behavior" : "編集時の動作", + "menu_close" : "閉じる", + "target_water_only" : "(水生ターゲットのみ)", + "target_manual_fire" : "(手動射撃)", + "target_antiair" : "(対空のみ)", + "target_guidance" : "(誘導のみ)", + "shield_hp" : "能力", + "shield_percost" : "金属あたりの容量", + "shield_regencost" : "リジェネコスト", + "shield_delay" : "リジェネ遅延", + "shield_nolink" : "他のシールドとリンクしない", + "vampirism_heals" : "自己回復", + "vampirism_perhit" : "ヒットごとのヘルス", + "wolverine_mine" : "地雷", + "stats_damage" : "ダメージ", + "stats_duringcloakstrike" : "(ファーストストライク時)", + "stats_shielddamage" : "シールドダメージ", + "stats_reload" : "リロード時間", + "stats_aimtime" : "照準時間", + "stats_horizontal_deviation" : "最大水平偏差", + "stats_vertical_deviation" : "最大垂直偏差", + "stats_exponential_damage_increase" : "増加量", + "stats_exponential_damage_capsat" : "キャップアウト", + "stats_ignores_shield" : "シールドを無視する", + "stats_stun_time" : "スタンの時間", + "stats_burn_time" : "燃焼時間", + "stats_aoe" : "爆発半径", + "stats_weapon_speed" : "発射速度", + "stats_force_decloak" : "強制脱着", + "weapon_instant_hit" : "即座に命中", + "stats_missile_launch_speed" : "発射速度", + "stats_missile_speed" : "最大速度", + "stats_missile_fuel_time" : "飛行時間", + "stats_acceleration" : "加速度", + "explodes_on_timeout" : "タイムアウト時に爆発", + "falls_on_timeout" : "タイムアウト時に倒れる", + "stats_homing" : "誘導速度", + "stats_cruisemissile" : "巡航ミサイル", + "stats_cruisealtitude" : "高度", + "stats_begins_descent" : "降下開始", + "stats_from_target" : "目標からのエルモ", + "stats_tracks_target" : "目標を追跡", + "stats_guided_cruise" : "誘導クルーズ,非誘導降下", + "stats_circular_spread" : "目標を中心に半径%{size}の円形の広がりを持つ", + "stats_cruise_error" : "目標から半径%{radius} elmos以内で攻撃", + "laser_guided" : "レーザー誘導", + "needs_guidance" : "(外部誘導が必要)", + "external_targeter" : "外部誘導を行う", + "needs_guidance_for_seconds" : "%{秒}のガイダンスが必要", + "stats_inaccuracy" : "不正確", + "stats_wobble" : "飛行不安定", + "stats_wobble_desc" : "最大", + "stats_blastwave_only_allies" : "味方にのみ影響する", + "stats_burst_time" : "バースト時間", + "stats_armor_boost_friendly_only" : "味方ユニットのアーマーを上昇させる", + "stats_armor_boost_all" : "全ユニットのアーマーを増加させる", + "stats_armor_boost" : "装甲ボーナス", + "duration" : "効果時間", + "stats_armor_boost_doesnt_diminish_duration" : "持続時間は距離によって減少しない", + "stats_armor_boost_doesnt_diminish_effect" : "効果が距離によって減少しない", + "stats_armor_boost_diminishes" : "距離によって効果と持続時間が減少する", + "stats_armor_pen" : "アーマーを無視する", + "stats_spawns" : "スポーン", + "stats_spawn_duration" : "自爆する", + "stats_blastwave" : "爆発波を発生させる", + "stats_blastwave_startsize" : "初期サイズ", + "stats_blastwave_healing_set" : "最大回復量", + "stats_blastwave_initial_healing" : "初期ヒーリング", + "stats_blastwave_initial_damage" : "初期ダメージ", + "stats_overslow_duration" : "飽和スロー", + "stats_impulse" : "インパルス", + "stats_blastwave_expansion_rate" : "膨張率", + "stats_blastwave_power_loss" : "パワーロス", + "stats_blastwave_final_radius" : "最終半径", + "stats_slows_down_after_firing" : "発射後に速度が低下する", + "weapon_creates_gravity_well" : "重力の井戸を作る", + "weapon_groundfire" : "地面に火をつける", + "weapon_creates_singularity" : "特異点を作る", + "weapon_firing_arc" : "射撃アーク", + "weapon_grid_demand" : "グリッドが必要", + "grid_link" : "グリッドリンク範囲", + "grid_needed" : "必要グリッドエネルギー", + "altitude" : "高度", + "altitude_bonus" : "高度ボーナス", + "revealpercent" : "%{percent}%達成時に敵に出現", + "sight_range" : "照準範囲", + "singularity_strength" : "強さ", + "weapon_arcing" : "弧を描くショット", + "weapon_stockpile_time" : "備蓄時間", + "weapon_stockpile_cost" : "備蓄コスト", + "weapon_smooths_ground" : "地面を滑らかにする", + "weapon_moves_structures" : "構造物の下を滑らかにする", + "weapon_high_traj" : "高弾道", + "weapon_toggable_traj" : "切り替え可能な軌道", + "weapon_arty_reveal" : "敵のレーダーに映っている間,%{time}秒間,姿を現す", + "weapon_water_capable" : "水が使える", + "weapon_potential_friendly_fire" : "潜在的フレンドリーファイア", + "weapon_no_ground_collide" : "地面を通過する", + "weapon_increased_damage_vs_large" : "大型ユニットに対するダメージ増加", + "weapon_damage_falloff": "射程距離に応じてダメージが減少する", + "weapon_damage_closeup_falloff" : "射程距離に応じてダメージが増加する", + "weapon_no_friendly_fire" : "味方の攻撃は受けない", + "weapon_piercing" : "貫通", + "weapon_shield_drain" : "射撃にシールドを消費する:", + "weapon_shield_drain_desc" : "一発ごとに課金", + "weapon_aim_delay" : "照準ディレイ", + "weapon_inaccuracy_vs_moving" : "移動するターゲットに対して不正確", + "weapon_interceptable" : "対核攻撃で撃墜可能", + "weapon_cluster_munitions" : "クラスター弾", + "weapon_cluster_ttr" : "発射までの時間", + "spooling_weapon" : "スプール兵器", + "spooling_weapon_bonus" : "一発ごとのリロード速度ボーナス", + "spooling_max_bonus" : "最大発射速度ボーナス", + "spooling_bonus_time_tomax" : "最大火力までの時間", + "construction" : "建設", + "starting_buildpower" : "スタート時のビルドパワー", + "buildpower_increases_use" : "ビルドパワーは使用とともに増加する", + "max_buildpower" : "最大ビルドパワー", + "buildpower_diminishes_with_disuse" : "使用しなくなるとビルドパワーが減少する", + "decay_rate" : "減衰率", + "base_buildpower" : "基本ビルドパワー", + "recharge_delay" : "リチャージ遅延", + "buildpower_regen_rate" : "再生速度", + "can_resurrect" : "残骸を復活させることができる", + "only_assists" : "アシストしかできない", + "vampirism" : "吸血鬼主義", + "vampirism_kills_increase_hp" : "キルで最大値が増加する", + "vampirism_kills_increase_hp_desc" : "犠牲者の最大HPの%{数}%%", + "armored_unit" : "硬化アーマー", + "armor_reduction" : "ダメージ軽減", + "armor_type_1" : "閉じた状態で適用", + "armor_type_2" : "停止中に適用", + "forced_closed" : "ダメージを受けると強制的に閉じる", + "area_cloak" : "エリアクローク", + "upkeep" : "アップキープ", + "recon_pulse" : "偵察パルス", + "recon_pulse_desc" : "敵のクローキングを妨害する。範囲: 500", + "recon_pulse_applied" : "2秒ごとにピング", + "personal_cloak" : "パーソナルクローク", + "upkeep_mobile" : "移動中にアップキープ", + "upkeep_stationary" : "静止している間アップキープ", + "decloak_radius" : "クローク解除半径", + "cloakstrike" : "隠蔽待ち伏せアドバンテージ", + "cloakstrike_lose_advantage" : "射撃時に遮蔽物と共にマルチプラーを失う", + "unit_no_decloak_on_fire" : "射撃時に遮蔽物を失わない", + "only_idle" : "アイドル時のみ", + "idle_cloak_free" : "自由で自動", + "cloak_regen" : "クローク中に回復する", + "recloaks_after_seconds" : "%{time}秒後にクローク解除", + "provides_intel" : "情報を提供する", + "radar" : "レーダー範囲", + "jamming" : "レーダーステルスフィールド", + "improves_radar" : "レーダーの精度を向上させる", + "speed" : "スピード", + "movement" : "移動タイプ", + "Movement Type" : "移動タイプ", + "climbs" : "最大傾斜許容度", + "turn_rate" : "ターンレート", + "metal_income" : "金属収入", + "energy_income" : "エネルギー収入", + "unit_info" : "ユニット情報", + "mid_air_jump" : "空中ジャンプ", + "morphing" : "モーフィング", + "morphs_to" : "モーフィング先", + "cost" : "コスト", + "bp" : "ビルドレート", + "rate" : "レート", + "rank_required" : "必須ランク", + "morph_time" : "時間", + "not_disabled_morph" : "モーフ中は無効", + "disabled_morph" : "モーフ中は無効", + "improved_regen" : "再生能力の向上", + "idle_regen" : "アイドル再生", + "regen_time_to_enable" : "有効にするまでの時間", + "constant_regen" : "戦闘再生", + "nano_regen" : "ナナイトリアクティブアーマー", + "base_regen" : "ベースリジェネレーション", + "max_regen" : "最大再生", + "max_below" : "以下の最大ボーナス", + "water_regen" : "水再生", + "armor_regen" : "装甲再生", + "teleporter" : "テレポーター", + "spawns_beacon" : "一方向リコール用のビーコンを産む", + "spawn_time" : "スポーンする時間", + "at_depth" : "深度", + "mass" : "質量", + "teleport_throughput" : "スループット", + "rearm_repair" : "航空機の再装備と修理", + "rearm_pads" : "着陸パッド", + "pad_bp" : "パッド製造能力", + "drone_bound" : "所有者に拘束される", + "drone_cannot_direct_control" : "直接コントロールできない", + "drone_uses_owners_commands" : "オーナーのコマンドを使う", + "drone_bound_to_range" : "所有者の範囲内にいなければならない", + "drone_dies_on_owner_death":"オーナーが死ぬと死ぬ", + "speed_boost" : "スピードブースト", + "wind_gen" : "風からエネルギーを生成する", + "wind_variable_income" : "変動収入", + "max_generation" : "最大発電量", + "wind_100_height" : "高さ100あたりのエネルギー", + "grey_goo" : "灰色のグー", + "grey_goo_consumption" : "近くの残骸を複製に使用する", + "jump" : "ジャンプ", + "dangerous_reclaim" : "再生しようとすると爆発する", + "floats" : "浮遊", + "can_move_to_surface" : "海底から地表に移動できる", + "cannot_move_sideways" : "浮いている間は横に移動できない", + "sinks_when_stun" : "気絶すると沈む", + "float_when_stun" : "気絶しても浮いている", + "transportation" : "輸送ユニット", + "transport_type" : "輸送タイプ", + "transport_light" : "ライト", + "transport_heavy" : "重い", + "transport_light_speed" : "負荷速度", + "transport_heavy_speed" : "重負荷スピード", + "anti_interception" : "戦略核を迎撃できる", + "combat_slowdown" : "戦闘速度の低下", + "radar_invisible" : "レーダーに映らない", + "instant_selfd" : "即座の自滅", + "requires_geo" : "サーマルベントが必要", + "extracts_metal" : "金属を抽出する", + "fireproof" : "耐火性(燃焼ダメージに免疫がある)", + "gravitronic_regulation" : "グラビトロニック・レギュレーション(インパルスに免疫)", + "storage" : "店舗リソース", + "shared_to_team" : "金属抽出をチームに共有", + "free" : "無料", + "movetype_immobile" : "不動", + "movetype_plane" : "航空機", + "movetype_gunship" : "ガンシップ", + "movetype_sub" : "潜水艦", + "movetype_waterwalker" : "水泳", + "movetype_hover" : "ホバークラフト", + "movetype_amph" : "水陸両用", + "movetype_spider" : "全地形対応", + "movetype_bot" : "ボット", + "movetype_veh" : "車両", + "movetype_ship" : "船", + "level" : "レベル", + "chassis" : "シャシー", + "modules" : "モジュール", + "death_explosion" : "死の爆発", + "builds" : "ビルド", + "weapons" : "武器", + "abilities" : "能力", + "stats" : "スタッツ", + "time_to_reach" : "到達までの時間", + "speed_while_reloading" : "リロード中の移動速度", + "drone_max_range" : "ドローンの最大射程距離", + "drone_target_range" : "ドローン捕捉範囲", + "drone_controllable" : "制御可能", + "drone_verybigrange" : "無限の最大レンジ", + "drone_production_speed" : "ドローン建造速度", + "can_be_transported" : "持ち運び可能", + "min_output" : "最低出力", + "max_output" : "最大出力", + "output_compounds" : "生産量は時間とともに増加する", + "output_decays" : "出力は時間とともに減少する", + "cloaked_speed" : "クロークド・スピード", + "decloaked_speed" : "脱着速度", + "pull" : "プル", + "push" : "プッシュ", + "radius" : "半径", + "stats_range" : "レンジ", + "regen" : "再生", + "acronyms_hp" : "hp", + "acronyms_second" : "秒", + "acronyms_dps" : "DPS", + "acronyms_agl" : "地上レベル", + "acronyms_emp" : "電磁パルス", + "acronyms_slow" : "遅い", + "acronyms_disarm" : "武装を解く", + "acronyms_capture" : "捕獲", + "alliance" : "チーム", + "team" : "スクワッド", + "yes" : "はい", + "no" : "いいえ", + "drone_carrier" : "ドローンメーカー", + "drone_buildslots" : "オートファブリケーター数", + "cooldown" : "クールダウン", + "drone_label" : "ドローンの補完", + "drones_per_cycle" : "サイクルあたりのドローン始動数", + "drone_build_time" : "製造時間", + "chainlightning" : "近くのユニットにアタックチェイン:", + "chainlightning_jumps" : "分割数", + "chainlightning_extrajumps" : "サブスプリットの数", + "chainlightning_efficency" : "効率性", + "sensor_steal" : "%{seconds}秒間センサーをハックする", + "sensor_tag" : "攻撃されたユニットを %{seconds}秒間表示", + "field_fac" : "友好的な工場からナノフレームデータをダウンロード可能", + "disrupt_shields" : "シールド再生を混乱させます" +} diff --git a/LuaUI/Configs/lang/context_menu.pl.json b/LuaUI/Configs/lang/context_menu.pl.json new file mode 100644 index 0000000000..b869e5e18a --- /dev/null +++ b/LuaUI/Configs/lang/context_menu.pl.json @@ -0,0 +1,289 @@ +{ + "edit_behavior" : "Edit Behavior", + "menu_close" : "Close", + "target_water_only" : "(aquatic targets only)", + "target_manual_fire" : "(manual fire)", + "target_antiair" : "(anti-air only)", + "target_guidance" : "(guidance only)", + "shield_hp" : "Capacity", + "shield_percost" : "Capacity per metal", + "shield_regencost" : "Regen cost", + "shield_delay" : "Regen delay", + "shield_nolink" : "Does not link with other shields", + "vampirism_heals" : "Heals self for", + "vampirism_perhit" : "health per hit", + "wolverine_mine" : "mine", + "stats_damage" : "Damage", + "stats_duringcloakstrike" : "(during cloak strike)", + "stats_shielddamage" : "Shield damage", + "stats_reload" : "Reload time", + "stats_aimtime" : "Aim time", + "stats_horizontal_deviation" : "Max Horizontal deviation", + "stats_vertical_deviation" : "Max Vertical Deviation", + "stats_exponential_damage_increase" : "Increases by", + "stats_exponential_damage_capsat" : "Caps out at", + "stats_ignores_shield" : "Ignores shields", + "stats_stun_time" : "Stun time", + "stats_burn_time" : "Burn time", + "stats_aoe" : "Explosion radius", + "stats_weapon_speed" : "Projectile speed", + "stats_force_decloak" : "Forces decloak for", + "weapon_instant_hit" : "Instantly hits", + "stats_missile_launch_speed" : "Launch speed", + "stats_missile_speed" : "Max speed", + "stats_missile_fuel_time" : "Flight Time", + "stats_acceleration" : "Acceleration", + "explodes_on_timeout" : "Explodes on timeout", + "falls_on_timeout" : "Falls down on timeout", + "stats_homing" : "Guidance Rate", + "stats_cruisemissile" : "Cruise Missile", + "stats_cruisealtitude" : "Altitude", + "stats_begins_descent" : "Begins descent", + "stats_from_target" : "elmo from target", + "stats_tracks_target" : "Tracks target", + "stats_guided_cruise" : "Guided Cruise, unguided descent", + "stats_circular_spread" : "Has circular spread (%{size} radius around the target)", + "stats_cruise_error" : "Strikes within %{radius} elmos of the target", + "laser_guided" : "Laser Guided", + "needs_guidance" : "(Needs external guidance)", + "external_targeter" : "Provides External Guidance", + "needs_guidance_for_seconds" : "Requires guidance for %{seconds}", + "stats_inaccuracy" : "Inaccuracy", + "stats_wobble" : "Flight Instability", + "revealpercent" : "Appears to enemies upon reaching %{percent}%% completion", + "stats_wobble_desc" : "up to", + "stats_blastwave_only_allies" : "Only affects allies", + "stats_burst_time" : "Burst time", + "stats_armor_boost_friendly_only" : "Boosts Allied Units' Armor", + "stats_armor_boost_all" : "Boosts All Units' Armor", + "stats_armor_boost" : "Armor bonus", + "duration" : "Duration", + "stats_armor_boost_doesnt_diminish_duration" : "Duration does not diminish with distance", + "stats_armor_boost_doesnt_diminish_effect" : "Effect does not diminish with distance", + "stats_armor_boost_diminishes" : "Effect and duration falloff with distance", + "stats_armor_pen" : "Ignores Armor", + "stats_spawns" : "Spawns", + "stats_spawn_duration" : "Self destructs after", + "stats_blastwave" : "Creates a blastwave", + "stats_blastwave_startsize" : "Initial Size", + "stats_blastwave_healing_set" : "Heals up to", + "stats_blastwave_initial_healing" : "Initial Healing", + "stats_blastwave_initial_damage" : "Initial Damage", + "stats_overslow_duration" : "Saturated Slow", + "stats_impulse" : "Impulse", + "stats_blastwave_expansion_rate" : "Expansion rate", + "stats_blastwave_power_loss" : "Power loss", + "stats_blastwave_final_radius" : "Final radius", + "stats_slows_down_after_firing" : "Speed lowers after firing", + "weapon_creates_gravity_well" : "Creates a gravity well", + "weapon_groundfire" : "Sets the ground on fire", + "weapon_creates_singularity" : "Creates a Singularity", + "weapon_firing_arc" : "Firing Arc", + "weapon_grid_demand" : "Grid Needed", + "grid_link" : "Grid Link Range", + "grid_needed" : "Required Grid Energy", + "altitude" : "Altitude", + "altitude_bonus" : "Altitude bonus", + "sight_range" : "Sight range", + "singularity_strength" : "Strength", + "weapon_arcing" : "Arcing shot", + "weapon_stockpile_time" : "Stockpile time", + "weapon_stockpile_cost" : "Stockpile cost", + "weapon_smooths_ground" : "Smoothes ground", + "weapon_moves_structures" : "Smoothes under structures", + "weapon_high_traj" : "High Trajectory", + "weapon_toggable_traj" : "Toggable Trajectory", + "weapon_arty_reveal" : "Reveals for %{time} seconds while in enemy radar", + "weapon_water_capable" : "Water capable", + "weapon_potential_friendly_fire" : "Potential Friendly Fire", + "weapon_no_ground_collide" : "Passes through ground", + "weapon_increased_damage_vs_large" : "Damage increase vs large units", + "weapon_damage_falloff" : "Damage falls off with range", + "weapon_damage_closeup_falloff" : "Damage increases with range", + "weapon_no_friendly_fire" : "No friendly fire", + "weapon_piercing" : "Piercing", + "weapon_shield_drain" : "Costs shield to fire:", + "weapon_shield_drain_desc" : "charge per shot", + "weapon_aim_delay" : "Aiming delay", + "weapon_inaccuracy_vs_moving" : "Inaccurate against moving targets", + "weapon_interceptable" : "Can be shot down by antinukes", + "weapon_cluster_munitions" : "Cluster Submunitions", + "weapon_cluster_ttr" : "Time-To-Release", + "spooling_weapon" : "Spooling Weapon", + "spooling_weapon_bonus" : "Bonus reload speed per shot", + "spooling_max_bonus" : "Maximum firerate bonus", + "spooling_bonus_time_to_max" : "Time Until Max Firerate", + "construction" : "Construction", + "starting_buildpower" : "Starting buildpower", + "buildpower_increases_use" : "Buildpower increases with use", + "max_buildpower" : "Maximum buildpower", + "buildpower_diminishes_with_disuse" : "Buildpower decreases after disuse", + "decay_rate" : "Decay rate", + "base_buildpower" : "Base Buildpower", + "recharge_delay" : "Recharge delay", + "buildpower_regen_rate" : "Regeneration rate", + "can_resurrect" : "Can resurrect wreckage", + "only_assists" : "Can only assist", + "vampirism" : "Vampirism", + "vampirism_kills_increase_hp" : "Increases max with kills", + "vampirism_kills_increase_hp_desc" : "%{number}%% of victim's max hp", + "armored_unit" : "Hardened Armor", + "armor_reduction" : "Damage Reduction", + "armor_type_1" : "Applies while closed", + "armor_type_2" : "Applies while stopped", + "forced_closed" : "Forcefully closed on damage", + "area_cloak" : "Area cloak", + "upkeep" : "Upkeep", + "recon_pulse" : "Recon Pulse", + "recon_pulse_desc" : "Jams enemy cloaking. Range: 500", + "recon_pulse_applied" : "Pings every 2 seconds", + "personal_cloak" : "Personal Cloak", + "upkeep_mobile" : "Upkeep while mobile", + "upkeep_stationary" : "Upkeep while stationary", + "decloak_radius" : "Decloak Radius", + "cloakstrike" : "Cloaked Ambush Advantage", + "cloakstrike_lose_advantage" : "Loses multipler alongside cloak when shooting", + "unit_no_decloak_on_fire" : "Doesn't lose cloak upon shooting", + "only_idle" : "Only when idle", + "idle_cloak_free" : "Free and automated", + "cloak_regen" : "Regenerates while cloaked", + "recloaks_after_seconds" : "Recloaks after %{time} seconds outside area cloakers", + "provides_intel" : "Provides intel", + "radar" : "Radar Range", + "jamming" : "Radar Stealth Field", + "improves_radar" : "Improves radar accuracy", + "speed" : "Speed", + "movement" : "Movement Type", + "climbs" : "Maximum Slope Tolerance", + "turn_rate" : "Turn rate", + "metal_income" : "Metal Income", + "energy_income" : "Energy Income", + "unit_info" : "Unit Info", + "mid_air_jump" : "Midair jump", + "morphing" : "Morphing", + "morphs_to" : "Morphs to", + "cost" : "Cost", + "bp" : "Build Rate", + "rate" : "Rate", + "rank_required" : "Required Rank", + "morph_time" : "Time", + "not_disabled_morph" : "Not disabled during morph", + "disabled_morph" : "Disabled during morph", + "improved_regen" : "Improved regeneration", + "idle_regen" : "Idle Regeneration", + "regen_time_to_enable" : "Time to enable", + "constant_regen" : "Combat Regeneration", + "nano_regen" : "Nanite Reactive Armor", + "base_regen" : "Base Regeneration", + "max_regen" : "Max Regeneration", + "max_below" : "Maximum bonus below", + "water_regen" : "Water Regeneration", + "armor_regen" : "Armored Regeneration", + "teleporter" : "Teleporter", + "spawns_beacon" : "Spawns a beacon for one-way recall", + "spawn_time" : "Time to spawn", + "at_depth" : "At depth", + "mass" : "Mass", + "teleport_throughput" : "Throughput", + "rearm_repair" : "Rearms and repairs aircraft", + "rearm_pads" : "Pads", + "pad_bp" : "Pad buildpower", + "drone_bound" : "Bound to owner", + "drone_cannot_direct_control" : "Cannot be directly controlled", + "drone_uses_owners_commands" : "Uses owner's commands", + "drone_bound_to_range" : "Must stay in range of owner", + "drone_dies_on_owner_death" : "Will die if owner does", + "speed_boost" : "Speed boost", + "wind_gen" : "Generates energy from wind", + "wind_variable_income" : "Variable income", + "max_generation" : "Maximum Generation", + "wind_100_height" : "Energy per 100 height", + "grey_goo" : "Grey Goo", + "grey_goo_consumption" : "Uses nearby wreckage for replication", + "jump" : "Jumping", + "dangerous_reclaim" : "Explodes when attempting to reclaim", + "floats" : "Floating", + "can_move_to_surface" : "Can move from seabed to surface", + "cannot_move_sideways" : "Cannot move sideways while afloat", + "sinks_when_stun" : "Sinks when stunned", + "float_when_stun" : "Stays afloat when stunned", + "transportation" : "Transports Units", + "transport_type" : "Transport Type", + "transport_light" : "Light", + "transport_heavy" : "Heavy", + "transport_light_speed" : "Loaded Speed", + "transport_heavy_speed" : "Heavy Load Speed", + "anti_interception" : "Can intercept strategic nukes", + "combat_slowdown" : "Combat slowdown", + "radar_invisible" : "Invisible to Radar", + "instant_selfd" : "Instant self-destruction", + "requires_geo" : "Requires thermal vent to build", + "extracts_metal" : "Extracts metal", + "fireproof" : "Fireproof (Immune to burning damage)", + "gravitronic_regulation" : "Gravitronic Regulation (Immune to impulse)", + "storage" : "Stores Resources", + "shared_to_team" : "Shares metal extraction to team", + "free" : "Free", + "movetype_immobile" : "Immobile", + "movetype_plane" : "Aircraft", + "movetype_gunship" : "Gunship", + "movetype_sub" : "Submarine", + "movetype_waterwalker" : "Swimming", + "movetype_hover" : "Hovercraft", + "movetype_amph" : "Amphibious", + "movetype_spider" : "All-terrain", + "movetype_bot" : "Bot", + "movetype_veh" : "Vehicle", + "movetype_ship" : "Ship", + "level" : "Level", + "chassis" : "Chassis", + "modules" : "MODULES", + "death_explosion" : "Death Explosion", + "builds" : "BUILDS", + "weapons" : "WEAPONS", + "abilities" : "ABILITIES", + "stats" : "STATS", + "time_to_reach" : "Time to reach", + "speed_while_reloading" : "Movement speed while reloading", + "drone_max_range" : "Drone Max Range", + "drone_target_range" : "Drone Acquisition Range", + "drone_production_speed" : "Drone Build Speed", + "can_be_transported" : "Transportable", + "min_output" : "Minimum Output", + "max_output" : "Maximum Output", + "output_compounds" : "Output increases over time", + "output_decays" : "Output decays over time", + "cloaked_speed" : "Cloaked Speed", + "decloaked_speed" : "Decloaked Speed", + "pull" : "pull", + "push" : "push", + "radius" : "Radius", + "stats_range" : "Range", + "regen" : "Regeneration", + "acronyms_hp" : "hp", + "acronyms_second" : "sec", + "acronyms_dps" : "DPS", + "acronyms_agl" : "AGL", + "acronyms_emp" : "EMP", + "acronyms_slow" : "S", + "acronyms_disarm" : "D", + "acronyms_capture" : "C", + "alliance" : "Team", + "team" : "Squad", + "yes" : "Yes", + "no" : "No", + "drone_carrier" : "Drone Manufacturer", + "drone_buildslots" : "Number of Autofabricators", + "cooldown" : "Cooldown", + "drone_label" : "Drone Complement", + "drones_per_cycle" : "Drones started per cycle", + "drone_build_time" : "Manufacture time", + "chainlightning": "Atak rozdziela się na pobliskie jednostki:", + "chainlightning_jumps": "Liczba podziałów", + "chainlightning_extrajumps": "Dodatkowe dywizje", + "chainlightning_efficiency": "Wydajność", + "sensor_steal": "Hakuje czujniki na %{sekundy} s", + "sensor_tag": "Ujawnia zaatakowane jednostki przez %{sekundy} s", + "field_fac": "Może pobrać dane nanoframe z zaprzyjaźnionych fabryk", + "disrupt_shields" : "Zakłóca regenerację tarczy" +} diff --git a/LuaUI/Configs/lang/context_menu.pt.json b/LuaUI/Configs/lang/context_menu.pt.json new file mode 100644 index 0000000000..2ef37a9316 --- /dev/null +++ b/LuaUI/Configs/lang/context_menu.pt.json @@ -0,0 +1,289 @@ +{ + "target_water_only" : "(apenas alvos aquáticos)", + "target_manual_fire" : "(fogo manual)", + "target_antiair" : "(apenas antiaéreo)", + "target_guidance" : "(apenas orientação)", + "shield_hp" : "Resistência", + "shield_percost" : "Resistência por metal", + "shield_regencost" : "Custo de regeneração", + "shield_delay" : "Atraso de regeneração", + "shield_nolink" : "Não se conecta com outros escudos", + "vampirism_heals" : "Cura própria vida por", + "vampirism_perhit" : "vida por projétil", + "wolverine_mine" : "mina", + "stats_damage" : "Dano", + "stats_duringcloakstrike" : "(durante ataque camuflado)", + "stats_shielddamage" : "Dano a escudos", + "stats_reload" : "Tempo de recarga", + "stats_aimtime" : "Tempo de mira", + "stats_horizontal_deviation" : "Desvio horizontal máximo", + "stats_vertical_deviation" : "Desvio vertical máximo", + "stats_exponential_damage_increase" : "Aumenta em", + "stats_exponential_damage_capsat" : "Limite em", + "stats_ignores_shield" : "Ignora escudos", + "stats_stun_time" : "Tempo de paralização", + "stats_burn_time" : "Tempo de queima", + "stats_aoe" : "Raio de explosão", + "stats_weapon_speed" : "Velocidade do projétil", + "stats_force_decloak" : "Remove invisibilidade por", + "weapon_instant_hit" : "Atinge instantaneamente", + "stats_missile_launch_speed" : "Velocidade de lançamento", + "stats_missile_speed" : "Velocidade máxima", + "stats_missile_fuel_time" : "Tempo de voo", + "stats_acceleration" : "Aceleração", + "explodes_on_timeout" : "Explode ao expirar", + "falls_on_timeout" : "Cai ao expirar", + "stats_homing" : "Taxa de orientação", + "stats_cruisemissile" : "Míssil de cruzeiro", + "stats_cruisealtitude" : "Altitude", + "stats_begins_descent" : "Começa a descer", + "revealpercent" : "Aparece para os inimigos ao atingir %{percent}%% de conclusão", + "stats_from_target" : "elmo do alvo", + "stats_tracks_target" : "Rastreia o alvo", + "stats_guided_cruise" : "Míssil de cruzeiro guiado, descida não guiada", + "stats_circular_spread" : "Possui dispersão circular (raio de %{size} ao redor do alvo)", + "stats_cruise_error" : "Ataca dentro de %{radius} elmos do alvo", + "laser_guided" : "Guiado por laser", + "needs_guidance" : "(Necessita de orientação externa)", + "external_targeter" : "Fornece Orientação Externa", + "needs_guidance_for_seconds" : "Requer orientação por %{seconds}", + "stats_inaccuracy" : "Imprecisão", + "stats_wobble" : "Instabilidade de Voo", + "stats_wobble_desc" : "até", + "stats_blastwave_only_allies" : "Apenas afeta aliados", + "stats_burst_time" : "Tempo de descarga", + "stats_armor_boost_friendly_only" : "Aumenta a Armadura das Unidades Aliadas", + "stats_armor_boost_all" : "Aumenta a Armadura de Todas as Unidades", + "stats_armor_boost" : "Bônus de Armadura", + "duration" : "Duração", + "stats_armor_boost_doesnt_diminish_duration" : "A duração não diminui com a distância", + "stats_armor_boost_doesnt_diminish_effect" : "O efeito não diminui com a distância", + "stats_armor_boost_diminishes" : "O efeito e a duração diminuem com a distância", + "stats_armor_pen" : "Ignora Armadura", + "stats_spawns" : "Gera", + "stats_spawn_duration" : "Autodestrói-se após", + "stats_blastwave" : "Cria uma onda de explosão", + "stats_blastwave_startsize" : "Tamanho Inicial", + "stats_blastwave_healing_set" : "Cura até", + "stats_blastwave_initial_healing" : "Cura Inicial", + "stats_blastwave_initial_damage" : "Dano Inicial", + "stats_overslow_duration" : "Desaceleração Excessiva", + "stats_impulse" : "Impulso", + "stats_blastwave_expansion_rate" : "Taxa de expansão", + "stats_blastwave_power_loss" : "Perda de potência", + "stats_blastwave_final_radius" : "Raio Final", + "stats_slows_down_after_firing" : "Velocidade diminui após disparar", + "weapon_creates_gravity_well" : "Cria um poço gravitacional", + "weapon_groundfire" : "Queima o solo", + "weapon_creates_singularity" : "Cria uma Singularidade", + "weapon_firing_arc" : "Arco de Disparo", + "weapon_grid_demand" : "Requisito de energia", + "grid_link" : "Alcance de Ligação de Grade", + "grid_needed" : "Energia necessária", + "altitude" : "Altitude", + "altitude_bonus" : "Bônus de altitude", + "sight_range" : "Alcance de Visão", + "singularity_strength" : "Força", + "weapon_arcing" : "Tiro com Curvatura", + "weapon_stockpile_time" : "Tempo de construção", + "weapon_stockpile_cost" : "Custo de construção", + "weapon_smooths_ground" : "Alisa o solo", + "weapon_moves_structures" : "Alisa sob estruturas", + "weapon_high_traj" : "Trajetória Alta", + "weapon_toggable_traj" : "Trajetória Alternável", + "weapon_arty_reveal" : "Revela por %{time} segundos quando no radar inimigo", + "weapon_water_capable" : "Capaz de atravessar água", + "weapon_potential_friendly_fire" : "Potencial de Fogo Amigo", + "weapon_no_ground_collide" : "Atravessa o solo", + "weapon_increased_damage_vs_large" : "Aumento de dano contra unidades grandes", + "weapon_damage_falloff" : "Dano diminui com a distância", + "weapon_damage_closeup_falloff" : "Dano aumenta com a distância", + "weapon_no_friendly_fire" : "Sem fogo amigo", + "weapon_piercing" : "Perfurante", + "weapon_shield_drain" : "Consome o escudo para disparar:", + "weapon_shield_drain_desc" : "Resistência por disparo", + "weapon_aim_delay" : "Atraso na mira", + "weapon_inaccuracy_vs_moving" : "Inpreciso contra alvos em movimento", + "weapon_interceptable" : "Pode ser abatido por antimíssel nuclear", + "weapon_cluster_munitions" : "Submunições conjuntas", + "weapon_cluster_ttr" : "Tempo até ativação", + "spooling_weapon" : "Arma de rotação", + "spooling_weapon_bonus" : "Velocidade de recarga bônus por tiro", + "spooling_max_bonus" : "Bônus máximo de taxa de disparo", + "spooling_bonus_time_to_max" : "Tempo até a taxa máxima de disparo", + "construction" : "Construção", + "starting_buildpower" : "Potência de construção inicial", + "buildpower_increases_use" : "Potência de construção aumenta com o uso", + "max_buildpower" : "Potência de construção máxima", + "buildpower_diminishes_with_disuse" : "Potência de construção diminui após desuso", + "decay_rate" : "Taxa de decaimento", + "base_buildpower" : "Potência de construção base", + "recharge_delay" : "Atraso de recarga", + "buildpower_regen_rate" : "Velocidade de regeneração", + "can_resurrect" : "Pode ressuscitar destroços", + "only_assists" : "Apenas auxilia", + "vampirism" : "Vampirismo", + "vampirism_kills_increase_hp" : "Aumenta o máximo com mortes", + "vampirism_kills_increase_hp_desc" : "%{number}%% da vida máxima da vítima", + "armored_unit" : "Armadura reforçada", + "armor_reduction" : "Redução de dano", + "armor_type_1" : "Aplica-se quando fechado", + "armor_type_2" : "Aplica-se quando parado", + "forced_closed" : "Forçadamente fechado ao receber dano", + "area_cloak" : "Camuflagem de área", + "upkeep" : "Custo de manutenção", + "recon_pulse" : "Pulso de reconhecimento", + "recon_pulse_desc" : "Interfere no camuflamento inimigo. Alcance: 500", + "recon_pulse_applied" : "Pulso a cada 2 segundos", + "personal_cloak" : "Camuflagem pessoal", + "upkeep_mobile" : "Custo de manutenção móvel", + "upkeep_stationary" : "Custo de manutenção parado", + "decloak_radius" : "Raio de revelação", + "cloakstrike" : "Vantagem de ataque furtivo", + "cloakstrike_lose_advantage" : "Perde multiplicador junto com camuflagem ao atirar", + "unit_no_decloak_on_fire" : "Não perde camuflagem ao disparar", + "only_idle" : "Apenas quando inativo", + "idle_cloak_free" : "Grátis e automático", + "cloak_regen" : "Regenera enquanto camuflado", + "recloaks_after_seconds" : "Recamufla após %{time} segundos fora da área de camufladores", + "provides_intel" : "Fornece informações", + "radar" : "Alcance do radar", + "jamming" : "Campo de ocultação do radar", + "improves_radar" : "Melhora a precisão do radar", + "speed" : "Velocidade", + "movement" : "Tipo de movimento", + "climbs" : "Tolerância máxima de inclinação", + "turn_rate" : "Taxa de viragem", + "metal_income" : "Geração de metal", + "energy_income" : "Geração de energia", + "unit_info" : "Informações da unidade", + "mid_air_jump" : "Salto no ar", + "morphing" : "Transformação", + "morphs_to" : "Transforma-se em", + "cost" : "Custo", + "bp" : "Potência de construção", + "rate" : "Velocidade de reprodução", + "rank_required" : "Classificação necessária", + "morph_time" : "Tempo", + "not_disabled_morph" : "Não desativado durante transformação", + "disabled_morph" : "Desativado durante transformação", + "improved_regen" : "Regeneração aprimorada", + "idle_regen" : "Regeneração quando inativo", + "regen_time_to_enable" : "Tempo para habilitar", + "constant_regen" : "Regeneração em combate", + "nano_regen" : "Armadura reativa de nanite", + "base_regen" : "Regeneração base", + "max_regen" : "Regeneração máxima", + "max_below" : "Bônus máximo abaixo", + "water_regen" : "Regeneração na água", + "armor_regen" : "Regeneração com armadura", + "teleporter" : "Teletransportador", + "spawns_beacon" : "Cria um farol para recolhida unidirecional", + "spawn_time" : "Tempo de criação", + "at_depth" : "Na profundidade", + "mass" : "Massa", + "teleport_throughput" : "Taxa de transferência", + "rearm_repair" : "Rearma e repara aeronaves", + "rearm_pads" : "Plataformas", + "pad_bp" : "Potência de construção da plataforma", + "drone_bound" : "Vinculado ao dono", + "drone_cannot_direct_control" : "Não pode ser controlado diretamente", + "drone_uses_owners_commands" : "Usa comandos do dono", + "drone_bound_to_range" : "Deve permanecer dentro do alcance do dono", + "drone_dies_on_owner_death" : "Morre se o dono morrer", + "speed_boost" : "Aceleração de velocidade", + "wind_gen" : "Gera energia a partir do vento", + "wind_variable_income" : "Geração variável", + "max_generation" : "Geração máxima", + "wind_100_height" : "Energia por 100 de altura", + "grey_goo" : "Pasta cinzenta", + "grey_goo_consumption" : "Usa destroços próximos para replicação", + "jump" : "Saltar", + "dangerous_reclaim" : "Explode ao tentar recolher destroços", + "floats" : "Flutuante", + "can_move_to_surface" : "Pode mover-se do fundo do mar para a superfície", + "cannot_move_sideways" : "Não se move lateralmente quando flutua", + "sinks_when_stun" : "Afunda quando paralizado", + "float_when_stun" : "Permanece flutuante quando paralizado", + "transportation" : "Transporta Unidades", + "transport_type" : "Tipo de Transporte", + "transport_light" : "Leve", + "transport_heavy" : "Pesado", + "transport_light_speed" : "Velocidade com carga", + "transport_heavy_speed" : "Velocidade com carga pesada", + "anti_interception" : "Pode interceptar mísseis estratégicos", + "combat_slowdown" : "Desaceleração de combate", + "radar_invisible" : "Invisível para o Radar", + "instant_selfd" : "Auto-destruição instantânea", + "requires_geo" : "Requer fissura térmica para construir", + "extracts_metal" : "Extrai metal", + "fireproof" : "À prova de fogo (imune a danos por queimadura)", + "gravitronic_regulation" : "Regulação Gravitónica (imune ao impulso)", + "storage" : "Armazena Recursos", + "shared_to_team" : "Partilha extração de metal com a equipa", + "free" : "Grátis", + "movetype_immobile" : "Estático", + "movetype_plane" : "Avião", + "movetype_gunship" : "Nave", + "movetype_sub" : "Submarino", + "movetype_waterwalker" : "Nadador", + "movetype_hover" : "Levitação", + "movetype_amph" : "Anfíbio", + "movetype_spider" : "Todo-o-terreno", + "movetype_bot" : "Robô", + "movetype_veh" : "Veículo", + "movetype_ship" : "Navio", + "level" : "Nível", + "chassis" : "Chassis", + "modules" : "MÓDULOS", + "death_explosion" : "Explosão da morte", + "builds" : "CONSTRÓI", + "weapons" : "ARMAS", + "abilities" : "HABILIDADES", + "stats" : "ESTATÍSTICAS", + "time_to_reach" : "Tempo para chegar", + "speed_while_reloading" : "Velocidade de movimento enquanto recarrega", + "drone_max_range" : "Alcance máximo do drone", + "drone_target_range" : "Alcance de aquisição do drone", + "drone_production_speed" : "Velocidade de Construção de Drones", + "can_be_transported" : "Transportável", + "min_output" : "Saída Mínima", + "max_output" : "Saída Máxima", + "output_compounds" : "Aumento da saída ao longo do tempo", + "output_decays" : "Decaimento da Saída ao Longo do Tempo", + "cloaked_speed" : "Velocidade com Camuflagem", + "decloaked_speed" : "Velocidade sem Camuflagem", + "pull" : "Puxar", + "push" : "Empurra", + "radius" : "Raio", + "stats_range" : "Alcance", + "regen" : "Regeneração", + "acronyms_hp" : "pv", + "acronyms_second" : "seg", + "acronyms_dps" : "DPS", + "acronyms_agl" : "AGL", + "acronyms_emp" : "P", + "acronyms_slow" : "S", + "acronyms_disarm" : "D", + "acronyms_capture" : "C", + "alliance" : "Equipa", + "team" : "Esquadrão", + "yes" : "Sim", + "no" : "Não", + "drone_carrier" : "Fabricante de drones", + "drone_buildslots" : "Número de fabricantes de automóveis", + "cooldown" : "Esfriar", + "drone_label" : "Complemento Drone", + "drones_per_cycle" : "Drones iniciados por ciclo", + "drone_build_time" : "Tempo de fabricação", + "chainlightning" : "O ataque se divide em unidades próximas:", + "chainlightning_jumps" : "Número de divisões", + "chainlightning_extrajumps": "Divisões extras", + "chainlightning_efficiency": "Eficiência", + "sensor_steal" : "Hackeia sensores por %{seconds}seg", + "sensor_tag": "Revela unidades atacadas por %{seconds}seg", + "sensor_steal" : "Hackeia sensores por %{seconds}seg", + "sensor_tag": "Revela unidades atacadas por %{seconds}seg", + "field_fac": "Pode baixar dados de nanoframes de fábricas amigáveis", + "disrupt_shields" : "Interrompe a regeneração do escudo" +} diff --git a/LuaUI/Configs/lang/context_menu.ru.json b/LuaUI/Configs/lang/context_menu.ru.json new file mode 100644 index 0000000000..b9cfa8b63d --- /dev/null +++ b/LuaUI/Configs/lang/context_menu.ru.json @@ -0,0 +1,289 @@ +{ + "edit_behavior" : "Изменить поведение", + "menu_close" : "закрыть", + "target_water_only" : "(только водорожденные цели)", + "target_manual_fire" : "(ручное нацеливание)", + "target_antiair" : "(только противовоздушная)", + "target_guidance" : "(только рекомендации)", + "shield_hp" : "Вместимость", + "shield_percost" : "Производительность на металл", + "shield_regencost" : "Стоимость регенерации", + "shield_delay" : "Задержка регенерации", + "shield_nolink" : "Не соединяется с другими щитами", + "vampirism_heals" : "Исцеляет себя за", + "vampirism_perhit" : "здоровье за удар", + "wolverine_mine" : "мина", + "stats_damage" : "Урон", + "stats_duringcloakstrike" : "(во время удара плащом)", + "stats_shielddamage" : "Урон от щита", + "stats_reload" : "Время перезагрузки", + "stats_aimtime" : "Время прицеливания", + "stats_horizontal_deviation" : "Максимальное горизонтальное отклонение", + "stats_vertical_deviation" : "Максимальное вертикальное отклонение", + "stats_exponential_damage_increase" : "Увеличивается на", + "stats_exponential_damage_capsat" : "Капсулы на", + "stats_ignores_shield" : "Игнорирует щиты", + "stats_stun_time" : "Время оглушения", + "stats_burn_time" : "Время горения", + "stats_aoe" : "Радиус взрыва", + "stats_weapon_speed" : "Скорость снаряда", + "stats_force_decloak" : "Принудительная деблокировка для", + "weapon_instant_hit" : "Мгновенно попадает", + "stats_missile_launch_speed" : "Скорость запуска", + "stats_missile_speed" : "Максимальная скорость", + "stats_missile_fuel_time" : "Время полета", + "stats_acceleration" : "Ускорение", + "explodes_on_timeout" : "Взрывается при отсутствии топлива", + "falls_on_timeout" : "Падения при отсутствии топлива", + "revealpercent" : "Появляется врагам после завершения %{percent}%%", + "stats_homing" : "Ориентировочная ставка", + "stats_cruisemissile" : "Крылатая ракета", + "stats_cruisealtitude" : "Высота", + "stats_begins_descent" : "Начинает спуск", + "stats_from_target" : "Элмо из мишени", + "stats_tracks_target" : "Отслеживает цель", + "stats_guided_cruise" : "Круиз с гидом, спуск без гида", + "stats_circular_spread" : "Имеет круговое распространение (радиус %{size} вокруг цели)", + "stats_cruise_error" : "Наносит удары в пределах %{radius} элмосов от цели", + "laser_guided" : "Лазерное наведение", + "needs_guidance" : "(Требуется внешнее руководство)", + "external_targeter" : "Обеспечивает внешнее руководство", + "needs_guidance_for_seconds" : "Требуется руководство в течение %{seconds}", + "stats_inaccuracy" : "Неточность", + "stats_wobble" : "Нестабильность полета", + "stats_wobble_desc" : "до", + "stats_blastwave_only_allies" : "Влияет только на союзников", + "stats_burst_time" : "Время вспышки", + "stats_armor_boost_friendly_only" : "Усиливает броню союзных подразделений", + "stats_armor_boost_all" : "Увеличивает броню всех юнитов", + "stats_armor_boost" : "Бонус к броне", + "duration" : "Продолжительность", + "stats_armor_boost_doesnt_diminish_duration" : "Продолжительность не уменьшается с расстоянием", + "stats_armor_boost_doesnt_diminish_effect" : "Эффект не уменьшается с расстоянием", + "stats_armor_boost_diminishes" : "Эффект и спад продолжительности с расстоянием", + "stats_armor_pen" : "Пробивает броню", + "stats_spawns" : "Порождает", + "stats_spawn_duration" : "Самоуничтожается после", + "stats_blastwave" : "Создает взрывную волну", + "stats_blastwave_startsize" : "Начальный размер", + "stats_blastwave_healing_set" : "Исцеляет до", + "stats_blastwave_initial_healing" : "Первоначальное исцеление", + "stats_blastwave_initial_damage" : "Первоначальный ущерб", + "stats_overslow_duration" : "Насыщенный медленный", + "stats_impulse" : "Импульс", + "stats_blastwave_expansion_rate" : "Скорость расширения", + "stats_blastwave_power_loss" : "Потеря мощности", + "stats_blastwave_final_radius" : "Окончательный радиус", + "stats_slows_down_after_firing" : "Скорость снижается после стрельбы", + "weapon_creates_gravity_well" : "Создает гравитационный колодец", + "weapon_groundfire" : "Поджигает землю", + "weapon_creates_singularity" : "Создает черную дыру", + "weapon_firing_arc" : "Дуга стрельбы", + "weapon_grid_demand" : "Необходима сетка", + "grid_link" : "Диапазон звеньев сетки", + "grid_needed" : "Необходимая энергия сети", + "altitude" : "Высота", + "altitude_bonus" : "Бонус за высоту", + "sight_range" : "Прицельная дальность", + "singularity_strength" : "Прочность", + "weapon_arcing" : "Стрельба из лука", + "weapon_stockpile_time" : "Время хранения запасов", + "weapon_stockpile_cost" : "Стоимость запасов", + "weapon_smooths_ground" : "Разглаживает землю", + "weapon_moves_structures" : "Разглаживает под конструкциями", + "weapon_high_traj" : "Высокая траектория", + "weapon_toggable_traj" : "Переключаемая траектория", + "weapon_arty_reveal" : "Раскрывается на %{time} секунд, пока находится в поле зрения врагов.", + "weapon_water_capable" : "Можно стрелять в воду", + "weapon_potential_friendly_fire" : "Потенциальный дружественный огонь", + "weapon_no_ground_collide" : "Проходит сквозь землю", + "weapon_increased_damage_vs_large" : "Увеличение урона против больших единиц", + "weapon_damage_falloff" : "Урон уменьшается с увеличением дальности", + "weapon_damage_closeup_falloff" : "Урон увеличивается с увеличением дальности", + "weapon_no_friendly_fire" : "Никакого дружественного огня", + "weapon_piercing" : "Стреляет через блоки", + "weapon_shield_drain" : "Затрачивает щит на стрельбу", + "weapon_shield_drain_desc" : "плата за выстрел", + "weapon_aim_delay" : "Задержка прицеливания", + "weapon_inaccuracy_vs_moving" : "Неточность против движущихся целей", + "weapon_interceptable" : "Может быть сбит противоракетами", + "weapon_cluster_munitions" : "Кассетные суббоеприпасы", + "weapon_cluster_ttr" : "Время освобождения", + "spooling_weapon" : "Орудие намотки", + "spooling_weapon_bonus" : "Бонусная скорость перезарядки на выстрел", + "spooling_max_bonus" : "Максимальный бонус к скорострельности", + "spooling_bonus_time_to_max" : "Время до максимальной скорострельности", + "construction" : "Строительство", + "starting_buildpower" : "Запуск мощности сборки", + "buildpower_increases_use" : "Мощность увеличивается по мере использования", + "max_buildpower" : "Максимальная мощность сборки", + "buildpower_diminishes_with_disuse" : "Строительная мощность снижается после прекращения использования", + "decay_rate" : "Скорость распада", + "base_buildpower" : "Базовая мощность", + "recharge_delay" : "Задержка пополнения", + "buildpower_regen_rate" : "Скорость регенерации", + "can_resurrect" : "Может воскрешать обломки", + "only_assists" : "Может только помочь", + "vampirism" : "Вампиризм", + "vampirism_kills_increase_hp" : "Увеличивает максимальный показатель с убийствами", + "vampirism_kills_increase_hp_desc" : "%{number}%% от максимального хп жертвы", + "armored_unit" : "Усиленная броня", + "armor_reduction" : "Снижение урона", + "armor_type_1" : "Применяется в закрытом состоянии", + "armor_type_2" : "Применяется во время остановки", + "forced_closed" : "Принудительное закрытие при повреждении", + "area_cloak" : "Местный плащ", + "upkeep" : "Поддержание", + "recon_pulse" : "Повторный импульс", + "recon_pulse_desc" : "Заглушает маскировку противника. Дальность: 500", + "recon_pulse_applied" : "Пинги каждые 2 секунды", + "personal_cloak" : "Личный плащ", + "upkeep_mobile" : "Уход в мобильном режиме", + "upkeep_stationary" : "Поддержание в неподвижном состоянии", + "decloak_radius" : "Радиус разблокировки", + "cloakstrike" : "Преимущество замаскированной засады", + "cloakstrike_lose_advantage" : "Теряет мультиплеер вместе с плащом при стрельбе", + "unit_no_decloak_on_fire" : "Не теряет плащ при стрельбе", + "only_idle" : "Только на холостом ходу", + "idle_cloak_free" : "Бесплатный и автоматизированный", + "cloak_regen" : "Регенерирует во время маскировки", + "recloaks_after_seconds" : "Перезакрывается через %{time}% секунд вне зоны маскировки", + "provides_intel" : "Предоставляет информацию", + "radar" : "Дальность действия радара", + "jamming" : "Поле радиолокационных помех", + "improves_radar" : "Повышает точность радара", + "speed" : "Скорость", + "movement" : "Тип движения", + "climbs" : "Максимальный допустимый уклон", + "turn_rate" : "Скорость оборота", + "metal_income" : "Доход от металла", + "energy_income" : "Энергетический доход", + "unit_info" : "Информация о подразделении", + "mid_air_jump" : "Прыжок в воздухе", + "morphing" : "Морфинг", + "morphs_to" : "превращается в", + "cost" : "Стоимость", + "bp" : "Темп строительства", + "rate" : "Тариф", + "rank_required" : "Требуемое звание", + "morph_time" : "Время", + "not_disabled_morph" : "Не отключается во время морфа", + "disabled_morph" : "Отключено во время морфа", + "improved_regen" : "Улучшенная регенерация", + "idle_regen" : "Регенерация в режиме холостого хода", + "regen_time_to_enable" : "Время для включения", + "constant_regen" : "Боевая регенерация", + "nano_regen" : "Нанитовая реактивная броня", + "base_regen" : "Регенерация базы", + "max_regen" : "Максимальная регенерация", + "max_below" : "Максимальный бонус ниже", + "water_regen" : "Регенерация воды", + "armor_regen" : "Бронированная регенерация", + "teleporter" : "Телепортатор", + "spawns_beacon" : "Создает маяк для одностороннего отзыва", + "spawn_time" : "Время нереститься", + "at_depth" : "На глубине", + "mass" : "Масса", + "teleport_throughput" : "Пропускная способность", + "rearm_repair" : "Вооружение и ремонт самолетов", + "rearm_pads" : "Посадочные площадки", + "pad_bp" : "Скорость ремонта посадочной площадки", + "drone_bound" : "Привязан к владельцу", + "drone_cannot_direct_control" : "Не поддается прямому контролю", + "drone_uses_owners_commands" : "Использует команды владельца", + "drone_bound_to_range" : "Должен оставаться в зоне действия владельца", + "drone_dies_on_owner_death" : "Погибнет, если владелец", + "speed_boost" : "Увеличение скорости", + "wind_gen" : "Генерирует энергию из ветра", + "wind_variable_income" : "Переменный доход", + "max_generation" : "Максимальная генерация", + "wind_100_height" : "Энергия на 100 высот", + "grey_goo" : "Серая слизь", + "grey_goo_consumption" : "Использует близлежащие обломки для репликации", + "jump" : "Прыжки", + "dangerous_reclaim" : "Взрывается при попытке извлечения", + "floats" : "Плавающий", + "can_move_to_surface" : "Может перемещаться с морского дна на поверхность", + "cannot_move_sideways" : "Не может двигаться боком, находясь на плаву", + "sinks_when_stun" : "Тонет, когда оглушен", + "float_when_stun" : "Остается на плаву, когда оглушен", + "transportation" : "Транспортные единицы", + "transport_type" : "Тип транспорта", + "transport_light" : "Свет", + "transport_heavy" : "Тяжелый", + "transport_light_speed" : "Загруженная скорость", + "transport_heavy_speed" : "Скорость при высоких нагрузках", + "anti_interception" : "Может перехватывать стратегические ядерные ракеты", + "combat_slowdown" : "Замедление боя", + "radar_invisible" : "Невидимый для радаров", + "instant_selfd" : "Мгновенное самоуничтожение", + "requires_geo" : "Требуется тепловая вентиляция для строительства", + "extracts_metal" : "Извлекает металл", + "fireproof" : "Огнеупорный (невосприимчив к повреждениям от ожогов)", + "gravitronic_regulation" : "Гравитронная регуляция (иммунитет к импульсу)", + "storage" : "Ресурсы магазинов", + "shared_to_team" : "Делится добычей металла с командой", + "free" : "Бесплатно", + "movetype_immobile" : "Неподвижный", + "movetype_plane" : "Самолет", + "movetype_gunship" : "Вертолет", + "movetype_sub" : "Подводная лодка", + "movetype_waterwalker" : "Плавание", + "movetype_hover" : "Судно на воздушной подушке", + "movetype_amph" : "Амфибия", + "movetype_spider" : "Вездеход", + "movetype_bot" : "Бот", + "movetype_veh" : "Транспортное средство", + "movetype_ship" : "Корабль", + "level" : "Уровень", + "chassis" : "Шасси", + "modules" : "МОДУЛИ", + "death_explosion" : "Взрыв смерти", + "builds" : "ПОКУПКИ", + "weapons" : "ОРУЖИЕ", + "abilities" : "СПОСОБНОСТИ", + "stats" : "СТАТИСТИКА", + "time_to_reach" : "Время достижения", + "speed_while_reloading" : "Скорость движения при перезарядке", + "drone_max_range" : "Максимальная дальность полета дрона", + "drone_target_range" : "Дальность захвата беспилотника", + "drone_production_speed" : "Скорость сборки беспилотника", + "can_be_transported" : "Транспортируемый", + "min_output" : "Минимальный выход", + "max_output" : "Максимальный выход", + "output_compounds" : "Производительность увеличивается с течением времени", + "output_decays" : "Производительность снижается с течением времени", + "cloaked_speed" : "Замаскированная скорость", + "decloaked_speed" : "Скорость разворачивания", + "pull" : "тянуть", + "push" : "нажмите", + "radius" : "Радиус", + "stats_range" : "Диапазон", + "regen" : "Регенерация", + "acronyms_hp" : "хп", + "acronyms_second" : "секунды", + "acronyms_dps" : "DPS", + "acronyms_agl" : "АГЛ", + "acronyms_emp" : "ЭМИ", + "acronyms_slow" : "М", + "acronyms_disarm" : "С", + "acronyms_capture" : "З", + "alliance" : "Команда", + "team" : "Отряд", + "yes" : "Да", + "no" : "Нет", + "drone_carrier" : "Производитель дронов", + "drone_buildslots" : "Количество автопроизводителей", + "cooldown" : "Остывать", + "drone_label" : "Дополнение к дрону", + "drones_per_cycle" : "Дроны запускаются за цикл", + "drone_build_time" : "Срок изготовления", + "chainlightning" : "Атака распределяется на ближайшие юниты:", + "chainlightning_jumps": "Количество разделений", + "chainlightning_extrajumps": "Дополнительные подразделения", + "chainlightning_efficency": "Эффективность", + "sensor_steal": "Взламывает датчики на %{seconds}сек", + "sensor_tag": "Показывает атакованные юниты в течение %{seconds}сек", + "field_fac": "Может загружать данные нанокадра с дружественных фабрик", + "disrupt_shields" : "Нарушает регенерацию щита" +} diff --git a/LuaUI/Configs/lang/context_menu.th.json b/LuaUI/Configs/lang/context_menu.th.json new file mode 100644 index 0000000000..8917d698ba --- /dev/null +++ b/LuaUI/Configs/lang/context_menu.th.json @@ -0,0 +1,289 @@ +{ + "edit_behavior" : "Edit Behaviour", + "menu_close" : "Close", + "target_water_only" : "(aquatic targets only)", + "target_manual_fire" : "(manual fire)", + "target_antiair" : "(anti-air only)", + "target_guidance" : "(guidance only)", + "shield_hp" : "Capacity", + "shield_percost" : "Capacity per metal", + "shield_regencost" : "Regen cost", + "shield_delay" : "Regen delay", + "shield_nolink" : "Does not link with other shields", + "vampirism_heals" : "Heals self for", + "vampirism_perhit" : "health per hit", + "wolverine_mine" : "mine", + "stats_damage" : "Damage", + "stats_duringcloakstrike" : "(during cloak strike)", + "stats_shielddamage" : "Shield damage", + "stats_reload" : "Reload time", + "stats_aimtime" : "Aim time", + "stats_horizontal_deviation" : "Max Horizontal deviation", + "stats_vertical_deviation" : "Max Vertical Deviation", + "stats_exponential_damage_increase" : "Increases by", + "stats_exponential_damage_capsat" : "Caps out at", + "stats_ignores_shield" : "Ignores shields", + "stats_stun_time" : "Stun time", + "stats_burn_time" : "Burn time", + "stats_aoe" : "Explosion radius", + "stats_weapon_speed" : "Projectile speed", + "stats_force_decloak" : "Forces decloak for", + "weapon_instant_hit" : "Instantly hits", + "stats_missile_launch_speed" : "Launch speed", + "stats_missile_speed" : "Max speed", + "stats_missile_fuel_time" : "Flight Time", + "stats_acceleration" : "Acceleration", + "explodes_on_timeout" : "Explodes on timeout", + "falls_on_timeout" : "Falls down on timeout", + "stats_homing" : "Guidance Rate", + "stats_cruisemissile" : "Cruise Missile", + "stats_cruisealtitude" : "Altitude", + "stats_begins_descent" : "Begins descent", + "stats_from_target" : "elmo from target", + "stats_tracks_target" : "Tracks target", + "stats_guided_cruise" : "Guided Cruise, unguided descent", + "stats_circular_spread" : "Has circular spread (%{size} radius around the target)", + "stats_cruise_error" : "Strikes within %{radius} elmos of the target", + "laser_guided" : "Laser Guided", + "needs_guidance" : "(Needs external guidance)", + "external_targeter" : "Provides External Guidance", + "needs_guidance_for_seconds" : "Requires guidance for %{seconds}", + "stats_inaccuracy" : "Inaccuracy", + "stats_wobble" : "Flight Instability", + "stats_wobble_desc" : "up to", + "stats_blastwave_only_allies" : "Only affects allies", + "stats_burst_time" : "Burst time", + "stats_armor_boost_friendly_only" : "Boosts Allied Units' Armor", + "stats_armor_boost_all" : "Boosts All Units' Armor", + "stats_armor_boost" : "Armor bonus", + "duration" : "Duration", + "stats_armor_boost_doesnt_diminish_duration" : "Duration does not diminish with distance", + "stats_armor_boost_doesnt_diminish_effect" : "Effect does not diminish with distance", + "stats_armor_boost_diminishes" : "Effect and duration falloff with distance", + "stats_armor_pen" : "Ignores Armor", + "stats_spawns" : "Spawns", + "stats_spawn_duration" : "Self destructs after", + "stats_blastwave" : "Creates a blastwave", + "stats_blastwave_startsize" : "Initial Size", + "stats_blastwave_healing_set" : "Heals up to", + "stats_blastwave_initial_healing" : "Initial Healing", + "stats_blastwave_initial_damage" : "Initial Damage", + "stats_overslow_duration" : "Saturated Slow", + "stats_impulse" : "Impulse", + "stats_blastwave_expansion_rate" : "Expansion rate", + "stats_blastwave_power_loss" : "Power loss", + "stats_blastwave_final_radius" : "Final radius", + "stats_slows_down_after_firing" : "Speed lowers after firing", + "weapon_creates_gravity_well" : "Creates a gravity well", + "weapon_groundfire" : "Sets the ground on fire", + "weapon_creates_singularity" : "Creates a Singularity", + "weapon_firing_arc" : "Firing Arc", + "weapon_grid_demand" : "Grid Needed", + "grid_link" : "Grid Link Range", + "grid_needed" : "Required Grid Energy", + "altitude" : "Altitude", + "altitude_bonus" : "Altitude bonus", + "revealpercent" : "Appears to enemies upon reaching %{percent}%% completion", + "sight_range" : "Sight range", + "singularity_strength" : "Strength", + "weapon_arcing" : "Arcing shot", + "weapon_stockpile_time" : "Stockpile time", + "weapon_stockpile_cost" : "Stockpile cost", + "weapon_smooths_ground" : "Smoothes ground", + "weapon_moves_structures" : "Smoothes under structures", + "weapon_high_traj" : "High Trajectory", + "weapon_toggable_traj" : "Toggable Trajectory", + "weapon_arty_reveal" : "Reveals for %{time} seconds while in enemy radar", + "weapon_water_capable" : "Water capable", + "weapon_potential_friendly_fire" : "Potential Friendly Fire", + "weapon_no_ground_collide" : "Passes through ground", + "weapon_increased_damage_vs_large" : "Damage increase vs large units", + "weapon_damage_falloff" : "Damage falls off with range", + "weapon_damage_closeup_falloff" : "Damage increases with range", + "weapon_no_friendly_fire" : "No friendly fire", + "weapon_piercing" : "Piercing", + "weapon_shield_drain" : "Costs shield to fire:", + "weapon_shield_drain_desc" : "charge per shot", + "weapon_aim_delay" : "Aiming delay", + "weapon_inaccuracy_vs_moving" : "Inaccurate against moving targets", + "weapon_interceptable" : "Can be shot down by antinukes", + "weapon_cluster_munitions" : "Cluster Submunitions", + "weapon_cluster_ttr" : "Time-To-Release", + "spooling_weapon" : "Spooling Weapon", + "spooling_weapon_bonus" : "Bonus reload speed per shot", + "spooling_max_bonus" : "Maximum firerate bonus", + "spooling_bonus_time_to_max" : "Time Until Max Firerate", + "construction" : "Construction", + "starting_buildpower" : "Starting buildpower", + "buildpower_increases_use" : "Buildpower increases with use", + "max_buildpower" : "Maximum buildpower", + "buildpower_diminishes_with_disuse" : "Buildpower decreases after disuse", + "decay_rate" : "Decay rate", + "base_buildpower" : "Base Buildpower", + "recharge_delay" : "Recharge delay", + "buildpower_regen_rate" : "Regeneration rate", + "can_resurrect" : "Can resurrect wreckage", + "only_assists" : "Can only assist", + "vampirism" : "Vampirism", + "vampirism_kills_increase_hp" : "Increases max with kills", + "vampirism_kills_increase_hp_desc" : "%{number}%% of victim's max hp", + "armored_unit" : "Hardened Armor", + "armor_reduction" : "Damage Reduction", + "armor_type_1" : "Applies while closed", + "armor_type_2" : "Applies while stopped", + "forced_closed" : "Forcefully closed on damage", + "area_cloak" : "Area cloak", + "upkeep" : "Upkeep", + "recon_pulse" : "Recon Pulse", + "recon_pulse_desc" : "Jams enemy cloaking. Range: 500", + "recon_pulse_applied" : "Pings every 2 seconds", + "personal_cloak" : "Personal Cloak", + "upkeep_mobile" : "Upkeep while mobile", + "upkeep_stationary" : "Upkeep while stationary", + "decloak_radius" : "Decloak Radius", + "cloakstrike" : "Cloaked Ambush Advantage", + "cloakstrike_lose_advantage" : "Loses multipler alongside cloak when shooting", + "unit_no_decloak_on_fire" : "Doesn't lose cloak upon shooting", + "only_idle" : "Only when idle", + "idle_cloak_free" : "Free and automated", + "cloak_regen" : "Regenerates while cloaked", + "recloaks_after_seconds" : "Recloaks after %{time} seconds outside area cloakers", + "provides_intel" : "Provides intel", + "radar" : "Radar Range", + "jamming" : "Radar Stealth Field", + "improves_radar" : "Improves radar accuracy", + "speed" : "Speed", + "movement" : "Movement Type", + "climbs" : "Maximum Slope Tolerance", + "turn_rate" : "Turn rate", + "metal_income" : "Metal Income", + "energy_income" : "Energy Income", + "unit_info" : "Unit Info", + "mid_air_jump" : "Midair jump", + "morphing" : "Morphing", + "morphs_to" : "Morphs to", + "cost" : "Cost", + "bp" : "Build Rate", + "rate" : "Rate", + "rank_required" : "Required Rank", + "morph_time" : "Time", + "not_disabled_morph" : "Not disabled during morph", + "disabled_morph" : "Disabled during morph", + "improved_regen" : "Improved regeneration", + "idle_regen" : "Idle Regeneration", + "regen_time_to_enable" : "Time to enable", + "constant_regen" : "Combat Regeneration", + "nano_regen" : "Nanite Reactive Armor", + "base_regen" : "Base Regeneration", + "max_regen" : "Max Regeneration", + "max_below" : "Maximum bonus below", + "water_regen" : "Water Regeneration", + "armor_regen" : "Armored Regeneration", + "teleporter" : "Teleporter", + "spawns_beacon" : "Spawns a beacon for one-way recall", + "spawn_time" : "Time to spawn", + "at_depth" : "At depth", + "mass" : "Mass", + "teleport_throughput" : "Throughput", + "rearm_repair" : "Rearms and repairs aircraft", + "rearm_pads" : "Pads", + "pad_bp" : "Pad buildpower", + "drone_bound" : "Bound to owner", + "drone_cannot_direct_control" : "Cannot be directly controlled", + "drone_uses_owners_commands" : "Uses owner's commands", + "drone_bound_to_range" : "Must stay in range of owner", + "drone_dies_on_owner_death" : "Will die if owner does", + "speed_boost" : "Speed boost", + "wind_gen" : "Generates energy from wind", + "wind_variable_income" : "Variable income", + "max_generation" : "Maximum Generation", + "wind_100_height" : "Energy per 100 height", + "grey_goo" : "Grey Goo", + "grey_goo_consumption" : "Uses nearby wreckage for replication", + "jump" : "Jumping", + "dangerous_reclaim" : "Explodes when attempting to reclaim", + "floats" : "Floating", + "can_move_to_surface" : "Can move from seabed to surface", + "cannot_move_sideways" : "Cannot move sideways while afloat", + "sinks_when_stun" : "Sinks when stunned", + "float_when_stun" : "Stays afloat when stunned", + "transportation" : "Transports Units", + "transport_type" : "Transport Type", + "transport_light" : "Light", + "transport_heavy" : "Heavy", + "transport_light_speed" : "Loaded Speed", + "transport_heavy_speed" : "Heavy Load Speed", + "anti_interception" : "Can intercept strategic nukes", + "combat_slowdown" : "Combat slowdown", + "radar_invisible" : "Invisible to Radar", + "instant_selfd" : "Instant self-destruction", + "requires_geo" : "Requires thermal vent to build", + "extracts_metal" : "Extracts metal", + "fireproof" : "Fireproof (Immune to burning damage)", + "gravitronic_regulation" : "Gravitronic Regulation (Immune to impulse)", + "storage" : "Stores Resources", + "shared_to_team" : "Shares metal extraction to team", + "free" : "Free", + "movetype_immobile" : "Immobile", + "movetype_plane" : "Aircraft", + "movetype_gunship" : "Gunship", + "movetype_sub" : "Submarine", + "movetype_waterwalker" : "Swimming", + "movetype_hover" : "Hovercraft", + "movetype_amph" : "Amphibious", + "movetype_spider" : "All-terrain", + "movetype_bot" : "Bot", + "movetype_veh" : "Vehicle", + "movetype_ship" : "Ship", + "level" : "Level", + "chassis" : "Chassis", + "modules" : "MODULES", + "death_explosion" : "Death Explosion", + "builds" : "BUILDS", + "weapons" : "WEAPONS", + "abilities" : "ABILITIES", + "stats" : "STATS", + "time_to_reach" : "Time to reach", + "speed_while_reloading" : "Movement speed while reloading", + "drone_max_range" : "Drone Max Range", + "drone_target_range" : "Drone Acquisition Range", + "drone_production_speed" : "Drone Build Speed", + "can_be_transported" : "Transportable", + "min_output" : "Minimum Output", + "max_output" : "Maximum Output", + "output_compounds" : "Output increases over time", + "output_decays" : "Output decays over time", + "cloaked_speed" : "Cloaked Speed", + "decloaked_speed" : "Decloaked Speed", + "pull" : "pull", + "push" : "push", + "radius" : "Radius", + "stats_range" : "Range", + "regen" : "Regeneration", + "acronyms_hp" : "hp", + "acronyms_second" : "sec", + "acronyms_dps" : "DPS", + "acronyms_agl" : "AGL", + "acronyms_emp" : "EMP", + "acronyms_slow" : "S", + "acronyms_disarm" : "D", + "acronyms_capture" : "C", + "alliance" : "Team", + "team" : "Squad", + "yes" : "Yes", + "no" : "No", + "drone_carrier" : "Drone Manufacturer", + "drone_buildslots" : "Number of Autofabricators", + "cooldown" : "Cooldown", + "drone_label" : "Drone Complement", + "drones_per_cycle" : "Drones started per cycle", + "drone_build_time" : "Manufacture time", + "chainlightning" : "การโจมตีแยกไปยังยูนิตใกล้เคียง:", + "chainlightning_jumps": "จำนวนการแยก", + "chainlightning_extrajumps" : "ดิวิชั่นพิเศษ", + "chainlightning_efficency" : "ประสิทธิภาพ", + "sensor_steal": "แฮ็กเซ็นเซอร์เป็นเวลา %{seconds} วินาที", + "sensor_tag" : "เปิดเผยยูนิตที่ถูกโจมตีเป็นเวลา %{seconds} วินาที", + "field_fac" : "สามารถดาวน์โหลดข้อมูลนาโนเฟรมจากโรงงานที่เป็นมิตร", + "disrupt_shields" : "ขัดขวางการฟื้นฟูโล่" +} diff --git a/LuaUI/Configs/lang/context_menu.tr.json b/LuaUI/Configs/lang/context_menu.tr.json new file mode 100644 index 0000000000..8c5eb33be4 --- /dev/null +++ b/LuaUI/Configs/lang/context_menu.tr.json @@ -0,0 +1,289 @@ +{ + "edit_behavior" : "Davranışı Düzenle", + "menu_close" : "Kapat", + "target_water_only" : "(sadece su hedefleri)", + "target_manual_fire" : "(manuel hedefleme)", + "target_antiair" : "(sadece uçaksavar)", + "target_guidance" : "(sadece rehberlik)", + "shield_hp" : "Kapasite", + "shield_percost" : "Maliyet başına kapasite", + "shield_regencost" : "Yenileme maliyeti", + "shield_delay" : "Yenilenme gecikmesi", + "shield_nolink" : "Diğer kalkanlarla bağlantı kurmaz", + "vampirism_heals" : "Kendini iyileştirir", + "vampirism_perhit" : "vuruş başına sağlık", + "wolverine_mine" : "Kara mayını", + "stats_damage" : "Zarar", + "stats_duringcloakstrike" : "(pusu sırasında)", + "stats_shielddamage" : "Kalkan hasarı", + "stats_reload" : "Tekrar dolum suresi", + "stats_aimtime" : "Nişan alma zamanı", + "stats_horizontal_deviation" : "Maksimum Yatay sapma", + "stats_vertical_deviation" : "Maksimum Dikey Sapma", + "stats_exponential_damage_increase" : "Tarafından artar", + "stats_exponential_damage_capsat" : "Büyük harf", + "stats_ignores_shield" : "Kalkanlara nüfuz eder", + "stats_stun_time" : "Şok zamanı", + "stats_burn_time" : "Yanma süresi", + "stats_aoe" : "Patlama yarıçapı", + "stats_weapon_speed" : "Mermi hızı", + "stats_force_decloak" : "Kuvvetler açığa çıkar", + "weapon_instant_hit" : "Anında vurur", + "stats_missile_launch_speed" : "Fırlatma hızı", + "stats_missile_speed" : "Maksimum hız", + "stats_missile_fuel_time" : "Uçuş Süresi", + "stats_acceleration" : "Hızlanma", + "explodes_on_timeout" : "Yakıt bittiğinde patlar", + "falls_on_timeout" : "Yakıt bittiğinde düşer", + "stats_homing" : "Rehberlik Oranı", + "revealpercent": "%{percent}%% tamamlamaya ulaşıldığında düşmanlara görünür", + "stats_cruisemissile" : "Seyir Füzesi", + "stats_cruisealtitude" : "Yükseklik", + "stats_begins_descent" : "İniş başlıyor", + "stats_from_target" : "hedeften elmo uzakta", + "stats_tracks_target" : "Hedefi izler", + "stats_guided_cruise" : "Rehberli seyir, rehbersiz iniş", + "stats_circular_spread" : "Dairesel yayılıma sahiptir (hedef etrafında %{size} yarıçap)", + "stats_cruise_error" : "Hedefin %{radius} elmos içinde vurur", + "laser_guided" : "Lazer Kılavuzlu", + "needs_guidance" : "(Dış rehberliğe ihtiyaç var)", + "external_targeter" : "Dış Rehberlik Sağlar", + "needs_guidance_for_seconds" : "%{seconds} için rehberlik gerektirir", + "stats_inaccuracy" : "Yanlışlık", + "stats_wobble" : "Uçuş Kararsızlığı", + "stats_wobble_desc" : "kadar", + "stats_blastwave_only_allies" : "Sadece müttefikleri etkiler", + "stats_burst_time" : "patlama süresi", + "stats_armor_boost_friendly_only" : "Müttefik Birimlerin Zırhını Artırır", + "stats_armor_boost_all" : "Tüm Birimlerin Zırhını Artırır", + "stats_armor_boost" : "Zırh bonusu", + "duration" : "Zırh takviyesi", + "stats_armor_boost_doesnt_diminish_duration" : "Süre mesafe ile azalmaz", + "stats_armor_boost_doesnt_diminish_effect" : "Etki mesafe ile azalmaz", + "stats_armor_boost_diminishes" : "Mesafe ile etki ve süre düşüşü", + "stats_armor_pen" : "Zırhı delip geçer", + "stats_spawns" : "Yaratır", + "stats_spawn_duration" : "Kendini imha ettikten sonra", + "stats_blastwave" : "Bir patlama dalgası yaratır", + "stats_blastwave_startsize" : "İlk Boyut", + "stats_blastwave_healing_set" : "Şuna kadar iyileştirir", + "stats_blastwave_initial_healing" : "İlk İyileşme", + "stats_blastwave_initial_damage" : "İlk Hasar", + "stats_overslow_duration" : "Doymuş Yavaş", + "stats_impulse" : "kuvvet", + "stats_blastwave_expansion_rate" : "Genişleme oranı", + "stats_blastwave_power_loss" : "Güç kaybı", + "stats_blastwave_final_radius" : "Nihai yarıçap", + "stats_slows_down_after_firing" : "Ateşlemeden sonra hız düşer", + "weapon_creates_gravity_well" : "Bir yerçekimi kuyusu oluşturur", + "weapon_groundfire" : "Zemini ateşe verir", + "weapon_creates_singularity" : "Bir Kara Delik Oluşturur", + "weapon_firing_arc" : "Ateşleme Arkı", + "weapon_grid_demand" : "Izgara Gerekli", + "grid_link" : "Izgara Bağlantı Aralığı", + "grid_needed" : "Gerekli Şebeke Enerjisi", + "altitude" : "Yükseklik", + "altitude_bonus" : "İrtifa bonusu", + "sight_range" : "Görüş mesafesi", + "singularity_strength" : "Güç", + "weapon_arcing" : "Ark atışı", + "weapon_stockpile_time" : "Stoklama süresi", + "weapon_stockpile_cost" : "Stoklama maliyeti", + "weapon_smooths_ground" : "Zemini pürüzsüzleştirir", + "weapon_moves_structures" : "Yapıların altını pürüzsüzleştirir", + "weapon_high_traj" : "Yüksek Yörünge", + "weapon_toggable_traj" : "Değiştirilebilir Yörünge", + "weapon_arty_reveal" : "Düşman radarındayken %{time} saniye boyunca ortaya çıkar", + "weapon_water_capable" : "Ateşi suya dönüştürebilir", + "weapon_potential_friendly_fire" : "Potansiyel Dost Ateşi", + "weapon_no_ground_collide" : "Yerden geçer", + "weapon_increased_damage_vs_large" : "Büyük birimlere karşı hasar artışı", + "weapon_damage_falloff" : "Hasar menzil ile birlikte düşer", + "weapon_damage_closeup_falloff" : "Hasar menzil ile artar", + "weapon_no_friendly_fire" : "Dost ateşi yok", + "weapon_piercing" : "Birimleri delip geçer", + "weapon_shield_drain" : "Ateş etmek için kalkan gerekir:", + "weapon_shield_drain_desc" : "atış başına ücret", + "weapon_aim_delay" : "Hedefleme gecikmesi", + "weapon_inaccuracy_vs_moving" : "Hareketli hedeflere karşı isabetsiz", + "weapon_interceptable" : "Antinükleer silahlar tarafından vurulabilir", + "weapon_cluster_munitions" : "Küme Mühimmatları", + "weapon_cluster_ttr" : "Yayınlanma Zamanı", + "spooling_weapon" : "Biriktirme Silahı", + "spooling_weapon_bonus" : "Atış başına yeniden doldurma hızı artışı", + "spooling_max_bonus" : "Maksimum ateş hızı artışı", + "spooling_bonus_time_to_max" : "Maksimum Ateş Hızına Kadar Geçen Süre", + "construction" : "İnşaat", + "starting_buildpower" : "Yapı gücünü başlatma", + "buildpower_increases_use" : "Yapı gücü kullanımla birlikte artar", + "max_buildpower" : "Maksimum yapı gücü", + "buildpower_diminishes_with_disuse" : "Kullanılmadığında yapı gücü azalır", + "decay_rate" : "Çürüme oranı", + "base_buildpower" : "Temel Yapı Gücü", + "recharge_delay" : "Şarj gecikmesi", + "buildpower_regen_rate" : "Rejenerasyon oranı", + "can_resurrect" : "Enkazı diriltebilir", + "only_assists" : "Sadece yardımcı olabilir", + "vampirism" : "Vampirizm", + "vampirism_kills_increase_hp" : "Öldürmelerle maksimum artar", + "vampirism_kills_increase_hp_desc" : "Kurbanın maksimum hp'sinin %{number}%%'ü", + "armored_unit" : "Sertleştirilmiş Zırh", + "armor_reduction" : "Hasar Azaltma", + "armor_type_1" : "Kapalıyken geçerlidir", + "armor_type_2" : "Durdurulduğunda geçerlidir", + "forced_closed" : "Hasar üzerine zorla kapatıldı", + "area_cloak" : "Alan pelerini", + "upkeep" : "Bakım", + "recon_pulse" : "Recon Pulse", + "recon_pulse_desc" : "Düşman gizlenmesini engeller. Menzil: 500", + "recon_pulse_applied" : "Her 2 saniyede bir tarar", + "personal_cloak" : "Kişisel Pelerin", + "upkeep_mobile" : "Mobil haldeyken bakım", + "upkeep_stationary" : "Sabit durumdayken bakım", + "decloak_radius" : "Gizlenmeme Yarıçapı", + "cloakstrike" : "Gizlenmiş Pusu Avantajı", + "cloakstrike_lose_advantage" : "Ateş ederken pelerinin yanında çoklayıcıyı da kaybeder", + "unit_no_decloak_on_fire" : "Ateş edildiğinde pelerini kaybetmez", + "only_idle" : "Sadece boştayken", + "idle_cloak_free" : "Ücretsiz ve otomatik", + "cloak_regen" : "Görünmezken yenilenir", + "recloaks_after_seconds" : "Alan gizleyicileri dışında %{time} saniye sonra yeniden gizlenir", + "provides_intel" : "İstihbarat sağlar", + "radar" : "Radar Menzili", + "jamming" : "Radar Karıştırma Alanı", + "improves_radar" : "Radar doğruluğunu artırır", + "speed" : "Hız", + "movement" : "Hareket Tipi", + "climbs" : "Maksimum Eğim Toleransı", + "turn_rate" : "Dönüş hızı", + "metal_income" : "Metal Gelirleri", + "energy_income" : "Enerji Geliri", + "unit_info" : "Birim Bilgisi", + "mid_air_jump" : "Havada zıplama", + "morphing" : "Dönüşüm", + "morphs_to" : "Dönüşür", + "cost" : "Maliyet", + "bp" : "Yapı Oranı", + "rate" : "Oran", + "rank_required" : "Gerekli Rütbe", + "morph_time" : "Zaman", + "not_disabled_morph" : "Dönüşüm sırasında devre dışı bırakılmaz", + "disabled_morph" : "Dönüşüm sırasında devre dışı", + "improved_regen" : "İyileştirilmiş rejenerasyon", + "idle_regen" : "Rölanti Rejenerasyonu", + "regen_time_to_enable" : "Etkinleştirme zamanı", + "constant_regen" : "Savaş Rejenerasyonu", + "nano_regen" : "Nanit Reaktif Zırh", + "base_regen" : "Taban Yenileme", + "max_regen" : "Maksimum Rejenerasyon", + "max_below" : "Aşağıdaki maksimum rejenerasyon", + "water_regen" : "Su Rejenerasyonu", + "armor_regen" : "Zırhlı Yenilenme", + "teleporter" : "Işınlayıcı", + "spawns_beacon" : "Tek yönlü geri çağırma için bir işaretçi doğurur", + "spawn_time" : "Yumurtlama zamanı", + "at_depth" : "Derinlikte", + "mass" : "Kütle", + "teleport_throughput" : "Verim", + "rearm_repair" : "Hava taşıtlarını yeniden düzenler ve onarır", + "rearm_pads" : "İniş pistleri", + "pad_bp" : "İniş pisti inşa gücü", + "drone_bound" : "Sahibine bağlı", + "drone_cannot_direct_control" : "Doğrudan kontrol edilemez", + "drone_uses_owners_commands" : "Sahibinin komutlarını kullanır", + "drone_bound_to_range" : "Sahibinin menzilinde kalmalıdır", + "drone_dies_on_owner_death" : "Sahibi yaparsa ölecek", + "speed_boost" : "Hız artışı", + "wind_gen" : "Rüzgardan enerji üretir", + "wind_variable_income" : "Değişken gelir", + "max_generation" : "Maksimum Üretim", + "wind_100_height" : "100 yükseklik başına enerji", + "grey_goo" : "Kendi kendini kopyalama", + "grey_goo_consumption" : "Çoğaltma için yakındaki enkazı kullanır", + "jump" : "Atlama", + "dangerous_reclaim" : "Geri almaya çalışırken patlar", + "floats" : "Yüzer", + "can_move_to_surface" : "Deniz tabanından yüzeye hareket edebilir", + "cannot_move_sideways" : "Su üstündeyken yanlara doğru hareket edemez", + "sinks_when_stun" : "Sersemletildiğinde batar", + "float_when_stun" : "Sersemletildiğinde ayakta kalır", + "transportation" : "Nakliye Birimleri", + "transport_type" : "Taşıma Türü", + "transport_light" : "Işık", + "transport_heavy" : "Ağır", + "transport_light_speed" : "Yüklü Hız", + "transport_heavy_speed" : "Ağır Yük Hızı", + "anti_interception" : "Stratejik nükleer bombaları engelleyebilir", + "combat_slowdown" : "Savaş yavaşlaması", + "radar_invisible" : "Radara Görünmez", + "instant_selfd" : "Anında kendini yok etme", + "requires_geo" : "İnşa etmek için termal havalandırma gerektirir", + "extracts_metal" : "Metal çıkarır", + "fireproof" : "Yanmaz (Yanma hasarına karşı bağışıklık)", + "gravitronic_regulation" : "Gravitronik Düzenleme (Dürtülere karşı bağışıklık)", + "storage" : "Mağaza Kaynakları", + "shared_to_team" : "Ekstraksiyonu ekiple paylaşır", + "free" : "Ücretsiz", + "movetype_immobile" : "Hareketsiz", + "movetype_plane" : "Uçak", + "movetype_gunship" : "Helikopter", + "movetype_sub" : "Denizaltı", + "movetype_waterwalker" : "Yüzme", + "movetype_hover" : "Hovercraft", + "movetype_amph" : "Amfibi", + "movetype_spider" : "Arazi tipi", + "movetype_bot" : "Yürümek", + "movetype_veh" : "Araç", + "movetype_ship" : "Gemi", + "level" : "Seviye", + "chassis" : "Şasi", + "modules" : "MODÜLLER", + "death_explosion" : "Ölüm Patlaması", + "builds" : "YAPABİLİR", + "weapons" : "SİLAHLAR", + "abilities" : "YETENEKLER", + "stats" : "İSTATİSTİKLER", + "time_to_reach" : "Ulaşma zamanı", + "speed_while_reloading" : "Yeniden doldururken hareket hızı", + "drone_max_range" : "Drone Maksimum Menzili", + "drone_target_range" : "Drone Edinim Aralığı", + "drone_production_speed" : "Drone İnşa Hızı", + "can_be_transported" : "Taşınabilir", + "min_output" : "Asgari Çıkış", + "max_output" : "Maksimum Çıkış", + "output_compounds" : "Çıktı zaman içinde artar", + "output_decays" : "Çıktı zaman içinde azalır", + "cloaked_speed" : "Gizlenmiş Hız", + "decloaked_speed" : "Görünmezlikten Çıkma Hızı", + "pull" : "çek", + "push" : "itmek", + "radius" : "Yarıçap", + "stats_range" : "Menzil", + "regen" : "Rejenerasyon", + "acronyms_hp" : "hp", + "acronyms_second" : "Sn", + "acronyms_dps" : "SBH", + "acronyms_agl" : "Yükseklik", + "acronyms_emp" : "ÇYP", + "acronyms_slow" : "YA", + "acronyms_disarm" : "S", + "acronyms_capture" : "Y", + "alliance" : "Takım", + "team" : "Tayfa", + "yes" : "Evet", + "no" : "Hayir", + "drone_carrier" : "Dron Üreticisi", + "drone_buildslots" : "Otofabrikatör Sayısı", + "cooldown" : "Sakin ol", + "drone_label" : "Drone Tamamlayıcı", + "drones_per_cycle" : "Döngü başına başlatılan dronlar", + "drone_build_time" : "Üretim zamanı", + "chainlightning" : "Saldırı yakındaki birimlere yayılır:", + "chainlightning_jumps": "Bölme sayısı", + "chainlightning_extrajumps": "Ekstra bölümler", + "chainlightning_efficency": "Verimlilik", + "sensor_steal": "Sensörleri %{seconds}sn boyunca hackler", + "sensor_tag": "%{seconds}sn boyunca saldırıya uğrayan birimleri ortaya çıkarır", + "field_fac": "Dost fabrikalardan nanoframe verileri indirilebilir", + "disrupt_shields" : "Kalkan yenilenmesini bozar" +} diff --git a/LuaUI/Configs/lang/context_menu.zh.json b/LuaUI/Configs/lang/context_menu.zh.json new file mode 100644 index 0000000000..4195cbdd2b --- /dev/null +++ b/LuaUI/Configs/lang/context_menu.zh.json @@ -0,0 +1,289 @@ +{ + "edit_behavior" : "编辑行为", + "menu_close" : "出口", + "target_water_only" : "(仅限水生目标)", + "target_manual_fire" : "(手动瞄准器)", + "target_antiair" : "(仅限防空)", + "target_guidance" : "(仅供指导)", + "shield_hp" : "能力", + "shield_percost" : "每种金属的容量", + "shield_regencost" : "再生成本", + "shield_delay" : "再生延迟", + "shield_nolink" : "不与其他盾牌连接", + "vampirism_heals" : "治疗自己的", + "vampirism_perhit" : "每一击的生命值", + "wolverine_mine" : "地雷", + "stats_damage" : "损害", + "stats_duringcloakstrike" : "(隐身攻击时)", + "stats_shielddamage" : "盾牌伤害", + "stats_reload" : "重新加载时间", + "stats_aimtime" : "瞄准时间", + "stats_horizontal_deviation" : "最大水平偏差", + "stats_vertical_deviation" : "最大垂直偏差", + "stats_exponential_damage_increase" : "增加了", + "stats_exponential_damage_capsat" : "帽子出在", + "stats_ignores_shield" : "无视护盾", + "stats_stun_time" : "眩晕时间", + "stats_burn_time" : "燃烧时间", + "stats_aoe" : "爆炸半径", + "stats_weapon_speed" : "射出速度", + "stats_force_decloak" : "力量解体为", + "weapon_instant_hit" : "瞬间击中", + "stats_missile_launch_speed" : "发射速度", + "stats_missile_speed" : "最大速度", + "stats_missile_fuel_time" : "飞行时间", + "stats_acceleration" : "加速", + "explodes_on_timeout" : "缺少燃料时发生爆炸", + "falls_on_timeout" : "缺少燃料时倒下", + "stats_homing" : "指导率", + "revealpercent" : "在完成 %{percent}%% 时向敌人显现", + "stats_cruisemissile" : "巡航导弹", + "stats_cruisealtitude" : "海拔高度", + "stats_begins_descent" : "开始下降", + "stats_from_target" : "目标公司的Elmo", + "stats_tracks_target" : "追踪目标", + "stats_guided_cruise" : "有向导的巡游,无向导的下山", + "stats_circular_spread" : "具有环形传播(目标周围%{size}半径)。", + "stats_cruise_error" : "在目标的%{radius}埃尔莫斯范围内进行打击", + "laser_guided" : "激光制导", + "needs_guidance" : "(需要外部指导)", + "external_targeter" : "提供外部指导", + "needs_guidance_for_seconds" : "需要指导%{seconds}", + "stats_inaccuracy" : "不准确", + "stats_wobble" : "飞行不稳定", + "stats_wobble_desc" : "至", + "stats_blastwave_only_allies" : "只影响到盟友", + "stats_burst_time" : "爆发时间", + "stats_armor_boost_friendly_only" : "提升盟军单位的装甲", + "stats_armor_boost_all" : "提升所有单位的装甲", + "stats_armor_boost" : "盔甲奖励", + "duration" : "时间", + "stats_armor_boost_doesnt_diminish_duration" : "持续时间不会随着距离的增加而减少", + "stats_armor_boost_doesnt_diminish_effect" : "效果不因距离而减弱", + "stats_armor_boost_diminishes" : "效果和持续时间随距离衰减", + "stats_armor_pen" : "无视盔甲", + "stats_spawns" : "诞生", + "stats_spawn_duration" : "后自毁", + "stats_blastwave" : "形成爆炸波", + "stats_blastwave_startsize" : "初始尺寸", + "stats_blastwave_healing_set" : "痊愈率达", + "stats_blastwave_initial_healing" : "初步愈合", + "stats_blastwave_initial_damage" : "最初的损害", + "stats_overslow_duration" : "饱和慢速", + "stats_impulse" : "冲动", + "stats_blastwave_expansion_rate" : "膨胀率", + "stats_blastwave_power_loss" : "功率损失", + "stats_blastwave_final_radius" : "最终半径", + "stats_slows_down_after_firing" : "发射后速度降低", + "weapon_creates_gravity_well" : "创造一个重力井", + "weapon_groundfire" : "将地面烧毁", + "weapon_creates_singularity" : "创造一个黑洞", + "weapon_firing_arc" : "发射弧度", + "weapon_grid_demand" : "需要的网格", + "grid_link" : "网格链接范围", + "grid_needed" : "所需的电网能源", + "altitude" : "海拔高度", + "altitude_bonus" : "海拔奖励", + "sight_range" : "视力范围", + "singularity_strength" : "强度", + "weapon_arcing" : "弧形射击", + "weapon_stockpile_time" : "储存时间", + "weapon_stockpile_cost" : "储存成本", + "weapon_smooths_ground" : "抚平地面", + "weapon_moves_structures" : "抚平结构下方", + "weapon_high_traj" : "高位弹道", + "weapon_toggable_traj" : "可切换的轨迹", + "weapon_arty_reveal" : "在敌方雷达中时,显影%{time}秒", + "weapon_water_capable" : "水的能力", + "weapon_potential_friendly_fire" : "潜在的友军射击", + "weapon_no_ground_collide" : "穿过地面", + "weapon_increased_damage_vs_large" : "对大型单位的伤害增加", + "weapon_damage_falloff" : "伤害随着范围的扩大而下降", + "weapon_damage_closeup_falloff" : "伤害随射程增加", + "weapon_no_friendly_fire" : "没有友好的火力", + "weapon_piercing" : "穿刺单位", + "weapon_shield_drain" : "发射时需要耗费盾牌", + "weapon_shield_drain_desc" : "每枪收费", + "weapon_aim_delay" : "瞄准延迟", + "weapon_inaccuracy_vs_moving" : "对付移动目标不准确", + "weapon_interceptable" : "可被反核弹击落", + "weapon_cluster_munitions" : "集束子弹药", + "weapon_cluster_ttr" : "发布时间", + "spooling_weapon" : "转轴武器", + "spooling_weapon_bonus" : "每发子弹的奖励重装速度", + "spooling_max_bonus" : "最大射速奖励", + "spooling_bonus_time_to_max" : "直到最大发射率的时间", + "construction" : "建筑", + "starting_buildpower" : "启动建设力量", + "buildpower_increases_use" : "建设力量随着使用而增加", + "max_buildpower" : "最大建造力", + "buildpower_diminishes_with_disuse" : "废弃后,建造力下降", + "decay_rate" : "衰减率", + "base_buildpower" : "基础建设力量", + "recharge_delay" : "充电延迟", + "buildpower_regen_rate" : "再生率", + "can_resurrect" : "能使残骸复活", + "only_assists" : "只能协助", + "vampirism" : "吸血鬼主义", + "vampirism_kills_increase_hp" : "杀人后增加最大生命值", + "vampirism_kills_increase_hp_desc" : "%{number}%受害者的最大生命值", + "armored_unit" : "坚硬的盔甲", + "armor_reduction" : "减少伤害", + "armor_type_1" : "关闭时适用", + "armor_type_2" : "在停止时适用", + "forced_closed" : "损坏时强行关闭", + "area_cloak" : "地区隐身衣", + "upkeep" : "维护", + "recon_pulse" : "侦察脉冲", + "recon_pulse_desc" : "卡住敌人的隐形装置。范围: 500", + "recon_pulse_applied" : "每2秒一次的平移", + "personal_cloak" : "个人隐身衣", + "upkeep_mobile" : "移动时的维护", + "upkeep_stationary" : "静止状态下的维护", + "decloak_radius" : "解散半径", + "cloakstrike" : "隐身伏击的优势", + "cloakstrike_lose_advantage" : "射击时失去了与隐身衣一起的多普勒。", + "unit_no_decloak_on_fire" : "射击时不会失去斗篷", + "only_idle" : "只有在空闲时", + "idle_cloak_free" : "免费和自动化", + "cloak_regen" : "隐身状态下的再生能力", + "recloaks_after_seconds" : "%{time}秒后在区域外隐身器上重新出现。", + "provides_intel" : "提供情报", + "radar" : "雷达范围", + "jamming" : "雷达隐身场", + "improves_radar" : "提高雷达精度", + "speed" : "速度", + "movement" : "运动类型", + "climbs" : "最大坡度公差", + "turn_rate" : "转动率", + "metal_income" : "金属收入", + "energy_income" : "能源收入", + "unit_info" : "单位信息", + "mid_air_jump" : "半空跳跃", + "morphing" : "变形", + "morphs_to" : "变形为", + "cost" : "费用", + "bp" : "建立率", + "rate" : "速率", + "rank_required" : "所需等级", + "morph_time" : "时间", + "not_disabled_morph" : "在变形过程中未被禁用", + "disabled_morph" : "在变形过程中被禁用", + "improved_regen" : "改善再生能力", + "idle_regen" : "闲置再生", + "regen_time_to_enable" : "启用时间", + "constant_regen" : "战斗再生", + "nano_regen" : "纳米反应式盔甲", + "base_regen" : "基地再生", + "max_regen" : "最大的再生能力", + "max_below" : "最高奖金如下", + "water_regen" : "水的再生", + "armor_regen" : "铠甲再生", + "teleporter" : "遥感器", + "spawns_beacon" : "生成一个单向召回的信标", + "spawn_time" : "产卵时间", + "at_depth" : "在深度上", + "mass" : "群体", + "teleport_throughput" : "吞吐量", + "rearm_repair" : "重新装备和修理飞机", + "rearm_pads" : "着陆点", + "pad_bp" : "降落台维修动力", + "drone_bound" : "捆绑在主人身上", + "drone_cannot_direct_control" : "不能直接控制", + "drone_uses_owners_commands" : "使用主人的命令", + "drone_bound_to_range" : "必须保持在主人的范围内", + "drone_dies_on_owner_death" : "如果主人这样做会死的", + "speed_boost" : "速度提升", + "wind_gen" : "从风中产生能量", + "wind_variable_income" : "可变收入", + "max_generation" : "最大生成量", + "wind_100_height" : "每100个高度的能量", + "grey_goo" : "灰色粘土", + "grey_goo_consumption" : "利用附近的残骸进行复制", + "jump" : "跳跃", + "dangerous_reclaim" : "试图回收时发生爆炸", + "floats" : "漂浮", + "can_move_to_surface" : "可以从海床移动到海面", + "cannot_move_sideways" : "漂浮时不能侧向移动", + "sinks_when_stun" : "晕倒时下沉", + "float_when_stun" : "眩晕时能保持漂浮状态", + "transportation" : "运输单位", + "transport_type" : "运输类型", + "transport_light" : "亮度", + "transport_heavy" : "沉重", + "transport_light_speed" : "装载速度", + "transport_heavy_speed" : "重载速度", + "anti_interception" : "可以拦截战略核弹", + "combat_slowdown" : "战斗速度减慢", + "radar_invisible" : "对雷达不可见", + "instant_selfd" : "瞬间自我毁灭", + "requires_geo" : "需要热风炉来建造", + "extracts_metal" : "提取金属", + "fireproof" : "耐火(对燃烧伤害免疫)", + "gravitronic_regulation" : "重力电子调节(对冲动免疫)", + "storage" : "商店资源", + "shared_to_team" : "向团队分享金属提取", + "free" : "免费", + "movetype_immobile" : "不动的", + "movetype_plane" : "飞机", + "movetype_gunship" : "炮艇", + "movetype_sub" : "潜水艇", + "movetype_waterwalker" : "游泳", + "movetype_hover" : "气垫船", + "movetype_amph" : "水陆两用", + "movetype_spider" : "全地形", + "movetype_bot" : "瓶子", + "movetype_veh" : "车辆", + "movetype_ship" : "船只", + "level" : "级别", + "chassis" : "底盘", + "modules" : "模块", + "death_explosion" : "死亡爆炸", + "builds" : "施工方案", + "weapons" : "武器", + "abilities" : "能力", + "stats" : "统计资料", + "time_to_reach" : "达到的时间", + "speed_while_reloading" : "重装时的移动速度", + "drone_max_range" : "无人机最大范围", + "drone_target_range" : "无人机采集范围", + "drone_production_speed" : "无人机建造速度", + "can_be_transported" : "可运输", + "min_output" : "最小输出", + "max_output" : "最大输出", + "output_compounds" : "产出随时间增加", + "output_decays" : "输出随时间衰减", + "cloaked_speed" : "隐身的速度", + "decloaked_speed" : "解散的速度", + "pull" : "牵引", + "push" : "推动", + "radius" : "半径", + "stats_range" : "范围", + "regen" : "再生", + "acronyms_hp" : "击球点", + "acronyms_second" : "秒", + "acronyms_dps" : "每秒伤害", + "acronyms_agl" : "地面以上", + "acronyms_emp" : "电磁脉冲", + "acronyms_slow" : "缓慢", + "acronyms_disarm" : "解除武装", + "acronyms_capture" : "捕获", + "alliance" : "团队", + "team" : "队伍", + "yes" : "是", + "no" : "没有", + "drone_carrier" : "无人机制造商", + "drone_buildslots" : "汽车制造商数量", + "cooldown" : "冷却", + "drone_label" : "无人机补充", + "drones_per_cycle" : "每个周期启动的无人机", + "drone_build_time" : "制造时间", + "chainlightning" : "攻击分散到附近的单位:", + "chainlightning_jumps": "分割次数", + "chainlightning_extrajumps" : "额外的师", + "chainlightning_efficency" : "效率", + "sensor_steal": "攻击传感器%{seconds}秒", + "sensor_tag": "显示受攻击 %{seconds} 秒的单位", + "field_fac" : "可以从友好工厂下载纳米帧数据", + "disrupt_shields" : "破坏盾牌再生" +} diff --git a/LuaUI/Widgets/gui_contextmenu.lua b/LuaUI/Widgets/gui_contextmenu.lua index ef13f49ab8..274aa52278 100644 --- a/LuaUI/Widgets/gui_contextmenu.lua +++ b/LuaUI/Widgets/gui_contextmenu.lua @@ -1,13 +1,13 @@ function widget:GetInfo() - return { - name = "Context Menu", - desc = "v0.088 Chili Context Menu\nPress [Space] while clicking for a context menu.", - author = "CarRepairer", - date = "2009-06-02", - license = "GNU GPL, v2 or later", - layer = 0, - enabled = true, - } + return { + name = "Context Menu", + desc = "v0.1 Chili Context Menu\nPress [Space] while clicking for a context menu.", + author = "CarRepairer, localized by Shaman", + date = "2009-06-02", + license = "GNU GPL, v2 or later", + layer = 0, + enabled = true, + } end --[[ @@ -29,7 +29,6 @@ stats_hide_damage stats_hide_reload stats_hide_dps stats_hide_projectile_speed - ]] -------------------------------------------------------------------------------- @@ -38,6 +37,7 @@ stats_hide_projectile_speed include("keysym.lua") VFS.Include("LuaRules/Utilities/numberfunctions.lua") VFS.Include("LuaRules/Utilities/versionCompare.lua") +local carrierDefs = {} local spSendLuaRulesMsg = Spring.SendLuaRulesMsg local spGetCurrentTooltip = Spring.GetCurrentTooltip @@ -85,7 +85,7 @@ local color2incolor -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -local WINDOW_WIDTH = 450 +local WINDOW_WIDTH = 650 local B_HEIGHT = 30 local icon_size = 18 @@ -149,16 +149,23 @@ AddFactoryOfUnits("staticmissilesilo") local buildOpts = VFS.Include("gamedata/buildoptions.lua") local factory_commands, econ_commands, defense_commands, special_commands = include("Configs/integral_menu_commands_processed.lua", nil, VFS.RAW_FIRST) +local droneDefs, _, commanderDroneDefs = VFS.Include("LuaRules/Configs/drone_defs.lua") +for id, data in pairs(droneDefs) do -- For whatever reason, unitDefID is not the same. + carrierDefs[UnitDefs[id].name] = data +end + + for i = 1, #buildOpts do local name = buildOpts[i] local unitDefID = UnitDefNames[name].id + local isDrone = UnitDefs[unitDefID].customParams.is_drone ~= nil if econ_commands[-unitDefID] then behaviourPath[unitDefID] = BEHAVIOUR_PATH .. "Economy" elseif defense_commands[-unitDefID] then behaviourPath[unitDefID] = BEHAVIOUR_PATH .. "Defence" elseif special_commands[-unitDefID] then behaviourPath[unitDefID] = BEHAVIOUR_PATH .. "Special" - else + elseif not isDrone then behaviourPath[-unitDefID] = BEHAVIOUR_PATH .. "Misc" end end @@ -221,6 +228,313 @@ options = { }, } +local hitscan = { + BeamLaser = true, + LightningCannon = true, +} -- there's no point in making this table repeatedly when we're going to reuse it. + +local localizationCommon = { + player = "Player", + commander = "Commander", + health = "Health", + metal = "Metal", + energy = "Energy", + buildpower = "Buildpower", +} + +local localization = { + menu_close = "close", + edit_behavior = "edit behavior", + target_water_only = "(water only)", + target_manual_fire = "(manual fire)", + target_antiair = "(anti-air only)", + target_guidance = "(guidance only)", + shield_hp = "Strength", + shield_percost = "Strength per metal", + shield_regencost = "Regen cost", + shield_delay = "Regen delay", + shield_nolink = "Does not link with other shields", + vampirism_heals = "Heals self for", + vampirism_perhit = "health per hit", + wolverine_mine = "mine", + altitude_bonus = "Altitude bonus", + stats_damage = "Damage", + stats_duringcloakstrike = "(during cloak strike)", + stats_shielddamage = "Shield damage", + stats_reload = "Reload time", + stats_aimtime = "Aim time", + stats_horizontal_deviation = "Max Horizontal deviation", + stats_vertical_deviation = "Max Vertical Deviation", + stats_exponential_damage_increase = "Increases by", + stats_exponential_damage_capsat = "Caps out at", + stats_ignores_shield = "Ignores shields", + stats_stun_time = "Stun time", + stats_burn_time = "Burn time", + stats_aoe = "Explosion radius", + stats_weapon_speed = "Projectile speed", + stats_force_decloak = "Forces decloak for", + weapon_instant_hit = "Instantly hits", + stats_missile_launch_speed = "Launch speed", + stats_missile_speed = "Max speed", + stats_missile_fuel_time = "Flight Time", + stats_acceleration = "Acceleration", + explodes_on_timeout = "Explodes on timeout", + falls_on_timeout = "Falls down on timeout", + stats_homing = "Guidance Rate", + stats_cruisemissile = "Cruise Missile", + stats_cruisealtitude = "Altitude", + stats_begins_descent = "Begins descent", + stats_from_target = "elmo from target", + stats_tracks_target = "Tracks target", + stats_guided_cruise = "Guided Cruise, unguided descent", + laser_guided = "Laser Guided", + needs_guidance = "(Needs external guidance)", + external_targeter = "Provides External Guidance", + stats_inaccuracy = "Inaccuracy", + stats_wobble = "Flight Instability", + stats_wobble_desc = "up to", + stats_blastwave_only_allies = "Only affects allies", + stats_burst_time = "Burst time", + stats_armor_boost_friendly_only = "Boosts Allied Units' Armor", + stats_armor_boost_all = "Boosts All Units' Armor", + stats_armor_boost = "Armor bonus", + duration = "Duration", + stats_armor_boost_doesnt_diminish_duration = "Duration does not diminish with distance", + stats_armor_boost_doesnt_diminish_effect = "Effect does not diminish with distance", + stats_armor_boost_diminishes = "Effect and duration falloff with distance", + stats_armor_pen = "Ignores Armor", + stats_spawns = "Spawns", + stats_spawn_duration = "Self destructs after", + stats_blastwave = "Creates a blastwave", + stats_blastwave_startsize = "Initial Size", + stats_blastwave_healing_set = "Heals up to", + stats_blastwave_initial_healing = "Initial Healing", + stats_blastwave_initial_damage = "Initial Damage", + stats_overslow_duration = "Saturated Slow", + stats_impulse = "Impulse", + stats_blastwave_expansion_rate = "Expansion rate", + stats_blastwave_power_loss = "Power loss", + stats_blastwave_final_radius = "Final radius", + stats_slows_down_after_firing = "Speed lowers after firing", + weapon_creates_gravity_well = "Creates a gravity well", + weapon_groundfire = "Sets the ground on fire", + weapon_creates_singularity = "Creates a Singularity", + weapon_firing_arc = "Firing Arc", + weapon_grid_demand = "Grid Needed", + grid_link = "Grid Link Range", + grid_needed = "Required Grid Energy", + altitude = "Altitude", + sight_range = "Sight range", + singularity_strength = "Strength", + weapon_arcing = "Arcing shot", + weapon_stockpile_time = "Stockpile time", + weapon_stockpile_cost = "Stockpile cost", + weapon_smooths_ground = "Smoothes ground", + weapon_moves_structures = "Smoothes under structures", + weapon_high_traj = "High Trajectory", + weapon_toggable_traj = "Toggable Trajectory", + weapon_water_capable = "Water capable", + weapon_potential_friendly_fire = "Potential Friendly Fire", + weapon_no_ground_collide = "Passes through ground", + weapon_increased_damage_vs_large = "Damage increase vs large units", + weapon_damage_falloff = "Damage falls off with range", + weapon_damage_closeup_falloff = "Damage increases with range", + weapon_no_friendly_fire = "No friendly fire", + weapon_piercing = "Piercing", + weapon_shield_drain = "Costs shield to fire:", + weapon_shield_drain_desc = "charge per shot", + weapon_aim_delay = "Aiming delay", + weapon_inaccuracy_vs_moving = "Inaccurate against moving targets", + weapon_interceptable = "Can be shot down by antinukes", + weapon_cluster_munitions = "Cluster Submunitions", + weapon_cluster_ttr = "Time-To-Release", + spooling_weapon = "Spooling Weapon", + spooling_weapon_bonus = "Bonus reload speed per shot", + spooling_max_bonus = "Maximum firerate bonus", + spooling_bonus_time_to_max = "Time Until Max Firerate", + construction = "Construction", + starting_buildpower = "Starting buildpower", + buildpower_increases_use = "Buildpower increases with use", + max_buildpower = "Maximum buildpower", + buildpower_diminishes_with_disuse = "Buildpower decreases after disuse", + decay_rate = "Decay rate", + base_buildpower = "Base Buildpower", + recharge_delay = "Recharge delay", + buildpower_regen_rate = "Regeneration rate", + can_resurrect = "Can resurrect wreckage", + only_assists = "Can only assist", + vampirism = "Vampirism", + vampirism_kills_increase_hp = "Increases max with kills", + armored_unit = "Hardened Armor", + armor_reduction = "Damage Reduction", + armor_type_1 = "Applies while closed", + armor_type_2 = "Applies while stopped", + forced_closed = "Forcefully closed on damage", + area_cloak = "Area cloak", + upkeep = "Upkeep", + recon_pulse = "Recon Pulse", + recon_pulse_desc = "Jams enemy cloaking. Range: 500", + recon_pulse_applied = "Pings every 2 seconds", + personal_cloak = "Personal Cloak", + upkeep_mobile = "Upkeep while mobile", + upkeep_stationary = "Upkeep while stationary", + decloak_radius = "Decloak Radius", + cloakstrike = "Cloaked Ambush Advantage", + cloakstrike_lose_advantage = "Loses multipler alongside cloak when shooting", + unit_no_decloak_on_fire = "Doesn't lose cloak upon shooting", + only_idle = "Only when idle", + idle_cloak_free = "Free and automated", + cloak_regen = "Regenerates while cloaked", + provides_intel = "Provides intel", + radar = "Radar Range", + jamming = "Radar Stealth Field", + improves_radar = "Improves radar accuracy", + speed = "Speed", + movement = "Movement Type", + climbs = "Maximum Slope Tolerance", + turn_rate = "Turn rate", + metal_income = "Metal Income", + energy_income = "Energy Income", + unit_info = "Unit Info", + mid_air_jump = "Midair jump", + morphing = "Morphing", + morphs_to = "Morphs to", + cost = "Cost", + bp = "Build Rate", + rate = "Rate", + rank_required = "Required Rank", + morph_time = "Time", + not_disabled_morph = "Not disabled during morph", + disabled_morph = "Disabled during morph", + improved_regen = "Improved regeneration", + idle_regen = "Idle Regeneration", + regen_time_to_enable = "Time to enable", + constant_regen = "Combat Regeneration", + nano_regen = "Nanite Reactive Armor", + base_regen = "Base Regeneration", + max_regen = "Max Regeneration", + max_below = "Maximum bonus below", + water_regen = "Water Regeneration", + armor_regen = "Armored Regeneration", + teleporter = "Teleporter", + spawns_beacon = "Spawns a beacon for one-way recall", + spawn_time = "Time to spawn", + at_depth = "At depth", + mass = "Mass", + teleport_throughput = "Throughput", + rearm_repair = "Rearms and repairs aircraft", + rearm_pads = "Pads", + pad_bp = "Pad buildpower", + drone_bound = "Bound to owner", + drone_cannot_direct_control = "Cannot be directly controlled", + drone_uses_owners_commands = "Uses owner's commands", + drone_bound_to_range = "Must stay in range of owner", + drone_dies_on_owner_death = "Will die if owner does", + speed_boost = "Speed boost", + wind_gen = "Generates energy from wind", + wind_variable_income = "Variable income", + max_generation = "Maximum Generation", + wind_100_height = "Energy per 100 height", + grey_goo = "Grey Goo", + grey_goo_consumption = "Uses nearby wreckage for replication", + jump = "Jumping", + dangerous_reclaim = "Explodes when attempting to reclaim", + floats = "Floating", + can_move_to_surface = "Can move from seabed to surface", + cannot_move_sideways = "Cannot move sideways while afloat", + sinks_when_stun = "Sinks when stunned", + float_when_stun = "Stays afloat when stunned", + transportation = "Transports Units", + transport_type = "Transport Type", + transport_light = "Light", + transport_heavy = "Heavy", + transport_light_speed = "Loaded Speed", + transport_heavy_speed = "Heavy Load Speed", + anti_interception = "Can intercept strategic nukes", + combat_slowdown = "Combat slowdown", + radar_invisible = "Invisible to Radar", + instant_selfd = "Instant self-destruction", + requires_geo = "Requires thermal vent to build", + extracts_metal = "Extracts metal", + fireproof = "Fireproof (Immune to burning damage)", + gravitronic_regulation = "Gravitronic Regulation (Immune to impulse)", + storage = "Stores Resources", + shared_to_team = "Shares metal extraction to team", + free = "Free", + movetype_immobile = "Immobile", + movetype_plane = "Aircraft", + movetype_gunship = "Gunship", + movetype_sub = "Submarine", + movetype_waterwalker = "Swimming", + movetype_hover = "Hovercraft", + movetype_amph = "Amphibious", + movetype_spider = "All-terrain", + movetype_bot = "Bot", + movetype_veh = "Vehicle", + movetype_ship = "Ship", + level = "Level", + chassis = "Chassis", + modules = "MODULES", + death_explosion = "Death Explosion", + builds = "BUILDS", + weapons = "WEAPONS", + abilities = "ABILITIES", + stats = "STATS", + time_to_reach = "Time to reach", + speed_while_reloading = "Movement speed while reloading", + drone_max_range = "Drone Max Range", + drone_target_range = "Drone Acqusition Range", + drone_controllable = "Controllable", + drone_verybigrange = "Infinite max range", + drone_autofabs = "Drone autofabs", + drone_production_speed = "Drone Build Speed", + can_be_transported = "Transportable", + min_output = "Minimum Output", + max_output = "Maximum Output", + output_compounds = "Output increases over time", + output_decays = "Output decays over time", + cloaked_speed = "Cloaked Speed", + decloaked_speed = "Decloaked Speed", + pull = "pull", + push = "push", + radius = "Radius", + stats_range = "Range", + regen = "Regeneration", + acronyms_hp = "hp", + acronyms_second = "sec", + acronyms_dps = "DPS", + acronyms_agl = "AGL", + acronyms_emp = "EMP", + acronyms_slow = "S", + acronyms_disarm = "D", + acronyms_capture = "C", + alliance = "Team", + team = "Squad", + yes = "Yes", + no = "No", + drone_carrier = "Drone carrier", + drone_buildslots = "Number of Autofabs", + cooldown = "Cooldown", + drone_label = "Drone Complement", + drones_per_cycle = "Drones started per cycle", + drone_build_time = "Build time", + chainlightning = "Forks to nearby units:", + chainlightning_jumps = "Jumps to", + chainlightning_efficency = "Effiency:", + chainlightning_extrajumps = "Forks jump to nearby units", + field_fac = "field factory", + disrupts_shields = "Disrupts shields" +} + +local function UpdateLocalization() + for k, _ in pairs(localization) do + localization[k] = WG.Translate ("interface", k) + end + for k, _ in pairs(localizationCommon) do + localizationCommon[k] = WG.Translate("interface", k) + end +end + local alreadyAdded = {} local function addUnit (unitDefID, path, buildable) @@ -257,11 +571,11 @@ end local function AddFactoryOfUnits(defName) local ud = UnitDefNames[defName] - local name = "Units/" .. string.gsub(ud.humanName, "/", "-") + local name = "Units/" .. string.gsub(ud.humanName, "/", "-") addUnit(ud.id, "Buildings/Factory", true) for i = 1, #ud.buildOptions do addUnit(ud.buildOptions[i], name, true) - end + end end AddFactoryOfUnits("factoryshield") @@ -297,7 +611,6 @@ addUnit(UnitDefNames["energyheavygeo"].id, "Buildings/Economy", true) -- moho ge addUnit(UnitDefNames["athena"].id, "Units/Misc", true) -- athena addUnit(UnitDefNames["wolverine_mine"].id, "Units/Misc", false) -- maybe should go under LV fac, like wolverine? to consider. addUnit(UnitDefNames["tele_beacon"].id, "Units/Misc", false) -addUnit(UnitDefNames["asteroid"].id, "Units/Misc", false) local lobbyIDs = {} -- stores peoples names by lobbyID to match commanders to owners @@ -330,7 +643,7 @@ for i = 1, #UnitDefs do elseif ud.name:lower():find('chicken') and Spring.GetGameRulesParam("difficulty") then -- fixme: not all of these are actually used addUnit(i,"Misc/Chickens", false) elseif ud.customParams.is_drone then - addUnit(i,"Units/Misc", false) + addUnit(i,"Units/Misc/Drones", false) end end end @@ -410,7 +723,7 @@ end local function CloseButton(width) return Button:New{ - caption = 'Close', + caption = localization.menu_close, OnClick = { CloseButtonFunc }, width=width, height = B_HEIGHT, @@ -459,858 +772,1110 @@ local function GetShieldRegenDrain(wd) return shieldRegen, shieldDrain end -local function weapons2Table(cells, ws, unitID) +local function AddEntryToCells(text, layer, entry, cells) + if layer > 0 then + text = string.rep("\t\t", layer) .. text + end + cells[#cells + 1] = text + if entry == nil then + cells[#cells + 1] = '' + else + cells[#cells + 1] = entry + end +end + +local function weapons2Table(cells, ws, unitID, bombletCount, recursedWepIds, deathExplosion, cost, isFeature, layer, index) + local isCommander + if unitID then + if isFeature then + isCommander = Spring.GetFeatureRulesParam(unitID, "comm_weapon_num_1") ~= nil + else + isCommander = Spring.GetUnitRulesParam(unitID, "comm_weapon_num_1") ~= nil + end + Spring.Echo("IsCommander: " .. tostring(isCommander)) + end + --Spring.Echo("Index: " .. tostring(index)) local cells = cells - - local wd = WeaponDefs[ws.weaponID] + local startPoint = #cells+1 + if layer == nil then layer = 0 end + local wd + if bombletCount then + wd = WeaponDefNames[ws] --GetWeapon for some reason doesn't work + else + wd = WeaponDefs[ws.weaponID] + end + local recursedWepIds = recursedWepIds + recursedWepIds[#recursedWepIds+1] = wd.name local cp = wd.customParams or emptyTable - + local comm_mult + if isFeature then + comm_mult = (unitID and Spring.GetFeatureRulesParam(unitID, "comm_damage_mult")) or 1 + else + comm_mult = (unitID and Spring.GetUnitRulesParam(unitID, "comm_damage_mult")) or 1 + end local name = wd.description or "Weapon" - if ws.count > 1 then + if bombletCount then + if not deathExplosion then + name = name .. " x " .. math.floor(bombletCount * comm_mult) + end + elseif ws.count > 1 then name = name .. " x " .. ws.count end - if wd.type == "TorpedoLauncher" then - name = name .. " (water only)" + name = name .. " " .. localization.target_water_only end - - if wd.manualFire or cp.ui_manual_fire then - name = name .. " (manual fire)" + if wd.manualFire then + name = name .. " " .. localization.target_manual_fire end - - if ws.aa_only then - name = name .. " (anti-air only)" + if not bombletCount and ws.aa_only then + name = name .. " " .. localization.target_antiair + end + if cp.targeter then + name = name .. " " .. localization.target_guidance + end + if not (cp.bogus or cp.hideweapon) then + AddEntryToCells(name, layer, nil, cells) end - - cells[#cells+1] = name - cells[#cells+1] = '' - if wd.isShield then local regen, drain = GetShieldRegenDrain(wd) - cells[#cells+1] = ' - Strength:' - cells[#cells+1] = numformat(wd.shieldPower * (unitID and Spring.GetUnitRulesParam(unitID, "totalShieldMaxMult") or 1)) .. " HP" - cells[#cells+1] = ' - Regen:' - cells[#cells+1] = regen .. " HP/s" - if wd.customParams.shield_rate_charge then - cells[#cells+1] = ' - Regen change:' - cells[#cells+1] = numformat(wd.customParams.shield_rate_charge * (unitID and Spring.GetUnitRulesParam(unitID, "totalStaticShieldRegen") or 1)) .. " HP/s²" - end - cells[#cells+1] = ' - Regen cost:' - cells[#cells+1] = drain .. " E/s" - local rechargeDelay = wd.shieldrechargedelay or wd.customParams.shield_recharge_delay + AddEntryToCells(localization.shield_hp .. ":", layer + 1, wd.shieldPower .. " " .. localization.acronyms_hp, cells) + AddEntryToCells(localization.shield_percost .. ":", layer + 1, numformat(wd.shieldPower / cost, 2), cells) + AddEntryToCells(localization.regen .. ":", layer + 1, regen .. localization.acronyms_hp .. "/" .. localization.acronyms_second, cells) + AddEntryToCells(localization.shield_regencost .. ":", layer + 1, drain .. " " .. localizationCommon.energy .. "/" .. localization.acronyms_second, cells) + local rechargeDelay = tonumber(wd.shieldrechargedelay or wd.customParams.shield_recharge_delay) if rechargeDelay and rechargeDelay > 0 then - cells[#cells+1] = ' - Regen delay:' - cells[#cells+1] = numformat(rechargeDelay) .. " s" + AddEntryToCells(localization.shield_delay .. ":", layer + 1, rechargeDelay .. " " .. localization.acronyms_second, cells) end - cells[#cells+1] = ' - Radius:' - cells[#cells+1] = numformat(wd.shieldRadius) .. " elmo" + AddEntryToCells(localization.radius .. ':', layer + 1, wd.shieldRadius .. " elmo", cells) if wd.customParams.unlinked then - cells[#cells+1] = ' - Does not link with other shields' - cells[#cells+1] = '' + AddEntryToCells(localization.shield_nolink, layer + 1, nil, cells) end else -- calculate damages - - local dam = 0 - local damw = 0 - local dams = 0 - local damd = 0 - local damc = 0 - - local stun_time = 0 - - local comm_mult = (unitID and Spring.GetUnitRulesParam(unitID, "comm_damage_mult")) or 1 - local baseDamage = tonumber(cp.stats_damage) or wd.customParams.shield_damage or 0 - local val = baseDamage * comm_mult - - if cp.disarmdamagemult then - damd = val * cp.disarmdamagemult - if (cp.disarmdamageonly == "1") then - val = 0 + if not (cp.bogus or cp.hideweapon) then + local dam = 0 + local damw = 0 + local dams = 0 + local damd = 0 + local damc = 0 + local stun_time = 0 + local baseDamage = tonumber(cp.stats_damage) or wd.customParams.shield_damage or 0 + if unitID and index then + if isFeature then + comm_mult = Spring.GetFeatureRulesParam(unitID, index .. "_actual_dmgboost") or comm_mult + else + comm_mult = Spring.GetUnitRulesParam(unitID, index .. "_actual_dmgboost") or comm_mult + end end - stun_time = tonumber(cp.disarmtimer) - end - - if cp.timeslow_damagefactor or cp.timeslow_onlyslow then - dams = val * (cp.timeslow_damagefactor or 1) - if (cp.timeslow_onlyslow == "1") then + local val = baseDamage * comm_mult + if cp.disarmdamagemult then + damd = val * cp.disarmdamagemult + if (cp.disarmdamageonly == "1") then + val = 0 + end + stun_time = tonumber(cp.disarmtimer) + end + if cp.timeslow_damagefactor then + dams = val * cp.timeslow_damagefactor + if (cp.timeslow_onlyslow == "1") then + val = 0 + end + end + if cp.is_capture then + damc = val val = 0 end - end - - if cp.is_capture then - damc = val - val = 0 - end - - if cp.extra_damage then - damw = tonumber(cp.extra_damage) * comm_mult - stun_time = tonumber(wd.customParams.extra_paratime) - end - - if wd.paralyzer then - damw = val - if stun_time == 0 then - stun_time = wd.damages.paralyzeDamageTime + if cp.extra_damage then + damw = tonumber(cp.extra_damage) * comm_mult + stun_time = tonumber(wd.customParams.extra_paratime) end - else - dam = val - end - - -- get reloadtime and calculate dps - local reloadtime = tonumber(cp.script_reload) or wd.reload - - local dps = math.floor(dam /reloadtime + 0.5) - local dpsw = math.floor(damw/reloadtime + 0.5) - local dpss = math.floor(dams/reloadtime + 0.5) - local dpsd = math.floor(damd/reloadtime + 0.5) - local dpsc = math.floor(damc/reloadtime + 0.5) - if cp.stats_typical_damage then - dps = math.floor(tonumber(cp.stats_typical_damage) * comm_mult /reloadtime + 0.5) - end - - local mult = tonumber(cp.statsprojectiles) or ((tonumber(cp.script_burst) or wd.salvoSize) * wd.projectiles) - mult = mult * (unitID and Spring.GetUnitRulesParam(unitID, "projectilesMult") or 1) - - local dps_str, dam_str, shield_dam_str = '', '', '' - local damageTypes = 0 - if dps > 0 then - dam_str = dam_str .. numformat(dam) - shield_dam_str = shield_dam_str .. numformat(dam) - if cp.stats_damage_per_second then - dps_str = dps_str .. numformat(tonumber(cp.stats_damage_per_second)) + if wd.paralyzer then + damw = val + if stun_time == 0 then + stun_time = wd.damages.paralyzeDamageTime + end else - dps_str = dps_str .. numformat(dps*mult) + dam = val end - damageTypes = damageTypes + 1 - end - if dpsw > 0 then - if dps_str ~= '' then - dps_str = dps_str .. ' + ' - dam_str = dam_str .. ' + ' - shield_dam_str = shield_dam_str .. ' + ' + if cp.vampirism then + AddEntryToCells(localization.vampirism_heals, layer + 1, numformat(tonumber(cp.vampirism) * dam, 1) .. ' ' .. localization.vampirism_perhit, cells) end - dam_str = dam_str .. color2incolor(colorCyan) .. numformat(damw) .. " (P)\008" - shield_dam_str = shield_dam_str .. color2incolor(colorCyan) .. numformat(math.floor(damw / 3)) .. " (P)\008" - dps_str = dps_str .. color2incolor(colorCyan) .. numformat(dpsw*mult) .. " (P)\008" - damageTypes = damageTypes + 1 - end - if dpss > 0 then - if dps_str ~= '' then - dps_str = dps_str .. ' + ' - dam_str = dam_str .. ' + ' - shield_dam_str = shield_dam_str .. ' + ' + -- get reloadtime and calculate dps + local reloadtime + if unitID and index then + if isFeature and Spring.GetFeatureRulesParam(unitID, "comm_weapon_num_1") ~= nil then + reloadtime = Spring.GetFeatureRulesParam(unitID, index .. "_basereload") or tonumber(cp.script_reload) or wd.reload + elseif not isFeature and Spring.GetUnitRulesParam(unitID, "comm_weapon_num_1") ~= nil then + reloadtime = Spring.GetUnitRulesParam(unitID, index .. "_basereload") or tonumber(cp.script_reload) or wd.reload + else + reloadtime = tonumber(cp.script_reload) or wd.reload + end + else + reloadtime = tonumber(cp.script_reload) or wd.reload end - dam_str = dam_str .. color2incolor(colorPurple) .. numformat(dams) .. " (S)\008" - shield_dam_str = shield_dam_str .. color2incolor(colorPurple) .. numformat(math.floor(dams / 3)) .. " (S)\008" - dps_str = dps_str .. color2incolor(colorPurple) .. numformat(dpss*mult) .. " (S)\008" - damageTypes = damageTypes + 1 - end - - if dpsd > 0 then - if dps_str ~= '' then - dps_str = dps_str .. ' + ' - dam_str = dam_str .. ' + ' - shield_dam_str = shield_dam_str .. ' + ' + local maxReload = reloadtime + local wantsExtraReloadInfo = false + if cp.recycler then + local maxbonus = tonumber(cp.recycle_maxbonus) -- recycle_reductiontime, recycle_reduction, recycle_reductionframes, recycle_maxbonus, recycle_bonus + maxReload = math.ceil((reloadtime / (1 + maxbonus)) * 30) / 30 + AddEntryToCells(localization.spooling_weapon .. ":", layer + 1, nil, cells) + local bonusReloadSpeed = tonumber(cp.recycle_bonus) + AddEntryToCells(localization.spooling_weapon_bonus .. ":", layer + 2, numformat(bonusReloadSpeed * 100, 1) .. '%', cells) + AddEntryToCells(localization.spooling_max_bonus .. ":", layer + 2, numformat(maxbonus * 100, 2) .. "%", cells) + local currentFireRate = reloadtime + local currentBonus = 0 + local totalFrames = 0 + local currentreload = math.ceil(reloadtime * 30) + while currentBonus < maxbonus do + totalFrames = totalFrames + currentreload + currentBonus = math.min(currentBonus + bonusReloadSpeed, maxbonus) + currentreload = math.ceil(reloadtime / (1 + currentBonus)) + end + totalFrames = totalFrames / 30 -- frames -> seconds + AddEntryToCells(localization.spooling_bonus_time_to_max .. ":", layer + 2, numformat(totalFrames, 2) .. localization.acronyms_second, cells) end - dam_str = dam_str .. color2incolor(colorDisarm) .. numformat(damd) .. " (D)\008" - shield_dam_str = shield_dam_str .. color2incolor(colorDisarm) .. numformat(math.floor(damd / 3)) .. " (D)\008" - dps_str = dps_str .. color2incolor(colorDisarm) .. numformat(dpsd*mult) .. " (D)\008" - damageTypes = damageTypes + 1 - end - - if dpsc > 0 then - if dps_str ~= '' then - dps_str = dps_str .. ' + ' - dam_str = dam_str .. ' + ' - shield_dam_str = shield_dam_str .. ' + ' + if maxReload ~= reloadtime then + wantsExtraReloadInfo = true end - dam_str = dam_str .. color2incolor(colorCapture) .. numformat(damc) .. " (C)\008" - shield_dam_str = shield_dam_str .. color2incolor(colorCapture) .. numformat(damc) .. " (C)\008" - dps_str = dps_str .. color2incolor(colorCapture) .. numformat(dpsc*mult) .. " (C)\008" - damageTypes = damageTypes + 1 - end - - if mult > 1 then - dam_str = dam_str .. " x " .. mult - shield_dam_str = shield_dam_str .. " x " .. mult - end - if cp.shield_mult then - shield_dam_str = shield_dam_str .. " x " .. math.floor(100*cp.shield_mult) .. '%' - end - - local show_damage = not cp.stats_hide_damage - local show_dps = not cp.stats_hide_dps - local show_reload = not cp.stats_hide_reload - local show_range = not cp.stats_hide_range - local show_aoe = not cp.stats_hide_aoe - - local hitscan = { - BeamLaser = true, - LightningCannon = true, - } - local show_projectile_speed = not cp.stats_hide_projectile_speed and not hitscan[wd.type] - - if ((dps + dpsw + dpss + dpsd + dpsc) < 2) then -- no damage: newtons and such - show_damage = false - show_dps = false - end - - if cp.damage_vs_shield and cp.spawns_name then -- Badger - dam_str = tostring(cp.damage_vs_shield) .. " (" .. dam .. " + " .. (tonumber(cp.damage_vs_shield)-dam) .. " mine)" - dps_str = numformat(math.floor(tonumber(cp.damage_vs_shield)/reloadtime)) - end - - if cp.stats_typical_damage then - cells[#cells+1] = ' - Typical Damage:' - cells[#cells+1] = numformat(math.floor(tonumber(cp.stats_typical_damage) * comm_mult)) - if cp.thermite_frames then - cells[#cells+1] = ' - Lingers when blocked by obstacles' - cells[#cells+1] = '' - cells[#cells+1] = ' - Projectile life:' - cells[#cells+1] = numformat(tonumber(cp.thermite_frames)/30) .. "s" - if cp.thermite_dps_end then - cells[#cells+1] = ' - Damage increases over time' - cells[#cells+1] = '' - cells[#cells+1] = ' - Initial damage:' - cells[#cells+1] = numformat(tonumber(cp.thermite_dps_start)) .. " HP/s" - cells[#cells+1] = ' - Final damage:' - cells[#cells+1] = numformat(tonumber(cp.thermite_dps_end)) .. " HP/s" - end - elseif wd.noExplode or cp.pretend_no_explode then - cells[#cells+1] = ' - Continual damage while piercing' - cells[#cells+1] = '' - end - end - - if cp.noexplode_speed_damage then - dam_str = dam_str .. " per touch" - end - if show_damage then - cells[#cells+1] = ' - Damage:' - cells[#cells+1] = dam_str - end - - -- shield damage - if (wd.interceptedByShieldType ~= 0) and show_damage and not cp.stats_hide_shield_damage then - if cp.damage_vs_shield then - cells[#cells+1] = ' - Shield damage:' - cells[#cells+1] = numformat(cp.stats_shield_damage) - elseif tonumber(cp.stats_shield_damage) ~= baseDamage then - cells[#cells+1] = ' - Shield damage:' - if damageTypes > 1 or mult > 1 then - cells[#cells+1] = numformat(math.floor(cp.stats_shield_damage * mult * comm_mult)) .. " (" .. shield_dam_str .. ")" + local aimtime = (tonumber(cp.aimdelay) or 0) / 30 + local fixedreload = reloadtime + aimtime + local projectiles + local bursts + if unitID and index and isCommander then + if isFeature then + projectiles = Spring.GetFeatureRulesParam(unitID, index .. "_projectilecount_override") or tonumber(cp.statsprojectiles) or wd.projectiles + bursts = Spring.GetFeatureRulesParam(unitID, index .. "_updatedburst_count") or (tonumber(cp.script_burst) or wd.salvoSize) else - cells[#cells+1] = numformat(math.floor(cp.stats_shield_damage * mult * comm_mult)) + local projectileRules = Spring.GetUnitRulesParam(unitID, index .. "_projectilecount_override") + local burstRules = Spring.GetUnitRulesParam(unitID, index .. "_updatedburst_count") + --Spring.Echo("Projectile count: " .. tostring(projectileRules)) + --Spring.Echo("Bursts: " .. tostring(burstRules)) + projectiles = projectileRules or tonumber(cp.statsprojectiles) or wd.projectiles + bursts = burstRules or (tonumber(cp.script_burst) or wd.salvoSize) end - end - end - - if cp.post_capture_reload then - cells[#cells+1] = ' - Reloadtime:' - cells[#cells+1] = numformat (tonumber(cp.post_capture_reload)/30) .. 's' - elseif cp.reammoseconds then - cells[#cells+1] = ' - Must rearm after shot' - cells[#cells+1] = '' - cells[#cells+1] = ' - Rearm time:' - cells[#cells+1] = cp.reammoseconds .. 's' - show_dps = false - elseif show_reload then - cells[#cells+1] = ' - Reloadtime:' - cells[#cells+1] = numformat (reloadtime) .. 's' - end - if show_dps then - cells[#cells+1] = ' - DPS:' - cells[#cells+1] = dps_str - end - - if (wd.interceptedByShieldType == 0) then - cells[#cells+1] = ' - Ignores shields' - cells[#cells+1] = '' - end - - if stun_time > 0 then - cells[#cells+1] = ' - Max stun time:' - cells[#cells+1] = color2incolor((damw > 0) and colorCyan or colorDisarm) .. numformat(stun_time) .. 's\008' - end - - if cp.setunitsonfire then - cells[#cells+1] = ' - Afterburn:' - local afterburn_frames = (cp.burntime or (450 * (wd.fireStarter or 0))) - cells[#cells+1] = color2incolor(colorFire) .. numformat(afterburn_frames/30) .. 's (15 DPS)\008' - end - - if show_range then - local range = cp.truerange or wd.range - local mult = unitID and ((Spring.GetUnitRulesParam(unitID, "comm_range_mult") or 1) * (Spring.GetUnitRulesParam(unitID, "rangeMult") or 1)) or 1 - cells[#cells+1] = ' - Range:' - cells[#cells+1] = numformat(range * mult) .. " elmo" - end - - local aoe = wd.impactOnly and 0 or wd.damageAreaOfEffect - if (aoe > 15 and show_aoe) or cp.stats_aoe then - cells[#cells+1] = ' - AoE radius:' - cells[#cells+1] = numformat(cp.stats_aoe or aoe) .. " elmo" - end - - if show_projectile_speed then - cells[#cells+1] = ' - Projectile speed:' - cells[#cells+1] = numformat(wd.projectilespeed * 30 * ((unitID and Spring.GetUnitRulesParam(unitID, "projectileSpeedMult")) or 1)) .. " elmo/s" - elseif hitscan[wd.type] then - cells[#cells+1] = ' - Instantly hits' - cells[#cells+1] = '' - end - - --[[ Unimportant stuff, maybe make togglable with some option later - if (wd.type == "MissileLauncher") then - if ((wd.startvelocity < wd.projectilespeed) and (wd.weaponAcceleration > 0)) then - cells[#cells+1] = ' - Missile speed:' - cells[#cells+1] = numformat(wd.startvelocity*30) .. " - " .. numformat(wd.projectilespeed*30) .. " elmo/s" - cells[#cells+1] = ' - Acceleration:' - cells[#cells+1] = numformat(wd.weaponAcceleration*900) .. " elmo/s^2" else - cells[#cells+1] = ' - Missile speed:' - cells[#cells+1] = numformat(wd.projectilespeed*30) .. " elmo/s" + projectiles = tonumber(cp.statsprojectiles) or wd.projectiles + bursts = (tonumber(cp.script_burst) or wd.salvoSize) end - cells[#cells+1] = ' - Flight time:' - if cp.flighttime then - cells[#cells+1] = numformat(tonumber(cp.flighttime)) .. "s" - else - cells[#cells+1] = numformat(((wd.range / wd.projectilespeed) + (wd.selfExplode and 25 or 0))/32) .. "s" + local mult = bursts * projectiles + local dps = dam /fixedreload + local dpsw = damw/fixedreload + local dpss = dams/fixedreload + local dpsd = damd/fixedreload + local dpsc = damc/fixedreload + local dps_str, dam_str, shield_dam_str = '', '', '' + local damageTypes = 0 + if dps > 0 then + dam_str = dam_str .. numformat(dam,2) + shield_dam_str = shield_dam_str .. numformat(dam,2) + if cp.stats_damage_per_second then + dps_str = dps_str .. numformat(tonumber(cp.stats_damage_per_second),2) + else + dps_str = dps_str .. numformat(dps*mult,2) + end + if wantsExtraReloadInfo then + dps_str = dps_str .. "(" .. numformat(dam/maxReload, 2) .. ")" + end + damageTypes = damageTypes + 1 + end + if dpsw > 0 then + if dps_str ~= '' then + dps_str = dps_str .. ' + ' + dam_str = dam_str .. ' + ' + shield_dam_str = shield_dam_str .. ' + ' + end + dam_str = dam_str .. color2incolor(colorCyan) .. numformat(damw,2) .. " (" .. localization.acronyms_emp .. ")\008" + shield_dam_str = shield_dam_str .. color2incolor(colorCyan) .. numformat(math.floor(damw / 3),2) .. " (" .. localization.acronyms_emp .. ")\008" + dps_str = dps_str .. color2incolor(colorCyan) .. numformat(dpsw*mult,2) .. " (" .. localization.acronyms_emp .. ")\008" + if wantsExtraReloadInfo then + dps_str = dps_str .. "(" .. color2incolor(colorCyan) .. numformat(damw/maxReload, 2) .. "\008)" + end + damageTypes = damageTypes + 1 + end + if dpss > 0 then + if dps_str ~= '' then + dps_str = dps_str .. ' + ' + dam_str = dam_str .. ' + ' + shield_dam_str = shield_dam_str .. ' + ' + end + dam_str = dam_str .. color2incolor(colorPurple) .. numformat(dams,2) .. " (" .. localization.acronyms_slow .. ")\008" + shield_dam_str = shield_dam_str .. color2incolor(colorPurple) .. numformat(math.floor(dams / 3),2) .. " (" .. localization.acronyms_slow .. ")\008" + dps_str = dps_str .. color2incolor(colorPurple) .. numformat(dpss*mult,2) .. " (" .. localization.acronyms_slow .. ")\008" + if wantsExtraReloadInfo then + dps_str = dps_str .. "(" .. color2incolor(colorPurple) .. numformat(dams / maxReload) .. "\008)" + end + damageTypes = damageTypes + 1 + end + if dpsd > 0 then + if dps_str ~= '' then + dps_str = dps_str .. ' + ' + dam_str = dam_str .. ' + ' + shield_dam_str = shield_dam_str .. ' + ' + end + dam_str = dam_str .. color2incolor(colorDisarm) .. numformat(damd,2) .. " (" .. localization.acronyms_disarm .. ")\008" + shield_dam_str = shield_dam_str .. color2incolor(colorDisarm) .. numformat(math.floor(damd / 3),2) .. " (" .. localization.acronyms_disarm .. ")\008" + dps_str = dps_str .. color2incolor(colorDisarm) .. numformat(dpsd*mult,2) .. " (" .. localization.acronyms_disarm .. ")\008" + if wantsExtraReloadInfo then + dps_str = dps_str .. "(" .. color2incolor(colorDisarm) .. numformat(damd / maxReload, 2) .. "\008" + end + damageTypes = damageTypes + 1 + end + if dpsc > 0 then + if dps_str ~= '' then + dps_str = dps_str .. ' + ' + dam_str = dam_str .. ' + ' + shield_dam_str = shield_dam_str .. ' + ' + end + dam_str = dam_str .. color2incolor(colorCapture) .. numformat(damc,2) .. " (" .. localization.acronyms_capture .. ")\008" + shield_dam_str = shield_dam_str .. color2incolor(colorCapture) .. numformat(damc,2) .. " (" .. localization.acronyms_capture .. ")\008" + dps_str = dps_str .. color2incolor(colorCapture) .. numformat(dpsc*mult,2) .. " (" .. localization.acronyms_capture .. ")\008" + if wantsExtraReloadInfo then + dps_str = dps_str .. "(" .. color2incolor(colorCapture) .. numformat(damc / maxReload, 2) .. "\008" + end + damageTypes = damageTypes + 1 + end + if mult > 1 then + dam_str = dam_str .. " x " .. mult + shield_dam_str = shield_dam_str .. " x " .. mult + end + if cp.shield_mult then + shield_dam_str = shield_dam_str .. " x " .. math.floor(100*cp.shield_mult) .. '%' + end + local show_damage = not (cp.stats_hide_damage or cp.norealdamage or cp.puredecloaktime) + local show_dps = not cp.stats_hide_dps + local show_reload = not cp.stats_hide_reload + local show_range = not cp.stats_hide_range + local show_aoe = not cp.stats_hide_aoe + local show_projectile_speed = not cp.stats_hide_projectile_speed and not hitscan[wd.type] + if ((dps + dpsw + dpss + dpsd + dpsc) < 2) then -- no damage: newtons and such + show_damage = false + show_dps = false + end + if cp.damage_vs_shield and cp.spawns_name then -- Badger + dam_str = tostring(cp.damage_vs_shield) .. " (" .. dam .. " + " .. (tonumber(cp.damage_vs_shield)-dam) .. " " .. localization.wolverine_mine .. ")" + dps_str = numformat(math.floor(tonumber(cp.damage_vs_shield)/reloadtime)) + end + if show_damage then + if cp.cloakstrike then + local str1 = localization.stats_damage .. ' ' .. localization.stats_duringcloakstrike .. ':' + --Spring.Echo(tostring(dam_str)) + --Spring.Echo("dam: " .. dam) + local csMult = tonumber(cp.cloakstrike) + local ndmg = dam * csMult + --Spring.Echo("ndmg: " .. ndmg) + local npara = damw * csMult + local nslow = dams * csMult + local ndis = damd * csMult + local ncap = damc * csMult + local newstr = dam_str + newstr = newstr:gsub(numformat(dam, 2), numformat(ndmg, 2)) + if npara then + newstr = newstr:gsub(numformat(damw, 2), numformat(npara, 2)) + end + if nslow then + newstr = newstr:gsub(numformat(dams, 2), numformat(nslow, 2)) + end + if ndis then + newstr = newstr:gsub(numformat(damd, 2), numformat(ndis, 2)) + end + if ncap then + newstr = newstr:gsub(numformat(damc, 2), numformat(ncap, 2)) + end + AddEntryToCells(str1, layer + 1, newstr, cells) + end + AddEntryToCells(localization.stats_damage .. ":", layer + 1, dam_str, cells) + if cp.chainlightning_searchdist then + local targets = cp.chainlightning_maxtargets + local efficency = numformat((tonumber(cp.chainlightning_efficiency) or 0) * 100, 2) .. "%" + AddEntryToCells(localization.chainlightning, layer + 1, nil, cells) + AddEntryToCells(localization.chainlightning_jumps, layer + 1, targets, cells) + AddEntryToCells(localization.chainlightning_efficency, layer + 2, efficency, cells) + AddEntryToCells(localization.stats_range, layer + 2, cp.chainlightning_searchdist, cells) + if cp.chainlightning_extrabounces then + AddEntryToCells(localization.chainlightning_extrajumps, layer + 2, cp.chainlightning_extrabounces, cells) + end + end + end + -- shield damage + if (wd.interceptedByShieldType ~= 0) and show_damage and not cp.stats_hide_shield_damage and not deathExplosion then + if cp.damage_vs_shield then + AddEntryToCells(localization.stats_shielddamage .. ':', layer + 1, numformat(cp.stats_shield_damage), cells) + elseif tonumber(cp.stats_shield_damage) ~= baseDamage then + local str1 = localization.stats_shielddamage .. ':' + if damageTypes > 1 or mult > 1 then + AddEntryToCells(str1, layer + 1, numformat(math.floor(cp.stats_shield_damage * mult * comm_mult), 2) .. "(" .. shield_dam_str .. ")", cells) + else + AddEntryToCells(str1, layer + 1, numformat(math.floor(cp.stats_shield_damage * mult * comm_mult), 2), cells) + end + end + end + if cp.shield_disruption then + AddEntryToCells(localization.disrupts_shields .. ":", layer + 1, numformat(tonumber(cp.shield_disruption) / 30, 1) .. localization.acronyms_second, cells) + end + if cp.post_capture_reload then + AddEntryToCells(localization.stats_reload .. ':', layer + 1, numformat (tonumber(cp.post_capture_reload)/30,2) .. localization.acronyms_second, cells) + elseif show_reload and not bombletCount then + AddEntryToCells(localization.stats_reload .. ':', layer + 1, numformat (reloadtime,2) .. localization.acronyms_second, cells) + end + if aimtime > 0 then + local headingerror = tonumber(cp.allowedheadingerror) or 0.000001 + local pitcherror = tonumber(cp.allowedpitcherror) or 0.01 + AddEntryToCells(localization.stats_aimtime .. ':', layer + 1, numformat(aimtime, 2) .. localization.acronyms_second, cells) + AddEntryToCells(localization.stats_horizontal_deviation .. ':', layer + 2, numformat(headingerror/2, 1) .. "°", cells) + AddEntryToCells(localization.stats_vertical_deviation .. ':', layer + 2, '±' .. numformat(pitcherror/2, 1) .. "°", cells) + end + if show_dps and not bombletCount then + AddEntryToCells(localization.acronyms_dps .. ':', layer + 1, dps_str, cells) + if cp.dmg_scaling then + AddEntryToCells(localization.stats_exponential_damage_increase .. ':', layer + 1, numformat(tonumber(cp.dmg_scaling) * 3000) .. "%/s", cells) -- 3000 = 100 * 30 + local str1 = localization.stats_exponential_damage_capsat .. ':' + if tonumber(cp.dmg_scaling_max) < 10000 then + AddEntryToCells(str1, layer + 2, numformat(tonumber(cp.dmg_scaling_max) * 100) .. "%", cells) + else + AddEntryToCells(str1, layer + 2, "∞%", cells) + end + end + end + if (wd.interceptedByShieldType == 0) then + AddEntryToCells(localization.stats_ignores_shield, layer + 1, '', cells) + end + if stun_time > 0 then + AddEntryToCells(localization.stats_stun_time .. ':', layer + 1, color2incolor((damw > 0) and colorCyan or colorDisarm) .. numformat(stun_time,2) .. 's\008', cells) + end + if cp.setunitsonfire then + local afterburn_frames = (cp.burntime or (450 * (wd.fireStarter or 0))) + AddEntryToCells(localization.stats_burn_time .. ':', layer + 1, color2incolor(colorFire) .. numformat(afterburn_frames/30) .. 's (15' .. localization.acronyms_dps .. ')\008', cells) + end + if cp.sensortag then + local secs = tonumber(cp.sensortag) or 0 + if secs > 0 then + AddEntryToCells(WG.Translate("interface", "sensor_tag", {seconds = numformat(secs, 1)}), layer + 1, '', cells) + end + end + if cp.sensorsteal then + local secs = tonumber(cp.sensorsteal) or 0 + if secs > 0 then + AddEntryToCells(WG.Translate("interface", "sensor_steal", {seconds = numformat(secs, 1)}), layer + 1, '', cells) + end + end + if show_range and not bombletCount then + local range = cp.truerange or wd.range + local rangemult + local baserange + if isFeature then + rangemult = (unitID and Spring.GetFeatureRulesParam(unitID, "comm_range_mult")) or 1 + baserange = (unitID and Spring.GetFeatureRulesParam(unitID, index .. "_range")) or cp.truerange or wd.range + else + rangemult = (unitID and Spring.GetUnitRulesParam(unitID, "comm_range_mult")) or 1 + baserange = (unitID and Spring.GetUnitRulesParam(unitID, index .. "_range")) or cp.truerange or wd.range + end + AddEntryToCells(localization.stats_range .. ':', layer + 1, numformat(baserange * rangemult, 2) .. " elmo", cells) + end + if wd.customParams.puredecloaktime then + AddEntryToCells(localization.stats_force_decloak, layer + 1, numformat(wd.customParams.puredecloaktime / 30, 1) .. localization.acronyms_second, cells) + end + local aoe = wd.impactOnly and 0 or wd.damageAreaOfEffect + if aoe > 15 and show_aoe then + AddEntryToCells(localization.stats_aoe .. ':', layer + 1, numformat(aoe) .. " elmo", cells) + end + if show_projectile_speed and not bombletCount then + local speed + if isCommander and unitID and index then + if isFeature then + speed = Spring.GetFeatureRulesParam(unitID, index .. "_speed") or wd.projectilespeed + else + speed = wd.projectilespeed + end + else + speed = wd.projectilespeed + end + AddEntryToCells(localization.stats_weapon_speed .. ':', layer + 1, numformat(speed*30) .. " elmo/" .. localization.acronyms_second, cells) + elseif hitscan[wd.type] then + AddEntryToCells(localization.weapon_instant_hit, layer + 1, '', cells) + end + --Unimportant stuff, maybe make togglable with some option later + if (wd.type == "MissileLauncher") then + if ((wd.startvelocity < wd.projectilespeed) and (wd.weaponAcceleration > 0)) then + AddEntryToCells(localization.stats_missile_launch_speed .. ':', layer + 1, numformat(wd.startvelocity*30) .. " - " .. numformat(wd.projectilespeed*30) .. " elmo/" .. localization.acronyms_second, cells) + AddEntryToCells(localization.stats_acceleration .. ':', layer + 1, numformat(wd.weaponAcceleration*900) .. " elmo/" .. localization.acronyms_second .. "²", cells) + else + AddEntryToCells(localization.stats_missile_speed .. ':', layer + 1, numformat(wd.projectilespeed*30) .. " elmo/" .. localization.acronyms_second, cells) + end + if cp.flighttime then + AddEntryToCells(localization.stats_missile_fuel_time .. ':', layer + 1, numformat(tonumber(cp.flighttime)) .. localization.acronyms_second, cells) + else + AddEntryToCells(localization.stats_missile_fuel_time .. ':', layer + 1, numformat(((wd.range / wd.projectilespeed) + (wd.selfExplode and 25 or 0))/32) .. localization.acronyms_second, cells) + end + if wd.selfExplode then + AddEntryToCells(localization.explodes_on_timeout, layer + 1, '', cells) + else + AddEntryToCells(localization.falls_on_timeout, layer + 1, '', cells) + end + end + if wd.tracks and wd.turnRate > 0 and (cp.cruisealt == nil or cp.cruisedist == nil) then + local turnrate = wd.turnRate * 30 * 180 / math.pi + AddEntryToCells(localization.stats_homing .. ':', layer + 1, numformat(turnrate, 1) .. " °/" .. localization.acronyms_second, cells) + end + if cp.ballistic_guidance then + AddEntryToCells(localization.stats_homing .. ':', layer + 1, numformat(tonumber(cp.ballistic_guidance), 1) .. " elmos/" .. localization.acronyms_second .. "²", cells) + end + if cp.cruisealt and cp.cruisedist then + AddEntryToCells(localization.stats_cruisemissile .. ':', layer + 1, '', cells) + AddEntryToCells(localization.stats_cruisealtitude .. ':', layer + 2, cp.cruisealt .. ' elmo ' .. localization.acronyms_agl, cells) + AddEntryToCells(localization.stats_begins_descent .. ':', layer + 2, wd.customParams.cruisedist .. ' ' .. localization.stats_from_target, cells) + if cp.cruisetracking and cp.cruise_nolock == nil then + local turnrate = wd.turnRate * 30 * 180 / math.pi + AddEntryToCells(localization.stats_tracks_target .. ':', layer + 2, numformat(turnrate, 1) .. '°/' .. localization.acronyms_second, cells) + end + if cp.cruisetracking and cp.cruise_nolock then + AddEntryToCells(localization.stats_guided_cruise, layer + 2, '', cells) + end + if wd.customParams.cruise_randomizationtype == "circle" then + AddEntryToCells(WG.Translate("interface", "stats_circular_spread", {size = cp.cruiserandomradius}), layer + 2, '', cells) + elseif wd.customParams.cruiserandomradius then + AddEntryToCells(WG.Translate("interface", "stats_cruise_error", {radius = cp.cruiserandomradius}), layer + 2, '', cells) + end + end + if cp.tracker and cp.externaltracker == nil then + AddEntryToCells(localization.laser_guided, layer + 1, '', cells) + elseif cp.tracker then + AddEntryToCells(localization.laser_guided .. " " .. localization.needs_guidance, layer + 1, '', cells) + end + if cp.externaltargeter then + AddEntryToCells(localization.external_targeter, layer + 1, '', cells) + end + if cp.needsuplink then + AddEntryToCells(WG.Translate("interface", "needs_guidance_for_seconds", {seconds = numformat(cp.needsuplink / 30, 2)}) .. " " .. localization.acronyms_second, layer + 1, '', cells) + end + if wd.wobble > 0 then + local wobble = wd.wobble * 30 * 180 / math.pi + AddEntryToCells(localization.stats_wobble .. ':', layer + 1, localization.stats_wobble_desc .. " " .. numformat(wobble, 1) .. "°/" .. localization.acronyms_second, cells) end - if wd.selfExplode then - cells[#cells+1] = " - Explodes on timeout" - else - cells[#cells+1] = " - Falls down on timeout" + if wd.sprayAngle > 0 and not bombletCount then + local sprayangle + if unitID and isCommander then + if isFeature then + sprayangle = Spring.GetFeatureRulesParam(unitID, index .. "_sprayangle") or wd.sprayAngle + else + sprayangle = Spring.GetUnitRulesParam(unitID, index .. "_sprayangle") or wd.sprayAngle + end + else + sprayangle = wd.sprayAngle + end + local accuracy = math.asin(sprayangle) * 90 / math.pi + AddEntryToCells(localization.stats_inaccuracy .. ':', layer + 1, numformat(accuracy, 1) .. "°", cells) end - cells[#cells+1] = '' - end - - if (wd.type == "StarburstLauncher") then - cells[#cells+1] = ' - Vertical rise:' - cells[#cells+1] = numformat(wd.uptime) .. "s" - end - ]] - - if wd.tracks and wd.turnRate > 0 then - cells[#cells+1] = ' - Homing:' - local turnrate = wd.turnRate * 30 * 180 / math.pi - cells[#cells+1] = numformat(turnrate) .. " deg/s" - end - - if wd.wobble > 0 then - cells[#cells+1] = ' - Wobbly:' - local wobble = wd.wobble * 30 * 180 / math.pi - cells[#cells+1] = "up to " .. numformat(wobble) .. " deg/s" - end - - if wd.sprayAngle > 0 then - cells[#cells+1] = ' - Inaccuracy:' - local accuracy = math.asin(wd.sprayAngle) * 90 / math.pi - cells[#cells+1] = numformat(accuracy) .. " deg" - end - - if wd.type == "BeamLaser" and wd.beamtime > 0.2 then - cells[#cells+1] = ' - Burst time:' - cells[#cells+1] = numformat(wd.beamtime) .. "s" - end - - if cp.spawns_name then - cells[#cells+1] = ' - Spawns: ' - cells[#cells+1] = Spring.Utilities.GetHumanName(UnitDefNames[cp.spawns_name]) - if cp.spawns_expire then - cells[#cells+1] = ' - Spawn life: ' - cells[#cells+1] = cp.spawns_expire .. "s" + + if wd.type == "BeamLaser" and wd.beamtime > 0.2 then + AddEntryToCells(localization.stats_burst_time .. ':', layer + 1, numformat(wd.beamtime) .. localization.acronyms_second, cells) end - end - - if cp.reload_move_mod_time then - cells[#cells+1] = ' - Move mult time: ' - cells[#cells+1] = cp.reload_move_mod_time .. "s" - end - - if cp.area_damage then - if (cp.area_damage_is_impulse == "1") then - cells[#cells+1] = ' - Creates a gravity well:' - cells[#cells+1] = '' - elseif (cp.area_damage_is_slow == "1") then - cells[#cells+1] = ' - Lingering slow damage in an area:' - cells[#cells+1] = '' - cells[#cells+1] = ' * DPS:' - cells[#cells+1] = color2incolor(colorPurple) .. cp.area_damage_dps .. " (S)\008" - else - cells[#cells+1] = ' - Sets the ground on fire:' - cells[#cells+1] = '' - cells[#cells+1] = ' * DPS:' - cells[#cells+1] = cp.area_damage_dps + if cp.grants_armor then + local impactsEnemies = cp.affects_enemy ~= nil + local duration = tonumber(cp.armor_duration) + local noScaling = cp.noscaling ~= nil + local noTimeScaling = noScaling or cp.notimescaling ~= nil + if not impactsEnemies then + AddEntryToCells(localization.stats_armor_boost_friendly_only .. ":", layer + 1, '', cells) + else + AddEntryToCells(localization.stats_armor_boost_all .. ":", layer + 1, '', cells) + end + AddEntryToCells(localization.stats_armor_boost .. ":", layer + 2, numformat(tonumber(cp.grants_armor) * 100, 1) .. "%", cells) + AddEntryToCells(localization.duration .. ":", layer + 2, numformat(duration, 1) .. localization.acronyms_second, cells) + if not noScaling and noTimeScaling then + AddEntryToCells(localization.stats_armor_boost_doesnt_diminish_duration, layer + 2, '', cells) + elseif noScaling then + AddEntryToCells(localization.stats_armor_boost_doesnt_diminish_effect, layer + 2, '', cells) + else + AddEntryToCells(localization.stats_armor_boost_diminishes, layer + 2, '', cells) + end end - cells[#cells+1] = ' * Radius:' - cells[#cells+1] = numformat(tonumber(cp.area_damage_radius)) .. " elmo" - cells[#cells+1] = ' * Duration:' - cells[#cells+1] = numformat(tonumber(cp.area_damage_duration)) .. " s" - end - - if wd.trajectoryHeight > 0 then - cells[#cells+1] = ' - Arcing shot:' - cells[#cells+1] = numformat(math.atan(wd.trajectoryHeight) * 180 / math.pi) .. " deg" - end - - if wd.stockpile then - cells[#cells+1] = ' - Stockpile time:' - cells[#cells+1] = (((tonumber(ws.stockpile_time) or 0) > 0) and tonumber(ws.stockpile_time) or wd.stockpileTime) .. 's' - if ((not ws.free_stockpile) and (ws.stockpile_cost or (wd.metalCost > 0))) then - cells[#cells+1] = ' - Stockpile cost:' - cells[#cells+1] = ws.stockpile_cost or wd.metalCost .. " M" + if cp.armorpiercing then + local apValue = tonumber(cp.armorpiercing) or 0 + if apValue ~= 0 then + AddEntryToCells(localization.stats_armor_pen .. ":", layer + 1, numformat(apValue * 100, 1) .. "%", cells) + end + end + if cp.spawns_name then + AddEntryToCells(localization.stats_spawns .. ':', layer + 1, Spring.Utilities.GetHumanName(UnitDefNames[cp.spawns_name]), cells) + if cp.spawns_expire then + AddEntryToCells(localization.stats_spawn_duration .. ':', layer + 1, cp.spawns_expire .. localization.acronyms_second, cells) + end + end + if cp.blastwave_size then + AddEntryToCells(localization.stats_blastwave .. ':', layer + 1, '', cells) + AddEntryToCells(localization.stats_blastwave_startsize .. ':', layer + 2, cp.blastwave_size, cells) + if blastwave_healing then + if cp.blastwave_healing_reduction then + AddEntryToCells(localization.stats_blastwave_healing_set .. ':', layer + 2, blastwave_healing .. ' ' .. localization.acronyms_hp, cells) + else + AddEntryToCells(localization.stats_blastwave_initial_healing .. ':', layer + 2, blastwave_healing, cells) + end + end + local slowdmg = tonumber(cp.blastwave_slowdmg) or 0 * comm_mult + local empdmg = tonumber(cp.blastwave_empdmg) or 0 * comm_mult + local overslow = tonumber(cp.blastwave_overslow) or 0 * comm_mult + local emptime = tonumber(cp.blastwave_emptime) or 0 * comm_mult + local damage = tonumber(cp.blastwave_damage) or 0 * comm_mult + local damagestring = damage .. " " + if empdmg > 0 then + damagestring = damagestring .. color2incolor(colorCyan) .. empdmg .. "( " .. emptime .. localization.acronyms_second .. ")\008 " + end + if slowdmg > 0 then + damagestring = damagestring .. color2incolor(colorPurple) ..slowdmg .. "\008 " + end + AddEntryToCells(localization.stats_blastwave_initial_damage .. ':', layer + 2, damagestring, cells) + if overslow > 0 then + AddEntryToCells(localization.stats_overslow_duration .. ":", layer + 2, numformat(overslow / 30, 3) .. localization.acronyms_second, cells) + end + if cp.blastwave_onlyfriendly then + AddEntryToCells(localization.stats_blastwave_only_allies, layer + 2, '', cells) + end + local speed = tonumber(cp.blastwave_speed) or 0 + local size = tonumber(cp.blastwave_size) or 0 + local life = tonumber(cp.blastwave_life) or 1 + local impulse = tonumber(cp.blastwave_impulse) or 0 + if impulse > 0 then + AddEntryToCells(localization.stats_impulse .. ':', layer + 2, numformat(impulse, 3), cells) + end + --AddEntryToCells(localization.stats_impulse ..':', layer + 2, size .. " elmos", cells) -- seems to be repeat info + AddEntryToCells(localization.stats_blastwave_expansion_rate .. ':', layer + 2, numformat(speed * 30, 2) .. " elmo/" .. localization.acronyms_second, cells) + AddEntryToCells(localization.stats_blastwave_power_loss .. ':', layer + 2, numformat((1 - (tonumber(cp.blastwave_lossfactor) or 0.95)) * 100, 2) .. "%/frame", cells) + AddEntryToCells(localization.duration .. ":", layer + 2, numformat(life / 30, 3) .. localization.acronyms_second, cells) + AddEntryToCells(localization.stats_blastwave_final_radius .. ':', layer + 2, numformat(size + (speed * life), 2) .. " elmos", cells) + end + + if cp.reload_move_mod_time and not bombletCount then + AddEntryToCells(localization.stats_slows_down_after_firing .. ':', layer + 1, cp.reload_move_mod_time .. localization.acronyms_second, cells) + end + if cp.area_damage then + if (cp.area_damage_is_impulse == "1") then + AddEntryToCells(localization.weapon_creates_gravity_well .. ":", layer + 1, '', cells) + else + AddEntryToCells(localization.weapon_groundfire .. ':', layer + 1, '', cells) + AddEntryToCells(localization.acronyms_dps .. ":", layer + 2, cp.area_damage_dps, cells) + end + AddEntryToCells(localization.radius .. ':', layer + 2, numformat(tonumber(cp.area_damage_radius)) .. " elmo", cells) + AddEntryToCells(localization.duration .. ':', layer + 2, numformat(tonumber(cp.area_damage_duration)) .. " " .. localization.acronyms_second, cells) + end + if cp.singularity then + AddEntryToCells(localization.weapon_creates_singularity, layer + 1, '', cells) + AddEntryToCells(localization.duration .. ":", layer + 2, numformat(cp.singu_lifespan/30, 1) .. localization.acronyms_second, cells) + local singustrength = tonumber(cp.singu_strength) * comm_mult + if singustrength > 0 then + AddEntryToCells(localization.singularity_strength .. ":", layer + 2, numformat(singustrength, 1) .. "elmo/" .. localization.acronyms_second .. localization.pull, cells) + else + AddEntryToCells(localization.singularity_strength .. ":", layer + 2, numformat(singustrength, 1) .. "elmo/" .. localization.acronyms_second .. localization.push, cells) + end + AddEntryToCells(localization.radius .. ':', layer + 2, cp.singu_radius .. " elmo", cells) + end + if wd.trajectoryHeight > 0 and not bombletCount then + AddEntryToCells(localization.weapon_arcing .. ':', layer + 1, numformat(math.atan(wd.trajectoryHeight) * 180 / math.pi) .. "°", cells) + end + + if not bombletCount and wd.stockpile then + AddEntryToCells(localization.weapon_stockpile_time ..':', layer + 1, (((tonumber(ws.stockpile_time) or 0) > 0) and tonumber(ws.stockpile_time) or wd.stockpileTime) .. localization.acronyms_second, cells) + if ((not ws.free_stockpile) and (ws.stockpile_cost or (wd.metalCost > 0))) then + AddEntryToCells(localization.weapon_stockpile_cost .. ':', layer + 1, ws.stockpile_cost or wd.metalCost .. " " .. localizationCommon.metal, cells) + end + end + + if not bombletCount and ws.firing_arc and (ws.firing_arc > -1) then + AddEntryToCells(localization.weapon_firing_arc .. ':', layer + 1, numformat(360*math.acos(ws.firing_arc)/math.pi) .. '°', cells) + end + + if cp.needs_link then + AddEntryToCells(localization.weapon_grid_demand .. ':', layer + 1, tonumber(cp.needs_link) .. " " .. localizationCommon.energy, cells) + end + + if cp.smoothradius then + AddEntryToCells(localization.weapon_smooths_ground, layer + 1, '', cells) + end + if cp["reveal_unit"] then + local artyrevealstring = WG.Translate("interface", "weapon_arty_reveal", {time = cp["reveal_unit"]}) + AddEntryToCells(artyrevealstring, layer + 1, '', cells) + end + if cp.movestructures then + AddEntryToCells(localization.weapon_moves_structures, layer + 1, '', cells) + end + + if not bombletCount then + local highTraj = wd.highTrajectory + if highTraj == 2 then + highTraj = ws.highTrajectory + end + if highTraj == 1 then + AddEntryToCells(localization.weapon_high_traj, layer + 1, '', cells) + elseif highTraj == 2 then + AddEntryToCells(localization.weapon_toggable_traj, layer + 1, '', cells) + end + end + + if wd.waterWeapon and (wd.type ~= "TorpedoLauncher") then + AddEntryToCells(localization.weapon_water_capable, layer + 1, '', cells) + end + + if not wd.avoidFriendly and not wd.noFriendlyCollide then + AddEntryToCells(localization.weapon_potential_friendly_fire, layer + 1, '', cells) + end + + if wd.noGroundCollide then + AddEntryToCells(localization.weapon_no_ground_collide, layer + 1, '', cells) + end + + if wd.noExplode then + AddEntryToCells(localization.weapon_piercing, layer + 1, '', cells) + if not (cp.single_hit or cp.single_hit_multi) then + AddEntryToCells(localization.weapon_increased_damage_vs_large, layer + 1, '', cells) + end + end + + if cp.dyndamageexp then + if wd.dynDamageInverted then + AddEntryToCells(localization.weapon_damage_closeup_falloff, layer + 1, '', cells) + else + AddEntryToCells(localization.weapon_damage_falloff, layer + 1, '', cells) + end + end + + if cp.nofriendlyfire then + AddEntryToCells(localization.weapon_no_friendly_fire, layer + 1, '', cells) + end + + if not bombletCount and cp.shield_drain then + AddEntryToCells(localization.weapon_shield_drain .. ":", layer + 1, cp.shield_drain .. " " .. localization.weapon_shield_drain_desc, cells) + end + + if not bombletCount and cp.aim_delay then + AddEntryToCells(localization.weapon_aim_delay .. ':', layer + 1, numformat(tonumber(cp.aim_delay)/1000) .. localization.acronyms_second, cells) + end + + if not bombletCount and wd.targetMoveError > 0 then + AddEntryToCells(localization.weapon_inaccuracy_vs_moving, layer + 1, '', cells) + end + if cp.stats_custom_tooltip_1 then + local q = 1 + local txt = "" + local desc = "" + local key + while cp["stats_custom_tooltip_" .. q] do + key = "stats_custom_tooltip_" .. q + if string.find(key, "_contextmenu_") then -- try to translate this. + key = string.gsub(key, "_contextmenu_", "") + txt = localization[key] + end + AddEntryToCells(cp["stats_custom_tooltip_" .. q] or "", layer + 1, cp["stats_custom_tooltip_entry_" .. q] or "", cells) + q = q + 1 + end + end + + if wd.targetable and ((wd.targetable == 1) or (wd.targetable == true)) then + AddEntryToCells(localization.weapon_interceptable, layer + 1, '', cells) end end - - if ws.firing_arc and (ws.firing_arc > -1) then - cells[#cells+1] = ' - Firing arc:' - cells[#cells+1] = numformat(360*math.acos(ws.firing_arc)/math.pi) .. ' deg' - end - - if cp.needs_link then - cells[#cells+1] = ' - Grid needed:' - cells[#cells+1] = tonumber(cp.needs_link) .. " E" - end - - if cp.smoothradius then - cells[#cells+1] = ' - Smooth ground' - cells[#cells+1] = numformat((tonumber(cp.smoothmult or 0) or 0)*100) .. '%' - end - - if cp.movestructures then - cells[#cells+1] = ' - Smooth structures' - cells[#cells+1] = numformat((tonumber(cp.movestructures or 0) or 0)*100) .. '%' - end - - local highTraj = wd.highTrajectory - if highTraj == 2 then - highTraj = ws.highTrajectory - end - if highTraj == 1 then - cells[#cells+1] = ' - High trajectory' - cells[#cells+1] = '' - elseif highTraj == 2 then - cells[#cells+1] = ' - Trajectory toggle' - cells[#cells+1] = '' - end - - if wd.waterWeapon and (wd.type ~= "TorpedoLauncher") then - cells[#cells+1] = ' - Water capable' - cells[#cells+1] = '' - end - - if not wd.avoidFriendly and not wd.noFriendlyCollide and not cp.ui_no_friendly_fire then - cells[#cells+1] = ' - Potential friendly fire' - cells[#cells+1] = '' - end - - if wd.noGroundCollide then - cells[#cells+1] = ' - Passes through ground' - cells[#cells+1] = '' - end - - if (wd.noExplode or cp.pretend_no_explode) and not cp.thermite_frames then - cells[#cells+1] = ' - Piercing ' - cells[#cells+1] = '' - end - - if cp.dyndamageexp then - cells[#cells+1] = ' - Damage falls off with range' - cells[#cells+1] = '' - end - - if cp.nofriendlyfire then - cells[#cells+1] = ' - No friendly fire' - cells[#cells+1] = '' - end - - if cp.shield_drain then - cells[#cells+1] = ' - Shield drain:' - cells[#cells+1] = cp.shield_drain .. " HP/shot" - end - - if cp.aim_delay then - cells[#cells+1] = ' - Aiming time:' - cells[#cells+1] = numformat(tonumber(cp.aim_delay)/1000) .. "s" - end - - if wd.targetMoveError > 0 then - cells[#cells+1] = ' - Inaccuracy vs moving targets' - cells[#cells+1] = '' -- actual value doesn't say much as it's a multiplier for the target speed - end - - if wd.targetable and ((wd.targetable == 1) or (wd.targetable == true)) then - cells[#cells+1] = ' - Can be shot down by antinukes' - cells[#cells+1] = '' + --cluster info + --RECURSION INCOMING! + if cp.numprojectiles1 then + if not (cp.bogus or cp.hideweapon) then + AddEntryToCells(localization.weapon_cluster_munitions .. ':', layer + 1, '', cells) + end + local submunitionCount = 1 + while cp["numprojectiles" .. submunitionCount] do + local isRecusive = false + for i = 1, #recursedWepIds do + if cp["projectile" .. submunitionCount] == recursedWepIds[i] then + isRecusive = true + end + end + if isRecusive then + AddEntryToCells(WeaponDefNames[cp["projectile" .. submunitionCount]].description .. ' x ' .. cp["numprojectiles" .. submunitionCount] .. ' (Previously Listed)', layer + 1, '', cells) + else + cells = weapons2Table(cells, cp["projectile" .. submunitionCount], unitID, cp["numprojectiles" .. submunitionCount] * (cp.bogus and bombletCount or 1) * (cp["clustercharges"] or 1), recursedWepIds, false, cost, isFeature, layer + 2, index) + end + submunitionCount = submunitionCount + 1 + end + if cp["clustercharges"] then + AddEntryToCells(localization.weapon_cluster_ttr .. ':', layer + 1, numformat(cp["clustercharges"]/30) .. localization.acronyms_second, cells) + end end end return cells end -local function printAbilities(ud, unitID, isCommander) +local function printAbilities(ud, unitID, isFeature) local cells = {} local cp = ud.customParams - if ud.buildSpeed > 0 and not cp.nobuildpower then - local buildSpeed = (unitID and Spring.Utilities.GetUnitBuildSpeed(unitID)) or ud.buildSpeed - cells[#cells+1] = 'Construction' - cells[#cells+1] = '' - cells[#cells+1] = ' - Buildpower: ' - cells[#cells+1] = numformat(buildSpeed) .. " cost/s" - if ud.buildDistance and not ud.isFactory then - cells[#cells+1] = ' - Build range:' - cells[#cells+1] = numformat(ud.buildDistance) .. " elmo" + local bpMult = 1 + if isFeature then + bpMult = unitID and Spring.GetFeatureRulesParam(unitID, "buildpower_mult") or 1 + elseif unitID and Spring.GetUnitRulesParam(unitID, "comm_level") then + bpMult = unitID and Spring.GetUnitRulesParam(unitID, "buildpower_mult") or 1 + end + local buildSpeed = ud.buildSpeed * bpMult + AddEntryToCells(localization.construction, 1, '', cells) + if ud.customParams.bp_overdrive then + local charge = tonumber(ud.customParams.bp_overdrive_initialcharge) + local maxCharge = tonumber(ud.customParams.bp_overdrive_totalcharge) + local bonusBP = tonumber(ud.customParams.bp_overdrive_bonus) -- negative for spooling, positive for decremental + local delay = tonumber(ud.customParams.bp_overdrive_chargedelay) -- in frames + local rechargeRate = tonumber(ud.customParams.bp_overdrive_chargerate) -- in per second. + local spooling = bonusBP < 0 + if spooling then + AddEntryToCells(localization.starting_buildpower .. ':', 2, numformat((1 - bonusBP) * buildSpeed), cells) + AddEntryToCells(localization.buildpower_increases_use, 2, '', cells) + AddEntryToCells(localization.max_buildpower .. ':', 2, numformat(buildSpeed), cells) + AddEntryToCells(localization.buildpower_diminishes_with_disuse .. ':', 2, numformat(delay / 30, 1) .. localization.acronyms_second, cells) + AddEntryToCells(localization.decay_rate .. ':', 2, numformat((rechargeRate / maxCharge) * 100, 1) .. '%/' .. localization.acronyms_second, cells) + else + AddEntryToCells(localization.base_buildpower .. ':', 2, numformat(buildSpeed), cells) + AddEntryToCells(localization.starting_buildpower .. ':', 2, buildSpeed * (1 + bonusBP), cells) + AddEntryToCells(localization.recharge_delay .. ':', 2, numformat(delay / 30, 1) .. localization.acronyms_second, cells) + AddEntryToCells(localization.buildpower_regen_rate .. ':', 2, numformat((rechargeRate / maxCharge) * 100, 1) .. '%/' .. localization.acronyms_second, cells) + end + else + AddEntryToCells(localizationCommon.buildpower .. ':', 2, numformat(buildSpeed), cells) end if ud.canResurrect then - cells[#cells+1] = ' - Can resurrect wreckage' - cells[#cells+1] = '' + AddEntryToCells(localization.can_resurrect, 2, '', cells) end if (#ud.buildOptions == 0) then - cells[#cells+1] = ' - Can only assist' - cells[#cells+1] = '' + AddEntryToCells(localization.only_assists, 2, '', cells) end - cells[#cells+1] = '' - cells[#cells+1] = '' + --AddEntryToCells('', 0, '', cells) + end + + if cp.vampirism_kill then + AddEntryToCells(localization.vampirism, 1, '', cells) + AddEntryToCells(localization.vampirism_kills_increase_hp .. ":", 2, WG.Translate("interface", "vampirism_kills_increase_hp_desc", {number = numformat(cp.vampirism_kill * 100, 1)}), cells) + end + if cp.field_factory then + AddEntryToCells(localization.field_fac, 1, '', cells) end if ud.armoredMultiple < 1 then - cells[#cells+1] = 'Armored form' - cells[#cells+1] = '' - cells[#cells+1] = ' - Reduction: ' - cells[#cells+1] = numformat((1-ud.armoredMultiple)*100) .. '%' + AddEntryToCells(localization.armored_unit, 1, '', cells) + AddEntryToCells(localization.armor_reduction .. ':', 2, numformat((1-ud.armoredMultiple)*100) .. '%', cells) + if cp.armortype and cp.armortype == '1' then + AddEntryToCells(localization.armor_type_1, 2, '', cells) + elseif cp.armortype and cp.armortype == '2' then + AddEntryToCells(localization.armor_type_2, 2, '', cells) + end if cp.force_close then - cells[#cells+1] = ' - Forced for: ' - cells[#cells+1] = cp.force_close .. 's on damage' - end - cells[#cells+1] = '' - cells[#cells+1] = '' - end - - if cp.area_cloak or (unitID and Spring.GetUnitRulesParam(unitID, "comm_area_cloak")) then - local areaCloakUpkeep = (unitID and Spring.GetUnitRulesParam(unitID, "comm_area_cloak_upkeep") or cp.area_cloak_upkeep) - local areaCloakRadius = ((unitID and Spring.GetUnitRulesParam(unitID, "comm_area_cloak_radius")) or cp.area_cloak_radius) - local areaCloakRecloak = ((unitID and Spring.GetUnitRulesParam(unitID, "comm_area_recloak_rate")) or cp.area_cloak_recloak_rate) - cells[#cells+1] = 'Area cloak' - cells[#cells+1] = '' - cells[#cells+1] = ' - Upkeep:' - cells[#cells+1] = areaCloakUpkeep .. " E/s" - cells[#cells+1] = ' - Radius:' - cells[#cells+1] = areaCloakRadius .. " elmo" - cells[#cells+1] = ' - Cloak rate:' - cells[#cells+1] = areaCloakRecloak .. " mass/s" - if cp.area_cloak_shift_range then - cells[#cells+1] = ' - Offset range:' - cells[#cells+1] = cp.area_cloak_shift_range - end - if cp.area_cloak_move_mult then - cells[#cells+1] = ' - Move speed:' - cells[#cells+1] = numformat(tonumber(cp.area_cloak_move_mult)*100) .. "%" - end - cells[#cells+1] = '' - cells[#cells+1] = '' - end - - if ud.canCloak and (not (unitID and isCommander) or Spring.GetUnitRulesParam(unitID, "comm_personal_cloak")) then - local decloakDistance = (unitID and Spring.GetUnitRulesParam(unitID, "comm_decloak_distance")) or ud.decloakDistance - cells[#cells+1] = 'Personal cloak' - cells[#cells+1] = '' - if not ud.isImmobile and ud.cloakCost ~= ud.cloakCostMoving then - cells[#cells+1] = ' - Upkeep mobile: ' - cells[#cells+1] = numformat(ud.cloakCostMoving) .. " E/s" - cells[#cells+1] = ' - Upkeep idle: ' + AddEntryToCells(localization.forced_closed .. ":", 2, cp.force_close .. localization.acronyms_second, cells) + end + AddEntryToCells('', 0, '', cells) + end + local commHasAreaCloak + if unitID and isFeature then + commHasAreaCloak = Spring.GetFeatureRulesParam(unitID, "comm_area_cloak") ~= nil + elseif unitID then + commHasAreaCloak = Spring.GetUnitRulesParam(unitID, "comm_area_cloak") ~= nil + end + if cp.area_cloak or commHasAreaCloak then + local areaCloakRadius, areaCloakUpkeep + if unitID and isFeature then + areaCloakUpkeep = unitID and Spring.GetFeatureRulesParam(unitID, "comm_area_cloak_upkeep") + areaCloakRadius = unitID and Spring.GetFeatureRulesParam(unitID, "comm_area_cloak_radius") + elseif unitID then + areaCloakUpkeep = unitID and Spring.GetUnitRulesParam(unitID, "comm_area_cloak_upkeep") + areaCloakRadius = unitID and Spring.GetUnitRulesParam(unitID, "comm_area_cloak_radius") + else + areaCloakUpkeep = cp.area_cloak_upkeep + areaCloakRadius = cp.area_cloak_radius + end + AddEntryToCells(localization.area_cloak, 1, '', cells) + AddEntryToCells(localization.upkeep .. ':', 1, areaCloakUpkeep .. " " .. localizationCommon.energy .. "/" .. localization.acronyms_second, cells) + AddEntryToCells(localization.radius .. ':', 1, areaCloakRadius .. " elmo", cells) + AddEntryToCells('', 0, '', cells) + end + local hasReconPulse = unitID ~= nil + if hasReconPulse and isFeature then + hasReconPulse = Spring.GetFeatureRulesParam(unitID, "commander_reconpulse") ~= nil + elseif hasReconPulse then + hasReconPulse = Spring.GetUnitRulesParam(unitID, "commander_reconpulse") ~= nil + end + if hasReconPulse then + AddEntryToCells(localization.recon_pulse, 1, '', cells) + AddEntryToCells(localization.recon_pulse_desc, 1, '', cells) + AddEntryToCells(localization.recon_pulse_applied, 1, '', cells) + end + local canCloak + if unitID and isFeature then + canCloak = Spring.GetFeatureRulesParam(unitID, "comm_personal_cloak") ~= nil + elseif unitID then + canCloak = Spring.GetUnitRulesParam(unitID, "comm_personal_cloak") ~= nil + end + if ud.canCloak and (not unitID or canCloak) then + local decloakDistance + if not unitID then + decloakDistance = ud.decloakDistance + elseif isFeature then + decloakDistance = Spring.GetFeatureRulesParam(unitID, "comm_decloak_distance") or ud.decloakDistance else - cells[#cells+1] = ' - Upkeep: ' + decloakDistance = Spring.GetUnitRulesParam(unitID, "comm_decloak_distance") or ud.decloakDistance + end + AddEntryToCells(localization.personal_cloak, 1, '', cells) + local extrastring + if not ud.isImmobile and ud.cloakCost ~= ud.cloakCostMoving and ud.cloakCost > 0 then + AddEntryToCells(localization.upkeep_mobile .. ':', 2, numformat(ud.cloakCostMoving) .. " " .. localizationCommon.energy .. "/" .. localization.acronyms_second, cells) + extrastring = localization.upkeep_stationary .. ':' + else + extrastring = localization.upkeep .. ':' + end + if ud.cloakCost > 0 then + AddEntryToCells(extrastring, 2, numformat(ud.cloakCost) .. " " .. localizationCommon.energy .. "/" .. localization.acronyms_second, cells) + else + AddEntryToCells(extrastring, 2, localization.free, cells) + end + AddEntryToCells(localization.decloak_radius .. ':', 2, numformat(decloakDistance) .. " elmo", cells) + if cp.cloakstrikeduration then + AddEntryToCells(localization.cloakstrike, 2, '', cells) + AddEntryToCells(localization.duration .. ':', 3, numformat(cp.cloakstrikeduration/30, 1) .. localization.acronyms_second, cells) + if ud.decloakOnFire then + AddEntryToCells(localization.cloakstrike_lose_advantage, 3, '', cells) + end end - cells[#cells+1] = numformat(ud.cloakCost) .. " E/s" - cells[#cells+1] = ' - Decloak radius: ' - cells[#cells+1] = numformat(decloakDistance) .. " elmo" if not ud.decloakOnFire then - cells[#cells+1] = ' - No decloak while shooting' - cells[#cells+1] = '' + AddEntryToCells(localization.unit_no_decloak_on_fire, 2, '', cells) end - cells[#cells+1] = '' - cells[#cells+1] = '' end if cp.idle_cloak then - cells[#cells+1] = 'Personal cloak' - cells[#cells+1] = '' - cells[#cells+1] = ' - Only when idle' - cells[#cells+1] = '' - cells[#cells+1] = ' - Free and automated' - cells[#cells+1] = '' - cells[#cells+1] = ' - Decloak radius: ' - cells[#cells+1] = numformat(ud.decloakDistance) .. " elmo" - cells[#cells+1] = '' - cells[#cells+1] = '' - end - - local radarRadius = unitID and Spring.GetUnitRulesParam(unitID, "radarRangeOverride") or ud.radarDistance - local jammerRadius = unitID and Spring.GetUnitRulesParam(unitID, "jammingRangeOverride") or ud.radarDistanceJam + AddEntryToCells(localization.personal_cloak, 1, '', cells) + AddEntryToCells(localization.only_idle, 2, '', cells) + AddEntryToCells(localization.idle_cloak_free, 2, '', cells) + AddEntryToCells(localization.decloak_radius .. ':', 2, numformat(ud.decloakDistance) .. " elmo", cells) + end + if cp.reveal_onprogress then + AddEntryToCells(WG.Translate("interface", "revealpercent", {percent = numformat(tonumber(cp.reveal_onprogress) * 100, 1)}), 1, '', cells) + end + local commcloakregen, commrecloaktime, commjammerrange, commradarrange, nanoregen, nanomax + if unitID then + if isFeature then + commcloakregen = Spring.GetFeatureRulesParam(unitID, "commcloakregen") + commrecloaktime = Spring.GetFeatureRulesParam(unitID, "commrecloaktime") + commjammerrange = Spring.GetFeatureRulesParam(unitID, "jammingRangeOverride") + commradarrange = Spring.GetFeatureRulesParam(unitID, "radarRangeOverride") + nanoregen = Spring.GetFeatureRulesParam(unitID, "commander_regen") + nanomax = Spring.GetFeatureRulesParam(unitID, "commander_max") + else + commcloakregen = Spring.GetUnitRulesParam(unitID, "commcloakregen") + commrecloaktime = Spring.GetUnitRulesParam(unitID, "commrecloaktime") + commjammerrange = Spring.GetUnitRulesParam(unitID, "jammingRangeOverride") + commradarrange = Spring.GetUnitRulesParam(unitID, "radarRangeOverride") + nanoregen = Spring.GetUnitRulesParam(unitID, "commander_regen") + nanomax = Spring.GetUnitRulesParam(unitID, "commander_max") + end + end + nanomax = nanomax or cp.nano_maxregen + nanoregen = nanoregen or cp.nanoregen + if cp.cloakregen or commcloakregen then + local cloakregen = commcloakregen or cp.cloakregen + AddEntryToCells(localization.cloak_regen .. ":", 2, cloakregen .. localization.acronyms_hp .. "/" .. localization.acronyms_second, cells) + end + if cp.recloaktime or commrecloaktime then + local recloaktime = commrecloaktime or cp.recloaktime + AddEntryToCells( WG.Translate("interface", "recloaks_after_seconds", {time = numformat(recloaktime / 30, 1)}), 2, '', cells) + end + AddEntryToCells('', 0, '', cells) + local radarRadius = commradarrange or ud.radarRadius + local jammerRadius = commjammerrange or ud.jammerRadius - if (radarRadius > 0) or (jammerRadius > 0) or ud.isTargetingUpgrade then - cells[#cells+1] = 'Provides intel' - cells[#cells+1] = '' + if (radarRadius > 0) or (jammerRadius > 0) or ud.targfac then + AddEntryToCells(localization.provides_intel, 1, '', cells) if (radarRadius > 0) then - cells[#cells+1] = ' - Radar:' - cells[#cells+1] = numformat(radarRadius) .. " elmo" + AddEntryToCells(localization.radar .. ':', 2,numformat(radarRadius) .. " elmo", cells) end if (jammerRadius > 0) then - cells[#cells+1] = ' - Radar jamming:' - cells[#cells+1] = numformat(jammerRadius) .. " elmo" + AddEntryToCells(localization.jamming .. ':', 2, numformat(jammerRadius) .. " elmo", cells) end - if ud.isTargetingUpgrade then - cells[#cells+1] = ' - Improves radar accuracy' - cells[#cells+1] = '' + if ud.targfac then + AddEntryToCells(localization.improves_radar, 2, '', cells) end - cells[#cells+1] = '' - cells[#cells+1] = '' + AddEntryToCells('', 0, '', cells) end if cp.canjump and (not cp.no_jump_handling) then - cells[#cells+1] = 'Jumping' - cells[#cells+1] = '' - cells[#cells+1] = ' - Range:' - cells[#cells+1] = (cp.jump_range * ((unitID and Spring.GetUnitRulesParam(unitID, "jumpRangeMult")) or 1)) .. " elmo" - cells[#cells+1] = ' - Reload: ' - cells[#cells+1] = (cp.jump_reload + ((unitID and Spring.GetUnitRulesParam(unitID, "upgradesJumpReloadMod")) or 0)) .. 's' - cells[#cells+1] = ' - Speed:' - cells[#cells+1] = numformat(30*tonumber(cp.jump_speed)) .. " elmo/s" - cells[#cells+1] = ' - Midair jump:' - cells[#cells+1] = (tonumber(cp.jump_from_midair) == 0) and "No" or "Yes" - cells[#cells+1] = '' - cells[#cells+1] = '' + local rangebonus, reloadbonus = 0, 0 + if unitID then + if isFeature then + rangebonus = Spring.GetFeatureRulesParam(unitID, "comm_jumprange_bonus") or 0 + reloadbonus = Spring.GetFeatureRulesParam(unitID, "comm_jumpreload_bonus") or 0 + else + rangebonus = Spring.GetUnitRulesParam(unitID, "comm_jumprange_bonus") or 0 + reloadbonus = Spring.GetUnitRulesParam(unitID, "comm_jumpreload_bonus") or 0 + end + end + rangebonus = rangebonus + 1 + reloadbonus = 1 - reloadbonus + AddEntryToCells(localization.jump, 1, '', cells) + AddEntryToCells(localization.stats_range .. ':', 2, numformat(cp.jump_range * rangebonus, 0) .. " elmo", cells) + AddEntryToCells(localization.stats_reload .. ':', 2, numformat(cp.jump_reload * reloadbonus, 1) .. localization.acronyms_second, cells) + AddEntryToCells(localization.speed .. ':', 2, numformat(30*tonumber(cp.jump_speed)) .. " elmo/" .. localization.acronyms_second, cells) + AddEntryToCells(localization.mid_air_jump .. ':', 2, (tonumber(cp.jump_from_midair) == 0) and localization.no or localization.yes, cells) + AddEntryToCells('', 0, '', cells) end if cp.morphto then - cells[#cells+1] = 'Morphing' - cells[#cells+1] = '' - cells[#cells+1] = ' - To: ' - cells[#cells+1] = Spring.Utilities.GetHumanName(UnitDefNames[cp.morphto]) - cells[#cells+1] = ' - Cost: ' - cells[#cells+1] = math.max(0, (UnitDefNames[cp.morphto].buildTime - ud.buildTime)) .. " M" + AddEntryToCells(localization.morphing, 1, '', cells) + AddEntryToCells(localization.morphs_to .. ":", 2, Spring.Utilities.GetHumanName(UnitDefNames[cp.morphto]), cells) + AddEntryToCells(localization.cost .. ':', 2, math.max(0, (UnitDefNames[cp.morphto].buildTime - ud.buildTime)) .. " " .. localizationCommon.metal, cells) if cp.morphrank and (tonumber(cp.morphrank) > 0) then - cells[#cells+1] = ' - Rank:' - cells[#cells+1] = cp.morphrank + AddEntryToCells(localization.rank_required .. ':', 2, cp.morphrank, cells) end - cells[#cells+1] = ' - Time: ' - cells[#cells+1] = cp.morphtime .. "s" + AddEntryToCells(localization.morph_time .. ':', 2, cp.morphtime .. localization.acronyms_second, cells) if cp.combatmorph == '1' then - cells[#cells+1] = ' - Not disabled during morph' + AddEntryToCells(localization.not_disabled_morph, 2, '', cells) else - cells[#cells+1] = ' - Disabled during morph' + AddEntryToCells(localization.disabled_morph, 2, '', cells) end - cells[#cells+1] = '' - cells[#cells+1] = '' - cells[#cells+1] = '' + AddEntryToCells('', 0, '', cells) end - - if (ud.idleTime < 1800) or (cp.amph_regen) or (cp.armored_regen) then - cells[#cells+1] = 'Improved regeneration' - cells[#cells+1] = '' + + if (ud.idleTime < 1800) or (cp.amph_regen) or (cp.armored_regen) or (cp.nanoregen) then + AddEntryToCells(localization.improved_regen, 1, '', cells) if ud.idleTime < 1800 then if ud.idleTime > 0 then - cells[#cells+1] = ' - Idle regen: ' - cells[#cells+1] = numformat(cp.idle_regen) .. ' HP/s' - cells[#cells+1] = ' - Time to enable: ' - cells[#cells+1] = numformat(ud.idleTime / 30) .. 's' + AddEntryToCells(localization.idle_regen .. ':', 2, numformat(cp.idle_regen) .. " " .. localization.acronyms_hp .. "/" .. localization.acronyms_second, cells) + AddEntryToCells(localization.regen_time_to_enable .. ':', 2, numformat(ud.idleTime / 30) .. localization.acronyms_second, cells) else - cells[#cells+1] = ' - Combat regen: ' - local dynamic_regen = unitID and Spring.GetUnitRulesParam(unitID, "comm_autorepair_rate") or cp.idle_regen - cells[#cells+1] = numformat(dynamic_regen) .. ' HP/s' + local dynamic_regen + if isFeature then + dynamic_regen = unitID and Spring.GetFeatureRulesParam(unitID, "comm_autorepair_rate") or cp.idle_regen + else + dynamic_regen = unitID and Spring.GetUnitRulesParam(unitID, "comm_autorepair_rate") or cp.idle_regen + end + AddEntryToCells(localization.constant_regen .. ':', 2, numformat(dynamic_regen) .. " " .. localization.acronyms_hp .. "/" .. localization.acronyms_second, cells) + end + end + if nanoregen then + local commHP = 0 + if unitID then + if isFeature then + commHP = Spring.GetFeatureRulesParam(unitID, "commander_healthbonus") or 0 + else + commHP = Spring.GetUnitRulesParam(unitID, "commander_healthbonus") or 0 + end end + local hp = ud.health + commHP + AddEntryToCells(localization.nano_regen .. ":", 2, '', cells) + AddEntryToCells(localization.base_regen .. ":", 3, nanoregen .. " " .. localization.acronyms_hp .. "/" .. localization.acronyms_second, cells) + AddEntryToCells(localization.max_regen .. ":", 3, numformat(nanoregen * nanomax, 1) .. " " .. localization.acronyms_hp .. "/" .. localization.acronyms_second, cells) + AddEntryToCells(localization.max_below .. ":", 3, numformat(hp / nanomax) .. localization.acronyms_hp, cells) end if cp.amph_regen then - cells[#cells+1] = ' - Water regen: ' - cells[#cells+1] = cp.amph_regen .. ' HP/s' - cells[#cells+1] = ' - At depth: ' - cells[#cells+1] = cp.amph_submerged_at .. " elmo" + AddEntryToCells(localization.water_regen .. ':', 2, cp.amph_regen .. localization.acronyms_hp .. "/" .. localization.acronyms_second, cells) + AddEntryToCells(localization.at_depth .. ':', 2, cp.amph_submerged_at .. " elmo", cells) end if cp.armored_regen then - cells[#cells+1] = ' - Closed regen: ' - cells[#cells+1] = numformat(tonumber(cp.armored_regen)) .. ' HP/s' + AddEntryToCells(localization.armor_regen .. ':', 2, numformat(tonumber(cp.armored_regen)) .. " " .. localization.acronyms_hp .. "/" .. localization.acronyms_second, cells) end - cells[#cells+1] = '' - cells[#cells+1] = '' + AddEntryToCells('', 0, '', cells) end if cp.teleporter then - cells[#cells+1] = 'Teleporter' - cells[#cells+1] = '' - cells[#cells+1] = ' - Spawns a beacon for one-way recall' - cells[#cells+1] = '' - cells[#cells+1] = ' - Spawn time:' - cells[#cells+1] = numformat(tonumber(cp.teleporter_beacon_spawn_time)) .. "s" - cells[#cells+1] = ' - Throughput: ' - cells[#cells+1] = numformat(tonumber(cp.teleporter_throughput)) .. " mass / s" - cells[#cells+1] = '' - cells[#cells+1] = '' + AddEntryToCells(localization.teleporter, 1, '', cells) + AddEntryToCells(localization.spawns_beacon, 2, '', cells) + AddEntryToCells(localization.spawn_time .. ':', 2, numformat(tonumber(cp.teleporter_beacon_spawn_time), 1) .. localization.acronyms_second, cells) + AddEntryToCells(localization.teleport_throughput .. ':', 2, numformat(tonumber(cp.teleporter_throughput), 1) .. localization.mass .. "/" .. localization.acronyms_second, cells) + AddEntryToCells('', 0, '', cells) end if cp.pad_count then - cells[#cells+1] = 'Rearms and repairs aircraft' - cells[#cells+1] = '' - cells[#cells+1] = ' - Pads:' - cells[#cells+1] = cp.pad_count - cells[#cells+1] = ' - Pad buildpower:' - cells[#cells+1] = (cp.pad_bp and numformat(cp.pad_bp) or '2.5') .. " cost/s" - cells[#cells+1] = '' - cells[#cells+1] = '' + local bp = tonumber(cp.pad_bp) or 2.5 + AddEntryToCells(localization.rearm_repair, 1, '', cells) + AddEntryToCells(localization.rearm_pads .. ':', 2, cp.pad_count, cells) + AddEntryToCells(localization.pad_bp .. ':', 2, numformat(bp / tonumber(cp.pad_count), 1), cells) -- Future Wars mechanic! Remove the dividend for base game! + AddEntryToCells('', 0, '', cells) end if cp.is_drone then - cells[#cells+1] = 'Bound to owner' - cells[#cells+1] = '' - cells[#cells+1] = " - Uncontrollable, uses owner's orders" - cells[#cells+1] = '' - cells[#cells+1] = ' - Must stay near owner' - cells[#cells+1] = '' - cells[#cells+1] = ' - Will die if owner does' - cells[#cells+1] = '' - cells[#cells+1] = '' - cells[#cells+1] = '' - end - - if cp.boost_speed_mult then - cells[#cells+1] = 'Speed boost' - cells[#cells+1] = '' - cells[#cells+1] = ' - Boost speed: ' - cells[#cells+1] = math.floor((tonumber(cp.boost_speed_mult or "1")*100) + 0.5) .. "%" - cells[#cells+1] = ' - Boost accel: ' - cells[#cells+1] = math.floor((tonumber(cp.boost_accel_mult or cp.boost_speed_mult or "1")*100) + 0.5) .. "%" - if cp.boost_reload_speed_mult then - cells[#cells+1] = ' - Recharge speed: ' - cells[#cells+1] = math.floor((tonumber(cp.boost_reload_speed_mult or "1")*100) + 0.5) .. "%" - end - cells[#cells+1] = ' - Duration: ' - cells[#cells+1] = numformat(tonumber(cp.boost_duration)/30) .. 's' - if cp.specialreloadtime then - cells[#cells+1] = ' - Reload: ' - cells[#cells+1] = numformat(tonumber(cp.specialreloadtime)/30) .. 's' - end - if cp.boost_distance then - cells[#cells+1] = ' - Distance: ' - cells[#cells+1] = numformat(tonumber(cp.boost_distance)) .. ' elmos (approx.)' - end - if cp.boost_detonate then - cells[#cells+1] = ' - Self detonates upon completion' - cells[#cells+1] = '' + AddEntryToCells(localization.drone_bound, 1, '', cells) + if not cp.is_controllable_drone then + AddEntryToCells(localization.drone_cannot_direct_control, 2, '', cells) + AddEntryToCells(localization.drone_uses_owners_commands, 2, '', cells) + AddEntryToCells(localization.drone_bound_to_range, 2, '', cells) end - cells[#cells+1] = '' - cells[#cells+1] = '' + AddEntryToCells(localization.drone_dies_on_owner_death, 2, '', cells) + AddEntryToCells('', 0, '', cells) end - if cp.scan_radius_base then - cells[#cells+1] = 'Reveals area on death' - cells[#cells+1] = '' - cells[#cells+1] = ' - Radius: ' - cells[#cells+1] = math.floor(tonumber(cp.scan_radius_base or "1")) .. ' elmos' - if cp.scan_radius_max then - cells[#cells+1] = ' - After full boost: ' - cells[#cells+1] = math.floor(tonumber(cp.scan_radius_max or "1")) .. ' elmos' - end - cells[#cells+1] = ' - Duration: ' - cells[#cells+1] = numformat(tonumber(cp.scan_frames)/30) .. 's' - cells[#cells+1] = ' - Reveals cloaked and underwater units' - cells[#cells+1] = '' - cells[#cells+1] = '' - cells[#cells+1] = '' + if cp.boost_speed_mult then + AddEntryToCells(localization.speed_boost, 1, '', cells) + AddEntryToCells(localization.speed .. ':', 2, 'x' .. cp.boost_speed_mult, cells) + AddEntryToCells(localization.duration .. ':', 2, numformat(tonumber(cp.boost_duration), 1) .. localization.acronyms_second, cells) + AddEntryToCells(localization.stats_reload .. ':', 2, numformat(tonumber(cp.specialreloadtime)/30, 1) .. localization.acronyms_second, cells) + AddEntryToCells('', 0, '', cells) end if cp.windgen then local wind_slope = Spring.GetGameRulesParam("WindSlope") or 0 local max_wind = Spring.GetGameRulesParam("WindMax") or 2.5 local bonus_100 = numformat(100*wind_slope*max_wind) - - cells[#cells+1] = 'Generates energy from wind' - cells[#cells+1] = '' - cells[#cells+1] = ' - Variable income' - cells[#cells+1] = '' - cells[#cells+1] = ' - Max wind:' - cells[#cells+1] = max_wind .. " E" - cells[#cells+1] = ' - Altitude bonus:' - cells[#cells+1] = bonus_100 .. " E / 100 height" - cells[#cells+1] = '' - cells[#cells+1] = '' + AddEntryToCells(localization.wind_gen, 1, '', cells) + AddEntryToCells(localization.wind_variable_income, 2, '', cells) + AddEntryToCells(localization.max_generation, 2, max_wind .. " " .. localizationCommon.energy, cells) + AddEntryToCells(localization.altitude_bonus, 2, bonus_100 .. " " .. localization.wind_100_height, cells) + AddEntryToCells('', 0, '', cells) end if cp.grey_goo then - cells[#cells+1] = 'Gray Goo' - cells[#cells+1] = '' - cells[#cells+1] = ' - Eats nearby wreckage to spawn units' - cells[#cells+1] = '' - cells[#cells+1] = ' - Spawns:' - cells[#cells+1] = Spring.Utilities.GetHumanName(UnitDefNames[cp.grey_goo_spawn]) - cells[#cells+1] = ' - BP:' - cells[#cells+1] = cp.grey_goo_drain - cells[#cells+1] = ' - Cost:' - cells[#cells+1] = cp.grey_goo_cost .. " M" - cells[#cells+1] = '' - cells[#cells+1] = '' + AddEntryToCells(localization.grey_goo, 1, '', cells) + AddEntryToCells(localization.grey_goo_consumption, 2, '', cells) + AddEntryToCells(localization.stats_spawns .. ':', 2, Spring.Utilities.GetHumanName(UnitDefNames[cp.grey_goo_spawn]), cells) + AddEntryToCells(localization.rate .. ':', 2, cp.grey_goo_drain .. " " .. localizationCommon.metal .. "/" .. localization.acronyms_second, cells) + AddEntryToCells(localization.cost .. ':', 2, cp.grey_goo_cost .. " " .. localizationCommon.metal, cells) + AddEntryToCells('', 0, '', cells) + end + if cp.dangerous_reclaim then + AddEntryToCells(localization.dangerous_reclaim, 1, '', cells) end - if cp.floattoggle then - cells[#cells+1] = 'Floating' - cells[#cells+1] = '' - cells[#cells+1] = ' - Can move from seabed to surface' - cells[#cells+1] = '' - cells[#cells+1] = ' - Cannot move sideways while afloat' - cells[#cells+1] = '' + AddEntryToCells(localization.floats, 1, '', cells) + AddEntryToCells(localization.can_move_to_surface, 2, '', cells) + AddEntryToCells(localization.cannot_move_sideways, 2, '', cells) if (cp.sink_on_emp ~= '0') then - cells[#cells+1] = ' - Sinks when stunned' + AddEntryToCells(localization.sinks_when_stun, 2, '', cells) else - cells[#cells+1] = ' - Stays afloat when stunned' + AddEntryToCells(localization.float_when_stun, 2, '', cells) end - cells[#cells+1] = '' end if ud.transportCapacity and (ud.transportCapacity > 0) then - cells[#cells+1] = 'Transport: ' - cells[#cells+1] = (((ud.customParams.islightonlytransport) and "Light") or ((ud.customParams.islighttransport) and "Medium") or "Heavy") - cells[#cells+1] = 'Light Speed: ' - cells[#cells+1] = math.floor((tonumber(ud.customParams.transport_speed_light or "1")*100) + 0.5) .. "%" - if not ud.customParams.islightonlytransport then - cells[#cells+1] = 'Medium Speed: ' - cells[#cells+1] = math.floor((tonumber(ud.customParams.transport_speed_medium or "1")*100) + 0.5) .. "%" - end + AddEntryToCells(localization.transportation, 1, '', cells) + AddEntryToCells(localization.transport_type .. ":", 2, ((ud.customParams.islighttransport) and localization.transport_light or localization.transport_heavy), cells) + AddEntryToCells(localization.transport_light_speed .. ':', 2, math.floor((tonumber(ud.customParams.transport_speed_light or "1")*100) + 0.5) .. "%", cells) if not ud.customParams.islighttransport then - cells[#cells+1] = 'Heavy Speed: ' - cells[#cells+1] = math.floor((tonumber(ud.customParams.transport_speed_heavy or "1")*100) + 0.5) .. "%" + AddEntryToCells(localization.transport_heavy_speed .. ':', 2, math.floor((tonumber(ud.customParams.transport_speed_heavy or "1")*100) + 0.5) .. "%", cells) end end if ud.customParams.nuke_coverage then - cells[#cells+1] = 'Can intercept strategic nukes' - cells[#cells+1] = '' - cells[#cells+1] = ' - Coverage:' - cells[#cells+1] = ud.customParams.nuke_coverage .. " elmo" - cells[#cells+1] = '' - cells[#cells+1] = '' + AddEntryToCells(localization.anti_interception, 1, '', cells) + AddEntryToCells(localization.stats_range .. ":", 2, ud.customParams.nuke_coverage .. " elmo", cells) + AddEntryToCells('', 0, '', cells) end if cp.combat_slowdown then - cells[#cells+1] = 'Combat slowdown: ' - cells[#cells+1] = numformat(100*tonumber(cp.combat_slowdown)) .. "%" + AddEntryToCells(localization.combat_slowdown .. ':', 1, numformat(100*tonumber(cp.combat_slowdown)) .. "%", cells) end - - if ud.stealth then - cells[#cells+1] = 'Invisible to radar' - cells[#cells+1] = '' + local commJammed + if unitID then + if isFeature then + commJammed = Spring.GetFeatureRulesParam(unitID, "comm_jammed") ~= nil + else + commJammed = Spring.GetUnitRulesParam(unitID, "comm_jammed") ~= nil + end end - - if ud.selfDestructCountdown <= 1 then - cells[#cells+1] = 'Instant self-destruction' - cells[#cells+1] = '' + if ud.stealth or commJammed then + AddEntryToCells(localization.radar_invisible, 1, '', cells) end - if ud.needGeo then - cells[#cells+1] = 'Requires thermal vent to build' - cells[#cells+1] = '' + if ud.selfDCountdown <= 1 then + AddEntryToCells(localization.instant_selfd, 1, '', cells) end local mexMult = tonumber(cp.metal_extractor_mult) @@ -1322,23 +1887,42 @@ local function printAbilities(ud, unitID, isCommander) cells[#cells+1] = '' end end - - if cp.fireproof then - cells[#cells+1] = 'Immunity to afterburn' - cells[#cells+1] = '' + if ud.needGeo then + AddEntryToCells(localization.requires_geo, 1, '', cells) end - if ud.metalStorage > 0 then - cells[#cells+1] = 'Stores metal: ' - cells[#cells+1] = ud.metalStorage .. " M" + if cp.ismex then + AddEntryToCells(localization.extracts_metal, 1, '', cells) + AddEntryToCells(localization.shared_to_team, 2, '', cells) + end + local isFireproof + if not unitID then + isFireproof = cp.fireproof + elseif isFeature then + isFireproof = Spring.GetFeatureRulesParam(unitID, "fireproof") or cp.fireproof + else + isFireproof = Spring.GetUnitRulesParam(unitID, "fireproof") or cp.fireproof end - if ud.energyStorage > 0 then - cells[#cells+1] = 'Stores energy: ' - cells[#cells+1] = ud.energyStorage .. " E" + if isFireproof then + AddEntryToCells(localization.fireproof, 1, '', cells) + end + if cp.singuimmune then + AddEntryToCells(localization.gravitronic_regulation, 1, '', cells) + end + local storageoverride = ud.metalStorage + if unitID then + if isFeature then + storageoverride = Spring.GetFeatureRulesParam(unitID, "commander_storage_override") or ud.metalStorage + else + storageoverride = Spring.GetUnitRulesParam(unitID, "commander_storage_override") or ud.metalStorage + end + end + if storageoverride > 0 then + AddEntryToCells(localization.storage .. ':', 1, math.max(storageoverride, ud.metalStorage), cells) end - if (#cells > 2 and cells[#cells-1] == '') then + if (#cells > 2 and cells[#cells-1] == '') then -- clean up last entry cells[#cells] = nil cells[#cells] = nil end @@ -1346,21 +1930,31 @@ local function printAbilities(ud, unitID, isCommander) return cells end -local function printWeapons(unitDef, unitID, isCommander) +local function printWeapons(unitDef, unitID, isFeature) local weaponStats = {} local wd = WeaponDefs - if not wd then - return false - end + if not wd then return false end local ucp = unitDef.customParams - for i = 1, #unitDef.weapons do - if not isCommander or -- filter out commander weapons not in current loadout - ( i == Spring.GetUnitRulesParam(unitID, "comm_weapon_num_1") - or i == Spring.GetUnitRulesParam(unitID, "comm_weapon_num_2") - or i == Spring.GetUnitRulesParam(unitID, "comm_shield_num")) then + local commweapon1, commweapon2, commshield + if unitID then + if isFeature then + commweapon1 = Spring.GetFeatureRulesParam(unitID, "comm_weapon_num_1") + commweapon2 = Spring.GetFeatureRulesParam(unitID, "comm_weapon_num_2") + commshield = Spring.GetFeatureRulesParam(unitID, "comm_shield_num") + else + commweapon1 = Spring.GetUnitRulesParam(unitID, "comm_weapon_num_1") + commweapon2 = Spring.GetUnitRulesParam(unitID, "comm_weapon_num_2") + commshield = Spring.GetUnitRulesParam(unitID, "comm_shield_num") + end + end + for i=1, #unitDef.weapons do + if not unitID or -- filter out commander weapons not in current loadout + ( i == commweapon1 + or i == commweapon2 + or i == commshield) then local weapon = unitDef.weapons[i] local weaponID = weapon.weaponDef local weaponDef = WeaponDefs[weaponID] @@ -1387,6 +1981,7 @@ local function printWeapons(unitDef, unitID, isCommander) local wsTemp = { weaponID = weaponID, count = 1, + weaponNum = i, -- stuff that the weapon gets from the owner unit aa_only = aa_only, @@ -1398,7 +1993,7 @@ local function printWeapons(unitDef, unitID, isCommander) } -- dual wielding comms - if (unitID and i == Spring.GetUnitRulesParam(unitID, "comm_weapon_id_1") and i == Spring.GetUnitRulesParam(unitID, "comm_weapon_id_2")) then + if (unitID and i == commweapon1 and i == commweapon2) then wsTemp.count = 2 end weaponStats[#weaponStats+1] = wsTemp @@ -1414,7 +2009,7 @@ local function printWeapons(unitDef, unitID, isCommander) cells[#cells+1] = '' cells[#cells+1] = '' end - cells = weapons2Table(cells, ws, unitID) + cells = weapons2Table(cells, ws, unitID, false, {}, false, unitDef.metalCost, isFeature, 0, ws.weaponNum) --end end @@ -1434,59 +2029,75 @@ local slopeTolerances = { -- returns the string, plus optionally the slope if it makes sense to show local function GetMoveType(ud) if ud.isImmobile then - return "Immobile" + return localization.movetype_immobile elseif ud.isStrafingAirUnit then - return "Plane" + return localization.movetype_plane elseif ud.isHoveringAirUnit then - return "Gunship" + return localization.movetype_gunship end local md = ud.moveDef if md.isSubmarine then - return "Submarine" + return localization.movetype_sub end - + local smClass = Game.speedModClasses - if md.smClass == smClass.Ship then - return "Ship" + if md.smClass == smClass.Ship then -- TODO: Better implementation for FW subfac eventually. + return localization.movetype_ship end local slope = slopeDegrees(md.maxSlope) if md.smClass == smClass.Hover then if slope == slopeTolerances.BOT then -- chickens can walk on water! - return "Waterwalker", slope + return localization.movetype_waterwalker, slope else - return "Hovercraft", slope + return localization.movetype_hover, slope end elseif md.depth > 1337 then - return "Amphibious", slope + return localization.movetype_amph, slope elseif slope == slopeTolerances.SPIDER then - return "All-terrain", slope + return localization.movetype_spider, slope elseif md.smClass == smClass.KBot then -- "bot" would sound weird for a chicken, but -- all seem to be either amphs or waterwalkers - return "Bot", slope + return localization.movetype_bot, slope else - return "Vehicle", slope + return localization.movetype_veh, slope end end + + local function GetWeapon(weaponName) return WeaponDefNames[weaponName] end -local function GetUnitMaxHealth(unitID, ud) - if unitID then - local _, maxHealth = Spring.GetUnitHealth(unitID) - if maxHealth then - return maxHealth - end +local function AddEmptyEntry(statschildren) + statschildren[#statschildren + 1] = Label:New{ caption = '', textColor = color.stats_fg, } + statschildren[#statschildren + 1] = Label:New{ caption = '', textColor = color.stats_fg, } +end + +local function AddEntry(text, layer, entry, color, colorentry, statschildren) + if text == nil then + text = '' + end + if layer == nil then + layer = 0 + end + if layer > 0 then + text = string.rep("\t\t", layer) .. text + end + statschildren[#statschildren + 1] = Label:New{ caption = text, textColor = color, } + if entry == nil then + statschildren[#statschildren + 1] = Label:New{ caption = '', textColor = color, } + else + statschildren[#statschildren + 1] = Label:New{ caption = entry, textColor = colorentry, } end - return ud.health end -local function printunitinfo(ud, buttonWidth, unitID) +local function printunitinfo(ud, buttonWidth, unitID, isFeature) + local cp = ud.customParams local icons = { Image:New{ file2 = (WG.GetBuildIconFrame)and(WG.GetBuildIconFrame(ud)), @@ -1515,7 +2126,7 @@ local function printunitinfo(ud, buttonWidth, unitID) right = 2, y = 88*(4/5), height = 30, - caption = "Edit Behaviour", + caption = localization.edit_behavior, tooltip = "Edit the default behaviour of " .. Spring.Utilities.GetHumanName(ud) .. ".", OnClick = {function () WG.crude.OpenPathToLabel(behaviourPath[ud.id], true, Spring.Utilities.GetHumanName(ud)) @@ -1533,86 +2144,126 @@ local function printunitinfo(ud, buttonWidth, unitID) } local statschildren = {} + + local isCommander + if isFeature then + isCommander = unitID and Spring.GetFeatureRulesParam(unitID, "comm_level") + else + isCommander = (unitID and Spring.GetUnitRulesParam(unitID, "comm_level")) + end - local isCommander = (unitID and Spring.GetUnitRulesParam(unitID, "comm_level")) - - local cost = numformat(Spring.Utilities.GetUnitCost(unitID, ud.id)) - local health = numformat(GetUnitMaxHealth(unitID, ud)) - local speed = numformat(ud.speed * (unitID and Spring.GetUnitRulesParam(unitID, "totalStaticMoveSpeedChange") or 1), true) -- Speeds often have 0.5s + local cost = numformat(ud.metalCost) + local health = numformat(ud.health) + local rawhealth = ud.health + local speed = numformat(ud.speed) local mass = numformat(ud.mass) -- stuff for modular commanders local legacyModules, legacyCommCost - if ud.customParams.commtype and not isCommander then -- old style pregenerated commander (still used in missions etc.) + if ud.customParams.commtype and not isCommander then -- old style pregenerated commander (still used in missions etc.) legacyModules = WG.ModularCommAPI and WG.ModularCommAPI.GetLegacyModulesForComm(ud.id) legacyCommCost = ud.customParams.cost -- or (WG.GetCommUnitInfo and WG.GetCommUnitInfo(ud.id) and WG.GetCommUnitInfo(ud.id).cost) end -- dynamic comms get special treatment if isCommander then - cost = Spring.GetUnitRulesParam(unitID, "comm_cost") or 1200 - health = select(2, Spring.GetUnitHealth(unitID)) - speed = numformat(ud.speed * (Spring.GetUnitRulesParam(unitID, "upgradesSpeedMult") or 1), true) -- Show a decimal place for comms due to fractional speed modules - mass = numformat(Spring.GetUnitRulesParam(unitID, "massOverride") or ud.mass) - - statschildren[#statschildren+1] = Label:New{ caption = "COMMANDER", textColor = color.stats_header, } - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header, } - statschildren[#statschildren+1] = Label:New{ caption = 'Level: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = Spring.GetUnitRulesParam(unitID, "comm_level")+1, textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = 'Chassis: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = chassisDefs[Spring.GetUnitRulesParam(unitID, "comm_chassis")].humanName, textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - - statschildren[#statschildren+1] = Label:New{ caption = 'MODULES', textColor = color.stats_header, } - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header, } - - local modules = Spring.GetUnitRulesParam(unitID, "comm_module_count") - - if modules > 0 then - local module_instances = {} - for i = 1, modules do - local moduleID = Spring.GetUnitRulesParam(unitID, "comm_module_" .. i) - module_instances[moduleID] = (module_instances[moduleID] or 0) + 1 + local level, chassisID, speedMult + if isFeature then + cost = Spring.GetFeatureRulesParam(unitID, "comm_cost") or 1200 + health = select(2, Spring.GetFeatureHealth(unitID)) + rawhealth = health + health = numformat(health) + speedMult = Spring.GetFeatureRulesParam(unitID, "upgradesSpeedMult") or 1 + mass = numformat(Spring.GetFeatureRulesParam(unitID, "massOverride") or ud.mass) + level = Spring.GetFeatureRulesParam(unitID, "comm_level") or 0 + chassisID = Spring.GetFeatureRulesParam(unitID, "comm_chassis") + else + cost = Spring.GetUnitRulesParam(unitID, "comm_cost") or 1200 + health = select(2, Spring.GetUnitHealth(unitID)) + rawhealth = health + health = numformat(health) + speedMult = Spring.GetUnitRulesParam(unitID, "upgradesSpeedMult") or 1 + mass = numformat(Spring.GetUnitRulesParam(unitID, "massOverride") or ud.mass) + level = Spring.GetUnitRulesParam(unitID, "comm_level") or 0 + chassisID = Spring.GetUnitRulesParam(unitID, "comm_chassis") + end + speed = numformat(ud.speed * speedMult) + + + AddEntry(string.upper(localizationCommon.commander), 0, nil, color.stats_header, nil, statschildren) + AddEntry(localization.level .. ': ', 1, level + 1, color.stats_fg, color.stats_fg, statschildren) + AddEntry(localization.chassis .. ': ', 1, chassisDefs[chassisID].humanName, color.stats_fg, color.stats_fg, statschildren) + AddEmptyEntry(statschildren) + AddEntry(localization.modules, 0, nil, color.stats_header, nil, statschildren) + if isFeature then + local modules = Spring.GetFeatureRulesParam(unitID, "comm_module_count") + + if modules > 0 then -- TODO: Localization + local module_instances = {} + for i = 1, modules do + local moduleID = Spring.GetFeatureRulesParam(unitID, "comm_module_" .. i) + if moduleID ~= nil then + module_instances[moduleID] = (module_instances[moduleID] or 0) + 1 + end + end + for moduleID, moduleCount in pairs(module_instances) do + local moduleStr = moduleDefs[moduleID].humanName + if moduleCount > 1 then moduleStr = moduleStr .. " x" .. moduleCount end + AddEntry(moduleStr, 1, nil, color.stats_fg, nil, statschildren) + end end - for moduleID, moduleCount in pairs(module_instances) do - local moduleStr = moduleDefs[moduleID].humanName - if moduleCount > 1 then moduleStr = moduleStr .. " x" .. moduleCount end - statschildren[#statschildren+1] = Label:New{ caption = moduleStr, textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_fg, } + else + local modules = Spring.GetUnitRulesParam(unitID, "comm_module_count") + + if modules > 0 then + local module_instances = {} + for i = 1, modules do + local moduleID = Spring.GetUnitRulesParam(unitID, "comm_module_" .. i) + module_instances[moduleID] = (module_instances[moduleID] or 0) + 1 + end + for moduleID, moduleCount in pairs(module_instances) do + local moduleStr = moduleDefs[moduleID].humanName + if moduleCount > 1 then moduleStr = moduleStr .. " x" .. moduleCount end + AddEntry(moduleStr, 1, nil, color.stats_fg, nil, statschildren) + end end end - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} + AddEmptyEntry(statschildren) + end + if legacyModules then + AddEmptyEntry(statschildren) + AddEntry(localization.modules, 0, nil, color.stats_header, nil, statschildren) + for i=1, #legacyModules do + AddEntry(legacyModules[i], 1, nil, color.stats_fg, nil, statschildren) + end end - local costStr = cost .. " M" + local costStr = cost .. " " .. localizationCommon.metal if (legacyCommCost) then - costStr = costStr .. "(" .. legacyCommCost .. " M)" + costStr = costStr .. "(" .. legacyCommCost .. " " .. localizationCommon.metal .. ")" end - statschildren[#statschildren+1] = Label:New{ caption = 'STATS', textColor = color.stats_header, } - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header, } - - statschildren[#statschildren+1] = Label:New{ caption = 'Cost: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = costStr, textColor = color.stats_fg, } - - statschildren[#statschildren+1] = Label:New{ caption = 'Health: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = health, textColor = color.stats_fg, } - - statschildren[#statschildren+1] = Label:New{ caption = 'Mass: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = mass, textColor = color.stats_fg, } - + AddEntry(localization.stats, 0, nil, color.stats_header, nil, statschildren) + AddEntry(localization.cost .. ": ", 1, costStr, color.stats_fg, color.stats_fg, statschildren) + AddEntry(localizationCommon.health .. ":", 1, health, color.stats_fg, color.stats_fg, statschildren) + if ud.metalCost > 0 then + AddEntry(localizationCommon.health .. "/" .. localization.cost .. ':', 1, string.format("%.2f", rawhealth / cost), color.stats_fg, color.stats_fg, statschildren) + end + AddEntry(localization.mass .. ":", 1, mass, color.stats_fg, color.stats_fg, statschildren) if not ud.isImmobile then - statschildren[#statschildren+1] = Label:New{ caption = 'Speed: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = speed .. " elmo/s", textColor = color.stats_fg, } + if cp.cloakstrikespeed then + local speedup = tonumber(cp.cloakstrikespeed) + local slowdown = tonumber(cp.cloakstrikeslow) + AddEntry(localization.cloaked_speed .. ":", 1, speed * speedup .. "elmo/" .. localization.acronyms_second, color.stats_fg, color.stats_fg, statschildren) + AddEntry(localization.decloaked_speed .. ":", 1, speed * slowdown .. "elmo/" .. localization.acronyms_second, color.stats_fg, color.stats_fg, statschildren) + else + AddEntry(localization.speed .. ":", 1, speed .. "elmo/" .. localization.acronyms_second, color.stats_fg, color.stats_fg, statschildren) + end local mt, slope = GetMoveType(ud) - statschildren[#statschildren+1] = Label:New{ caption = 'Movement: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = mt, textColor = color.stats_fg, } + AddEntry(localization.movement .. ":", 1, mt, color.stats_fg, color.stats_fg, statschildren) if slope then - statschildren[#statschildren+1] = Label:New{ caption = 'Climbs: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = slope .. " deg", textColor = color.stats_fg, } + AddEntry(localization.climbs .. ":", 1, slope .. "°", color.stats_fg, color.stats_fg, statschildren) end end @@ -1621,127 +2272,227 @@ local function printunitinfo(ud, buttonWidth, unitID) if (ud.maxAcc) > 0 then statschildren[#statschildren+1] = Label:New{ caption = 'Acceleration: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(ud.maxAcc * gameSpeed2) .. " elmo/s^2", textColor = color.stats_fg, } + statschildren[#statschildren+1] = Label:New{ caption = numformat(ud.maxAcc * gameSpeed2) .. " elmo/s², textColor = color.stats_fg, } end if (ud.maxDec) > 0 then statschildren[#statschildren+1] = Label:New{ caption = 'Brake rate: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(ud.maxDec * gameSpeed2) .. " elmo/s^2", textColor = color.stats_fg, } + statschildren[#statschildren+1] = Label:New{ caption = numformat(ud.maxDec * gameSpeed2) .. " elmo/s²", textColor = color.stats_fg, } end ]] local COB_angle_to_degree = 360 / 65536 if ud.turnRate > 0 then - statschildren[#statschildren+1] = Label:New{ caption = 'Turn rate: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(ud.turnRate * Game.gameSpeed * COB_angle_to_degree) .. " deg/s", textColor = color.stats_fg, } + AddEntry(localization.turn_rate .. ":", 1, numformat(ud.turnRate * Game.gameSpeed * COB_angle_to_degree) .. "°/" .. localization.acronyms_second, color.stats_fg, color.stats_fg, statschildren) + end + local metal, energy + if isCommander and unitID then + if isFeature then + metal = Spring.GetFeatureRulesParam(unitID, "wanted_metalIncome") or 0 + energy = Spring.GetFeatureRulesParam(unitID, "wanted_energyIncome") or 0 + else + metal = Spring.GetUnitRulesParam(unitID, "wanted_metalIncome") or 0 + energy = Spring.GetUnitRulesParam(unitID, "wanted_energyIncome") or 0 + end + else + metal = (ud.metalMake or 0) + (ud.customParams.income_metal or 0) + energy = (ud.energyMake or 0) - (ud.customParams.upkeep_energy or 0) + (ud.customParams.income_energy or 0) end - - local metal = (isCommander and (Spring.GetUnitRulesParam(unitID, "wanted_metalIncome") or 0) or ((ud.metalMake or 0) + (ud.customParams.income_metal or 0))) if metal ~= 0 then - local mult = (unitID and Spring.GetUnitRulesParam(unitID, "totalStaticMetalMult") or 1) - statschildren[#statschildren+1] = Label:New{ caption = 'Metal: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = (metal > 0 and '+' or '') .. numformat(metal * mult) .. " M/s", textColor = color.stats_fg, } + AddEntry(localization.metal_income .. ":", 1, (metal > 0 and '+' or '') .. numformat(metal,2) .. " /" .. localization.acronyms_second, color.stats_fg, color.stats_fg, statschildren) end - - local energy = (isCommander and (Spring.GetUnitRulesParam(unitID, "wanted_energyIncome") or 0) or ((ud.energyMake or 0) - (ud.customParams.upkeep_energy or 0) + (ud.customParams.income_energy or 0))) if energy ~= 0 then - local mult = (unitID and Spring.GetUnitRulesParam(unitID, "totalStaticEnergyMult") or 1) - statschildren[#statschildren+1] = Label:New{ caption = 'Energy: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = (energy > 0 and '+' or '') .. numformat(energy * mult) .. " E/s", textColor = color.stats_fg, } + if ud.customParams and ud.customParams["decay_rate"] then + energy = energy * (tonumber(ud.customParams["decay_initialrate"]) or 10) + end + AddEntry(localization.energy_income .. ":", 1, (energy > 0 and '+' or '') .. numformat(energy,2) .. " /" .. localization.acronyms_second, color.stats_fg, color.stats_fg, statschildren) + if ud.customParams and ud.customParams["decay_rate"] then + local baseoutput = ud.customParams.income_energy + local startperc = tonumber(ud.customParams["decay_initialrate"]) + local decayperc = tonumber(ud.customParams["decay_rate"]) + local decayrate = decayperc * 100 + local mindecay = tonumber(ud.customParams["decay_minoutput"]) or 0 + local decaytime = tonumber(ud.customParams["decay_time"]) or 1 + local txt = "" + local timetoreach = 0 + if decayrate < 0 then + txt = localization.output_compounds .. ":" + else + txt = localization.output_decays ..":" + end + AddEntry(txt, 1, nil, color.stats_fg, nil, statschildren) + local endperc + local decays + if decayrate > 0 then + AddEntry(localization.rate .. ":", 2, numformat(decayrate, 1) .. "%/" .. numformat(decaytime, 1) .. localization.acronyms_second, color.stats_fg, color.stats_fg, statschildren) + txt = localization.min_output .. ":" + endperc = mindecay + mindecay = mindecay * baseoutput + decays = true + else + AddEntry(localization.rate .. ":", 2, numformat(-decayrate, 1) .. "%/" .. numformat(decaytime, 1) .. localization.acronyms_second, color.stats_fg, color.stats_fg, statschildren) + txt = localization.max_output .. ":" + mindecay = tonumber(ud.customParams["decay_maxoutput"]) or 0 + endperc = mindecay + mindecay = mindecay * baseoutput + decays = false + end + local sim = startperc + while sim ~= endperc do + timetoreach = timetoreach + decaytime + if decayrate < 0 then + sim = math.min(sim * (1 - decayperc), endperc) + else + sim = math.max(sim * (1 - decayperc), endperc) + end + end + local mm = math.floor(timetoreach / 60) + local ss = timetoreach%60 + timetoreach = string.format("%02d:%02d", mm, ss) + decayrate = math.abs(decayrate) + AddEntry(txt, 2, numformat(mindecay, 1), color.stats_fg, color.stats_fg, statschildren) + AddEntry(localization.time_to_reach .. ":", 2, timetoreach, color.stats_fg, color.stats_fg, statschildren) + end + end + do + --[[local sonar + if unitID then + sonar = Spring.GetUnitRulesParam(unitID, "sonarRangeOverride") or ud.sonarRadius + else + sonar = ud.sonarRadius + end + if sonar > 0 then + statschildren[#statschildren+1] = Label:New{ caption = 'Sonar: ', textColor = color.stats_fg, } + statschildren[#statschildren+1] = Label:New{ caption = numformat(sonar) .. " elmo", textColor = color.stats_fg, } + end]] -- Irrelevant because Sonar is dead. Add back for basegame. + local sight + if unitID then + if isFeature then + sight = Spring.GetFeatureRulesParam(unitID, "sightRangeOverride") or ud.losRadius + else + sight = Spring.GetUnitRulesParam(unitID, "sightRangeOverride") or ud.losRadius + end + else + sight = ud.losRadius + end + AddEntry(localization.sight_range .. ":", 1, numformat(sight) .. " elmo", color.stats_fg, color.stats_fg, statschildren) end - local senseMult = (unitID and Spring.GetUnitRulesParam(unitID, "senseMult") or 1) - if ud.sightDistance > 0 then - statschildren[#statschildren+1] = Label:New{ caption = 'Sight: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(ud.sightDistance * senseMult) .. " elmo", textColor = color.stats_fg, } - end - - if (ud.sonarDistance > 0) then - statschildren[#statschildren+1] = Label:New{ caption = 'Sonar: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(ud.sonarDistance * senseMult) .. " elmo", textColor = color.stats_fg, } - end - if ud.cruiseAltitude > 0 then - statschildren[#statschildren+1] = Label:New{ caption = 'Altitude: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(ud.cruiseAltitude * 1.5) .. " elmo", textColor = color.stats_fg, } + if ud.wantedHeight > 0 then + AddEntry(localization.altitude .. ':', 1, numformat(ud.wantedHeight) .. " elmo", color.stats_fg, color.stats_fg, statschildren) end if ud.customParams.pylonrange then - statschildren[#statschildren+1] = Label:New{ caption = 'Grid link range: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(ud.customParams.pylonrange) .. " elmo", textColor = color.stats_fg, } + AddEntry(localization.grid_link .. ':', 1, numformat(ud.customParams.pylonrange) .. " elmo", color.stats_fg, color.stats_fg, statschildren) end - - if ud.customParams.heat_per_shot then - statschildren[#statschildren+1] = Label:New{ caption = 'Heat Per Shot: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(ud.customParams.heat_per_shot*100) .. "%", textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = 'Heat Decay: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(ud.customParams.heat_decay*100) .. "%/s", textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = 'Heat Max Slow: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(ud.customParams.heat_max_slow*100) .. "%", textColor = color.stats_fg, } + if ud.customParams.neededlink then + AddEntry(localization.grid_needed .. ":", 1, numformat(ud.customParams.neededlink) .. " " .. localizationCommon.energy, color.stats_fg, color.stats_fg, statschildren) end -- transportability by light or heavy airtrans if not (ud.canFly or ud.cantBeTransported) then - statschildren[#statschildren+1] = Label:New{ caption = 'Transportable: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = ((ud.customParams.requireheavytrans and "Heavy") or (ud.customParams.requiremediumtrans and "Medium") or "Light"), textColor = color.stats_fg, } + AddEntry(localization.can_be_transported .. ":", 1, ((ud.customParams.requireheavytrans and localization.transport_heavy) or localization.transport_light), color.stats_fg, color.stats_fg, statschildren) + end + local name = ud.name + + local function fillOutDroneData(tab, maxDrones, droneBuildSpeed, reloadMult, dronerange) + local name = Spring.Utilities.GetHumanName(UnitDefs[tab.drone]) + AddEntry(name .. " x" .. (maxDrones or tab.maxDrones), 2, nil, color.stats_header, nil, statschildren) + AddEntry(localization.drone_build_time .. ":", 3, numformat(tab.buildTime / droneBuildSpeed, 1) .. localization.acronyms_second, color.stats_fg, color.stats_fg, statschildren) + AddEntry(localization.cooldown .. ":", 3, numformat(tab.reloadTime / reloadMult, 1) .. localization.acronyms_second, color.stats_fg, color.stats_fg, statschildren) + AddEntry(localization.drones_per_cycle .. ":", 3, tab.spawnSize, color.stats_fg, color.stats_fg, statschildren) + local range, maxRange = tab.range*dronerange, tab.maxChaseRange*dronerange + if range >= 100000 then + AddEntry(localization.drone_verybigrange, 3, 10, color.stats_fg, color.stats_fg, statschildren) + else + AddEntry(localization.drone_target_range .. ":", 3, numformat(range, 0), color.stats_fg, color.stats_fg, statschildren) + AddEntry(localization.drone_max_range .. ":", 3, numformat(maxRange, 0), color.stats_fg, color.stats_fg, statschildren) + end + if tab.controllable then + AddEntry(localization.drone_controllable, 3, 10, color.stats_fg, color.stats_fg, statschildren) + end end - + if isCommander then - local batDrones = Spring.GetUnitRulesParam(unitID, "carrier_count_droneheavyslow") - if batDrones and batDrones > 0 then - statschildren[#statschildren+1] = Label:New{ caption = 'Battle Drones: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = batDrones, textColor = color.stats_fg, } + local batDrones, compDrones, droneSlots, droneBuildSpeed, assaultDrones, repairDrones, dronerange, dronemax, reloadMult + if isFeature then + batDrones = Spring.GetFeatureRulesParam(unitID, "carrier_count_droneheavyslow") + compDrones = Spring.GetFeatureRulesParam(unitID, "carrier_count_drone") + droneBuildSpeed = Spring.GetFeatureRulesParam(unitID, "comm_drone_buildrate") or 1 + droneSlots = Spring.GetFeatureRulesParam(unitID, "comm_extra_drones") or 1 + repairDrones = Spring.GetFeatureRulesParam(unitID, "carrier_count_dronecon") + assaultDrones = Spring.GetFeatureRulesParam(unitID, "carrier_count_droneassault") + dronerange = 600 * (Spring.GetFeatureRulesParam(unitID, "comm_drone_range") or 1) + dronemax = 1250 * (Spring.GetFeatureRulesParam(unitID, "comm_drone_range") or 1) + reloadMult = Spring.GetFeatureRulesParam(unitID, "comm_drone_rebuildrate") or 1 + else + batDrones = Spring.GetUnitRulesParam(unitID, "carrier_count_droneheavyslow") + compDrones = Spring.GetUnitRulesParam(unitID, "carrier_count_drone") + droneSlots = Spring.GetUnitRulesParam(unitID, "comm_extra_drones") or 1 + repairDrones = Spring.GetUnitRulesParam(unitID, "carrier_count_dronecon") + assaultDrones = Spring.GetUnitRulesParam(unitID, "carrier_count_droneassault") + dronemax = 1250 * (Spring.GetUnitRulesParam(unitID, "comm_drone_range") or 1) + dronerange = 600 * (Spring.GetUnitRulesParam(unitID, "comm_drone_range") or 1) + droneBuildSpeed = Spring.GetUnitRulesParam(unitID, "comm_drone_buildrate") or 1 + reloadMult = Spring.GetUnitRulesParam(unitID, "comm_drone_rebuildrate") or 1 + end + local hasDrones = false + if (batDrones and batDrones > 0) or (compDrones and compDrones > 0) or (assaultDrones and assaultDrones > 0) or (repairDrones and repairDrones > 0) then + hasDrones = true + AddEmptyEntry(statschildren) + AddEntry(string.upper(localization.drone_carrier), 0, nil, color.stats_header, nil, statschildren) + AddEntry(localization.drone_buildslots .. ":", 1, droneSlots, color.stats_fg, color.stats_fg, statschildren) + AddEntry(localization.drone_production_speed .. ':', 1, numformat(100*droneBuildSpeed, 2) .. "%", color.stats_fg, color.stats_fg, statschildren) + AddEmptyEntry(statschildren) + AddEntry(localization.drone_label .. ":", 1, nil, color.stats_header, nil, statschildren) + if assaultDrones and assaultDrones > 0 then + fillOutDroneData(commanderDroneDefs["droneassault"], assaultDrones, droneBuildSpeed, reloadMult, dronerange) + end + if compDrones and compDrones > 0 then + fillOutDroneData(commanderDroneDefs["drone"], compDrones, droneBuildSpeed, reloadMult, dronerange) + end + if batDrones and batDrones > 0 then + fillOutDroneData(commanderDroneDefs["droneheavyslow"], batDrones, droneBuildSpeed, reloadMult, dronerange) + end + if repairDrones and repairDrones > 0 then + fillOutDroneData(commanderDroneDefs["dronecon"], repairDrones, droneBuildSpeed, reloadMult, dronerange) + end end - local compDrones = Spring.GetUnitRulesParam(unitID, "carrier_count_drone") - if compDrones and compDrones > 0 then - statschildren[#statschildren+1] = Label:New{ caption = 'Companion Drones: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = compDrones, textColor = color.stats_fg, } + elseif carrierDefs[name] then + AddEmptyEntry(statschildren) + AddEntry(string.upper(localization.drone_carrier), 0, nil, color.stats_header, nil, statschildren) + local carrierDef = carrierDefs[name] + AddEntry(localization.drone_buildslots .. ":", 1, #carrierDef.spawnPieces, color.stats_fg, color.stats_fg, statschildren) + AddEmptyEntry(statschildren) + AddEntry(localization.drone_label .. ":", 1, nil, color.stats_header, nil, statschildren) + for i = 1, #carrierDef do + local tab = carrierDef[i] + fillOutDroneData(tab, nil, 1, 1, 1) end - -- else - -- Do something for Reef and other carriers end - if ud.customParams.reload_move_penalty then - statschildren[#statschildren+1] = Label:New{ caption = 'Reload move mult: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(100*tonumber(ud.customParams.reload_move_penalty)) .. "%", textColor = color.stats_fg, } - end - - if legacyModules then - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = 'MODULES', textColor = color.stats_header, } - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - for i=1, #legacyModules do - statschildren[#statschildren+1] = Label:New{ caption = legacyModules[i], textColor = color.stats_fg,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_fg,} - end + AddEntry(localization.speed_while_reloading .. ":", 1, numformat(100*tonumber(ud.customParams.reload_move_penalty)) .. "%", color.stats_fg, color.stats_fg, statschildren) end - local cells = printAbilities(ud, unitID, isCommander) + local cells = printAbilities(ud, isCommander and unitID, isFeature) - if cells and #cells > 0 then - - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - - statschildren[#statschildren+1] = Label:New{ caption = 'ABILITIES', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - for i=1, #cells do - statschildren[#statschildren+1] = Label:New{ caption = cells[i], textColor = color.stats_fg, } + if cells and #cells > 2 then + AddEmptyEntry(statschildren) + AddEntry(localization.abilities, 0, nil, color.stats_header, nil, statschildren) + for i=2, #cells, 2 do + AddEntry(cells[i - 1], 1, cells[i], color.stats_fg, color.stats_fg, statschildren) end end - cells = printWeapons(ud, unitID, isCommander) + cells = printWeapons(ud, isCommander and unitID, isFeature) + if cells and #cells > 0 then - - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - - statschildren[#statschildren+1] = Label:New{ caption = 'WEAPONS', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - for i=1, #cells do - statschildren[#statschildren+1] = Label:New{ caption = cells[i], textColor = color.stats_fg, } + AddEmptyEntry(statschildren) + AddEntry(localization.weapons, 0, nil, color.stats_header, nil, statschildren) + for i = 2, #cells, 2 do + AddEntry(cells[i - 1], 1, cells[i], color.stats_fg, color.stats_fg, statschildren) end end @@ -1749,64 +2500,48 @@ local function printunitinfo(ud, buttonWidth, unitID) local default_buildlist = UnitDefNames["shieldcon"].buildOptions local this_buildlist = ud.buildOptions if ((#this_buildlist ~= #default_buildlist) and (#this_buildlist > 0)) then - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - - statschildren[#statschildren+1] = Label:New{ caption = 'BUILDS', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} + AddEmptyEntry(statschildren) + AddEntry(localization.builds, 0, nil, color.stats_header, nil, statschildren) for i=1, #this_buildlist do - statschildren[#statschildren+1] = Label:New{ caption = Spring.Utilities.GetHumanName(UnitDefs[this_buildlist[i]]), textColor = color.stats_fg, } + AddEntry(Spring.Utilities.GetHumanName(UnitDefs[this_buildlist[i]]), 1, nil, color.stats_fg, nil, statschildren) -- desc. would be nice, but there is horizontal cutoff -- and long names can overlap (eg. Adv Radar) -- statschildren[#statschildren+1] = Label:New{ caption = UnitDefs[this_buildlist[i]].tooltip, textColor = colorDisarm,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = colorDisarm,} end end -- death explosion if ud.canKamikaze or ud.customParams.stats_show_death_explosion then - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = 'Death Explosion', textColor = color.stats_header,} - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_fg, } - - local expMult = unitID and Spring.GetUnitRulesParam(unitID, "deathExplodeMult") or 1 - expMult = math.max(1, math.floor(expMult - 0.5) + 1) -- Attributes only supports integer mults at this point. - - local weaponName = ud.customParams.stats_detonate_weapon or ud.deathExplosion:lower() - local weaponStats = GetWeapon( weaponName ) + AddEmptyEntry(statschildren) + AddEntry(string.upper(localization.death_explosion), 0, nil, color.stats_header, color.stats_fg, statschildren) + + --[[ + local weaponStats = GetWeapon( ud.deathExplosion:lower() ) local wepCp = weaponStats.customParams - local damageValue = tonumber(weaponStats.customParams.stats_damage) * expMult + local damageValue = tonumber(weaponStats.customParams.stats_damage) statschildren[#statschildren+1] = Label:New{ caption = 'Damage: ', textColor = color.stats_fg, } if (weaponStats.paralyzer) then - statschildren[#statschildren+1] = Label:New{ caption = numformat(damageValue) .. " (P)", textColor = colorCyan, } + statschildren[#statschildren+1] = Label:New{ caption = numformat(damageValue,2) .. " (P)", textColor = colorCyan, } statschildren[#statschildren+1] = Label:New{ caption = 'Max EMP time: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(weaponStats.damages.paralyzeDamageTime) .. "s", textColor = color.stats_fg, } + statschildren[#statschildren+1] = Label:New{ caption = numformat(weaponStats.damages.paralyzeDamageTime,2) .. "s", textColor = color.stats_fg, } else local damageSlow = (wepCp.timeslow_damagefactor or 0)*damageValue local damageText if damageSlow > 0 then if wepCp.timeslow_onlyslow == "1" then - damageText = color2incolor(colorPurple) .. numformat(damageSlow) .. " (S)\008" + damageText = color2incolor(colorPurple) .. numformat(damageSlow,2) .. " (S)\008" else - damageText = numformat(damageValue) .. " + " .. color2incolor(colorPurple) .. numformat(damageSlow) .. " (S)\008" + damageText = numformat(damageValue,2) .. " + " .. color2incolor(colorPurple) .. numformat(damageSlow,2) .. " (S)\008" end else - damageText = numformat(damageValue) + damageText = numformat(damageValue,2) end statschildren[#statschildren+1] = Label:New{ caption = damageText, textColor = color.stats_fg, } end - local radius = weaponStats.damageAreaOfEffect - if expMult > 1 then - local maxRadius = radius - local expLevel = 1 + math.log(expMult) / math.log(2) - local maxRadius = (5 + 15*expLevel)*(50 + math.pow(radius, 0.8))/100 + radius - radius = (radius + maxRadius) / 2 -- Just a rule of thumb - end statschildren[#statschildren+1] = Label:New{ caption = 'AoE radius: ', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = numformat(radius) .. " elmo", textColor = color.stats_fg, } + statschildren[#statschildren+1] = Label:New{ caption = numformat(weaponStats.damageAreaOfEffect,2) .. " elmo", textColor = color.stats_fg, } if (weaponStats.customParams.setunitsonfire) then statschildren[#statschildren+1] = Label:New{ caption = 'Afterburn: ', textColor = color.stats_fg, } @@ -1814,16 +2549,22 @@ local function printunitinfo(ud, buttonWidth, unitID) end -- statschildren[#statschildren+1] = Label:New{ caption = 'Edge Damage: ', textColor = color.stats_fg, } - -- statschildren[#statschildren+1] = Label:New{ caption = numformat(damageValue * weaponStats.edgeEffectiveness), textColor = color.stats_fg, } + -- statschildren[#statschildren+1] = Label:New{ caption = numformat(damageValue * weaponStats.edgeEffectiveness,2), textColor = color.stats_fg, } -- edge damage is always 0, see http://springrts.com/mediawiki/images/1/1c/EdgeEffectiveness.png - + ]]-- + + local cells = weapons2Table({}, ud.deathExplosion:lower(), unitID, 1, {}, true, ud.metalCost) + + if cells and #cells > 0 then + for i=2, #cells, 2 do + AddEntry(cells[i - 1], 1, cells[i], color.stats_fg, color.stats_fg, statschildren) + end + end end --adding this because of annoying cutoff - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_fg, } - statschildren[#statschildren+1] = Label:New{ caption = '', textColor = color.stats_fg, } + AddEmptyEntry(statschildren) + AddEmptyEntry(statschildren) local stack_icons = Chili.Control:New{ @@ -1912,7 +2653,7 @@ local function KillStatsWindow(num) statswindows[num] = nil end -MakeStatsWindow = function(ud, x,y, unitID) +MakeStatsWindow = function(ud, x,y, unitID, isFeature) hideWindow(window_unitcontext) local x = x local y = y @@ -1937,10 +2678,10 @@ MakeStatsWindow = function(ud, x,y, unitID) right = 5, bottom = B_HEIGHT + 10, padding = {2,2,2,2}, - children = printunitinfo(ud, window_width, unitID) , + children = printunitinfo(ud, window_width, unitID, isFeature), }, Button:New{ - caption = 'Close', + caption = localization.menu_close, OnClick = { function(self) KillStatsWindow(num) end }, x=5, @@ -1953,28 +2694,47 @@ MakeStatsWindow = function(ud, x,y, unitID) --classname = "back_button", } } - - statswindows[num] = Window:New{ - x = x, - y = y, - width = WINDOW_WIDTH, - height = options.window_height.value, - resizable = true, - parent = screen0, - backgroundColor = color.stats_bg, - classname = "main_window_small", - - minWidth = 250, - minHeight = 300, - - caption = Spring.Utilities.GetHumanName(ud, unitID) ..' - '.. Spring.Utilities.GetDescription(ud, unitID), - - children = children, - } + if isFeature then + statswindows[num] = Window:New{ + x = x, + y = y, + width = WINDOW_WIDTH, + height = options.window_height.value, + resizable = true, + parent = screen0, + backgroundColor = color.stats_bg, + classname = "main_window_small", + + minWidth = 250, + minHeight = 300, + + caption = Spring.Utilities.GetFeatureName(ud, unitID) ..' - '.. Spring.Utilities.GetFeatureDescription(ud, unitID), + + children = children, + } + else + statswindows[num] = Window:New{ + x = x, + y = y, + width = WINDOW_WIDTH, + height = options.window_height.value, + resizable = true, + parent = screen0, + backgroundColor = color.stats_bg, + classname = "main_window_small", + + minWidth = 250, + minHeight = 300, + + caption = Spring.Utilities.GetHumanName(ud, unitID) ..' - '.. Spring.Utilities.GetDescription(ud, unitID), + + children = children, + } + end AdjustWindow(statswindows[num]) end -local function PriceWindow(unitID, action) +local function PriceWindow(unitID, action) -- Bitrotted? local window_width = 250 local header = 'Offer For Sale' @@ -2075,16 +2835,16 @@ local function MakeUnitContextMenu(unitID,x,y) local playerName = spGetPlayerInfo(player, false) or 'noname' local teamColor = {spGetTeamColor(team)} - local window_width = 200 + local window_width = 350 --local buttonWidth = window_width - 0 local children = { Label:New{ caption = Spring.Utilities.GetHumanName(ud) ..' - '.. Spring.Utilities.GetDescription(ud), width=window_width, textColor = color.context_header,}, - Label:New{ caption = 'Player: ' .. playerName, width=window_width, textColor=teamColor }, - Label:New{ caption = 'Alliance - ' .. alliance .. ' Team - ' .. team, width=window_width ,textColor = color.context_fg,}, + Label:New{ caption = localizationCommon.player .. ': ' .. playerName, width=window_width, textColor=teamColor }, + Label:New{ caption = localization.alliance ..' - ' .. alliance .. ' ' .. localization.team .. ' - ' .. team, width=window_width ,textColor = color.context_fg,}, Button:New{ - caption = 'Unit Info', + caption = localization.unit_info, OnClick = { function() MakeStatsWindow(ud,x,y) end }, width=window_width, --backgroundColor=color.sub_back_bg, @@ -2095,7 +2855,7 @@ local function MakeUnitContextMenu(unitID,x,y) local y = scrH-y local x = x - if marketandbounty then + if marketandbounty then -- NOT LOCALIZED: Bitrot / Removed? if team == myTeamID then children[#children+1] = Button:New{ caption = 'Set Sale Price', @@ -2128,7 +2888,7 @@ local function MakeUnitContextMenu(unitID,x,y) end - if ceasefires and myAlliance ~= alliance then + if ceasefires and myAlliance ~= alliance then -- DITTO. --window_height = window_height + B_HEIGHT*2 --error no such window_height! children[#children+1] = Button:New{ caption = 'Vote for ceasefire', OnClick = { function() spSendLuaRulesMsg('cf:y'..alliance) end }, width=window_width} children[#children+1] = Button:New{ caption = 'Break ceasefire/unvote', OnClick = { function() spSendLuaRulesMsg('cf:n'..alliance) spSendLuaRulesMsg('cf:b'..alliance) end }, width=window_width} @@ -2215,7 +2975,7 @@ function widget:MousePress(x,y,button) local udid = UnitDefs[Spring.GetUnitDefID(unitID)] if udid then - MakeStatsWindow(udid,x,y, unitID) + MakeStatsWindow(udid,x, y, unitID, false) end -- FIXME enable later when does not show useless info return true @@ -2234,7 +2994,7 @@ function widget:MousePress(x,y,button) local ud = UnitDefNames[live_name] if ud then - MakeStatsWindow(ud,x,y) + MakeStatsWindow(ud, x, y, data, true) return true end end @@ -2256,28 +3016,25 @@ end function widget:Initialize() - if (not WG.Chili) then widgetHandler:RemoveWidget(widget) return end - -- setup Chili - Chili = WG.Chili - Button = Chili.Button - Label = Chili.Label - Window = Chili.Window - ScrollPanel = Chili.ScrollPanel - StackPanel = Chili.StackPanel - Grid = Chili.Grid - TextBox = Chili.TextBox - Image = Chili.Image - screen0 = Chili.Screen0 - color2incolor = Chili.color2incolor - + Chili = WG.Chili + Button = Chili.Button + Label = Chili.Label + Window = Chili.Window + ScrollPanel = Chili.ScrollPanel + StackPanel = Chili.StackPanel + Grid = Chili.Grid + TextBox = Chili.TextBox + Image = Chili.Image + screen0 = Chili.Screen0 + color2incolor = Chili.color2incolor widget:ViewResize(Spring.GetViewGeometry()) - WG.MakeStatsWindow = MakeStatsWindow + WG.InitializeTranslation(UpdateLocalization, GetInfo().name) end function widget:Shutdown()