diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index b623093ff1..c4328bde36 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -39,7 +39,7 @@ jobs: cp -a Mindustry/core/build/javadoc/. docs/ cd docs git add . - git commit -m "Update ${RELEASE_VERSION:1}" + git commit --allow-empty -m "Update ${RELEASE_VERSION:1}" git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/MindustryGame/docs cd ../Mindustry - name: Update F-Droid build string diff --git a/android/build.gradle b/android/build.gradle index 5f355a0ec7..d073b66a15 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,6 +7,7 @@ buildscript{ } dependencies{ + //note that later versions, like alpha05, fail to work correctly classpath 'com.android.tools.build:gradle:7.1.0-alpha02' } } @@ -18,7 +19,6 @@ configurations{ natives } repositories{ mavenCentral() maven{ url "https://maven.google.com" } - jcenter() //remove later once google/JetBrains fixes the dependency } task deploy(type: Copy){ diff --git a/annotations/src/main/resources/revisions/PuddleComp/1.json b/annotations/src/main/resources/revisions/PuddleComp/1.json new file mode 100644 index 0000000000..2e4c653aed --- /dev/null +++ b/annotations/src/main/resources/revisions/PuddleComp/1.json @@ -0,0 +1 @@ +{version:1,fields:[{name:amount,type:float},{name:liquid,type:mindustry.type.Liquid},{name:tile,type:mindustry.world.Tile},{name:x,type:float},{name:y,type:float}]} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 419d78ee4f..cfab64d455 100644 --- a/build.gradle +++ b/build.gradle @@ -341,7 +341,11 @@ project(":core"){ } } def changelogs = file("../fastlane/metadata/android/en-US/changelogs/") - new File(changelogs, androidVersion + ".txt").text = (result) + changelogs.mkdirs() + try{ + new File(changelogs, androidVersion + ".txt").text = (result) + }catch(Exception ignored){ + } } } diff --git a/core/assets-raw/sprites/blocks/environment/craters1.png b/core/assets-raw/sprites/blocks/environment/crater-stone1.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/craters1.png rename to core/assets-raw/sprites/blocks/environment/crater-stone1.png diff --git a/core/assets-raw/sprites/blocks/environment/craters2.png b/core/assets-raw/sprites/blocks/environment/crater-stone2.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/craters2.png rename to core/assets-raw/sprites/blocks/environment/crater-stone2.png diff --git a/core/assets-raw/sprites/blocks/environment/craters3.png b/core/assets-raw/sprites/blocks/environment/crater-stone3.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/craters3.png rename to core/assets-raw/sprites/blocks/environment/crater-stone3.png diff --git a/core/assets-raw/sprites/blocks/environment/craters4.png b/core/assets-raw/sprites/blocks/environment/crater-stone4.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/craters4.png rename to core/assets-raw/sprites/blocks/environment/crater-stone4.png diff --git a/core/assets-raw/sprites/blocks/environment/craters5.png b/core/assets-raw/sprites/blocks/environment/crater-stone5.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/craters5.png rename to core/assets-raw/sprites/blocks/environment/crater-stone5.png diff --git a/core/assets-raw/sprites/blocks/environment/craters6.png b/core/assets-raw/sprites/blocks/environment/crater-stone6.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/craters6.png rename to core/assets-raw/sprites/blocks/environment/crater-stone6.png diff --git a/core/assets-raw/sprites/blocks/environment/deepwater.png b/core/assets-raw/sprites/blocks/environment/deep-water.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/deepwater.png rename to core/assets-raw/sprites/blocks/environment/deep-water.png diff --git a/core/assets-raw/sprites/blocks/environment/slag.png b/core/assets-raw/sprites/blocks/environment/molten-slag.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/slag.png rename to core/assets-raw/sprites/blocks/environment/molten-slag.png diff --git a/core/assets-raw/sprites/blocks/environment/water.png b/core/assets-raw/sprites/blocks/environment/shallow-water.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/water.png rename to core/assets-raw/sprites/blocks/environment/shallow-water.png diff --git a/core/assets-raw/sprites/blocks/production/disassembler.png b/core/assets-raw/sprites/blocks/production/disassembler.png index 7dbfcb1474..4e4a4d3433 100644 Binary files a/core/assets-raw/sprites/blocks/production/disassembler.png and b/core/assets-raw/sprites/blocks/production/disassembler.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-foundation-thruster1.png b/core/assets-raw/sprites/blocks/storage/core-foundation-thruster1.png new file mode 100644 index 0000000000..f40a7eb905 Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-foundation-thruster1.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-foundation-thruster2.png b/core/assets-raw/sprites/blocks/storage/core-foundation-thruster2.png new file mode 100644 index 0000000000..21bb44abc9 Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-foundation-thruster2.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster1.png b/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster1.png new file mode 100644 index 0000000000..112429f26a Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster1.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster2.png b/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster2.png new file mode 100644 index 0000000000..83897e87d7 Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster2.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-shard-thruster1.png b/core/assets-raw/sprites/blocks/storage/core-shard-thruster1.png new file mode 100644 index 0000000000..7d6fd61604 Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-shard-thruster1.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-shard-thruster2.png b/core/assets-raw/sprites/blocks/storage/core-shard-thruster2.png new file mode 100644 index 0000000000..2a15417fbe Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-shard-thruster2.png differ diff --git a/core/assets-raw/sprites/blocks/units/additive-reconstructor.png b/core/assets-raw/sprites/blocks/units/additive-reconstructor.png index 7534cc4f15..40ea654c1d 100644 Binary files a/core/assets-raw/sprites/blocks/units/additive-reconstructor.png and b/core/assets-raw/sprites/blocks/units/additive-reconstructor.png differ diff --git a/core/assets-raw/sprites/effects/clear-effect.png b/core/assets-raw/sprites/effects/clear-effect.png new file mode 100644 index 0000000000..92e99b0ef3 Binary files /dev/null and b/core/assets-raw/sprites/effects/clear-effect.png differ diff --git a/core/assets-raw/sprites/teams/team-crux.png b/core/assets-raw/sprites/teams/team-crux.png new file mode 100644 index 0000000000..4fb6783a5b Binary files /dev/null and b/core/assets-raw/sprites/teams/team-crux.png differ diff --git a/core/assets-raw/sprites/teams/team-derelict.png b/core/assets-raw/sprites/teams/team-derelict.png new file mode 100644 index 0000000000..38ac90dcb1 Binary files /dev/null and b/core/assets-raw/sprites/teams/team-derelict.png differ diff --git a/core/assets-raw/sprites/teams/team-sharded.png b/core/assets-raw/sprites/teams/team-sharded.png new file mode 100644 index 0000000000..a3643d4bba Binary files /dev/null and b/core/assets-raw/sprites/teams/team-sharded.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index cad3e67db0..2d722ad20d 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -215,6 +215,7 @@ hosts.none = [lightgray]No local games found! host.invalid = [scarlet]Can't connect to host. servers.local = Local Servers +servers.local.steam = Open Games & Local Servers servers.remote = Remote Servers servers.global = Community Servers @@ -316,7 +317,7 @@ data.invalid = This isn't valid game data. data.import.confirm = Importing external data will overwrite[scarlet] all[] your current game data.\n[accent]This cannot be undone![]\n\nOnce the data is imported, your game will exit immediately. quit.confirm = Are you sure you want to quit? loading = [accent]Loading... -reloading = [accent]Reloading Mods... +downloading = [accent]Downloading... saving = [accent]Saving... respawn = [accent][[{0}][] to respawn in core cancelbuilding = [accent][[{0}][] to clear plan @@ -538,6 +539,7 @@ configure = Configure Loadout loadout = Loadout resources = Resources bannedblocks = Banned Blocks +bannedunits = Banned Units addall = Add All launch.from = Launching From: [accent]{0} launch.destination = Destination: {0} @@ -834,13 +836,13 @@ category.items = Items category.crafting = Input/Output category.function = Function category.optional = Optional Enhancements +setting.skipcoreanimation.name = Skip Core Launch/Land Animation setting.landscape.name = Lock Landscape setting.shadows.name = Shadows setting.blockreplace.name = Automatic Block Suggestions setting.linear.name = Linear Filtering setting.hints.name = Hints setting.logichints.name = Logic Hints -setting.flow.name = Display Resource Flow Rate setting.backgroundpause.name = Pause In Background setting.buildautopause.name = Auto-Pause Building setting.doubletapmine.name = Double-Tap to Mine @@ -875,6 +877,7 @@ setting.seconds = {0} seconds setting.milliseconds = {0} milliseconds setting.fullscreen.name = Fullscreen setting.borderlesswindow.name = Borderless Window +setting.borderlesswindow.name.windows = Borderless Fullscreen setting.borderlesswindow.description = Restart may be required to apply changes. setting.fps.name = Show FPS & Ping setting.smoothcamera.name = Smooth Camera @@ -1104,13 +1107,12 @@ unit.reign.name = Reign unit.vela.name = Vela unit.corvus.name = Corvus -block.resupply-point.name = Resupply Point block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Sand Boulder block.basalt-boulder.name = Basalt Boulder block.grass.name = Grass -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Salt block.salt-wall.name = Salt Wall @@ -1141,8 +1143,8 @@ block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Deep Water -block.water.name = Water +block.deep-water.name = Deep Water +block.shallow-water.name = Water block.tainted-water.name = Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar @@ -1151,7 +1153,7 @@ block.sand.name = Sand block.darksand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.craters.name = Craters +block.crater-stone.name = Craters block.sand-water.name = Sand Water block.darksand-water.name = Dark Sand Water block.char.name = Char @@ -1355,6 +1357,7 @@ hint.placeTurret = Place \uf861 [accent]Turrets[] to defend your base from enemi hint.breaking = [accent]Right-click[] and drag to break blocks. hint.breaking.mobile = Activate the \ue817 [accent]hammer[] in the bottom right and tap to break blocks.\n\nHold down your finger for a second and drag to break in a selection. hint.blockInfo = View information of a block by selecting it in the [accent]build menu[], then selecting the [accent][[?][] button at the right. +hint.derelict = [accent]Derelict[] structures are broken remnants of old bases that no longer function.\n\nThese structures can be [accent]deconstructed[] for resources. hint.research = Use the \ue875 [accent]Research[] button to research new technology. hint.research.mobile = Use the \ue875 [accent]Research[] button in the \ue88c [accent]Menu[] to research new technology. hint.unitControl = Hold [accent][[L-ctrl][] and [accent]click[] to control friendly units or turrets. @@ -1406,7 +1409,7 @@ liquid.slag.description = Refined in separators into constituent metals, or spra liquid.oil.description = Used in advanced material production and as incendiary ammunition. liquid.cryofluid.description = Used as coolant in reactors, turrets and factories. -block.resupply-point.description = Resupplies nearby units with copper ammunition. Not compatible with units that require battery power. +block.derelict =  [lightgray]Derelict block.armored-conveyor.description = Moves items forward. Does not accept inputs from the sides. block.illuminator.description = Emits light. block.message.description = Stores a message for communication between allies. diff --git a/core/assets/bundles/bundle_be.properties b/core/assets/bundles/bundle_be.properties index 59d125147c..5124f7c3c7 100644 --- a/core/assets/bundles/bundle_be.properties +++ b/core/assets/bundles/bundle_be.properties @@ -960,7 +960,7 @@ block.parallax.name = Парралакс block.cliff.name = Скала block.sand-boulder.name = Пяшчаны валун block.grass.name = Трава -block.slag.name = Шлак +block.molten-slag.name = Шлак block.space.name = Space block.salt.name = Соль block.salt-wall.name = Саляная сцяна @@ -991,8 +991,8 @@ block.spawn.name = Кропка з’яўлення ворагаў block.core-shard.name = Ядро: «Аскепак» block.core-foundation.name = Ядро: «Штаб» block.core-nucleus.name = Ядро: «Атам» -block.deepwater.name = Глубокаводдзе -block.water.name = Вада +block.deep-water.name = Глубокаводдзе +block.shallow-water.name = Вада block.tainted-water.name = Забруджанная вада block.darksand-tainted-water.name = Тёмный пясок з забруджанай вадой block.tar.name = Нафта @@ -1001,7 +1001,7 @@ block.sand.name = Пясок block.darksand.name = Тёмны пясок block.ice.name = Лёд block.snow.name = Снег -block.craters.name = Кратэры +block.crater-stone.name = Кратэры block.sand-water.name = Пясок з вадой block.darksand-water.name = Тёмный пясок з вадой block.char.name = Выпаленая зямля diff --git a/core/assets/bundles/bundle_bg.properties b/core/assets/bundles/bundle_bg.properties index 42489f046f..d9c9dbc9f9 100644 --- a/core/assets/bundles/bundle_bg.properties +++ b/core/assets/bundles/bundle_bg.properties @@ -1074,7 +1074,7 @@ block.cliff.name = Скала block.sand-boulder.name = Пясъчен Камък block.basalt-boulder.name = Базалтов Камък block.grass.name = Трева -block.slag.name = Шлака +block.molten-slag.name = Шлака block.space.name = Космос block.salt.name = Сол block.salt-wall.name = Стена от Сол @@ -1105,8 +1105,8 @@ block.spawn.name = Вражеска Начална Точка block.core-shard.name = Ядро: Шард block.core-foundation.name = Core: Фондация block.core-nucleus.name = Core: Център -block.deepwater.name = Дълбока Вода -block.water.name = Вода +block.deep-water.name = Дълбока Вода +block.shallow-water.name = Вода block.tainted-water.name = Замърсена Вода block.darksand-tainted-water.name = Тъмен Пясък - Замърсена Вода block.tar.name = Катран @@ -1115,7 +1115,7 @@ block.sand.name = Пясък block.darksand.name = Тъмен Пясък block.ice.name = Лед block.snow.name = Сняг -block.craters.name = Кратери +block.crater-stone.name = Кратери block.sand-water.name = Пясък - Вода block.darksand-water.name = Тъмен Пясък - Вода block.char.name = Овъглен Камък diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties index f727c74fc6..e79b28b90f 100644 --- a/core/assets/bundles/bundle_cs.properties +++ b/core/assets/bundles/bundle_cs.properties @@ -307,7 +307,7 @@ waiting.players = Čekání na hráče... wave.enemies = [lightgray]{0} zbývajících nepřátel wave.enemycores = [accent]{0}[lightgray] nepřátelská jádra wave.enemycore = [accent]{0}[lightgray] nepřátelské jádro -wave.enemy = [lightgray]{0} zbývající nepřátel +wave.enemy = [lightgray]{0} zbývající nepřítel wave.guardianwarn = Počet vln do příchodu strážce: [accent]{0}[]. wave.guardianwarn.one = [accent]Strážce přijde již příští vlnu![] loadimage = Nahrát obrázek @@ -323,16 +323,16 @@ map.nospawn.attack = Tato mapa nemá nepřátelská jádra, která by mohla být map.invalid = Chyba v načítání mapy: poškozený nebo neplatný soubor mapy. workshop.update = Aktualizovat položku workshop.error = Chyba při načítání podrobností z Workshopu na Steamu: {0} -map.publish.confirm = Jsi si jistý, že chceš vystavit tuto mapu?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami Workshopu na Steamu (EULA), jinak se Tvoje mapa nezobrazí.[] +map.publish.confirm = Jsi si jistý, že chceš publikovat tuto mapu?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami Workshopu na Steamu (EULA), jinak se Tvoje mapa nezobrazí.[] workshop.menu = Vyber si, co bys chtěl dělat s touto položkou. workshop.info = Informace o položce changelog = Seznam změn (volitelně): eula = Smluvní podmínky platformy Steam missing = Tato položka byla smazána nebo přesunuta.\n[lightgray]Položka bude automaticky odebrána ze seznamu Workshopu na Steamu. publishing = [accent]Publikuji... -publish.confirm = Opravdu chceš toto vystavit?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami Workshopu na Steamu (EULA), jinak se Tvoje položky nezobrazí.[] -publish.error = Chyba při vystavování položky: {0} -steam.error = Nepodařilo se inicializovat služby platformy Steam.Chyba: {0} +publish.confirm = Opravdu chceš toto publikovat?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami Workshopu na Steamu (EULA), jinak se Tvoje položky nezobrazí.[] +publish.error = Chyba při publikování položky: {0} +steam.error = Nepodařilo se inicializovat služby platformy Steam. Chyba: {0} editor.brush = Štětec editor.openin = Otevřít v editoru @@ -341,12 +341,12 @@ editor.oregen.info = Generování rud: editor.mapinfo = Informace o mapě editor.author = Autor: editor.description = Popis: -editor.nodescription = Než může být mapa publikována, musí mít popisek dlouhý nejméně 4 znaky. +editor.nodescription = Než může být mapa publikována, musí mít popis dlouhý nejméně 4 znaky. editor.waves = Vln: editor.rules = Pravidla: editor.generation = Generace: editor.ingame = Upravit ve hře -editor.publish.workshop = Vystavit ve Workshopu na Steamu +editor.publish.workshop = Publikovat do Workshopu na Steamu editor.newmap = Nová mapa editor.center = Vycentrovat workshop = Workshop na Steamu @@ -684,6 +684,7 @@ stat.lightningchance = Pravděpodobnost blesku stat.lightningdamage = Poškození bleskem stat.flammability = Hořlavost stat.radioactivity = Radioaktivita +stat.charge = Nabití stat.heatcapacity = Tepelná kapacita stat.viscosity = Vazkost stat.temperature = Teplota @@ -1022,7 +1023,7 @@ block.cliff.name = Útes block.sand-boulder.name = Pískovec block.basalt-boulder.name = Čedičový balvan block.grass.name = Tráva -block.slag.name = Struska +block.molten-slag.name = Struska block.space.name = Vesmír block.salt.name = Sůl block.salt-wall.name = Solné skály @@ -1053,8 +1054,8 @@ block.spawn.name = Nepřátelská líheň block.core-shard.name = Jádro: Odštěpek block.core-foundation.name = Jádro: Základ block.core-nucleus.name = Jádro: Atom -block.deepwater.name = Hluboká voda -block.water.name = Voda +block.deep-water.name = Hluboká voda +block.shallow-water.name = Voda block.tainted-water.name = Zamořená voda block.darksand-tainted-water.name = Zamořená voda s černým pískem block.tar.name = Dehet @@ -1063,7 +1064,7 @@ block.sand.name = Písek block.darksand.name = Černý písek block.ice.name = Led block.snow.name = Sníh -block.craters.name = Krátery +block.crater-stone.name = Krátery block.sand-water.name = Voda s pískem block.darksand-water.name = Voda s černým pískem block.char.name = Dřevěné uhlí diff --git a/core/assets/bundles/bundle_da.properties b/core/assets/bundles/bundle_da.properties index d7937f0154..e18a09d242 100644 --- a/core/assets/bundles/bundle_da.properties +++ b/core/assets/bundles/bundle_da.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Klippe block.sand-boulder.name = Sandkampesten block.grass.name = Græs -block.slag.name = Ildgrød +block.molten-slag.name = Ildgrød block.space.name = Rum block.salt.name = Salt block.salt-wall.name = Saltvæg @@ -991,8 +991,8 @@ block.spawn.name = Fjendtligt Ankomstpunkt block.core-shard.name = Kerne: Skår block.core-foundation.name = Kerne: Fundament block.core-nucleus.name = Kerne: Nukleus -block.deepwater.name = Dybt Vand -block.water.name = Vand +block.deep-water.name = Dybt Vand +block.shallow-water.name = Vand block.tainted-water.name = Moget Vand block.darksand-tainted-water.name = Mørkt Sand Moget Vand block.tar.name = Tjærre @@ -1001,7 +1001,7 @@ block.sand.name = Sand block.darksand.name = Mørkt Sand block.ice.name = Is block.snow.name = Sne -block.craters.name = Kratere +block.crater-stone.name = Kratere block.sand-water.name = Sandet Lavvande block.darksand-water.name = Mørkt Sandet Lavvande block.char.name = Trækul diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index 4e08fe56a9..55f13ee6a1 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -101,6 +101,7 @@ customgame = Benutzerdefiniertes Spiel newgame = Neues Spiel none = none.found = [lightgray] +none.inmap = [lightgray] minimap = Minimap position = Position close = Schließen @@ -565,6 +566,7 @@ sectors.unexplored = [lightgray]Unentdeckt sectors.resources = Ressourcen: sectors.production = Produktion: sectors.export = Export: +sectors.import = Import: sectors.time = Zeit: sectors.threat = Gefahr: sectors.wave = Welle: @@ -724,7 +726,7 @@ stat.maxconsecutive = Max. Konsekutive stat.buildcost = Baukosten stat.inaccuracy = Ungenauigkeit stat.shots = Schüsse -stat.reload = Schüsse/Sekunde +stat.reload = Schussrate stat.ammo = Munition stat.shieldhealth = Schildlebenspunkte stat.cooldowntime = Cooldown-Zeit @@ -793,7 +795,7 @@ bullet.damage = [stat]{0}[lightgray] Schaden bullet.splashdamage = [stat]{0}[lightgray] Flächenschaden ~[stat] {1}[lightgray] Kacheln bullet.incendiary = [stat]entzündend bullet.homing = [stat]zielsuchend -bullet.frag = [stat]explosiv +bullet.frag = [stat]{0}[lightgray]x explosive Projektile: bullet.lightning = [stat]{0}[lightgray]x Blitz ~ [stat]{1}[lightgray] Schaden bullet.buildingdamage = [stat]{0}%[lightgray]Blockschaden bullet.knockback = [stat]{0}[lightgray] zurückstoßend @@ -806,6 +808,7 @@ bullet.reload = [stat]{0}[lightgray]x Feuerrate unit.blocks = Blöcke unit.blockssquared = Blöcke² unit.powersecond = Stromeinheiten/Sekunde +unit.tilessecond = Blöcke/Sekunde unit.liquidsecond = Flüssigkeitseinheiten/Sekunde unit.itemssecond = Materialeinheiten/Sekunde unit.liquidunits = Flüssigkeitseinheiten @@ -844,7 +847,6 @@ setting.doubletapmine.name = Doppeltippen zum Abbauen setting.modcrashdisable.name = Mods bei Absturz deaktivieren setting.animatedwater.name = Animiertes Wasser setting.animatedshields.name = Animierte Schilde -setting.antialias.name = Antialias[lightgray] (Neustart erforderlich)[] setting.playerindicators.name = Spieler-Indikatoren setting.indicators.name = Verbündeten-Indikatoren setting.autotarget.name = Auto-Zielauswahl @@ -853,7 +855,8 @@ setting.touchscreen.name = Touchscreen-Steuerung setting.fpscap.name = Max. FPS setting.fpscap.none = Kein(e) setting.fpscap.text = {0} FPS -setting.uiscale.name = UI-Skalierung[lightgray] (Neustart erforderlich)[] +setting.uiscale.name = UI-Skalierung +setting.uiscale.description = Neustart erforderlich. setting.swapdiagonal.name = Immer diagonale Platzierung setting.difficulty.training = Training setting.difficulty.easy = Leicht @@ -871,7 +874,8 @@ setting.saveinterval.name = Autosave-Häufigkeit setting.seconds = {0} Sekunden setting.milliseconds = {0} Millisekunden setting.fullscreen.name = Vollbild -setting.borderlesswindow.name = Randloses Fenster [lightgray](Neustart vielleicht erforderlich) +setting.borderlesswindow.name = Randloses Fenster +setting.borderlesswindow.description = Neustart vielleicht erforderlich. setting.fps.name = FPS anzeigen setting.smoothcamera.name = Sanfte Kamerabewegungen setting.vsync.name = VSync @@ -994,6 +998,7 @@ rules.wavetimer = Wellen-Timer rules.waves = Wellen rules.attack = Angriff-Modus rules.buildai = KI kann bauen +rules.cleanupdeadteams = Blöcke von erorberten Teams zerstören (PvP) rules.corecapture = Kern nach Zerstörung einnehmen rules.polygoncoreprotection = Polygonaler Kernschutz rules.enemyCheat = Unbegrenzte Ressourcen für die KI (Rotes Team) @@ -1102,7 +1107,7 @@ block.cliff.name = Klippe block.sand-boulder.name = Sandbrocken block.basalt-boulder.name = Basaltbrocken block.grass.name = Gras -block.slag.name = Schlacke +block.molten-slag.name = Schlacke block.space.name = Weltall block.salt.name = Salz block.salt-wall.name = Salzwand @@ -1133,8 +1138,8 @@ block.spawn.name = Gegnerischer Startpunkt block.core-shard.name = Kern: Scherbe block.core-foundation.name = Kern: Fundament block.core-nucleus.name = Kern: Nukleus -block.deepwater.name = Tiefes Wasser -block.water.name = Wasser +block.deep-water.name = Tiefes Wasser +block.shallow-water.name = Wasser block.tainted-water.name = Dreckiges Wasser block.darksand-tainted-water.name = Dreckiges Wasser (Dunkler Sand) block.tar.name = Teer @@ -1143,7 +1148,7 @@ block.sand.name = Sand block.darksand.name = Dunkler Sand block.ice.name = Eis block.snow.name = Schnee -block.craters.name = Krater +block.crater-stone.name = Krater block.sand-water.name = Sandiges Wasser block.darksand-water.name = Dunkles sandiges Wasser block.char.name = Holzkohle @@ -1288,7 +1293,6 @@ block.meltdown.name = Meltdown block.foreshadow.name = Foreshadow block.container.name = Behälter block.launch-pad.name = Launchpad -block.launch-pad-large.name = Großes Launchpad block.segment.name = Segment block.command-center.name = Kommandozentrale block.ground-factory.name = Bodenfabrik @@ -1309,11 +1313,11 @@ block.payload-source.name = Frachtquelle block.disassembler.name = Großer Trenner block.silicon-crucible.name = Silizium Schmelztiegel block.overdrive-dome.name = Beschleunigungs-Maschine +block.interplanetary-accelerator.name = Interplanetarischer Beschleuniger #experimental, may be removed block.block-forge.name = Block-Fabrik block.block-loader.name = Block-Lader block.block-unloader.name = Block-Entlader -block.interplanetary-accelerator.name = Interplanetarischer Beschleuniger block.switch.name = Schalter block.micro-processor.name = Mikroprozessor @@ -1543,6 +1547,8 @@ block.memory-bank.description = Speichert Informationen für einen Prozessor. Ho block.logic-display.description = Zeigt mithilfe eines Prozessors Beliebiges an. block.large-logic-display.description = Zeigt mithilfe eines Prozessors Beliebiges an. block.interplanetary-accelerator.description = Ein Riesen-Railgun-Turm, der mithilfe des Elektromagnetismus Kerne auf die nötige Geschwindigkeit bringt, um interplanetarisches Reisen zu ermöglichen. +block.repair-turret.description = Heilt durchgehend die nächste befreundete, beschädigte Einheit in der Umgebung. Verwendet optional Kühlung. +block.payload-propulsion-tower.description = Frachttransportationsturm mit hoher Reichweite. Schießt Fracht zu verbundenen Türmen. unit.dagger.description = Schießt normale Kugeln auf alle Feinde in der Nähe. unit.mace.description = Schießt Feuer auf alle Gegner in der Nähe. @@ -1577,6 +1583,11 @@ unit.omura.description = Schießt eine Railgun mit hoher Reichweite, um Gegner z unit.alpha.description = Beschützt den Scherbenkern vor Feinden. Baut Blöcke. unit.beta.description = Beschützt den Fundamentkern vor Feinden. Baut Blöcke. unit.gamma.description = Beschützt den Nukleuskern vor Feinden. Baut Blöcke. +unit.retusa.description = Platziert Minen und heilt verbündete Einheiten. +unit.oxynoe.description = Schießt Block-heilendes Feuer auf Gegner und zerstört gegnerische Projektile. +unit.cyerce.description = Schießt zielsuchende Cluster-Raketen auf Gegner und heilt verbündete Einheiten. +unit.aegires.description = Schockt alle gegnerische Einheiten und Blöcke, die das Energiefeld betreten. Heilt alle verbündete. +unit.navanax.description = Schießt explosive EMP-Projektile, die gegnerische Stromnetze zerstören und eigene Blöcke heilen. Zerschmilzt Gegner mit 4 autonomen Laserstrahlen. lst.read = Liest einen Wert aus einer verbundenen Spiecherzelle. lst.write = Schreibt eine Zahl in einer verbundene Speicherzelle. diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index 8701bc0531..54bc3a9fb1 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -1103,7 +1103,7 @@ block.cliff.name = Pared block.sand-boulder.name = Roca de arena block.basalt-boulder.name = Roca de basalto block.grass.name = Hierba -block.slag.name = Magma +block.molten-slag.name = Magma block.space.name = Espacio block.salt.name = Sal block.salt-wall.name = Muro de sal @@ -1134,8 +1134,8 @@ block.spawn.name = Punto de generación block.core-shard.name = Núcleo: Shard block.core-foundation.name = Núcleo: Foundation block.core-nucleus.name = Núcleo: Nucleus -block.deepwater.name = Aguas profundas -block.water.name = Agua +block.deep-water.name = Aguas profundas +block.shallow-water.name = Agua block.tainted-water.name = Agua contaminada block.darksand-tainted-water.name = Agua contaminada con arena oscura block.tar.name = Alquitrán @@ -1144,7 +1144,7 @@ block.sand.name = Arena block.darksand.name = Arena oscura block.ice.name = Hielo block.snow.name = Nieve -block.craters.name = Cráter +block.crater-stone.name = Cráter block.sand-water.name = Agua con arena block.darksand-water.name = Agua con arena oscura block.char.name = Cenizas diff --git a/core/assets/bundles/bundle_et.properties b/core/assets/bundles/bundle_et.properties index 46cf235d26..1cc5726bac 100644 --- a/core/assets/bundles/bundle_et.properties +++ b/core/assets/bundles/bundle_et.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Liivakamakas block.grass.name = Rohi -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Sool block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Vaenlaste maandumisala block.core-shard.name = Tuumik: Osake block.core-foundation.name = Tuumik: Arenenud block.core-nucleus.name = Tuumik: Täielik -block.deepwater.name = Sügav vesi -block.water.name = Vesi +block.deep-water.name = Sügav vesi +block.shallow-water.name = Vesi block.tainted-water.name = Riknenud vesi block.darksand-tainted-water.name = Riknenud vesi tumedal liival block.tar.name = Tõrv @@ -1001,7 +1001,7 @@ block.sand.name = Liiv block.darksand.name = Tume liiv block.ice.name = Jää block.snow.name = Lumi -block.craters.name = Kraatrid +block.crater-stone.name = Kraatrid block.sand-water.name = Vesi liival block.darksand-water.name = Vesi tumedal liival block.char.name = Puusüsi diff --git a/core/assets/bundles/bundle_eu.properties b/core/assets/bundles/bundle_eu.properties index 537d0b3133..dbc1825e7c 100644 --- a/core/assets/bundles/bundle_eu.properties +++ b/core/assets/bundles/bundle_eu.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Hondar harkaitza block.grass.name = Belarra -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Gatza block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Etsai-sorrera block.core-shard.name = Muina: Maskorra block.core-foundation.name = Muina: Fundazioa block.core-nucleus.name = Muina: Nukleoa -block.deepwater.name = Ur sakona -block.water.name = Ura +block.deep-water.name = Ur sakona +block.shallow-water.name = Ura block.tainted-water.name = Ur kutsatua block.darksand-tainted-water.name = Hondar ilunez kutsatutako ura block.tar.name = Mundruna @@ -1001,7 +1001,7 @@ block.sand.name = Hondarra block.darksand.name = Hondar iluna block.ice.name = Izotza block.snow.name = Elurra -block.craters.name = Kraterrak +block.crater-stone.name = Kraterrak block.sand-water.name = Hondar ura block.darksand-water.name = Hondar ilun ura block.char.name = Kokea diff --git a/core/assets/bundles/bundle_fi.properties b/core/assets/bundles/bundle_fi.properties index d2a998db77..71a42b0512 100644 --- a/core/assets/bundles/bundle_fi.properties +++ b/core/assets/bundles/bundle_fi.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Vuoren block.sand-boulder.name = Hiekkalohkare block.grass.name = Ruoho -block.slag.name = Kuono +block.molten-slag.name = Kuono block.space.name = Space block.salt.name = Suolapitoisuus block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Vihollisten syntymispiste block.core-shard.name = Ydin: Siru block.core-foundation.name = Ydin: Pohjaus block.core-nucleus.name = Ydin: Tuma -block.deepwater.name = Syvää vettä -block.water.name = Vettä +block.deep-water.name = Syvää vettä +block.shallow-water.name = Vettä block.tainted-water.name = Saastevettä block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Terva @@ -1001,7 +1001,7 @@ block.sand.name = Hiekka block.darksand.name = Tumma hiekka block.ice.name = Jää block.snow.name = Lumi -block.craters.name = Kraatterit +block.crater-stone.name = Kraatterit block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_fil.properties b/core/assets/bundles/bundle_fil.properties index c5663baa1d..7581748a30 100644 --- a/core/assets/bundles/bundle_fil.properties +++ b/core/assets/bundles/bundle_fil.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Sand Boulder block.grass.name = Grass -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Salt block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Deep Water -block.water.name = Water +block.deep-water.name = Deep Water +block.shallow-water.name = Water block.tainted-water.name = Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar @@ -1001,7 +1001,7 @@ block.sand.name = Sand block.darksand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.craters.name = Craters +block.crater-stone.name = Craters block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index 942ae5c750..2fb0b33c5c 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -101,6 +101,7 @@ customgame = Partie personnalisée newgame = Nouvelle partie none = none.found = [lightgray] +none.inmap = [lightgray] minimap = Mini-carte position = Position close = Fermer @@ -214,6 +215,7 @@ hosts.none = [lightgray]Aucune partie en LAN trouvée ! host.invalid = [scarlet]Impossible de se connecter à l'hôte. servers.local = Serveurs locaux +servers.local.steam = Open Games & Serveurs Locaux servers.remote = Serveurs distants servers.global = Serveurs communautaires @@ -725,7 +727,7 @@ stat.maxconsecutive = Max Consécutif stat.buildcost = Coût de construction stat.inaccuracy = Précision stat.shots = Tirs -stat.reload = Tirs/Seconde +stat.reload = Cadence de tir stat.ammo = Munitions stat.shieldhealth = Santé du bouclier stat.cooldowntime = Temps de refroidissement @@ -794,7 +796,8 @@ bullet.damage = [stat]{0}[lightgray] dégâts bullet.splashdamage = [stat]{0}[lightgray] dégâts de zone ~[stat] {1}[lightgray] blocs bullet.incendiary = [stat]incendiaire bullet.homing = [stat]autoguidé -bullet.frag = [stat]fragmentation +bullet.fragbullets = [stat]{0}[lightgray]x balles à fragmentation +bullet.frag.stats = [stat]Balle à fragmentation: bullet.lightning = [stat]{0}[lightgray]x foudre ~ [stat]{1}[lightgray] dégâts bullet.buildingdamage = [stat]{0}%[lightgray] des dégâts aux bâtiments bullet.knockback = [stat]{0}[lightgray] recul @@ -841,14 +844,12 @@ setting.blockreplace.name = Suggestion automatique des Blocs setting.linear.name = Filtrage linéaire setting.hints.name = Astuces setting.logichints.name = Astuces pour les commandes des processeurs -setting.flow.name = Afficher le Débit des ressources setting.backgroundpause.name = Pause en Arrière-plan setting.buildautopause.name = Confirmation avant construction setting.doubletapmine.name = Double-clic pour Miner setting.modcrashdisable.name = Désactiver les mods lors d'un crash au démarrage setting.animatedwater.name = Surfaces Animées setting.animatedshields.name = Boucliers Animés -setting.antialias.name = Anticrénelage[lightgray] (redémarrage du jeu nécessaire)[] setting.playerindicators.name = Indicateurs alliés setting.indicators.name = Indicateurs ennemis setting.autotarget.name = Visée automatique @@ -857,7 +858,8 @@ setting.touchscreen.name = Commandes d'écran tactile setting.fpscap.name = Max FPS setting.fpscap.none = Illimité setting.fpscap.text = {0} FPS -setting.uiscale.name = Échelle de l'interface[lightgray] (redémarrage du jeu nécessaire)[] +setting.uiscale.name = Échelle de l'interface +setting.uiscale.description = Redémarrage du jeu nécessaire pour appliquer les changements. setting.swapdiagonal.name = Autoriser le placement en diagonale setting.difficulty.training = Entraînement setting.difficulty.easy = Facile @@ -875,7 +877,8 @@ setting.saveinterval.name = Intervalle des Sauvegardes automatiques setting.seconds = {0} secondes setting.milliseconds = {0} millisecondes setting.fullscreen.name = Plein Écran -setting.borderlesswindow.name = Fenêtre sans bords[lightgray] (peut nécessiter le redémarrage du jeu) +setting.borderlesswindow.name = Fenêtré sans bordures +setting.borderlesswindow.description = Un redémarrage peut être nécessaire pour appliquer les changements. setting.fps.name = Afficher FPS et Ping setting.smoothcamera.name = Lissage de la Caméra setting.vsync.name = Synchronisation Verticale @@ -1005,6 +1008,7 @@ rules.wavetimer = Compte à rebours des vagues rules.waves = Vagues rules.attack = Mode « Attaque » rules.buildai = Constructions de l'IA +rules.cleanupdeadteams = Détruire les structures des équipes vaincues (JcJ) rules.corecapture = Capture du Noyau lors de sa Destruction rules.polygoncoreprotection = Protection du noyau polygonal rules.enemyCheat = Ressources infinies pour l'IA (équipe rouge) @@ -1113,7 +1117,7 @@ block.cliff.name = Falaise block.sand-boulder.name = Bloc de Sable block.basalt-boulder.name = Rocher de Basalte block.grass.name = Herbe -block.slag.name = Scories +block.molten-slag.name = Scories block.space.name = Espace block.salt.name = Sel block.salt-wall.name = Mur de Sel @@ -1144,8 +1148,8 @@ block.spawn.name = Point d'Apparition Ennemi block.core-shard.name = Noyau: Fragment block.core-foundation.name = Noyau: Fondation block.core-nucleus.name = Noyau: Épicentre -block.deepwater.name = Eau profonde -block.water.name = Eau +block.deep-water.name = Eau profonde +block.shallow-water.name = Eau block.tainted-water.name = Eau Contaminée block.darksand-tainted-water.name = Eau Contaminée avec fond de Sable sombre block.tar.name = Goudron @@ -1154,7 +1158,7 @@ block.sand.name = Sable block.darksand.name = Sable sombre block.ice.name = Glace block.snow.name = Neige -block.craters.name = Cratères +block.crater-stone.name = Cratères block.sand-water.name = Eau avec fond de Sable block.darksand-water.name = Eau avec fond de Sable sombre block.char.name = Cendres @@ -1299,7 +1303,6 @@ block.meltdown.name = Fusion block.foreshadow.name = Présage block.container.name = Conteneur block.launch-pad.name = Rampe de lancement -block.launch-pad-large.name = Grande rampe de lancement block.segment.name = Diviseur block.command-center.name = Centre de Commande block.ground-factory.name = Usine d'Unités Terrestres @@ -1320,11 +1323,11 @@ block.payload-source.name = Source de Charge utile block.disassembler.name = Désassembleur block.silicon-crucible.name = Grande Fonderie de Silicium block.overdrive-dome.name = Dôme Accélérant +block.interplanetary-accelerator.name = Accélérateur Interplanétaire #experimental, may be removed block.block-forge.name = Forgeur de Blocs block.block-loader.name = Chargeur de Blocs block.block-unloader.name = Déchargeur de Blocs -block.interplanetary-accelerator.name = Accélérateur Interplanétaire block.switch.name = Interrupteur block.micro-processor.name = Micro Processeur @@ -1338,7 +1341,7 @@ block.memory-bank.name = Banque de mémoire team.blue.name = bleu team.crux.name = crux team.sharded.name = sharded -team.derelict.name = derelict +team.derelict.name = Vestige team.green.name = vert team.purple.name = mauve @@ -1357,8 +1360,9 @@ hint.placeConveyor = Les Convoyeurs transportent les ressources des foreuses ver hint.placeConveyor.mobile = Les Convoyeurs transportent les ressources des foreuses vers d'autres blocs. Sélectionnez un \uf896 [accent]Convoyeur[] dans l'onglet \ue814 [accent]Distribution[].\n\nMaintenez votre doigt et déplacez-le pour placer plusieurs convoyeurs. hint.placeTurret = Placez des \uf861 [accent]Tourelles[] pour défendre votre base contre les ennemis.\n\nLes Tourelles nécessitent des munitions (dans ce cas, du \uf838Cuivre).\nUtilisez les convoyeurs et les foreuses pour les ravitailler. hint.breaking = Maintenez [accent]Clic-droit[] pour détruire des blocs. -hint.breaking.mobile = Activez le \ue817 [accent]marteau[] en bas à droite Touchez pour détruire des blocs.\n\nRetenez votre doigt pendant une seconde et déplacez-le pour détruire les blocs dans la zone de sélection. +hint.breaking.mobile = Activez le \ue817 [accent]marteau[] en bas à droite, Touchez pour détruire des blocs.\n\nRetenez votre doigt pendant une seconde et déplacez-le pour détruire les blocs dans la zone de sélection. hint.blockInfo = Pour afficher les informations relatives à un bloc, il suffit de le sélectionner dans le [accent]menu de construction[], puis de cliquer sur le bouton [accent][[?][] à droite. +hint.derelict = [accent]Les structures abandonnées[] sont des vestiges brisés d'anciennes bases qui ne fonctionnent plus. Ces structures peuvent être [accent]déconstruites pour obtenir des ressources. hint.research = Utilisez le bouton \ue875 [accent]Recherche[] pour rechercher de nouvelles technologies. hint.research.mobile = Utilisez le bouton \ue875 [accent]Recherche[] dans le \ue88c [accent]Menu[] pour rechercher de nouvelles technologies. hint.unitControl = Retenez [accent][[Ctrl-gauche][] et [accent]cliquez[] pour contrôler une tourelle ou une unité alliée. @@ -1410,6 +1414,7 @@ liquid.slag.description = Différents types de métaux en fusion mélangés. Peu liquid.oil.description = Un liquide utilisé dans la production de matériaux avancés. Peut être transformé en charbon ou pulvérisé sur les ennemis, puis enflammé. liquid.cryofluid.description = Un liquide inerte, non corrosif, créé à partir d’eau et de titane. Possède une capacité d'absorption de chaleur extrêmement élevée. Largement utilisé comme liquide de refroidissement. +block.derelict = [lightgray] Vestiges block.resupply-point.description = Approvisionne les unités proches en munitions. Pas compatible avec celles qui ont besoin d'énergie pour tirer. block.illuminator.description = Une petite source lumineuse compacte et configurable. Nécessite de l'énergie pour fonctionner. block.armored-conveyor.description = Déplace les objets à la même vitesse que les convoyeurs en titane, mais est plus résistant. Seulement d'autres convoyeurs peuvent faire entrer des ressources par ses côtés. @@ -1518,7 +1523,7 @@ block.scatter.description = Une tourelle anti-aérienne essentielle. Mitraille l block.scorch.description = Brûle les ennemis terrestres près de lui. Très efficace à courte portée. block.hail.description = Une petite tourelle d'artillerie visant les ennemis terrestres. Efficace à longue portée. block.wave.description = Une tourelle de taille moyenne tirant un jet de liquide. Peut éteindre les incendies automatiquement si elle est alimentée en eau. -block.lancer.description = Une tourelle de taille moyenne chargeant et tirant de puissants lasers aux ennemis terrestres. +block.lancer.description = Une tourelle de taille moyenne chargeant et tirant de puissants lasers sur les ennemis terrestres. block.arc.description = Une petite tourelle tirant des arcs électriques sur les ennemis. block.swarmer.description = Une tourelle de taille moyenne attaquant les ennemis terrestres et aériens à l'aide de missiles autoguidés. Consomme beaucoup de munitions. block.salvo.description = Une version plus grande et améliorée de la tourelle Duo. Tire par salves. @@ -1531,7 +1536,7 @@ block.foreshadow.description = Une tourelle massive tirant une puissante balle s block.repair-point.description = Soigne l'unité endommagée la plus proche. block.segment.description = Endommage et détruit les tirs ennemis. Les lasers ne peuvent pas être ciblés. block.parallax.description = Tire un rayon tracteur qui attire les ennemis volants, infligeant aussi des dégâts. -block.tsunami.description = Tire un puissant jet de liquide aux ennemis. Peut éteindre les incendies automatiquement si elle est alimentée en eau. +block.tsunami.description = Tire un puissant jet de liquide sur les ennemis. Peut éteindre les incendies automatiquement si elle est alimentée en eau. block.silicon-crucible.description = Raffine du silicium avec du sable et du charbon en utilisant de la pyratite comme source de chaleur additionnelle. Cette usine est plus efficace dans les endroits chauds. block.disassembler.description = Cette version avancée du séparateur peut produire du thorium. block.overdrive-dome.description = Accélère le fonctionnement des bâtiments autour de lui. Requiert du silicium et du tissu phasé pour fonctionner. @@ -1554,6 +1559,8 @@ block.memory-bank.description = Stocke des informations pour un processeur logiq block.logic-display.description = Affiche des images à partir des instructions d'un processeur logique. block.large-logic-display.description = Affiche des images à partir des instructions d'un processeur logique. Possède une plus grande résolution qu'un écran. block.interplanetary-accelerator.description = Un énorme canon électromagnétique à rails. Accélère les Noyaux pour qu'ils échappent à la gravité de leur planète et leur permettent un déploiement interplanétaire. +block.repair-turret.description = Répare en continu l'unité endommagée la plus proche dans son périmètre. Accepte le liquide de refroidissement en option. +block.payload-propulsion-tower.description = Structure de transport de charges utiles à longue portée. Projette des charges utiles vers d'autres tours de propulsion de charges utiles reliées. unit.dagger.description = Tire des balles normales aux ennemis proches. unit.mace.description = Tire des jets de flammes aux ennemis proches. @@ -1588,6 +1595,11 @@ unit.omura.description = Tire avec un canon à rails à longue portée, une puis unit.alpha.description = Défend le Noyau fragment contre les ennemis. Peut construire des structures. unit.beta.description = Défend le Noyau fondation contre les ennemis. Peut construire des structures. unit.gamma.description = Défend le Noyau épicentre contre les ennemis. Peut construire des structures. +unit.retusa.description = Pose des mines de proximité. Répare les unités alliées. +unit.oxynoe.description = Tire des jets de flammes qui réparent les structures et endommage les ennemis proches. Cible les projectiles ennemis proches avec une tourelle de défense ponctuelle. +unit.cyerce.description = Tire des missiles à fragmentation sur les ennemis. Répare les unités alliées. +unit.aegires.description = Secoue toutes les unités et structures ennemies qui entrent dans son champ d'énergie. Répare tous les alliés. +unit.navanax.description = Tire des projectiles explosifs EMP, infligeant des dommages importants aux réseaux électriques ennemis et réparant les structures alliées. Fait fondre les ennemis proches avec 4 tourelles laser autonomes. lst.read = Lit un nombre depuis un bloc de mémoire relié au processeur. lst.write = Écrit un nombre dans un bloc de mémoire relié au processeur. diff --git a/core/assets/bundles/bundle_hu.properties b/core/assets/bundles/bundle_hu.properties index 47734eb072..c7cee9bc4e 100644 --- a/core/assets/bundles/bundle_hu.properties +++ b/core/assets/bundles/bundle_hu.properties @@ -1044,7 +1044,7 @@ block.cliff.name = Cliff block.sand-boulder.name = Sand Boulder block.basalt-boulder.name = Basalt Boulder block.grass.name = Grass -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Salt block.salt-wall.name = Salt Wall @@ -1075,8 +1075,8 @@ block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Deep Water -block.water.name = Water +block.deep-water.name = Deep Water +block.shallow-water.name = Water block.tainted-water.name = Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar @@ -1085,7 +1085,7 @@ block.sand.name = Sand block.darksand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.craters.name = Craters +block.crater-stone.name = Craters block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_in_ID.properties b/core/assets/bundles/bundle_in_ID.properties index c78204530d..9252a94e7f 100644 --- a/core/assets/bundles/bundle_in_ID.properties +++ b/core/assets/bundles/bundle_in_ID.properties @@ -1102,7 +1102,7 @@ block.cliff.name = Cliff block.sand-boulder.name = Batu Pasir Besar block.basalt-boulder.name = Batu Basal Besar block.grass.name = Rumput -block.slag.name = Lahar +block.molten-slag.name = Lahar block.space.name = Luar Angkasa block.salt.name = Garam block.salt-wall.name = Bukit Garam @@ -1133,8 +1133,8 @@ block.spawn.name = Muncul Musuh block.core-shard.name = Inti: Bagian block.core-foundation.name = Inti: Pondasi block.core-nucleus.name = Inti: Nukleus -block.deepwater.name = Air Dalam -block.water.name = Air +block.deep-water.name = Air Dalam +block.shallow-water.name = Air block.tainted-water.name = Air Ternoda block.darksand-tainted-water.name = Air Ternodai Pasir Hitam block.tar.name = Minyak Mentah @@ -1143,7 +1143,7 @@ block.sand.name = Pasir block.darksand.name = Pasir Hitam block.ice.name = Es block.snow.name = Salju -block.craters.name = Kawah +block.crater-stone.name = Kawah block.sand-water.name = Air Pasir block.darksand-water.name = Air Pasir Hitam block.char.name = Bara diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties index dd1d40f0f7..f9ba38c603 100644 --- a/core/assets/bundles/bundle_it.properties +++ b/core/assets/bundles/bundle_it.properties @@ -1024,7 +1024,7 @@ block.cliff.name = Scogliera block.sand-boulder.name = Masso di Sabbia block.basalt-boulder.name = Masso di Basalto block.grass.name = Erba -block.slag.name = Scoria +block.molten-slag.name = Scoria block.space.name = Spazio block.salt.name = Sale block.salt-wall.name = Muro di Sale @@ -1055,8 +1055,8 @@ block.spawn.name = Punto di Generazione Nemico block.core-shard.name = Nucleo: Frammento block.core-foundation.name = Nucleo: Fondamento block.core-nucleus.name = Nucleo: Kernel -block.deepwater.name = Acqua Profonda -block.water.name = Acqua +block.deep-water.name = Acqua Profonda +block.shallow-water.name = Acqua block.tainted-water.name = Acqua Contaminata block.darksand-tainted-water.name = Acqua Contaminata Scura block.tar.name = Catrame @@ -1065,7 +1065,7 @@ block.sand.name = Sabbia block.darksand.name = Sabbia Scura block.ice.name = Ghiaccio block.snow.name = Neve -block.craters.name = Crateri +block.crater-stone.name = Crateri block.sand-water.name = Acqua Sabbiosa block.darksand-water.name = Acqua Sabbiosa Scura block.char.name = Carbone diff --git a/core/assets/bundles/bundle_ja.properties b/core/assets/bundles/bundle_ja.properties index df0475b176..c6b5b42c56 100644 --- a/core/assets/bundles/bundle_ja.properties +++ b/core/assets/bundles/bundle_ja.properties @@ -1037,7 +1037,7 @@ block.cliff.name = 崖 block.sand-boulder.name = 巨大な礫 block.basalt-boulder.name = 玄武岩の礫 block.grass.name = 草 -block.slag.name = スラグ +block.molten-slag.name = スラグ block.space.name = Space block.salt.name = 岩塩氷河 block.salt-wall.name = 塩の壁 @@ -1068,8 +1068,8 @@ block.spawn.name = 敵の出現場所 block.core-shard.name = コア: シャード block.core-foundation.name = コア: ファンデーション block.core-nucleus.name = コア: ニュークリアス -block.deepwater.name = 深層水 -block.water.name = 水 +block.deep-water.name = 深層水 +block.shallow-water.name = 水 block.tainted-water.name = 汚れた水 block.darksand-tainted-water.name = 黒い砂で汚れた水 block.tar.name = タール @@ -1078,7 +1078,7 @@ block.sand.name = 砂 block.darksand.name = 黒い砂 block.ice.name = 氷 block.snow.name = 雪 -block.craters.name = クレーター +block.crater-stone.name = クレーター block.sand-water.name = 濁った水 block.darksand-water.name = 黒い砂で濁った水 block.char.name = 焦げ跡 diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 4c68f6efef..89dbb2eaa5 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -122,7 +122,6 @@ committingchanges = 바뀐 점 적용 done = 완료 feature.unsupported = 기기가 이 기능을 지원하지 않습니다. -mods.initfailed = [red]⚠[]이전 Mindustry 인스턴스를 초기화하지 못했습니다. 잘못된 모드로 인해 발생한 것일 수 있습니다.\n\n 게임 충돌 무한반복을 막기 위해, [red]모든 모드가 비활성화되었습니다.[]\n\n이 시스템을 비활성화할려면, [accent]설정->게임->로딩 중 충돌 시 모드 비활성화[]설정을 끄세요. mods = 모드 mods.none = [lightgray]모드를 찾을 수 없습니다! mods.guide = 모드 제작 가이드 @@ -566,6 +565,7 @@ sectors.unexplored = [lightgray]미개척지 sectors.resources = 자원: sectors.production = 생산량: sectors.export = 수출량: +sectors.import = 수입량: sectors.time = 진행 시간: sectors.threat = 위험도: sectors.wave = 단계: @@ -725,7 +725,7 @@ stat.maxconsecutive = 최대 체인 stat.buildcost = 건설 비용 stat.inaccuracy = 오차각 stat.shots = 발사 수 -stat.reload = 초당 발사 수 +stat.reload = 발사 주기 stat.ammo = 탄약 stat.shieldhealth = 보호막 내구도 stat.cooldowntime = 쿨타임 @@ -794,7 +794,7 @@ bullet.damage = [stat]{0}[lightgray] 피해량 bullet.splashdamage = [stat]{0}[lightgray] 범위 피해량 ~ [stat]{1}[lightgray] 타일 bullet.incendiary = [stat]방화 bullet.homing = [stat]유도 -bullet.frag = [stat]파편 +bullet.frags = [stat]{0}[lightgray]개 파편 탄환: bullet.lightning = [stat]{0}[lightgray]x 전격 ~ [stat]{1}[lightgray] 피해량 bullet.buildingdamage = [stat]{0}%[lightgray] 건물 피해량 bullet.knockback = [stat]{0}[lightgray] 넉백 @@ -846,7 +846,6 @@ setting.doubletapmine.name = 연속 터치로 채광 setting.modcrashdisable.name = 로딩 중 충돌 시 모드 비활성화 setting.animatedwater.name = 액체 애니메이션 효과 setting.animatedshields.name = 보호막 애니메이션 효과 -setting.antialias.name = 위신호 제거 필터[lightgray] (재시작 필요)[] setting.playerindicators.name = 플레이어 위치 표시기 setting.indicators.name = 적 위치 표시기 setting.autotarget.name = 자동 조준 @@ -855,7 +854,8 @@ setting.touchscreen.name = 터치스크린 조작 setting.fpscap.name = 최대 FPS setting.fpscap.none = 없음 setting.fpscap.text = {0} FPS -setting.uiscale.name = UI 스케일링[lightgray] (재시작 필요)[] +setting.uiscale.name = UI 스케일링 +setting.uiscale.description = 적용하려면 재시작이 필요합니다. setting.swapdiagonal.name = 항상 대각선 배치 setting.difficulty.training = 훈련 setting.difficulty.easy = 무난 @@ -873,7 +873,8 @@ setting.saveinterval.name = 저장 간격 setting.seconds = {0} 초 setting.milliseconds = {0} 밀리초 setting.fullscreen.name = 전체 화면 -setting.borderlesswindow.name = 테두리 없는 창 모드[lightgray] (재시작이 필요할 수 있습니다) +setting.borderlesswindow.name = 테두리 없는 창 모드 +setting.borderlesswindow.description = 적용하려면 재시작이 필요할 수도 있습니다. setting.fps.name = FPS와 핑 표시 setting.smoothcamera.name = 부드러운 시점 setting.vsync.name = 수직 동기화 @@ -996,6 +997,7 @@ rules.wavetimer = 시간 제한이 있는 단계 rules.waves = 단계 rules.attack = 공격 모드 rules.buildai = AI 건설 +rules.cleanupdeadteams = 패배한 팀 건물 정리하기 (PvP) rules.corecapture = 코어 파괴 시 점령 rules.polygoncoreprotection = 다각형 코어 건설 금지구역 rules.enemyCheat = 적Ai 무한자원 @@ -1047,7 +1049,7 @@ item.silicon.name = 실리콘 item.plastanium.name = 플라스터늄 item.phase-fabric.name = 메타 item.surge-alloy.name = 설금 -item.spore-pod.name = 포자 +item.spore-pod.name = 포자 꼬투리 item.sand.name = 모래 item.blast-compound.name = 폭발물 item.pyratite.name = 파이라타이트 @@ -1104,7 +1106,7 @@ block.cliff.name = 언덕 block.sand-boulder.name = 사암 바위 block.basalt-boulder.name = 현무암 바위 block.grass.name = 잔디 -block.slag.name = 용암 +block.molten-slag.name = 용암 block.space.name = 우주 block.salt.name = 소금 block.salt-wall.name = 소금 벽 @@ -1135,8 +1137,8 @@ block.spawn.name = 적 소환지점 block.core-shard.name = 코어: 조각 block.core-foundation.name = 코어: 기반 block.core-nucleus.name = 코어: 핵심 -block.deepwater.name = 깊은 물 -block.water.name = 물 +block.deep-water.name = 깊은 물 +block.shallow-water.name = 물 block.tainted-water.name = 오염된 물 block.darksand-tainted-water.name = 오염된 젖은 검은 모래 block.tar.name = 타르 @@ -1145,7 +1147,7 @@ block.sand.name = 모래 block.darksand.name = 검은 모래 block.ice.name = 얼음 block.snow.name = 눈 -block.craters.name = 구덩이 +block.crater-stone.name = 구덩이 block.sand-water.name = 젖은 모래 block.darksand-water.name = 젖은 검은 모래 block.char.name = 숯 @@ -1290,7 +1292,6 @@ block.meltdown.name = 멜트다운 block.foreshadow.name = 포어쉐도우 block.container.name = 컨테이너 block.launch-pad.name = 지역 자원 수송기 -block.launch-pad-large.name = 대형 지역 자원 수송기 block.segment.name = 세그먼트 block.command-center.name = 유닛 지휘소 block.ground-factory.name = 지상 공장 @@ -1311,11 +1312,11 @@ block.payload-source.name = 화물 공급기 block.disassembler.name = 광재 분해기 block.silicon-crucible.name = 실리콘 도가니 block.overdrive-dome.name = 대형 과부하 프로젝터 +block.interplanetary-accelerator.name = 성간 코어 가속기 #experimental, may be removed / 이 아래의 블록들은 테스트용 임시 블록들이였습니다. block.block-forge.name = 블록 제작대 block.block-loader.name = 블록 로더 block.block-unloader.name = 블록 언로더 -block.interplanetary-accelerator.name = 성간 코어 가속기 block.switch.name = 스위치 block.micro-processor.name = 마이크로 프로세서 @@ -1350,6 +1351,7 @@ hint.placeTurret = 적에게서 기지를 막아내려면 \uf861 [accent]포탑[ hint.breaking = 블록을 부수려면 [accent]우클릭[]이나 드래그를 하십시오. hint.breaking.mobile = 블록을 부수려면 오른쪽 아래의 \ue817 [accent]망치[]를 눌러 해체 모드를 활성화하십시오.\n\n손가락으로 누른 채로 끌어서 해체 범위를 지정하십시오. hint.blockInfo = [accent]건설 메뉴[]에서 블록을 선택해서 정보를 보십시오, 그다음 오른쪽의 [accent][[?][] 버튼을 선택하십시오. +hint.derelict = [accent]버려진[] 구조물들은 더 이상 작동하지 않는 오래된 기지의 부서진 잔해입니다.\n\n이 구조물들은 자원으로 다시 [accent]철거[]될 수 있습니다. hint.research = 새 기술을 연구하려면 \ue875 [accent]연구[]버튼을 누르십시오. hint.research.mobile = 새 기술을 연구하려면 \ue88c [accent]메뉴[] 아래의 \ue875 [accent]연구[]버튼을 누르십시오. hint.unitControl = 아군 유닛과 포탑을 조종하려면 [accent][[왼쪽 ctrl][]을 누른 채로 [accent]클릭[] 하십시오. @@ -1401,6 +1403,7 @@ liquid.slag.description = 다양한 종류의 금속들이 함께 섞여 녹아 liquid.oil.description = 고급 재료 생산에 사용되는 액체. 석탄으로 전환하거나 무기로 뿌려서 불을 지를 수 있습니다. liquid.cryofluid.description = 물과 티타늄으로 만든 비부식성 액체. 열용량이 매우 높으며 냉각수로 광범위하게 사용됩니다. +block.derelict = [lightgray] 버려짐[] block.resupply-point.description = 주변 유닛들에 구리 탄약을 보급합니다. 배터리 전력이 필요한 유닛들은 호환되지 않습니다. block.armored-conveyor.description = 앞으로 자원들을 운반합니다. 측면에서 자원들을 받아들이지 않습니다. block.illuminator.description = 발광합니다. @@ -1545,6 +1548,8 @@ block.memory-bank.description = 프로세서를 위한 데이터를 저장합니 block.logic-display.description = 프로세서를 이용해 그래픽을 출력할 수 있습니다. block.large-logic-display.description = 프로세서를 이용해 그래픽을 출력할 수 있습니다. block.interplanetary-accelerator.description = 거대한 전자기 레일건 타워. 코어를 행성 간 이동을 위한 탈출 속도까지 가속합니다. +block.repair-turret.description = 가장 가까운 유닛을 지속적으로 수리합니다. 냉각수를 넣을 수 있습니다. +block.payload-propulsion-tower.description = 장거리 화물 운반 구조물. 화물을 연결된 다른 화물 추진탑으로 발사합니다. unit.dagger.description = 주변 모든 적에게 일반적인 탄환을 발사합니다. unit.mace.description = 주변 모든 적에게 화염 줄기를 발사합니다. @@ -1579,6 +1584,11 @@ unit.omura.description = 적에게 장거리 관통 레일건을 발사합니다 unit.alpha.description = 적으로부터 코어: 조각을 방어합니다. 구조물을 짓습니다. unit.beta.description = 적으로부터 코어: 기반을 방어합니다. 구조물을 짓습니다. unit.gamma.description = 적으로부터 코어: 핵심을 방어합니다. 구조물을 짓습니다. +unit.retusa.description = 근접 시한지뢰를 설치합니다. 아군 유닛을 수리할 수 있습니다. +unit.oxynoe.description = 주변 적에게 블록을 수리하는 화염을 발사합니다. 주변 적 탄환을 요격 포탑으로 요격할 수 있습니다. +unit.cyerce.description = 주변 적에게 유도 집속 미사일을 발사합니다. 아군 유닛을 수리할 수 있습니다. +unit.aegires.description = 애너지 필드 안의 모든 적 유닛과 블록을 감전시킵니다. 아군에겐 전격으로 수리합니다. +unit.navanax.description = 적 전력망에 상당한 피해를 주고 아군 블록을 수리하는 거대한 EMP 고폭탄을 발사합니다. 4개의 자율 레이저 포탑으로 주변 적을 녹입니다. lst.read = 연결된 메모리 셀에서 숫자 읽기 lst.write = 연결된 메모리 셀에 숫자 쓰기 @@ -1631,7 +1641,7 @@ lenum.always = 항상 참 lenum.idiv = 정수 나누기 lenum.div = 나누기\n0으로 나누면 [accent]null[]을 반환합니다. lenum.mod = 나머지 -lenum.equal = 동치 비교. 형변환 가능\nNull이 아닌 객체가 숫자와 비교할려면 1이 되고, Null이면 0이 됩니다. +lenum.equal = 동치 비교. 형변환 가능\nNull이 아닌 객체가 숫자와 비교하려면 1이 되고, Null이면 0이 됩니다. lenum.notequal = 동치 부정. 형변환 가능 lenum.strictequal = 엄격한 동치 비교. 형변환 불가능\n[accent]null[]를 확인하는데 쓸 수 있습니다. lenum.shl = 왼쪽으로 비트 이동 @@ -1818,7 +1828,7 @@ block.inverted-sorter.details = block.distributor.details = block.overflow-gate.details = block.underflow-gate.details = -block.mass-driver.details = [lightgray][비공식][]발사할려면 최소 아이템 10개가 필요하다. +block.mass-driver.details = [lightgray][비공식][]발사하려면 최소 아이템 10개가 필요하다. block.mechanical-pump.details = block.rotary-pump.details = block.thermal-pump.details = diff --git a/core/assets/bundles/bundle_lt.properties b/core/assets/bundles/bundle_lt.properties index 0a8290e544..4add695c67 100644 --- a/core/assets/bundles/bundle_lt.properties +++ b/core/assets/bundles/bundle_lt.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Smėlio Riedulys block.grass.name = Žolė -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Druska block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Priešų Atsiradimo Zona block.core-shard.name = Branduolys: Šerdis block.core-foundation.name = Branduolys: Pagrindas block.core-nucleus.name = Branduolys: Centras -block.deepwater.name = Gilus Vanduo -block.water.name = Vanduo +block.deep-water.name = Gilus Vanduo +block.shallow-water.name = Vanduo block.tainted-water.name = Užterštas Vanduo block.darksand-tainted-water.name = Tamsaus Smėlio Užterštas Vanduo block.tar.name = Derva @@ -1001,7 +1001,7 @@ block.sand.name = Smėlis block.darksand.name = Tamsus Smėlis block.ice.name = Ledas block.snow.name = Sniegas -block.craters.name = Krateriai +block.crater-stone.name = Krateriai block.sand-water.name = Smėlio vanduo block.darksand-water.name = Tamsaus Smėlio Vanduo block.char.name = Char diff --git a/core/assets/bundles/bundle_nl.properties b/core/assets/bundles/bundle_nl.properties index 6523ead319..b9de625fe1 100644 --- a/core/assets/bundles/bundle_nl.properties +++ b/core/assets/bundles/bundle_nl.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Zandkei block.grass.name = Gras -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Zout block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Vijandelijke Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Diep Water -block.water.name = Water +block.deep-water.name = Diep Water +block.shallow-water.name = Water block.tainted-water.name = Vervuild Water block.darksand-tainted-water.name = Donker Zand Vervuild Water block.tar.name = Olie @@ -1001,7 +1001,7 @@ block.sand.name = Donker Zand block.darksand.name = Donker Zand block.ice.name = Ijs block.snow.name = Sneeuw -block.craters.name = Krarters +block.crater-stone.name = Krarters block.sand-water.name = Zand water block.darksand-water.name = Donker Zand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_nl_BE.properties b/core/assets/bundles/bundle_nl_BE.properties index 2f6d94840c..ce3afc9610 100644 --- a/core/assets/bundles/bundle_nl_BE.properties +++ b/core/assets/bundles/bundle_nl_BE.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Sand Boulder block.grass.name = Grass -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Salt block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Deep Water -block.water.name = Water +block.deep-water.name = Deep Water +block.shallow-water.name = Water block.tainted-water.name = Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar @@ -1001,7 +1001,7 @@ block.sand.name = Sand block.darksand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.craters.name = Craters +block.crater-stone.name = Craters block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index c89019a76f..38d2bfbcbe 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -41,7 +41,7 @@ be.ignore = Zignoruj be.noupdates = Nie znaleziono aktualizacji. be.check = Sprawdź aktualizacje -mod.featured.dialog.title = Przeglądarka Modów +mods.browser = Przeglądarka Modów mods.browser.selected = Wybrany Mod mods.browser.add = Zainsta-\nluj Moda mods.browser.reinstall = Przeins-\ntaluj @@ -67,6 +67,14 @@ schematic.delete.confirm = Ten schemat zostanie usunięty. schematic.rename = Zmień nazwę schematu schematic.info = {0}x{1}, {2} bloków schematic.disabled = [scarlet]Schematy są wyłączone[]\nNie możesz używać schematów na tej [accent]mapie[] lub [accent]serwerze. +schematic.tags = Tagi: +schematic.edittags = Zmień Znacznik +schematic.addtag = Dodaj Znacznik +schematic.texttag = Tekst Znacznika +schematic.icontag = Ikona Znacznika +schematic.renametag = Zmień Nazwę Znacznika +schematic.tagdelconfirm = Czy kompletnie usunąć znacznik? +schematic.tagexists = Taki znacznik już istnieje. stats = Statystyki stat.wave = Fale powstrzymane:[accent] {0} @@ -159,7 +167,7 @@ planetmap = Mapa Planety launchcore = Wystrzel Rdzeń filename = Nazwa Pliku: unlocked = Odblokowano nową zawartość! -available =Nowe Odkrycie dostępne +available = Nowe Odkrycie dostępne completed = [accent]Ukończony techtree = Drzewo Techno-\nlogiczne research.legacy = Znaleziono badania z wersji [accent]5.0[].\nChcesz [accent]załadować je[], czy [accent]usunąć[] dane z drzewa technologicznego w nowej kampanii (zalecane)? @@ -502,7 +510,7 @@ memory = Pam: {0}mb memory2 = Pam:\n {0}mb +\n {1}mb language.restart = Uruchom grę ponownie, aby nowo ustawiony język zaczął funkcjonować. settings = Ustawienia -tutorial = Poradnik +tutorial = Samouczek tutorial.retake = Ponów Samouczek editor = Edytor mapeditor = Edytor Map @@ -530,7 +538,7 @@ launch.from = Wystrzelony z: [accent]{0} launch.destination = Cel: {0} configure.invalid = Ilość musi być liczbą pomiędzy 0 a {0}. add = Dodaj... -boss.health = Zdrowie Strażnika +guardian = Zdrowie Strażnika connectfail = [crimson]Nie można połączyć się z serwerem:\n\n[accent]{0} error.unreachable = Serwer niedostępny.\nSprawdź, czy adres jest wpisany poprawnie. @@ -620,6 +628,20 @@ sector.extractionOutpost.description = Odległa placówka zbudowana przez wroga sector.impact0078.description = Tutaj leżą pozostałości międzygwiezdnego statku transportowego, który jako pierwszy wszedł do tego układu.\n\nWydobądź jak najwięcej z wraku. Zbadaj każdą nienaruszoną technologię. sector.planetaryTerminal.description = Ostatni cel.\n\nTa baza przybrzeżna zawiera strukturę zdolną do wyrzucania rdzeni na lokalne planety. Jest wyjątkowo dobrze strzeżona.\n\nProdukuj jednostki morskie. Jak najszybciej wyeliminuj wroga. Zbadaj tą strukturę. +status.burning.name = Podpalenie +status.freezing.name = Zamrożenie +status.wet.name = Mokrość +status.muddy.name = Zabłocenie +status.melting.name = Topnienie +status.sapped.name = Osłabienie +status.electrified.name = Naelektryzowanie +status.spore-slowed.name = Zarodnikowe Spowolnienie +status.tarred.name = Osmołowanie +status.overclock.name = Przyspieszenie +status.shocked.name = Porażenie +status.blasted.name = Wysadzenie +status.unmoving.name = Unieruchomienie + settings.language = Język settings.data = Dane Gry settings.reset = Przywróć Domyślne @@ -655,7 +677,8 @@ stat.input = Wejście stat.output = Wyjście stat.booster = Wzmacniacz stat.tiles = Wymagane Pola -stat.affinities = Uwydajnienie +stat.affinities = Uwydajnienia +stat.opposites = Przeciwieństwa stat.powercapacity = Pojemność mocy stat.powershot = moc/strzał stat.damage = Obrażenia @@ -703,7 +726,7 @@ stat.lightningchance = Szansa Na Błyskawicę stat.lightningdamage = Obrażenia Błyskawic stat.flammability = Palność stat.radioactivity = Radioaktywność -stat.charge = Charge +stat.charge = Naładowanie stat.heatcapacity = Pojemność Cieplna stat.viscosity = Lepkość stat.temperature = Temperatura @@ -717,13 +740,21 @@ stat.abilities = Umiejętności stat.canboost = Może przyspieszyć stat.flying = Może latać stat.ammouse = Zużycie Amunicji +stat.damagemultiplier = Mnożnik Obrażeń +stat.healthmultiplier = Mnożnik Zdrowia +stat.speedmultiplier = Mnożnik Prędkości +stat.reloadmultiplier = Mnożnik Prędkości Przeładowywania +stat.buildspeedmultiplier = Mnożnik Prędkości Budowania +stat.reactive = Reaguje +stat.healing = Leczy -ability.forcefield = Pole Mocy +ability.forcefield = Pole Siłowe ability.repairfield = Pole Naprawy ability.statusfield = Pole Statusu ability.unitspawn = Fabryka Jednostek {0} ability.shieldregenfield = Strefa Tarczy Regenerującej ability.movelightning = Pioruny Poruszania +ability.energyfield = Pole Energii: [accent]{0}[] obrażenia ~ [accent]{1}[] bloki / [accent]{2}[] cele bar.drilltierreq = Wymagane Lepsze Wiertło bar.noresources = Brak Zasobów @@ -746,6 +777,7 @@ bar.power = Prąd bar.progress = Postęp Budowy bar.input = Wejście bar.output = Wyjście +bar.strength = [stat]{0}[lightgray]x siły units.processorcontrol = [lightgray]Kontrolowany przez procesor @@ -756,6 +788,7 @@ bullet.sapping = [stat]wyczerpujący bullet.homing = [stat]naprowadzający bullet.shock = [stat]piorunowy bullet.frag = [stat]fragmentacyjny +bullet.lightning = [stat]{0}[lightgray]x błyskawice ~ [stat]{1}[lightgray] Obrażenia bullet.buildingdamage = [stat]{0}%[lightgray] obrażeń budynkom bullet.knockback = [stat]{0}[lightgray] odrzut bullet.pierce = [stat]{0}[lightgray]x przebicia @@ -769,6 +802,7 @@ bullet.reload = [stat]{0}[lightgray]x szybkość ataku unit.blocks = bloki unit.blockssquared = bloki² unit.powersecond = jednostek prądu na sekundę +unit.tilessecond = bloków na sekundę unit.liquidsecond = jednostek płynu na sekundę unit.itemssecond = przedmiotów na sekundę unit.liquidunits = jednostek płynu @@ -991,7 +1025,8 @@ rules.weather.duration = Czas trwania: content.item.name = Przedmioty content.liquid.name = Płyny content.unit.name = Jednostki -content.block.name = Klocki +content.block.name = Bloki +content.status.name = Efekty Statusu content.sector.name = Sektory item.copper.name = Miedź @@ -1055,7 +1090,7 @@ block.cliff.name = Klif block.sand-boulder.name = Piaskowy Głaz block.basalt-boulder.name = Bazaltowy Głaz block.grass.name = Trawa -block.slag.name = Żużel +block.molten-slag.name = Żużel block.space.name = Kosmos block.salt.name = Sól block.salt-wall.name = Ściana Solna @@ -1086,8 +1121,8 @@ block.spawn.name = Spawn wrogów block.core-shard.name = Rdzeń: Odłamek block.core-foundation.name = Rdzeń: Podstawa block.core-nucleus.name = Rdzeń: Jądro -block.deepwater.name = Głęboka Woda -block.water.name = Woda +block.deep-water.name = Głęboka Woda +block.shallow-water.name = Woda block.tainted-water.name = Skażona Woda block.darksand-tainted-water.name = Skażona Woda z Ciemnym Piaskiem block.tar.name = Smoła @@ -1096,7 +1131,7 @@ block.sand.name = Piasek block.darksand.name = Czarny piasek block.ice.name = Lód block.snow.name = Śnieg -block.craters.name = Kratery +block.crater-stone.name = Kratery block.sand-water.name = Woda z Piaskiem block.darksand-water.name = Woda z Ciemnym Piaskiem block.char.name = Popiół @@ -1157,7 +1192,7 @@ block.distributor.name = Dystrybutor block.sorter.name = Sortownik block.inverted-sorter.name = Odwrotny Sortownik block.message.name = Wiadomość -block.illuminator.name = Illuminator +block.illuminator.name = Iluminator block.overflow-gate.name = Brama Przepełnieniowa block.underflow-gate.name = Brama Niedomiaru block.silicon-smelter.name = Huta Krzemu @@ -1397,7 +1432,7 @@ block.phase-conveyor.description = Zaawansowany blok transportowy dla przedmiot block.sorter.description = Sortuje przedmioty. Jeśli przedmiot pasuje to przechodzi dalej, jeśli nie - to przechodzi na boki. block.inverted-sorter.description = Sortuje przedmioty jak zwykły sortownik, ale odpowiednie surowce wyciągane są na boki. block.router.description = Akceptuje przedmioty z jednego miejsca i rozdziela je do trzech innych kierunków. Przydatne w rozdzielaniu materiałów z jednego źródła do wielu celów.\n\n[scarlet]Nigdy nie używaj przy punkcje wejścia materiałów produkcyjnych, ponieważ zostaną one zatkane przez materiały wyjściowe.[] -block.router.details = Konieczne zło. Nie zaleca się stosowania obok nakładów produkcyjnych, ponieważ zostaną one zatkane. +block.router.details = Nieuniknione zło. Nie zaleca się stosowania obok nakładów produkcyjnych, ponieważ zostaną one zatkane. block.distributor.description = Zaawansowany rozdzielacz, rozdzielający przedmioty do 7 innych kierunków. block.overflow-gate.description = Rozdzielacz, który przerzuca przedmioty, kiedy główna droga jest przepełniona. block.underflow-gate.description = Odwrotność bramy przepełnieniowej, który przepuszcza przedmioty główną drogą, gdy boczne drogi są przepełnione. @@ -1517,150 +1552,155 @@ unit.risso.description = Strzela sporą ilością pocisków i rakiet w najbliżs unit.minke.description = Strzela granatami i standardowymi pociskami w najbliższych przeciwników. unit.bryde.description = Strzela granatami i rakietami na dużą odległość we wrogów. unit.sei.description = Strzela dużą ilością rakiet oraz przebijających zbroje pocisków we wrogów. -unit.omura.description = Strzela przebijającym superszybkim pociskiem we wrogów ze sporej odległości. Produkuje Błyski (jednostki). +unit.omura.description = Strzela przebijającym superszybkim pociskiem we wrogów ze sporej odległości. Produkuje jednostki Flare. unit.alpha.description = Chroni Rdzeń: Odłamek przed wrogami. Buduje struktury. unit.beta.description = Chroni Rdzeń: Podstawa przed wrogami. Buduje struktury. unit.gamma.description = Chroni Rdzeń: Jądro przed wrogami. Buduje struktury. -lst.read = Read a number from a linked memory cell. -lst.write = Write a number to a linked memory cell. -lst.print = Add text to the print buffer.\nDoes not display anything until [accent]Print Flush[] is used. -lst.draw = Add an operation to the drawing buffer.\nDoes not display anything until [accent]Draw Flush[] is used. -lst.drawflush = Flush queued [accent]Draw[] operations to a display. -lst.printflush = Flush queued [accent]Print[] operations to a message block. -lst.getlink = Get a processor link by index. Starts at 0. -lst.control = Control a building. -lst.radar = Locate units around a building with range. -lst.sensor = Get data from a building or unit. -lst.set = Set a variable. -lst.operation = Perform an operation on 1-2 variables. -lst.end = Jump to the top of the instruction stack. -lst.jump = Conditionally jump to another statement. -lst.unitbind = Bind to the next unit of a type, and store it in [accent]@unit[]. -lst.unitcontrol = Control the currently bound unit. -lst.unitradar = Locate units around the currently bound unit. -lst.unitlocate = Locate a specific type of position/building anywhere on the map.\nRequires a bound unit. +lst.read = Wczytuje liczbę z połączonej komórki pamięci. +lst.write = Zapisuje liczbę do połączonej komórki pamięci. +lst.print = Dodaje tekst do buforu drukującego.\nNie wyświetla niczego dopóki [accent]Print Flush[] nie jest użyte. +lst.draw = Dodaje operacje do buforu rysującego.\nNie wyświetla niczego dopóki [accent]Draw Flush[] nie jest użyte. +lst.drawflush = Wyświetla oczekujące operacje z funkcji [accent]Draw[] na wyświetlaczu. +lst.printflush = Dodaje oczekujące operacje z funkcji [accent]Print[] do bloku wiadomości. +lst.getlink = Zdobywa połączenie procesora przez indeks. Zaczyna się od 0. +lst.control = Kontroluje budynek. +lst.radar = Lokalizuje jednostki wokół budynku w jego zasięgu. +lst.sensor = Zdobywa dane z budynku lub jednostki. +lst.set = Ustawia zmienną. +lst.operation = Wykonuje operację na 1-2 zmiennych. +lst.end = Przeskakuje na początek stosu instrukcji. +lst.wait = Czeka określoną liczbę sekund. +lst.lookup = Znajduje typ przedmiotu/cieczy/jednostki/bloku poprzez ID.\nCałkowite zliczenia każdego typu można uzyskać za pomocą:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] +lst.jump = Warunkowo przeskakuje do innego stanu. +lst.unitbind = Powiązuje z następną jednostką danego typu i przechowuje ją w [accent]@unit[]. +lst.unitcontrol = Kontroluje obecnie powiązaną jednostkę. +lst.unitradar = Lokalizuje jednostki wokół obecnie powiązanej jednostki. +lst.unitlocate = Lokalizuje specyficzny typ pozycji/budynku gdziekolwiek na mapie.\nWymaga powiązanej jednostki. -logic.nounitbuild = [red]Unit building logic is not allowed here. +logic.nounitbuild = [red]Logika budowania jednostek nie jest tu dozwolona. -lenum.type = Type of building/unit.\ne.g. for any router, this will return [accent]@router[].\nNot a string. -lenum.shoot = Shoot at a position. -lenum.shootp = Shoot at a unit/building with velocity prediction. -lenum.configure = Building configuration, e.g. sorter item. -lenum.enabled = Whether the block is enabled. +lenum.type = Typ budynku/jednostki.\nnp. dla każdego rozdzielacza, zwróci [accent]@router[].\nNie jest łańcuchem znaków (string). +lenum.shoot = Strzel w określoną pozycje. +lenum.shootp = Strzel w jednostkę/budynek z przewidywaną prędkością. +lenum.configure = Konfiguracja budowania, np. sortowany przedmiot w sortowniku. +lenum.enabled = Sprawdza czy blok jest włączony. -laccess.color = Illuminator color. -laccess.controller = Unit controller. If processor controlled, returns processor.\nIf in a formation, returns leader.\nOtherwise, returns the unit itself. -laccess.dead = Whether a unit/building is dead or no longer valid. -laccess.controlled = Returns:\n[accent]@ctrlProcessor[] if unit controller is processor\n[accent]@ctrlPlayer[] if unit/building controller is player\n[accent]@ctrlFormation[] if unit is in formation\nOtherwise, 0. -laccess.commanded = [red]Deprecated. Will be removed![]\nUse [accent]controlled[] instead. +laccess.color = Kolor iluminatora. +laccess.controller = Kontroler jednostki. Jeśli jest kontrolowana przez procesor, zwraca procesor.\nJeśli we formacji, zwracja przywódcę.\nW innym wypadku zwraca samą jednostkę. +laccess.dead = Sprawdza czy jednostka/budynek jest zniszczony lub już nie istnieje. +laccess.controlled = Zwraca:\n[accent]@ctrlProcessor[] jeśli kontrolerem jednostki jest procesor\n[accent]@ctrlPlayer[] jeśli kontrolerem jednostki/budynku jest gracz\n[accent]@ctrlFormation[] jeśli jednostka jest w formacji\nW innym wypadku 0. +laccess.commanded = [red]Przestarzałe. Zostanie usunięte![]\nZamiast tego użyj [accent]controlled[]. +laccess.progress = Postęp akcji, od 0 do 1.\nZwraca produkcję, przeładowanie wieżyczki lub postęp konstrukcji. -graphicstype.clear = Fill the display with a color. -graphicstype.color = Set color for next drawing operations. -graphicstype.stroke = Set line width. -graphicstype.line = Draw line segment. -graphicstype.rect = Fill a rectangle. -graphicstype.linerect = Draw a rectangle outline. -graphicstype.poly = Fill a regular polygon. -graphicstype.linepoly = Draw a regular polygon outline. -graphicstype.triangle = Fill a triangle. -graphicstype.image = Draw an image of some content.\nex: [accent]@router[] or [accent]@dagger[]. +graphicstype.clear = Wypełnia wyświetlacz kolorem. +graphicstype.color = Ustawia kolor następnych operacji rysujących. +graphicstype.stroke = Ustawia grubość linii. +graphicstype.line = Rysuje segment linii. +graphicstype.rect = Wypełnia prostokąt. +graphicstype.linerect = Rysuje obwód prostokąta. +graphicstype.poly = Wypełnia regularny wielokąt. +graphicstype.linepoly = Rysuje obwód regularnego wielokąta. +graphicstype.triangle = Wypełnia trójkąt. +graphicstype.image = Rysuje ikonę jakiejś treści.\nnp. [accent]@router[] lub [accent]@dagger[]. -lenum.always = Always true. -lenum.idiv = Integer division. -lenum.div = Division.\nReturns [accent]null[] on divide-by-zero. +lenum.always = Zawsze prawda. +lenum.idiv = Dzielenie liczb całkowitych. +lenum.div = Dzielenie.\nZwraca [accent]null[] w trakcie dzielenia przez zero. lenum.mod = Modulo. -lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0. -lenum.notequal = Not equal. Coerces types. -lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[]. -lenum.shl = Bit-shift left. -lenum.shr = Bit-shift right. -lenum.or = Bitwise OR. -lenum.land = Logical AND. -lenum.and = Bitwise AND. -lenum.not = Bitwise flip. -lenum.xor = Bitwise XOR. +lenum.equal = Równość. Wymusza typ.\nNiezerowe objekty połączone z liczbami stają się 1, w innym wypadku 0. +lenum.notequal = Nierówność. Wymusza typ. +lenum.strictequal = Ścisła równość. Nie wymusza typów.\nMoże być użyte do wykrycia [accent]null[]. +lenum.shl = Przesunięcie bitowe w lewo. +lenum.shr = Przesunięcie bitowe w prawo. +lenum.or = Bitowe OR (lub). +lenum.land = Logiczne AND (i). +lenum.and = Bitowe AND (i). +lenum.not = Bitowe NOT. +lenum.xor = Bitowe XOR. + +lenum.min = Minimum dwóch liczb. +lenum.max = Maksimum dwóch liczb. +lenum.angle = Kąt wektoru w stopniach. +lenum.len = Długość wektoru. + +lenum.sin = Sinus, w stopniach. +lenum.cos = Cosinus, w stopniach. +lenum.tan = Tangens, w stopniach. -lenum.min = Minimum of two numbers. -lenum.max = Maximum of two numbers. -lenum.angle = Angle of vector in degrees. -lenum.len = Length of vector. -lenum.sin = Sine, in degrees. -lenum.cos = Cosine, in degrees. -lenum.tan = Tangent, in degrees. #not a typo, look up 'range notation' -lenum.rand = Random decimal in range [0, value). -lenum.log = Natural logarithm (ln). -lenum.log10 = Base 10 logarithm. -lenum.noise = 2D simplex noise. -lenum.abs = Absolute value. -lenum.sqrt = Square root. +lenum.rand = Losowa liczba w przedziale [0, wartość). +lenum.log = Logarytm naturalny (ln). +lenum.log10 = Logarytm o podstawie 10. +lenum.noise = Szum simplex 2D. +lenum.abs = Wartość bezwzględna. +lenum.sqrt = Pierwiastek kwadratowy. -lenum.any = Any unit. -lenum.ally = Ally unit. -lenum.attacker = Unit with a weapon. -lenum.enemy = Enemy unit. -lenum.boss = Guardian unit. -lenum.flying = Flying unit. -lenum.ground = Ground unit. -lenum.player = Unit controlled by a player. +lenum.any = Dowolna jednostka. +lenum.ally = Sojusznicza jednostka. +lenum.attacker = Jednostka z bronią. +lenum.enemy = Przeciwnik. +lenum.boss = Strażnik. +lenum.flying = Latająca jednostka. +lenum.ground = Jednostka lądowa. +lenum.player = Jednostka kontrolowana przez gracza. -lenum.ore = Ore deposit. -lenum.damaged = Damaged ally building. -lenum.spawn = Enemy spawn point.\nMay be a core or a position. -lenum.building = Building in a specific group. +lenum.ore = Depozyt rudy. +lenum.damaged = Uszkodzony sojuszniczy budynek. +lenum.spawn = Punkt zrzutu przeciwnika.\nMoże być rdzeniem lub pozycją. +lenum.building = Budynek ze specyficznej grupy. -lenum.core = Any core. -lenum.storage = Storage building, e.g. Vault. -lenum.generator = Buildings that generate power. -lenum.factory = Buildings that transform resources. -lenum.repair = Repair points. -lenum.rally = Command center. -lenum.battery = Any battery. -lenum.resupply = Resupply points.\nOnly relevant when [accent]"Unit Ammo"[] is enabled. -lenum.reactor = Impact/Thorium reactor. -lenum.turret = Any turret. +lenum.core = Dowolny rdzeń. +lenum.storage = Budynek przechowujący, np. Magazyn. +lenum.generator = Budynki generujące prąd. +lenum.factory = Budynki przetwarzające surowce. +lenum.repair = Punkty naprawy. +lenum.rally = Centrum dowodzenia. +lenum.battery = Dowolna bateria. +lenum.resupply = Punkty uzupełniające.\nMa znaczenie tylko gdy [accent]"Unit Ammo"[] jest załączone. +lenum.reactor = Reaktor uderzeniowy/torowy. +lenum.turret = Dowolna wieżyczka. -sensor.in = The building/unit to sense. +sensor.in = Wykrywany budynek/jednostka. -radar.from = Building to sense from.\nSensor range is limited by building range. -radar.target = Filter for units to sense. -radar.and = Additional filters. -radar.order = Sorting order. 0 to reverse. -radar.sort = Metric to sort results by. -radar.output = Variable to write output unit to. +radar.from = Budynek wykrywający.\nZasięg czujnika jest limitowany przez zasięg budynku. +radar.target = Filtr wykrywanych jednostek. +radar.and = Dodatkowe filtry. +radar.order = Kolejność sortowania. 0 aby odwrócić. +radar.sort = Wartość, według której będą sortowane wyniki. +radar.output = Zmienna, do której zostanie przypisana jednostka wyjściowa. -unitradar.target = Filter for units to sense. -unitradar.and = Additional filters. -unitradar.order = Sorting order. 0 to reverse. -unitradar.sort = Metric to sort results by. -unitradar.output = Variable to write output unit to. +unitradar.target = Filtr wykrywanych jednostek. +unitradar.and = Dodatkowe filtry. +unitradar.order = Kolejność sortowania. 0 aby odwrócić. +unitradar.sort = Wartość, według której będą sortowane wyniki. +unitradar.output = Zmienna, do której zostanie przypisana jednostka wyjściowa. -control.of = Building to control. -control.unit = Unit/building to aim at. -control.shoot = Whether to shoot. +control.of = Kontrolowany budynek. +control.unit = Jednostka/budynek, w którą ma celować. +control.shoot = Strzelanie. -unitlocate.enemy = Whether to locate enemy buildings. -unitlocate.found = Whether the object was found. -unitlocate.building = Output variable for located building. -unitlocate.outx = Output X coordinate. -unitlocate.outy = Output Y coordinate. -unitlocate.group = Building group to look for. +unitlocate.enemy = Lokalizowanie budynków przeciwnika. +unitlocate.found = Znalezienie obiektu. +unitlocate.building = Zmienna wyjściowa dla zlokalizowanego budynku. +unitlocate.outx = Wyjściowy koordynat X. +unitlocate.outy = Wyjściowy koordynat Y. +unitlocate.group = Grupa szukanych budynków. -lenum.idle = Don't move, but keep building/mining.\nThe default state. -lenum.stop = Stop moving/mining/building. -lenum.move = Move to exact position. -lenum.approach = Approach a position with a radius. -lenum.pathfind = Pathfind to the enemy spawn. -lenum.target = Shoot a position. -lenum.targetp = Shoot a target with velocity prediction. -lenum.itemdrop = Drop an item. -lenum.itemtake = Take an item from a building. -lenum.paydrop = Drop current payload. -lenum.paytake = Pick up payload at current location. -lenum.flag = Numeric unit flag. -lenum.mine = Mine at a position. -lenum.build = Build a structure. -lenum.getblock = Fetch a building and type at coordinates.\nUnit must be in range of position.\nSolid non-buildings will have the type [accent]@solid[]. -lenum.within = Check if unit is near a position. -lenum.boost = Start/stop boosting. +lenum.idle = Przestań się poruszać, jednak nadal buduj/wydobywaj.\nDomyślny stan. +lenum.stop = Przestań poruszać się/kopać/budować. +lenum.move = Przemieść się do określonej pozycji. +lenum.approach = Podejdź do pozycji w promieniu. +lenum.pathfind = Odnajdź ścieżkę do punktu zrzutu przeciwników. +lenum.target = Strzel w określoną pozycje. +lenum.targetp = Strzel w jednostkę/budynek z przewidywaną prędkością. +lenum.itemdrop = Upuść przedmiot. +lenum.itemtake = Zabierz przedmiot z budynku. +lenum.paydrop = Upuść obecny ładunek. +lenum.paytake = Podnieś ładunek z obecnego miejsca. +lenum.flag = Numeryczny znacznik jednostki. +lenum.mine = Kop na danej pozycji. +lenum.build = Buduj strukturę. +lenum.getblock = Pobierz budynek i typ z koordynatów.\nJednostka musi być w zasięgu pozycji.\nSolidne niebudynki będą miały typ [accent]@solid[]. +lenum.within = Sprawdź czy jednostka jest w pobliżu pozycji. +lenum.boost = Zacznij/zakończ boostować. diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties index 20818e5d05..ee276a99a0 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -1073,7 +1073,7 @@ block.parallax.name = Paralaxe block.cliff.name = Relevo block.sand-boulder.name = Pedregulho de areia block.grass.name = Grama -block.slag.name = Escória +block.molten-slag.name = Escória block.space.name = Space block.salt.name = Sal block.salt-wall.name = Parede de sal @@ -1104,8 +1104,8 @@ block.spawn.name = Área inimiga block.core-shard.name = Fragmento do núcleo block.core-foundation.name = Fundação do núcleo block.core-nucleus.name = Centro do núcleo -block.deepwater.name = Água profunda -block.water.name = Água +block.deep-water.name = Água profunda +block.shallow-water.name = Água block.tainted-water.name = Água tinta block.darksand-tainted-water.name = Água tinta sobre areia escura block.tar.name = Piche @@ -1114,7 +1114,7 @@ block.sand.name = Areia block.darksand.name = Areia escura block.ice.name = Gelo block.snow.name = Neve -block.craters.name = Crateras +block.crater-stone.name = Crateras block.sand-water.name = Água sobre areia block.darksand-water.name = Água sobre areia escura block.char.name = Cinzas diff --git a/core/assets/bundles/bundle_pt_PT.properties b/core/assets/bundles/bundle_pt_PT.properties index 6e08cc7d3f..a9894b0d6b 100644 --- a/core/assets/bundles/bundle_pt_PT.properties +++ b/core/assets/bundles/bundle_pt_PT.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Pedregulho de areia block.grass.name = Grama -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Sal block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Spawn dos inimigos block.core-shard.name = Fragmento do núcleo block.core-foundation.name = Fundação do núcleo block.core-nucleus.name = Núcleo do núcleo -block.deepwater.name = Água profunda -block.water.name = Água +block.deep-water.name = Água profunda +block.shallow-water.name = Água block.tainted-water.name = Água contaminada block.darksand-tainted-water.name = Água contaminada sobre areia escura block.tar.name = Piche @@ -1001,7 +1001,7 @@ block.sand.name = Areia block.darksand.name = Areia escura block.ice.name = Gelo block.snow.name = Neve -block.craters.name = Crateras +block.crater-stone.name = Crateras block.sand-water.name = Água sobre areia block.darksand-water.name = Água sobre areia escura block.char.name = Char diff --git a/core/assets/bundles/bundle_ro.properties b/core/assets/bundles/bundle_ro.properties index 71c94ec606..529254eb2e 100644 --- a/core/assets/bundles/bundle_ro.properties +++ b/core/assets/bundles/bundle_ro.properties @@ -100,6 +100,7 @@ joingame = Intră în Joc customgame = Personalizat newgame = Joc Nou none.found = [lightgray] +none.inmap = [lightgray] none = minimap = Minihartă position = Poziție @@ -564,7 +565,8 @@ weather.fog.name = Ceață sectors.unexplored = [lightgray]Neexplorat sectors.resources = Resurse: sectors.production = Producție: -sectors.export = Export: +sectors.export = Exportă: +sectors.import = Importă: sectors.time = Timp: sectors.threat = Amenințare: sectors.wave = Valul: @@ -643,7 +645,7 @@ status.electrified.name = Electrificat status.spore-slowed.name = Încetinit de Spori status.tarred.name = Păcurit status.overclock.name = Suprasolicitat -status.shocked.name = Șoc +status.shocked.name = Electrocutat status.blasted.name = Explozie status.unmoving.name = Nemișcat @@ -724,7 +726,7 @@ stat.maxconsecutive = Maxim Consecutive stat.buildcost = Cost Construcție stat.inaccuracy = Inacuratețe stat.shots = Lovituri -stat.reload = Lovituri/Secundă +stat.reload = Rata de Tragere stat.ammo = Muniție stat.shieldhealth = Viață Scut stat.cooldowntime = Timp de Reîncărcare @@ -793,10 +795,10 @@ bullet.damage = [stat]{0}[lightgray] forță bullet.splashdamage = [stat]{0}[lightgray] forță pe raza ~[stat] {1}[lightgray] pătrate bullet.incendiary = [stat]incendiar bullet.homing = [stat]cu radar -bullet.frag = [stat]se sparge +bullet.frags = [stat]{0}[lightgray]x fragmente: bullet.lightning = [stat]{0}[lightgray]x fulgere ~ [stat]{1}[lightgray] forță bullet.buildingdamage = [stat]{0}%[lightgray] forță/clădire -bullet.knockback = [stat]{0} [lightgray]împingere +bullet.knockback = [stat]{0}[lightgray] împingere bullet.pierce = [stat]{0}[lightgray]x penetrează bullet.infinitepierce = [stat]penetrează bullet.healpercent = [stat]{0}[lightgray]% reparare @@ -806,6 +808,7 @@ bullet.reload = [stat]{0}[lightgray]x lovituri unit.blocks = blocuri unit.blockssquared = blocuri² unit.powersecond = electricitate/secundă +unit.tilessecond = pătrate/secundă unit.liquidsecond = unități lichid/secundă unit.itemssecond = materiale/secundă unit.liquidunits = unități lichid @@ -821,7 +824,7 @@ unit.shieldhealth = viață scut unit.items = materiale unit.thousands = mii unit.millions = mil -unit.billions = b +unit.billions = mld unit.pershot = /lovitură category.purpose = Utilizare category.general = General @@ -844,7 +847,6 @@ setting.doubletapmine.name = Dublu-Click pt a Mina setting.modcrashdisable.name = Dezactivează Modurile în Cazul unui Crash la Pornire setting.animatedwater.name = Suprafețe Animate setting.animatedshields.name = Scuturi Animate -setting.antialias.name = Antialiasing[lightgray] (necesită repornire)[] setting.playerindicators.name = Indicatori Jucător setting.indicators.name = Indicatori Inamic setting.autotarget.name = Auto-Țintire @@ -853,7 +855,8 @@ setting.touchscreen.name = Controale Touchscreen setting.fpscap.name = FPS Maxim setting.fpscap.none = Niciuna setting.fpscap.text = FPS (0) -setting.uiscale.name = Scară Interfață [lightgray] (repornirea necesară)[] +setting.uiscale.name = Scară Interfață +setting.uiscale.description = Repornire necesară pt a aplica schimbările. setting.swapdiagonal.name = Plasează Mereu Diagonal setting.difficulty.training = Antrenament setting.difficulty.easy = Ușor @@ -871,7 +874,8 @@ setting.saveinterval.name = Interval de Salvare setting.seconds = {0} secunde setting.milliseconds = {0} millisecunde setting.fullscreen.name = Ecran Complet -setting.borderlesswindow.name = Fereastră Fără Margine[lightgray] (repornirea poate fi necesară) +setting.borderlesswindow.name = Fereastră Fără Margine +setting.borderlesswindow.description = Repornirea poate fi necesară pt a aplica schimbările. setting.fps.name = Vezi FPS & Ping setting.smoothcamera.name = Cameră Graduală setting.vsync.name = VSync @@ -994,6 +998,7 @@ rules.wavetimer = Valuri pe Timp rules.waves = Valuri rules.attack = Modul Atac rules.buildai = AI-ul Construiește +rules.cleanupdeadteams = Îndepărtează Clădirile Echipelor Învinse (PvP) rules.corecapture = Capturează Nucleele Distruse rules.enemyCheat = Resurse infinite pt AI (echipa roșie) rules.blockhealthmultiplier = Multiplicatorul Vieții Blocurilor @@ -1102,7 +1107,7 @@ block.cliff.name = Deal block.sand-boulder.name = Bolovan de Nisip block.grass.name = Iarbă block.basalt-boulder.name = Bolovan de Bazalt -block.slag.name = Zgură +block.molten-slag.name = Zgură block.space.name = Cosmos block.salt.name = Sare block.salt-wall.name = Perete de Sare @@ -1133,8 +1138,8 @@ block.spawn.name = Punctul de Lansare Inamic block.core-shard.name = Nucleu: Shard block.core-foundation.name = Nucleu: Foundation block.core-nucleus.name = Nucleu: Core -block.deepwater.name = Apă Adâncă -block.water.name = Apă +block.deep-water.name = Apă Adâncă +block.shallow-water.name = Apă block.tainted-water.name = Apă Tulbure block.darksand-tainted-water.name = Apă Tulbure cu Nisip Negru block.tar.name = Păcură @@ -1143,7 +1148,7 @@ block.sand.name = Nisip block.darksand.name = Nisip Negru block.ice.name = Gheață block.snow.name = Zăpadă -block.craters.name = Cratere +block.crater-stone.name = Cratere block.sand-water.name = Apă cu Nisip block.darksand-water.name = Apă cu Nisip Negru block.char.name = Turbă @@ -1278,7 +1283,7 @@ block.surge-wall.name = Perete de Aliaj block.surge-wall-large.name = Perete Mare de Aliaj block.cyclone.name = Ciclon block.fuse.name = Fuse -block.shock-mine.name = Mină cu Șocuri +block.shock-mine.name = Mină cu Electroșocuri block.overdrive-projector.name = Proiector de Suprasolicitare block.force-projector.name = Proiector de Forță block.arc.name = Arc @@ -1288,7 +1293,6 @@ block.meltdown.name = Meltdown block.foreshadow.name = Foreshadow block.container.name = Container block.launch-pad.name = Platformă de Lansare -block.launch-pad-large.name = Platformă de Lansare Mare block.segment.name = Segment block.command-center.name = Centru de Comandă block.ground-factory.name = Fabrică Unități Artilerie @@ -1348,6 +1352,7 @@ hint.placeTurret = Construiește \uf861 [accent]Arme[] pt a-ți apăra baza de i hint.breaking = Ține apăsat [accent]click-dreapta[] și trage pe ecran pt a distruge blocuri. hint.breaking.mobile = Activează \ue817 [accent]ciocanul[] din dreapta-jos și dă click pt a distruge blocuri.\n\nȚine apăsat cu degetul pt o secundă și trage pt a distruge mai multe blocuri deodată. hint.blockInfo = Poți vedea informații despre un bloc selectându-l în [accent]meniul de construcție[] și dând click pe butonul [accent][[?][] din dreapta. +hint.derelict = [accent]Structurile abandonate[] sunt rămășițe stricate ale bazelor vechi care nu mai funcționează.\n\nAceste structuri pot fi [accent]deconstruite[] pt resurse. hint.research = Folosește butonul \ue875 [accent]Cercetează[] pt a cerceta noi tehnologii. hint.research.mobile = Folosește butonul \ue875 [accent]Cercetează[] din \ue88c [accent]Meniu[] pt a cerceta noi tehnologii. hint.unitControl = Ține apăsat [accent][[Ctrl][] și [accent]dă click[] pt a controla unități aliate sau arme. @@ -1399,6 +1404,7 @@ liquid.slag.description = Rafinată în separatoare înapoi în materialele cons liquid.oil.description = Folosit în producerea avansată de materiale și ca muniție incendiară. liquid.cryofluid.description = Folosit ca răcitor în reactoare, arme și fabrici. +block.derelict = [lightgray] Structuri Abandonate block.resupply-point.description = Realimentează unitățile din apropiere cu muniție de cupru. Nu este compatibil cu unitățile care se încarcă din baterii. block.armored-conveyor.description = Transportă materialele înainte. Nu acceptă materiale de pe lateral decât de la alte benzi. block.illuminator.description = Emite lumină. @@ -1457,7 +1463,7 @@ block.router.details = Un rău necesar. Nu folosi niciodată pt a introduce mate block.distributor.description = Distribuie materialele primite în alte 7 direcții în mod egal. block.overflow-gate.description = Transportă materialele doar la stânga și dreapta dacă drumul din față este blocat. block.underflow-gate.description = Opusul porții de revărsare. Transportă materialele în față dacă benzile din stânga și dreapta sunt blocate. -block.mass-driver.description = Dispozitiv folosit pt transportul materialelor pe distanțe mari. Adună mai multe materiale și apoi le lansează până la un alt distributor în masă pe o rază mare. +block.mass-driver.description = Structură de transport al materialelor pe distanțe mari. Adună mai multe materiale și apoi le lansează către un alt distributor în masă. block.mechanical-pump.description = Pompează lichide din mediul înconjurător. Nu necesită electricitate. block.rotary-pump.description = Pompează lichide din mediul înconjurător. Necesită electricitate. block.thermal-pump.description = Pompează lichide din mediul înconjurător. @@ -1543,6 +1549,8 @@ block.memory-bank.description = Stochează informație pt un procesor. Capacitat block.logic-display.description = Afișează grafica transmisă de un procesor logic. block.large-logic-display.description = Afișează grafica transmisă de un procesor logic. block.interplanetary-accelerator.description = Un turn masiv cu o armă railgun electromagnetică. Accelerează nucleele la viteză cosmică pt lansare interplanetară. +block.repair-turret.description = Repară încontinuu cea mai deteriorată unitate din vecinătate. Poate accepta răcitor. +block.payload-propulsion-tower.description = Structură de transport al încărcăturii pe distanțe mari. Lansează încărcătura către un alt turn propulsor conectat. unit.dagger.description = Trage cu gloanțe standard către toți inamicii din apropiere. unit.mace.description = Trage cu jeturi de flacără aprinsă către toți inamicii din apropiere. @@ -1577,6 +1585,11 @@ unit.omura.description = Trage cu un railgun cu gloanțe care penetrează scutur unit.alpha.description = Apără nucleul Shard de inamici. Construiește structuri. unit.beta.description = Apără nucleul Foundation de inamici. Construiește structuri. unit.gamma.description = Apără nucleul Core de inamici. Construiește structuri. +unit.retusa.description = Plasează mine de proximitate. Repară unitățile aliate. +unit.oxynoe.description = Trage cu jeturi de flacără către inamicii din apropiere, reparând structurile aliate. Țintește proiectilele inamice din apropiere cu o armă care le deteriorează și distruge. +unit.cyerce.description = Trage cu bombe cu dispersie echipate cu radar către inamici. Repară unitățile aliate. +unit.aegires.description = Electrocutează toate unitățile și structurile inamice care intră în câmpul său de energie. Repară toți aliații. +unit.navanax.description = Trage cu proiectile EMP explozive, lovind rețelele electrice inamice cu o forță semnificativă și reparând structurile aliate. Topește inamicii din apropiere cu cele 4 arme autonome cu laser. lst.read = Citește un număr dintr-o celulă de memorie conectată. lst.write = Scrie un număr într-o celulă de memorie conectată. @@ -1591,6 +1604,8 @@ lst.sensor = Obține date de la o clădire sau unitate. lst.set = Setează o variabilă. lst.operation = Efectuează o operație pe 1-2 variabile. lst.end = Sari la începutul listei de instrucțiuni. +lst.wait = Așteaptă un anumit număr de secunde. +lst.lookup = Caută un tip de material/lichid/unitate/bloc după ID.\nNumărul total din fiecare tip poate fi accesat cu:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] lst.jump = Dacă condiția este adevărată, mergi la o altă instrucțiune. lst.unitbind = Controlează următoarea unitate de tipul selectat și reține-o în [accent]@unit[]. lst.unitcontrol = Controlează unitatea controlată de procesor. diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index 25cfa5d9da..d72304ef21 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -1102,7 +1102,7 @@ block.cliff.name = Скала block.sand-boulder.name = Песчаный валун block.basalt-boulder.name = Базальтовый валун block.grass.name = Трава -block.slag.name = Шлак +block.molten-slag.name = Шлак block.space.name = Космос block.salt.name = Соль block.salt-wall.name = Соляная стена @@ -1133,8 +1133,8 @@ block.spawn.name = Точка появления врагов block.core-shard.name = Ядро: «Осколок» block.core-foundation.name = Ядро: «Штаб» block.core-nucleus.name = Ядро: «Атом» -block.deepwater.name = Глубоководье -block.water.name = Вода +block.deep-water.name = Глубоководье +block.shallow-water.name = Вода block.tainted-water.name = Загрязнённая вода block.darksand-tainted-water.name = Тёмный песок с загрязнённой водой block.tar.name = Нефть @@ -1143,7 +1143,7 @@ block.sand.name = Песок block.darksand.name = Тёмный песок block.ice.name = Лёд block.snow.name = Снег -block.craters.name = Кратеры +block.crater-stone.name = Кратеры block.sand-water.name = Песок с водой block.darksand-water.name = Тёмный песок с водой block.char.name = Выжженная земля diff --git a/core/assets/bundles/bundle_sv.properties b/core/assets/bundles/bundle_sv.properties index 12c3e84a7b..4a0ab8db0f 100644 --- a/core/assets/bundles/bundle_sv.properties +++ b/core/assets/bundles/bundle_sv.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Sandbumling block.grass.name = Gräs -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Salt block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Djupt Vatten -block.water.name = Vatten +block.deep-water.name = Djupt Vatten +block.shallow-water.name = Vatten block.tainted-water.name = Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tjära @@ -1001,7 +1001,7 @@ block.sand.name = Sand block.darksand.name = Mörk Sand block.ice.name = Is block.snow.name = Snö -block.craters.name = Kratrar +block.crater-stone.name = Kratrar block.sand-water.name = Sandvatten block.darksand-water.name = Mörksandvatten block.char.name = Char diff --git a/core/assets/bundles/bundle_th.properties b/core/assets/bundles/bundle_th.properties index f973f39a9a..4dca059487 100644 --- a/core/assets/bundles/bundle_th.properties +++ b/core/assets/bundles/bundle_th.properties @@ -5,7 +5,7 @@ discord = เข้าร่วมเซิร์ฟเวอร์ Discord ข link.discord.description = พื้นที่พูดคุยอย่างเป็นทางการของ Mindustry link.reddit.description = Subreddit ของ Mindustry link.github.description = แหล่งโค้ดของเกม -link.changelog.description = รายการอัพเดต +link.changelog.description = รายการอัปเดต link.dev-builds.description = เวอร์ชั่นระหว่างพัฒนา (ไม่เสถียร) link.trello.description = บอร์ด Trello อย่างเป็นทางการสำหรับฟีเจอร์ต่างๆ ที่วางแผนไว้ link.itch.io.description = หน้าเว็บ itch.io สำหรับดาวน์โหลดบน PC @@ -36,10 +36,10 @@ load.scripts = สคริปต์ be.update = เวอร์ชั่นรุ่นพัฒนาล่าสุดออกแล้ว: be.update.confirm = ดาวน์โหลดเวอร์ชั่นใหม่แล้วรีสตาร์ทเลยไหม? -be.updating = กำลังอัพเดต... +be.updating = กำลังอัปเดต... be.ignore = ยกเลิก -be.noupdates = ไม่พบอัพเดตใหม่ -be.check = ตรวจหาอัพเดตใหม่ +be.noupdates = ไม่พบอัปเดตใหม่ +be.check = ตรวจหาอัปเดตใหม่ mods.browser = ค้นหาม็อด mods.browser.selected = เลือกแล้ว @@ -93,7 +93,7 @@ level.highscore = คะแนนสูงสุด: [accent]{0} level.mode = เกมโหมด: coreattack = < แกนกลางถูกโจมตี! > nearpoint = [[ [scarlet]ออกจากจุดเกิดด่วน![] ]\nการทำลายล้างกำลังใกล้เข้ามา -database = ฐานข้อมูลหลัก +database = ฐานข้อมูลแกนกลาง savegame = เซฟเกม loadgame = โหลดเกม joingame = เข้าร่วมเกม @@ -101,6 +101,7 @@ customgame = เกมที่กำหนดเอง newgame = เริ่มเกมใหม่ none = <ไม่มี> none.found = [lightgray]<ไม่เจออะไรเลย> +none.inmap = [lightgray]<ไม่มีในแมพ> minimap = มินิแมพ position = ตำแหน่ง close = ปิด @@ -155,7 +156,7 @@ mod.jarwarn = [scarlet]ม็อดไฟล์ JAR นั้นค่อนข mod.item.remove = ไอเท็มนี้เป็นส่วนหนึ่งของม็อด [accent]'{0}'[] หากต้องการนำออก กรุณาถอนการติดตั้งม็อดนั้น mod.remove.confirm = ม็อดนี้จะถูกลบ mod.author = [lightgray]ผู้สร้าง:[] {0} -mod.missing = เซฟนี้มีม็อดที่คุณพึ่งอัพเดตหรือไม่ได้ติดตั้งแล้ว อาจทำให้เซฟเสีย คุณแน่จะหรือว่าจะโหลดเซฟนี้?\n[lightgray]ม็อดที่ใช้:\n{0} +mod.missing = เซฟนี้มีม็อดที่คุณพึ่งอัปเดตหรือไม่ได้ติดตั้งแล้ว อาจทำให้เซฟเสีย คุณแน่จะหรือว่าจะโหลดเซฟนี้?\n[lightgray]ม็อดที่ใช้:\n{0} mod.preview.missing = ก่อนที่จะนำม็อดไปลงในเวิร์กช็อป คุณต้องใส่รูปพรีวิวก่อน\nใส่รูปชื่อ[accent] preview.png[] ลงในโฟลเดอร์ของม็อดแล้วลองอีกครั้ง mod.folder.missing = ม็อดที่อยู่ในรูปแบบโฟลเดอร์เท่านั้นที่สามารถลงในเวิร์กช็อปได้\nunzip ไฟล์แล้วลบไฟล์ zip เก่า แล้วรีสตาร์ทเกมหรือรีโหลดม็อด mod.scripts.disable = เครื่องของคุณไม่รองรับม็อดที่มีสคริปต์ คุณจำเป็นต้องปิดม็อดเหล่านี้ก่อนจึงจะสามารถเล่นได้ @@ -166,10 +167,10 @@ noname = ใส่ชื่อ[accent]ผู้เล่น[]ก่อน planetmap = แผนที่ดาวเคราะห์ launchcore = ส่งแกนกลาง filename = ชื่อไฟล์: -unlocked = เนื้อหาใหม่ปลดล็อค! +unlocked = เนื้อหาใหม่ปลดล็อก! available = มีการวิจัยใหม่พร้อมปลดล็อก! completed = [accent]วิจัยแล้ว -techtree = การวิจัย +techtree = ต้นไม้แห่งเทคโนโลยี research.legacy = พบข้อมูลการวิจัยของเวอร์ชั่น [accent]5.0[]\nคุณต้องการ[accent]โหลดข้อมูล[]หรือ[accent]ทิ้งข้อมูลไป[]และเริ่มต้นวิจัยในแคมเปญใหม่ (แนะนำ) research.load = โหลด research.discard = ทอดทิ้ง @@ -186,19 +187,19 @@ server.kicked.kick = คุณถูกเตะออกจากเซิร server.kicked.whitelist = คุณไม่ได้ถูกรับเชิญ\nคนที่ถูกรับเชิญเท่านั้นที่จะเข้าได้ server.kicked.serverClose = เซิร์ฟเวอร์ถูกปิด server.kicked.vote = คุณถูกโหวตเตะออก บัยบาย -server.kicked.clientOutdated = ไคลเอนต์เก่า! กรุณาอัพเดตเกมของคุณ! -server.kicked.serverOutdated = เซิร์ฟเวอร์เก่า! โปรดถามเจ้าของเซิร์ฟเวอร์เพื่ออัพเดต! +server.kicked.clientOutdated = ไคลเอนต์เก่า! กรุณาอัปเดตเกมของคุณ! +server.kicked.serverOutdated = เซิร์ฟเวอร์เก่า! โปรดถามเจ้าของเซิร์ฟเวอร์เพื่ออัปเดต! server.kicked.banned = คุณถูกแบนในเซิร์ฟเวอร์นี้ server.kicked.typeMismatch = เซิร์ฟเวอร์นี้ไม่เข้ากับประเภทบิลด์ของคุณ server.kicked.playerLimit = เซิร์ฟเวอร์เต็ม กรุณารอให้เซิร์ฟเวอร์ว่างก่อน server.kicked.recentKick = คุณเพิ่งถูกเตะออกจากเซิร์ฟเวอร์นี้\nกรุณารอสักครู่เพื่อเข้าร่วมอีกครั้ง -server.kicked.nameInUse = มีคนที่ใช้ชืชื่อนี้\nอยู่ในเซิฟเวอร์แล้ว +server.kicked.nameInUse = มีคนที่ใช้ชื่อนี้\nอยู่ในเซิร์ฟเวอร์แล้ว server.kicked.nameEmpty = ชื่อของคุณไม่สามารถใช้ได้ server.kicked.idInUse = คุณเชื่อมต่อกับเซิร์ฟเวอร์นี้อยู่แล้ว เราไม่อนุญาตให้เชื่อมต่อสองบัญชีในเซิร์ฟเวอร์เดียวกัน server.kicked.customClient = เซิร์ฟเวอร์นี้ไม่รองรับเวอร์ชั่นที่ถูกปรับแต่ง กรุณาโหลดเวอร์ชั่นอย่างเป็นทางการของ Mindustry server.kicked.gameover = จบเกม! server.kicked.serverRestarting = เซิร์ฟเวอร์กำลังเริ่มใหม่ -server.versions = เวอร์ชั่นของคุณ:[accent] {0}[]\nเวอร์ชั่นของเซิฟเวอร์:[accent] {1}[] +server.versions = เวอร์ชั่นของคุณ:[accent] {0}[]\nเวอร์ชั่นของเซิร์ฟเวอร์:[accent] {1}[] host.info = ปุ่ม[accent]โฮสต์[]นั้นโฮสต์เซิร์ฟเวอร์ที่พอร์ต [scarlet]6567[] \nทุกคนที่อยู่ใน [lightgray]Wi-Fi หรือเครือข่ายท้องถิ่น[]เดียวกันจะสามารถเห็นเซิร์ฟเวอร์ของคุณในรายชื่อของ\nเซิร์ฟเวอร์ได้\n\nถ้าคุณต้องการให้ผู้เล่นอื่นๆ สามารถเชื่อมต่อได้จากทุกที่โดยใช้ IP คุณจำเป็นจะต้องใช้การ[accent]การส่งต่อพอร์ต (Port Forwarding)[] \n\n[lightgray]โน๊ต: ถ้าผู้เล่นคนใดมีปัญหาในการเชื่อมต่อ LAN ของคุณ เช็คให้แน่ใจว่าคุณได้อนุญาตให้ Mindustry เข้าถึงเครือข่ายท้องถิ่นของคุณในการตั้งค่า Firewall จำไว้ว่าเครือข่ายสาธารณะบางครั้งอาจไม่อนุญาตการ\nค้นหาเซิร์ฟเวอร์ join.info = คุณสามารถใส่ [accent]IP ของเซิร์ฟเวอร์[]เพื่อที่จะเชื่อมต่อหรือค้นหาเซิร์ฟเวอร์ เซิร์ฟเวอร์ที่ใช้[accent]เครือข่ายท้องถิ่น[]จะสามารถเชื่อมโดยใช้\n LAN หรือ WAN ก็ได้\n\n[lightgray]ถ้าคุณอยากเชื่อมต่อกับใครบางคนโดยใช้ IP คุณต้องไปถามโฮสต์เอาว่า IP ของโฮสต์คืออะไร ซึ่งสามารถหาได้โดยการค้นหาในกูเกิ้ลว่า "ip ของฉัน" จากเครื่องของโฮสต์ hostserver = โฮสต์เกมผู้เล่นหลายคน @@ -214,6 +215,7 @@ hosts.none = [lightgray]ไม่พบเซิร์ฟเวอร์ท้ host.invalid = [scarlet]ไม่สามารถเชื่อมต่อกับโฮสต์ได้ servers.local = เซิร์ฟเวอร์ท้องถิ่น +servers.local.steam = เกมสาธารณะ & เซิร์ฟเวอร์ท้องถิ่น servers.remote = เซิร์ฟเวอร์ทางไกล servers.global = เซิร์ฟเวอร์ของชุมชน @@ -255,14 +257,14 @@ disconnect.error = การเชื่อมต่อมีปัญหา disconnect.closed = การเชื่อมต่อถูกปิดแล้ว disconnect.timeout = หมดเวลา disconnect.data = การโหลดข้อมูลของโลกผิดพลาด! -cantconnect = ไม่สามารถเข้าร่วมเซิฟเวอร์ ([accent]{0}[]) +cantconnect = ไม่สามารถเข้าร่วมเซิร์ฟเวอร์ ([accent]{0}[]) connecting = [accent]กำลังเชื่อมต่อ... reconnecting = [accent]กำลังเชื่อมต่อใหม่... connecting.data = [accent]กำลังโหลดข้อมูลของโลก ... server.port = พอร์ต: server.addressinuse = มีคนใช้ที่อยู่นี้แล้ว! server.invalidport = เลขพอร์ตไม่ถูกต้อง! -server.error = [crimson]การโฮสต์เซิฟเวอร์ผิดพลาด +server.error = [crimson]การโฮสต์เซิร์ฟเวอร์ผิดพลาด save.new = เซฟใหม่ save.overwrite = คุณแน่ใจหรือว่าจะเซฟทับ\nเซฟนี้? overwrite = เขียนทับ @@ -340,14 +342,14 @@ loadimage = โหลดรูป saveimage = เซฟรูป unknown = ไม่ทราบ custom = กำหนดเอง -builtin = Built-In +builtin = ติดตัว map.delete.confirm = คุณแน่ใจหรือว่าจะลบแมพนี้? การกระทำครั้งนี้ไม่สามารถย้อนกลับได้! map.random = [accent]สุ่มแมพ map.nospawn = แมพนี้ไม่มีแกนกลางให้ผู้เล่นเกิด! กรุณาใส่แกนกลาง[accent]สีเหลือง[] ในตัวแก้ไข map.nospawn.pvp = แมพนี้ไม่มีแกนกลางของศัตรูสำหรับให้ผู้เล่นเกิด! กรุณาใส่แกนกลาง[scarlet]ที่ไม่ใช่สีส้ม[] ในตัวแก้ไข map.nospawn.attack = แมพนี้ไม่มีแกนกลางของศัตรูสำหรับให้ผู้เล่นโจมตี! กรุณาใส่แกนกลาง[scarlet]สีแดง[] ในตัวแก้ไข map.invalid = โหลดแมพผิดพลาด: ไฟล์แมพเสียหายหรือไม่ถูกต้อง -workshop.update = อัพเดตไอเท็ม +workshop.update = อัปเดตไอเท็ม workshop.error = ผิดพลาดในการนำเวิร์กช็อปมา รายละเอียดดังนี้: {0} map.publish.confirm = คุณแน่ใจหรือว่าจะเผยแพร่แมพนี้?\n\n[lightgray]คุณต้องแน่ใจก่อนว่าคุณเห็นด้วยกับ Workshop EULA, มิฉนั้นแมพจะไม่ปรากฏ! workshop.menu = เลือกว่าจะทำอะไรกับไอเท็มนี้ @@ -357,7 +359,7 @@ eula = Steam EULA missing = ไอเท็มนี้ถูกลบหรือย้าย\n[lightgray]ยกเลิกการเชื่อมต่อของหน้ารายการเวิร์กช็อปแล้ว publishing = [accent]กำลังเผยแพร่... publish.confirm = คุณแน่ใจหรือว่าจะเผยแพร่สิ่งนี้?\n\n[lightgray]คุณต้องแน่ใจก่อนว่าคุณเห็นด้วยกับ Workshop EULA มิฉนั้นไอเท็มของคุณจะไม่ปรากฏ! -publish.error = การเผยแพร่ไอเท็มดังต่อไปนี้ผิดพลาด: {0} +publish.error = เกิดข้อผิดพลาดการเผยแพร่ไอเท็มดังต่อไปนี้: {0} steam.error = ไม่สามารถเริ่ม Steam service ได้\nError: {0} editor.brush = แปรง @@ -401,7 +403,7 @@ editor.default = [lightgray]<ค่าเริ่มต้น> details = รายละเอียด... edit = แก้ไข... editor.name = ชื่อ: -editor.spawn = สปาวน์ยูนิต +editor.spawn = สร้างยูนิต editor.removeunit = ลบยูนิต editor.teams = ทีม editor.errorload = โหลดไฟล์ผิดพลาด @@ -411,7 +413,7 @@ editor.errorlegacy = แมพนี้เก่าเกินไปและ editor.errornot = นี่ไม่ใช้ไฟล์แมพ editor.errorheader = ไฟล์แมพนี้เสียหรือไม่ถูกต้อง editor.errorname = แมพไม่มีการกำหนดชื่อ คุณกำลังโหลดไฟล์เซฟอยู่หรือป่าว? -editor.update = อัพเดต +editor.update = อัปเดต editor.randomize = สุ่ม editor.apply = ใช้ editor.generate = การกำเนิด @@ -420,8 +422,8 @@ editor.loadmap = โหลดแมพ editor.savemap = เซฟแมพ editor.saved = เซฟเรียบร้อย! editor.save.noname = แมพของคุณไม่มีชื่อ! สามารถตั้งชื่อได้ในเมนู 'ข้อมูลแมพ' -editor.save.overwrite = แมพของคุณไปทับกับแมพ built-in! เปลี่ยนชื่อได้ในเมนู 'ข้อมูลแมพ' -editor.import.exists = [scarlet]ไม่สามารถนำเข้าได้:[] มีแมพ built-in ที่ชื่อ '{0}' อยู่แล้ว! +editor.save.overwrite = แมพของคุณไปทับกับแมพติดตัว! เปลี่ยนชื่อได้ในเมนู 'ข้อมูลแมพ' +editor.import.exists = [scarlet]ไม่สามารถนำเข้าได้:[] มีแมพติดตัวที่ชื่อ '{0}' อยู่แล้ว! editor.import = นำเข้า... editor.importmap = นำเข้าแมพ editor.importmap.description = นำเข้าแมพที่มีอยู่แล้ว @@ -521,7 +523,7 @@ mapeditor = แก้ไขแมพ abandon = ละทิ้ง abandon.text = โซนนี้และทรัพยากรทั้งหมดจะถูกยืดไปเป็นของศัตรู -locked = ล็อค +locked = ล็อก complete = [lightgray]ต้องมี: requirement.wave = ถึงคลื่นที่ {0} ใน {1} requirement.core = ทำลายแกนกลางของศัตรูใน {0} @@ -545,15 +547,15 @@ add = เพิ่ม... guardian = การ์เดียน connectfail = [crimson]การเชื่อมต่อผิดพลาด:\n\n[accent]{0} -error.unreachable = เซิฟเวอร์ไม่สามารถเข้าถึงได้\nแน่ใจหรือว่าที่อยู่เขียนถูกต้อง? +error.unreachable = เซิร์ฟเวอร์ไม่สามารถเข้าถึงได้\nแน่ใจหรือว่าที่อยู่เขียนถูกต้อง? error.invalidaddress = ที่อยู่ไม่ถูกต้อง error.timedout = Timed out!\nเช็คให้แน่ใจว่า port forwarding ของโฮสต์เปิดอยู่และที่อยู่นั้นถูกต้อง! -error.mismatch = Packet error:\nอาจเกิดจากเวอร์ชั่นของ ไคลเอนต์/เซิร์ฟเวอร์ ไม่ตรงกัน\nเช็คให้แน่ใจว่าเซิฟเวอร์ใช้ Mindustry เวอร์ชั่นล่าสุด! +error.mismatch = Packet error:\nอาจเกิดจากเวอร์ชั่นของ ไคลเอนต์/เซิร์ฟเวอร์ ไม่ตรงกัน\nเช็คให้แน่ใจว่าเซิร์ฟเวอร์ใช้ Mindustry เวอร์ชั่นล่าสุด! error.alreadyconnected = เชื่อมต่ออยู่แล้ว error.mapnotfound = ไม่พบไฟล์แมพ error.io = Network I/O error error.any = Error: เครือข่ายที่ไม่รู้จัก -error.bloom = ไม่สามารถเริ่มต้น bloom ได้\nอุปกรณ์ของคุณอาจไม่รองรับ +error.bloom = ไม่สามารถเริ่มต้นบลูมได้\nอุปกรณ์ของคุณอาจไม่รองรับ weather.rain.name = ฝน weather.snow.name = หิมะ @@ -565,6 +567,7 @@ sectors.unexplored = [lightgray]ยังไม่ได้สำรวจ sectors.resources = ทรัพยากร: sectors.production = การผลิต: sectors.export = การส่งออก: +sectors.import = การนำเข้า: sectors.time = เวลา: sectors.threat = ภัยคุกคาม: sectors.wave = คลื่น: @@ -577,7 +580,7 @@ sectors.rename = เปลี่ยนชื่อเซ็กเตอร์ sectors.enemybase = [scarlet]ฐานทัพศัตรู sectors.vulnerable = [scarlet]เสี่ยงภัย sectors.underattack = [scarlet]เซ็กเตอร์ถูกโจมตี! เสียหาย [accent]{0}% -sectors.survives = [accent]จะอยู่รอดอีก {0} คลื่น +sectors.survives = [accent]จะอยู่รอดได้ {0} คลื่น sectors.go = ไป sector.curcapture = ยึดครองแล้ว sector.curlost = เราเสียเซ็กเตอร์! @@ -602,7 +605,7 @@ planet.sun.name = ดวงอาทิตย์ sector.impact0078.name = อิมแพค 0078 sector.groundZero.name = กราวน์ ซีโร่ sector.craters.name = บ่ออุกกาบาต -sector.frozenForest.name = ป่าหนาวแหน็บ +sector.frozenForest.name = ป่าหนาวเหน็บ sector.ruinousShores.name = ชายฝั่งพังทลาย sector.stainedMountains.name = ภูเขาหลากสี sector.desolateRift.name = เดโซเลต ริฟต์ @@ -621,8 +624,8 @@ sector.frozenForest.description = แม้แต่ที่นี่ ที่ sector.saltFlats.description = ณ ขอบของทะเลทราย เป็นที่ตั้งของที่ราบเกลือ สามารถพบทรัพยากรบางอย่างได้ที่นี่\n\nศัตรูได้ตั้งฐานเก็บทรัพยากรไว้ที่นี่ ทำลายแกนกลางของพวกมัน อย่าให้มีอะไรเหลือ sector.craters.description = น้ำขังอยู่ในหลุมอุกกาบาศแห่งนี้ อนุสรณ์สถานของสงครามเก่าแก่ ยึดพื้นที่นี่มา เก็บทราย เผา[accent]กระจกเมต้า[] ปั๊มน้ำเพื่อมาหล่อเย็นป้อมปืนและเครื่องขุดเจาะ sector.ruinousShores.description = ถัดจากทะเลทราย เป็นที่ตั้งของชายฝั่ง ที่ครั้งก่อน เคยเป็นที่ตั้งของฐานป้องกันชายฝั่ง ซึ่งทุกทำลายไปซะส่วนใหญ่แล้ว มีเหลือแค่ระบบการป้องกันพื้นฐาน ทุกอย่างที่เหลือถูกทำลายเหลือเพียงแค่เศษเหล็ก\n\nทำการขยายการสำรวจต่อไป ค้นพบกับเทคโนโลยีอีกครั้ง -sector.stainedMountains.description = เข้าลึกไปในพื้นที่ จะพบกับภูเขา ซึ่งยังไม่ถูกสปอร์แตะต้อง\nขุด[accent]ไทเทเนี่ยม[]ที่อุดมสมบูรณ์ในพื้นที่นี้ เรียนรู้ที่จะใช้มัน\n\nมีศัตรูมากขึ้นในบริเวณนี้ อย่าปล่อยให้พวกมันส่งยูนิตที่แข็งแกร่งที่สุดของพวกมันออกมา -sector.overgrowth.description = พื้นที่นี้ถูกปกคลุมไปด้วยพืช เข้าใกล้กับแหล่งกำเนิดของสปอร์\nศัตรูได้ตั้งฐานเฝ้าระวังไว้ที่นี่ สร้างยูนิตเมส ทำลายฐานซะ\nวิจัย[accent]เครื่องพัฒนารุ่นยกกำลัง[]เพื่อผลิตยูนิตขนาดที่ใหญ่ขึ้น +sector.stainedMountains.description = เข้าลึกไปในพื้นที่ จะพบกับภูเขา ซึ่งยังไม่ถูกสปอร์แตะต้อง\nขุด[accent]ไทเทเนี่ยม[]ที่อุดมสมบูรณ์ในพื้นที่นี้ เรียนรู้ที่จะใช้มัน\n\nมีศัตรูปรากฏตัวมากขึ้นในบริเวณนี้ อย่าปล่อยให้พวกมันส่งยูนิตที่แข็งแกร่งที่สุดออกมา +sector.overgrowth.description = พื้นที่นี้ถูกปกคลุมไปด้วยพืช เข้าใกล้กับแหล่งกำเนิดของสปอร์\nศัตรูได้ตั้งฐานเฝ้าระวังไว้ที่นี่ สร้างยูนิตเมส ทำลายฐานทิ้งซะ\nวิจัย[accent]เครื่องพัฒนารุ่นยกกำลัง[]เพื่อผลิตยูนิตขนาดที่ใหญ่ขึ้น sector.tarFields.description = ขอบของพื้นที่ผลิตน้ำมัน อยู่ระหว่างภูเขาและทะเลทราย หนึ่งในพื้นที่ที่มีแหล่งน้ำมันดิบที่ใช้งานได้\nแม้ว่าจะถูกทิ้งร้าง พื้นที่นี้ยังคงมีฐานทัพของศัตรูอยู่ใกล้ๆ อย่าประมาทกับพวกมัน\n\n[lightgray]วิจัยเทคโนโลยีการแปรรูปน้ำมันหากเป็นไปได้ sector.desolateRift.description = เป็นพื้นที่ที่อันตรายมาก ทรัพยากรมากมาย แต่พื้นที่แคบ ความเสี่ยงการโดนทำลายล้างสูง ออกไปจากที่นี่ให้เร็วที่สุด อย่าถูกหลอกโดยระยะเวลาระหว่างการโจมตีของศัตรูที่เว้นไว้นานกว่าปกติ sector.nuclearComplex.description = สถานที่ผลิตและแปรรูปทอเรี่ยมเก่า ถูกทำลายไม่เหลือสิ้น\nวิจัยทอเรี่ยมและวิธีการใช้มัน\n\nศัตรูในบริเวณนี้มีจำนวนมาก คอยตรวจตราหาผู้บุกรุกอยู่ตลอดเวลา @@ -655,10 +658,10 @@ settings.resetKey = รีเซ็ต settings.controls = การควบคุม settings.game = เกม settings.sound = เสียง -settings.graphics = กราฟฟิค +settings.graphics = กราฟิก settings.cleardata = เคลียร์ข้อมูลเกม... settings.clear.confirm = คุณแน่ใจหรือว่าจะเคลียร์ข้อมูลเกม?\nสิ่งที่ทำไปแล้วจะไม่สามารถย้อนกลับได้! -settings.clearall.confirm = [scarlet]คำเตือน![]\nการกระทำนี้จะลบข้อมูลทั้งหมด นั้นรวมไปถึงเซฟ แมพ การวิจัยแล้วและก็ปุ่มควบตุม\nเมื่อคุณกด 'โอเค' เกมจะลบข้อมูลทุกอย่างและออกโดยอัตโนมัติ +settings.clearall.confirm = [scarlet]คำเตือน![]\nการกระทำนี้จะลบข้อมูลทั้งหมด นั้นรวมไปถึงเซฟ แมพ การวิจัยแล้วและก็ปุ่มควบคุม\nเมื่อคุณกด 'โอเค' เกมจะลบข้อมูลทุกอย่างและออกโดยอัตโนมัติ settings.clearsaves.confirm = คุณแน่ใจหรือว่าคุณต้องการเคลียร์เซฟทั้งหมด? settings.clearsaves = เคลียร์เซฟ settings.clearresearch = เคลียร์การวิจัย @@ -715,7 +718,7 @@ stat.speedincrease = เพิ่มความเร็ว stat.range = ระยะ stat.drilltier = แร่ที่ขุดได้ stat.drillspeed = ความเร็วการขุดเฉลี่ย -stat.boosteffect = แอฟเฟ็คของบูสต์ +stat.boosteffect = เอฟเฟกต์ของบูสต์ stat.maxunits = จำนวนยูนิตสูงสุด stat.armor = เกราะ stat.health = พลังชีวิต @@ -724,7 +727,7 @@ stat.maxconsecutive = ติดต่อกันสูงสุด stat.buildcost = ใช้ stat.inaccuracy = ความคลาดเคลื่อน stat.shots = นัด -stat.reload = นัด/วินาที +stat.reload = อัตราการยิง stat.ammo = กระสุน stat.shieldhealth = พลังชีวิตโล่ stat.cooldowntime = เวลาคูลดาวน์ @@ -747,7 +750,7 @@ stat.commandlimit = จำนวนยูนิตที่สั่งการ stat.abilities = ทักษะ stat.canboost = สามารถบูสต์ stat.flying = บินได้ -stat.ammouse = ใช้กระสุน +stat.ammouse = การใช้กระสุน stat.damagemultiplier = พหุคูณดาเมจ stat.healthmultiplier = พหุคูณพลังชีวิต stat.speedmultiplier = พหุคูณความเร็ว @@ -758,7 +761,7 @@ stat.healing = การรักษา ability.forcefield = โล่พลังงาน ability.repairfield = สนามซ่อมแซม -ability.statusfield = สนามเอฟเฟกต์ {0} +ability.statusfield = {0} สนามเอฟเฟกต์ ability.unitspawn = โรงงาน{0} ability.shieldregenfield = สนามรักษาโล่ ability.movelightning = ปล่อยสายฟ้าเมื่อเคลื่อนที่ @@ -793,7 +796,7 @@ bullet.damage = [stat]{0}[lightgray] ดาเมจ bullet.splashdamage = [stat]{0}[lightgray] ดาเมจกระจาย ~[stat] {1}[lightgray] ช่อง bullet.incendiary = [stat]ติดไฟ bullet.homing = [stat]ติดตามตัว -bullet.frag = [stat]กระจาย +bullet.frags = [stat]{0}[lightgray]x กระจาย กระสุน: bullet.lightning = [stat]{0}[lightgray]x สายฟ้า ~ [stat]{1}[lightgray] ดาเมจ bullet.buildingdamage = [lightgray]ดาเมจต่อสิ่งก่อสร้าง [stat]{0}%[lightgray] bullet.knockback = [stat]{0}[lightgray] ดันกลับ @@ -806,6 +809,7 @@ bullet.reload = [lightgray]ความเร็วการยิง: [stat]{0} unit.blocks = บล็อก unit.blockssquared = บล็อก² unit.powersecond = หน่วย/วินาที +unit.tilessecond = ช่อง/วินาที unit.liquidsecond = หน่วย/วินาที unit.itemssecond = ไอเท็ม/วินาที unit.liquidunits = หน่วยของเหลว @@ -822,7 +826,7 @@ unit.items = ไอเท็ม unit.thousands = k unit.millions = [] []ล้าน unit.billions = [] []พันล้าน -unit.pershot = [] []กระสุน/การยิง +unit.pershot = [] []ไอเท็ม/การยิง category.purpose = วัตถุประสงค์ category.general = ทั่วไป category.power = พลังงาน @@ -831,20 +835,19 @@ category.items = ไอเท็ม category.crafting = การผลิต category.function = ฟังค์ชั่น category.optional = ทางเลือกการเพิ่มประสิทธิภาพ -setting.landscape.name = ล็อคภูมิทัศน์แนวนอน +setting.skipcoreanimation.name = ข้ามแอนิเมชั่นบิน/ลงจอดของแกนกลาง +setting.landscape.name = ล็อกภูมิทัศน์แนวนอน setting.shadows.name = เงา setting.blockreplace.name = แนะนำบล็อกโดยอัตโนมัติ setting.linear.name = การกรองเชิงเส้น setting.hints.name = คำแนะนำ setting.logichints.name = คำแนะนำลอจิก -setting.flow.name = แสดงอัตราการไหลของทรัพยากร setting.backgroundpause.name = หยุดในพื้นหลัง setting.buildautopause.name = หยุดสร้างชั่วคราวแบบอัตโนมัติ setting.doubletapmine.name = แตะสองครั้งเพื่อขุด setting.modcrashdisable.name = ปิดม็อดเมื่อเกมขัดข้อง setting.animatedwater.name = แอนิเมชั่นพื้นและน้ำ setting.animatedshields.name = แอนิเมชั่นเกราะ -setting.antialias.name = Antialias[lightgray] (จำเป็นต้องรีสตาร์ท)[] setting.playerindicators.name = ตัวบอกผู้เล่น setting.indicators.name = ตัวบอกศัตรู/พักพวก setting.autotarget.name = เล็งเป้าอัตโนมัติ @@ -853,7 +856,8 @@ setting.touchscreen.name = การควบคุมแบบหน้าจ setting.fpscap.name = FPS สูงสุด setting.fpscap.none = ∞ setting.fpscap.text = {0} FPS -setting.uiscale.name = ขนาด UI[lightgray] (จำเป็นต้องรีสตาร์ท)[] +setting.uiscale.name = อัตราขนาด UI +setting.uiscale.description = จำเป็นต้องรีสตาร์ทเพื่อใส่การเปลี่ยนแปลง setting.swapdiagonal.name = การวางเป็นเส้นทแยงเสมอ setting.difficulty.training = ฝึกซ้อม setting.difficulty.easy = ง่าย @@ -862,16 +866,17 @@ setting.difficulty.hard = ยาก setting.difficulty.insane = ยากมาก setting.difficulty.name = ระดับความยาก: setting.screenshake.name = การสั่นของจอ -setting.effects.name = แสดงเอฟเฟ็ค +setting.effects.name = แสดงเอฟเฟ็กต์ setting.destroyedblocks.name = แสดงบล็อกที่ถูกทำลาย -setting.blockstatus.name = แสดงสเตตัสของบล็อก +setting.blockstatus.name = แสดงสถานะของบล็อก setting.conveyorpathfinding.name = ตรวจสอบเส้นทางการวางอัจฉริยะ setting.sensitivity.name = ความเร็วของตัวควบคุม setting.saveinterval.name = ระยะห่างระหว่างการเซฟ setting.seconds = {0} วินาที setting.milliseconds = {0} มิลลิวินาที setting.fullscreen.name = เต็มจอ -setting.borderlesswindow.name = วินโดว์แบบไร้ขอบ[lightgray] (อาจจะต้องรีตาร์ท) +setting.borderlesswindow.name = หน้าต่างแบบไร้ขอบ +setting.borderlesswindow.description = อาจจะต้องรีสตาร์ทเพื่อใส่การเปลี่ยนแปลง setting.fps.name = แสดง FPS และ Ping setting.smoothcamera.name = กล้องแบบลื่นไหล setting.vsync.name = VSync @@ -887,19 +892,19 @@ setting.sfxvol.name = ระดับเสียง SFX setting.mutesound.name = ปิดเสียง setting.crashreport.name = ส่งรายงานการแครชแบบไม่ระบุตัวตน setting.savecreate.name = สร้างเซฟโดยอัตโนมัติ -setting.publichost.name = การมองเห็นเซิฟเวอร์สาธารณะ +setting.publichost.name = การมองเห็นเซิร์ฟเวอร์สาธารณะ setting.playerlimit.name = จำกัดผู้เล่น setting.chatopacity.name = ความโปร่งแสงของแชท setting.lasersopacity.name = ความโปร่งแสงของเลเซอร์พลังงาน setting.bridgeopacity.name = ความโปร่งแสงของสะพาน setting.playerchat.name = แสดงบับเบิ้ลแชทของผู้เล่น setting.showweather.name = แสดงแกรฟฟิกสภาพอากาศ -public.confirm = คุณต้องการให้เกมของคุณเปิดเป็นสาธารณะหรือไม่?\n[accent]ทุกคนจะสามารถเข้าร่วมเกมของคุณได้\n[lightgray]คุณสามารถเปลี่ยนการตั้งค่านี้ได้ที่ ตั้งค่า->เกม->การมองเห็นเซิฟเวอร์สาธารณะ -public.confirm.really = หากคุณอยากเล่นกับเล่นกับเพื่อน ใช้ [green]Invite Friend[] ดีกว่า แทนที่จะใช้ [scarlet]Public server[]!\nคุณแน่ใจนะว่าจะเปลี่ยนเกมคุณเป็น[scarlet]สาธารณะ[]? -public.beta = เกมเวอร์ชั่นเบต้าไม่สามารถเปิดเซิฟเวอร์สาธารณะได้ -uiscale.reset = ขนาดของ UI มีการเปลี่ยนแปลง\nกด "โอเค" เพื่อยืนยันขนาด UI นี้\n[scarlet]เปลี่ยนกลับไปเป็นแบบเดิมและออกในอีก[accent] {0}[] วินาที... +public.confirm = คุณต้องการให้เกมของคุณเปิดเป็นสาธารณะหรือไม่?\n[accent]ทุกคนจะสามารถเข้าร่วมเกมของคุณได้\n[lightgray]คุณสามารถเปลี่ยนการตั้งค่านี้ได้ที่ ตั้งค่า->เกม->การมองเห็นเซิร์ฟเวอร์สาธารณะ +public.confirm.really = หากคุณอยากเล่นกับเล่นกับเพื่อน ใช้[green]ชวนเพื่อน[]ดีกว่า แทนที่จะใช้[scarlet]เซิร์ฟเวอร์สาธารณะ[]!\nคุณแน่ใจนะว่าจะเปลี่ยนเกมคุณเป็น[scarlet]สาธารณะ[]? +public.beta = เกมเวอร์ชั่นเบต้าไม่สามารถเปิดเซิร์ฟเวอร์สาธารณะได้ +uiscale.reset = อัตราขนาดของ UI ได้มีการเปลี่ยนแปลง\nกด "โอเค" เพื่อยืนยันขนาด UI นี้\n[scarlet]จะเปลี่ยนกลับไปเป็นแบบเดิมและออกในอีก[accent] {0}[] วินาที... uiscale.cancel = ยกเลิกและออก -setting.bloom.name = Bloom +setting.bloom.name = บลูม keybind.title = ตั้งค่าปุ่ม keybinds.mobile = [scarlet]การตั้งค่าปุ่มส่วนใหญ่ไม่สามารถใช้ในมือถือได้ เฉพาะการเคลื่อนไหวพื้นฐานเท่านั้นที่ใช้ได้ category.general.name = ทั่วไป @@ -972,7 +977,7 @@ keybind.chat_history_prev.name = ประวัติแชทก่อนห keybind.chat_history_next.name = ประวัติแชทถัดไป keybind.chat_scroll.name = เลื่อนแชท keybind.chat_mode.name = เปลี่ยนโหมดแชท -keybind.drop_unit.name = ดรอปยูนิต +keybind.drop_unit.name = วางยูนิต keybind.zoom_minimap.name = ซูมมินิแมพ mode.help.title = คำอธิบายโหมด mode.survival.name = เอาชีวิตรอด @@ -994,6 +999,7 @@ rules.wavetimer = นับถอยหลังการปล่อยคล rules.waves = คลื่น rules.attack = โหมดการโจมตี rules.buildai = AI ก่อสร้าง +rules.cleanupdeadteams = ลบล้างสิ่งก่อสร้างศัตรูที่พ่ายแพ้ (PvP) rules.corecapture = ยืดแกนกลางเมื่อทำลาย rules.polygoncoreprotection = รัศมีปกป้องแกนกลางแบบหลายเหลี่ยม rules.enemyCheat = AI (ทีมสีแดง) มีทรัพยากรไม่จำกัด @@ -1085,7 +1091,7 @@ unit.sei.name = เซย์ unit.omura.name = โอมูร่า unit.retusa.name = เรธูซ่า unit.oxynoe.name = อ๊อกซิโนอ์ -unit.cyerce.name = ไซเยิส +unit.cyerce.name = เซียรส์ unit.aegires.name = เอเกียเรส unit.navanax.name = นาวาแน็คซ์ unit.alpha.name = อัลฟ่า @@ -1102,7 +1108,7 @@ block.cliff.name = หน้าผา block.sand-boulder.name = ก้อนหินทราย block.basalt-boulder.name = ก้อนบะซอลต์ block.grass.name = หญ้า -block.slag.name = แร่หลอม +block.molten-slag.name = แร่หลอม block.space.name = อวกาศ block.salt.name = เกลือ block.salt-wall.name = กำแพงเกลือ @@ -1133,8 +1139,8 @@ block.spawn.name = จุดเกิดศัตรู block.core-shard.name = แกนกลาง: ชาร์ด block.core-foundation.name = แกนกลาง: ฟาวน์เดชั่น block.core-nucleus.name = แกนกลาง: นิวเคลียส -block.deepwater.name = น้ำลึก -block.water.name = น้ำ +block.deep-water.name = น้ำลึก +block.shallow-water.name = น้ำ block.tainted-water.name = น้ำเสีย block.darksand-tainted-water.name = น้ำเสียบนทรายดำ block.tar.name = น้ำมันดิบ @@ -1143,7 +1149,7 @@ block.sand.name = ทราย block.darksand.name = ทรายดำ block.ice.name = น้ำแข็ง block.snow.name = หิมะ -block.craters.name = หลุมอุกกาบาต +block.crater-stone.name = หลุมอุกกาบาต block.sand-water.name = น้ำบนทราย block.darksand-water.name = น้ำบนทรายดำ block.char.name = ถ่าน @@ -1247,7 +1253,7 @@ block.wave.name = คลื่นน้ำ block.tsunami.name = สึนามิ block.swarmer.name = สวอร์มเมอร์ block.salvo.name = ซัลโว -block.ripple.name = ริปเปิล +block.ripple.name = ริปเปิ้ล block.phase-conveyor.name = สายพานเฟส block.bridge-conveyor.name = สะพานไอเท็ม block.plastanium-compressor.name = เครื่องอัดพลาสตาเนี่ยม @@ -1268,7 +1274,7 @@ block.bridge-conduit.name = สะพานของเหลว block.rotary-pump.name = ปั๊มโรตารี่ block.thorium-reactor.name = เตาปฏิกรณ์ทอเรี่ยม block.mass-driver.name = เครื่องโอนถ่ายมวล -block.blast-drill.name = เครื่องขุดระเบิดอากาศ +block.blast-drill.name = เครื่องขุดแอร์บลาสต์ block.thermal-pump.name = ปั๊มความร้อน block.thermal-generator.name = เครื่องกำเนิดไฟฟ้าจากความร้อน block.alloy-smelter.name = เครื่องหลอมอัลลอย @@ -1288,7 +1294,6 @@ block.meltdown.name = เมลท์ดาวน์ block.foreshadow.name = ฟอร์ชาโดว์ block.container.name = ตู้เก็บของ block.launch-pad.name = ฐานส่งของ -block.launch-pad-large.name = ฐานส่งของขนาดใหญ่ block.segment.name = เซ็กเมนต์ block.command-center.name = ศูนย์ควบคุม block.ground-factory.name = โรงงานยูนิตพื้นดิน @@ -1309,11 +1314,11 @@ block.payload-source.name = จุดกำเนิดสิ่งบรรท block.disassembler.name = เครื่องถอดแยกส่วนประกอบ block.silicon-crucible.name = เบ้าหลอมซิลิคอน block.overdrive-dome.name = โดมเร่งประสิทธิภาพ +block.interplanetary-accelerator.name = ฐานเร่งความเร็วระหว่างดาวเคราะห์ #experimental, may be removed block.block-forge.name = เครื่องสร้างบล็อก block.block-loader.name = เครื่องโหลดบล็อก block.block-unloader.name = เครื่องถ่ายบล็อก -block.interplanetary-accelerator.name = เครื่องส่งจรวดระหว่างดาวเคราะห์ block.switch.name = สวิตช์ block.micro-processor.name = ตัวประมวลผลขนาดเล็ก @@ -1343,11 +1348,12 @@ hint.desktopPause = กด [accent][[Space][] เพื่อหยุดชั hint.placeDrill = เลือกเมนู \ue85e [accent]เครื่องขุด[] ในแท็บเมนูขวาล่าง แล้วเลือก \uf870 [accent]เครื่องขุด[] แล้วกดที่แร่ทองแดงเพื่อวาง hint.placeDrill.mobile = เลือกเมนู \ue85e [accent]เครื่องขุด[] ในแท็บเมนูขวาล่าง แล้วเลือก \uf870 [accent]เครื่องขุด[] แล้วกดที่แร่ทองแดงเพื่อวาง\n\nกด \ue800 [accent]ติ้กถูก[] ที่ขวาล่างเพื่อยืนยัน hint.placeConveyor = สายพานจะย้ายไอเท็มจากเครื่องขุดไปยังบล็อกอื่นๆ เลือก \uf896 [accent]สายพาน[] จากแท็บ \ue814 [accent]การเคลื่อนย้าย[]\n\nคลิ๊กแล้วลากเพื่อวางหลายๆ สายพาน\n[accent]เลื่อน[]เพื่อหมุน -hint.placeConveyor.mobile = สายพานจะเคลื่อนย้ายไอเท็มจากที่ขุดไปยังบล็อกอื่นๆ เลือก \uf896 [accent]สายพาน[] จากแท็บ \ue814 [accent]การเคลื่อนย้าย[]\n\nเอานิ้วจิ้มลงไปสักแป็บนึงแล้วลากเพื่อวางหลายๆ อัน +hint.placeConveyor.mobile = สายพานจะเคลื่อนย้ายไอเท็มจากที่ขุดไปยังบล็อกอื่นๆ เลือก \uf896 [accent]สายพาน[] จากแท็บ \ue814 [accent]การเคลื่อนย้าย[]\n\nเอานิ้วจิ้มลงไปสักแป๊บนึงแล้วลากเพื่อวางหลายๆ อัน hint.placeTurret = วาง \uf861 [accent]ป้อมปืน[] เพื่อป้องกันฐานทัพจากศัตรู\n\nป้อมปืนต้องมีกระสุน ในกรณีนี้ \uf838 ทองแดง\nใช้สายพานลากจากเครื่องขุดไปที่ป้อมปืนเพื่อเติมกระสุน hint.breaking = [accent]คลิ๊กขวา[] แล้วลากเพื่อทำลายบล็อก -hint.breaking.mobile = เปิดใช้ \ue817 [accent]ค้อน[] ตรงล่างขวาแล้วเลือกเพื่อทำลายบล็อก\n\nเอานิ้วจิ้มลงไปสักแป็บนึงแล้วลากเพื่อเลือกหลายๆ อัน +hint.breaking.mobile = เปิดใช้ \ue817 [accent]ค้อน[] ตรงล่างขวาแล้วเลือกเพื่อทำลายบล็อก\n\nเอานิ้วจิ้มลงไปสักแป๊บนึงแล้วลากเพื่อเลือกหลายๆ อัน hint.blockInfo = ดูข้อมูลของบล็อกโดยการเลือกจาก[accent]เมนูการสร้าง[] แล้วกดที่รูป [accent][[?][] ตรงด้านขวา +hint.derelict = สิ่งก่อสร้างที่ถูก[accent]ทิ้งร้าง[]คือเศษซากพังทลายของฐานเก่าแก่ที่ไม่สามารถใช้งานได้แล้ว\n\nสิ่งก่อสร้างพวกนี้สามารถ[accent]ทุบทิ้ง[]เพื่อเก็บเกี่ยวทรัพยากรที่อยู่ในนั้นได้ hint.research = ใช้ปุ่ม \ue875 [accent]วิจัย[] เพื่อวิจัยเทคโนโลยีใหม่ๆ hint.research.mobile = ใช้ปุ่ม \ue875 [accent]วิจัย[] ใน \ue88c [accent]เมนู[] เพื่อวิจัยเทคโนโลยีใหม่ๆ hint.unitControl = กด [accent][[L-Ctrl][] ค้างไว้แล้วกด[accent]คลิ๊ก[]เพื่อควบคุมยานพวกพ้องหรือป้อมปืน @@ -1361,14 +1367,14 @@ hint.boost = กด [accent][[L-Shift][] เพื่อบูสต์ข้า hint.command = กด [accent][[G][] เพื่อสั่งการยูนิตข้างๆ ของตัว[accent]ชนิดคล้ายกัน[]จัดเป็นรูปแบบล้อมรอบคุณ\n\nถ้าจะสั่งการยูนิตพื้นดิน คุณต้องควบคุมยูนิตประเภทเดียวกันอยู่ก่อน hint.command.mobile = [accent][[กดสองครั้ง][] ที่ตัวยูนิตของคุณเพื่อสั่งการยูนิตรอบข้างให้มารวมตัวกันเป็นวงล้อมรอบคุณ hint.payloadPickup = กด [accent][[[] เพื่อหยิบบล็อกเล็กๆ หรือยูนิต -hint.payloadPickup.mobile = [accent]กดค้างไว้[] ที่บล็อกเล็กๆ หรือตัวยูนิตเพื่อหยิบขึ้นมา +hint.payloadPickup.mobile = [accent]กดค้างไว้[]ที่บล็อกเล็กๆ หรือตัวยูนิตเพื่อหยิบขึ้นมา hint.payloadDrop = กด [accent]][] เพื่อปล่อยสิ่งที่บรรทุกอยู่ hint.payloadDrop.mobile = [accent]กดค้างไว้[]ที่พื้นที่โล่งๆ เพื่อปล่อยสิ่งที่บรรทุกอยู่ -hint.waveFire = ป้อมปืน[accent]คลื่นน้ำ[]หากมีน้ำเป็นกระสุนจะช่วยดับไฟรอบข้างให้อัตโนมัติ +hint.waveFire = ป้อมปืน[accent]คลื่นน้ำ[]หากเติมน้ำเข้าไปจะช่วยดับไฟรอบข้างให้อัตโนมัติ hint.generator = \uf879 [accent]เครื่องกำเนิดไฟฟ้าเผาไหม้[]จะเผาถ่านและส่งพลังงานไปยังบล็อกที่อยู่ใกล้ๆ\n\nระยะของพลังงานสามารถขยายได้ด้วย \uf87f [accent]ตัวจ่ายพลังงาน[] -hint.guardian = หน่วย[accent]การ์เดียน[]มีเกราะป้องกันหนาแน่น กระสุนเปราะบางอย่าง[accent]ทองแดง[]และ[accent]ตะกั่ว[][scarlet]ไม่มีประสิทธิภาพ[]\n\nควรใช้ป้อมปืนที่ดีกว่านี้หรือใช้ \uf835 [accent]กราไฟท์[]ใน \uf861ดูโอ/\uf859ซัลโวเป็นกระสุนเพื่อทำลายการ์เดียน -hint.coreUpgrade = สามารถอัพเกรดแกนกลางได้โดย[accent]วางแกนกลางที่ใหญ่กว่าทับมัน[]\n\nวาง  [accent]แกนกลาง: ฟาวน์เดชั่น[]ทับ  [accent]แกนกลาง: ชาร์ด[] ต้องแน่ใจว่ารอบข้างมีที่ว่างก่อนจะวาง -hint.presetLaunch = [accent]เซ็กเตอร์ลงจอด[]สีเทา อย่างเช่น[accent]ป่าหนาวแหน็บ[] สามารถลงจอดจากที่ไหนที่ได้ในแผนที่ พวกนั้นไม่จำเป็นต้องยืดครองเซ็กเตอร์รอบข้างเพื่อส่งแกนกลางไป\n\n[accent]เซ็กเตอร์ที่มีเลข[] อย่างเช่นอันนี้[accent]ไม่จำเป็น[]ต้องยืดครอง +hint.guardian = หน่วย[accent]การ์เดียน[]มีเกราะป้องกันหนาแน่น กระสุนเปราะบางอย่าง[accent]ทองแดง[]และ[accent]ตะกั่ว[][scarlet]ไม่มีประสิทธิภาพ[]\n\nควรใช้ป้อมปืนที่ดีกว่านี้หรือใช้ \uf835 [accent]กราไฟท์[]ใส่ใน \uf861 ดูโอ/ \uf859 ซัลโวเป็นกระสุนเพื่อทำลายการ์เดียน +hint.coreUpgrade = สามารถอัปเกรดแกนกลางได้โดย[accent]วางแกนกลางที่ใหญ่กว่าทับมัน[]\n\nวาง  [accent]แกนกลาง: ฟาวน์เดชั่น[]ทับ  [accent]แกนกลาง: ชาร์ด[] ต้องแน่ใจว่ารอบข้างมีที่ว่างก่อนจะวาง +hint.presetLaunch = [accent]เซ็กเตอร์ลงจอด[]สีเทา อย่างเช่น[accent]ป่าหนาวเหน็บ[] สามารถลงจอดจากที่ไหนที่ได้ในแผนที่ พวกนั้นไม่จำเป็นต้องยืดครองเซ็กเตอร์รอบข้างเพื่อส่งแกนกลางไป\n\n[accent]เซ็กเตอร์ที่มีเลข[] อย่างเช่นอันนี้[accent]ไม่จำเป็น[]ต้องยืดครอง hint.coreIncinerate = เมื่อแกนกลางมีจำนวนไอเท็มชนิดหนึ่งที่เต็ม ไอเท็มชนิดนั้นที่เข้ามาเพิ่มจะ[accent]ถูกเผา[] hint.coopCampaign = ตอนที่เล่น[accent]แคมเปญร่วมกัน[]กับเพื่อน ไอเท็มที่ผลิตในแมพนี้จะถูกส่ง[accent]ไปยังเซ็กเตอร์ของคุณด้วย[]\n\nการวิจัยใหม่ที่โฮสต์ได้วิจัยก็เก็บเป็นของคุณด้วย @@ -1386,9 +1392,9 @@ item.titanium.description = ใช้อย่างแพร่หลายใ item.titanium.details = โลหะเบาซึ่งหายากตามธรรมชาติ เป็นโลหะที่แข็งแรงใช้ได้ จึงใช้กันอย่างแพร่หลายในการแปรรูปหรือสิ่งก่อสร้าง item.thorium.description = ใช้ในการเสริมเกราะของสิ่งก่อสร้างต่างๆ หรือนำไปเป็นเป็นเชื้อเพลิงนิวเคลียร์ item.thorium.details = แร่ธาตุที่หาได้ยากมากในธรรมชาติ เป็นแร่ธาตุที่ทั้งแข็งแกร่งและหนาแน่น จึงใช้กันอย่างแพร่หลายในสิ่งก่อสร้างคงทน มีคุณสมบัติพิเศษคือกัมมันตภาพรังสี ทำให้แร่ธาตุนี้อาจเป็นภัยหากใช้ในทางที่ผิด -item.scrap.description = ใช้ในเตาหลอมแร่และเครื่องบดเพื่อเปลี่ยนเป็นวัสดุอื่นๆ +item.scrap.description = ใช้ในเตาหลอมแร่และเครื่องบดอัดเพื่อเปลี่ยนเป็นวัสดุอื่นๆ item.scrap.details = เศษที่เหลือจากสิ่งก่อสร้างและยูนิตเก่า มีร่องรอยของโลหะหลายชนิดอยู่ เกิดจากฐานทัพโบราณในสมัยสงครามเก่าแก่ถูกทำลาย ทำให้วัสดุต่างๆ พังลงมารวมกับ -item.silicon.description = ใช้ในแผงโซล่าเซลล์ อุปกรณ์อิเล็กทรอนิกที่ซับซ้อนหรือนำไปเป็นกระสุนติดตามตัวสำหรับป้อมปืน +item.silicon.description = ใช้ในแผงโซล่าเซลล์ อุปกรณ์อิเล็กทรอนิกที่ซับซ้อน\nหรือนำไปเป็นกระสุนติดตามตัวสำหรับป้อมปืน item.silicon.details = วัสดุกึ่งตัวนำที่มีประโยชน์มาก ผลิตจากการเผาทรายและถ่านหินเข้าด้วยกัน ใช้ในสิ่งก่อสร้างแทบทุกชนิดตั้งแต่ต้นเกมยันปลายเกม จึงควรผลิตวัสดุนี้ให้เยอะที่สุด item.plastanium.description = ใช้ในอากาศยานขั้นสูง เป็นฉนวนกันความร้อนหรือนำไปเป็นกระสุนกระจาย item.plastanium.details = วัสดุที่เบาและดัดได้ ผลิตจากการอัดไทเทเนี่ยมและน้ำมันเข้าด้วยกัน @@ -1410,13 +1416,14 @@ liquid.oil.details = ของเหลวเฉื่อยพบได้ไ liquid.cryofluid.description = ใช้ในการหล่อเย็นเตาปฏิกร สิ่งก่อสร้างหรือโรงงานต่างๆ liquid.cryofluid.details = ของเหลวเฉื่อยและไม่กัดกร่อน ผลิตจากน้ำและไทเทเนี่ยม มีคุณสมบัติการถ่ายเทความร้อนสูง -block.resupply-point.description = เติมกระสุนยูนิตรอบข้างด้วยกระสุนทองแดง ใช้ไม่ได้กับยูนิตที่ใช้พลังงานเป็นกระสุน +block.derelict = [lightgray] ถูกทิ้งร้าง +block.resupply-point.description = เติมกระสุนยูนิตรอบข้างด้วยกระสุนทองแดง ใช้กับยูนิตที่ใช้พลังงานเป็นกระสุนไม่ได้ block.armored-conveyor.description = เลื่อนไอเท็มไปข้างหน้า เร็วเท่าสายพานไทเทเนี่ยม แต่มีเกราะที่แข็งแรงกว่า ไม่รับไอเท็มจากด้านข้างยกเว้นเป็นสายพานชนิดเดียวกัน block.illuminator.description = ตัวเปล่งแสงขนาดกะทัดรัด ส่องสว่างในที่มืดได้ดี\nแถมยังกำหนดสีของแสงได้ด้วย... เจ๋งใช่มั้ยล่ะ block.message.description = เก็บข้อความ ใช้สื่อสารกับพันธมิตร block.graphite-press.description = อัดก้อนถ่านหินให้เป็นแผ่นกราไฟต์บริสุทธิ์ block.multi-press.description = อัดก้อนถ่านหินให้เป็นแผ่นกราไฟต์บริสุทธิ์ ใช้น้ำและพลังงานในการแปรรูปถ่านหินให้เร็วและมีประสิทธิภาพมากขึ้น -block.silicon-smelter.description = ผลิตซิลิกอนจากทรายและถ่านหินบริสุทธิ์ +block.silicon-smelter.description = ผลิตซิลิกอนจากการหลอมทรายและถ่านหินเข้าด้วยกัน block.kiln.description = เผาทรายและตะกั่วเป็นกระจกเมต้า block.plastanium-compressor.description = บีบอัดน้ำมันและไทเทเนี่ยมเข้าด้วยกันเพื่อผลิตพลาสตาเนี่ยม block.phase-weaver.description = สังเคราะห์ใยเฟสจากทรายและทอเรี่ยม ใช้พลังงานจำนวนมากในการทำงาน @@ -1524,34 +1531,34 @@ block.duo.description = ป้อมปืนขนาดเล็ก ยิง block.scatter.description = ยิงก้อนตะกั่ว เศษเหล็กหรือกระจกเมต้าใส่ยานบินศัตรูที่อยู่ใกล้เคียง block.scorch.description = เผาศัตรูพื้นดินที่อยู่ใกล้ๆ มีประสิทธิภาพสูงสุดเมื่อใช้ในระยะใกล้ block.hail.description = ป้อมปืนใหญ่ขนาดย่อม ยิงลูกระเบิดใส่ศัตรูพื้นดินจากระยะไกล -block.wave.description = ป้อมปืนขนาดกลาง พ่นของเหลวสาดใส่ศัตรู จะดับไฟให้อัตโนมัติเมื่อใส่น้ำเข้าไป -block.lancer.description = ป้อมปืนเลเซอร์ต่อต้านพื้นดินขนาดกลาง ชาร์จและยิงลำแสงพลังงานอันทรงพลังใส่ศัตรู -block.arc.description = ป้อมปืนไฟฟ้าระยะใกล้ ยิงสายฟ้าใส่ศัตรูพื้นดิน จะทำดาเมจมหาศาลเมื่อศัตรูเปียกน้ำ -block.swarmer.description = ป้อมยิงขีปนาวุธขนาดกลาง ยิงขีปนาวุธติดตามตัวใส่ศัตรูทั้งอากาศและพื้นดิน +block.wave.description = พ่นของเหลวสาดใส่ศัตรู จะดับไฟให้อัตโนมัติเมื่อใส่น้ำเข้าไป +block.lancer.description = ชาร์จแล้วยิงลำแสงพลังงานอันทรงพลังใส่ศัตรูพื้นดิน +block.arc.description = ยิงสายฟ้าใส่ศัตรูพื้นดิน จะทำดาเมจมหาศาลเมื่อศัตรูเปียกน้ำ +block.swarmer.description = ยิงขีปนาวุธติดตามตัวใส่ศัตรูทั้งอากาศและพื้นดิน block.salvo.description = ป้อมปืนขนาดกลาง ระดมยิงกระสุนหนักใส่ศัตรูอย่างรวดเร็ว -block.fuse.description = ป้อมปืนระยะใกล้ขนาดใหญ่ ยิงลำแสงเจาะทะลุสามเส้นใส่ศัตรูที่อยู่ใกล้เคียง -block.ripple.description = ป้อมปืนใหญ่พลังงานสูง ยิงกระจุกของลูกระเบิดใส่ศัตรูพื้นดินจากระยะไกล -block.cyclone.description = ป้อมปืนต่อต้านทั้งอากาศยานและพื้นดิน ยิงกระสุนเป็นกระจุกระเบิดใส่ยูนิตศัตรูอย่างรวดเร็ว +block.fuse.description = ป้อมปืนระยะใกล้ขนาดใหญ่ ยิงลำแสงเจาะทะลุสามแฉกใส่ศัตรูที่อยู่ใกล้เคียง +block.ripple.description = ป้อมปืนใหญ่อันทรงพลัง ยิงลูกระเบิดเป็นกระจุกใส่ศัตรูพื้นดินจากระยะไกล +block.cyclone.description = ป้อมปืนรวดเร็วดั่งพายุ ยิงก้อนสะเก็ดระเบิดใส่ยูนิตศัตรูอย่างรวดเร็ว block.spectre.description = ปืนใหญ่คู่ขนาดยักษ์ ยิงกระสุนเจาะเกราะใส่ศัตรูทั้งบนอากาศและพื้นดิน block.meltdown.description = ชาร์จแล้วยิงลำแสงเลเซอร์ใส่ศัตรูที่อยู่ใกล้เคียงอย่างต่อเนื่อง ต้องมีของเหลวมาหล่อเย็นป้อมปืนเพื่อทำงาน block.foreshadow.description = ป้อมปืนเรลกันขนาดมหึมา ยิงลำแสงพลังงานใส่เป้าหมายเดี่ยวขนาดใหญ่\nมีระยะการยิงไกลมาก จะเลือกยิงยูนิตที่มีพลังชีวิตมากที่สุดก่อน -block.repair-point.description = ซ่อมแซมยูนิตที่อยู่ในรัศมีอย่างต่อเนื่อง +block.repair-point.description = ซ่อมแซมยูนิตที่อยู่ในรัศมีของมันอย่างต่อเนื่อง block.segment.description = สร้างความเสียหายและทำลายกระสุนที่กำลังเข้ามา ไม่สามารถทำลายลำแสงเลเซอร์ได้ block.parallax.description = ยิงลำแสงที่ดึงยานบินศัตรูเข้าหา สร้างความเสียหายแก่พวกมันระหว่างทาง block.tsunami.description = ยิงกระแสของเหลวอันทรงพลังใส่ศัตรู จะดับไฟให้อัตโนมัติเมื่อใส่น้ำเข้าไป -block.silicon-crucible.description = หลอมซิลิกอนจากทรายและถ่าน ใช้ไพราไทต์เป็นแหล่งความร้อนเพิ่มเติม ทำงานเร็วกว่าถ้าตั้งอยู่ในพื้นที่ร้อน +block.silicon-crucible.description = หลอมซิลิกอนจากทรายและถ่านหิน ใช้ไพราไทต์เป็นแหล่งความร้อนเพิ่มเติม จะทำงานเร็วกว่าถ้าตั้งอยู่ในพื้นที่ร้อน block.disassembler.description = แยกแร่หลอมออกเป็นแร่ธาตุปริมาณเล็กน้อยโดยมีประสิทธิภาพต่ำ สามารถผลิตทอเรี่ยมได้ block.overdrive-dome.description = เร่งประสิทธิภาพสิ่งก่อสร้างรอบข้างอย่างมหาศาล ต้องมีใยเฟสกับซิลิกอนเพื่อทำงาน block.payload-conveyor.description = เคลื่อนย้ายสิ่งของบรรทุกหนัก อย่างเช่นยูนิต block.payload-router.description = แยกสิ่งของบรรทุกออกเป็นสามทิศทาง block.command-center.description = ควบคุมและสั่งการยูนิตด้วยคำสั่งที่มีมากมาย -block.ground-factory.description = ผลิตยูนิตทางบก ยูนิตที่ผลิตสามารถใช้ได้เลย หรือนำไปใส่ในเครื่องพัฒนาเพื่ออัพเกรด -block.air-factory.description = ผลิตยูนิตทางอากาศ ยูนิตที่ผลิตสามารถใช้ได้เลย หรือนำไปใส่ในเครื่องพัฒนาเพื่ออัพเกรด -block.naval-factory.description = ผลิตยูนิตเรือ ยูนิตที่ผลิตสามารถใช้ได้เลย หรือนำไปใส่ในเครื่องพัฒนาเพื่ออัพเกรด -block.additive-reconstructor.description = อัพเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่สอง -block.multiplicative-reconstructor.description = อัพเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่สาม -block.exponential-reconstructor.description = อัพเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่สี่ -block.tetrative-reconstructor.description = อัพเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่ห้าและรุ่นสุดท้าย +block.ground-factory.description = ผลิตยูนิตทางบก ยูนิตที่ผลิตสามารถใช้ได้เลย หรือนำไปใส่ในเครื่องพัฒนาเพื่ออัปเกรด +block.air-factory.description = ผลิตยูนิตทางอากาศ ยูนิตที่ผลิตสามารถใช้ได้เลย หรือนำไปใส่ในเครื่องพัฒนาเพื่ออัปเกรด +block.naval-factory.description = ผลิตยูนิตเรือ ยูนิตที่ผลิตสามารถใช้ได้เลย หรือนำไปใส่ในเครื่องพัฒนาเพื่ออัปเกรด +block.additive-reconstructor.description = อัปเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่สอง +block.multiplicative-reconstructor.description = อัปเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่สาม +block.exponential-reconstructor.description = อัปเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่สี่ +block.tetrative-reconstructor.description = อัปเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่ห้าและรุ่นสุดท้าย block.switch.description = สวิตช์เปิดปิดได้ สามารถควบคุมหรืออ่านค่าได้ด้วยตัวประมวลผลลอจิก block.micro-processor.description = รันคำสั่งลอจิกเป็นลำดับวนไปวนมา สามารถใช้ควบคุมยูนิตหรือสิ่งก่อสร้าง ไม่ค่อยเร็วเท่าไหร่ block.logic-processor.description = รันคำสั่งลอจิกเป็นลำดับวนไปวนมา สามารถใช้ควบคุมยูนิตหรือสิ่งก่อสร้าง ค่อนข้างเร็ว มีระยะการเชื่อมต่อที่ค่อนข้างไกล @@ -1561,6 +1568,8 @@ block.memory-bank.description = เก็บข้อมูลเป็นตั block.logic-display.description = แสดงกราฟิกโดยควบคุมจากตัวประมวลผลลอจิก block.large-logic-display.description = แสดงกราฟิกโดยควบคุมจากตัวประมวลผลลอจิก มีขนาดใหญ่กว่า block.interplanetary-accelerator.description = หอคอยเรลกันแม่เหล็กไฟฟ้าขนาดมหึมา เร่งความเร็วแกนกลางเพื่อบินสู่อวกาศไปยังดาวเคราะห์อื่นๆ +block.repair-turret.description = ซ่อมแซมยูนิตที่อยู่ในรัศมีของมันอย่างต่อเนื่อง สามารถใช้ของเหลวมาหล่อเย็นเพื่อเพิ่มประสิทธิภาพได้ +block.payload-propulsion-tower.description = บล็อกขนส่งสิ่งบรรทุกทางไกล\nยิงสิ่งบรรทุกไปยังหอเคลื่อนย้ายสิ่งบรรทุกอีกเครื่องที่เชื่อมต่อไว้ unit.dagger.description = ยิงกระสุนธรรมดาใส่ศัตรูที่อยู่ใกล้เคียง unit.mace.description = ยิงเปลวไฟใส่ศัตรูที่อยู่ใกล้เคียง ทำให้ศัตรูถูกเผาไหม้ @@ -1595,6 +1604,11 @@ unit.omura.description = ยิงลำแสงปืนเรลกันเ unit.alpha.description = ปกป้องแกนกลางชาร์ดจากศัตรู สร้างสิ่งต่างๆ unit.beta.description = ปกป้องแกนกลางฟาวน์เดชั่นจากศัตรู สร้างสิ่งต่างๆ unit.gamma.description = ปกป้องแกนกลางนิวเคลียสจากศัตรู สร้างสิ่งต่างๆ +unit.retusa.description = วางทุ่นระเบิดระยะใกล้ และซ่อมแซมยูนิตพวกพ้องที่อยู่ใกล้เคียง +unit.oxynoe.description = ยิงเปลวไฟเผาไหม้ใส่ศัตรูที่อยู่ใกล้เคียงและซ่อมแซมสิ่งก่อสร้างของพวกพ้อง\nทำลายกระสุนที่กำลังเข้ามาด้วยปืนป้องกันจุด +unit.cyerce.description = ยิงขีปนาวุธพลาสม่าติดตามตัวเป็นกระจุกระเบิดใส่ศัตรู\nซ่อมแซมยูนิตพวกพ้องที่อยู่ใกล้เคียงด้วยปืนซ่อมแซม +unit.aegires.description = ช็อตทุกสิ่งก่อสร้างและยูนิตศัตรูที่เข้ามาในสนามพลังงานของมัน\nซ่อมแซมสิ่งก่อสร้างและยูนิตพวกพ้อง +unit.navanax.description = ยิงลูกระเบิดคลื่นชีพจรแม่เหล็กขนาดใหญ่ สร้างความเสียหายอย่างหนักให้กับเครือข่ายพลังงานศัตรู\nและซ่อมแซมสิ่งก่อสร้างของพวกพ้อง\nหลอมละลายศัตรูที่อยู่ใกล้เคียงด้วยป้อมปืนเลเซอร์อัตโนมัติสี่ป้อม lst.read = อ่านเลขจากเซลล์ความจำที่เชื่อมต่อไว้ lst.write = เขียนเลขไปยังเซลล์ความจำที่เชื่อมต่อไว้ diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties index 8b9f3a97aa..6c573d95d1 100644 --- a/core/assets/bundles/bundle_tk.properties +++ b/core/assets/bundles/bundle_tk.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Sand Boulder block.grass.name = Grass -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Salt block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = su alti -block.water.name = su +block.deep-water.name = su alti +block.shallow-water.name = su block.tainted-water.name = Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar @@ -1001,7 +1001,7 @@ block.sand.name = kum block.darksand.name = Dark Sand block.ice.name = buz block.snow.name = kar -block.craters.name = Craters +block.crater-stone.name = Craters block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 8fbcd2b97c..9f32da7999 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -18,7 +18,7 @@ linkfail = Link açılamadı!\nURL kopyalandı. screenshot = Ekran görüntüsü {0} konumuna kaydedildi screenshot.invalid = Harita çok büyük, muhtemelen ekran görüntüsü için yeterli bellek yok. gameover = Kaybettin -gameover.waiting = [accent]Harita Bekleniyor... +gameover.waiting = [accent]Sonraki Harita Bekleniyor... gameover.pvp = [accent] {0}[] Takımı kazandı! gameover.disconnect = Bağlantı Koptu! highscore = [accent]Yeni rekor! @@ -35,7 +35,7 @@ load.mod = Modlar load.scripts = Betikler be.update = Yeni bir erken erişim sürümü var: -be.update.confirm = Yüklenip yeniden başlatılsın mı? +be.update.confirm = İndirip yeniden başlatılsın mı? be.updating = Yeni sürüm yükleniyor... be.ignore = Hayır be.noupdates = Yeni güncelleme bulunamadı. @@ -54,30 +54,30 @@ schematic.add = Şemayı Kaydet... schematics = Şemalar schematic.replace = Aynı isimde bir şema zaten var. Üzerine yazılsın mı? schematic.exists = Aynı isimde bir şema zaten var. -schematic.import = Şema İçeri Aktar... +schematic.import = Şemayı İçeri Aktar... schematic.exportfile = Dışa Aktar schematic.importfile = İçe Aktar -schematic.browseworkshop = Atölyeyi incele +schematic.browseworkshop = Atölyeyi araştır schematic.copy = Panoya Kopyala schematic.copy.import = Panodan İçeri Aktar -schematic.shareworkshop = Atölyede Kaydet +schematic.shareworkshop = Atölyede paylaş schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Şemayı döndür schematic.saved = Şema Kaydedildi. -schematic.delete.confirm = Bu şema tamamen yok edilecek. +schematic.delete.confirm = Bu şema tamamen silinecek. schematic.rename = Şemayı yeniden adlandır schematic.info = {0}x{1}, {2} blok -schematic.disabled = [scarlet]Schematics disabled[]\nYou are not allowed to use schematics on this [accent]map[] or [accent]server. +schematic.disabled = [scarlet]Şema devre dışı bırakıldı[]\nBu şemayı [accent]bu haritada[] veya [accent]server'da kullanma iznin yok. schematic.tags = Etiketler: schematic.edittags = Etiketleri Düzenle schematic.addtag = Etiket Ekle schematic.texttag = Yazı Etiketi -schematic.icontag = İcon Etiketi +schematic.icontag = İkon Etiketi schematic.renametag = Etiketi Yeniden Adlandır schematic.tagdelconfirm = Bu Etiketi Silmek istediğine emin misin? schematic.tagexists = Böyle bir Etiket zaten var. stats = İstatistikler -stat.wave = Yenilen Dalgalar:[accent] {0} +stat.wave = Bozguna Uğratılan Dalgalar:[accent] {0} stat.enemiesDestroyed = Yok Edilen Düşmanlar:[accent] {0} stat.built = İnşa Edilen Yapılar:[accent] {0} stat.destroyed = Yok Edilen Yapılar:[accent] {0} @@ -89,7 +89,7 @@ stat.rank = Rütbe: [accent]{0} globalitems = [accent]Toplanan Kaynaklar map.delete = "[accent]{0}[]" haritasını silmek istediğine emin misin? level.highscore = Rekor: [accent]{0} -level.select = Seviye Seçimi +level.select = Bölüm Seçimi level.mode = Oyun Modu: coreattack = < Merkez saldırı altında! > nearpoint = [[ [scarlet]İNİŞ PİSTİNDEN AYRIL[] ]\nimha tehlikesi @@ -101,6 +101,7 @@ customgame = Özel Oyun newgame = Yeni Oyun none = none.found = [lightgray] +none.inmap = [lightgray] minimap = Harita position = Pozisyon close = Kapat @@ -121,7 +122,7 @@ committingchanges = Değişiklikler Uygulanıyor done = Bitti feature.unsupported = Cihazınızda bu özellik desteklenmemektedir. -mods.initfailed = [red]⚠[] OH NO! Mindustry Çöktü. Bu Büyük ihtimalle bir moddan kaynaklandı.\n\nSonsuz Çökmeyi önlemek için, [red]tüm modlar kapatıldı.[]\n\nBu özelliği kapamak için, [accent]Ayarlar->Oyun->Modları Çökmede Kapa[]. +mods.initfailed = [red]⚠[] OLAMAZ! Mindustry Çöktü. Bu Büyük ihtimalle bir moddan kaynaklandı.\n\nSonsuz Çökmeyi önlemek için, [red]tüm modlar kapatıldı.[]\n\nBu özelliği kapamak için, [accent]Ayarlar->Oyun->Modları Başlangıçta Çökme Durumunda Kapat[]. mods = Modlar mods.none = [lightgray]Hiç mod bulunamadı! mods.guide = Mod Rehberi @@ -214,6 +215,7 @@ hosts.none = [lightgray]Yerel oyun bulunamadı! host.invalid = [scarlet]Kurucuya bağlanılamıyor. servers.local = Yerel Sunucular +servers.local.steam = Açık Oyunar & Yerel Sunucular servers.remote = Uzak Sunucular servers.global = Topluluk Sunucuları @@ -565,6 +567,7 @@ sectors.unexplored = [lightgray]Keşfedilmemiş sectors.resources = Kaynaklar: sectors.production = Üretim: sectors.export = İhracat: +sectors.import = İthalat: sectors.time = Zaman: sectors.threat = Tehlike: sectors.wave = Dalga: @@ -806,6 +809,7 @@ bullet.reload = [stat]{0}[lightgray]x atış hızı unit.blocks = blok unit.blockssquared = blok² unit.powersecond = enerji birimi/saniye +unit.tilessecond = alan/saniye unit.liquidsecond = sıvı birimi/saniye unit.itemssecond = eşya/saniye unit.liquidunits = sıvı birimi @@ -871,7 +875,8 @@ setting.saveinterval.name = Kayıt Aralığı setting.seconds = {0} Saniye setting.milliseconds = {0} milisaniye setting.fullscreen.name = Tam Ekran -setting.borderlesswindow.name = Kenarsız Pencere [lightgray](yeniden açmak gerekebilir) +setting.borderlesswindow.name = Kenarsız Pencere +setting.borderlesswindow.description = Oyunu baştan açman gerekebilir. setting.fps.name = FPS Göster setting.smoothcamera.name = Yumuşak Geçişli Kamera setting.vsync.name = VSync @@ -994,6 +999,7 @@ rules.wavetimer = Dalga Zamanlayıcısı rules.waves = Dalgalar rules.attack = Saldırı Modu rules.buildai = Yapay Zeka İnşası +rules.cleanupdeadteams = Kaybeden Takımın Bloklarını Temizle (PvP) rules.corecapture = Yıkımca Çekirdeği Elegeçir rules.polygoncoreprotection = Çokgenli Çekirdek Koruması rules.enemyCheat = Sonsuz AI (Kırmızı Takım) Kaynakları @@ -1102,7 +1108,7 @@ block.cliff.name = Uçurum block.sand-boulder.name = Kumlu Kaya Parçaları block.basalt-boulder.name = Bazalt Kaya block.grass.name = Çimen -block.slag.name = Cüruf +block.molten-slag.name = Cüruf block.space.name = Uzay block.salt.name = Tuz block.salt-wall.name = Tuz Duvar @@ -1133,8 +1139,8 @@ block.spawn.name = Düşman Doğma Noktası block.core-shard.name = Merkez: Parçacık block.core-foundation.name = Merkez: Temel block.core-nucleus.name = Merkez: Çekirdek -block.deepwater.name = Derin Su -block.water.name = Su +block.deep-water.name = Derin Su +block.shallow-water.name = Su block.tainted-water.name = Kirli Su block.darksand-tainted-water.name = Kara Kumlu Kirli Su block.tar.name = Katran @@ -1143,7 +1149,7 @@ block.sand.name = Kum block.darksand.name = Kara Kum block.ice.name = Buz block.snow.name = Kar -block.craters.name = Krater +block.crater-stone.name = Krater block.sand-water.name = Kumlu Su block.darksand-water.name = Kara Kumlu Su block.char.name = Kömür @@ -1288,7 +1294,6 @@ block.meltdown.name = Meltdown block.foreshadow.name = Foreshadow block.container.name = Konteyner block.launch-pad.name = Kalkış Pisti -block.launch-pad-large.name = Büyük Kalkış Pisti block.segment.name = Segment block.command-center.name = Komuta Merkezi block.ground-factory.name = Yer Birimi Fabrikası @@ -1348,6 +1353,7 @@ hint.placeTurret = \uf861 [accent]Silahlar[] seni düşman birimlerinden korumak hint.breaking = Blokları silmek için silmek istediğiniz objelerin üstüne [accent]Sağ Tıklayın[]. Birden fazla obje silmek için sağ tuşu basılı tutun ve farenizi sürükleyin. hint.breaking.mobile = Ekranın sağ altındaki \ue817 [accent]çekiç[] tuşuna basın ve silmek istediğiniz objelere tıklayın. \n\nBirden fazla obje silmek için parmağınızı ekranda 1 saniye basılı tutun ve parmağınızı sürükleyin. hint.blockInfo = Bir blok hakkında bilgiyi görüntülemek için [accent]inşa menüsüne[] tıklayın. Sonra sağdaki [accent][[?][] sembolüne tıklayın. +hint.derelict = [accent]Sahipsiz[] binalar artık çalışmaz durumdadır. \n\nBu binaları [accent]yıkarsanız[] size malzeme verirler. hint.research = \ue875 [accent]Araştırma[] sekmesini kullanarak yeni teknolojiler araştırabilirsiniz. hint.research.mobile = \ue88c [accent]Menüdeki[] \ue875 [accent]Araştırma[] sekmesini kullanarak yeni teknolojiler araştırabilirsiniz. hint.unitControl = Kendi takımınızdaki taret ve birimleri kontrol etmek için [accent][[Sol CTRL][] tuşunu basılı tutarak istediğiniz taretin yada birimin üstüne sol tıklayın. @@ -1369,8 +1375,6 @@ hint.generator = \uf879 [accent]Termik Jeneratör[] kömür yakarak enerji üret hint.guardian = [accent]Gardiyan[] birimleri güçlü bir zırha sahiptir. [accent]bakır[] ve [accent]kurşun[] gibi mermilere karşı [scarlet]Dayanıklıdır[].\n\nGardiyanları öldürmek için [accent]salvo[] gibi daha güçlü taretleri ve \uf835 [accent]grafit[] gibi daha çok hasar veren mermileri kullanın. hint.coreUpgrade = Merkezinizi, [accent]merkezinizin üstüne daha gelişmiş bir merkez[] koyarak geliştirebilirsiniz. \n\n[accent]Parçacık[] olarak adlandırılan fakirhanenizin üstüne [accent]Temel[] olarak adlandırılan merkezinizi koyun. Merkezinizin etrafında hiçbir yapı olmamalıdır. hint.presetLaunch = [accent]Donmuş Ormanlar[] gibi [accent]ana sektörlere iniş[] herhangi bir yerden yapılabilir. Yakındaki bir sektörden fırlatma gerektirmez.\n\nBunun gibi [accent]sayı ile isimlendirilmiş[] sektörleri ele geçirmek [accent]isteğe bağlıdır.[]. -hint.coreUpgrade = Bir çekirdeğin Üstüne başka bir çekirdek koayarak onu geliştirebilirsin!\n\n Daha gelişmiş çekirdekler daha fazla kapasite demektir. -hint.presetLaunch = Hikaye Sektörlerine her yerden fırltış yapabilirsin! Ancak Numaralı Sektörlere temas olmadan Fırlatış yapılamaz. hint.coreIncinerate = Bir çekirdek ağzına kadar dolduktan sonra, ekstra itemler [accent]eritilir[]. hint.coopCampaign = Arkadaşlarınla Multiplayer Campaign oynarken, her yaptığınız Araştırma ve item aktarımı, senin oyun içi Campaign ine de aktarılır. #Yukarıdaki bağzı cümleler Anti Dragon tarafından çevirildi. @@ -1401,6 +1405,7 @@ liquid.slag.description = Çeşitli tipte erimiş metallerin birbirine karışı liquid.oil.description = İleri seviye malzeme üretiminde kullanılan bir sıvıdır. Yakıt olarak kömür haline getirilebilir veya püskürtülüp ateşe verilerek bir silah olarak kullanılabilir. liquid.cryofluid.description = Su ve titanyumdan oluşturulan inaktif bir sıvı. Son derece yüksek ısı kapasitesine sahiptir. Soğutucu olarak yaygın olarak kullanılır. +block.derelict = [lightgray] Sahipsiz block.resupply-point.description = Yakındaki birimlere mermi verir. Elektikle çalışmaz. block.armored-conveyor.description = Materyalleri titanyum konveyörlerle aynı hızda taşır ama daha fazla zırha sahiptir. Diğer konveyörler dışında yan taraflardan materyal kabul etmez. block.illuminator.description = Küçük, kompakt, yapılandırılabilir bir ışık kaynağı. Çalışması için enerji gerekir. @@ -1504,7 +1509,6 @@ block.vault.description = Her materyalden az miktarda saklar. Materyalleri kasad block.container.description = Her materyalden az miktarda saklar. Materyalleri konteynerden almak için bir boşaltıcı bloğu kullanılabilir. block.unloader.description = Materyalleri bir konteyner, kasa, veya çekirdekten çıkarıp; bir konveyöre veya dibindeki bir bloğa koyar. Çıkardığı materyal türü dokunularak değiştirilebilir. block.launch-pad.description = Başka Bir Sektöre item gönderir. -block.launch-pad-large.description = Kalkış pistinin daha gelişmiş bir versiyonu. Daha fazla materyali daha sık gönderebilir. block.duo.description = Küçük, ucuz bir taret. Yer birimlerine karşı etkilidir. block.scatter.description = Önemli bir uçaksavar tareti. Düşman birimlerine hurda ya da kurşun uçaksavar mermileri atar. block.scorch.description = Etrafındaki düşmanları ateşe verir. Yakın mesafede çok etkilidir. @@ -1519,6 +1523,7 @@ block.ripple.description = Çok güçlü bir havan tareti. Uzak mesafedeki düş block.cyclone.description = Büyük bir anti hava ve anti kara tareti. Yakınındaki düşmanlara patlayıcı uçaksavar mermi kümeleri atar. block.spectre.description = Dev bir çift namlulu top. Hava ve kara birimlerine iri, zırh delici mermiler atar. block.meltdown.description = Dev bir lazer topu. Yüklenip yakındaki düşmanlara uzun süreli lazer ışınları yollar. Çalışması için soğutucu gerekir. +block.foreshadow.description = Çok uzaktaki Tek bir hedefe inanılmaz güçlü bir şok ışını vurur. En fazla canı olan elemanı hedef alır. block.repair-point.description = Kendisine en yakın hasarlı birimi tamir eder. block.segment.description = Gelen mermilere zarar verir ve onları yok eder. Lazer mermilere etki etmez. block.parallax.description = Çekici bir ışın fırlatarak hava düşmanlarını kendine çeker. Onlara az da olsa zarar verir. @@ -1545,6 +1550,8 @@ block.memory-bank.description = Bilgi saklar. Yüksek kapasiteye sahiptir. block.logic-display.description = Bir işlemciden bilgi alarak grafik gösteririr. block.large-logic-display.description = Bir işlemciden bilgi alarak grafik gösteririr. block.interplanetary-accelerator.description = Gezegenler Arası ulaşım şimdi parmaklarının ucunda... +block.repair-turret.description = Sürekli en yakın elemanı tamir eder. Soğutucu kullanabilir. +block.payload-propulsion-tower.description = Kütle sürücü gibi bir yerden başka bir yere fırlatır, ancak malzeme yerine yük fırlatmakta kullanılır. #burdan sonraki her şeyi benim translate etmem gerekti!!! -RTOmega unit.dagger.description = Düşmanlara basit mermilerle ateş eder. unit.mace.description = Düşmanlara alev atar. @@ -1579,6 +1586,11 @@ unit.omura.description = Uzun menzil bir ışın atıcıya sahiptir. Mermisi ner unit.alpha.description = Çekirdeği korur. Bina inşa eder. unit.beta.description = Çekirdeği korur. Bina inşa eder. unit.gamma.description = Çekirdeği korur. Bina inşa eder. +unit.retusa.description = Sensörlü mayın döşer. Yakındakileri tamir eder. +unit.oxynoe.description = Tamir edici ateş fırlatır. Düşman mermilerini havada vurur. +unit.cyerce.description = Takipçi toplu füze atar. Yakındakileri tamir eder. +unit.aegires.description = Enerji alanına giren düşmanları şoklar. Yakındakileri tamir eder. +unit.navanax.description = Devasa patlayıcı EMP gülleleri fırlatır, düşman elektir sistemlerini yok eder ve müttefiklerini tamir eder. Yaklaşan düşmanları 4 mini oto-laser turreti ile eritir. lst.read = Bağlı hafıza kutusundaki numarayı okur. lst.write = Bağlı hafıza kutuaundaki numaraya yazar. @@ -1593,6 +1605,8 @@ lst.sensor = Bloklardan bilgi alır. lst.set = Bir değişken ata. lst.operation = Değişkenlerle işlem yap. lst.end = Döngünün sonuna atla. +lst.wait = Belli süre bekler. +lst.lookup = ID kullanarak herhangi bir blok,eleman,bina vs ye bak.\nToplam sayı kullanımı:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] lst.jump = Bir yerden başka bir yere atla. lst.unitbind = Bir birimi bağla: [accent]@unit[]. lst.unitcontrol = Bağlı birimi kontrol et. diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index 062421a05c..09e3df9cd8 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -55,15 +55,24 @@ schematic.delete.confirm = Ви справді хочете видалити ц schematic.rename = Перейменувати схему schematic.info = {0}x{1}, блоків: {2} schematic.disabled = [scarlet]Схеми вимкнені[]\nВам не дозволяється використовувати схеми на цій [accent]мапі[] чи [accent]сервері. +schematic.tags = Мітки: +schematic.edittags = Редагувати мітки +schematic.addtag = Додати мітку +schematic.texttag = Текстова мітка +schematic.icontag = Мітка із значком +schematic.renametag = Перейменувати мітку +schematic.tagdelconfirm = Видалити цю мітку повністю? +schematic.tagexists = Схожа мітка вже існує. + mod.featured.title = Переглядач модифікацій mods.browser = Переглядач модифікацій -mods.browser.selected = Обрана модифікація +mods.browser.selected = Вибрана модифікація mods.browser.add = Установити mods.browser.reinstall = Перевстановити mods.github.open = Відкрити mods.browser.sortdate = Сортувати за давністю -mods.browser.sortstars = Сортувати за кількостю зірок +mods.browser.sortstars = Сортувати за популярністю stats = Статистика stat.wave = Хвиль відбито:[accent] {0} @@ -298,7 +307,6 @@ data.exported = Дані вивантажено. data.invalid = Це не дійсні ігрові дані. data.import.confirm = Вивантаження зовнішніх даних перезапише[scarlet] ВСІ[] ваші поточні ігрові дані.\n[accent]Це неможливо скасувати![]\n\nЯк тільки дані імпортуються, гра негайно закриється. quit.confirm = Ви дійсно хочете вийти? -quit.confirm.tutorial = Ви впевнені, що знаєте, що робите?\nНавчання можна пройти наново[accent] Налаштування->Гра->Пройти навчання ще раз.[] loading = [accent]Завантаження… reloading = [accent]Перезавантаження модифікацій… saving = [accent]Збереження… @@ -463,11 +471,13 @@ filter.option.circle-scale = Масштаб круга filter.option.octaves = Циклічність застосування filter.option.falloff = Спад циклічності filter.option.angle = Кут +filter.option.rotate = Повернути filter.option.amount = Кількість filter.option.block = Блок filter.option.floor = Поверхня filter.option.flooronto = Цільова поверхня filter.option.target = Ціль +filter.option.replacement = Заміщення filter.option.wall = Стіна filter.option.ore = Руда filter.option.floor2 = Друга поверхня @@ -483,7 +493,8 @@ load = Завантажити save = Зберегти fps = FPS: {0} ping = Затримка: {0} мс -memory = Mem: {0}мб +tps = TPS: {0} +memory = Mem: {0} мб memory2 = Mem:\n {0}мб +\n {1}мб language.restart = Перезапустіть свою гру, щоби налаштування мови набули чинності. settings = Налаштування @@ -513,7 +524,7 @@ launch.from = Запуск з [accent]{0} launch.destination = Пункт призначення: {0} configure.invalid = Кількість має бути числом між 0 та {0}. add = Додати… -boss.health = Здоров’я Вартового +guardian = Вартовий connectfail = [crimson]Помилка з’єднання:\n\n[accent]{0} error.unreachable = Сервер не є доступним.\nЧи правильно написана адреса? error.invalidaddress = Некоректна адреса. @@ -553,6 +564,7 @@ sector.missingresources = [scarlet]Недостатньо ресурсів у я sector.attacked = Сектор [accent]{0}[white] під атакою! sector.lost = Сектор [accent]{0}[white] втрачено! sector.captured = Сектор [accent]{0}[white]захоплено! +sector.changeicon = Змінити значок threat.low = низька threat.medium = середня threat.high = висока @@ -600,6 +612,7 @@ status.wet.name = Вологий status.muddy.name = Забризканий гряззю status.melting.name = Плавиться status.sapped.name = Виснажений +status.electrified.name = Наелектризований status.spore-slowed.name = Сповільнений спорами status.tarred.name = Покритий нафтою status.overclock.name = Прискорений @@ -628,6 +641,7 @@ settings.clearcampaignsaves.confirm = Ви справді хочете очис paused = [accent]< Пауза > clear = Очистити banned = [scarlet]Заблоковано +unsupported.environment = [scarlet]Непідтримуване середовище yes = Так no = Ні info.title = Інформація @@ -636,6 +650,7 @@ error.crashtitle = Виникла помилка unit.nobuild = [scarlet]Ця одиниця не може будувати lastaccessed = [lightgray]Остання зміна від {0} block.unknown = [lightgray]??? +stat.showinmap = <завантажте мапу для показу> stat.description = Призначення stat.input = Ввід stat.output = Вивід @@ -665,6 +680,7 @@ stat.memorycapacity = Ємність пам’яті stat.basepowergeneration = Базова генерація енергії stat.productiontime = Час виробництва stat.repairtime = Час повного відновлення блоку +stat.repairspeed = Швидкість відновлення stat.weapons = Зброя stat.bullet = Кулі stat.speedincrease = Збільшення швидкості @@ -713,11 +729,12 @@ stat.reactive = Реактивний ability.forcefield = Щитове поле ability.repairfield = Ремонтувальне поле -ability.statusfield = Поле підсилення +ability.statusfield = {0} Поле підсилення ability.unitspawn = Завод одиниць «{0}» ability.shieldregenfield = Поле, що відновлює щити ability.movelightning = Блискавки під час руху -bar.drilltierreq = Потребується кращий бур +ability.energyfield = Енергетичне поле: [accent]{0}[] шкоди ~ [accent]{1}[] блоків / [accent]{2}[] цілей +bar.drilltierreq = Потрібен ліпший бур bar.noresources = Бракує ресурсів bar.corereq = Необхідне основне ядро bar.drillspeed = Швидкість буріння: {0} за с. @@ -738,6 +755,7 @@ bar.power = Енергія bar.progress = Хід будування bar.input = Ввід bar.output = Вивід +bar.strength = x[stat]{0}[lightgray] сила units.processorcontrol = [lightgray]Керується процесором bullet.damage = [stat]{0}[lightgray] шкода bullet.splashdamage = [stat]{0}[lightgray] шкода по ділянці ~[stat] {1}[lightgray] плиток @@ -755,6 +773,7 @@ bullet.reload = [stat]{0}[lightgray]x швидкість перезаряджа unit.blocks = блоки unit.blockssquared = блоків² unit.powersecond = одиниць енергії за секунду +unit.tilessecond = плиток за секунду unit.liquidsecond = одиниць рідини за секунду unit.itemssecond = предметів за секунду unit.liquidunits = одиниць рідини @@ -939,6 +958,8 @@ rules.wavetimer = Таймер для хвиль rules.waves = Хвилі rules.attack = Режим атаки rules.buildai = Будування ШІ +rules.corecapture = Захоплення ядра після знищення +rules.polygoncoreprotection = Полігональний захист ядер rules.enemyCheat = Нескінченні ресурси для червоної команди ШІ rules.blockhealthmultiplier = Множник здоров’я блоків rules.blockdamagemultiplier = Множник шкоди блоків @@ -1022,6 +1043,11 @@ unit.minke.name = Смугач unit.bryde.name = Брайд unit.sei.name = Сейвал unit.omura.name = Омура +unit.retusa.name = Ретуза +unit.oxynoe.name = Оксино +unit.cyerce.name = Саєс +unit.aegires.name = Еґірес +unit.navanax.name = Наванакс unit.alpha.name = Альфа unit.beta.name = Бета unit.gamma.name = Гамма @@ -1035,7 +1061,7 @@ block.cliff.name = Скеля block.sand-boulder.name = Пісочний валун block.basalt-boulder.name = Базальтовий валун block.grass.name = Трава -block.slag.name = Шлак +block.molten-slag.name = Шлак block.space.name = Космос block.salt.name = Сіль block.salt-wall.name = Соляна стіна @@ -1066,8 +1092,8 @@ block.spawn.name = Місце появи противника block.core-shard.name = Ядро «Уламок» block.core-foundation.name = Ядро «Штаб» block.core-nucleus.name = Ядро «Атом» -block.deepwater.name = Глибоководдя -block.water.name = Вода +block.deep-water.name = Глибоководдя +block.shallow-water.name = Вода block.tainted-water.name = Забруднена вода block.darksand-tainted-water.name = Темний пісок із забрудненою водою block.tar.name = Дьоготь @@ -1076,11 +1102,12 @@ block.sand.name = Пісок block.darksand.name = Темний пісок block.ice.name = Лід block.snow.name = Сніг -block.craters.name = Кратери +block.crater-stone.name = Кратери block.sand-water.name = Пісок із водою block.darksand-water.name = Темний пісок із водою block.char.name = Випалена земля block.dacite.name = Дацит +block.rhyolite.name = Риоліт block.dacite-wall.name = Дацитова стіна block.dacite-boulder.name = Дацитовий валун block.ice-snow.name = Крижаний сніг @@ -1098,7 +1125,8 @@ block.spore-cluster.name = Скупчення спор block.metal-floor.name = Металева підлога 1 block.metal-floor-2.name = Металева підлога 2 block.metal-floor-3.name = Металева підлога 3 -block.metal-floor-5.name = Металева підлога 4 +block.metal-floor-4.name = Металева підлога 4 +block.metal-floor-5.name = Металева підлога 5 block.metal-floor-damaged.name = Пошкоджена металева підлога block.dark-panel-1.name = Темна панель 1 block.dark-panel-2.name = Темна панель 2 @@ -1188,6 +1216,7 @@ block.solar-panel.name = Сонячна панель block.solar-panel-large.name = Велика сонячна панель block.oil-extractor.name = Екстрактор нафти block.repair-point.name = Ремонтний пункт +block.repair-point.name = Ремонтна башта block.pulse-conduit.name = Імпульсний трубопровід block.plated-conduit.name = Зміцнений трубопровід block.phase-conduit.name = Фазовий трубопровід @@ -1230,6 +1259,12 @@ block.exponential-reconstructor.name = Експоненційний реконс block.tetrative-reconstructor.name = Тетративний реконструктор block.payload-conveyor.name = Вантажний конвеєр block.payload-router.name = Розвантажувальний маршрутизатор +block.duct.name = Duct +block.duct-router.name = Канальний маршрутизатор +block.duct-bridge.name = Канальний міст +block.payload-propulsion-tower.name = Вантажна катапульта +block.payload-void.name = Вантажний вакуум +block.payload-source.name = Вантажне джерело block.disassembler.name = Розбирач block.silicon-crucible.name = Кремнієвий тигель block.overdrive-dome.name = Великий прискорювач @@ -1246,8 +1281,8 @@ block.large-logic-display.name = Великий логічний дисплей block.memory-cell.name = Комірка пам’яті block.memory-bank.name = Блок пам’яті team.blue.name = Синя -team.crux.name = Червона -team.sharded.name = Помаранчева +team.crux.name = Загарбники +team.sharded.name = Розколоті team.orange.name = Помаранчева team.derelict.name = Знедолена team.green.name = Зелена @@ -1268,6 +1303,7 @@ hint.placeConveyor.mobile = Конвеєри переміщують предме hint.placeTurret = Розмістіть  [accent]башти[], щоби захистити базу від ворогів.\n\nБашти потребують боєприпасів. У цьому випадку \uf838мідь.\nДля її подачі використовуйте конвеєри та бури. hhint.breaking = Натисніть [accent]ПКМ[] і тягніть, щоби зруйнувати блоки. hint.breaking.mobile = Активуйте  [accent]молот[] внизу праворуч і торкніться блоків, щоби їх розібрати.\n\nУтримуйте палець протягом секунди і протягніть, щоби розібрати виділене. +hint.blockInfo = Подивіться інформацію про блок. Перейдіть до [accent]меню будівництва[] і натисніть на кнопку [accent][[?][] правпоруч hint.research = Використовуйте кнопку  [accent]Дослідження[] для дослідження нової технології. hint.research.mobile = Використовуйте  [accent]Дослідження[] в  [accent]меню[] для дослідження нової технології. hint.unitControl = Утримуйте [accent][[лівий Ctrl][] і [accent]натисніть[] на одиницю чи башту, щоби контролювати її. @@ -1300,7 +1336,7 @@ item.graphite.description = Використовується для боєпри item.sand.description = Використовується для виробництва інших удосконалених матеріалів. item.coal.description = Використовується для виробництва палива і вдосконалених матеріалів. item.coal.details = Виглядає скам’янілою рослинною речовиною, утвореною задовго до Сівби. -item.titanium.description = Використовується в транспортуванні рідин, бурів та авіації. +item.titanium.description = Використовується в транспортуванні будівль, бурів та в заводах. item.thorium.description = Використовується в міцних конструкціях і як ядерне паливо. item.scrap.description = Використовується в Плавильнях і Подрібнювачах для перероблення в інші матеріали в інші матеріали. item.scrap.details = Залишки старих споруд та підрозділів. @@ -1507,6 +1543,8 @@ lst.sensor = Отримати дані з певної будівлі чи од lst.set = Установити значення змінної. lst.operation = Виконує операцію над 1-2 змінними. lst.end = Перейти до верхньої частини стеку операцій. +lst.wait = Зачекати певну кількість секунд. +lst.lookup = Знайдіть тип елемента, рідини, одиниці чи блоку за ідентифікатором.\nМожна отримати доступ до загальної кількості кожного типу через \n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] lst.jump = Умовне переходження до іншої операції. lst.unitbind = Прив’язка до одиниці певного типу та його зберігання в [accent]@unit[]. lst.unitcontrol = Контролювати поточну прив’язану одиницю. @@ -1518,7 +1556,7 @@ logic.nounitbuild = [red]Будування за допомогою процес lenum.type = Тип будівлі чи одиниці.\nНаприклад, для будь-якого маршрутизатора (англ. router), функція вертатиме [accent]@router[].\nНе є рядком. lenum.shoot = Стріляти в зазначену позицію. lenum.shootp = Стріляти в одиницю чи будівлю із передбаченням швидкості. -lenum.configure = Конфігурація будівлі, як-от в сортувальника. +lenum.config = Конфігурація будівлі, як-от в сортувальника. lenum.enabled = Чи блок увімкнено. laccess.color = Колір освітлювача. @@ -1526,6 +1564,7 @@ laccess.controller = Керувач одиницями. Якщо процесо laccess.dead = Чи є одиниця або будівля мертвою або недійсною. laccess.controlled = Повертає \n[accent]@ctrlProcessor[] якщо одиниця контролюється процесором;\n[accent]@ctrlPlayer[] якщо одиниця чи будівля контролюєть гравцем\n[accent]@ctrlFormation[] якщо одиниця у загоні (формуванні)\nІнакше — 0. laccess.commanded = [red]Застаріле. Буде видалено![]\nВикористовуйте натомість [accent]controlled[]. +laccess.progress = Прогрес дії, від 0 до 1.\nПовертає виробництво, перезавантаження башти або хід будівництва. graphicstype.clear = Залити дисплей вказаним кольором. graphicstype.color = Установити колір для подальшої операції малювання. @@ -1560,6 +1599,9 @@ lenum.len = Довжина вектора. lenum.sin = Синус, у градусах. lenum.cos = Косинус, у градусах. lenum.tan = Тангенс, у градусах. +lenum.asin = Арксинус, у градусах. +lenum.acos = Арккосинус, у градусах. +lenum.atan = Арктангенс, у градусах. #це не одруківка, пошукайте 'позначення діапазону' lenum.rand = Випадкове десяткове число у діапазоні [0, значення). lenum.log = Натуральний логарифм (ln). diff --git a/core/assets/bundles/bundle_vi.properties b/core/assets/bundles/bundle_vi.properties index 951bb1ecde..067d3703d9 100644 --- a/core/assets/bundles/bundle_vi.properties +++ b/core/assets/bundles/bundle_vi.properties @@ -1102,7 +1102,7 @@ block.cliff.name = Vách đá block.sand-boulder.name = Tường cát block.basalt-boulder.name = Tường đá basalt block.grass.name = Cỏ -block.slag.name = Xỉ nóng chảy +block.molten-slag.name = Xỉ nóng chảy block.space.name = Không gian block.salt.name = Muối block.salt-wall.name = Tường muối @@ -1133,8 +1133,8 @@ block.spawn.name = Khu vực tạo ra kẻ địch block.core-shard.name = Căn cứ: Cơ sở block.core-foundation.name = Căn cứ: Trụ sở block.core-nucleus.name = Căn cứ: Trung tâm -block.deepwater.name = Nước sâu -block.water.name = Nước +block.deep-water.name = Nước sâu +block.shallow-water.name = Nước block.tainted-water.name = Nước nhiểm bẩn block.darksand-tainted-water.name = Nước nhiễm bẩn cát đen block.tar.name = Dầu @@ -1143,7 +1143,7 @@ block.sand.name = Cát block.darksand.name = Cát đen block.ice.name = Băng block.snow.name = Tuyết -block.craters.name = Miệng núi lửa +block.crater-stone.name = Miệng núi lửa block.sand-water.name = Nước cát block.darksand-water.name = Nước cát đen block.char.name = Char diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties index e94bf8c026..e306743ea4 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -41,10 +41,13 @@ be.ignore = 忽略 be.noupdates = 未发现更新。 be.check = 检测更新 -mod.featured.dialog.title = 模组浏览器 (尚未完成) +mods.browser = 模组浏览器 mods.browser.selected = 已选模组 -mods.browser.add=安装 -mods.github.open=查看 +mods.browser.add = 安装 +mods.browser.reinstall = 重装 +mods.github.open = 查看 +mods.browser.sortdate = 按时间排序 +mods.browser.sortstars = 按星标排序 schematic = 蓝图 schematic.add = 保存蓝图… @@ -64,6 +67,14 @@ schematic.delete.confirm = 确认删除蓝图? schematic.rename = 重命名蓝图 schematic.info = {0}x{1},{2} 个方块 schematic.disabled = [scarlet]蓝图已禁用![]\n您不能在此[accent]地图[]或[accent]服务器[]上使用蓝图. +schematic.tags = 标签: +schematic.edittags = 编辑标签 +schematic.addtag = 增加新标签 +schematic.texttag = 文字标签 +schematic.icontag = 图标标签 +schematic.renametag = 重命名标签 +schematic.tagdelconfirm = 确定要完全删除这个标签吗? +schematic.tagexists = 这个标签已经存在了。 stats = 统计资料 stat.wave = 防守波数:[accent]{0} @@ -90,6 +101,7 @@ customgame = 自定义游戏 newgame = 新游戏 none = <无> none.found = [lightgray]<未找到> +none.inmap = [lightgray]<无法在地图中找到> minimap = 小地图 position = 位置 close = 关闭 @@ -110,26 +122,29 @@ committingchanges = 正在提交更改 done = 已完成 feature.unsupported = 您的设备不支持此功能。 -mods.alphainfo = 请注意,测试版本中的模组[scarlet]很容易存在缺陷[]。\n在 Mindustry 的 GitHub 或 Discord 上报告你发现的问题。 +mods.initfailed = [red]⚠[] 前一次的mindustry启动失败,这可能是由存在异常的模组导致的。\n\n为了防止循环崩溃,[red]所有模组都被禁用了。[]\n\n如果想关闭这个功能,可以在[accent]设置->游戏->游戏启动崩溃时不禁用模组[]里关闭. mods = 模组 mods.none = [lightgray]没有找到模组! mods.guide = 模组制作教程 mods.report = 报告 Bug mods.openfolder = 打开模组文件夹 +mods.viewcontent = 查看内容 mods.reload = 重载 mods.reloadexit = 游戏将退出以重载模组。 +mod.installed = [[已装载] mod.display = [gray]模组:[orange] {0} mod.enabled = [lightgray]已启用 mod.disabled = [scarlet]已禁用 +mod.multiplayer.compatible = [gray]多人游戏兼容性 mod.disable = 禁用 mod.content = 内容: -mod.delete.error = 无法删除模组。可能文件被占用。 -mod.requiresversion = [scarlet]所需的游戏版本:[accent]{0} +mod.delete.error = 无法删除模组。文件可能正在使用中。 +mod.requiresversion = [scarlet]所需的最低游戏版本:[accent]{0} mod.outdated = [scarlet]该模组可能不能在6.0上正确地运行(缺失 minGameVersion: 105) mod.missingdependencies = [scarlet]缺少前置模组:{0} mod.erroredcontent = [scarlet]内容错误 mod.errors = 读取内容时发生错误. -mod.noerrorplay = [scarlet]你的模组发生了错误.[] 禁用相关模组或修复错误后才能进入游戏. +mod.noerrorplay = [scarlet]您的模组发生了错误.[] 禁用相关模组或修复错误后才能进入游戏. mod.nowdisabled = [scarlet]“{0}”模组缺少依赖条件:[accent] {1}\n[lightgray]需要先下载上述模组。\n此模组现在将自动禁用。 mod.enable = 启用 mod.requiresrestart = 需要重启使模组生效。 @@ -165,19 +180,19 @@ researched = [lightgray]{0}己研究。 research.progress = {0}% 完成度 players = {0} 位玩家在线 players.single = {0} 位玩家在线 -players.search = 研究 +players.search = 搜索 players.notfound = [gray]没有找到玩家。 server.closing = [accent]服务器关闭… -server.kicked.kick = 你被踢出了服务器。 -server.kicked.whitelist = 你不在服务器白名单中。 +server.kicked.kick = 您被踢出了服务器。 +server.kicked.whitelist = 您不在服务器白名单中。 server.kicked.serverClose = 服务器已关闭。 server.kicked.vote = 您被投票踢出了服务器。 -server.kicked.clientOutdated = 客户端过旧,请更新你的游戏。 +server.kicked.clientOutdated = 客户端过旧,请更新您的游戏。 server.kicked.serverOutdated = 服务器过旧,请联系服务器管理员升级服务器。 server.kicked.banned = 您在这个服务器上被封禁了。 -server.kicked.typeMismatch = 此服务器与你的不稳定测试版不兼容。 +server.kicked.typeMismatch = 此服务器与您的不稳定测试版不兼容。 server.kicked.playerLimit = 服务器已满,请等待一个空位。 -server.kicked.recentKick = 你刚刚被踢出服务器。\n请稍后重新连接! +server.kicked.recentKick = 您刚刚被踢出服务器。\n请稍后重新连接! server.kicked.nameInUse = 您的名字与服务器中的一个人重复了。 server.kicked.nameEmpty = 无效的名字! server.kicked.idInUse = 您已经连接了这个服务器!不允许在一台设备上用两个客户端连接。 @@ -214,6 +229,8 @@ trace.ip = IP 地址:[accent]{0} trace.id = 唯一的 ID:[accent]{0} trace.mobile = 移动客户端:[accent]{0} trace.modclient = 自定义客户端:[accent]{0} +trace.times.joined = 进入服务器次数: [accent]{0} +trace.times.kicked = 踢出服务器次数: [accent]{0} invalidid = 无效的客户端 ID!提交一个错误报告。 server.bans = 黑名单 server.bans.none = 没有被封禁的玩家! @@ -287,6 +304,7 @@ cancel = 取消 openlink = 打开链接 copylink = 复制链接 back = 返回 +max = 最大值 crash.export = 导出崩溃日志 crash.none = 找不到崩溃日志。 crash.exported = 崩溃日志已导出。 @@ -297,7 +315,6 @@ data.exported = 数据已导出。 data.invalid = 非有效游戏数据。 data.import.confirm = 导入外部游戏数据将覆盖本地[scarlet]全部[]的游戏数据。\n[accent]此操作无法撤销![]\n\n数据导入后将自动退出游戏。 quit.confirm = 确定退出? -quit.confirm.tutorial = 确定要跳过教程?\n您可以通过[accent]设置->游戏->重玩教程[]来重玩教程。 loading = [accent]加载中… reloading = [accent]重载模组中… saving = [accent]保存中… @@ -306,6 +323,7 @@ cancelbuilding = [accent][[{0}][]来清除规划 selectschematic = [accent][[{0}][]来选择复制 pausebuilding = [accent][[{0}][]来暂停建造 resumebuilding = [scarlet][[{0}][]来恢复建造 +enablebuilding = [scarlet][[{0}][]来启用建造 showui = UI已隐藏\n按[accent][[{0}][]显示UI wave = [accent]第{0}波 wave.cap = [accent]波次 {0}/{1} @@ -324,7 +342,7 @@ saveimage = 保存图片 unknown = 未知 custom = 自定义 builtin = 内置的 -map.delete.confirm = 您确定你想要删除这张地图吗?这个操作无法撤销! +map.delete.confirm = 您确定想要删除这张地图吗?这个操作无法撤销! map.random = [accent]随机地图 map.nospawn = 这个地图没有核心!请在编辑器中添加一个[royal]己方[]的核心。 map.nospawn.pvp = 这个地图没有敌人的核心!请在编辑器中添加一个[royal]敌人[]的核心。 @@ -332,7 +350,7 @@ map.nospawn.attack = 这个地图没有敌人的核心!请在编辑中向地 map.invalid = 地图载入错误:地图文件可能已经损坏。 workshop.update = 更新地图 workshop.error = 获取创意工坊详细信息时出错:{0} -map.publish.confirm = 确定上传此地图?\n\n[lightgray]确定你同意 Steam 创意工坊的最终用户许可协议,否则你的地图将不会被展示! +map.publish.confirm = 确定上传此地图?\n\n[lightgray]确定您同意 Steam 创意工坊的最终用户许可协议,否则您的地图将不会被展示! workshop.menu = 选择此项目的目的。 workshop.info = 项目信息 changelog = 更新日志(可选): @@ -345,8 +363,8 @@ steam.error = 初始化 Steam 服务失败。\n错误:{0} editor.brush = 笔刷 editor.openin = 在编辑器中打开 -editor.oregen = 矿石的生成 -editor.oregen.info = 矿石的生成: +editor.oregen = 矿物的生成 +editor.oregen.info = 矿物的生成: editor.mapinfo = 地图信息 editor.author = 作者: editor.description = 描述: @@ -361,7 +379,6 @@ editor.center = 居中 workshop = 创意工坊 waves.title = 波数 waves.remove = 移除 -waves.never = < 无限 > waves.every = 每 waves.waves = 波 waves.perspawn = 每次生成 @@ -436,30 +453,32 @@ toolmode.orthogonal = 正交线 toolmode.orthogonal.description = 只绘制正交线。 toolmode.square = 方形 toolmode.square.description = 方形刷子 -toolmode.eraseores = 清除矿石 -toolmode.eraseores.description = 只清除矿石。 -toolmode.fillteams = 填充团队 -toolmode.fillteams.description = 填充团队而不是方块。 -toolmode.drawteams = 绘制团队 -toolmode.drawteams.description = 绘制团队而不是方块。 +toolmode.eraseores = 清除矿物 +toolmode.eraseores.description = 只清除矿物。 +toolmode.fillteams = 填充队伍 +toolmode.fillteams.description = 填充队伍而不是方块。 +toolmode.drawteams = 绘制队伍 +toolmode.drawteams.description = 绘制队伍而不是方块。 filters.empty = [lightgray]没有过滤条件!用下方的按钮添加。 + filter.distort = 扭曲程度 filter.noise = 波动程度 filter.enemyspawn = 敌人生成点选择 filter.spawnpath = 敌人生成途径 filter.corespawn = 核心降落点选择 filter.median = 平均数 -filter.oremedian = 矿石平均数 +filter.oremedian = 矿物平均数 filter.blend = 混合程度 -filter.defaultores = 默认矿石 -filter.ore = 矿石 +filter.defaultores = 默认矿物 +filter.ore = 矿物 filter.rivernoise = 河流波动程度 filter.mirror = 镜像 filter.clear = 清理 filter.option.ignore = 忽略 filter.scatter = 分散程度 filter.terrain = 地形 + filter.option.scale = 规模大小 filter.option.chance = 几率大小 filter.option.mag = 巨大程度 @@ -468,13 +487,15 @@ filter.option.circle-scale = 圆规模 filter.option.octaves = 递增 filter.option.falloff = 递减 filter.option.angle = 角度大小 +filter.option.rotate = 旋转 filter.option.amount = 数量 filter.option.block = 方块 filter.option.floor = 地面 filter.option.flooronto = 地面目标 filter.option.target = 目标 +filter.option.replacement = 替换 filter.option.wall = 墙 -filter.option.ore = 矿石 +filter.option.ore = 矿物 filter.option.floor2 = 二重地面 filter.option.threshold2 = 二重阈值 filter.option.radius = 半径大小 @@ -487,8 +508,9 @@ play = 开始游戏 campaign = 战役模式 load = 载入游戏 save = 保存 -fps = 帧数:{0} +fps = FPS:{0} ping = 延迟:{0}毫秒 +tps = TPS: {0} memory = 内存: {0}mb memory2 = 内存:\n {0}mb +\n {1}mb language.restart = 为了使语言设置生效请重启游戏。 @@ -521,7 +543,7 @@ launch.from = 发射地: [accent]{0} launch.destination = 目的地: {0} configure.invalid = 数量必须是0到{0}之间的数字。 add = 添加… -boss.health = Boss 生命值 +guardian = 守卫者 connectfail = [crimson]服务器连接失败:[accent]{0} error.unreachable = 无法访问服务器。\n确定输对地址了吗? @@ -537,15 +559,16 @@ error.bloom = 未能初始化特效。\n您的设备可能不支持。 weather.rain.name = 降雨 weather.snow.name = 降雪 weather.sandstorm.name = 沙尘暴 -weather.sporestorm.name = 孢子雾 +weather.sporestorm.name = 孢子风暴 weather.fog.name = 雾 sectors.unexplored = [lightgray]未探索 sectors.resources = 资源: sectors.production = 产出: sectors.export = 输出: +sectors.import = 输入: sectors.time = 时间: -sectors.threat = 威胁 +sectors.threat = 威胁: sectors.wave = 进攻波: sectors.stored = 贮存: sectors.resume = 继续 @@ -554,7 +577,7 @@ sectors.select = 选择 sectors.nonelaunch = [lightgray]无 (太阳) sectors.rename = 重命名区块 sectors.enemybase = [scarlet]敌人基地 -sectors.vulnerable = [scarlet]脆弱的 +sectors.vulnerable = [scarlet]易受攻击 sectors.underattack = [scarlet]遭到攻击![accent]{0}% 损毁度 sectors.survives = [accent]存活{0}波 sectors.go = 进入 @@ -565,12 +588,13 @@ sector.attacked = 区块[accent]{0}[white]受到攻击! sector.lost = 区块[accent]{0}[white]已丢失! #note: the missing space in the line below is intentional sector.captured = 区块[accent]{0}[white]已占领! +sector.changeicon = 更改图标 threat.low = 低度 threat.medium = 中度 threat.high = 高度 threat.extreme = 极高 -threat.eradication = 扫荡 +threat.eradication = 毁灭 planets = 行星 @@ -605,12 +629,26 @@ sector.tarFields.description = 产油区边缘,位于山脉和沙漠之间。 sector.desolateRift.description = 非常危险的区域。这儿的资源丰富但空间很小。敌人十分危险。尽快离开,不要被敌人的攻击间隔太长所愚弄。 sector.nuclearComplex.description = 以前生产和加工钍的设施已变成废墟。\n[lightgray]研究钍及其多种用途。\n\n敌人在这里大量存在,不断消灭入侵者。 sector.fungalPass.description = 介于高山和低矮孢子丛生的土地之间的过渡地带。这里有一个小型的敌方侦察基地。\n侦察它。\n使用尖刀和爬行者单位来摧毁两个核心。 -sector.biomassFacility.description = 孢子的发源地。这里有最初研究和生产孢子的设施。\n研究这里的科技,培养孢子来制造燃料和聚合物。\n\n[lightgray]设施损毁后,孢子散播了出去,原生生态系统无法抵挡这种外来物种。 +sector.biomassFacility.description = 孢子的发源地。这里有最初研究和生产孢子的设施。\n研究这里的科技,培养孢子来制造燃料和混合物。\n\n[lightgray]设施损毁后,孢子散播了出去,原生生态系统无法抵挡这种外来物种。 sector.windsweptIslands.description = 海岸线之外坐落着这一串群岛。据记载这里曾有生产[accent]塑钢[]的建筑。\n\n抵御敌人的海军,在岛上建立基地,研究这些工厂。 sector.extractionOutpost.description = 一座遥远的前哨,敌人为了向其他区域发射资源而建立。\n\n跨区域运输技术是征服这个星球不可或缺的技术。摧毁敌人基地,研究发射台。 sector.impact0078.description = 这里有最初进入这个星系的星际运输船的遗迹。\n\n回收可以利用的资源,研究科技。 sector.planetaryTerminal.description = 最终目标。\n\n这座滨海基地有一个可以将核心发射到其他行星的建筑,防卫森严。\n\n制造海军单位,尽快消灭敌人,研究发射建筑。 +status.burning.name = 燃烧 +status.freezing.name = 冰冻 +status.wet.name = 潮湿 +status.muddy.name = 泥泞 +status.melting.name = 熔化 +status.sapped.name = 削弱 +status.electrified.name = 麻痹 +status.spore-slowed.name = 孢子减速 +status.tarred.name = 油浸 +status.overclock.name = 超频 +status.shocked.name = 电击 +status.blasted.name = 爆炸 +status.unmoving.name = 静止 + settings.language = 语言 settings.data = 游戏数据 settings.reset = 恢复默认设置 @@ -632,6 +670,7 @@ settings.clearcampaignsaves.confirm = 您确定要清除战役进度? paused = [accent]< 暂停 > clear = 清除 banned = [scarlet]已禁止 +unsupported.environment = [scarlet]不支持的环境 yes = 是 no = 否 info.title = [accent]详情 @@ -641,12 +680,14 @@ unit.nobuild = [scarlet]单位未能建造 lastaccessed = [lightgray]上次操作: {0} block.unknown = [lightgray]??? +stat.showinmap = <加载地图以展示> stat.description = 介绍 stat.input = 输入 stat.output = 输出 stat.booster = 增强物品/液体 stat.tiles = 所需地型 stat.affinities = 相关 +stat.opposites = 对立 stat.powercapacity = 能量容量 stat.powershot = 能量/发射 stat.damage = 伤害 @@ -669,6 +710,7 @@ stat.memorycapacity = 内存容量 stat.basepowergeneration = 基础能源输出 stat.productiontime = 生产时间 stat.repairtime = 建筑完全修复时间 +stat.repairspeed = 修复速度 stat.weapons = 武器 stat.bullet = 子弹 stat.speedincrease = 提速 @@ -678,6 +720,7 @@ stat.drillspeed = 基础钻探速度 stat.boosteffect = 增强效果 stat.maxunits = 最大单位数量 stat.health = 生命值 +stat.armor = 护甲 stat.buildtime = 建造时间 stat.maxconsecutive = 最大连续 stat.buildcost = 建造花费 @@ -693,6 +736,7 @@ stat.lightningchance = 激发闪电几率 stat.lightningdamage = 激发闪电伤害 stat.flammability = 燃烧性 stat.radioactivity = 放射性 +stat.charge = 放电性 stat.heatcapacity = 热容量 stat.viscosity = 粘度 stat.temperature = 温度 @@ -703,9 +747,16 @@ stat.minetier = 采矿等级 stat.payloadcapacity = 载货容量 stat.commandlimit = 指挥上限 stat.abilities = 能力 -stat.canboost = 可助推 -stat.flying = 可飞行 +stat.canboost = 是否能助推 +stat.flying = 是否能飞行 stat.ammouse = 弹药消耗 +stat.damagemultiplier = 伤害倍率 +stat.healthmultiplier = 生命倍率 +stat.speedmultiplier = 移速倍率 +stat.reloadmultiplier = 射速倍率 +stat.buildspeedmultiplier = 建造速度倍率 +stat.reactive = 反应性 +stat.healing = 治疗 ability.forcefield = 力墙场 ability.repairfield = 修复场 @@ -713,6 +764,7 @@ ability.statusfield = 状态场 ability.unitspawn = {0} 单位工厂 ability.shieldregenfield = 护盾再生场 ability.movelightning = 闪电助推器 +ability.energyfield = 能量场: [accent]{0}[] 伤害 ~ [accent]{1}[] 格 / [accent]{2}[] 目标数 bar.drilltierreq = 需要更高级的钻头 bar.noresources = 缺失资源 @@ -720,11 +772,12 @@ bar.corereq = 缺失核心基座 bar.drillspeed = 挖掘速度:{0}/秒 bar.pumpspeed = 泵压速度:{0}/秒 bar.efficiency = 效率:{0}% +bar.boost = 超速:{0}% bar.powerbalance = 能量:{0}/秒 bar.powerstored = 储能:{0}/{1} bar.poweramount = 能量:{0} bar.poweroutput = 能量输出:{0} -bar.powerlines = 链接: {0}/{1} +bar.powerlines = 链接:{0}/{1} bar.items = 物品:{0} bar.capacity = 容量:{0} bar.unitcap = {0} {1}/{2} @@ -734,29 +787,28 @@ bar.power = 电力 bar.progress = 制造进度 bar.input = 输入 bar.output = 输出 +bar.strength = [stat]{0}[lightgray]x 效率 units.processorcontrol = [lightgray]由处理器控制 bullet.damage = [stat]{0}[lightgray] 伤害 bullet.splashdamage = [stat]{0}[lightgray] 范围伤害 ~[stat] {1}[lightgray] 格 bullet.incendiary = [stat] 燃烧 -bullet.sapping = [stat] 削弱 bullet.homing = [stat] 追踪 -bullet.shock = [stat] 电击 bullet.frag = [stat] 分裂 +bullet.lightning = [stat]{0}[lightgray]x 电弧 ~ [stat]{1}[lightgray] 伤害 bullet.buildingdamage = [stat]{0}%[lightgray] 对建筑伤害 bullet.knockback = [stat]{0}[lightgray] 击退 bullet.pierce = [stat]{0}[lightgray]x 穿透 -bullet.infinitepierce = [stat] 穿透 +bullet.infinitepierce = [stat] 贯穿 bullet.healpercent = [stat]{0}[lightgray]% 修复 -bullet.freezing = [stat] 冰冻 -bullet.tarred = [stat] 减速 bullet.multiplier = [stat]{0}[lightgray]x 装弹数量 bullet.reload = [stat]{0}[lightgray]x 装弹速度 unit.blocks = 方块 unit.blockssquared = 方块² unit.powersecond = 能量/秒 +unit.tilessecond = 格/秒 unit.liquidsecond = 液体/秒 unit.itemssecond = 物品/秒 unit.liquidunits = 液体 @@ -791,18 +843,20 @@ setting.logichints.name = 逻辑代码提示 setting.flow.name = 显示资源传送速度[scarlet] setting.backgroundpause.name = 在背景中暂停 setting.buildautopause.name = 自动暂停建造 -setting.animatedwater.name = 流动的水 -setting.animatedshields.name = 动态画面 -setting.antialias.name = 抗锯齿 -setting.playerindicators.name = 玩家指示灯 -setting.indicators.name = 队友指示器 +setting.doubletapmine.name = 双击以采矿 +setting.modcrashdisable.name = 游戏启动崩溃时不禁用模组 +setting.animatedwater.name = 动态液体 +setting.animatedshields.name = 动态力场 +setting.playerindicators.name = 玩家指示器 +setting.indicators.name = 敌军指示器 setting.autotarget.name = 自动射击 setting.keyboard.name = 鼠标+键盘操控 setting.touchscreen.name = 触屏操控 setting.fpscap.name = 最大FPS setting.fpscap.none = 无 setting.fpscap.text = {0} FPS -setting.uiscale.name = UI缩放比例[lightgray](需要重新启动)[] +setting.uiscale.name = UI缩放比例 +setting.uiscale.description = 需要重新启动以应用更改。 setting.swapdiagonal.name = 总是斜线建造 setting.difficulty.training = 训练 setting.difficulty.easy = 简单 @@ -820,7 +874,8 @@ setting.saveinterval.name = 自动保存间隔 setting.seconds = {0} 秒 setting.milliseconds = {0} 毫秒 setting.fullscreen.name = 全屏 -setting.borderlesswindow.name = 无边界窗口[lightgray](可能需要重启) +setting.borderlesswindow.name = 无边界窗口 +setting.borderlesswindow.description = 可能需要重新启动以应用更改。 setting.fps.name = 显示 FPS 和网络延迟 setting.smoothcamera.name = 镜头平滑 setting.vsync.name = 垂直同步 @@ -910,6 +965,7 @@ keybind.pause_building.name = 暂停/继续建造 keybind.minimap.name = 小地图 keybind.planet_map.name = 行星地图 keybind.research.name = 研究 +keybind.block_info.name = 方块信息 keybind.chat.name = 聊天 keybind.player_list.name = 玩家列表 keybind.console.name = 控制台 @@ -936,21 +992,27 @@ mode.custom = 自定义模式 rules.infiniteresources = 无限资源 rules.reactorexplosions = 反应堆爆炸 -rules.schematic = 启用蓝图 +rules.coreincinerates = 核心自动焚烧溢出物资 +rules.schematic = 允许使用蓝图 rules.wavetimer = 波次计时器 rules.waves = 波次 rules.attack = 攻击模式 rules.buildai = AI建造 +rules.cleanupdeadteams = 清理被打败的队伍的建筑(PvP模式) +rules.corecapture = 摧毁核心时占领该核心 +rules.polygoncoreprotection = 多边形核心保护区域 rules.enemyCheat = 敌人(红队)无限资源 rules.blockhealthmultiplier = 建筑生命倍数 rules.blockdamagemultiplier = 建筑伤害倍数 rules.unitbuildspeedmultiplier = 单位生产速度倍数 rules.unithealthmultiplier = 单位生命倍数 rules.unitdamagemultiplier = 单位伤害倍数 -rules.enemycorebuildradius = 敌对核心非建设区半径:[lightgray](格) +rules.unitcapvariable = 每个核心提供的单位上限 +rules.unitcap = 基础单位上限 +rules.enemycorebuildradius = 敌方核心禁造区半径:[lightgray](格) rules.wavespacing = 波次间隔时间:[lightgray](秒) -rules.buildcostmultiplier = 建设花费倍数 -rules.buildspeedmultiplier = 建设时间倍数 +rules.buildcostmultiplier = 建材倍率 +rules.buildspeedmultiplier = 建造速率 rules.deconstructrefundmultiplier = 拆除返还倍数 rules.waitForWaveToEnd = 等待敌人时间 rules.dropzoneradius = 敌人出生点禁区大小:[lightgray](格) @@ -962,7 +1024,7 @@ rules.title.unit = 单位 rules.title.experimental = 实验性 rules.title.environment = 环境性 rules.lighting = 光照 -rules.enemyLights = 单位光照 +rules.enemyLights = 敌方光照 rules.fire = 火焰 rules.explosions = 建筑/单位爆炸伤害 rules.ambientlight = 环境光 @@ -973,8 +1035,9 @@ rules.weather.duration = 时长: content.item.name = 物品 content.liquid.name = 液体 -content.unit.name = 部队 -content.block.name = 块 +content.unit.name = 单位 +content.block.name = 建筑 +content.status.name = 状态效果 content.sector.name = 区域 item.copper.name = 铜 @@ -985,14 +1048,15 @@ item.titanium.name = 钛 item.thorium.name = 钍 item.silicon.name = 硅 item.plastanium.name = 塑钢 -item.phase-fabric.name = 相位物 +item.phase-fabric.name = 相织物 item.surge-alloy.name = 巨浪合金 item.spore-pod.name = 孢子荚 item.sand.name = 沙 item.blast-compound.name = 爆炸混合物 -item.pyratite.name = 硫 +item.pyratite.name = 火石 item.metaglass.name = 钢化玻璃 item.scrap.name = 废料 + liquid.water.name = 水 liquid.slag.name = 矿渣 liquid.oil.name = 石油 @@ -1024,6 +1088,11 @@ unit.minke.name = 飞鲨 unit.bryde.name = 戟鲸 unit.sei.name = 蛟龙 unit.omura.name = 海神 +unit.retusa.name = 潜螺 +unit.oxynoe.name = 电鳗 +unit.cyerce.name = 江豚 +unit.aegires.name = 神盾 +unit.navanax.name = 龙王 unit.alpha.name = 阿尔法 unit.beta.name = 贝塔 unit.gamma.name = 伽马 @@ -1038,7 +1107,7 @@ block.cliff.name = 悬崖 block.sand-boulder.name = 砂岩 block.basalt-boulder.name = 玄武岩巨石 block.grass.name = 草地 -block.slag.name = 矿渣 +block.molten-slag.name = 矿渣 block.space.name = 太空 block.salt.name = 盐碱地 block.salt-wall.name = 盐墙 @@ -1069,23 +1138,24 @@ block.spawn.name = 敌人出生点 block.core-shard.name = 初代核心 block.core-foundation.name = 次代核心 block.core-nucleus.name = 终代核心 -block.deepwater.name = 深水 -block.water.name = 水 +block.deep-water.name = 深水 +block.shallow-water.name = 水 block.tainted-water.name = 污水 -block.darksand-tainted-water.name = 暗沙 污水 +block.darksand-tainted-water.name = 黑沙 污水 block.tar.name = 石油 block.stone.name = 石头 block.sand.name = 沙子 block.darksand.name = 黑沙 block.ice.name = 冰 block.snow.name = 雪 -block.craters.name = 陨石坑 +block.crater-stone.name = 陨石坑 block.sand-water.name = 沙 水 -block.darksand-water.name = 暗沙 水 +block.darksand-water.name = 黑沙 水 block.char.name = 焦土 -block.dacite.name = 英安岩 -block.dacite-wall.name = 英安岩墙 -block.dacite-boulder.name = 英安巨岩 +block.dacite.name = 安山岩 +block.rhyolite.name = 流纹岩 +block.dacite-wall.name = 安山岩墙 +block.dacite-boulder.name = 安山巨岩 block.ice-snow.name = 冰雪地 block.stone-wall.name = 石墙 block.ice-wall.name = 冰墙 @@ -1101,7 +1171,8 @@ block.spore-cluster.name = 孢子簇 block.metal-floor.name = 金属地板1 block.metal-floor-2.name = 金属地板2 block.metal-floor-3.name = 金属地板3 -block.metal-floor-5.name = 金属地板4 +block.metal-floor-4.name = 金属地板4 +block.metal-floor-5.name = 金属地板5 block.metal-floor-damaged.name = 损坏的金属地板 block.dark-panel-1.name = 暗面板1 block.dark-panel-2.name = 暗面板2 @@ -1111,16 +1182,16 @@ block.dark-panel-5.name = 暗面板5 block.dark-panel-6.name = 暗面板6 block.dark-metal.name = 暗金属 block.basalt.name = 玄武岩 -block.hotrock.name = 热石头 -block.magmarock.name = 岩浆石头 +block.hotrock.name = 灼热岩石 +block.magmarock.name = 熔融岩石 block.copper-wall.name = 铜墙 block.copper-wall-large.name = 大型铜墙 block.titanium-wall.name = 钛墙 block.titanium-wall-large.name = 大型钛墙 block.plastanium-wall.name = 塑钢墙 block.plastanium-wall-large.name = 大型塑钢墙 -block.phase-wall.name = 相位物墙 -block.phase-wall-large.name = 大型相位物墙 +block.phase-wall.name = 相织物墙 +block.phase-wall-large.name = 大型相织物墙 block.thorium-wall.name = 钍墙 block.thorium-wall-large.name = 大型钍墙 block.door.name = 门 @@ -1144,7 +1215,7 @@ block.illuminator.name = 照明器 block.overflow-gate.name = 溢流门 block.underflow-gate.name = 反向溢流门 block.silicon-smelter.name = 硅冶炼厂 -block.phase-weaver.name = 相位物编织器 +block.phase-weaver.name = 相织物编织器 block.pulverizer.name = 粉碎机 block.cryofluid-mixer.name = 冷冻液混合器 block.melter.name = 熔炉 @@ -1182,10 +1253,10 @@ block.tsunami.name = 海啸 block.swarmer.name = 蜂群 block.salvo.name = 齐射炮 block.ripple.name = 浪涌 -block.phase-conveyor.name = 相位物传送带桥 +block.phase-conveyor.name = 相织物传送带桥 block.bridge-conveyor.name = 传送带桥 block.plastanium-compressor.name = 塑钢压缩机 -block.pyratite-mixer.name = 硫化物混合器 +block.pyratite-mixer.name = 火石混合器 block.blast-mixer.name = 爆炸物混合器 block.solar-panel.name = 太阳能板 block.solar-panel-large.name = 大型太阳能板 @@ -1193,7 +1264,7 @@ block.oil-extractor.name = 石油钻井 block.repair-point.name = 维修点 block.pulse-conduit.name = 脉冲导管 block.plated-conduit.name = 电镀导管 -block.phase-conduit.name = 相位物导管桥 +block.phase-conduit.name = 相织物导管桥 block.liquid-router.name = 液体路由器 block.liquid-tank.name = 储液罐 block.liquid-junction.name = 液体交叉器 @@ -1233,14 +1304,20 @@ block.exponential-reconstructor.name = 多幂级单位重构工厂 block.tetrative-reconstructor.name = 无量级单位重构工厂 block.payload-conveyor.name = 载荷传送带 block.payload-router.name = 载荷路由器 +block.duct.name = 物品导管 +block.duct-router.name = 物品导管路由器 +block.duct-bridge.name = 物品导管桥 +block.payload-propulsion-tower.name = 载荷驱动台 +block.payload-void.name = 载荷黑洞 +block.payload-source.name =载荷源 block.disassembler.name = 解离机 block.silicon-crucible.name = 热能坩埚 block.overdrive-dome.name = 超速穹顶投射器 +block.interplanetary-accelerator.name = 行星际加速器 #experimental, may be removed block.block-forge.name = 方块熔炉 block.block-loader.name = 方块装载机 block.block-unloader.name = 方块卸载机 -block.interplanetary-accelerator.name = 行星际加速器 block.switch.name = 开关 block.micro-processor.name = 微型处理器 @@ -1254,50 +1331,50 @@ block.memory-bank.name = 内存库 team.blue.name = 蓝 team.crux.name = 红 team.sharded.name = 黄 -team.orange.name = 橙 team.derelict.name = 灰 team.green.name = 绿 team.purple.name = 紫 hint.skip = 跳过 -hint.desktopMove = 使用[accent][[WASD][]来移动. -hint.zoom = 滚动[accent]鼠标滚轮[]放大或缩小. -hint.mine = 移动到\uf8c4 铜矿附近并[accent]点按[]进行手动开采. -hint.desktopShoot = [accent][[鼠标左键][]射击. +hint.desktopMove = 使用[accent][[WASD][]来移动。 +hint.zoom = 滚动[accent]鼠标滚轮[]放大或缩小。 +hint.mine = 移动到\uf8c4 铜矿附近并[accent]点按[]进行手动开采。 +hint.desktopShoot = [accent][[鼠标左键][]射击。 hint.depositItems = 要转移物品,请将其从飞船上拖到核心。 -hint.respawn = 要于核心中重生,请按[accent][[V][]. -hint.respawn.mobile = 您已切换控制单元/结构. 如果要重生飞船,请[accent]点击左上方的图标(您的单元/结构图标).[] -hint.desktopPause = 按[accent][[Space][]暂停和取消暂停游戏. -hint.placeDrill = 选择右下角菜单中的\ue85e [accent]钻头[]分类,然后选择一个\uf870 [accent]钻头[]然后单击铜矿将其放置. -hint.placeDrill.mobile = 选择右下角菜单中的\ue85e [accent]钻头[]分类,然后选择一个\uf870 [accent]钻头[],然后点击铜矿将其放置.\n\n点击右下角\ue800 [accent]复选标记[]以确认. -hint.placeConveyor = 传送带将物品从钻头移到其他方块中。从\ue814 [accent]布局[]分类选择\uf896 [accent]传送带[].\n\n单击并拖动以放置多个传送带.\n[accent]滚动[]以旋转. -hint.placeConveyor.mobile = 传送带将物品从钻头移到其他块中。从\ue814 [accent]布局[]分类选择\uf896 [accent]传送带[].\n\n长按一秒钟,然后拖动以放置多个传送带. -hint.placeTurret = 放置\uf861 [accent]炮塔[]以抵御敌人,保卫你的核心.\n\n炮塔需要弹药-\uf838 铜.\n使用传送带和钻头为它们供弹。 -hint.breaking = [accent]右击[]并拖动以拆除方块. -hint.breaking.mobile = 点击在右下角的\ue817 [accent]锤子[]点击以拆除方块.\n\n按住手指一秒钟,然后拖动并选择. -hint.research = 点击\ue875 [accent]科技树[]按钮研究新技术. -hint.research.mobile = 点击在\ue88c [accent]菜单[]中的\ue875 [accent]科技树[]按钮以研究新技术. +hint.respawn = 要于核心中重生,请按[accent][[V][]。 +hint.respawn.mobile = 您已切换控制单元/建筑。如果要重生为飞船,请[accent]点击左上方的图标(您的单元/结构图标)。[] +hint.desktopPause = 按[accent][[Space][]暂停和取消暂停游戏。 +hint.placeDrill = 选择右下角菜单中的\ue85e [accent]钻头[]分类,然后选择一个\uf870 [accent]钻头[]然后单击铜矿将其放置。 +hint.placeDrill.mobile = 选择右下角菜单中的\ue85e [accent]钻头[]分类,然后选择一个\uf870 [accent]钻头[],然后点击铜矿将其放置。\n\n点击右下角\ue800 [accent]复选标记[]以确认。 +hint.placeConveyor = 传送带将物品从钻头移到其他方块中。从\ue814 [accent]布局[]分类选择\uf896 [accent]传送带[]。\n\n单击并拖动以放置多个传送带。\n[accent]滚动[]以旋转。 +hint.placeConveyor.mobile = 传送带将物品从钻头移到其他块中。从\ue814 [accent]布局[]分类选择\uf896 [accent]传送带[]。\n\n长按一秒钟,然后拖动以放置多个传送带。 +hint.placeTurret = 放置\uf861 [accent]炮塔[]以抵御敌人,保卫你的核心。\n\n炮塔需要弹药-\uf838 铜。\n使用传送带和钻头为它们供弹。 +hint.breaking = [accent]右击[]并拖动以拆除方块。 +hint.breaking.mobile = 点击在右下角的\ue817 [accent]锤子[]点击以拆除方块。\n\n按住手指一秒钟,然后拖动并选择。 +hint.blockInfo = 在 [accent]建造菜单[]中选择一个建筑,然后点击右边的 [accent][[?][]按钮以查看这个方块的信息。 +hint.research = 点击\ue875 [accent]科技树[]按钮研究新技术。 +hint.research.mobile = 点击在\ue88c [accent]菜单[]中的\ue875 [accent]科技树[]按钮以研究新技术。 hint.unitControl = 按住[accent][[L-ctrl][]并[accent]点击[]友军单位或炮塔来进行控制。 hint.unitControl.mobile = [accent][双击][]友军单位或炮塔来进行控制。 -hint.launch = 一旦收集到足够的资源,您就可以通过从右下角的\ue827 [accent]地图[]选择附近的区域[accent]发射[]核心. -hint.launch.mobile = 一旦收集到足够的资源,您就可以通过在\ue88c [accent]菜单[]的\ue827 [accent]地图[]选择附近的区域[accent]发射[]核心. -hint.schematicSelect = 按住[accent][[F][]并拖动以选择要复制和粘贴的块.\n\n[accent][鼠标中键][]复制单个块类型. -hint.conveyorPathfind = 按住[accent][[L-Ctrl][]拖动传送带并使其自动寻路. -hint.conveyorPathfind.mobile = 启用\ue844 [accent]传送带自动寻路[]并拖动,传送带会自动生成路径. -hint.boost = 按住[accent][[L-Shift][]用当前单位飞越障碍物.\n\n但只有少数地面单位有助推器. -hint.command = 按住[accent][[G][]指挥附近的单位编队. -hint.command.mobile = [accent][[双击][]您的部队指挥附近的部队编队. -hint.payloadPickup = 按[accent][[[]捡起小方块或单位. -hint.payloadPickup.mobile = [accent]长按一个小方块或一个单位来捡起来. -hint.payloadDrop = 按[accent]][]放下有效载荷. -hint.payloadDrop.mobile = [accent]点住[]一个空的位置将有效载荷丢到那里. -hint.waveFire = [accent]波浪[]炮塔加水弹药会自动扑灭附近的火. -hint.generator = \uf879 [accent]燃烧发电机[]燃烧煤炭并将电力传输到相邻方块.\n\n用\uf87f [accent]能量节点[]可以扩展电力传输范围. -hint.guardian = [accent]Boss[]单位装甲厚重.[accent]铜[]和[accent]铅[]这类较弱的子弹对其[scarlet]作用不佳[].\n\n使用高级别炮塔或使用\uf835 [accent]石墨[]作为\uf861 双管炮及\uf859 齐射炮的弹药来消灭Boss. +hint.launch = 一旦收集到足够的资源,您就可以通过从右下角的\ue827 [accent]地图[]选择附近的区域[accent]发射[]核心。 +hint.launch.mobile = 一旦收集到足够的资源,您就可以通过在\ue88c [accent]菜单[]的\ue827 [accent]地图[]选择附近的区域[accent]发射[]核心。 +hint.schematicSelect = 按住[accent][[F][]并拖动以选择要复制和粘贴的块。\n\n[accent][鼠标中键][]复制单个块类型。 +hint.conveyorPathfind = 按住[accent][[L-Ctrl][]拖动传送带并使其自动寻路。 +hint.conveyorPathfind.mobile = 启用\ue844 [accent]传送带自动寻路[]并拖动,传送带会自动生成路径。 +hint.boost = 按住[accent][[L-Shift][]用当前单位飞越障碍物。\n\n但只有少数地面单位有助推器。 +hint.command = 按住[accent][[G][]指挥附近的单位编队。 +hint.command.mobile = [accent][[双击][]您的部队指挥附近的部队编队。 +hint.payloadPickup = 按[accent][[[]捡起方块或单位。 +hint.payloadPickup.mobile = [accent]长按一个方块或一个单位来捡起来。 +hint.payloadDrop = 按[accent]][]放下捡起的方块或单位。 +hint.payloadDrop.mobile = [accent]点住[]一个空的位置将捡起的方块或单位丢到那里。 +hint.waveFire = [accent]波浪[]炮塔加水弹药会自动扑灭附近的火。 +hint.generator = \uf879 [accent]燃烧发电机[]燃烧煤炭并将电力传输到相邻方块。\n\n用\uf87f [accent]能量节点[]可以扩展电力传输范围。 +hint.guardian = [accent]Boss[]单位装甲厚重。[accent]铜[]和[accent]铅[]这类较弱的子弹对其[scarlet]作用不佳[]。\n\n使用高级别炮塔或使用\uf835 [accent]石墨[]作为\uf861 双管炮及\uf859 齐射炮的弹药来消灭Boss。 hint.coreUpgrade = 核心可以通过[accent]在上面覆盖高等级核心[]进行升级。\n\n在[accent]初代核心[]上放置一个[accent]次代核心[]。确保周围没有障碍物。 hint.presetLaunch = 灰色的[accent]降落地区[],如[accent]冰冻森林[],可以从任何区域发射,不需要占领附近的区块。\n\n[accent]数字编号的区域[],如这个,是[accent]可选的[]。 hint.coreIncinerate = 核心存满一种物品后,再进入的同种物品会被[accent]摧毁[]。 -hint.coopCampaign = 游玩[accent]合作战役[]时,当前地图生产的资源也会被送入[accent]你本地的区域[]。\n\n新科技也会同步解锁。 +hint.coopCampaign = 游玩[accent]合作战役[]时,当前地图生产的资源也会被送入[accent]您本地的区域[]。\n\n新科技也会同步解锁。 item.copper.description = 用于所有类型的建筑和弹药。 item.copper.details = 铜。在塞普罗上的异常丰富的金属。不经加固,结构会较脆弱。 @@ -1327,7 +1404,7 @@ liquid.oil.description = 用于先进材料生产和燃烧弹药。 liquid.cryofluid.description = 用作反应堆、炮塔和工厂的冷却剂。 block.resupply-point.description = 为附近的部队提供铜弹药。与需要电池供电的设备不兼容。 -block.armored-conveyor.description = 向前方移动物品。不接受边上的输入。 +block.armored-conveyor.description = 将物品向前输送。不接受两侧的非传送带输入。 block.illuminator.description = 释放光源。 block.message.description = 保存一条文字信息。用于队友之间进行交流。 block.graphite-press.description = 将煤炭压缩为石墨。 @@ -1335,11 +1412,11 @@ block.multi-press.description = 将煤炭压缩为石墨。需要水进行冷却 block.silicon-smelter.description = 将沙和煤炭精炼为硅。 block.kiln.description = 将沙和铅熔炼为钢化玻璃。 block.plastanium-compressor.description = 用石油和钛生产塑钢。 -block.phase-weaver.description = 从钍和沙合成相位物。 +block.phase-weaver.description = 用钍和沙合成相织物。 block.alloy-smelter.description = 将钛、铅、硅和铜熔合成巨浪合金。 block.cryofluid-mixer.description = 将水和细钛粉混合制成冷冻液。 -block.blast-mixer.description = 从硫化物和孢子荚中产生爆炸化合物。 -block.pyratite-mixer.description = 把煤、铅和沙子混和为硫化物。 +block.blast-mixer.description = 把火石和孢子荚混合为爆炸混合物。 +block.pyratite-mixer.description = 把煤、铅和沙子混合为火石。 block.melter.description = 将废料熔化成矿渣。 block.separator.description = 将矿渣分离成矿物成分。 block.spore-press.description = 将孢子荚压缩成石油。 @@ -1362,18 +1439,18 @@ block.thorium-wall.description = 保护己方结构,挡下敌方炮弹。 block.thorium-wall-large.description = 保护己方结构,挡下敌方炮弹。 block.phase-wall.description = 保护己方结构,挡下敌方炮弹。在受攻击时反射大多数子弹。 block.phase-wall-large.description = 保护己方结构,挡下敌方炮弹。在受攻击时反射大多数子弹。 -block.surge-wall.description = 保护己方结构,挡下敌方炮弹。受攻击时定期释放电弧。 -block.surge-wall-large.description = 保护己方结构,挡下敌方炮弹。受攻击时定期释放电弧。 +block.surge-wall.description = 保护己方结构,挡下敌方炮弹。受攻击时有几率释放电弧。 +block.surge-wall-large.description = 保护己方结构,挡下敌方炮弹。受攻击时有几率释放电弧。 block.door.description = 可以开关的墙。 block.door-large.description = 可以开关的墙。 block.mender.description = 定期修复附近的区块。\n可使用硅来提高范围和效率。 -block.mend-projector.description = 修复其附近的区块。\n可使用相位物来提高射程和效率。 -block.overdrive-projector.description = 提高附近建筑物的速度。\n可使用相位物来提高射程和效率。 -block.force-projector.description = 在自身周围创建一个六角形力场,使里面的建筑物和单位免受伤害。\n持续承受高伤害会导致过热,可以使用冷却液降温。相位物可用于增加护盾大小。 +block.mend-projector.description = 修复其附近的区块。\n可使用相织物来提高范围和效率。 +block.overdrive-projector.description = 提高附近建筑物的速度。\n可使用相织物来提高范围和效率。 +block.force-projector.description = 在自身周围创建一个六角形力场,使里面的建筑物和单位免受伤害。\n持续承受高伤害会导致过热,可以使用冷却液降温。相织物可用于增加护盾大小和盾容。 block.shock-mine.description = 对踩到它的敌人释放电弧进行攻击。 block.conveyor.description = 将物品向前输送。 block.titanium-conveyor.description = 将物品向前输送。快于初级传送带。 -block.plastanium-conveyor.description = 打包物品进行运输。\n在后方输入物品,在前方三个方向输出物品。需要多个装载和卸载点才能达到峰值载量。 +block.plastanium-conveyor.description = 打包物品进行运输。\n在后方输入物品,在前方三个方向输出物品。需要多个装载和卸载点才能达到最大运载量。 block.junction.description = 两条交叉传送带的桥梁。 block.bridge-conveyor.description = 跨越任意地形或建筑物运输物品。 block.phase-conveyor.description = 跨越任意地形或建筑物即时运输物品。比传送带桥范围更大,但需要电力。 @@ -1384,7 +1461,7 @@ block.router.details = 这是个好东西,也可以带来麻烦。不建议在 block.distributor.description = 将物品平均分配到其他7个方向。 block.overflow-gate.description = 当前方被阻塞时才会向左和右输出,用于处理多余的物品。 block.underflow-gate.description = 与溢流门相反。 当左右均堵塞时才向前方运输。 -block.mass-driver.description = 长距离物品传输结构,收集若干物品后将其射到远处的另一个质量驱动器。 +block.mass-driver.description = 长距离物品传输建筑,收集若干物品后将其射到远处的另一个质量驱动器。 block.mechanical-pump.description = 泵送液体,不需要能量。 block.rotary-pump.description = 泵送液体,需要能量。 block.thermal-pump.description = 泵送液体。 @@ -1405,7 +1482,7 @@ block.battery-large.description = 储存电网多余电力,并在电网供电 block.combustion-generator.description = 燃烧煤等可燃材料发电。 block.thermal-generator.description = 放置在炽热的地形上能够发电。 block.steam-generator.description = 通过燃烧易燃材料并将水转化为蒸汽来发电。 -block.differential-generator.description = 利用低温流体与燃烧的硫之间的温差产生大量能量。 +block.differential-generator.description = 利用低温流体与燃烧的火石之间的温差产生大量能量。 block.rtg-generator.description = 利用放射物的衰变产生的热量以缓慢的速度产生能量。 block.solar-panel.description = 提供少量太阳能。 block.solar-panel-large.description = 提供少量太阳能。比标准太阳能电池板更高效。 @@ -1431,7 +1508,7 @@ block.unloader.description = 从周围方块卸载指定物品。 block.launch-pad.description = 将货物发射至指定区块。 block.duo.description = 交替向敌人发射子弹。 block.scatter.description = 向敌机发射铅、废料或钢化玻璃高射炮弹。 -block.scorch.description = 焚烧任何靠近它的地面敌人。近距离高效 +block.scorch.description = 焚烧任何靠近它的地面敌人。近距离高效。 block.hail.description = 向远距离地面敌人发射小型炮弹。 block.wave.description = 向敌人射出液体流。使用水作弹药时能够自动灭火。 block.lancer.description = 充能并向地面单位发射强力的的波束。 @@ -1448,11 +1525,11 @@ block.repair-point.description = 持续修复其附近受损最严重的单位 block.segment.description = 摧毁袭来的除激光以外的子弹或导弹。 block.parallax.description = 通过牵引光束牵引空中目标,并在这个过程中对其造成伤害。 block.tsunami.description = 向敌人射出强力的液体流。使用水作弹药时能够自动灭火。 -block.silicon-crucible.description = 从沙子和煤中提炼硅,用硫化物作为附加热源。在炙热地型上更高效。 +block.silicon-crucible.description = 从沙子和煤中提炼硅,用火石作为附加热源。在炙热地型上更高效。 block.disassembler.description = 以低效率将矿渣分离成微量的外来矿物成分。能产生钍。 -block.overdrive-dome.description = 提高附近建筑物的速度。需要相位物和硅来工作。 -block.payload-conveyor.description = 移动大型有效载荷,例如从工厂生产的单位。 -block.payload-router.description = 将输入的有效载荷向3个方向输出。 +block.overdrive-dome.description = 提高附近建筑物的速度。需要相织物和硅来工作。 +block.payload-conveyor.description = 移动大型载荷,例如从工厂生产的单位。 +block.payload-router.description = 将输入的载荷向3个方向输出。 block.command-center.description = 使用多个不同的命令控制单位。 block.ground-factory.description = 产生陆军单位。输出的单位可以直接使用,也可以移入重构厂进行升级。 block.air-factory.description = 产生空军单位。输出的单位可以直接使用,也可以移入重构厂进行升级。 @@ -1469,41 +1546,48 @@ block.memory-cell.description = 存储处理器的信息。 block.memory-bank.description = 存储处理器的信息。内存量更大。 block.logic-display.description = 显示处理器中的任意图形。 block.large-logic-display.description = 显示处理器中的任意图形。 -block.interplanetary-accelerator.description = 一个巨大的电磁轨道加速器。加速核心逃逸速度以进行星际部署。 +block.interplanetary-accelerator.description = 一个巨大的电磁轨道加速器。加速核心至逃逸速度以进行星际部署。 +block.repair-turret.description = 持续修复其范围内最近的受损单位。可使用液体冷却以提高修复效率。 +block.payload-propulsion-tower.description = 长距离载荷运输建筑。向与其相链接的其它载荷驱动台发射载荷。 -unit.dagger.description = 攻击附近所有敌人。发射标准子弹。 -unit.mace.description = 攻击附近所有敌人。发射火焰。 -unit.fortress.description = 攻击地面敌人。发射远程火炮。 -unit.scepter.description = 攻击附近所有敌人。发射充能弹。 -unit.reign.description = 攻击附近所有敌人。发射穿透性子弹。 -unit.nova.description = 发射激光弹来攻击敌人并修复盟军建筑。能够飞行。 -unit.pulsar.description = 发射电弧来攻击敌人并修复盟军建筑。能够飞行。 -unit.quasar.description = 发射穿透性激光束来攻击敌人并修复盟军建筑。能够飞行。拥有护盾。 -unit.vela.description = 发射巨大的持续激光束攻击敌人,引起火灾并修复盟军建筑。能够飞行。 -unit.corvus.description = 发射巨大的激光爆破束,摧毁敌人并修复盟军建筑。可以跨越大多数地形。 +unit.dagger.description = 向附近所有敌人发射标准子弹。 +unit.mace.description = 向附近所有敌人喷射火焰。 +unit.fortress.description = 向附近所有地面敌人发射远程火炮。 +unit.scepter.description = 向附近所有敌人发射一串电荷弹。 +unit.reign.description = 向附近所有敌人发射巨型穿甲弹。 +unit.nova.description = 发射激光弹攻击敌人并修复友方建筑。能够飞行。 +unit.pulsar.description = 发射数条电弧攻击敌人并修复友方建筑。能够飞行。 +unit.quasar.description = 发射穿透性激光束攻击敌人并修复友方建筑。能够飞行。拥有护盾。 +unit.vela.description = 发射巨型持续激光束攻击敌人,点燃敌人并修复友方建筑。能够飞行。 +unit.corvus.description = 发射巨型爆破激光束攻击敌人并修复友方建筑。可以跨越大多数地形。 unit.crawler.description = 冲向敌人并自毁,造成大爆炸。 -unit.atrax.description = 向地面目标发射削弱性的矿渣球体。可以跨越大多数地形。 +unit.atrax.description = 向地面敌人发射削弱性矿渣球。可以跨越大多数地形。 unit.spiroct.description = 向敌人发射激光束,并在此过程中自我修复。可以跨越大多数地形。 -unit.arkyid.description = 向敌人发射大量激光束,并在此过程中自我修复。可以跨越大多数地形。 -unit.toxopid.description = 向敌人发射大型电能集束炮弹和穿透激光。可以跨越大多数地形。 -unit.flare.description = 攻击地面敌人。发射标准子弹。 -unit.horizon.description = 攻击地面敌人。投下炸弹。 -unit.zenith.description = 攻击附近所有敌人。发射导弹群。 -unit.antumbra.description = 攻击附近所有敌人。发射密集的子弹。 -unit.eclipse.description = 攻击附近所有敌人。发射穿透性激光和分裂弹。 +unit.arkyid.description = 向敌人发射大型激光束,并在此过程中自我修复。可以跨越大多数地形。 +unit.toxopid.description = 向敌人发射大型电能集束炮弹和穿透性激光。可以跨越大多数地形。 +unit.flare.description = 向附近所有地面敌人发射标准子弹。 +unit.horizon.description = 向地面敌人投下炸弹簇。 +unit.zenith.description = 向附近所有敌人发射导弹群。 +unit.antumbra.description = 向附近所有敌人发射弹幕。 +unit.eclipse.description = 向附近所有敌人发射两道穿透性激光和一连串子弹。 unit.mono.description = 自动开采铜和铅,并将其放入核心中。 -unit.poly.description = 自动重建受损结构,协助其他单位建造。 +unit.poly.description = 自动重建被摧毁的建筑并协助其他单位建造。 unit.mega.description = 自动修复受损结构。能够携带方块和小型地面部队。 -unit.quad.description = 向地面目标投掷大型炸弹,修复盟军建筑并摧毁敌人。能够携带中型地面部队。 -unit.oct.description = 用它的再生护盾保护附近的盟友。能够携带大多数地面部队。 -unit.risso.description = 攻击附近所有敌人。发射一连串的导弹和子弹。 -unit.minke.description = 攻击附近所有敌人。发射炮弹和标准子弹。 -unit.bryde.description = 攻击附近所有敌人。发射发射远程炮弹和导弹。 -unit.sei.description = 攻击附近所有敌人。发射一连串的导弹和穿甲弹。 -unit.omura.description = 攻击附近所有敌人。发射远程穿透轨道炮。可构造星耀单元。 -unit.alpha.description = 保护初代核心。可构建结构。 -unit.beta.description = 保护次代核心。可构建结构。 -unit.gamma.description = 保护终代核心。可构建结构。 +unit.quad.description = 向地面敌人投掷大型炸弹,修复友方建筑并攻击敌人。能够携带中型地面部队。 +unit.oct.description = 用它的再生护盾保护附近的友方单位。能够携带大多数地面部队。 +unit.risso.description = 向附近所有敌人发射一连串的导弹和子弹。 +unit.minke.description = 向附近所有敌人发射炮弹和标准子弹。 +unit.bryde.description = 向附近所有敌人发射远程炮弹和导弹。 +unit.sei.description = 向附近所有敌人发射一连串的导弹和穿甲弹。 +unit.omura.description = 向附近所有敌人发射远程穿透轨道炮。构造星辉单位。 +unit.alpha.description = 保护初代核心。可建造建筑。 +unit.beta.description = 保护次代核心。可建造建筑。 +unit.gamma.description = 保护终代核心。可建造建筑。 +unit.retusa.description = 在附近放置水雷并修复友方建筑。 +unit.oxynoe.description = 向附近所有敌人喷射火焰并修复友方建筑。使用点防御摧毁附近的敌方射弹。 +unit.cyerce.description = 向附近所有敌人发射跟踪集束导弹并修复友方建筑。 +unit.aegires.description = 电击一切在它能量场范围内的敌方单位和建筑并修复所有友方单位和建筑。 +unit.navanax.description = 发射电磁脉冲爆弹,破坏敌方电网并修复友方建筑。使用四门自动激光炮塔融化附近所有敌人。 lst.read = 从连接的内存读取数字 lst.write = 写入数字到连接的内存 @@ -1518,6 +1602,8 @@ lst.sensor = 从建筑或单位取得数据 lst.set = 设置变量 lst.operation = 操作一两个变量 lst.end = 跳至指令栈顶\n(第一条语句) +lst.wait = 等待指定的秒数。 +lst.lookup = 通过ID寻找特定的物品/液体/单位/块的类型。\n查找每个类型的总数量可以使用:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] lst.jump = 有条件地跳到另一语句 lst.unitbind = 绑定下一个某型号单位\n并存到[accent]@unit[] lst.unitcontrol = 控制绑定的单位 @@ -1537,6 +1623,7 @@ laccess.controller = 单位控制者\n如果是处理器,返回处理器\n如 laccess.dead = 单位或建筑是不是死了或无效了 laccess.controlled = 若单位控制者是处理器,返回[accent]@ctrlProcessor[]\n若单位/建筑由玩家控制,返回[accent]@ctrlPlayer[]\n若单位在编队中,返回[accent]@ctrlFormation[]\n其他的,返回0 laccess.commanded = [red]已弃用,将被移除![]\n应该使用[accent]controlled[] +laccess.progress = 动作进度, 范围0~1。\n返回方块生产、炮塔装填或建造的进度。 graphicstype.clear = 用指定颜色填满显示屏 graphicstype.color = 设置后续画图操作的颜色 @@ -1568,9 +1655,16 @@ lenum.min = 取小的那个数 lenum.max = 取大的那个数 lenum.angle = 方位角° lenum.len = 原点到该点距离 + lenum.sin = 正弦°(对边:斜边) lenum.cos = 余弦°(邻边:斜边) lenum.tan = 正切°(对边:邻边) + +lenum.asin = 反正弦 +lenum.acos = 反余弦 +lenum.atan = 反正切 + +#not a typo, look up 'range notation' lenum.rand = [0, 值) 范围内随机数 lenum.log = 自然对数(ln) lenum.log10 = 10底对数 diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index a77a616d24..de77a25028 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -1097,7 +1097,7 @@ block.cliff.name = 峭壁 block.sand-boulder.name = 沙礫巨岩 block.basalt-boulder.name = 玄武岩巨石 block.grass.name = 草 -block.slag.name = 熔渣 +block.molten-slag.name = 熔渣 block.space.name = 太空 block.salt.name = 鹽 block.salt-wall.name = 鹽牆 @@ -1128,8 +1128,8 @@ block.spawn.name = 敵人生成 block.core-shard.name = 核心:碎片 block.core-foundation.name = 核心:基地 block.core-nucleus.name = 核心:核子 -block.deepwater.name = 深水 -block.water.name = 水 +block.deep-water.name = 深水 +block.shallow-water.name = 水 block.tainted-water.name = 污水 block.darksand-tainted-water.name = 黑沙污水 block.tar.name = 焦油 @@ -1138,7 +1138,7 @@ block.sand.name = 沙 block.darksand.name = 黑沙 block.ice.name = 冰 block.snow.name = 雪 -block.craters.name = 彈坑 +block.crater-stone.name = 彈坑 block.sand-water.name = 沙水 block.darksand-water.name = 黑沙水 block.char.name = 燒焦 diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties index 42b5d4a1df..88b2e7d939 100755 --- a/core/assets/icons/icons.properties +++ b/core/assets/icons/icons.properties @@ -334,34 +334,12 @@ 63399=blasted|status-blasted-ui 63398=corroded|status-corroded-ui 63397=disarmed|status-disarmed-ui -63396=rhyolite|block-rhyolite-ui -63395=rhyolite-crater|block-rhyolite-crater-ui -63394=regolith|block-regolith-ui -63393=yellow-stone|block-yellow-stone-ui -63392=redmat|block-redmat-ui -63391=bluemat|block-bluemat-ui -63390=beryl-wall|block-beryl-wall-ui -63389=redweed|block-redweed-ui -63388=pur-bush|block-pur-bush-ui -63387=yellowcoral|block-yellowcoral-ui -63386=coralchunk|block-coralchunk-ui 63385=duct|block-duct-ui -63384=beam-drill|block-beam-drill-ui -63383=beryllium|item-beryllium-ui -63382=fissile-matter|item-fissile-matter-ui -63381=neoplasm|liquid-neoplasm-ui -63380=cell-synthesis-chamber|block-cell-synthesis-chamber-ui -63379=nuclear-warhead|block-nuclear-warhead-ui -63378=warhead-assembler|block-warhead-assembler-ui -63377=ballistic-silo|block-ballistic-silo-ui 63376=repair-turret|block-repair-turret-ui 63375=payload-propulsion-tower|block-payload-propulsion-tower-ui 63374=payload-incinerator|block-payload-incinerator-ui 63373=payload-void|block-payload-void-ui 63372=payload-source|block-payload-source-ui -63371=regolith-wall|block-regolith-wall-ui -63370=rhyolite-wall|block-rhyolite-wall-ui -63369=yellow-stone-wall|block-yellow-stone-wall-ui 63368=retusa|unit-retusa-ui 63367=directional-item-bridge|block-directional-item-bridge-ui 63366=duct-router|block-duct-router-ui @@ -371,31 +349,14 @@ 63362=aegires|unit-aegires-ui 63361=electrified|status-electrified-ui 63360=navanax|unit-navanax-ui -63359=wall-ore-beryllium|block-wall-ore-beryllium-ui -63358=graphitic-stone|block-graphitic-stone-ui -63357=graphitic-wall|block-graphitic-wall-ui -63356=carbon-wall|block-carbon-wall-ui -63355=silicon-arc-smelter|block-silicon-arc-smelter-ui 63354=payload-launch-pad|block-payload-launch-pad-ui 63353=silicon-arc-furnace|block-silicon-arc-furnace-ui 63352=metal-floor-4|block-metal-floor-4-ui -63351=redice|block-redice-ui -63350=red-ice|block-red-ice-ui -63349=red-ice-wall|block-red-ice-wall-ui -63348=ferrous|block-ferrous-ui -63347=ferric-stone|block-ferric-stone-ui -63346=ferric-stone-wall|block-ferric-stone-wall-ui -63345=ferric-craters|block-ferric-craters-ui -63344=ferric-boulder|block-ferric-boulder-ui -63343=beryllic-stone|block-beryllic-stone-ui -63342=beryllic-stone-wall|block-beryllic-stone-wall-ui -63341=beryllic-boulder|block-beryllic-boulder-ui -63340=carbon-boulder|block-carbon-boulder-ui -63339=carbon-stone|block-carbon-stone-ui -63338=payload-deconstructor|block-payload-deconstructor-ui -63337=cliff-crusher|block-cliff-crusher-ui -63336=deconstructor|block-deconstructor-ui -63335=constructor|block-constructor-ui -63334=large-constructor|block-large-constructor-ui -63333=payload-loader|block-payload-loader-ui -63332=payload-unloader|block-payload-unloader-ui +63351=invincible|status-invincible-ui +63356=sharded|team-sharded +63357=crux|team-crux +63358=derelict|team-derelict +63350=deep-water|block-deep-water-ui +63349=shallow-water|block-shallow-water-ui +63348=molten-slag|block-molten-slag-ui +63347=crater-stone|block-crater-stone-ui diff --git a/core/assets/logicids.dat b/core/assets/logicids.dat index 291a134435..07a91ab487 100644 Binary files a/core/assets/logicids.dat and b/core/assets/logicids.dat differ diff --git a/core/assets/maps/extractionOutpost.msav b/core/assets/maps/extractionOutpost.msav index 7ce6a6904e..288046fd92 100644 Binary files a/core/assets/maps/extractionOutpost.msav and b/core/assets/maps/extractionOutpost.msav differ diff --git a/core/assets/scripts/global.js b/core/assets/scripts/global.js index bb17455eac..37b756544e 100755 --- a/core/assets/scripts/global.js +++ b/core/assets/scripts/global.js @@ -90,7 +90,6 @@ importPackage(Packages.mindustry.editor) importPackage(Packages.mindustry.entities) importPackage(Packages.mindustry.entities.abilities) importPackage(Packages.mindustry.entities.bullet) -importPackage(Packages.mindustry.entities.comp) importPackage(Packages.mindustry.entities.effect) importPackage(Packages.mindustry.entities.units) importPackage(Packages.mindustry.game) @@ -107,6 +106,7 @@ importPackage(Packages.mindustry.maps.planet) importPackage(Packages.mindustry.net) importPackage(Packages.mindustry.service) importPackage(Packages.mindustry.type) +importPackage(Packages.mindustry.type.ammo) importPackage(Packages.mindustry.type.weapons) importPackage(Packages.mindustry.type.weather) importPackage(Packages.mindustry.ui) @@ -156,6 +156,7 @@ const ResearchEvent = Packages.mindustry.game.EventType.ResearchEvent const UnlockEvent = Packages.mindustry.game.EventType.UnlockEvent const StateChangeEvent = Packages.mindustry.game.EventType.StateChangeEvent const CoreChangeEvent = Packages.mindustry.game.EventType.CoreChangeEvent +const BuildTeamChangeEvent = Packages.mindustry.game.EventType.BuildTeamChangeEvent const TileChangeEvent = Packages.mindustry.game.EventType.TileChangeEvent const TilePreChangeEvent = Packages.mindustry.game.EventType.TilePreChangeEvent const GameOverEvent = Packages.mindustry.game.EventType.GameOverEvent diff --git a/core/assets/sprites/clouds.png b/core/assets/sprites/clouds.png index 93a8684689..adcf7a97db 100644 Binary files a/core/assets/sprites/clouds.png and b/core/assets/sprites/clouds.png differ diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index 224f8ec96e..04adcb30ca 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -103,8 +103,8 @@ public class Vars implements Loadable{ public static final float invasionGracePeriod = 20; /** min armor fraction damage; e.g. 0.05 = at least 5% damage */ public static final float minArmorDamage = 0.1f; - /** launch animation duration */ - public static final float launchDuration = 140f; + /** land/launch animation duration */ + public static final float coreLandDuration = 160f; /** size of tiles in units */ public static final int tilesize = 8; /** size of one tile payload (^2) */ @@ -142,8 +142,8 @@ public class Vars implements Loadable{ public static boolean clientLoaded = false; /** max GL texture size */ public static int maxTextureSize = 2048; - /** Whether to show the core landing animation. */ - public static boolean showLandAnimation = true; + /** Whether to show sector info upon landing. */ + public static boolean showSectorLandInfo = true; /** Whether to check for memory use before taking screenshots. */ public static boolean checkScreenshotMemory = true; /** Whether to prompt the user to confirm exiting. */ diff --git a/core/src/mindustry/ai/BlockIndexer.java b/core/src/mindustry/ai/BlockIndexer.java index aae2ca6467..f91aa89e11 100644 --- a/core/src/mindustry/ai/BlockIndexer.java +++ b/core/src/mindustry/ai/BlockIndexer.java @@ -13,7 +13,6 @@ import mindustry.game.Teams.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; -import mindustry.world.blocks.*; import mindustry.world.meta.*; import java.util.*; @@ -32,7 +31,7 @@ public class BlockIndexer{ /** Stores all ore quadrants on the map. Maps ID to qX to qY to a list of tiles with that ore. */ private IntSeq[][][] ores; /** Stores all damaged tile entities by team. */ - private ObjectSet[] damagedTiles = new ObjectSet[Team.all.length]; + private Seq[] damagedTiles = new Seq[Team.all.length]; /** All ores available on this map. */ private ObjectSet allOres = new ObjectSet<>(); /** Stores teams that are present here as tiles. */ @@ -59,7 +58,7 @@ public class BlockIndexer{ }); Events.on(WorldLoadEvent.class, event -> { - damagedTiles = new ObjectSet[Team.all.length]; + damagedTiles = new Seq[Team.all.length]; flagMap = new TileArray[Team.all.length][BlockFlag.all.length]; activeTeams = new Seq<>(Team.class); @@ -74,10 +73,6 @@ public class BlockIndexer{ for(Tile tile : world.tiles){ process(tile); - if(tile.build != null && tile.build.damaged()){ - notifyTileDamaged(tile.build); - } - var drop = tile.drop(); if(drop != null){ @@ -104,6 +99,7 @@ public class BlockIndexer{ public void removeIndex(Tile tile){ var team = tile.team(); if(tile.build != null && tile.isCenter()){ + var build = tile.build; var flags = tile.block().flags; var data = team.data(); @@ -118,7 +114,15 @@ public class BlockIndexer{ //unregister building from building quadtree if(data.buildings != null){ - data.buildings.remove(tile.build); + data.buildings.remove(build); + } + + //is no longer registered + build.wasDamaged = false; + + //unregister damaged buildings + if(build.damaged() && damagedTiles[team.id] != null){ + damagedTiles[team.id].remove(build); } } } @@ -175,25 +179,12 @@ public class BlockIndexer{ } /** Returns all damaged tiles by team. */ - public ObjectSet getDamaged(Team team){ - breturnArray.clear(); - + public Seq getDamaged(Team team){ if(damagedTiles[team.id] == null){ - damagedTiles[team.id] = new ObjectSet<>(); + return damagedTiles[team.id] = new Seq<>(false); } - ObjectSet set = damagedTiles[team.id]; - for(Building build : set){ - if((!build.isValid() || build.team != team || !build.damaged()) || build.block instanceof ConstructBlock){ - breturnArray.add(build); - } - } - - for(Building tile : breturnArray){ - set.remove(tile); - } - - return set; + return damagedTiles[team.id]; } /** Get all allied blocks with a flag. */ @@ -271,12 +262,22 @@ public class BlockIndexer{ return returnArray; } - public void notifyTileDamaged(Building entity){ - if(damagedTiles[entity.team.id] == null){ - damagedTiles[entity.team.id] = new ObjectSet<>(); + public void notifyBuildHealed(Building build){ + if(build.wasDamaged && !build.damaged() && damagedTiles[build.team.id] != null){ + damagedTiles[build.team.id].remove(build); + build.wasDamaged = false; + } + } + + public void notifyBuildDamaged(Building build){ + if(build.wasDamaged || !build.damaged()) return; + + if(damagedTiles[build.team.id] == null){ + damagedTiles[build.team.id] = new Seq<>(false); } - damagedTiles[entity.team.id].add(entity); + damagedTiles[build.team.id].add(build); + build.wasDamaged = true; } public void allBuildings(float x, float y, float range, Cons cons){ @@ -306,7 +307,7 @@ public class BlockIndexer{ for(int i = 0; i < activeTeams.size; i++){ Team enemy = activeTeams.items[i]; - if(enemy == team || (team == Team.derelict && !state.rules.coreCapture)) continue; + if(enemy == team || (enemy == Team.derelict && !state.rules.coreCapture)) continue; Building candidate = indexer.findTile(enemy, x, y, range, pred, true); if(candidate == null) continue; @@ -417,6 +418,8 @@ public class BlockIndexer{ data.buildings = new QuadTree<>(new Rect(0, 0, world.unitWidth(), world.unitHeight())); } data.buildings.insert(tile.build); + + notifyBuildDamaged(tile.build); } if(!tile.block().isStatic()){ diff --git a/core/src/mindustry/ai/formations/Formation.java b/core/src/mindustry/ai/formations/Formation.java index db2ce02e14..cbbb02a541 100644 --- a/core/src/mindustry/ai/formations/Formation.java +++ b/core/src/mindustry/ai/formations/Formation.java @@ -175,16 +175,6 @@ public class Formation{ return -1; } - // debug - public SlotAssignment getSlotAssignmentAt(int index){ - return slotAssignments.get(index); - } - - // debug - public int getSlotAssignmentCount(){ - return slotAssignments.size; - } - /** Writes new slot locations to each member */ public void updateSlots(){ positionOffset.set(anchor); diff --git a/core/src/mindustry/ai/types/FlyingAI.java b/core/src/mindustry/ai/types/FlyingAI.java index b3e35a21d1..db5ae84dab 100644 --- a/core/src/mindustry/ai/types/FlyingAI.java +++ b/core/src/mindustry/ai/types/FlyingAI.java @@ -33,16 +33,31 @@ public class FlyingAI extends AIController{ @Override protected Teamc findTarget(float x, float y, float range, boolean air, boolean ground){ - Teamc result = target(x, y, range, air, ground); - if(result != null) return result; + var result = findMainTarget(x, y, range, air, ground); - if(ground) result = targetFlag(x, y, BlockFlag.generator, true); - if(result != null) return result; + //if the main target is in range, use it, otherwise target whatever is closest + return checkTarget(result, x, y, range) ? target(x, y, range, air, ground) : result; + } - if(ground) result = targetFlag(x, y, BlockFlag.core, true); - if(result != null) return result; + @Override + protected Teamc findMainTarget(float x, float y, float range, boolean air, boolean ground){ + var core = targetFlag(x, y, BlockFlag.core, true); - return null; + if(core != null && Mathf.within(x, y, core.getX(), core.getY(), range)){ + return core; + } + + for(var flag : unit.team.isAI() ? unit.type.targetFlags : unit.type.playerTargetFlags){ + if(flag == null){ + Teamc result = target(x, y, range, air, ground); + if(result != null) return result; + }else if(ground){ + Teamc result = targetFlag(x, y, flag, true); + if(result != null) return result; + } + } + + return core; } protected void attack(float circleLength){ diff --git a/core/src/mindustry/ai/types/LogicAI.java b/core/src/mindustry/ai/types/LogicAI.java index 193e5aaf48..d33d5ad372 100644 --- a/core/src/mindustry/ai/types/LogicAI.java +++ b/core/src/mindustry/ai/types/LogicAI.java @@ -102,7 +102,7 @@ public class LogicAI extends AIController{ } //look where moving if there's nothing to aim at - if(!shoot){ + if(!shoot || !unit.type.omniMovement){ unit.lookAt(unit.prefRotation()); }else if(unit.hasWeapons() && unit.mounts.length > 0 && !unit.mounts[0].weapon.ignoreRotation){ //if there is, look at the object unit.lookAt(unit.mounts[0].aimX, unit.mounts[0].aimY); @@ -131,7 +131,13 @@ public class LogicAI extends AIController{ //do not move when infinite vectors are used. if(vec.isNaN() || vec.isInfinite()) return; - unit.approach(vec); + if(unit.type.omniMovement){ + unit.approach(vec); + }else{ + unit.rotateMove(vec); + } + + } @Override diff --git a/core/src/mindustry/async/AsyncCore.java b/core/src/mindustry/async/AsyncCore.java index 88272feb95..5de761d0ca 100644 --- a/core/src/mindustry/async/AsyncCore.java +++ b/core/src/mindustry/async/AsyncCore.java @@ -2,6 +2,7 @@ package mindustry.async; import arc.*; import arc.struct.*; +import arc.util.async.*; import mindustry.game.EventType.*; import java.util.concurrent.*; @@ -49,7 +50,7 @@ public class AsyncCore{ executor = Executors.newFixedThreadPool(processes.size, r -> { Thread thread = new Thread(r, "AsyncLogic-Thread"); thread.setDaemon(true); - thread.setUncaughtExceptionHandler((t, e) -> Core.app.post(() -> { throw new RuntimeException(e); })); + thread.setUncaughtExceptionHandler((t, e) -> Threads.throwAppException(e)); return thread; }); } diff --git a/core/src/mindustry/async/PhysicsProcess.java b/core/src/mindustry/async/PhysicsProcess.java index c8594a3ee2..c62281802c 100644 --- a/core/src/mindustry/async/PhysicsProcess.java +++ b/core/src/mindustry/async/PhysicsProcess.java @@ -42,10 +42,10 @@ public class PhysicsProcess implements AsyncProcess{ if(entity.physref == null){ PhysicsBody body = new PhysicsBody(); - body.x = entity.x(); - body.y = entity.y(); + body.x = entity.x; + body.y = entity.y; body.mass = entity.mass(); - body.radius = entity.hitSize() / 2f; + body.radius = entity.hitSize / 2f; PhysicRef ref = new PhysicRef(entity, body); refs.add(ref); diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 15585e6162..fd7534c3ff 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -93,7 +93,7 @@ public class Blocks implements ContentList{ commandCenter, groundFactory, airFactory, navalFactory, additiveReconstructor, multiplicativeReconstructor, exponentialReconstructor, tetrativeReconstructor, - repairPoint, repairTurret, resupplyPoint, + repairPoint, repairTurret, //payloads payloadConveyor, payloadRouter, payloadPropulsionTower, deconstructor, constructor, largeConstructor, payloadLoader, payloadUnloader, @@ -131,7 +131,7 @@ public class Blocks implements ContentList{ new ConstructBlock(i); } - deepwater = new Floor("deepwater"){{ + deepwater = new Floor("deep-water"){{ speedMultiplier = 0.2f; variants = 0; liquidDrop = Liquids.water; @@ -144,7 +144,7 @@ public class Blocks implements ContentList{ albedo = 0.5f; }}; - water = new Floor("water"){{ + water = new Floor("shallow-water"){{ speedMultiplier = 0.5f; variants = 0; status = StatusEffects.wet; @@ -198,7 +198,7 @@ public class Blocks implements ContentList{ cacheLayer = CacheLayer.tar; }}; - slag = new Floor("slag"){{ + slag = new Floor("molten-slag"){{ drownTime = 150f; status = StatusEffects.melting; statusDuration = 240f; @@ -223,7 +223,7 @@ public class Blocks implements ContentList{ stone = new Floor("stone"); - craters = new Floor("craters"){{ + craters = new Floor("crater-stone"){{ variants = 3; blendGroup = stone; }}; @@ -806,8 +806,8 @@ public class Blocks implements ContentList{ craftTime = 35f; size = 2; - consumes.power(1f); - consumes.liquid(Liquids.slag, 0.07f); + consumes.power(1.1f); + consumes.liquid(Liquids.slag, 4f / 60f); }}; disassembler = new Separator("disassembler"){{ @@ -851,7 +851,9 @@ public class Blocks implements ContentList{ craftTime = 40f; updateEffect = Fx.pulverizeSmall; hasItems = hasPower = true; - drawer = new DrawRotator(); + drawer = new DrawRotator(){{ + drawSpinSprite = true; + }}; ambientSound = Sounds.grinding; ambientSoundVolume = 0.025f; @@ -1142,15 +1144,20 @@ public class Blocks implements ContentList{ itemBridge = new BufferedItemBridge("bridge-conveyor"){{ requirements(Category.distribution, with(Items.lead, 6, Items.copper, 6)); + fadeIn = moveArrows = false; range = 4; speed = 74f; + arrowSpacing = 6f; bufferCapacity = 14; }}; phaseConveyor = new ItemBridge("phase-conveyor"){{ requirements(Category.distribution, with(Items.phaseFabric, 5, Items.silicon, 7, Items.lead, 10, Items.graphite, 10)); range = 12; + arrowPeriod = 0.9f; + arrowTimeScl = 2.75f; hasPower = true; + pulse = true; consumes.power(0.30f); }}; @@ -1217,7 +1224,7 @@ public class Blocks implements ContentList{ mechanicalPump = new Pump("mechanical-pump"){{ requirements(Category.liquid, with(Items.copper, 15, Items.metaglass, 10)); - pumpAmount = 0.11f; + pumpAmount = 7f / 60f; }}; rotaryPump = new Pump("rotary-pump"){{ @@ -1273,8 +1280,10 @@ public class Blocks implements ContentList{ requirements(Category.liquid, with(Items.graphite, 2, Items.metaglass, 2)); }}; - bridgeConduit = new LiquidExtendingBridge("bridge-conduit"){{ + bridgeConduit = new LiquidBridge("bridge-conduit"){{ requirements(Category.liquid, with(Items.graphite, 4, Items.metaglass, 8)); + fadeIn = moveArrows = false; + arrowSpacing = 6f; range = 4; hasPower = false; }}; @@ -1282,8 +1291,11 @@ public class Blocks implements ContentList{ phaseConduit = new LiquidBridge("phase-conduit"){{ requirements(Category.liquid, with(Items.phaseFabric, 5, Items.silicon, 7, Items.metaglass, 20, Items.titanium, 10)); range = 12; + arrowPeriod = 0.9f; + arrowTimeScl = 2.75f; hasPower = true; canOverdrive = false; + pulse = true; consumes.power(0.30f); }}; @@ -1463,6 +1475,7 @@ public class Blocks implements ContentList{ drillEffect = Fx.mineHuge; rotateSpeed = 6f; warmupSpeed = 0.01f; + itemCapacity = 20; //more than the laser drill liquidBoostIntensity = 1.8f; @@ -1502,14 +1515,13 @@ public class Blocks implements ContentList{ maxBoost = 2f; consumes.power(80f / 60f); - consumes.liquid(Liquids.water, 20f / 60f); + consumes.liquid(Liquids.water, 18f / 60f); }}; oilExtractor = new Fracker("oil-extractor"){{ requirements(Category.production, with(Items.copper, 150, Items.graphite, 175, Items.lead, 115, Items.thorium, 115, Items.silicon, 75)); result = Liquids.oil; updateEffect = Fx.pulverize; - liquidCapacity = 50f; updateEffectChance = 0.05f; pumpAmount = 0.25f; size = 3; @@ -1563,6 +1575,7 @@ public class Blocks implements ContentList{ health = 3500; itemCapacity = 9000; size = 4; + thrusterLength = 34/4f; unitCapModifier = 16; researchCostMultiplier = 0.07f; @@ -1575,6 +1588,7 @@ public class Blocks implements ContentList{ health = 6000; itemCapacity = 13000; size = 5; + thrusterLength = 40/4f; unitCapModifier = 24; researchCostMultiplier = 0.11f; @@ -1584,14 +1598,14 @@ public class Blocks implements ContentList{ requirements(Category.effect, with(Items.titanium, 250, Items.thorium, 125)); size = 3; itemCapacity = 1000; - health = size * size * 60; + health = size * size * 55; }}; container = new StorageBlock("container"){{ requirements(Category.effect, with(Items.titanium, 100)); size = 2; itemCapacity = 300; - health = size * size * 60; + health = size * size * 55; }}; unloader = new Unloader("unloader"){{ @@ -1788,7 +1802,7 @@ public class Blocks implements ContentList{ shots = 4; burstSpacing = 5; inaccuracy = 10f; - range = 215f; + range = 235f; xRand = 6f; size = 2; health = 300 * size * size; @@ -2029,13 +2043,13 @@ public class Blocks implements ContentList{ range = 195f; reloadTime = 90f; firingMoveFract = 0.5f; - shootDuration = 220f; + shootDuration = 230f; powerUse = 17f; shootSound = Sounds.laserbig; loopSound = Sounds.beam; loopSoundVolume = 2f; - shootType = new ContinuousLaserBulletType(70){{ + shootType = new ContinuousLaserBulletType(75){{ length = 200f; hitEffect = Fx.hitMeltdown; hitColor = Pal.meltdownHit; @@ -2200,17 +2214,6 @@ public class Blocks implements ContentList{ acceptCoolant = true; }}; - resupplyPoint = new ResupplyPoint("resupply-point"){{ - requirements(Category.units, BuildVisibility.ammoOnly, with(Items.lead, 20, Items.copper, 15, Items.silicon, 15)); - - size = 2; - range = 80f; - itemCapacity = 20; - ammoAmount = 5; - - consumes.item(Items.copper, 1); - }}; - //endregion //region payloads @@ -2229,7 +2232,7 @@ public class Blocks implements ContentList{ size = 5; reloadTime = 140f; chargeTime = 100f; - range = 500f; + range = 600f; maxPayloadSize = 3.5f; consumes.power(6f); }}; diff --git a/core/src/mindustry/content/Bullets.java b/core/src/mindustry/content/Bullets.java index 560e34f6cd..abef6c9c16 100644 --- a/core/src/mindustry/content/Bullets.java +++ b/core/src/mindustry/content/Bullets.java @@ -1,17 +1,9 @@ package mindustry.content; import arc.graphics.*; -import arc.graphics.g2d.*; -import arc.math.*; -import arc.util.*; import mindustry.ctype.*; -import mindustry.entities.*; import mindustry.entities.bullet.*; -import mindustry.gen.*; import mindustry.graphics.*; -import mindustry.world.*; - -import static mindustry.Vars.*; public class Bullets implements ContentList{ public static BulletType @@ -113,6 +105,7 @@ public class Bullets implements ContentList{ splashDamageRadius = 25f * 0.75f; splashDamage = 35f; status = StatusEffects.burning; + statusDuration = 60f * 12f; frontColor = Pal.lightishOrange; backColor = Pal.lightOrange; makeFire = true; @@ -132,7 +125,6 @@ public class Bullets implements ContentList{ frontColor = Pal.missileYellow; status = StatusEffects.blasted; - statusDuration = 60f; }}; flakGlassFrag = new BasicBulletType(3f, 5, "bullet"){{ @@ -177,7 +169,7 @@ public class Bullets implements ContentList{ width = 6f; height = 8f; hitEffect = Fx.flakExplosion; - splashDamage = 22f * 1.5f; + splashDamage = 25f * 1.5f; splashDamageRadius = 20f; fragBullet = flakGlassFrag; fragBullets = 6; @@ -342,11 +334,14 @@ public class Bullets implements ContentList{ lifetime = 60f; }}; - standardDenseBig = new BasicBulletType(7f, 55, "bullet"){{ - hitSize = 5; + standardDenseBig = new BasicBulletType(7.5f, 50, "bullet"){{ + hitSize = 4.8f; width = 15f; height = 21f; shootEffect = Fx.shootBig; + ammoMultiplier = 4; + reloadMultiplier = 1.7f; + knockback = 0.3f; }}; standardThoriumBig = new BasicBulletType(8f, 80, "bullet"){{ @@ -359,7 +354,7 @@ public class Bullets implements ContentList{ knockback = 0.7f; }}; - standardIncendiaryBig = new BasicBulletType(7f, 60, "bullet"){{ + standardIncendiaryBig = new BasicBulletType(7f, 70, "bullet"){{ hitSize = 5; width = 16f; height = 21f; @@ -370,50 +365,13 @@ public class Bullets implements ContentList{ makeFire = true; pierceCap = 2; pierceBuilding = true; - knockback = 0.7f; + knockback = 0.7f; + ammoMultiplier = 3; }}; - fireball = new BulletType(1f, 4){ - { - pierce = true; - collidesTiles = false; - collides = false; - drag = 0.03f; - hitEffect = despawnEffect = Fx.none; - } + fireball = new FireBulletType(1f, 4); - @Override - public void init(Bullet b){ - b.vel.setLength(0.6f + Mathf.random(2f)); - } - - @Override - public void draw(Bullet b){ - Draw.color(Pal.lightFlame, Pal.darkFlame, Color.gray, b.fin()); - Fill.circle(b.x, b.y, 3f * b.fout()); - Draw.reset(); - } - - @Override - public void update(Bullet b){ - if(Mathf.chance(0.04 * Time.delta)){ - Tile tile = world.tileWorld(b.x, b.y); - if(tile != null){ - Fires.create(tile); - } - } - - if(Mathf.chance(0.1 * Time.delta)){ - Fx.fireballsmoke.at(b.x, b.y); - } - - if(Mathf.chance(0.1 * Time.delta)){ - Fx.ballfire.at(b.x, b.y); - } - } - }; - - basicFlame = new BulletType(3.35f, 16f){{ + basicFlame = new BulletType(3.35f, 17f){{ ammoMultiplier = 3f; hitSize = 7f; lifetime = 18f; @@ -428,13 +386,13 @@ public class Bullets implements ContentList{ hittable = false; }}; - pyraFlame = new BulletType(3.35f, 25f){{ - ammoMultiplier = 4f; + pyraFlame = new BulletType(4f, 50f){{ + ammoMultiplier = 6f; hitSize = 7f; lifetime = 18f; pierce = true; collidesAir = false; - statusDuration = 60f * 6; + statusDuration = 60f * 10; shootEffect = Fx.shootPyraFlame; hitEffect = Fx.hitFlameSmall; despawnEffect = Fx.none; diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index 2f3a3dda82..f8564761b1 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -130,7 +130,7 @@ public class Fx{ Fill.circle(x, y, e.fslope() * 1.5f * size); }), - pointBeam = new Effect(25f, e -> { + pointBeam = new Effect(25f, 300f, e -> { if(!(e.data instanceof Position)) return; Position pos = e.data(); @@ -184,6 +184,16 @@ public class Fx{ Lines.square(e.x, e.y, tilesize / 2f * e.rotation + e.fin() * 3f); }), + coreLaunchConstruct = new Effect(35, e -> { + color(Pal.accent); + stroke(4f - e.fin() * 3f); + Lines.square(e.x, e.y, tilesize / 2f * e.rotation * 1.2f + e.fin() * 5f); + + randLenVectors(e.id, 5 + (int)(e.rotation * 5), e.rotation * 3f + (tilesize * e.rotation) * e.finpow() * 1.5f, (x, y) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * (4f + e.rotation)); + }); + }), + tapBlock = new Effect(12, e -> { color(Pal.accent); stroke(3f - e.fin() * 2f); @@ -1628,7 +1638,7 @@ public class Fx{ coalSmeltsmoke = new Effect(40f, e -> { randLenVectors(e.id, 0.2f + e.fin(), 4, 6.3f, (x, y, fin, out) -> { color(Color.darkGray, Pal.coalBlack, e.finpowdown()); - Fill.circle(e.x + x, e.y + y, out * 2f + 0.25f); + Fill.circle(e.x + x, e.y + y, out * 2f + 0.35f); }); }), @@ -1869,6 +1879,13 @@ public class Fx{ Lines.poly(e.x, e.y, 6, e.rotation + e.fin()); }), + coreLandDust = new Effect(100f, e -> { + color(e.color, e.fout(0.1f)); + rand.setSeed(e.id); + Tmp.v1.trns(e.rotation, e.finpow() * 90f * rand.random(0.2f, 1f)); + Fill.circle(e.x + Tmp.v1.x, e.y + Tmp.v1.y, 8f * rand.random(0.6f, 1f) * e.fout(0.2f)); + }).layer(Layer.block + 1f), + unitShieldBreak = new Effect(35, e -> { if(!(e.data instanceof Unitc)) return; @@ -1962,8 +1979,5 @@ public class Fx{ } Lines.endLine(); - }).followParent(false), - - coreLand = new Effect(120f, e -> { - }); + }).followParent(false); } diff --git a/core/src/mindustry/content/Planets.java b/core/src/mindustry/content/Planets.java index f3f13b4804..e17c5b6e63 100644 --- a/core/src/mindustry/content/Planets.java +++ b/core/src/mindustry/content/Planets.java @@ -7,6 +7,7 @@ import arc.math.geom.*; import arc.struct.*; import arc.util.*; import mindustry.ctype.*; +import mindustry.graphics.*; import mindustry.graphics.g3d.*; import mindustry.graphics.g3d.PlanetGrid.*; import mindustry.maps.planet.*; @@ -85,6 +86,7 @@ public class Planets implements ContentList{ atmosphereRadOut = 0.3f; startSector = 15; alwaysUnlocked = true; + landCloudColor = Pal.spore.cpy().a(0.5f); }}; makeAsteroid("verlius", sun, Blocks.stoneWall, Blocks.iceWall, 0.5f, 12, 2f, gen -> { diff --git a/core/src/mindustry/content/StatusEffects.java b/core/src/mindustry/content/StatusEffects.java index fb75fcabd3..793c5e3e42 100644 --- a/core/src/mindustry/content/StatusEffects.java +++ b/core/src/mindustry/content/StatusEffects.java @@ -69,12 +69,12 @@ public class StatusEffects implements ContentList{ transitionDamage = 14; init(() -> { - affinity(shocked, ((unit, result, time) -> { + affinity(shocked, (unit, result, time) -> { unit.damagePierce(transitionDamage); if(unit.team == state.rules.waveTeam){ Events.fire(Trigger.shock); } - })); + }); opposite(burning, melting); }); }}; @@ -96,11 +96,11 @@ public class StatusEffects implements ContentList{ init(() -> { opposite(wet, freezing); - affinity(tarred, ((unit, result, time) -> { + affinity(tarred, (unit, result, time) -> { unit.damagePierce(8f); Fx.burning.at(unit.x + Mathf.range(unit.bounds() / 2f), unit.y + Mathf.range(unit.bounds() / 2f)); result.set(melting, Math.min(time + result.time, 200f)); - })); + }); }); }}; @@ -133,8 +133,8 @@ public class StatusEffects implements ContentList{ effect = Fx.oily; init(() -> { - affinity(melting, ((unit, result, time) -> result.set(melting, result.time + time))); - affinity(burning, ((unit, result, time) -> result.set(burning, result.time + time))); + affinity(melting, (unit, result, time) -> result.set(melting, result.time + time)); + affinity(burning, (unit, result, time) -> result.set(burning, result.time + time)); }); }}; diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 8cfaa3f989..63ad6ebde5 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -14,6 +14,7 @@ import mindustry.entities.effect.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.type.*; +import mindustry.type.ammo.*; import mindustry.type.weapons.*; import mindustry.world.meta.*; @@ -52,8 +53,8 @@ public class UnitTypes implements ContentList{ //air + payload, legacy public static @EntityDef(value = {Unitc.class, Payloadc.class}, legacy = true) UnitType quad; - //air + payload + ammo distribution - public static @EntityDef({Unitc.class, Payloadc.class, AmmoDistributec.class}) UnitType oct; + //air + payload + legacy (different branch) + public static @EntityDef(value = {Unitc.class, Payloadc.class}, legacy = true) UnitType oct; //air, legacy public static @EntityDef(value = {Unitc.class}, legacy = true) UnitType alpha, beta, gamma; @@ -89,6 +90,7 @@ public class UnitTypes implements ContentList{ hitSize = 10f; health = 540; armor = 4f; + ammoType = new ItemAmmoType(Items.coal); immunities.add(StatusEffects.burning); @@ -99,10 +101,10 @@ public class UnitTypes implements ContentList{ reload = 11f; recoil = 1f; ejectEffect = Fx.none; - bullet = new BulletType(4.1f, 32f){{ + bullet = new BulletType(4.1f, 35f){{ ammoMultiplier = 3f; hitSize = 7f; - lifetime = 12f; + lifetime = 13f; pierce = true; statusDuration = 60f * 4; shootEffect = Fx.shootSmallFlame; @@ -123,6 +125,7 @@ public class UnitTypes implements ContentList{ health = 900; armor = 9f; mechFrontSway = 0.55f; + ammoType = new ItemAmmoType(Items.graphite); weapons.add(new Weapon("artillery"){{ top = false; @@ -156,6 +159,7 @@ public class UnitTypes implements ContentList{ armor = 10f; canDrown = false; mechFrontSway = 1f; + ammoType = new ItemAmmoType(Items.thorium); mechStepParticles = true; mechStepShake = 0.15f; @@ -220,6 +224,7 @@ public class UnitTypes implements ContentList{ canDrown = false; mechFrontSway = 1.9f; mechSideSway = 0.6f; + ammoType = new ItemAmmoType(Items.thorium); weapons.add( new Weapon("reign-weapon"){{ @@ -282,7 +287,7 @@ public class UnitTypes implements ContentList{ commandLimit = 8; abilities.add(new RepairFieldAbility(10f, 60f * 4, 60f)); - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(1000); weapons.add(new Weapon("heal-weapon"){{ top = false; @@ -319,7 +324,7 @@ public class UnitTypes implements ContentList{ commandLimit = 9; abilities.add(new ShieldRegenFieldAbility(20f, 40f, 60f * 5, 60f)); - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(1300); weapons.add(new Weapon("heal-shotgun-weapon"){{ top = false; @@ -339,7 +344,7 @@ public class UnitTypes implements ContentList{ bullet = new LightningBulletType(){{ lightningColor = hitColor = Pal.heal; - damage = 12f; + damage = 14f; lightningLength = 7; lightningLengthRand = 7; shootEffect = Fx.shootHeal; @@ -372,7 +377,7 @@ public class UnitTypes implements ContentList{ commandLimit = 10; mechFrontSway = 0.55f; - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(1500); speed = 0.4f; hitSize = 13f; @@ -408,23 +413,23 @@ public class UnitTypes implements ContentList{ vela = new UnitType("vela"){{ hitSize = 24f; - rotateSpeed = 1.6f; + rotateSpeed = 1.7f; canDrown = false; mechFrontSway = 1f; buildSpeed = 3f; mechStepParticles = true; mechStepShake = 0.15f; - ammoType = AmmoTypes.powerHigh; + ammoType = new PowerAmmoType(2500); - speed = 0.39f; + speed = 0.44f; boostMultiplier = 2.2f; engineOffset = 12f; engineSize = 6f; lowAltitude = true; riseSpeed = 0.02f; - health = 7500f; + health = 8200f; armor = 9f; canBoost = true; landShake = 4f; @@ -449,8 +454,8 @@ public class UnitTypes implements ContentList{ cooldownTime = 200f; bullet = new ContinuousLaserBulletType(){{ - damage = 30f; - length = 175f; + damage = 35f; + length = 180f; hitEffect = Fx.hitMeltHeal; drawSize = 420f; lifetime = 160f; @@ -493,7 +498,7 @@ public class UnitTypes implements ContentList{ hovering = true; visualElevation = 0.2f; allowLegStep = true; - ammoType = AmmoTypes.powerHigh; + ammoType = new PowerAmmoType(4000); groundLayer = Layer.legUnit; speed = 0.3f; @@ -558,6 +563,7 @@ public class UnitTypes implements ContentList{ health = 200; mechSideSway = 0.25f; range = 40f; + ammoType = new ItemAmmoType(Items.coal); weapons.add(new Weapon(){{ reload = 24f; @@ -595,6 +601,7 @@ public class UnitTypes implements ContentList{ legMoveSpace = 1.4f; hovering = true; armor = 3f; + ammoType = new ItemAmmoType(Items.coal); allowLegStep = true; visualElevation = 0.2f; @@ -634,7 +641,7 @@ public class UnitTypes implements ContentList{ legBaseOffset = 2f; hovering = true; armor = 5f; - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(1000); buildSpeed = 0.75f; @@ -706,7 +713,7 @@ public class UnitTypes implements ContentList{ legLengthScl = 0.96f; rippleScale = 2f; legSpeed = 0.2f; - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(2000); buildSpeed = 1f; legSplashDamage = 32; @@ -810,7 +817,7 @@ public class UnitTypes implements ContentList{ legLengthScl = 0.93f; rippleScale = 3f; legSpeed = 0.19f; - ammoType = AmmoTypes.powerHigh; + ammoType = new ItemAmmoType(Items.graphite, 8); buildSpeed = 1f; legSplashDamage = 80; @@ -928,6 +935,9 @@ public class UnitTypes implements ContentList{ engineOffset = 5.5f; range = 140f; targetAir = false; + //as default AI, flares are not very useful in core rushes, they attack nothing in the way + playerTargetFlags = new BlockFlag[]{null}; + targetFlags = new BlockFlag[]{BlockFlag.generator, null}; commandLimit = 4; circleTarget = true; hitSize = 7; @@ -961,9 +971,12 @@ public class UnitTypes implements ContentList{ range = 140f; faceTarget = false; armor = 3f; - targetFlag = BlockFlag.factory; + //do not rush core, attack closest + playerTargetFlags = new BlockFlag[]{null}; + targetFlags = new BlockFlag[]{BlockFlag.factory, null}; commandLimit = 5; circleTarget = true; + ammoType = new ItemAmmoType(Items.graphite); weapons.add(new Weapon(){{ minShootVelocity = 0.75f; @@ -997,10 +1010,13 @@ public class UnitTypes implements ContentList{ range = 140f; hitSize = 20f; lowAltitude = true; + forceMultiTarget = true; armor = 5f; + targetFlags = new BlockFlag[]{BlockFlag.launchPad, BlockFlag.storage, BlockFlag.battery, null}; engineOffset = 12f; engineSize = 3f; + ammoType = new ItemAmmoType(Items.graphite); weapons.add(new Weapon("zenith-missiles"){{ reload = 40f; @@ -1045,7 +1061,8 @@ public class UnitTypes implements ContentList{ engineOffset = 21; engineSize = 5.3f; hitSize = 46f; - targetFlag = BlockFlag.battery; + targetFlags = new BlockFlag[]{BlockFlag.generator, BlockFlag.core, null}; + ammoType = new ItemAmmoType(Items.thorium); BulletType missiles = new MissileBulletType(2.7f, 14){{ width = 8f; @@ -1120,7 +1137,8 @@ public class UnitTypes implements ContentList{ hitSize = 58f; destructibleWreck = false; armor = 13f; - targetFlag = BlockFlag.reactor; + targetFlags = new BlockFlag[]{BlockFlag.reactor, BlockFlag.core, null}; + ammoType = new ItemAmmoType(Items.thorium); BulletType fragBullet = new FlakBulletType(4f, 5){{ shootEffect = Fx.shootBig; @@ -1200,7 +1218,7 @@ public class UnitTypes implements ContentList{ range = 50f; isCounted = false; - ammoType = AmmoTypes.powerLow; + ammoType = new PowerAmmoType(500); mineTier = 1; mineSpeed = 2.5f; @@ -1221,7 +1239,7 @@ public class UnitTypes implements ContentList{ hitSize = 9f; lowAltitude = true; - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(900); mineTier = 2; mineSpeed = 3.5f; @@ -1281,7 +1299,7 @@ public class UnitTypes implements ContentList{ buildSpeed = 2.6f; isCounted = false; - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(1100); weapons.add( new Weapon("heal-weapon-mount"){{ @@ -1317,7 +1335,7 @@ public class UnitTypes implements ContentList{ quad = new UnitType("quad"){{ armor = 8f; health = 6000; - speed = 1.4f; + speed = 1.3f; rotateSpeed = 2f; accel = 0.05f; drag = 0.017f; @@ -1333,9 +1351,9 @@ public class UnitTypes implements ContentList{ buildBeamOffset = 23; range = 140f; targetAir = false; - targetFlag = BlockFlag.battery; + targetFlags = new BlockFlag[]{BlockFlag.battery, BlockFlag.factory, null}; - ammoType = AmmoTypes.powerHigh; + ammoType = new PowerAmmoType(3000); weapons.add( new Weapon(){{ @@ -1405,9 +1423,7 @@ public class UnitTypes implements ContentList{ commandLimit = 6; lowAltitude = true; buildBeamOffset = 43; - - ammoCapacity = 1300; - ammoResupplyAmount = 20; + ammoCapacity = 1; abilities.add(new ForceFieldAbility(140f, 4f, 7000f, 60f * 8), new RepairFieldAbility(130f, 60f * 2, 140f)); }}; @@ -1475,6 +1491,7 @@ public class UnitTypes implements ContentList{ accel = 0.3f; rotateSpeed = 2.6f; rotateShooting = false; + ammoType = new ItemAmmoType(Items.graphite); trailLength = 20; trailX = 5.5f; @@ -1518,6 +1535,7 @@ public class UnitTypes implements ContentList{ hitSize = 20f; armor = 7f; rotateShooting = false; + ammoType = new ItemAmmoType(Items.graphite); trailLength = 22; trailX = 7f; @@ -1581,6 +1599,7 @@ public class UnitTypes implements ContentList{ inaccuracy = 5f; velocityRnd = 0.1f; shootSound = Sounds.missile; + ammoType = new ItemAmmoType(Items.thorium); ejectEffect = Fx.none; bullet = new MissileBulletType(2.7f, 12){{ @@ -1614,6 +1633,7 @@ public class UnitTypes implements ContentList{ accel = 0.2f; rotateSpeed = 1.3f; rotateShooting = false; + ammoType = new ItemAmmoType(Items.thorium); trailLength = 50; trailX = 18f; @@ -1699,6 +1719,7 @@ public class UnitTypes implements ContentList{ accel = 0.19f; rotateSpeed = 0.9f; rotateShooting = false; + ammoType = new PowerAmmoType(4000); float spawnTime = 60f * 15f; @@ -1756,6 +1777,7 @@ public class UnitTypes implements ContentList{ trailScl = 1.3f; rotateShooting = false; range = 100f; + ammoType = new PowerAmmoType(900); armor = 3f; @@ -1833,6 +1855,7 @@ public class UnitTypes implements ContentList{ trailX = 5.5f; trailY = -4f; trailScl = 1.9f; + ammoType = new ItemAmmoType(Items.coal); buildSpeed = 2f; @@ -1901,6 +1924,7 @@ public class UnitTypes implements ContentList{ hitSize = 20f; armor = 6f; rotateShooting = false; + ammoType = new ItemAmmoType(Items.graphite); trailLength = 23; trailX = 9f; @@ -2036,6 +2060,8 @@ public class UnitTypes implements ContentList{ accel = 0.2f; rotateSpeed = 1.4f; rotateShooting = false; + ammoType = new PowerAmmoType(3500); + ammoCapacity = 40; //clip size is massive due to energy field clipSize = 250f; @@ -2079,6 +2105,7 @@ public class UnitTypes implements ContentList{ accel = 0.2f; rotateSpeed = 1.1f; rotateShooting = false; + ammoType = new PowerAmmoType(4500); trailLength = 70; trailX = 23f; diff --git a/core/src/mindustry/core/ContentLoader.java b/core/src/mindustry/core/ContentLoader.java index 6022f7bc9a..88e7886438 100644 --- a/core/src/mindustry/core/ContentLoader.java +++ b/core/src/mindustry/core/ContentLoader.java @@ -34,7 +34,6 @@ public class ContentLoader{ new StatusEffects(), new Liquids(), new Bullets(), - new AmmoTypes(), new UnitTypes(), new Blocks(), new Loadouts(), diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index a416b5d2fd..e4f84b8d38 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -36,7 +36,6 @@ import java.text.*; import java.util.*; import static arc.Core.*; -import static mindustry.Vars.net; import static mindustry.Vars.*; /** @@ -195,14 +194,16 @@ public class Control implements ApplicationListener, Loadable{ }); Events.run(Trigger.newGame, () -> { - Building core = player.bestCore(); + var core = player.bestCore(); if(core == null) return; camera.position.set(core); player.set(core); - if(showLandAnimation){ + if(!settings.getBool("skipcoreanimation")){ + //delay player respawn so animation can play. + player.deathTimer = -80f; //TODO this sounds pretty bad due to conflict if(settings.getInt("musicvol") > 0){ Musics.land.stop(); @@ -211,14 +212,14 @@ public class Control implements ApplicationListener, Loadable{ } app.post(() -> ui.hudfrag.showLand()); - renderer.zoomIn(Fx.coreLand.lifetime); - app.post(() -> Fx.coreLand.at(core.getX(), core.getY(), 0, core.block)); + renderer.showLanding(); - Time.run(Fx.coreLand.lifetime, () -> { + Time.run(coreLandDuration, () -> { Fx.launch.at(core); Effect.shake(5f, 5f, core); + core.thrusterTime = 1f; - if(state.isCampaign()){ + if(state.isCampaign() && Vars.showSectorLandInfo){ ui.announce("[accent]" + state.rules.sector.name() + "\n" + (state.rules.sector.info.resources.any() ? "[lightgray]" + bundle.get("sectors.resources") + "[white] " + state.rules.sector.info.resources.toString(" ", u -> u.emoji()) : ""), 5); @@ -328,6 +329,7 @@ public class Control implements ApplicationListener, Loadable{ slot.load(); slot.setAutosave(true); state.rules.sector = sector; + state.rules.cloudColor = sector.planet.landCloudColor; //if there is no base, simulate a new game and place the right loadout at the spawn position if(state.rules.defaultTeam.cores().isEmpty() || hadNoCore){ @@ -542,7 +544,12 @@ public class Control implements ApplicationListener, Loadable{ core.items.each((i, a) -> i.unlock()); } - if(Core.input.keyTap(Binding.pause) && !scene.hasDialog() && !scene.hasKeyboard() && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){ + //cannot launch while paused + if(state.is(State.paused) && renderer.isCutscene()){ + state.set(State.playing); + } + + if(Core.input.keyTap(Binding.pause) && !renderer.isCutscene() && !scene.hasDialog() && !scene.hasKeyboard() && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){ state.set(state.is(State.playing) ? State.paused : State.playing); } diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java index da52f23269..6d01275325 100644 --- a/core/src/mindustry/core/NetClient.java +++ b/core/src/mindustry/core/NetClient.java @@ -1,6 +1,7 @@ package mindustry.core; import arc.*; +import arc.audio.*; import arc.func.*; import arc.graphics.*; import arc.math.*; @@ -159,8 +160,6 @@ public class NetClient implements ApplicationListener{ clientPacketReliable(type, contents); } - //TODO enable in build 129 - /* @Remote(variants = Variant.both, unreliable = true) public static void sound(Sound sound, float volume, float pitch, float pan){ if(sound == null) return; @@ -173,7 +172,7 @@ public class NetClient implements ApplicationListener{ if(sound == null) return; sound.at(x, y, pitch, volume); - }*/ + } @Remote(variants = Variant.both, unreliable = true) public static void effect(Effect effect, float x, float y, float rotation, Color color){ diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java index 5183069725..e7fe48677e 100644 --- a/core/src/mindustry/core/Renderer.java +++ b/core/src/mindustry/core/Renderer.java @@ -18,6 +18,7 @@ import mindustry.game.EventType.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.graphics.g3d.*; +import mindustry.world.blocks.storage.*; import mindustry.world.blocks.storage.CoreBlock.*; import static arc.Core.*; @@ -27,6 +28,12 @@ public class Renderer implements ApplicationListener{ /** These are global variables, for headless access. Cached. */ public static float laserOpacity = 0.5f, bridgeOpacity = 0.75f; + private static final float cloudScaling = 1700f, cfinScl = -2f, cfinOffset = 0.3f, calphaFinOffset = 0.25f; + private static final float[] cloudAlphas = {0, 0.5f, 1f, 0.1f, 0, 0f}; + private static final float cloudAlpha = 0.81f; + private static final float[] thrusterSizes = {0f, 0f, 0f, 0f, 0.3f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 0f}; + private static final Interp landInterp = Interp.pow3; + public final BlockRenderer blocks = new BlockRenderer(); public final MinimapRenderer minimap = new MinimapRenderer(); public final OverlayRenderer overlays = new OverlayRenderer(); @@ -37,15 +44,34 @@ public class Renderer implements ApplicationListener{ public @Nullable Bloom bloom; public FrameBuffer effectBuffer = new FrameBuffer(); public boolean animateShields, drawWeather = true, drawStatus; + public float weatherAlpha; /** minZoom = zooming out, maxZoom = zooming in */ public float minZoom = 1.5f, maxZoom = 6f; public Seq envRenderers = new Seq<>(); public TextureRegion[] bubbles = new TextureRegion[16], splashes = new TextureRegion[12]; private @Nullable CoreBuild landCore; + private @Nullable CoreBlock launchCoreType; private Color clearColor = new Color(0f, 0f, 0f, 1f); - private float targetscale = Scl.scl(4), camerascale = targetscale, landscale, landTime, weatherAlpha, minZoomScl = Scl.scl(0.01f); - private float shakeIntensity, shaketime; + private float + //seed for cloud visuals, 0-1 + cloudSeed = 0f, + //target camera scale that is lerp-ed to + targetscale = Scl.scl(4), + //current actual camera scale + camerascale = targetscale, + //minimum camera zoom value for landing/launching; constant TODO make larger? + minZoomScl = Scl.scl(0.02f), + //starts at coreLandDuration, ends at 0. if positive, core is landing. + landTime, + //timer for core landing particles + landPTimer, + //intensity for screen shake + shakeIntensity, + //current duration of screen shake + shakeTime; + //for landTime > 0: if true, core is currently *launching*, otherwise landing. + private boolean launching; private Vec2 camShakeOffset = new Vec2(); public Renderer(){ @@ -55,7 +81,7 @@ public class Renderer implements ApplicationListener{ public void shake(float intensity, float duration){ shakeIntensity = Math.max(shakeIntensity, intensity); - shaketime = Math.max(shaketime, duration); + shakeTime = Math.max(shakeTime, duration); } public void addEnvRenderer(int mask, Runnable render){ @@ -97,12 +123,22 @@ public class Renderer implements ApplicationListener{ drawStatus = Core.settings.getBool("blockstatus"); if(landTime > 0){ + if(!state.isPaused()){ + updateLandParticles(); + } + if(!state.isPaused()){ landTime -= Time.delta; } - landscale = Interp.pow5In.apply(minZoomScl, Scl.scl(4f), 1f - landTime / Fx.coreLand.lifetime); - camerascale = landscale; + float fin = landTime / coreLandDuration; + if(!launching) fin = 1f - fin; + camerascale = landInterp.apply(minZoomScl, Scl.scl(4f), fin); weatherAlpha = 0f; + + //snap camera to cutscene core regardless of player input + if(landCore != null){ + camera.position.set(landCore); + } }else{ weatherAlpha = Mathf.lerpDelta(weatherAlpha, 1f, 0.08f); } @@ -114,12 +150,12 @@ public class Renderer implements ApplicationListener{ landTime = 0f; graphics.clear(Color.black); }else{ - if(shaketime > 0){ + if(shakeTime > 0){ float intensity = shakeIntensity * (settings.getInt("screenshake", 4) / 4f) * 0.75f; camShakeOffset.setToRandomDirection().scl(Mathf.random(intensity)); camera.position.add(camShakeOffset); shakeIntensity -= 0.25f * Time.delta; - shaketime -= Time.delta; + shakeTime -= Time.delta; shakeIntensity = Mathf.clamp(shakeIntensity, 0f, 100f); }else{ camShakeOffset.setZero(); @@ -136,16 +172,13 @@ public class Renderer implements ApplicationListener{ } } - public boolean isLanding(){ + /** @return whether a launch/land cutscene is playing. */ + public boolean isCutscene(){ return landTime > 0; } - public float weatherAlpha(){ - return weatherAlpha; - } - public float landScale(){ - return landTime > 0 ? landscale : 1f; + return landTime > 0 ? camerascale : 1f; } @Override @@ -278,48 +311,160 @@ public class Renderer implements ApplicationListener{ } private void drawBackground(){ - + //nothing to draw currently } - private void drawLanding(){ - CoreBuild entity = landCore == null ? player.bestCore() : landCore; - //var clouds = assets.get("sprites/clouds.png", Texture.class); - if(landTime > 0 && entity != null){ - float fout = landTime / Fx.coreLand.lifetime; + void updateLandParticles(){ + float time = launching ? coreLandDuration - landTime : landTime; + float tsize = Mathf.sample(thrusterSizes, (time + 35f) / coreLandDuration); - //TODO clouds - /* - float scaling = 10000f; - float sscl = 1f + fout*1.5f; - float offset = -0.38f; + landPTimer += tsize * Time.delta; + if(landCore != null && landPTimer >= 1f){ + landCore.tile.getLinkedTiles(t -> { + if(Mathf.chance(0.4f)){ + Fx.coreLandDust.at(t.worldx(), t.worldy(), landCore.angleTo(t) + Mathf.range(30f), Tmp.c1.set(t.floor().mapColor).mul(1.5f + Mathf.range(0.15f))); + } + }); - Tmp.tr1.set(clouds); - Tmp.tr1.set((camera.position.x - camera.width/2f * sscl) / scaling, (camera.position.y - camera.height/2f * sscl) / scaling, (camera.position.x + camera.width/2f * sscl) / scaling, (camera.position.y + camera.height/2f * sscl) / scaling); - Draw.alpha(Mathf.slope(Mathf.clamp(((1f - fout) + offset)/(1f + offset)))); - Draw.mixcol(Pal.spore, 0.5f); - Draw.rect(Tmp.tr1, camera.position.x, camera.position.y, camera.width, camera.height); - Draw.reset();*/ + landPTimer = 0f; + } + } - TextureRegion reg = entity.block.fullIcon; + void drawLanding(){ + CoreBuild build = landCore == null ? player.bestCore() : landCore; + var clouds = assets.get("sprites/clouds.png", Texture.class); + if(landTime > 0 && build != null){ + float fout = landTime / coreLandDuration; + + if(launching) fout = 1f - fout; + + float fin = 1f - fout; + + //draw core + var block = launching && launchCoreType != null ? launchCoreType : (CoreBlock)build.block; + TextureRegion reg = block.fullIcon; float scl = Scl.scl(4f) / camerascale; - float s = reg.width * Draw.scl * scl * 4f * fout; + float shake = 0f; + float s = reg.width * Draw.scl * scl * 3.6f * Interp.pow2Out.apply(fout); + float rotation = Interp.pow2In.apply(fout) * 135f, x = build.x + Mathf.range(shake), y = build.y + Mathf.range(shake); + float thrustOpen = 0.25f; + float thrusterFrame = fin >= thrustOpen ? 1f : fin / thrustOpen; + float thrusterSize = Mathf.sample(thrusterSizes, fin); + + //when launching, thrusters stay out the entire time. + if(launching){ + Interp i = Interp.pow2Out; + thrusterFrame = i.apply(Mathf.clamp(fout*13f)); + thrusterSize = i.apply(Mathf.clamp(fout*9f)); + } Draw.color(Pal.lightTrail); - Draw.rect("circle-shadow", entity.x, entity.y, s, s); + //TODO spikier heat + Draw.rect("circle-shadow", x, y, s, s); - Angles.randLenVectors(1, (1f- fout), 100, 1000f * scl * (1f-fout), (x, y, ffin, ffout) -> { - Lines.stroke(scl * ffin); - Lines.lineAngle(entity.x + x, entity.y + y, Mathf.angle(x, y), (ffin * 20 + 1f) * scl); + Draw.color(Pal.lightTrail); + + float pfin = Interp.pow3Out.apply(fin), pf = Interp.pow2In.apply(fout); + + //draw particles + Angles.randLenVectors(1, pfin, 100, 800f * scl * pfin, (ax, ay, ffin, ffout) -> { + Lines.stroke(scl * ffin * pf * 3f); + Lines.lineAngle(build.x + ax, build.y + ay, Mathf.angle(ax, ay), (ffin * 20 + 1f) * scl); }); Draw.color(); - Draw.mixcol(Color.white, fout); - Draw.rect(reg, entity.x, entity.y, reg.width * Draw.scl * scl, reg.height * Draw.scl * scl, fout * 135f); + Draw.mixcol(Color.white, Interp.pow5In.apply(fout)); + + //accent tint indicating that the core was just constructed + if(launching){ + float f = Mathf.clamp(1f - fout * 12f); + if(f > 0.001f){ + Draw.mixcol(Pal.accent, f); + } + } + + Draw.scl(scl); + + Draw.alpha(1f); + + //draw thruster flame + float strength = (1f + (block.size - 3)/2.5f) * scl * thrusterSize * (0.95f + Mathf.absin(2f, 0.1f)); + float offset = (block.size - 3) * 3f * scl; + + for(int i = 0; i < 4; i++){ + Tmp.v1.trns(i * 90 + rotation, 1f); + + Tmp.v1.setLength((block.size * tilesize/2f + 1f)*scl + strength*2f + offset); + Draw.color(build.team.color); + Fill.circle(Tmp.v1.x + x, Tmp.v1.y + y, 6f * strength); + + Tmp.v1.setLength((block.size * tilesize/2f + 1f)*scl + strength*0.5f + offset); + Draw.color(Color.white); + Fill.circle(Tmp.v1.x + x, Tmp.v1.y + y, 3.5f * strength); + } + + drawThrusters(block, x, y, rotation, thrusterFrame); + + Drawf.spinSprite(block.region, x, y, rotation); + + Draw.alpha(Interp.pow4In.apply(thrusterFrame)); + drawThrusters(block, x, y, rotation, thrusterFrame); + Draw.alpha(1f); + + Drawf.spinSprite(block.teamRegions[build.team.id], x, y, rotation); + + Draw.scl(); Draw.reset(); + + //draw clouds + if(state.rules.cloudColor.a > 0.0001f){ + float scaling = cloudScaling; + float sscl = Math.max(1f + Mathf.clamp(fin + cfinOffset)* cfinScl, 0f) * camerascale; + + Tmp.tr1.set(clouds); + Tmp.tr1.set( + (camera.position.x - camera.width/2f * sscl) / scaling, + (camera.position.y - camera.height/2f * sscl) / scaling, + (camera.position.x + camera.width/2f * sscl) / scaling, + (camera.position.y + camera.height/2f * sscl) / scaling); + + Tmp.tr1.scroll(10f * cloudSeed, 10f * cloudSeed); + + Draw.alpha(Mathf.sample(cloudAlphas, fin + calphaFinOffset) * cloudAlpha); + Draw.mixcol(state.rules.cloudColor, state.rules.cloudColor.a); + Draw.rect(Tmp.tr1, camera.position.x, camera.position.y, camera.width, camera.height); + Draw.reset(); + } } } + void drawThrusters(CoreBlock block, float x, float y, float rotation, float frame){ + float length = block.thrusterLength * (frame - 1f) - 1f/4f; + float alpha = Draw.getColor().a; + + //two passes for consistent lighting + for(int j = 0; j < 2; j++){ + for(int i = 0; i < 4; i++){ + var reg = i >= 2 ? block.thruster2 : block.thruster1; + float rot = (i * 90) + rotation % 90f; + Tmp.v1.trns(rot, length * Draw.xscl); + + //second pass applies extra layer of shading + if(j == 1){ + Tmp.v1.rotate(-90f); + Draw.alpha((rotation % 90f) / 90f * alpha); + rot -= 90f; + Draw.rect(reg, x + Tmp.v1.x, y + Tmp.v1.y, rot); + }else{ + Draw.alpha(alpha); + Draw.rect(reg, x + Tmp.v1.x, y + Tmp.v1.y, rot); + } + } + } + Draw.alpha(1f); + } + public void scaleCamera(float amount){ targetscale *= (amount / 4) + 1; clampScale(); @@ -350,9 +495,23 @@ public class Renderer implements ApplicationListener{ clampScale(); } - public void zoomIn(float duration){ - landscale = minZoomScl; - landTime = duration; + public void showLanding(){ + launching = false; + camerascale = minZoomScl; + landTime = coreLandDuration; + cloudSeed = Mathf.random(1f); + } + + public void showLaunch(CoreBlock coreType){ + Vars.ui.hudfrag.showLaunch(); + launchCoreType = coreType; + launching = true; + landCore = player.team().core(); + cloudSeed = Mathf.random(1f); + landTime = coreLandDuration; + if(landCore != null){ + Fx.coreLaunchConstruct.at(landCore.x, landCore.y, coreType.size); + } } public void takeMapScreenshot(){ diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java index ad491eb41e..ada34573b3 100644 --- a/core/src/mindustry/core/World.java +++ b/core/src/mindustry/core/World.java @@ -289,6 +289,7 @@ public class World{ if(liquid != null) content.add(liquid); } + state.rules.cloudColor = sector.planet.landCloudColor; sector.info.resources = content.asArray(); sector.info.resources.sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id))); sector.saveInfo(); diff --git a/core/src/mindustry/ctype/ContentType.java b/core/src/mindustry/ctype/ContentType.java index e62377628c..8dfffce5e3 100644 --- a/core/src/mindustry/ctype/ContentType.java +++ b/core/src/mindustry/ctype/ContentType.java @@ -16,7 +16,7 @@ public enum ContentType{ typeid_UNUSED, error, planet, - ammo; + ammo_UNUSED; public static final ContentType[] all = values(); } diff --git a/core/src/mindustry/entities/Puddles.java b/core/src/mindustry/entities/Puddles.java index 183f64eacc..8422329c6c 100644 --- a/core/src/mindustry/entities/Puddles.java +++ b/core/src/mindustry/entities/Puddles.java @@ -16,12 +16,12 @@ public class Puddles{ /** Deposits a Puddle between tile and source. */ public static void deposit(Tile tile, Tile source, Liquid liquid, float amount){ - deposit(tile, source, liquid, amount, 0); + deposit(tile, source, liquid, amount, true); } /** Deposits a Puddle at a tile. */ public static void deposit(Tile tile, Liquid liquid, float amount){ - deposit(tile, tile, liquid, amount, 0); + deposit(tile, tile, liquid, amount, true); } /** Returns the Puddle on the specified tile. May return null. */ @@ -29,7 +29,7 @@ public class Puddles{ return map.get(tile.pos()); } - public static void deposit(Tile tile, Tile source, Liquid liquid, float amount, int generation){ + public static void deposit(Tile tile, Tile source, Liquid liquid, float amount, boolean initial){ if(tile == null) return; if(tile.floor().isLiquid && !canStayOn(liquid, tile.floor().liquidDrop)){ @@ -38,16 +38,14 @@ public class Puddles{ Puddle p = map.get(tile.pos()); - if(generation == 0 && p != null && p.lastRipple <= Time.time - 40f){ + if(initial && p != null && p.lastRipple <= Time.time - 40f){ Fx.ripple.at((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f, 1f, tile.floor().liquidDrop.color); p.lastRipple = Time.time; } return; } - if(tile.floor().solid){ - return; - } + if(tile.floor().solid) return; Puddle p = map.get(tile.pos()); if(p == null){ @@ -55,14 +53,13 @@ public class Puddles{ puddle.tile = tile; puddle.liquid = liquid; puddle.amount = amount; - puddle.generation = generation; puddle.set((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); - puddle.add(); map.put(tile.pos(), puddle); + puddle.add(); }else if(p.liquid == liquid){ p.accepting = Math.max(amount, p.accepting); - if(generation == 0 && p.lastRipple <= Time.time - 40f && p.amount >= maxLiquid / 2f){ + if(initial && p.lastRipple <= Time.time - 40f && p.amount >= maxLiquid / 2f){ Fx.ripple.at((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f, 1f, p.liquid.color); p.lastRipple = Time.time; } diff --git a/core/src/mindustry/entities/Units.java b/core/src/mindustry/entities/Units.java index 6fa7889d8e..ae4f8e00eb 100644 --- a/core/src/mindustry/entities/Units.java +++ b/core/src/mindustry/entities/Units.java @@ -22,6 +22,7 @@ public class Units{ private static float cdist; private static boolean boolResult; private static int intResult; + private static Building buildResult; @Remote(called = Loc.server) public static void unitCapDeath(Unit unit){ @@ -142,7 +143,7 @@ public class Units{ /** Returns the nearest damaged tile. */ public static Building findDamagedTile(Team team, float x, float y){ - return Geometry.findClosest(x, y, indexer.getDamaged(team)); + return indexer.getDamaged(team).min(b -> b.dst2(x, y)); } /** Returns the nearest ally tile in a range. */ @@ -157,6 +158,26 @@ public class Units{ return indexer.findEnemyTile(team, x, y, range, pred); } + /** @return the closest building of the provided team that matches the predicate. */ + public static @Nullable Building closestBuilding(Team team, float wx, float wy, float range, Boolf pred){ + buildResult = null; + cdist = 0f; + + var buildings = team.data().buildings; + if(buildings == null) return null; + buildings.intersect(wx - range, wy - range, range*2f, range*2f, b -> { + if(pred.get(b)){ + float dst = b.dst(wx, wy) - b.hitSize()/2f; + if(dst <= range && (buildResult == null || dst <= cdist)){ + cdist = dst; + buildResult = b; + } + } + }); + + return buildResult; + } + /** Iterates through all buildings in a range. */ public static void nearbyBuildings(float x, float y, float range, Cons cons){ indexer.allBuildings(x, y, range, cons); diff --git a/core/src/mindustry/entities/abilities/EnergyFieldAbility.java b/core/src/mindustry/entities/abilities/EnergyFieldAbility.java index 8681e37843..3844fc3915 100644 --- a/core/src/mindustry/entities/abilities/EnergyFieldAbility.java +++ b/core/src/mindustry/entities/abilities/EnergyFieldAbility.java @@ -14,6 +14,8 @@ import mindustry.gen.*; import mindustry.graphics.*; import mindustry.type.*; +import static mindustry.Vars.*; + public class EnergyFieldAbility extends Ability{ private static final Seq all = new Seq<>(); @@ -31,6 +33,7 @@ public class EnergyFieldAbility extends Ability{ public float effectRadius = 5f, sectorRad = 0.14f, rotateSpeed = 0.5f; public int sectors = 5; public Color color = Pal.heal; + public boolean useAmmo = true; protected float timer, curStroke; protected boolean anyNearby = false; @@ -88,8 +91,7 @@ public class EnergyFieldAbility extends Ability{ curStroke = Mathf.lerpDelta(curStroke, anyNearby ? 1 : 0, 0.09f); - if((timer += Time.delta) >= reload){ - + if((timer += Time.delta) >= reload && (!useAmmo || unit.ammo > 0 || !state.rules.unitAmmo)){ Tmp.v1.trns(unit.rotation - 90, x, y).add(unit.x, unit.y); float rx = Tmp.v1.x, ry = Tmp.v1.y; anyNearby = false; @@ -131,7 +133,11 @@ public class EnergyFieldAbility extends Ability{ } }else{ anyNearby = true; - other.damage(damage); + if(other instanceof Building b){ + b.damage(unit.team, damage); + }else{ + other.damage(damage); + } if(other instanceof Statusc s){ s.apply(status, statusDuration); } @@ -143,6 +149,10 @@ public class EnergyFieldAbility extends Ability{ if(anyNearby){ shootSound.at(unit); + + if(useAmmo && state.rules.unitAmmo){ + unit.ammo --; + } } timer = 0f; diff --git a/core/src/mindustry/entities/abilities/MoveLightningAbility.java b/core/src/mindustry/entities/abilities/MoveLightningAbility.java index 4cc62b7172..0a56d3bd15 100644 --- a/core/src/mindustry/entities/abilities/MoveLightningAbility.java +++ b/core/src/mindustry/entities/abilities/MoveLightningAbility.java @@ -24,6 +24,8 @@ public class MoveLightningAbility extends Ability{ public Color color = Color.valueOf("a9d8ff"); /** Shifts where the lightning spawns along the Y axis */ public float offset = 0f; + /** Offset along the X axis. */ + public float width = 0f; /** Jittering heat sprite like the shield on v5 Javelin */ public String heatRegion = "error"; /** Bullet type that is fired. Can be null */ @@ -33,6 +35,8 @@ public class MoveLightningAbility extends Ability{ public Effect shootEffect = Fx.sparkShoot; public Sound shootSound = Sounds.spark; + + protected float side = 1f; MoveLightningAbility(){} @@ -61,7 +65,7 @@ public class MoveLightningAbility extends Ability{ public void update(Unit unit){ float scl = Mathf.clamp((unit.vel().len() - minSpeed) / (maxSpeed - minSpeed)); if(Mathf.chance(Time.delta * chance * scl)){ - float x = unit.x + Angles.trnsx(unit.rotation, offset, 0), y = unit.y + Angles.trnsy(unit.rotation, offset, 0); + float x = unit.x + Angles.trnsx(unit.rotation, offset, width * side), y = unit.y + Angles.trnsy(unit.rotation, offset, width * side); shootEffect.at(x, y, unit.rotation, color); shootSound.at(unit); @@ -73,6 +77,8 @@ public class MoveLightningAbility extends Ability{ if(bullet != null){ bullet.create(unit, unit.team, x, y, unit.rotation + bulletAngle + Mathf.range(bulletSpread)); } + + side *= -1f; } } diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index 3640299921..213c911a6b 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -343,15 +343,6 @@ public class BulletType extends Content implements Cloneable{ if(instantDisappear){ b.time = lifetime; } - - if(fragBullet != null || splashDamageRadius > 0 || lightning > 0){ - despawnHit = true; - } - - if(lightRadius == -1){ - lightRadius = Math.max(18, hitSize * 5f); - } - drawSize = Math.max(drawSize, trailLength * speed * 2f); } public void update(Bullet b){ @@ -412,6 +403,15 @@ public class BulletType extends Content implements Cloneable{ if(lightningType == null){ lightningType = !collidesAir ? Bullets.damageLightningGround : Bullets.damageLightning; } + + if(fragBullet != null || splashDamageRadius > 0 || lightning > 0){ + despawnHit = true; + } + + if(lightRadius == -1){ + lightRadius = Math.max(18, hitSize * 5f); + } + drawSize = Math.max(drawSize, trailLength * speed * 2f); } @Override diff --git a/core/src/mindustry/entities/bullet/FireBulletType.java b/core/src/mindustry/entities/bullet/FireBulletType.java new file mode 100644 index 0000000000..a2b14e4481 --- /dev/null +++ b/core/src/mindustry/entities/bullet/FireBulletType.java @@ -0,0 +1,64 @@ +package mindustry.entities.bullet; + +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; +import mindustry.graphics.*; + +public class FireBulletType extends BulletType{ + public Color colorFrom = Pal.lightFlame, colorMid = Pal.darkFlame, colorTo = Color.gray; + public float radius = 3f; + public float velMin = 0.6f, velMax = 2.6f; + public float fireTrailChance = 0.04f; + public Effect trailEffect2 = Fx.ballfire; + public float fireEffectChance = 0.1f, fireEffectChance2 = 0.1f; + + { + pierce = true; + collidesTiles = false; + collides = false; + drag = 0.03f; + hitEffect = despawnEffect = Fx.none; + trailEffect = Fx.fireballsmoke; + } + + public FireBulletType(float speed, float damage){ + super(speed, damage); + } + + public FireBulletType(){} + + @Override + public void init(Bullet b){ + super.init(b); + + b.vel.setLength(Mathf.random(velMin, velMax)); + } + + @Override + public void draw(Bullet b){ + Draw.color(colorFrom, colorMid, colorTo, b.fin()); + Fill.circle(b.x, b.y, radius * b.fout()); + Draw.reset(); + } + + @Override + public void update(Bullet b){ + super.update(b); + + if(Mathf.chanceDelta(fireTrailChance)){ + Fires.create(b.tileOn()); + } + + if(Mathf.chanceDelta(fireEffectChance)){ + trailEffect.at(b.x, b.y); + } + + if(Mathf.chanceDelta(fireEffectChance2)){ + trailEffect2.at(b.x, b.y); + } + } +} diff --git a/core/src/mindustry/entities/bullet/MassDriverBolt.java b/core/src/mindustry/entities/bullet/MassDriverBolt.java index 91dae839a8..006c490183 100644 --- a/core/src/mindustry/entities/bullet/MassDriverBolt.java +++ b/core/src/mindustry/entities/bullet/MassDriverBolt.java @@ -13,7 +13,7 @@ import static mindustry.Vars.*; public class MassDriverBolt extends BulletType{ public MassDriverBolt(){ - super(1f, 50); + super(1f, 75); collidesTiles = false; lifetime = 1f; despawnEffect = Fx.smeltsmoke; diff --git a/core/src/mindustry/entities/comp/AmmoDistributeComp.java b/core/src/mindustry/entities/comp/AmmoDistributeComp.java deleted file mode 100644 index 96e10a9ce0..0000000000 --- a/core/src/mindustry/entities/comp/AmmoDistributeComp.java +++ /dev/null @@ -1,28 +0,0 @@ -package mindustry.entities.comp; - -import arc.util.*; -import mindustry.annotations.Annotations.*; -import mindustry.game.*; -import mindustry.gen.*; -import mindustry.type.*; -import mindustry.world.blocks.units.*; - -@Component -abstract class AmmoDistributeComp implements Unitc{ - @Import float x, y; - @Import UnitType type; - @Import Team team; - @Import float ammo; - - private transient float ammoCooldown; - - @Override - public void update(){ - if(ammoCooldown > 0f) ammoCooldown -= Time.delta; - - if(ammo > 0 && ammoCooldown <= 0f && ResupplyPoint.resupply(team, x, y, type.ammoResupplyRange, Math.min(type.ammoResupplyAmount, ammo), type.ammoType.color, u -> u != self())){ - ammo -= Math.min(type.ammoResupplyAmount, ammo); - ammoCooldown = 5f; - } - } -} diff --git a/core/src/mindustry/entities/comp/BuilderComp.java b/core/src/mindustry/entities/comp/BuilderComp.java index 5861278d2d..288150e938 100644 --- a/core/src/mindustry/entities/comp/BuilderComp.java +++ b/core/src/mindustry/entities/comp/BuilderComp.java @@ -96,7 +96,7 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{ if(!(tile.build instanceof ConstructBuild cb)){ if(!current.initialized && !current.breaking && Build.validPlace(current.block, team, current.x, current.y, current.rotation)){ - boolean hasAll = infinite || current.isRotation(team) || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item)); + boolean hasAll = infinite || current.isRotation(team) || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item, Math.min(Mathf.round(i.amount * state.rules.buildCostMultiplier), 1))); if(hasAll){ Call.beginPlace(self(), current.block, team, current.x, current.y, current.rotation); @@ -176,7 +176,7 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{ /** @return whether this request should be skipped, in favor of the next one. */ boolean shouldSkip(BuildPlan request, @Nullable Building core){ //requests that you have at least *started* are considered - if(state.rules.infiniteResources || team.rules().infiniteResources || request.breaking || core == null || request.isRotation(team)) return false; + if(state.rules.infiniteResources || team.rules().infiniteResources || request.breaking || core == null || request.isRotation(team) || (isBuilding() && !within(plans.last(), buildingRange))) return false; return (request.stuck && !core.items.has(request.block.requirements)) || (Structs.contains(request.block.requirements, i -> !core.items.has(i.item, Math.min(i.amount, 15)) && Mathf.round(i.amount * state.rules.buildCostMultiplier) > 0) && !request.initialized); } diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index b98b8bf470..5dc11a407e 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -49,6 +49,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, static final float timeToSleep = 60f * 1, timeToUncontrol = 60f * 6; static final ObjectSet tmpTiles = new ObjectSet<>(); static final Seq tempBuilds = new Seq<>(); + static final BuildTeamChangeEvent teamChangeEvent = new BuildTeamChangeEvent(); static int sleepingEntities = 0; @Import float x, y, health, maxHealth; @@ -63,6 +64,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, transient boolean enabled = true; transient float enabledControlTime; transient String lastAccessed; + transient boolean wasDamaged; //used only by the indexer PowerModule power; ItemModule items; @@ -158,7 +160,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } public final void readBase(Reads read){ - health = read.f(); + //cap health by block health in case of nerfs + health = Math.min(read.f(), block.health); byte rot = read.b(); team = Team.get(read.b()); @@ -1071,7 +1074,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } public String getDisplayName(){ - return block.localizedName; + //derelict team icon currently doesn't display + return team == Team.derelict ? + block.localizedName + "\n" + Core.bundle.get("block.derelict") : + block.localizedName + (team == player.team() || team.emoji.isEmpty() ? "" : " " + team.emoji); } public TextureRegion getDisplayIcon(){ @@ -1100,7 +1106,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, table.row(); table.table(this::displayConsumption).growX(); - boolean displayFlow = (block.category == Category.distribution || block.category == Category.liquid) && Core.settings.getBool("flow") && block.displayFlow; + boolean displayFlow = (block.category == Category.distribution || block.category == Category.liquid) && block.displayFlow; if(displayFlow){ String ps = " " + StatUnit.perSecond.localized(); @@ -1254,9 +1260,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, /** Changes this building's team in a safe manner. */ public void changeTeam(Team next){ + Team last = this.team; indexer.removeIndex(tile); this.team = next; indexer.addIndex(tile); + Events.fire(teamChangeEvent.set(last, self())); } public boolean canPickup(){ @@ -1342,6 +1350,18 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, return tile.build == self() && !dead(); } + @MethodPriority(100) + @Override + public void heal(){ + indexer.notifyBuildHealed(self()); + } + + @MethodPriority(100) + @Override + public void heal(float amount){ + indexer.notifyBuildHealed(self()); + } + @Override public float hitSize(){ return tile.block().size * tilesize; diff --git a/core/src/mindustry/entities/comp/BulletComp.java b/core/src/mindustry/entities/comp/BulletComp.java index 839e0b0c44..86b779b82d 100644 --- a/core/src/mindustry/entities/comp/BulletComp.java +++ b/core/src/mindustry/entities/comp/BulletComp.java @@ -81,7 +81,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw } public boolean hasCollided(int id){ - return collided.size != 0 && !collided.contains(id); + return collided.size != 0 && collided.contains(id); } @Replace diff --git a/core/src/mindustry/entities/comp/PuddleComp.java b/core/src/mindustry/entities/comp/PuddleComp.java index 12f56fbaa4..38df428c41 100644 --- a/core/src/mindustry/entities/comp/PuddleComp.java +++ b/core/src/mindustry/entities/comp/PuddleComp.java @@ -1,5 +1,6 @@ package mindustry.entities.comp; +import arc.func.*; import arc.graphics.*; import arc.graphics.g2d.*; import arc.math.*; @@ -20,16 +21,29 @@ import static mindustry.entities.Puddles.*; @EntityDef(value = {Puddlec.class}, pooled = true) @Component(base = true) abstract class PuddleComp implements Posc, Puddlec, Drawc{ - private static final int maxGeneration = 2; private static final Rect rect = new Rect(), rect2 = new Rect(); private static int seeds; + private static Puddle paramPuddle; + private static Cons unitCons = unit -> { + if(unit.isGrounded() && !unit.hovering){ + unit.hitbox(rect2); + if(rect.overlaps(rect2)){ + unit.apply(paramPuddle.liquid.effect, 60 * 2); + + if(unit.vel.len2() > 0.1f * 0.1f){ + Fx.ripple.at(unit.x, unit.y, unit.type.rippleScale, paramPuddle.liquid.color); + } + } + } + }; + @Import int id; @Import float x, y; - transient float accepting, updateTime, lastRipple; + transient private boolean mismatch = false; + transient float accepting, updateTime, lastRipple = Time.time + Mathf.random(40f); float amount; - int generation; Tile tile; Liquid liquid; @@ -39,46 +53,45 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ @Override public void update(){ - //update code float addSpeed = accepting > 0 ? 3f : 0f; amount -= Time.delta * (1f - liquid.viscosity) / (5f + addSpeed); amount += accepting; accepting = 0f; - if(amount >= maxLiquid / 1.5f && generation < maxGeneration){ + if(amount >= maxLiquid / 1.5f){ float deposited = Math.min((amount - maxLiquid / 1.5f) / 4f, 0.3f) * Time.delta; + int targets = 0; for(Point2 point : Geometry.d4){ Tile other = world.tile(tile.x + point.x, tile.y + point.y); if(other != null && other.block() == Blocks.air){ - Puddles.deposit(other, tile, liquid, deposited, generation + 1); - amount -= deposited / 2f; //tweak to speed up/slow down Puddle propagation + targets ++; + Puddles.deposit(other, tile, liquid, deposited, false); } } + amount -= deposited * targets; } amount = Mathf.clamp(amount, 0, maxLiquid); if(amount <= 0f){ remove(); + return; + } + + if(Puddles.get(tile) != self()){ + mismatch = true; + remove(); + return; } //effects-only code if(amount >= maxLiquid / 2f && updateTime <= 0f){ - Units.nearby(rect.setSize(Mathf.clamp(amount / (maxLiquid / 1.5f)) * 10f).setCenter(x, y), unit -> { - if(unit.isGrounded() && !unit.hovering){ - unit.hitbox(rect2); - if(rect.overlaps(rect2)){ - unit.apply(liquid.effect, 60 * 2); + paramPuddle = self(); - if(unit.vel.len() > 0.1){ - Fx.ripple.at(unit.x, unit.y, unit.type.rippleScale, liquid.color); - } - } - } - }); + Units.nearby(rect.setSize(Mathf.clamp(amount / (maxLiquid / 1.5f)) * 10f).setCenter(x, y), unitCons); - if(liquid.temperature > 0.7f && (tile.build != null) && Mathf.chance(0.5)){ + if(liquid.temperature > 0.7f && tile.build != null && Mathf.chance(0.5)){ Fires.create(tile); } @@ -121,7 +134,9 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ @Override public void remove(){ - Puddles.remove(tile); + if(!mismatch){ + Puddles.remove(tile); + } } @Override diff --git a/core/src/mindustry/entities/comp/StatusComp.java b/core/src/mindustry/entities/comp/StatusComp.java index 70d1e38dcb..3c72200829 100644 --- a/core/src/mindustry/entities/comp/StatusComp.java +++ b/core/src/mindustry/entities/comp/StatusComp.java @@ -154,7 +154,7 @@ abstract class StatusComp implements Posc, Flyingc{ public void draw(){ for(StatusEntry e : statuses){ - e.effect.draw(self()); + e.effect.draw(self(), e.time); } } diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java index cfd1554ecc..ae4001d25f 100644 --- a/core/src/mindustry/entities/comp/UnitComp.java +++ b/core/src/mindustry/entities/comp/UnitComp.java @@ -59,6 +59,14 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I vel.approachDelta(vector, type.accel * realSpeed()); } + public void rotateMove(Vec2 vec){ + moveAt(Tmp.v2.trns(rotation, vec.len())); + + if(!vec.isZero()){ + rotation = Angles.moveToward(rotation, vec.angle(), type.rotateSpeed * Math.max(Time.delta, 1)); + } + } + public void aimLook(Position pos){ aim(pos); lookAt(pos); @@ -126,6 +134,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I if(isBuilding()){ return state.rules.infiniteResources ? Float.MAX_VALUE : Math.max(type.clipSize, type.region.width) + buildingRange + tilesize*4f; } + if(mining()){ + return type.clipSize + type.miningRange; + } return type.clipSize; } diff --git a/core/src/mindustry/entities/units/AIController.java b/core/src/mindustry/entities/units/AIController.java index e4d2bfaf2b..0af7565424 100644 --- a/core/src/mindustry/entities/units/AIController.java +++ b/core/src/mindustry/entities/units/AIController.java @@ -6,6 +6,7 @@ import arc.util.*; import mindustry.*; import mindustry.ai.*; import mindustry.entities.*; +import mindustry.game.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; @@ -79,7 +80,6 @@ public class AIController implements UnitController{ return Units.invalidateTarget(target, unit.team, unit.x, unit.y); } - protected void pathfind(int pathTarget){ int costType = unit.pathType(); @@ -97,7 +97,7 @@ public class AIController implements UnitController{ boolean ret = retarget(); if(ret){ - target = findTarget(unit.x, unit.y, unit.range(), unit.type.targetAir, unit.type.targetGround); + target = findMainTarget(unit.x, unit.y, unit.range(), unit.type.targetAir, unit.type.targetGround); } if(invalid(target)){ @@ -155,6 +155,7 @@ public class AIController implements UnitController{ } protected Teamc targetFlag(float x, float y, BlockFlag flag, boolean enemy){ + if(unit.team == Team.derelict) return null; Tile target = Geometry.findClosest(x, y, enemy ? indexer.getEnemy(unit.team, flag) : indexer.getAllied(unit.team, flag)); return target == null ? null : target.build; } @@ -167,6 +168,10 @@ public class AIController implements UnitController{ return timer.get(timerTarget, target == null ? 40 : 90); } + protected Teamc findMainTarget(float x, float y, float range, boolean air, boolean ground){ + return findTarget(x, y, range, air, ground); + } + protected Teamc findTarget(float x, float y, float range, boolean air, boolean ground){ return target(x, y, range, air, ground); } diff --git a/core/src/mindustry/game/EventType.java b/core/src/mindustry/game/EventType.java index 9d590de52c..5ff6a6f264 100644 --- a/core/src/mindustry/game/EventType.java +++ b/core/src/mindustry/game/EventType.java @@ -284,6 +284,21 @@ public class EventType{ } } + /** + * Called after a building's team changes. + * Event object is reused, do not nest! + * */ + public static class BuildTeamChangeEvent{ + public Team previous; + public Building build; + + public BuildTeamChangeEvent set(Team previous, Building build){ + this.build = build; + this.previous = previous; + return this; + } + } + /** Called when a core block is placed/removed or its team is changed. */ public static class CoreChangeEvent{ public CoreBuild core; diff --git a/core/src/mindustry/game/Gamemode.java b/core/src/mindustry/game/Gamemode.java index 43425914c4..6e9dffc06e 100644 --- a/core/src/mindustry/game/Gamemode.java +++ b/core/src/mindustry/game/Gamemode.java @@ -23,7 +23,7 @@ public enum Gamemode{ rules.waves = true; rules.waveTimer = true; - rules.waveSpacing = 60f * Time.toMinutes; + rules.waveSpacing = 2f * Time.toMinutes; rules.teams.get(rules.waveTeam).infiniteResources = true; }, map -> map.teams.contains(state.rules.waveTeam.id)), pvp(rules -> { diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java index f66dd658ea..ad70638368 100644 --- a/core/src/mindustry/game/Rules.java +++ b/core/src/mindustry/game/Rules.java @@ -50,7 +50,7 @@ public class Rules{ public boolean unitAmmo = false; /** Whether cores add to unit limit */ public boolean unitCapVariable = true; - /** How fast unit pads build units. */ + /** How fast unit factories build units. */ public float unitBuildSpeedMultiplier = 1f; /** How much damage any other units deal. */ public float unitDamageMultiplier = 1f; @@ -94,6 +94,8 @@ public class Rules{ public Seq weather = new Seq<>(1); /** Blocks that cannot be placed. */ public ObjectSet bannedBlocks = new ObjectSet<>(); + /** Units that cannot be built. */ + public ObjectSet bannedUnits = new ObjectSet<>(); /** Reveals blocks normally hidden by build visibility. */ public ObjectSet revealedBlocks = new ObjectSet<>(); /** Unlocked content names. Only used in multiplayer when the campaign is enabled. */ @@ -109,6 +111,8 @@ public class Rules{ public Team defaultTeam = Team.sharded; /** team of the enemy in waves/sectors. */ public Team waveTeam = Team.crux; + /** color of clouds that is displayed when the player is landing */ + public Color cloudColor = new Color(0f, 0f, 0f, 0f); /** name of the custom mode that this ruleset describes, or null. */ public @Nullable String modeName; /** Whether cores incinerate items when full, just like in the campaign. */ diff --git a/core/src/mindustry/game/Schematics.java b/core/src/mindustry/game/Schematics.java index f21381802c..0a91c9d1b3 100644 --- a/core/src/mindustry/game/Schematics.java +++ b/core/src/mindustry/game/Schematics.java @@ -114,6 +114,7 @@ public class Schematics implements Loadable{ target.tiles.addAll(newSchematic.tiles); target.width = newSchematic.width; target.height = newSchematic.height; + newSchematic.labels = target.labels; newSchematic.tags.putAll(target.tags); newSchematic.file = target.file; @@ -432,6 +433,11 @@ public class Schematics implements Loadable{ if(seq.contains(t -> !t.block().alwaysReplace && !t.synthetic())){ return; } + for(var t : seq){ + if(t.block() != Blocks.air){ + t.remove(); + } + } } tile.setBlock(st.block, team, st.rotation); diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index 4d2b20b9cc..80859f48bc 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -1,5 +1,6 @@ package mindustry.game; +import arc.func.*; import arc.math.*; import arc.struct.*; import arc.util.*; @@ -21,6 +22,7 @@ public class SectorInfo{ private static final int valueWindow = 60; /** refresh period of export in ticks */ private static final float refreshPeriod = 60; + private static float returnf; /** Core input statistics. */ public ObjectMap production = new ObjectMap<>(); @@ -76,6 +78,8 @@ public class SectorInfo{ public int waveVersion = -1; /** Whether this sector was indicated to the player or not. */ public boolean shown = false; + /** Temporary seq for last imported items. Do not use. */ + public transient ItemSeq lastImported = new ItemSeq(); /** Special variables for simulation. */ public float sumHealth, sumRps, sumDps, waveHealthBase, waveHealthSlope, waveDpsBase, waveDpsSlope, bossHealth, bossDps, curEnemyHealth, curEnemyDps; @@ -265,23 +269,29 @@ public class SectorInfo{ return map; } + public boolean anyExports(){ + if(export.size == 0) return false; + returnf = 0f; + export.each((i, e) -> returnf += e.mean); + return returnf >= 0.01f; + } + /** @return a newly allocated map with import statistics. Use sparingly. */ //TODO this can be a float map - public ObjectMap importStats(){ + public ObjectMap importStats(Planet planet){ ObjectMap imports = new ObjectMap<>(); - //for all sectors on all planets that have bases and export to this sector - for(Planet planet : content.planets()){ - for(Sector sector : planet.sectors){ - Sector dest = sector.info.getRealDestination(); - if(sector.hasBase() && sector.info != this && dest != null && dest.info == this){ - //add their exports to our imports - sector.info.export.each((item, stat) -> { - imports.get(item, ExportStat::new).mean += stat.mean; - }); - } + eachImport(planet, sector -> sector.info.export.each((item, stat) -> imports.get(item, ExportStat::new).mean += stat.mean)); + return imports; + } + + /** Iterates through every sector this one imports from. */ + public void eachImport(Planet planet, Cons cons){ + for(Sector sector : planet.sectors){ + Sector dest = sector.info.getRealDestination(); + if(sector.hasBase() && sector.info != this && dest != null && dest.info == this){ + cons.get(sector); } } - return imports; } public static class ExportStat{ diff --git a/core/src/mindustry/game/Team.java b/core/src/mindustry/game/Team.java index e8141d6063..53366df21b 100644 --- a/core/src/mindustry/game/Team.java +++ b/core/src/mindustry/game/Team.java @@ -17,6 +17,8 @@ public class Team implements Comparable{ public final int id; public final Color color; public final Color[] palette; + public final int[] palettei = new int[3]; + public String emoji = ""; public boolean hasPalette; public String name; @@ -31,9 +33,9 @@ public class Team implements Comparable{ Color.valueOf("ffd37f"), Color.valueOf("eab678"), Color.valueOf("d4816b")), crux = new Team(2, "crux", Color.valueOf("f25555"), Color.valueOf("fc8e6c"), Color.valueOf("f25555"), Color.valueOf("a04553")), - green = new Team(3, "green", Color.valueOf("54d67d")), - purple = new Team(4, "purple", Color.valueOf("995bb0")), - blue = new Team(5, "blue", Color.valueOf("5a4deb")); + green = new Team(3, "green", Color.valueOf("54d67d"), Color.valueOf("96f58c"), Color.valueOf("54d67d"), Color.valueOf("28785c")), + purple = new Team(4, "purple", Color.valueOf("995bb0"), Color.valueOf("f08dd5"), Color.valueOf("995bb0"), Color.valueOf("312c63")), + blue = new Team(5, "blue", Color.valueOf("554deb"), Color.valueOf("80aaff"), Color.valueOf("554deb"), Color.valueOf("3f207d")); static{ Mathf.rand.setSeed(8); @@ -60,6 +62,10 @@ public class Team implements Comparable{ palette[0] = color; palette[1] = color.cpy().mul(0.75f); palette[2] = color.cpy().mul(0.5f); + + for(int i = 0; i < 3; i++){ + palettei[i] = palette[i].rgba(); + } } /** Specifies a 3-color team palette. */ @@ -69,6 +75,9 @@ public class Team implements Comparable{ palette[0] = pal1; palette[1] = pal2; palette[2] = pal3; + for(int i = 0; i < 3; i++){ + palettei[i] = palette[i].rgba(); + } hasPalette = true; } @@ -96,6 +105,11 @@ public class Team implements Comparable{ return state.teams.isActive(this); } + /** @return whether this team is solely comprised of AI, with no players. */ + public boolean isAI(){ + return state.rules.waves && this == state.rules.waveTeam; + } + public boolean isEnemy(Team other){ return this != other; } diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java index e89b4b7ad0..f12250980c 100644 --- a/core/src/mindustry/game/Universe.java +++ b/core/src/mindustry/game/Universe.java @@ -148,8 +148,35 @@ public class Universe{ //update relevant sectors for(Planet planet : content.planets()){ + + //first pass: clear import stats for(Sector sector : planet.sectors){ - if(sector.hasSave() && sector.hasBase()){ + if(sector.hasBase() && !sector.isBeingPlayed()){ + sector.info.lastImported.clear(); + } + } + + //second pass: update export & import statistics + for(Sector sector : planet.sectors){ + if(sector.hasBase() && !sector.isBeingPlayed()){ + + //export to another sector + if(sector.info.destination != null){ + Sector to = sector.info.destination; + if(to.hasBase()){ + ItemSeq items = new ItemSeq(); + //calculated exported items to this sector + sector.info.export.each((item, stat) -> items.add(item, (int)(stat.mean * newSecondsPassed * sector.getProductionScale()))); + to.addItems(items); + to.info.lastImported.add(items); + } + } + } + } + + //third pass: everything else + for(Sector sector : planet.sectors){ + if(sector.hasBase()){ //if it is being attacked, capture time is 0; otherwise, increment the timer if(sector.isAttacked()){ @@ -199,26 +226,16 @@ public class Universe{ float scl = sector.getProductionScale(); - //export to another sector - if(sector.info.destination != null){ - Sector to = sector.info.destination; - if(to.hasBase()){ - ItemSeq items = new ItemSeq(); - //calculated exported items to this sector - sector.info.export.each((item, stat) -> items.add(item, (int)(stat.mean * newSecondsPassed * scl))); - to.addItems(items); - } - } + //add production, making sure that it's capped + sector.info.production.each((item, stat) -> sector.info.items.add(item, Math.min((int)(stat.mean * newSecondsPassed * scl), sector.info.storageCapacity - sector.info.items.get(item)))); - sector.info.export.each((item, amount) -> { - if(sector.info.items.get(item) <= 0 && sector.info.production.get(item, ExportStat::new).mean < 0){ - //disable export when production is negative. - sector.info.export.get(item).mean = 0f; + sector.info.export.each((item, stat) -> { + if(sector.info.items.get(item) <= 0 && sector.info.production.get(item, ExportStat::new).mean < 0 && stat.mean > 0){ + //cap export by import when production is negative. + stat.mean = Math.min(sector.info.lastImported.get(item) / (float)newSecondsPassed, stat.mean); } }); - //add production, making sure that it's capped - sector.info.production.each((item, stat) -> sector.info.items.add(item, Math.min((int)(stat.mean * newSecondsPassed * scl), sector.info.storageCapacity - sector.info.items.get(item)))); //prevent negative values with unloaders sector.info.items.checkNegative(); diff --git a/core/src/mindustry/graphics/FloorRenderer.java b/core/src/mindustry/graphics/FloorRenderer.java index 1e2247f71e..836481b92c 100644 --- a/core/src/mindustry/graphics/FloorRenderer.java +++ b/core/src/mindustry/graphics/FloorRenderer.java @@ -281,10 +281,13 @@ public class FloorRenderer{ for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize && tilex < world.width(); tilex++){ for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize && tiley < world.height(); tiley++){ Tile tile = world.rawTile(tilex, tiley); + boolean wall = tile.block().cacheLayer != CacheLayer.normal; - if(tile.block().cacheLayer != CacheLayer.normal){ + if(wall){ used.add(tile.block().cacheLayer); - }else{ + } + + if(!wall || world.isAccessible(tilex, tiley)){ used.add(tile.floor().cacheLayer); } } diff --git a/core/src/mindustry/graphics/MenuRenderer.java b/core/src/mindustry/graphics/MenuRenderer.java index 3bb562bde1..1cd431c7e8 100644 --- a/core/src/mindustry/graphics/MenuRenderer.java +++ b/core/src/mindustry/graphics/MenuRenderer.java @@ -29,7 +29,7 @@ public class MenuRenderer implements Disposable{ private float time = 0f; private float flyerRot = 45f; private int flyers = Mathf.chance(0.2) ? Mathf.random(35) : Mathf.random(15); - private UnitType flyerType = content.units().select(u -> u.hitSize <= 20f && u.flying && u.region.found()).random(); + private UnitType flyerType = content.units().select(u -> u.hitSize <= 20f && u.flying && u.onTitleScreen && u.region.found()).random(); public MenuRenderer(){ Time.mark(); diff --git a/core/src/mindustry/graphics/MinimapRenderer.java b/core/src/mindustry/graphics/MinimapRenderer.java index 1a3b7dc7f8..a66d388357 100644 --- a/core/src/mindustry/graphics/MinimapRenderer.java +++ b/core/src/mindustry/graphics/MinimapRenderer.java @@ -33,13 +33,14 @@ public class MinimapRenderer{ updateAll(); }); - //make sure to call on the graphics thread Events.on(TileChangeEvent.class, event -> { //TODO don't update when the minimap is off? if(!ui.editor.isShown()){ update(event.tile); } }); + + Events.on(BuildTeamChangeEvent.class, event -> update(event.build.tile)); } public Pixmap getPixmap(){ diff --git a/core/src/mindustry/graphics/g3d/PlanetRenderer.java b/core/src/mindustry/graphics/g3d/PlanetRenderer.java index 20a6483e01..c5c349cc5c 100644 --- a/core/src/mindustry/graphics/g3d/PlanetRenderer.java +++ b/core/src/mindustry/graphics/g3d/PlanetRenderer.java @@ -217,8 +217,11 @@ public class PlanetRenderer implements Disposable{ } public void drawArc(Planet planet, Vec3 a, Vec3 b, Color from, Color to, float length, float timeScale, int pointCount){ + //increase curve height when on opposite side of planet, so it doesn't tunnel through + float dot = 1f - (Tmp.v32.set(a).nor().dot(Tmp.v33.set(b).nor()) + 1f)/2f; + Vec3 avg = Tmp.v31.set(b).add(a).scl(0.5f); - avg.setLength(planet.radius*(1f+length)); + avg.setLength(planet.radius*(1f+length) + dot * 1.35f); points.clear(); points.addAll(Tmp.v33.set(b).setLength(outlineRad), Tmp.v31, Tmp.v34.set(a).setLength(outlineRad)); diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java index 6506db2d34..efe122e893 100644 --- a/core/src/mindustry/input/DesktopInput.java +++ b/core/src/mindustry/input/DesktopInput.java @@ -43,7 +43,7 @@ public class DesktopInput extends InputHandler{ /** Whether player is currently deleting removal requests. */ public boolean deleting = false, shouldShoot = false, panning = false; /** Mouse pan speed. */ - public float panScale = 0.005f, panSpeed = 4.5f, panBoostSpeed = 11f; + public float panScale = 0.005f, panSpeed = 4.5f, panBoostSpeed = 15f; /** Delta time between consecutive clicks. */ public long selectMillis = 0; /** Previously selected tile. */ @@ -204,7 +204,6 @@ public class DesktopInput extends InputHandler{ panning = false; } - //TODO awful UI state checking code if(((player.dead() || state.isPaused()) && !ui.chatfrag.shown()) && !scene.hasField() && !scene.hasDialog()){ if(input.keyDown(Binding.mouse_move)){ panCam = true; @@ -237,7 +236,7 @@ public class DesktopInput extends InputHandler{ } } - if(!player.dead() && !state.isPaused() && !scene.hasField()){ + if(!player.dead() && !state.isPaused() && !scene.hasField() && !renderer.isCutscene()){ updateMovement(player.unit()); if(Core.input.keyTap(Binding.respawn)){ @@ -646,6 +645,8 @@ public class DesktopInput extends InputHandler{ if(omni){ unit.moveAt(movement); }else{ + unit.rotateMove(movement); + unit.moveAt(Tmp.v2.trns(unit.rotation, movement.len())); //problem: actual unit rotation is controlled by velocity, but velocity is 1) unpredictable and 2) can be set to 0 diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index bc385af592..f97385122c 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -230,7 +230,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ Unit unit = player.unit(); - if(build != null && build.team == unit.team + if(build != null && state.teams.canInteract(unit.team, build.team) && unit.within(build, tilesize * build.block.size * 1.2f + tilesize * 5f)){ //pick up block's payload @@ -356,7 +356,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ Events.fire(new TapEvent(player, tile)); } - @Remote(targets = Loc.both, called = Loc.both, forward = true) + @Remote(targets = Loc.both, called = Loc.server, forward = true) public static void buildingControlSelect(Player player, Building build){ if(player == null || build == null || player.dead()) return; @@ -510,7 +510,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ }else{ Building build = world.buildWorld(pay.x(), pay.y()); - if(build != null && build.team == unit.team){ + if(build != null && state.teams.canInteract(unit.team, build.team)){ Call.requestBuildPayload(player, build); } } diff --git a/core/src/mindustry/input/MobileInput.java b/core/src/mindustry/input/MobileInput.java index c97e92455c..2480cad5ab 100644 --- a/core/src/mindustry/input/MobileInput.java +++ b/core/src/mindustry/input/MobileInput.java @@ -681,7 +681,7 @@ public class MobileInput extends InputHandler implements GestureListener{ } } - if(!player.dead() && !state.isPaused()){ + if(!player.dead() && !state.isPaused() && !renderer.isCutscene()){ updateMovement(player.unit()); } @@ -822,7 +822,7 @@ public class MobileInput extends InputHandler implements GestureListener{ shiftDeltaX %= tilesize; shiftDeltaY %= tilesize; } - }else if(!renderer.isLanding()){ + }else{ //pan player Core.camera.position.x -= deltaX; Core.camera.position.y -= deltaY; @@ -922,10 +922,7 @@ public class MobileInput extends InputHandler implements GestureListener{ if(omni){ unit.moveAt(movement); }else{ - unit.moveAt(Tmp.v2.trns(unit.rotation, movement.len())); - if(!movement.isZero()){ - unit.rotation = Angles.moveToward(unit.rotation, movement.angle(), unit.type.rotateSpeed * Math.max(Time.delta, 1)); - } + unit.rotateMove(movement); } //update shooting if not building + not mining diff --git a/core/src/mindustry/input/Placement.java b/core/src/mindustry/input/Placement.java index f4afb96683..55044dc8e0 100644 --- a/core/src/mindustry/input/Placement.java +++ b/core/src/mindustry/input/Placement.java @@ -108,7 +108,13 @@ public class Placement{ points.addAll(result); } + public static boolean isSidePlace(Seq plans){ + return plans.size > 1 && Mathf.mod(Tile.relativeTo(plans.first().x, plans.first().y, plans.get(1).x, plans.get(1).y) - plans.first().rotation, 2) == 1; + } + public static void calculateBridges(Seq plans, ItemBridge bridge){ + if(isSidePlace(plans)) return; + //check for orthogonal placement + unlocked state if(!(plans.first().x == plans.peek().x || plans.first().y == plans.peek().y) || !bridge.unlockedNow()){ return; @@ -170,6 +176,8 @@ public class Placement{ } public static void calculateDuctBridges(Seq plans, DuctBridge bridge){ + if(isSidePlace(plans)) return; + //check for orthogonal placement + unlocked state if(!(plans.first().x == plans.peek().x || plans.first().y == plans.peek().y) || !bridge.unlockedNow()){ return; @@ -180,7 +188,6 @@ public class Placement{ var result = plans1.clear(); var team = player.team(); - var rot = plans.first().rotation; outer: for(int i = 0; i < plans.size;){ diff --git a/core/src/mindustry/io/JsonIO.java b/core/src/mindustry/io/JsonIO.java index 9f51b32cb0..3e6beb26e8 100644 --- a/core/src/mindustry/io/JsonIO.java +++ b/core/src/mindustry/io/JsonIO.java @@ -214,7 +214,8 @@ public class JsonIO{ String str = jsonData.asString(); Item item = Vars.content.getByName(ContentType.item, str); Liquid liquid = Vars.content.getByName(ContentType.liquid, str); - return item != null ? item : liquid; + Block block = Vars.content.getByName(ContentType.block, str); + return item != null ? item : liquid == null ? block : liquid; } }); diff --git a/core/src/mindustry/io/SaveFileReader.java b/core/src/mindustry/io/SaveFileReader.java index 30b2a48d47..fe87b8292c 100644 --- a/core/src/mindustry/io/SaveFileReader.java +++ b/core/src/mindustry/io/SaveFileReader.java @@ -50,7 +50,11 @@ public abstract class SaveFileReader{ "holostone-wall", "dacite-wall", "rock", "boulder", "snowrock", "snow-boulder", - "cliffs", "stone-wall", + "cliffs", "stone-wall", + "craters", "crater-stone", + "deepwater", "deep-water", + "water", "shallow-water", + "slag", "molten-slag", "cryofluidmixer", "cryofluid-mixer", "block-forge", "constructor" diff --git a/core/src/mindustry/io/SaveVersion.java b/core/src/mindustry/io/SaveVersion.java index 90fd35a59d..527742d836 100644 --- a/core/src/mindustry/io/SaveVersion.java +++ b/core/src/mindustry/io/SaveVersion.java @@ -363,7 +363,7 @@ public abstract class SaveVersion extends SaveFileReader{ int amount = stream.readInt(); for(int j = 0; j < amount; j++){ readChunk(stream, true, in -> { - byte typeid = in.readByte(); + int typeid = in.readUnsignedByte(); if(mapping[typeid] == null){ in.skipBytes(lastRegionLength - 1); return; @@ -408,7 +408,8 @@ public abstract class SaveVersion extends SaveFileReader{ for(int j = 0; j < total; j++){ String name = stream.readUTF(); - map[type.ordinal()][j] = content.getByName(type, fallback.get(name, name)); + //fallback only for blocks + map[type.ordinal()][j] = content.getByName(type, type == ContentType.block ? fallback.get(name, name) : name); } } diff --git a/core/src/mindustry/maps/Maps.java b/core/src/mindustry/maps/Maps.java index 613067f61f..b6a2f1fc1e 100644 --- a/core/src/mindustry/maps/Maps.java +++ b/core/src/mindustry/maps/Maps.java @@ -420,6 +420,8 @@ public class Maps{ writeCache(map); }catch(Exception e){ e.printStackTrace(); + }finally{ + pix.dispose(); } }); }catch(Exception e){ diff --git a/core/src/mindustry/maps/SectorDamage.java b/core/src/mindustry/maps/SectorDamage.java index 786074c3dd..5ee6e1f15a 100644 --- a/core/src/mindustry/maps/SectorDamage.java +++ b/core/src/mindustry/maps/SectorDamage.java @@ -496,7 +496,7 @@ public class SectorDamage{ other.build.addPlan(false); other.remove(); }else{ - indexer.notifyTileDamaged(other.build); + indexer.notifyBuildDamaged(other.build); } }else if(other.solid() && !other.synthetic()){ //skip damage propagation through solid blocks diff --git a/core/src/mindustry/mod/ClassMap.java b/core/src/mindustry/mod/ClassMap.java index 169933ce8c..73886727dd 100644 --- a/core/src/mindustry/mod/ClassMap.java +++ b/core/src/mindustry/mod/ClassMap.java @@ -35,6 +35,7 @@ public class ClassMap{ classes.put("BulletType", mindustry.entities.bullet.BulletType.class); classes.put("ContinuousLaserBulletType", mindustry.entities.bullet.ContinuousLaserBulletType.class); classes.put("EmpBulletType", mindustry.entities.bullet.EmpBulletType.class); + classes.put("FireBulletType", mindustry.entities.bullet.FireBulletType.class); classes.put("FlakBulletType", mindustry.entities.bullet.FlakBulletType.class); classes.put("LaserBoltBulletType", mindustry.entities.bullet.LaserBoltBulletType.class); classes.put("LaserBulletType", mindustry.entities.bullet.LaserBulletType.class); @@ -56,9 +57,6 @@ public class ClassMap{ classes.put("Research", mindustry.game.Objectives.Research.class); classes.put("SectorComplete", mindustry.game.Objectives.SectorComplete.class); classes.put("AmmoType", mindustry.type.AmmoType.class); - classes.put("AmmoTypes", mindustry.type.AmmoTypes.class); - classes.put("ItemAmmoType", mindustry.type.AmmoTypes.ItemAmmoType.class); - classes.put("PowerAmmoType", mindustry.type.AmmoTypes.PowerAmmoType.class); classes.put("Category", mindustry.type.Category.class); classes.put("ErrorContent", mindustry.type.ErrorContent.class); classes.put("Item", mindustry.type.Item.class); @@ -78,6 +76,8 @@ public class ClassMap{ classes.put("Weapon", mindustry.type.Weapon.class); classes.put("Weather", mindustry.type.Weather.class); classes.put("WeatherEntry", mindustry.type.Weather.WeatherEntry.class); + classes.put("ItemAmmoType", mindustry.type.ammo.ItemAmmoType.class); + classes.put("PowerAmmoType", mindustry.type.ammo.PowerAmmoType.class); classes.put("PointDefenseWeapon", mindustry.type.weapons.PointDefenseWeapon.class); classes.put("RepairBeamWeapon", mindustry.type.weapons.RepairBeamWeapon.class); classes.put("HealBeamMount", mindustry.type.weapons.RepairBeamWeapon.HealBeamMount.class); @@ -145,7 +145,7 @@ public class ClassMap{ classes.put("DuctBridge", mindustry.world.blocks.distribution.DuctBridge.class); classes.put("DuctBridgeBuild", mindustry.world.blocks.distribution.DuctBridge.DuctBridgeBuild.class); classes.put("DuctRouter", mindustry.world.blocks.distribution.DuctRouter.class); - classes.put("DuctBuild", mindustry.world.blocks.distribution.DuctRouter.DuctBuild.class); + classes.put("DuctRouterBuild", mindustry.world.blocks.distribution.DuctRouter.DuctRouterBuild.class); classes.put("ExtendingItemBridge", mindustry.world.blocks.distribution.ExtendingItemBridge.class); classes.put("ExtendingItemBridgeBuild", mindustry.world.blocks.distribution.ExtendingItemBridge.ExtendingItemBridgeBuild.class); classes.put("ItemBridge", mindustry.world.blocks.distribution.ItemBridge.class); @@ -330,8 +330,6 @@ public class ClassMap{ classes.put("ReconstructorBuild", mindustry.world.blocks.units.Reconstructor.ReconstructorBuild.class); classes.put("RepairPoint", mindustry.world.blocks.units.RepairPoint.class); classes.put("RepairPointBuild", mindustry.world.blocks.units.RepairPoint.RepairPointBuild.class); - classes.put("ResupplyPoint", mindustry.world.blocks.units.ResupplyPoint.class); - classes.put("ResupplyPointBuild", mindustry.world.blocks.units.ResupplyPoint.ResupplyPointBuild.class); classes.put("UnitBlock", mindustry.world.blocks.units.UnitBlock.class); classes.put("UnitBuild", mindustry.world.blocks.units.UnitBlock.UnitBuild.class); classes.put("UnitFactory", mindustry.world.blocks.units.UnitFactory.class); diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java index 9c8c7f3b3a..5c4d48cecd 100644 --- a/core/src/mindustry/mod/ContentParser.java +++ b/core/src/mindustry/mod/ContentParser.java @@ -29,6 +29,7 @@ import mindustry.gen.*; import mindustry.graphics.*; import mindustry.mod.Mods.*; import mindustry.type.*; +import mindustry.type.ammo.*; import mindustry.type.weather.*; import mindustry.world.*; import mindustry.world.blocks.units.*; @@ -95,6 +96,19 @@ public class ContentParser{ readFields(result, data); return result; }); + put(AmmoType.class, (type, data) -> { + //string -> item + //if liquid ammo support is added, this should scan for liquids as well + if(data.isString()) return find(ContentType.item, data.asString()); + //number -> power + if(data.isNumber()) return new PowerAmmoType(data.asFloat()); + + var bc = resolve(data.getString("type", ""), ItemAmmoType.class); + data.remove("type"); + AmmoType result = make(bc); + readFields(result, data); + return result; + }); put(DrawBlock.class, (type, data) -> { if(data.isString()){ //try to instantiate @@ -746,7 +760,7 @@ public class ContentParser{ /** Tries to resolve a class from the class type map. */ Class resolve(String base, Class def){ //no base class specified - if(base.isEmpty() && def != null) return def; + if((base == null || base.isEmpty()) && def != null) return def; //return mapped class if found in the global map var out = ClassMap.classes.get(!base.isEmpty() && Character.isLowerCase(base.charAt(0)) ? Strings.capitalize(base) : base); diff --git a/core/src/mindustry/mod/Mods.java b/core/src/mindustry/mod/Mods.java index 693ac2222a..43845886d7 100644 --- a/core/src/mindustry/mod/Mods.java +++ b/core/src/mindustry/mod/Mods.java @@ -626,7 +626,7 @@ public class Mods implements Loadable{ try{ //this binds the content but does not load it entirely Content loaded = parser.parse(l.mod, l.file.nameWithoutExtension(), l.file.readString("UTF-8"), l.file, l.type); - Log.debug("[@] Loaded '@'.", l.mod.meta.name, (loaded instanceof UnlockableContent ? ((UnlockableContent)loaded).localizedName : loaded)); + Log.debug("[@] Loaded '@'.", l.mod.meta.name, (loaded instanceof UnlockableContent u ? u.localizedName : loaded)); }catch(Throwable e){ if(current != content.getLastAdded() && content.getLastAdded() != null){ parser.markError(content.getLastAdded(), l.mod, l.file, e); @@ -723,7 +723,7 @@ public class Mods implements Loadable{ if(!metaf.exists()){ Log.warn("Mod @ doesn't have a '[mod/plugin].[h]json' file, skipping.", sourceFile); - throw new IllegalArgumentException("Invalid file: No mod.json found."); + throw new ModLoadException("Invalid file: No mod.json found."); } ModMeta meta = json.fromJson(ModMeta.class, Jval.read(metaf.readString()).toString(Jformat.plain)); @@ -750,7 +750,7 @@ public class Mods implements Loadable{ //unload mods.remove(other); }else{ - throw new IllegalArgumentException("A mod with the name '" + baseName + "' is already imported."); + throw new ModLoadException("A mod with the name '" + baseName + "' is already imported."); } } @@ -779,12 +779,23 @@ public class Mods implements Loadable{ (meta.getMinMajor() >= 105 || headless) ){ if(ios){ - throw new IllegalArgumentException("Java class mods are not supported on iOS."); + throw new ModLoadException("Java class mods are not supported on iOS."); } loader = platform.loadJar(sourceFile, mainLoader); mainLoader.addChild(loader); Class main = Class.forName(mainClass, true, loader); + + //detect mods that incorrectly package mindustry in the jar + if((main.getSuperclass().getName().equals("mindustry.mod.Plugin") || main.getSuperclass().getName().equals("mindustry.mod.Mod")) && + main.getSuperclass().getClassLoader() != Mod.class.getClassLoader()){ + throw new ModLoadException( + "This mod/plugin has loaded Mindustry dependencies from its own class loader. " + + "You are incorrectly including Mindustry dependencies in the mod JAR - " + + "make sure Mindustry is declared as `compileOnly` in Gradle, and that the JAR is created with `runtimeClasspath`!" + ); + } + metas.put(main, meta); mainMod = (Mod)main.getDeclaredConstructor().newInstance(); }else{ @@ -1017,6 +1028,12 @@ public class Mods implements Loadable{ } } + public static class ModLoadException extends RuntimeException{ + public ModLoadException(String message){ + super(message); + } + } + public enum ModState{ enabled, contentErrors, diff --git a/core/src/mindustry/net/CrashSender.java b/core/src/mindustry/net/CrashSender.java index 1f3720c8ac..75e1b5b2f9 100644 --- a/core/src/mindustry/net/CrashSender.java +++ b/core/src/mindustry/net/CrashSender.java @@ -6,19 +6,14 @@ import arc.func.*; import arc.struct.*; import arc.util.*; import arc.util.io.*; -import arc.util.serialization.*; -import arc.util.serialization.JsonValue.*; -import arc.util.serialization.JsonWriter.*; import mindustry.*; import mindustry.core.*; -import mindustry.gen.*; import java.io.*; import java.text.*; import java.util.*; import static arc.Core.*; -import static mindustry.Vars.net; import static mindustry.Vars.*; public class CrashSender{ @@ -126,6 +121,9 @@ public class CrashSender{ }catch(Throwable ignored){ } + //disabled until further notice. + /* + JsonValue value = new JsonValue(ValueType.object); boolean fn = netActive, fs = netServer; @@ -144,7 +142,7 @@ public class CrashSender{ ex(() -> value.addChild("trace", new JsonValue(parseException(exception)))); ex(() -> value.addChild("javaVersion", new JsonValue(OS.javaVersion))); ex(() -> value.addChild("javaArch", new JsonValue(OS.osArchBits))); - + Log.info("Sending crash report."); //post to crash report URL, exit code indicates send success @@ -154,7 +152,7 @@ public class CrashSender{ }).block(r -> { Log.info("Crash sent successfully."); System.exit(1); - }); + });*/ ret(); }catch(Throwable death){ diff --git a/core/src/mindustry/net/Net.java b/core/src/mindustry/net/Net.java index fe2c4cc12e..0dc711ea3d 100644 --- a/core/src/mindustry/net/Net.java +++ b/core/src/mindustry/net/Net.java @@ -96,7 +96,7 @@ public class Net{ String type = t.getClass().toString().toLowerCase(); boolean isError = false; - if(e instanceof BufferUnderflowException || e instanceof BufferOverflowException){ + if(e instanceof BufferUnderflowException || e instanceof BufferOverflowException || e.getCause() instanceof EOFException){ error = Core.bundle.get("error.io"); }else if(error.equals("mismatch") || e instanceof LZ4Exception || (e instanceof IndexOutOfBoundsException && e.getStackTrace()[0].getClassName().contains("java.nio"))){ error = Core.bundle.get("error.mismatch"); diff --git a/core/src/mindustry/type/AmmoType.java b/core/src/mindustry/type/AmmoType.java index afe0a9818a..78e89fd0d4 100644 --- a/core/src/mindustry/type/AmmoType.java +++ b/core/src/mindustry/type/AmmoType.java @@ -1,28 +1,12 @@ package mindustry.type; import arc.graphics.*; -import mindustry.ctype.*; import mindustry.gen.*; -import mindustry.graphics.*; /** Type of ammo that a unit uses. */ -public class AmmoType extends Content{ - public String icon = Iconc.itemCopper + ""; - public Color color = Pal.ammo; - public Color barColor = Pal.ammo; - - public AmmoType(char icon, Color color){ - this.icon = icon + ""; - this.color = color; - } - - public AmmoType(){ - } - - public void resupply(Unit unit){} - - @Override - public ContentType getContentType(){ - return ContentType.ammo; - } +public interface AmmoType{ + String icon(); + Color color(); + Color barColor(); + void resupply(Unit unit); } diff --git a/core/src/mindustry/type/AmmoTypes.java b/core/src/mindustry/type/AmmoTypes.java deleted file mode 100644 index 761bcbc8d0..0000000000 --- a/core/src/mindustry/type/AmmoTypes.java +++ /dev/null @@ -1,85 +0,0 @@ -package mindustry.type; - -import mindustry.*; -import mindustry.content.*; -import mindustry.ctype.*; -import mindustry.gen.*; -import mindustry.graphics.*; -import mindustry.world.*; -import mindustry.world.meta.*; - -public class AmmoTypes implements ContentList{ - public static AmmoType - powerLow, - power, - powerHigh, - copper, - thorium; - - @Override - public void load(){ - powerLow = new PowerAmmoType(500); - power = new PowerAmmoType(1000); - powerHigh = new PowerAmmoType(2000); - copper = new ItemAmmoType(Items.copper); - thorium = new ItemAmmoType(Items.thorium); - } - - public static class PowerAmmoType extends AmmoType{ - public float totalPower = 1000; - - public PowerAmmoType(){ - super(Iconc.power, Pal.powerLight); - barColor = color; - } - - public PowerAmmoType(float totalPower){ - this(); - this.totalPower = totalPower; - } - - @Override - public void resupply(Unit unit){ - float range = unit.hitSize + 60f; - Tile closest = Vars.indexer.findClosestFlag(unit.x, unit.y, unit.team, BlockFlag.battery); - - if(closest != null && closest.build != null && unit.within(closest.build, range) && closest.build.power != null){ - var build = closest.build; - - if(build.block.consumes.hasPower() && build.block.consumes.getPower().buffered){ - float amount = closest.build.power.status * build.block.consumes.getPower().capacity; - float powerPerAmmo = totalPower / unit.type.ammoCapacity; - float ammoRequired = unit.type.ammoCapacity - unit.ammo; - float powerRequired = ammoRequired * powerPerAmmo; - float powerTaken = Math.min(amount, powerRequired); - - if(powerTaken > 1){ - closest.build.power.status -= powerTaken / build.block.consumes.getPower().capacity; - unit.ammo += powerTaken / powerPerAmmo; - - Fx.itemTransfer.at(build.x, build.y, Math.max(powerTaken / 100f, 1f), Pal.power, unit); - } - } - } - } - } - - public static class ItemAmmoType extends AmmoType{ - public Item item; - - public ItemAmmoType(Item item){ - this.item = item; - this.color = item.color; - } - - public ItemAmmoType(){ - } - - @Override - public void load(){ - if(item != null){ - icon = item.emoji(); - } - } - } -} diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index 9694111761..ffe379a56b 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -67,6 +67,8 @@ public class Planet extends UnlockableContent{ public boolean bloom = false; /** Whether this planet is displayed. */ public boolean visible = true; + /** Tint of clouds displayed when landing. */ + public Color landCloudColor = new Color(1f, 1f, 1f, 0.5f); /** For suns, this is the color that shines on other planets. Does nothing for children. */ public Color lightColor = Color.white.cpy(); /** Atmosphere tint for landable planets. */ diff --git a/core/src/mindustry/type/Sector.java b/core/src/mindustry/type/Sector.java index 344d33dffc..a2111160e9 100644 --- a/core/src/mindustry/type/Sector.java +++ b/core/src/mindustry/type/Sector.java @@ -11,6 +11,7 @@ import arc.util.*; import mindustry.*; import mindustry.game.Saves.*; import mindustry.game.*; +import mindustry.gen.*; import mindustry.graphics.g3d.PlanetGrid.*; import mindustry.ui.*; import mindustry.world.modules.*; @@ -131,6 +132,13 @@ public class Sector{ return info.contentIcon != null ? info.contentIcon.uiIcon : info.icon == null ? null : Fonts.getLargeIcon(info.icon); } + @Nullable + public String iconChar(){ + if(info.contentIcon != null) return info.contentIcon.emoji(); + if(info.icon != null) return Iconc.codes.get(info.icon) + ""; + return null; + } + public boolean isCaptured(){ return save != null && !info.waves; } diff --git a/core/src/mindustry/type/StatusEffect.java b/core/src/mindustry/type/StatusEffect.java index fe9a7f487f..20d5b1809e 100644 --- a/core/src/mindustry/type/StatusEffect.java +++ b/core/src/mindustry/type/StatusEffect.java @@ -43,13 +43,13 @@ public class StatusEffect extends UnlockableContent{ public Color color = Color.white.cpy(); /** Effect that happens randomly on top of the affected unit. */ public Effect effect = Fx.none; + /** Affinity & opposite values for stat displays. */ + public ObjectSet affinities = new ObjectSet<>(), opposites = new ObjectSet<>(); /** Transition handler map. */ protected ObjectMap transitions = new ObjectMap<>(); /** Called on init. */ protected Runnable initblock = () -> {}; - public ObjectSet affinities = new ObjectSet<>(), opposites = new ObjectSet<>(); - public StatusEffect(String name){ super(name); } @@ -152,6 +152,10 @@ public class StatusEffect extends UnlockableContent{ }); } + public void draw(Unit unit, float time){ + draw(unit); //Backwards compatibility + } + public void draw(Unit unit){ } diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index b2da070588..1ea7acc16b 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -24,6 +24,7 @@ import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.graphics.MultiPacker.*; +import mindustry.type.ammo.*; import mindustry.ui.*; import mindustry.world.*; import mindustry.world.blocks.environment.*; @@ -41,7 +42,11 @@ public class UnitType extends UnlockableContent{ /** If true, the unit is always at elevation 1. */ public boolean flying; + /** If `flying` and this is true, the unit can appear on the title screen */ + public boolean onTitleScreen = true; + /** Creates a new instance of this unit class. */ public Prov constructor; + /** The default AI controller to assign on creation. */ public Prov defaultController = () -> !flying ? new GroundAI() : new FlyingAI(); /** Environmental flags that are *all* required for this unit to function. 0 = any environment */ @@ -73,7 +78,10 @@ public class UnitType extends UnlockableContent{ public Effect fallThrusterEffect = Fx.fallSmoke; public Effect deathExplosionEffect = Fx.dynamicExplosion; public Seq abilities = new Seq<>(); - public BlockFlag targetFlag = BlockFlag.generator; + /** Flags to target based on priority. Null indicates that the closest target should be found. The closest enemy core is used as a fallback. */ + public BlockFlag[] targetFlags = {null}; + /** targetFlags, as an override for "non-AI" teams. By default, units of this type will rush the core. */ + public BlockFlag[] playerTargetFlags = {BlockFlag.core, null}; public Color outlineColor = Pal.darkerMetal; public int outlineRadius = 3; @@ -84,9 +92,6 @@ public class UnitType extends UnlockableContent{ public float legSplashDamage = 0f, legSplashRange = 5; public boolean flipBackLegs = true; - public int ammoResupplyAmount = 10; - public float ammoResupplyRange = 100f; - public float mechSideSway = 0.54f, mechFrontSway = 0.1f; public float mechStride = -1f; public float mechStepShake = -1f; @@ -95,7 +100,7 @@ public class UnitType extends UnlockableContent{ public int itemCapacity = -1; public int ammoCapacity = -1; - public AmmoType ammoType = AmmoTypes.copper; + public AmmoType ammoType = new ItemAmmoType(Items.copper); public int mineTier = -1; public float buildSpeed = -1f, mineSpeed = 1f; public Sound mineSound = Sounds.minebeam; @@ -118,6 +123,7 @@ public class UnitType extends UnlockableContent{ public boolean canHeal = false; /** If true, all weapons will attack the same target. */ public boolean singleTarget = false; + public boolean forceMultiTarget = false; public ObjectSet immunities = new ObjectSet<>(); public Sound deathSound = Sounds.bang; @@ -195,7 +201,7 @@ public class UnitType extends UnlockableContent{ bars.row(); if(state.rules.unitAmmo){ - bars.add(new Bar(ammoType.icon + " " + Core.bundle.get("stat.ammo"), ammoType.barColor, () -> unit.ammo / ammoCapacity)); + bars.add(new Bar(ammoType.icon() + " " + Core.bundle.get("stat.ammo"), ammoType.barColor(), () -> unit.ammo / ammoCapacity)); bars.row(); } @@ -232,6 +238,10 @@ public class UnitType extends UnlockableContent{ return (envEnabled & env) != 0 && (envDisabled & env) == 0 && (envRequired == 0 || (envRequired & env) == envRequired); } + public boolean isBanned(){ + return state.rules.bannedUnits.contains(this); + } + @Override public void getDependencies(Cons cons){ //units require reconstructors being researched @@ -318,7 +328,7 @@ public class UnitType extends UnlockableContent{ } clipSize = Math.max(clipSize, lightRadius * 1.1f); - singleTarget = weapons.size <= 1; + singleTarget = weapons.size <= 1 && !forceMultiTarget; if(itemCapacity < 0){ itemCapacity = Math.max(Mathf.round((int)(hitSize * 4.3), 10), 10); @@ -388,9 +398,9 @@ public class UnitType extends UnlockableContent{ //dynamically create ammo capacity based on firing rate if(ammoCapacity < 0){ - float shotsPerSecond = weapons.sumf(w -> 60f / w.reload); + float shotsPerSecond = weapons.sumf(w -> w.useAmmo ? 60f / w.reload : 0f); //duration of continuous fire without reload - float targetSeconds = 30; + float targetSeconds = 35; ammoCapacity = Math.max(1, (int)(shotsPerSecond * targetSeconds)); } diff --git a/core/src/mindustry/type/Weather.java b/core/src/mindustry/type/Weather.java index a21cb992af..93790fbeee 100644 --- a/core/src/mindustry/type/Weather.java +++ b/core/src/mindustry/type/Weather.java @@ -344,15 +344,15 @@ public class Weather extends UnlockableContent{ @Override public void draw(){ - if(renderer.weatherAlpha() > 0.0001f && renderer.drawWeather && Core.settings.getBool("showweather")){ + if(renderer.weatherAlpha > 0.0001f && renderer.drawWeather && Core.settings.getBool("showweather")){ Draw.draw(Layer.weather, () -> { - Draw.alpha(renderer.weatherAlpha() * opacity * weather.opacityMultiplier); + Draw.alpha(renderer.weatherAlpha * opacity * weather.opacityMultiplier); weather.drawOver(self()); Draw.reset(); }); Draw.draw(Layer.debris, () -> { - Draw.alpha(renderer.weatherAlpha() * opacity * weather.opacityMultiplier); + Draw.alpha(renderer.weatherAlpha * opacity * weather.opacityMultiplier); weather.drawUnder(self()); Draw.reset(); }); diff --git a/core/src/mindustry/type/ammo/ItemAmmoType.java b/core/src/mindustry/type/ammo/ItemAmmoType.java new file mode 100644 index 0000000000..6263209e75 --- /dev/null +++ b/core/src/mindustry/type/ammo/ItemAmmoType.java @@ -0,0 +1,57 @@ +package mindustry.type.ammo; + +import arc.graphics.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.type.*; + +public class ItemAmmoType implements AmmoType{ + public float range = 85f; + public int ammoPerItem = 15; + public Item item; + + public ItemAmmoType(Item item){ + this.item = item; + } + + public ItemAmmoType(Item item, int ammoPerItem){ + this.item = item; + this.ammoPerItem = ammoPerItem; + } + + public ItemAmmoType(){ + } + + @Override + public String icon(){ + return item.emoji(); + } + + @Override + public Color color(){ + return item.color; + } + + @Override + public Color barColor(){ + return Pal.ammo; + } + + @Override + public void resupply(Unit unit){ + //do not resupply when it would waste resources + if(unit.type.ammoCapacity - unit.ammo < ammoPerItem) return; + + float range = unit.hitSize + this.range; + + Building build = Units.closestBuilding(unit.team, unit.x, unit.y, range, u -> u.block.allowResupply && u.items.has(item)); + + if(build != null){ + Fx.itemTransfer.at(build.x, build.y, ammoPerItem / 2f, item.color, unit); + unit.ammo = Math.min(unit.ammo + ammoPerItem, unit.type.ammoCapacity); + build.items.remove(item, 1); + } + } +} diff --git a/core/src/mindustry/type/ammo/PowerAmmoType.java b/core/src/mindustry/type/ammo/PowerAmmoType.java new file mode 100644 index 0000000000..49d0b4dbb5 --- /dev/null +++ b/core/src/mindustry/type/ammo/PowerAmmoType.java @@ -0,0 +1,58 @@ +package mindustry.type.ammo; + +import arc.graphics.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.type.*; + +public class PowerAmmoType implements AmmoType{ + public float range = 85f; + public float totalPower = 1000; + + public PowerAmmoType(float totalPower){ + this.totalPower = totalPower; + } + + public PowerAmmoType(){ + + } + + @Override + public String icon(){ + return Iconc.power + ""; + } + + @Override + public Color color(){ + return Pal.powerLight; + } + + @Override + public Color barColor(){ + return Pal.powerLight; + } + + @Override + public void resupply(Unit unit){ + float range = unit.hitSize + this.range; + + Building build = Units.closestBuilding(unit.team, unit.x, unit.y, range, u -> u.block.consumes.hasPower() && u.block.consumes.getPower().buffered); + + if(build != null){ + float amount = build.power.status * build.block.consumes.getPower().capacity; + float powerPerAmmo = totalPower / unit.type.ammoCapacity; + float ammoRequired = unit.type.ammoCapacity - unit.ammo; + float powerRequired = ammoRequired * powerPerAmmo; + float powerTaken = Math.min(amount, powerRequired); + + if(powerTaken > 1){ + build.power.status -= powerTaken / build.block.consumes.getPower().capacity; + unit.ammo += powerTaken / powerPerAmmo; + + Fx.itemTransfer.at(build.x, build.y, Math.max(powerTaken / 100f, 1f), Pal.power, unit); + } + } + } +} diff --git a/core/src/mindustry/ui/Bar.java b/core/src/mindustry/ui/Bar.java index 6bab3a146d..d8e2b4b6da 100644 --- a/core/src/mindustry/ui/Bar.java +++ b/core/src/mindustry/ui/Bar.java @@ -68,6 +68,10 @@ public class Bar extends Element{ return this; } + public void flash(){ + blink = 1f; + } + public Bar blink(Color color){ blinkColor.set(color); return this; @@ -107,8 +111,10 @@ public class Bar extends Element{ } Draw.colorl(0.1f); + Draw.alpha(parentAlpha); bar.draw(x, y, width, height); Draw.color(color, blinkColor, blink); + Draw.alpha(parentAlpha); Drawable top = Tex.barTop; float topWidth = width * value; @@ -128,7 +134,7 @@ public class Bar extends Element{ GlyphLayout lay = Pools.obtain(GlyphLayout.class, GlyphLayout::new); lay.setText(font, name); - font.setColor(Color.white); + font.setColor(1f, 1f, 1f, parentAlpha); font.draw(name, x + width / 2f - lay.width / 2f, y + height / 2f + lay.height / 2f + 1); Pools.free(lay); diff --git a/core/src/mindustry/ui/Fonts.java b/core/src/mindustry/ui/Fonts.java index 7beff27396..bbd55bbd95 100644 --- a/core/src/mindustry/ui/Fonts.java +++ b/core/src/mindustry/ui/Fonts.java @@ -21,6 +21,7 @@ import arc.util.*; import mindustry.*; import mindustry.core.*; import mindustry.ctype.*; +import mindustry.game.*; import mindustry.gen.*; import java.util.*; @@ -155,6 +156,12 @@ public class Fonts{ } } }); + + for(Team team : Team.baseTeams){ + if(Core.atlas.has("team-" + team.name)){ + team.emoji = stringIcons.get(team.name, ""); + } + } } /** Called from a static context for use in the loading screen.*/ diff --git a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java index 3b5978a290..0bee65257d 100644 --- a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java +++ b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java @@ -28,87 +28,93 @@ public class CustomRulesDialog extends BaseDialog{ private Table main; private Prov resetter; private LoadoutDialog loadoutDialog; - private BaseDialog banDialog; public CustomRulesDialog(){ super("@mode.custom"); loadoutDialog = new LoadoutDialog(); - banDialog = new BaseDialog("@bannedblocks"); - banDialog.addCloseButton(); - - banDialog.shown(this::rebuildBanned); - banDialog.buttons.button("@addall", Icon.add, () -> { - rules.bannedBlocks.addAll(content.blocks().select(Block::canBeBuilt)); - rebuildBanned(); - }).size(180, 64f); - - banDialog.buttons.button("@clear", Icon.trash, () -> { - rules.bannedBlocks.clear(); - rebuildBanned(); - }).size(180, 64f); setFillParent(true); shown(this::setup); addCloseButton(); } - private void rebuildBanned(){ - float previousScroll = banDialog.cont.getChildren().isEmpty() ? 0f : ((ScrollPane)banDialog.cont.getChildren().first()).getScrollY(); - banDialog.cont.clear(); - banDialog.cont.pane(t -> { - t.margin(10f); + private void showBanned(String title, ContentType type, ObjectSet set, Boolf pred){ + BaseDialog bd = new BaseDialog(title); + bd.addCloseButton(); - if(rules.bannedBlocks.isEmpty()){ - t.add("@empty"); - } + Runnable[] rebuild = {null}; - Seq array = Seq.with(rules.bannedBlocks); - array.sort(); + rebuild[0] = () -> { + float previousScroll = bd.cont.getChildren().isEmpty() ? 0f : ((ScrollPane)bd.cont.getChildren().first()).getScrollY(); + bd.cont.clear(); + bd.cont.pane(t -> { + t.margin(10f); - int cols = mobile && Core.graphics.isPortrait() ? 1 : mobile ? 2 : 3; - int i = 0; - - for(Block block : array){ - t.table(Tex.underline, b -> { - b.left().margin(4f); - b.image(block.uiIcon).size(iconMed).padRight(3); - b.add(block.localizedName).color(Color.lightGray).padLeft(3).growX().left().wrap(); - - b.button(Icon.cancel, Styles.clearPartiali, () -> { - rules.bannedBlocks.remove(block); - rebuildBanned(); - }).size(70f).pad(-4f).padLeft(0f); - }).size(300f, 70f).padRight(5); - - if(++i % cols == 0){ - t.row(); + if(set.isEmpty()){ + t.add("@empty"); } - } - }).get().setScrollYForce(previousScroll); - banDialog.cont.row(); - banDialog.cont.button("@add", Icon.add, () -> { - BaseDialog dialog = new BaseDialog("@add"); - dialog.cont.pane(t -> { - t.left().margin(14f); - int[] i = {0}; - content.blocks().each(b -> !rules.bannedBlocks.contains(b) && b.canBeBuilt(), b -> { - int cols = mobile && Core.graphics.isPortrait() ? 4 : 12; - t.button(new TextureRegionDrawable(b.uiIcon), Styles.cleari, iconMed, () -> { - rules.bannedBlocks.add(b); - rebuildBanned(); - dialog.hide(); - }).size(60f); - if(++i[0] % cols == 0){ + Seq array = set.asArray(); + array.sort(); + + int cols = mobile && Core.graphics.isPortrait() ? 1 : mobile ? 2 : 3; + int i = 0; + + for(T con : array){ + t.table(Tex.underline, b -> { + b.left().margin(4f); + b.image(con.uiIcon).size(iconMed).padRight(3); + b.add(con.localizedName).color(Color.lightGray).padLeft(3).growX().left().wrap(); + + b.button(Icon.cancel, Styles.clearPartiali, () -> { + set.remove(con); + rebuild[0].run(); + }).size(70f).pad(-4f).padLeft(0f); + }).size(300f, 70f).padRight(5); + + if(++i % cols == 0){ t.row(); } - }); - }); + } + }).get().setScrollYForce(previousScroll); + bd.cont.row(); + bd.cont.button("@add", Icon.add, () -> { + BaseDialog dialog = new BaseDialog("@add"); + dialog.cont.pane(t -> { + t.left().margin(14f); + int[] i = {0}; + content.getBy(type).each(b -> !set.contains(b) && pred.get(b), b -> { + int cols = mobile && Core.graphics.isPortrait() ? 4 : 12; + t.button(new TextureRegionDrawable(b.uiIcon), Styles.cleari, iconMed, () -> { + set.add(b); + rebuild[0].run(); + dialog.hide(); + }).size(60f); - dialog.addCloseButton(); - dialog.show(); - }).size(300f, 64f); + if(++i[0] % cols == 0){ + t.row(); + } + }); + }); + + dialog.addCloseButton(); + dialog.show(); + }).size(300f, 64f); + }; + + bd.shown(rebuild[0]); + bd.buttons.button("@addall", Icon.add, () -> { + set.addAll(content.getBy(type).select(pred)); + rebuild[0].run(); + }).size(180, 64f); + + bd.buttons.button("@clear", Icon.trash, () -> { + set.clear(); + rebuild[0].run(); + }).size(180, 64f); + + bd.show(); } public void show(Rules rules, Prov resetter){ @@ -157,7 +163,7 @@ public class CustomRulesDialog extends BaseDialog{ )).left().width(300f); main.row(); - main.button("@bannedblocks", banDialog::show).left().width(300f); + main.button("@bannedblocks", () -> showBanned("@bannedblocks", ContentType.block, rules.bannedBlocks, Block::canBeBuilt)).left().width(300f); main.row(); title("@rules.title.unit"); @@ -167,6 +173,9 @@ public class CustomRulesDialog extends BaseDialog{ number("@rules.unitdamagemultiplier", f -> rules.unitDamageMultiplier = f, () -> rules.unitDamageMultiplier); number("@rules.unitbuildspeedmultiplier", f -> rules.unitBuildSpeedMultiplier = f, () -> rules.unitBuildSpeedMultiplier, 0.001f, 50f); + main.button("@bannedunits", () -> showBanned("@bannedunits", ContentType.unit, rules.bannedUnits, u -> !u.isHidden())).left().width(300f); + main.row(); + title("@rules.title.enemy"); check("@rules.attack", b -> rules.attackMode = b, () -> rules.attackMode); check("@rules.buildai", b -> rules.teams.get(rules.waveTeam).ai = rules.teams.get(rules.waveTeam).infiniteResources = b, () -> rules.teams.get(rules.waveTeam).ai); diff --git a/core/src/mindustry/ui/dialogs/DatabaseDialog.java b/core/src/mindustry/ui/dialogs/DatabaseDialog.java index 5c2aa76d17..ede404aa9a 100644 --- a/core/src/mindustry/ui/dialogs/DatabaseDialog.java +++ b/core/src/mindustry/ui/dialogs/DatabaseDialog.java @@ -13,7 +13,9 @@ import mindustry.*; import mindustry.ctype.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.type.*; import mindustry.ui.*; +import mindustry.world.*; import static mindustry.Vars.*; @@ -50,14 +52,24 @@ public class DatabaseDialog extends BaseDialog{ table.table(list -> { list.left(); - int cols = Mathf.clamp((Core.graphics.getWidth() - 30) / (32 + 10), 1, 18); + int cols = (int)Mathf.clamp((Core.graphics.getWidth() - Scl.scl(30)) / Scl.scl(32 + 10), 1, 22); int count = 0; for(int i = 0; i < array.size; i++){ UnlockableContent unlock = (UnlockableContent)array.get(i); Image image = unlocked(unlock) ? new Image(unlock.uiIcon).setScaling(Scaling.fit) : new Image(Icon.lock, Pal.gray); - list.add(image).size(8 * 4).pad(3); + + //banned cross + if(state.isGame() && (unlock instanceof UnitType u && u.isBanned() || unlock instanceof Block b && state.rules.bannedBlocks.contains(b))){ + list.stack(image, new Image(Icon.cancel){{ + setColor(Color.scarlet); + touchable = Touchable.disabled; + }}).size(8 * 4).pad(3); + }else{ + list.add(image).size(8 * 4).pad(3); + } + ClickListener listener = new ClickListener(); image.addListener(listener); if(!mobile && unlocked(unlock)){ diff --git a/core/src/mindustry/ui/dialogs/FileChooser.java b/core/src/mindustry/ui/dialogs/FileChooser.java index 6ece055569..9259130d5c 100644 --- a/core/src/mindustry/ui/dialogs/FileChooser.java +++ b/core/src/mindustry/ui/dialogs/FileChooser.java @@ -39,6 +39,7 @@ public class FileChooser extends BaseDialog{ if(!lastDirectory.exists()){ lastDirectory = homeDirectory; + directory = lastDirectory; } onResize(() -> { diff --git a/core/src/mindustry/ui/dialogs/JoinDialog.java b/core/src/mindustry/ui/dialogs/JoinDialog.java index 2d42534be5..68368a1230 100644 --- a/core/src/mindustry/ui/dialogs/JoinDialog.java +++ b/core/src/mindustry/ui/dialogs/JoinDialog.java @@ -271,7 +271,7 @@ public class JoinDialog extends BaseDialog{ hosts.clear(); - section("@servers.local", local, false); + section(steam ? "@servers.local.steam" : "@servers.local", local, false); section("@servers.remote", remote, false); section("@servers.global", global, true); diff --git a/core/src/mindustry/ui/dialogs/KeybindDialog.java b/core/src/mindustry/ui/dialogs/KeybindDialog.java index 0aefcb2a38..c51003724c 100644 --- a/core/src/mindustry/ui/dialogs/KeybindDialog.java +++ b/core/src/mindustry/ui/dialogs/KeybindDialog.java @@ -13,6 +13,7 @@ import arc.struct.*; import arc.util.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.ui.*; import static arc.Core.*; @@ -72,7 +73,7 @@ public class KeybindDialog extends Dialog{ } if(sections.length != 1){ - TextButton button = new TextButton(bundle.get("section." + section.name + ".name", Strings.capitalize(section.name))/*, "toggle"*/); + TextButton button = new TextButton(bundle.get("section." + section.name + ".name", Strings.capitalize(section.name))); if(section.equals(this.section)) button.toggle(); @@ -115,9 +116,9 @@ public class KeybindDialog extends Dialog{ } }).disabled(sectionControls.get(section, 0) + 1 >= devices.size).size(40); - table.add(stable).colspan(4); + //no alternate devices until further notice + //table.add(stable).colspan(4).row(); - table.row(); table.add().height(10); table.row(); if(section.device.type() == DeviceType.controller){ @@ -127,6 +128,7 @@ public class KeybindDialog extends Dialog{ table.row(); String lastCategory = null; + var tstyle = Styles.defaultt; for(KeyBind keybind : keybinds.getKeybinds()){ if(lastCategory != keybind.category() && keybind.category() != null){ @@ -149,7 +151,7 @@ public class KeybindDialog extends Dialog{ table.add(axt).left().minWidth(90).padRight(20); } - table.button(bundle.get("settings.rebind", "Rebind"), () -> { + table.button("@settings.rebind", tstyle, () -> { rebindAxis = true; rebindMin = true; openDialog(section, keybind); @@ -160,13 +162,13 @@ public class KeybindDialog extends Dialog{ table.add(keybinds.get(section, keybind).key.toString(), style.keyColor).left().minWidth(90).padRight(20); - table.button(bundle.get("settings.rebind", "Rebind"), () -> { + table.button("@settings.rebind", tstyle, () -> { rebindAxis = false; rebindMin = false; openDialog(section, keybind); }).width(130f); } - table.button(bundle.get("settings.resetKey", "Reset"), () -> { + table.button("@settings.resetKey", tstyle, () -> { keybinds.resetToDefault(section, keybind); setup(); }).width(130f); @@ -175,7 +177,7 @@ public class KeybindDialog extends Dialog{ table.visible(() -> this.section.equals(section)); - table.button(bundle.get("settings.reset", "Reset to Defaults"), () -> { + table.button("@settings.reset", () -> { keybinds.resetToDefaults(); setup(); }).colspan(4).padTop(4).fill(); diff --git a/core/src/mindustry/ui/dialogs/ModsDialog.java b/core/src/mindustry/ui/dialogs/ModsDialog.java index abad12a00a..578652fa7b 100644 --- a/core/src/mindustry/ui/dialogs/ModsDialog.java +++ b/core/src/mindustry/ui/dialogs/ModsDialog.java @@ -36,6 +36,7 @@ import static mindustry.Vars.*; public class ModsDialog extends BaseDialog{ private ObjectMap textureCache = new ObjectMap<>(); + private float modImportProgress; private String searchtxt = ""; private @Nullable Seq modList; private boolean orderDate = false; @@ -488,11 +489,16 @@ public class ModsDialog extends BaseDialog{ private void handleMod(String repo, HttpResponse result){ try{ Fi file = tmpDirectory.child(repo.replace("/", "") + ".zip"); - Streams.copy(result.getResultAsStream(), file.write(false)); + long len = result.getContentLength(); + Floatc cons = len <= 0 ? f -> {} : p -> modImportProgress = p; + + Streams.copyProgress(result.getResultAsStream(), file.write(false), len, 4096, cons); + var mod = mods.importMod(file); mod.setRepo(repo); file.delete(); Core.app.post(() -> { + try{ setup(); ui.loadfrag.hide(); @@ -510,10 +516,13 @@ public class ModsDialog extends BaseDialog{ } private void githubImportMod(String repo, boolean isJava){ + modImportProgress = 0f; + ui.loadfrag.show("@downloading"); + ui.loadfrag.setProgress(() -> modImportProgress); + if(isJava){ githubImportJavaMod(repo); }else{ - ui.loadfrag.show(); Http.get(ghApi + "/repos/" + repo, res -> { var json = Jval.read(res.getResultAsString()); String mainBranch = json.getString("default_branch"); diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 17cb4f55cb..73992fb3be 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -33,6 +33,7 @@ import mindustry.type.*; import mindustry.ui.*; import mindustry.world.blocks.storage.*; +import static arc.Core.*; import static mindustry.Vars.*; import static mindustry.graphics.g3d.PlanetRenderer.*; import static mindustry.ui.dialogs.PlanetDialog.Mode.*; @@ -373,6 +374,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } if(selectAlpha > 0.001f){ + + for(Sector sec : planet.sectors){ if(sec.hasBase()){ for(Sector enemy : sec.near()){ @@ -380,6 +383,18 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ planets.drawArc(planet, enemy.tile.v, sec.tile.v, Team.crux.color.write(Tmp.c2).a(selectAlpha), Color.clear, 0.24f, 110f, 25); } } + + + if(selected != null && selected != sec && selected.hasBase()){ + //imports + if(sec.info.getRealDestination() == selected && sec.info.anyExports()){ + planets.drawArc(planet, sec.tile.v, selected.tile.v, Color.gray.write(Tmp.c2).a(selectAlpha), Pal.accent.write(Tmp.c3).a(selectAlpha), 0.4f, 90f, 25); + } + //exports + if(selected.info.getRealDestination() == sec && selected.info.anyExports()){ + planets.drawArc(planet, selected.tile.v, sec.tile.v, Pal.place.write(Tmp.c2).a(selectAlpha), Pal.accent.write(Tmp.c3).a(selectAlpha), 0.4f, 90f, 25); + } + } } } } @@ -617,6 +632,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } void displayItems(Table c, float scl, ObjectMap stats, String name){ + displayItems(c, scl, stats, name, t -> {}); + } + + void displayItems(Table c, float scl, ObjectMap stats, String name, Cons builder){ Table t = new Table().left(); int i = 0; @@ -634,8 +653,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } if(t.getChildren().any()){ - c.add(name).left().row(); - c.add(t).padLeft(10f).left().row(); + c.defaults().left(); + c.add(name).row(); + builder.get(c); + c.add(t).padLeft(10f).row(); } } @@ -645,6 +666,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ dialog.cont.pane(c -> { c.defaults().padBottom(5); + if(sector.preset != null && sector.preset.description != null){ + c.add(sector.preset.displayDescription()).left().row(); + } + c.add(Core.bundle.get("sectors.time") + " [accent]" + sector.save.getPlayTime()).left().row(); if(sector.info.waves && sector.hasBase()){ @@ -668,11 +693,21 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ displayItems(c, sector.getProductionScale(), sector.info.production, "@sectors.production"); //export - displayItems(c, sector.getProductionScale(), sector.info.export, "@sectors.export"); + displayItems(c, sector.getProductionScale(), sector.info.export, "@sectors.export", t -> { + if(sector.info.destination != null){ + String ic = sector.info.destination.iconChar(); + t.add(Iconc.rightOpen + " " + (ic == null || ic.isEmpty() ? "" : ic + " ") + sector.info.destination.name()).padLeft(10f).row(); + } + }); //import if(sector.hasBase()){ - displayItems(c, 1f, sector.info.importStats(), "@sectors.import"); + displayItems(c, 1f, sector.info.importStats(sector.planet), "@sectors.import", t -> { + sector.info.eachImport(sector.planet, other -> { + String ic = other.iconChar(); + t.add(Iconc.rightOpen + " " + (ic == null || ic.isEmpty() ? "" : ic + " ") + other.name()).padLeft(10f).row(); + }); + }); } ItemSeq items = sector.items(); @@ -747,10 +782,11 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ t.button(Icon.none, Styles.clearTogglei, () -> { sector.info.icon = null; + sector.info.contentIcon = null; sector.saveInfo(); hide(); updateSelected(); - }).checked(sector.info.icon == null); + }).checked(sector.info.icon == null && sector.info.contentIcon == null); int cols = (int)Math.min(20, Core.graphics.getWidth() / Scl.scl(52f)); @@ -758,7 +794,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ for(var key : defaultIcons){ var value = Icon.icons.get(key); - t.button(value, Styles.cleari, () -> { + t.button(value, Styles.clearTogglei, () -> { sector.info.icon = key; sector.info.contentIcon = null; sector.saveInfo(); @@ -777,7 +813,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ i = 0; for(UnlockableContent u : content.getBy(ctype).as()){ if(!u.isHidden() && u.unlocked()){ - t.button(new TextureRegionDrawable(u.uiIcon), Styles.cleari, iconMed, () -> { + t.button(new TextureRegionDrawable(u.uiIcon), Styles.clearTogglei, iconMed, () -> { sector.info.icon = null; sector.info.contentIcon = u; sector.saveInfo(); @@ -931,14 +967,37 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ CoreBlock block = from.info.bestCoreType instanceof CoreBlock b ? b : (CoreBlock)Blocks.coreShard; loadouts.show(block, from, () -> { + var schemCore = universe.getLastLoadout().findCore(); from.removeItems(universe.getLastLoadout().requirements()); from.removeItems(universe.getLaunchResources()); - launching = true; - zoom = planets.planet.minZoom; + if(settings.getBool("skipcoreanimation")){ + //just... go there + control.playSector(from, sector); + //hide only after load screen is shown + Time.runTask(8f, this::hide); + }else{ + //hide immediately so launch sector is visible + hide(); - ui.hudfrag.showLaunchDirect(); - Time.runTask(launchDuration, () -> control.playSector(from, sector)); + //allow planet dialog to finish hiding before actually launching + Time.runTask(5f, () -> { + Runnable doLaunch = () -> { + renderer.showLaunch(schemCore); + //run with less delay, as the loading animation is delayed by several frames + Time.runTask(coreLandDuration - 8f, () -> control.playSector(from, sector)); + }; + + //load launchFrom sector right before launching so animation is correct + if(!from.isBeingPlayed()){ + //run *after* the loading animation is done + Time.runTask(9f, doLaunch); + control.playSector(from); + }else{ + doLaunch.run(); + } + }); + } }); } }else if(mode == select){ diff --git a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java index e291ace87d..8efa0f740e 100644 --- a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -292,13 +292,15 @@ public class SettingsMenuDialog extends Dialog{ if(mobile){ game.checkPref("autotarget", true); - game.checkPref("keyboard", false, val -> { - control.setInput(val ? new DesktopInput() : new MobileInput()); - input.setUseKeyboard(val); - }); - if(Core.settings.getBool("keyboard")){ - control.setInput(new DesktopInput()); - input.setUseKeyboard(true); + if(!ios){ + game.checkPref("keyboard", false, val -> { + control.setInput(val ? new DesktopInput() : new MobileInput()); + input.setUseKeyboard(val); + }); + if(Core.settings.getBool("keyboard")){ + control.setInput(new DesktopInput()); + input.setUseKeyboard(true); + } } } //the issue with touchscreen support on desktop is that: @@ -354,7 +356,7 @@ public class SettingsMenuDialog extends Dialog{ }); graphics.sliderPref("screenshake", 4, 0, 8, i -> (i / 4f) + "x"); - graphics.sliderPref("fpscap", 240, 15, 245, 5, s -> (s > 240 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s))); + graphics.sliderPref("fpscap", 240, 10, 245, 5, s -> (s > 240 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s))); graphics.sliderPref("chatopacity", 100, 0, 100, 5, s -> s + "%"); graphics.sliderPref("lasersopacity", 100, 0, 100, 5, s -> { if(ui.settings != null){ @@ -367,6 +369,12 @@ public class SettingsMenuDialog extends Dialog{ if(!mobile){ graphics.checkPref("vsync", true, b -> Core.graphics.setVSync(b)); graphics.checkPref("fullscreen", false, b -> { + if(b && settings.getBool("borderlesswindow")){ + Core.graphics.setWindowedMode(Core.graphics.getWidth(), Core.graphics.getHeight()); + settings.put("borderlesswindow", false); + graphics.rebuild(); + } + if(b){ Core.graphics.setFullscreenMode(Core.graphics.getDisplayMode()); }else{ @@ -374,15 +382,23 @@ public class SettingsMenuDialog extends Dialog{ } }); - graphics.checkPref("borderlesswindow", false, b -> Core.graphics.setUndecorated(b)); + graphics.checkPref("borderlesswindow", false, b -> { + if(b && settings.getBool("fullscreen")){ + Core.graphics.setWindowedMode(Core.graphics.getWidth(), Core.graphics.getHeight()); + settings.put("fullscreen", false); + graphics.rebuild(); + } + Core.graphics.setBorderless(b); + }); Core.graphics.setVSync(Core.settings.getBool("vsync")); + if(Core.settings.getBool("fullscreen")){ Core.app.post(() -> Core.graphics.setFullscreenMode(Core.graphics.getDisplayMode())); } if(Core.settings.getBool("borderlesswindow")){ - Core.app.post(() -> Core.graphics.setUndecorated(true)); + Core.app.post(() -> Core.graphics.setBorderless(true)); } }else if(!ios){ graphics.checkPref("landscape", false, b -> { @@ -446,11 +462,11 @@ public class SettingsMenuDialog extends Dialog{ } } + graphics.checkPref("skipcoreanimation", false); + if(!mobile){ Core.settings.put("swapdiagonal", false); } - - graphics.checkPref("flow", true); } public void exportData(Fi file) throws IOException{ @@ -610,7 +626,8 @@ public class SettingsMenuDialog extends Dialog{ Setting(String name){ this.name = name; - title = bundle.get("setting." + name + ".name"); + String winkey = "setting." + name + ".name.windows"; + title = OS.isWindows && bundle.has(winkey) ? bundle.get(winkey) : bundle.get("setting." + name + ".name"); description = bundle.getOrNull("setting." + name + ".description"); } diff --git a/core/src/mindustry/ui/fragments/ChatFragment.java b/core/src/mindustry/ui/fragments/ChatFragment.java index 75eaac5ab0..4b4bd3e46d 100644 --- a/core/src/mindustry/ui/fragments/ChatFragment.java +++ b/core/src/mindustry/ui/fragments/ChatFragment.java @@ -32,7 +32,7 @@ public class ChatFragment extends Table{ private Font font; private GlyphLayout layout = new GlyphLayout(); private float offsetx = Scl.scl(4), offsety = Scl.scl(4), fontoffsetx = Scl.scl(2), chatspace = Scl.scl(50); - private Color shadowColor = new Color(0, 0, 0, 0.4f); + private Color shadowColor = new Color(0, 0, 0, 0.5f); private float textspacing = Scl.scl(10); private Seq history = new Seq<>(); private int historyPos = 0; diff --git a/core/src/mindustry/ui/fragments/HintsFragment.java b/core/src/mindustry/ui/fragments/HintsFragment.java index f4f677e720..b548a5536c 100644 --- a/core/src/mindustry/ui/fragments/HintsFragment.java +++ b/core/src/mindustry/ui/fragments/HintsFragment.java @@ -12,6 +12,7 @@ import arc.struct.*; import arc.util.*; import mindustry.*; import mindustry.content.*; +import mindustry.game.*; import mindustry.game.EventType.*; import mindustry.gen.*; import mindustry.input.*; @@ -54,6 +55,12 @@ public class HintsFragment extends Fragment{ hints.remove(hint); }else if(hint != null){ display(hint); + }else{ + //moused over a derelict structure + var build = world.buildWorld(Core.input.mouseWorldX(), Core.input.mouseWorldY()); + if(build != null && build.team == Team.derelict){ + events.add("derelictmouse"); + } } } }); @@ -157,6 +164,7 @@ public class HintsFragment extends Fragment{ conveyorPathfind(() -> control.input.block == Blocks.titaniumConveyor, () -> Core.input.keyRelease(Binding.diagonal_placement) || (mobile && Core.settings.getBool("swapdiagonal"))), boost(visibleDesktop, () -> !player.dead() && player.unit().type.canBoost, () -> Core.input.keyDown(Binding.boost)), blockInfo(() -> true, () -> ui.content.isShown()), + derelict(() -> ui.hints.events.contains("derelictmouse"), () -> false), command(() -> state.rules.defaultTeam.data().units.size > 3 && !net.active(), () -> player.unit().isCommanding()), payloadPickup(() -> !player.unit().dead && player.unit() instanceof Payloadc p && p.payloads().isEmpty(), () -> player.unit() instanceof Payloadc p && p.payloads().any()), payloadDrop(() -> !player.unit().dead && player.unit() instanceof Payloadc p && p.payloads().any(), () -> player.unit() instanceof Payloadc p && p.payloads().isEmpty()), diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java index 9b857b1ce2..5fc4654cd2 100644 --- a/core/src/mindustry/ui/fragments/HudFragment.java +++ b/core/src/mindustry/ui/fragments/HudFragment.java @@ -545,20 +545,17 @@ public class HudFragment extends Fragment{ } } - public void showLaunchDirect(){ - Image image = new Image(); - image.color.a = 0f; - image.setFillParent(true); - image.actions(Actions.fadeIn(launchDuration / 60f, Interp.pow2In), Actions.delay(8f / 60f), Actions.remove()); - Core.scene.add(image); - } - public void showLaunch(){ + float margin = 30f; + Image image = new Image(); image.color.a = 0f; + image.touchable = Touchable.disabled; image.setFillParent(true); - image.actions(Actions.fadeIn(40f / 60f)); + image.actions(Actions.delay((coreLandDuration - margin) / 60f), Actions.fadeIn(margin / 60f, Interp.pow2In), Actions.delay(6f / 60f), Actions.remove()); image.update(() -> { + image.toFront(); + ui.loadfrag.toFront(); if(state.isMenu()){ image.remove(); } @@ -571,9 +568,10 @@ public class HudFragment extends Fragment{ image.color.a = 1f; image.touchable = Touchable.disabled; image.setFillParent(true); - image.actions(Actions.fadeOut(0.8f), Actions.remove()); + image.actions(Actions.fadeOut(35f / 60f), Actions.remove()); image.update(() -> { image.toFront(); + ui.loadfrag.toFront(); if(state.isMenu()){ image.remove(); } @@ -726,7 +724,7 @@ public class HudFragment extends Fragment{ t.add(new SideBar(() -> player.unit().healthf(), () -> true, true)).width(bw).growY().padRight(pad); t.image(() -> player.icon()).scaling(Scaling.bounded).grow().maxWidth(54f); t.add(new SideBar(() -> player.dead() ? 0f : player.displayAmmo() ? player.unit().ammof() : player.unit().healthf(), () -> !player.displayAmmo(), false)).width(bw).growY().padLeft(pad).update(b -> { - b.color.set(player.displayAmmo() ? player.dead() || player.unit() instanceof BlockUnitc ? Pal.ammo : player.unit().type.ammoType.color : Pal.health); + b.color.set(player.displayAmmo() ? player.dead() || player.unit() instanceof BlockUnitc ? Pal.ammo : player.unit().type.ammoType.color() : Pal.health); }); t.getChildren().get(1).toFront(); diff --git a/core/src/mindustry/ui/fragments/LoadingFragment.java b/core/src/mindustry/ui/fragments/LoadingFragment.java index 348783fe05..a5ab8eeff7 100644 --- a/core/src/mindustry/ui/fragments/LoadingFragment.java +++ b/core/src/mindustry/ui/fragments/LoadingFragment.java @@ -38,13 +38,17 @@ public class LoadingFragment extends Fragment{ text("@loading"); - bar = t.add(new Bar()).pad(3).size(500f, 40f).visible(false).get(); + bar = t.add(new Bar()).pad(3).padTop(6).size(500f, 40f).visible(false).get(); t.row(); button = t.button("@cancel", () -> {}).pad(20).size(250f, 70f).visible(false).get(); table = t; }); } + public void toFront(){ + table.toFront(); + } + public void setProgress(Floatp progress){ bar.reset(0f); bar.visible = true; diff --git a/core/src/mindustry/ui/fragments/MenuFragment.java b/core/src/mindustry/ui/fragments/MenuFragment.java index da51d18ede..ca3001f5b5 100644 --- a/core/src/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/mindustry/ui/fragments/MenuFragment.java @@ -120,7 +120,6 @@ public class MenuFragment extends Fragment{ table.add(tools); table.add(mods); - //if(platform.canDonate()) table.add(donate); if(!ios) table.add(exit); }).colspan(4); }else{ @@ -139,7 +138,6 @@ public class MenuFragment extends Fragment{ table.defaults().set(container.defaults()); table.add(mods); - //if(platform.canDonate()) table.add(donate); if(!ios) table.add(exit); }).colspan(2); } diff --git a/core/src/mindustry/ui/fragments/PlacementFragment.java b/core/src/mindustry/ui/fragments/PlacementFragment.java index b81f6a34f8..04684a2b70 100644 --- a/core/src/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/mindustry/ui/fragments/PlacementFragment.java @@ -15,6 +15,7 @@ import mindustry.core.*; import mindustry.entities.*; import mindustry.entities.units.*; import mindustry.game.EventType.*; +import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.input.*; @@ -38,6 +39,7 @@ public class PlacementFragment extends Fragment{ Block menuHoverBlock; Displayable hover; Object lastDisplayState; + Team lastTeam; boolean wasHovered; Table blockTable, toggler, topTable; ScrollPane blockPane; @@ -283,13 +285,14 @@ public class PlacementFragment extends Fragment{ //don't refresh unnecessarily //refresh only when the hover state changes, or the displayed block changes - if(wasHovered == isHovered && lastDisplayState == displayState) return; + if(wasHovered == isHovered && lastDisplayState == displayState && lastTeam == player.team()) return; topTable.clear(); topTable.top().left().margin(5); lastDisplayState = displayState; wasHovered = isHovered; + lastTeam = player.team(); //show details of selected block, with costs if(displayBlock != null){ diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index 391f6255ca..6411248331 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -71,8 +71,10 @@ public class Block extends UnlockableContent{ public boolean update; /** whether this block has health and can be destroyed */ public boolean destructible; - /** whether unloaders work on this block*/ + /** whether unloaders work on this block */ public boolean unloadable = true; + /** whether units can resupply by taking items from this block */ + public boolean allowResupply = false; /** whether this is solid */ public boolean solid; /** whether this block CAN be solid. */ @@ -431,7 +433,7 @@ public class Block extends UnlockableContent{ boolean buffered = cons.buffered; float capacity = cons.capacity; - bars.add("power", entity -> new Bar(() -> buffered ? Core.bundle.format("bar.poweramount", Float.isNaN(entity.power.status * capacity) ? "" : (int)(entity.power.status * capacity)) : + bars.add("power", entity -> new Bar(() -> buffered ? Core.bundle.format("bar.poweramount", Float.isNaN(entity.power.status * capacity) ? "" : UI.formatAmount((int)(entity.power.status * capacity))) : Core.bundle.get("bar.power"), () -> Pal.powerBar, () -> Mathf.zero(cons.requestedPower(entity)) && entity.power.graph.getPowerProduced() + entity.power.graph.getBatteryStored() > 0f ? 1f : entity.power.status)); } @@ -794,6 +796,11 @@ public class Block extends UnlockableContent{ } clipSize = Math.max(clipSize, size * tilesize); + + //only kept to ensure compatibility with v6 mods. + if(expanded){ + clipSize += tilesize * 10f; + } if(emitLight){ clipSize = Math.max(clipSize, lightRadius * 2f); @@ -882,6 +889,36 @@ public class Block extends UnlockableContent{ } } + //generate paletted team regions + if(teamRegion != null && teamRegion.found()){ + for(Team team : Team.all){ + //if there's an override, don't generate anything + if(team.hasPalette && !Core.atlas.has(name + "-team-" + team.name)){ + var base = Core.atlas.getPixmap(teamRegion); + Pixmap out = new Pixmap(base.width, base.height); + + for(int x = 0; x < base.width; x++){ + for(int y = 0; y < base.height; y++){ + int color = base.get(x, y); + int index = color == 0xffffffff ? 0 : color == 0xdcc6c6ff ? 1 : color == 0x9d7f7fff ? 2 : -1; + out.setRaw(x, y, index == -1 ? base.get(x, y) : team.palettei[index]); + } + } + + if(Core.settings.getBool("linear")){ + Pixmaps.bleed(out); + } + + packer.add(PageType.main, name + "-team-" + team.name, out); + } + } + + teamRegions = new TextureRegion[Team.all.length]; + for(Team team : Team.all){ + teamRegions[team.id] = teamRegion.found() && team.hasPalette ? Core.atlas.find(name + "-team-" + team.name, teamRegion) : teamRegion; + } + } + Pixmap last = null; var gen = icons(); diff --git a/core/src/mindustry/world/ItemBuffer.java b/core/src/mindustry/world/ItemBuffer.java index e9001ac534..d91da022ce 100644 --- a/core/src/mindustry/world/ItemBuffer.java +++ b/core/src/mindustry/world/ItemBuffer.java @@ -2,6 +2,8 @@ package mindustry.world; import arc.util.*; import arc.util.io.*; +import mindustry.annotations.Annotations.*; +import mindustry.gen.*; import mindustry.type.*; import static mindustry.Vars.*; @@ -20,7 +22,7 @@ public class ItemBuffer{ public void accept(Item item, short data){ //if(!accepts()) return; - buffer[index++] = Pack.longInt(Float.floatToIntBits(Time.time), Pack.shortInt(item.id, data)); + buffer[index++] = TimeItem.get(data, item.id, Time.time); } public void accept(Item item){ @@ -30,10 +32,10 @@ public class ItemBuffer{ public Item poll(float speed){ if(index > 0){ long l = buffer[0]; - float time = Float.intBitsToFloat(Pack.leftInt(l)); + float time = TimeItem.time(l); if(Time.time >= time + speed || Time.time < time){ - return content.item(Pack.leftShort(Pack.rightInt(l))); + return content.item(TimeItem.item(l)); } } return null; @@ -63,4 +65,11 @@ public class ItemBuffer{ } index = Math.min(index, length - 1); } + + @Struct + class TimeItemStruct{ + short data; + short item; + float time; + } } diff --git a/core/src/mindustry/world/Tile.java b/core/src/mindustry/world/Tile.java index ebe5d21414..776cb976f3 100644 --- a/core/src/mindustry/world/Tile.java +++ b/core/src/mindustry/world/Tile.java @@ -108,7 +108,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{ } /** - * Returns the flammability of the Used for fire calculations. + * Returns the flammability of the tile. Used for fire calculations. * Takes flammability of floor liquid into account. */ public float getFlammability(){ @@ -675,7 +675,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{ build.health = health; if(build.damaged()){ - indexer.notifyTileDamaged(build); + indexer.notifyBuildDamaged(build); } } diff --git a/core/src/mindustry/world/blocks/ConstructBlock.java b/core/src/mindustry/world/blocks/ConstructBlock.java index 0e6961a245..d77e85e94d 100644 --- a/core/src/mindustry/world/blocks/ConstructBlock.java +++ b/core/src/mindustry/world/blocks/ConstructBlock.java @@ -84,6 +84,11 @@ public class ConstructBlock extends Block{ if(builder != null && builder.getControllerName() != null){ tile.build.lastAccessed = builder.getControllerName(); } + + //make sure block indexer knows it's damaged + if(tile.build.damaged()){ + indexer.notifyBuildDamaged(tile.build); + } } //last builder was this local client player, call placed() diff --git a/core/src/mindustry/world/blocks/campaign/LaunchPad.java b/core/src/mindustry/world/blocks/campaign/LaunchPad.java index c36b5a7a91..8f10c7b5b9 100644 --- a/core/src/mindustry/world/blocks/campaign/LaunchPad.java +++ b/core/src/mindustry/world/blocks/campaign/LaunchPad.java @@ -22,7 +22,6 @@ import mindustry.logic.*; import mindustry.type.*; import mindustry.ui.*; import mindustry.world.*; -import mindustry.world.consumers.*; import mindustry.world.meta.*; import static mindustry.Vars.*; @@ -42,7 +41,6 @@ public class LaunchPad extends Block{ solid = true; update = true; configurable = true; - drawDisabled = false; flags = EnumSet.of(BlockFlag.launchPad); } @@ -73,12 +71,6 @@ public class LaunchPad extends Block{ return !state.isCampaign() || net.client() ? SystemCursor.arrow : super.getCursor(); } - //cannot be disabled - @Override - public float efficiency(){ - return power != null && (block.consumes.has(ConsumeType.power) && !block.consumes.getPower().buffered) ? power.status : 1f; - } - @Override public boolean shouldConsume(){ return true; @@ -156,7 +148,7 @@ public class LaunchPad extends Block{ Sector dest = state.rules.sector == null ? null : state.rules.sector.info.getRealDestination(); return Core.bundle.format("launch.destination", - dest == null ? Core.bundle.get("sectors.nonelaunch") : + dest == null || !dest.hasBase() ? Core.bundle.get("sectors.nonelaunch") : "[accent]" + dest.name()); }).pad(4).wrap().width(200f).left(); } diff --git a/core/src/mindustry/world/blocks/campaign/PayloadLaunchPad.java b/core/src/mindustry/world/blocks/campaign/PayloadLaunchPad.java index e5acad5bf7..3c8cf9481f 100644 --- a/core/src/mindustry/world/blocks/campaign/PayloadLaunchPad.java +++ b/core/src/mindustry/world/blocks/campaign/PayloadLaunchPad.java @@ -21,7 +21,6 @@ import mindustry.logic.*; import mindustry.type.*; import mindustry.ui.*; import mindustry.world.blocks.payloads.*; -import mindustry.world.consumers.*; import mindustry.world.meta.*; import static mindustry.Vars.*; @@ -61,12 +60,6 @@ public class PayloadLaunchPad extends PayloadBlock{ return !state.isCampaign() || net.client() ? SystemCursor.arrow : super.getCursor(); } - //cannot be disabled - @Override - public float efficiency(){ - return power != null && (block.consumes.has(ConsumeType.power) && !block.consumes.getPower().buffered) ? power.status : 1f; - } - @Override public boolean shouldConsume(){ return true; diff --git a/core/src/mindustry/world/blocks/distribution/BufferedItemBridge.java b/core/src/mindustry/world/blocks/distribution/BufferedItemBridge.java index a87fb0348a..6fe8e90722 100644 --- a/core/src/mindustry/world/blocks/distribution/BufferedItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/BufferedItemBridge.java @@ -1,12 +1,11 @@ package mindustry.world.blocks.distribution; -import arc.math.*; import arc.util.io.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; -public class BufferedItemBridge extends ExtendingItemBridge{ +public class BufferedItemBridge extends ItemBridge{ public final int timerAccept = timers++; public float speed = 40f; @@ -19,7 +18,7 @@ public class BufferedItemBridge extends ExtendingItemBridge{ canOverdrive = true; } - public class BufferedItemBridgeBuild extends ExtendingItemBridgeBuild{ + public class BufferedItemBridgeBuild extends ItemBridgeBuild{ ItemBuffer buffer = new ItemBuffer(bufferCapacity); @Override @@ -30,11 +29,9 @@ public class BufferedItemBridge extends ExtendingItemBridge{ Item item = buffer.poll(speed / timeScale); if(timer(timerAccept, 4 / timeScale) && item != null && other.acceptItem(this, item)){ - cycleSpeed = Mathf.lerpDelta(cycleSpeed, 4f, 0.05f); + moved = true; other.handleItem(this, item); buffer.remove(); - }else{ - cycleSpeed = Mathf.lerpDelta(cycleSpeed, 0f, 0.008f); } } diff --git a/core/src/mindustry/world/blocks/distribution/Conveyor.java b/core/src/mindustry/world/blocks/distribution/Conveyor.java index 1714e038df..c45b6a7981 100644 --- a/core/src/mindustry/world/blocks/distribution/Conveyor.java +++ b/core/src/mindustry/world/blocks/distribution/Conveyor.java @@ -32,6 +32,8 @@ public class Conveyor extends Block implements Autotiler{ public float speed = 0f; public float displayedSpeed = 0f; + public @Nullable Block junctionReplacement, bridgeReplacement; + public Conveyor(String name){ super(name); rotate = true; @@ -55,6 +57,14 @@ public class Conveyor extends Block implements Autotiler{ stats.add(Stat.itemsMoved, displayedSpeed, StatUnit.itemsSecond); } + @Override + public void init(){ + super.init(); + + if(junctionReplacement == null) junctionReplacement = Blocks.junction; + if(bridgeReplacement == null || !(bridgeReplacement instanceof ItemBridge)) bridgeReplacement = Blocks.itemBridge; + } + @Override public void drawRequestRegion(BuildPlan req, Eachable list){ int[] bits = getTiling(req, list); @@ -79,7 +89,9 @@ public class Conveyor extends Block implements Autotiler{ @Override public void handlePlacementLine(Seq plans){ - Placement.calculateBridges(plans, (ItemBridge)Blocks.itemBridge); + if(bridgeReplacement == null) return; + + Placement.calculateBridges(plans, (ItemBridge)bridgeReplacement); } @Override @@ -94,12 +106,14 @@ public class Conveyor extends Block implements Autotiler{ @Override public Block getReplacement(BuildPlan req, Seq requests){ + if(junctionReplacement == null) return this; + Boolf cont = p -> requests.contains(o -> o.x == req.x + p.x && o.y == req.y + p.y && (req.block instanceof Conveyor || req.block instanceof Junction)); return cont.get(Geometry.d4(req.rotation)) && cont.get(Geometry.d4(req.rotation - 2)) && req.tile() != null && req.tile().block() instanceof Conveyor && - Mathf.mod(req.tile().build.rotation - req.rotation, 2) == 1 ? Blocks.junction : this; + Mathf.mod(req.tile().build.rotation - req.rotation, 2) == 1 ? junctionReplacement : this; } public class ConveyorBuild extends Building implements ChainedBuilding{ diff --git a/core/src/mindustry/world/blocks/distribution/DuctRouter.java b/core/src/mindustry/world/blocks/distribution/DuctRouter.java index 69f90d52d4..c9f8cb0967 100644 --- a/core/src/mindustry/world/blocks/distribution/DuctRouter.java +++ b/core/src/mindustry/world/blocks/distribution/DuctRouter.java @@ -48,7 +48,7 @@ public class DuctRouter extends Block{ Draw.rect(topRegion, req.drawx(), req.drawy(), req.rotation * 90); } - public class DuctBuild extends Building{ + public class DuctRouterBuild extends Building{ public float progress; public @Nullable Item current; diff --git a/core/src/mindustry/world/blocks/distribution/ExtendingItemBridge.java b/core/src/mindustry/world/blocks/distribution/ExtendingItemBridge.java index 98b48e043a..7e2e5eac55 100644 --- a/core/src/mindustry/world/blocks/distribution/ExtendingItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/ExtendingItemBridge.java @@ -1,70 +1,15 @@ package mindustry.world.blocks.distribution; -import arc.graphics.g2d.*; -import arc.math.*; -import arc.math.geom.*; -import mindustry.core.*; -import mindustry.graphics.*; -import mindustry.world.*; - -import static mindustry.Vars.*; - +/** @deprecated use ItemBridge instead. */ +@Deprecated public class ExtendingItemBridge extends ItemBridge{ public ExtendingItemBridge(String name){ super(name); - hasItems = true; } + @Deprecated public class ExtendingItemBridgeBuild extends ItemBridgeBuild{ - @Override - public void draw(){ - Draw.rect(region, x, y); - Draw.z(Layer.power); - - Tile other = world.tile(link); - if(!linkValid(tile, other)) return; - - int i = tile.absoluteRelativeTo(other.x, other.y); - - float ex = other.worldx() - x - Geometry.d4(i).x * tilesize / 2f, - ey = other.worldy() - y - Geometry.d4(i).y * tilesize / 2f; - - float uptime = state.isEditor() ? 1f : this.uptime; - - ex *= uptime; - ey *= uptime; - - if(Mathf.zero(Renderer.bridgeOpacity)) return; - Draw.alpha(Renderer.bridgeOpacity); - - Lines.stroke(8f); - Lines.line(bridgeRegion, - x + Geometry.d4(i).x * tilesize / 2f, - y + Geometry.d4(i).y * tilesize / 2f, - x + ex, - y + ey, false); - - Draw.rect(endRegion, x, y, i * 90 + 90); - Draw.rect(endRegion, - x + ex + Geometry.d4(i).x * tilesize / 2f, - y + ey + Geometry.d4(i).y * tilesize / 2f, i * 90 + 270); - - int dist = Math.max(Math.abs(other.x - tile.x), Math.abs(other.y - tile.y)); - - int arrows = (dist) * tilesize / 6 - 1; - - Draw.color(); - - for(int a = 0; a < arrows; a++){ - Draw.alpha(Mathf.absin(a / (float)arrows - time / 100f, 0.1f, 1f) * uptime * Renderer.bridgeOpacity); - Draw.rect(arrowRegion, - x + Geometry.d4(i).x * (tilesize / 2f + a * 6f + 2) * uptime, - y + Geometry.d4(i).y * (tilesize / 2f + a * 6f + 2) * uptime, - i * 90f); - } - Draw.reset(); - } } } diff --git a/core/src/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/mindustry/world/blocks/distribution/ItemBridge.java index 19df522079..2ee12f952a 100644 --- a/core/src/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/ItemBridge.java @@ -5,7 +5,6 @@ import arc.graphics.g2d.*; import arc.math.*; import arc.math.geom.*; import arc.struct.*; -import arc.struct.IntSet.*; import arc.util.*; import arc.util.io.*; import mindustry.annotations.Annotations.*; @@ -23,12 +22,20 @@ import static mindustry.Vars.*; public class ItemBridge extends Block{ private static BuildPlan otherReq; + public final int timerCheckMoved = timers ++; + public int range; public float transportTime = 2f; public @Load("@-end") TextureRegion endRegion; public @Load("@-bridge") TextureRegion bridgeRegion; public @Load("@-arrow") TextureRegion arrowRegion; + public boolean fadeIn = true; + public boolean moveArrows = true; + public boolean pulse = false; + public float arrowSpacing = 4f, arrowOffset = 2f, arrowPeriod = 0.4f; + public float arrowTimeScl = 6.2f; + //for autolink public @Nullable ItemBridgeBuild lastBuild; @@ -169,12 +176,10 @@ public class ItemBridge extends Block{ public class ItemBridgeBuild extends Building{ public int link = -1; - //TODO awful - public IntSet incoming = new IntSet(); - public float uptime; - public float time; - public float time2; - public float cycleSpeed = 1f; + public IntSeq incoming = new IntSeq(false, 4); + public float warmup; + public float time = -8f, timeSpeed; + public boolean wasMoved, moved; public float transportCounter; @Override @@ -271,36 +276,44 @@ public class ItemBridge extends Block{ } public void checkIncoming(){ - IntSetIterator it = incoming.iterator(); - while(it.hasNext){ - int i = it.next(); + int idx = 0; + while(idx < incoming.size){ + int i = incoming.items[idx]; Tile other = world.tile(i); if(!linkValid(tile, other, false) || ((ItemBridgeBuild)other.build).link != tile.pos()){ - it.remove(); + incoming.removeIndex(idx); + idx --; } + idx ++; } } @Override public void updateTile(){ - time += cycleSpeed * delta(); - time2 += (cycleSpeed - 1f) * delta(); + if(timer(timerCheckMoved, 30f)){ + wasMoved = moved; + moved = false; + } + + //smooth out animation, so it doesn't stop/start immediately + timeSpeed = Mathf.approachDelta(timeSpeed, wasMoved ? 1f : 0f, 1f / 60f); + + time += timeSpeed * delta(); checkIncoming(); Tile other = world.tile(link); if(!linkValid(tile, other)){ doDump(); - uptime = 0f; + warmup = 0f; }else{ - ((ItemBridgeBuild)other.build).incoming.add(tile.pos()); - - if(consValid() && Mathf.zero(1f - efficiency())){ - uptime = Mathf.lerpDelta(uptime, 1f, 0.04f); - }else{ - uptime = Mathf.lerpDelta(uptime, 0f, 0.02f); + var inc = ((ItemBridgeBuild)other.build).incoming; + int pos = tile.pos(); + if(!inc.contains(pos)){ + inc.add(pos); } + warmup = Mathf.approachDelta(warmup, efficiency(), 1f / 30f); updateTransport(other.build); } } @@ -311,21 +324,18 @@ public class ItemBridge extends Block{ } public void updateTransport(Building other){ - boolean any = false; transportCounter += edelta(); while(transportCounter >= transportTime){ Item item = items.take(); if(item != null && other.acceptItem(this, item)){ other.handleItem(this, item); - any = true; + moved = true; }else if(item != null){ items.add(item, 1); items.undoFlow(item); } transportCounter -= transportTime; } - - cycleSpeed = Mathf.lerpDelta(cycleSpeed, any ? 4f : 1f, any ? 0.05f : 0.01f); } @Override @@ -341,8 +351,13 @@ public class ItemBridge extends Block{ int i = relativeTo(other.x, other.y); - Draw.color(Color.white, Color.black, Mathf.absin(Time.time, 6f, 0.07f)); - Draw.alpha(Math.max(uptime, 0.25f) * Renderer.bridgeOpacity); + if(pulse){ + Draw.color(Color.white, Color.black, Mathf.absin(Time.time, 6f, 0.07f)); + } + + float warmup = hasPower ? this.warmup : 1f; + + Draw.alpha((fadeIn ? Math.max(warmup, 0.25f) : 1f) * Renderer.bridgeOpacity); Draw.rect(endRegion, x, y, i * 90 + 90); Draw.rect(endRegion, other.drawx(), other.drawy(), i * 90 + 270); @@ -357,40 +372,26 @@ public class ItemBridge extends Block{ other.worldx() - Tmp.v1.x, other.worldy() - Tmp.v1.y, false); - int dist = Math.max(Math.abs(other.x - tile.x), Math.abs(other.y - tile.y)); - - float time = time2 / 1.7f; - int arrows = (dist) * tilesize / 4 - 2; + int dist = Math.max(Math.abs(other.x - tile.x), Math.abs(other.y - tile.y)) - 1; Draw.color(); + int arrows = (int)(dist * tilesize / arrowSpacing), dx = Geometry.d4x(i), dy = Geometry.d4y(i); + for(int a = 0; a < arrows; a++){ - Draw.alpha(Mathf.absin(a / (float)arrows - time / 100f, 0.1f, 1f) * uptime * Renderer.bridgeOpacity); + Draw.alpha(Mathf.absin(a - time / arrowTimeScl, arrowPeriod, 1f) * warmup * Renderer.bridgeOpacity); Draw.rect(arrowRegion, - x + Geometry.d4(i).x * (tilesize / 2f + a * 4f + time % 4f), - y + Geometry.d4(i).y * (tilesize / 2f + a * 4f + time % 4f), i * 90f); + x + dx * (tilesize / 2f + a * arrowSpacing + arrowOffset), + y + dy * (tilesize / 2f + a * arrowSpacing + arrowOffset), + i * 90f); } + Draw.reset(); } @Override public boolean acceptItem(Building source, Item item){ - if(team != source.team) return false; - - Tile other = world.tile(link); - - if(items.total() >= itemCapacity) return false; - - if(linked(source)) return true; - - if(linkValid(tile, other)){ - int rel = relativeTo(other); - int rel2 = relativeTo(Edges.getFacingEdge(source, this)); - - return rel != rel2; - } - - return false; + return hasItems && team == source.team && items.total() < itemCapacity && checkAccept(source, world.tile(link)); } @Override @@ -400,16 +401,17 @@ public class ItemBridge extends Block{ @Override public boolean acceptLiquid(Building source, Liquid liquid){ - if(team != source.team || !hasLiquids) return false; - - Tile other = world.tile(link); - - if(!(liquids.current() == liquid || liquids.get(liquids.current()) < 0.2f)) return false; + return + hasLiquids && team == source.team && + (liquids.current() == liquid || liquids.get(liquids.current()) < 0.2f) && + checkAccept(source, world.tile(link)); + } + protected boolean checkAccept(Building source, Tile other){ if(tile == null || linked(source)) return true; if(linkValid(tile, other)){ - int rel = relativeTo(other.x, other.y); + int rel = relativeTo(other); int rel2 = relativeTo(Edges.getFacingEdge(source, this)); return rel != rel2; @@ -433,10 +435,8 @@ public class ItemBridge extends Block{ Tile edge = Edges.getFacingEdge(to.tile, tile); int i = relativeTo(edge.x, edge.y); - IntSetIterator it = incoming.iterator(); - - while(it.hasNext){ - int v = it.next(); + for(int j = 0; j < incoming.size; j++){ + int v = incoming.items[j]; if(relativeTo(Point2.x(v), Point2.y(v)) == i){ return false; } @@ -460,29 +460,38 @@ public class ItemBridge extends Block{ return Point2.unpack(link).sub(tile.x, tile.y); } + @Override + public byte version(){ + return 1; + } + @Override public void write(Writes write){ super.write(write); write.i(link); - write.f(uptime); + write.f(warmup); write.b(incoming.size); - IntSetIterator it = incoming.iterator(); - - while(it.hasNext){ - write.i(it.next()); + for(int i = 0; i < incoming.size; i++){ + write.i(incoming.items[i]); } + + write.bool(wasMoved || moved); } @Override public void read(Reads read, byte revision){ super.read(read, revision); link = read.i(); - uptime = read.f(); + warmup = read.f(); byte links = read.b(); for(int i = 0; i < links; i++){ incoming.add(read.i()); } + + if(revision >= 1){ + wasMoved = moved = read.bool(); + } } } } diff --git a/core/src/mindustry/world/blocks/environment/Floor.java b/core/src/mindustry/world/blocks/environment/Floor.java index 5865a00fb2..b40b7e9667 100644 --- a/core/src/mindustry/world/blocks/environment/Floor.java +++ b/core/src/mindustry/world/blocks/environment/Floor.java @@ -27,7 +27,7 @@ public class Floor extends Block{ public float dragMultiplier = 1f; /** Damage taken per tick on this tile. */ public float damageTaken = 0f; - /** How many ticks it takes to drown on this. */ + /** How many ticks it takes to drown on this. 0 to disable. */ public float drownTime = 0f; /** Effect when walking on this floor. */ public Effect walkEffect = Fx.none; @@ -41,11 +41,11 @@ public class Floor extends Block{ public StatusEffect status = StatusEffects.none; /** Intensity of applied status effect. */ public float statusDuration = 60f; - /** liquids that drop from this block, used for pumps */ + /** liquids that drop from this block, used for pumps. */ public @Nullable Liquid liquidDrop = null; /** Multiplier for pumped liquids, used for deep water. */ public float liquidMultiplier = 1f; - /** whether this block can be drowned in */ + /** whether this block is liquid. */ public boolean isLiquid; /** if true, this block cannot be mined by players. useful for annoying things like sand. */ public boolean playerUnmineable = false; diff --git a/core/src/mindustry/world/blocks/liquid/Conduit.java b/core/src/mindustry/world/blocks/liquid/Conduit.java index 3bfd3958ed..108405ad48 100644 --- a/core/src/mindustry/world/blocks/liquid/Conduit.java +++ b/core/src/mindustry/world/blocks/liquid/Conduit.java @@ -31,6 +31,7 @@ public class Conduit extends LiquidBlock implements Autotiler{ public @Load("@-cap") TextureRegion capRegion; public boolean leaks = true; + public @Nullable Block junctionReplacement, bridgeReplacement; public Conduit(String name){ super(name); @@ -41,6 +42,14 @@ public class Conduit extends LiquidBlock implements Autotiler{ noUpdateDisabled = true; } + @Override + public void init(){ + super.init(); + + if(junctionReplacement == null) junctionReplacement = Blocks.liquidJunction; + if(bridgeReplacement == null || !(bridgeReplacement instanceof ItemBridge)) bridgeReplacement = Blocks.bridgeConduit; + } + @Override public void drawRequestRegion(BuildPlan req, Eachable list){ int[] bits = getTiling(req, list); @@ -58,12 +67,14 @@ public class Conduit extends LiquidBlock implements Autotiler{ @Override public Block getReplacement(BuildPlan req, Seq requests){ + if(junctionReplacement == null) return this; + Boolf cont = p -> requests.contains(o -> o.x == req.x + p.x && o.y == req.y + p.y && o.rotation == req.rotation && (req.block instanceof Conduit || req.block instanceof LiquidJunction)); return cont.get(Geometry.d4(req.rotation)) && cont.get(Geometry.d4(req.rotation - 2)) && req.tile() != null && req.tile().block() instanceof Conduit && - Mathf.mod(req.build().rotation - req.rotation, 2) == 1 ? Blocks.liquidJunction : this; + Mathf.mod(req.build().rotation - req.rotation, 2) == 1 ? junctionReplacement : this; } @Override @@ -73,7 +84,9 @@ public class Conduit extends LiquidBlock implements Autotiler{ @Override public void handlePlacementLine(Seq plans){ - Placement.calculateBridges(plans, (ItemBridge)Blocks.bridgeConduit); + if(bridgeReplacement == null) return; + + Placement.calculateBridges(plans, (ItemBridge)bridgeReplacement); } @Override diff --git a/core/src/mindustry/world/blocks/liquid/LiquidBridge.java b/core/src/mindustry/world/blocks/liquid/LiquidBridge.java index 0944f7fef8..984688a468 100644 --- a/core/src/mindustry/world/blocks/liquid/LiquidBridge.java +++ b/core/src/mindustry/world/blocks/liquid/LiquidBridge.java @@ -1,13 +1,9 @@ package mindustry.world.blocks.liquid; -import arc.math.*; import mindustry.gen.*; -import mindustry.type.*; import mindustry.world.blocks.distribution.*; import mindustry.world.meta.*; -import static mindustry.Vars.*; - public class LiquidBridge extends ItemBridge{ public LiquidBridge(String name){ @@ -21,43 +17,17 @@ public class LiquidBridge extends ItemBridge{ } public class LiquidBridgeBuild extends ItemBridgeBuild{ + @Override - public void updateTile(){ - time += cycleSpeed * delta(); - time2 += (cycleSpeed - 1f) * delta(); - - checkIncoming(); - - Building other = world.build(link); - if(other == null || !linkValid(tile, other.tile())){ - dumpLiquid(liquids.current(), 1f); - }else{ - ((ItemBridgeBuild)other).incoming.add(tile.pos()); - - if(consValid()){ - float alpha = 0.04f; - if(hasPower){ - alpha *= efficiency(); // Exceed boot time unless power is at max. - } - uptime = Mathf.lerpDelta(uptime, 1f, alpha); - }else{ - uptime = Mathf.lerpDelta(uptime, 0f, 0.02f); - } - - if(uptime >= 0.5f){ - - if(moveLiquid(other, liquids.current()) > 0.1f){ - cycleSpeed = Mathf.lerpDelta(cycleSpeed, 4f, 0.05f); - }else{ - cycleSpeed = Mathf.lerpDelta(cycleSpeed, 1f, 0.01f); - } - } + public void updateTransport(Building other){ + if(warmup >= 0.25f){ + moved |= moveLiquid(other, liquids.current()) > 0.05f; } } @Override - public boolean acceptItem(Building source, Item item){ - return false; + public void doDump(){ + dumpLiquid(liquids.current(), 1f); } } } diff --git a/core/src/mindustry/world/blocks/liquid/LiquidExtendingBridge.java b/core/src/mindustry/world/blocks/liquid/LiquidExtendingBridge.java index d08f14d277..37dcc69b7d 100644 --- a/core/src/mindustry/world/blocks/liquid/LiquidExtendingBridge.java +++ b/core/src/mindustry/world/blocks/liquid/LiquidExtendingBridge.java @@ -1,57 +1,14 @@ package mindustry.world.blocks.liquid; -import arc.math.*; -import mindustry.gen.*; -import mindustry.type.*; -import mindustry.world.blocks.distribution.*; -import mindustry.world.meta.*; - -import static mindustry.Vars.*; - -public class LiquidExtendingBridge extends ExtendingItemBridge{ +/** @deprecated use LiquidBridge instead. */ +@Deprecated +public class LiquidExtendingBridge extends LiquidBridge{ public LiquidExtendingBridge(String name){ super(name); - hasItems = false; - hasLiquids = true; - outputsLiquid = true; - group = BlockGroup.liquids; - envEnabled = Env.any; } - public class LiquidExtendingBridgeBuild extends ExtendingItemBridgeBuild{ - @Override - public void updateTile(){ - time += cycleSpeed * delta(); - time2 += (cycleSpeed - 1f) * delta(); - - checkIncoming(); - - Building other = world.build(link); - if(other == null || !linkValid(tile, other.tile())){ - dumpLiquid(liquids.current(), 1f); - }else{ - ((ItemBridgeBuild)other).incoming.add(tile.pos()); - - if(consValid()){ - uptime = Mathf.lerpDelta(uptime, 1f, 0.04f); - }else{ - uptime = Mathf.lerpDelta(uptime, 0f, 0.02f); - } - - if(uptime >= 0.5f){ - if(moveLiquid(other, liquids.current()) > 0.1f){ - cycleSpeed = Mathf.lerpDelta(cycleSpeed, 4f, 0.05f); - }else{ - cycleSpeed = Mathf.lerpDelta(cycleSpeed, 0f, 0.01f); - } - } - } - } - - @Override - public boolean acceptItem(Building source, Item item){ - return false; - } + @Deprecated + public class LiquidExtendingBridgeBuild extends LiquidBridgeBuild{ } } diff --git a/core/src/mindustry/world/blocks/logic/LogicBlock.java b/core/src/mindustry/world/blocks/logic/LogicBlock.java index ac498f38c2..e8cf14ef16 100644 --- a/core/src/mindustry/world/blocks/logic/LogicBlock.java +++ b/core/src/mindustry/world/blocks/logic/LogicBlock.java @@ -177,7 +177,7 @@ public class LogicBlock extends Block{ public boolean active = true, valid; public int x, y; public String name; - Building lastBuild; + public Building lastBuild; public LogicLink(int x, int y, String name, boolean valid){ this.x = x; @@ -400,7 +400,8 @@ public class LogicBlock extends Block{ var cur = world.build(l.x, l.y); boolean valid = validLink(cur); - if(valid != l.valid || (l.lastBuild != null && l.lastBuild != cur)){ + if(l.lastBuild == null) l.lastBuild = cur; + if(valid != l.valid || l.lastBuild != cur){ l.lastBuild = cur; changed = true; l.valid = valid; diff --git a/core/src/mindustry/world/blocks/logic/LogicDisplay.java b/core/src/mindustry/world/blocks/logic/LogicDisplay.java index 2c54d1d1cf..7e6bb10e29 100644 --- a/core/src/mindustry/world/blocks/logic/LogicDisplay.java +++ b/core/src/mindustry/world/blocks/logic/LogicDisplay.java @@ -107,6 +107,15 @@ public class LogicDisplay extends Block{ }); Draw.blend(); } + + @Override + public void remove(){ + super.remove(); + if(buffer != null){ + buffer.dispose(); + buffer = null; + } + } } static int unpackSign(int value){ diff --git a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java index b0b1d1c5a8..86023894e3 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java @@ -193,8 +193,14 @@ public class PayloadBlock extends Block{ } public void dumpPayload(){ + //translate payload forward slightly + float tx = Angles.trnsx(payload.rotation(), 0.1f), ty = Angles.trnsy(payload.rotation(), 0.1f); + payload.set(payload.x() + tx, payload.y() + ty, payload.rotation()); + if(payload.dump()){ payload = null; + }else{ + payload.set(payload.x() - tx, payload.y() - ty, payload.rotation()); } } diff --git a/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java b/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java index 5e04456ac3..7087c5f008 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java @@ -60,6 +60,7 @@ public class PayloadMassDriver extends PayloadBlock{ sync = true; rotate = true; outputsPayload = true; + group = BlockGroup.units; //point2 is relative config(Point2.class, (PayloadDriverBuild tile, Point2 point) -> tile.link = Point2.pack(point.x + tile.tileX(), point.y + tile.tileY())); diff --git a/core/src/mindustry/world/blocks/payloads/PayloadSource.java b/core/src/mindustry/world/blocks/payloads/PayloadSource.java index f64377ede2..62600833b9 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadSource.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadSource.java @@ -30,6 +30,7 @@ public class PayloadSource extends PayloadBlock{ configurable = true; //make sure to display large units. clipSize = 120; + noUpdateDisabled = true; config(Block.class, (PayloadSourceBuild build, Block block) -> { if(canProduce(block) && build.block != block){ @@ -70,11 +71,11 @@ public class PayloadSource extends PayloadBlock{ } public boolean canProduce(Block b){ - return b.isVisible() && b.size < size && !(b instanceof CoreBlock); + return b.isVisible() && b.size < size && !(b instanceof CoreBlock) && !state.rules.bannedBlocks.contains(b); } public boolean canProduce(UnitType t){ - return !t.isHidden(); + return !t.isHidden() && !t.isBanned(); } public class PayloadSourceBuild extends PayloadBlockBuild{ diff --git a/core/src/mindustry/world/blocks/payloads/PayloadVoid.java b/core/src/mindustry/world/blocks/payloads/PayloadVoid.java index fa41218e3c..9ef2cb5800 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadVoid.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadVoid.java @@ -48,6 +48,11 @@ public class PayloadVoid extends PayloadBlock{ drawPayload(); } + @Override + public boolean acceptUnitPayload(Unit unit){ + return true; + } + @Override public void updateTile(){ if(moveInPayload(false) && cons.valid()){ diff --git a/core/src/mindustry/world/blocks/payloads/UnitPayload.java b/core/src/mindustry/world/blocks/payloads/UnitPayload.java index 409f71eabb..dd33a3ca91 100644 --- a/core/src/mindustry/world/blocks/payloads/UnitPayload.java +++ b/core/src/mindustry/world/blocks/payloads/UnitPayload.java @@ -4,6 +4,7 @@ import arc.*; import arc.graphics.*; import arc.graphics.g2d.*; import arc.math.*; +import arc.scene.style.*; import arc.util.*; import arc.util.io.*; import mindustry.*; @@ -14,16 +15,31 @@ import mindustry.game.EventType.*; import mindustry.gen.*; import mindustry.type.*; +import static mindustry.Vars.*; + public class UnitPayload implements Payload{ - public static final float deactiveDuration = 40f; + public static final float overlayDuration = 40f; public Unit unit; - public float deactiveTime = 0f; + public float overlayTime = 0f; + public @Nullable TextureRegion overlayRegion; public UnitPayload(Unit unit){ this.unit = unit; } + /** Flashes a red overlay region. */ + public void showOverlay(TextureRegion icon){ + overlayRegion = icon; + overlayTime = 1f; + } + + /** Flashes a red overlay region. */ + public void showOverlay(TextureRegionDrawable icon){ + if(icon == null || headless) return; + showOverlay(icon.getRegion()); + } + @Override public ItemStack[] requirements(){ return unit.type.getTotalRequirements(); @@ -73,7 +89,8 @@ public class UnitPayload implements Payload{ if(unit.type == null) return true; if(!Units.canCreate(unit.team, unit.type)){ - deactiveTime = 1f; + overlayTime = 1f; + overlayRegion = null; return false; } @@ -122,16 +139,17 @@ public class UnitPayload implements Payload{ unit.type.drawCell(unit); //draw warning - if(deactiveTime > 0){ + if(overlayTime > 0){ + var region = overlayRegion == null ? Icon.warning.getRegion() : overlayRegion; Draw.color(Color.scarlet); - Draw.alpha(0.8f * Interp.exp5Out.apply(deactiveTime)); + Draw.alpha(0.8f * Interp.exp5Out.apply(overlayTime)); float size = 8f; - Draw.rect(Icon.warning.getRegion(), unit.x, unit.y, size, size); + Draw.rect(region, unit.x, unit.y, size, size); Draw.reset(); - deactiveTime = Math.max(deactiveTime - Time.delta/deactiveDuration, 0f); + overlayTime = Math.max(overlayTime - Time.delta/overlayDuration, 0f); } } diff --git a/core/src/mindustry/world/blocks/power/LightBlock.java b/core/src/mindustry/world/blocks/power/LightBlock.java index 3b42f1a0cb..36fc8c0f5f 100644 --- a/core/src/mindustry/world/blocks/power/LightBlock.java +++ b/core/src/mindustry/world/blocks/power/LightBlock.java @@ -37,7 +37,8 @@ public class LightBlock extends Block{ @Override public void init(){ - lightRadius = radius; + //double needed for some reason + lightRadius = radius*2f; emitLight = true; super.init(); } diff --git a/core/src/mindustry/world/blocks/power/PowerGenerator.java b/core/src/mindustry/world/blocks/power/PowerGenerator.java index 5a2bd12f0d..fe86c5fd15 100644 --- a/core/src/mindustry/world/blocks/power/PowerGenerator.java +++ b/core/src/mindustry/world/blocks/power/PowerGenerator.java @@ -61,16 +61,25 @@ public class PowerGenerator extends PowerDistributor{ return powerProduction * productionEfficiency; } + @Override + public byte version(){ + return 1; + } + @Override public void write(Writes write){ super.write(write); write.f(productionEfficiency); + write.f(generateTime); } @Override public void read(Reads read, byte revision){ super.read(read, revision); productionEfficiency = read.f(); + if(revision >= 1){ + generateTime = read.f(); + } } } } diff --git a/core/src/mindustry/world/blocks/power/PowerNode.java b/core/src/mindustry/world/blocks/power/PowerNode.java index 2cf6718522..35fa1a3291 100644 --- a/core/src/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/mindustry/world/blocks/power/PowerNode.java @@ -364,6 +364,7 @@ public class PowerNode extends PowerBlock{ @Override public void dropped(){ power.links.clear(); + updatePowerGraph(); } @Override diff --git a/core/src/mindustry/world/blocks/production/AttributeCrafter.java b/core/src/mindustry/world/blocks/production/AttributeCrafter.java index d1480f6a16..ac2f7ceeee 100644 --- a/core/src/mindustry/world/blocks/production/AttributeCrafter.java +++ b/core/src/mindustry/world/blocks/production/AttributeCrafter.java @@ -26,11 +26,11 @@ public class AttributeCrafter extends GenericCrafter{ public void setBars(){ super.setBars(); - bars.add("efficiency", entity -> + bars.add("efficiency", (AttributeCrafterBuild entity) -> new Bar(() -> - Core.bundle.format("bar.efficiency", (int)(entity.efficiency() * 100)), + Core.bundle.format("bar.efficiency", (int)(entity.efficiencyScale() * 100)), () -> Pal.lightOrange, - entity::efficiency)); + entity::efficiencyScale)); } @Override @@ -44,8 +44,12 @@ public class AttributeCrafter extends GenericCrafter{ public float attrsum; @Override - public float efficiency(){ - return (baseEfficiency + Math.min(maxBoost, boostScale * attrsum) + attribute.env()) * super.efficiency(); + public float getProgressIncrease(float base){ + return super.getProgressIncrease(base) * efficiencyScale(); + } + + public float efficiencyScale(){ + return baseEfficiency + Math.min(maxBoost, boostScale * attrsum) + attribute.env(); } @Override diff --git a/core/src/mindustry/world/blocks/production/Pump.java b/core/src/mindustry/world/blocks/production/Pump.java index 49d700342f..9a9aca65c3 100644 --- a/core/src/mindustry/world/blocks/production/Pump.java +++ b/core/src/mindustry/world/blocks/production/Pump.java @@ -88,7 +88,7 @@ public class Pump extends LiquidBlock{ public void draw(){ Draw.rect(name, x, y); - Drawf.liquid(liquidRegion, x, y, liquids.total() / liquidCapacity, liquids.current().color); + Drawf.liquid(liquidRegion, x, y, liquids.currentAmount() / liquidCapacity, liquids.current().color); } @Override diff --git a/core/src/mindustry/world/blocks/production/Separator.java b/core/src/mindustry/world/blocks/production/Separator.java index a863178208..8fb7a09998 100644 --- a/core/src/mindustry/world/blocks/production/Separator.java +++ b/core/src/mindustry/world/blocks/production/Separator.java @@ -8,6 +8,7 @@ import arc.util.io.*; import mindustry.annotations.Annotations.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.logic.*; import mindustry.type.*; import mindustry.world.*; import mindustry.world.consumers.*; @@ -123,6 +124,12 @@ public class Separator extends Block{ } } + @Override + public double sense(LAccess sensor){ + if(sensor == LAccess.progress) return progress; + return super.sense(sensor); + } + @Override public boolean canDump(Building to, Item item){ return !consumes.itemFilters.get(item.id); diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 4c3e405a74..0fab6fc94d 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -20,7 +20,6 @@ import mindustry.logic.*; import mindustry.type.*; import mindustry.ui.*; import mindustry.world.*; -import mindustry.world.blocks.units.*; import mindustry.world.meta.*; import mindustry.world.modules.*; @@ -30,15 +29,13 @@ public class CoreBlock extends StorageBlock{ //hacky way to pass item modules between methods private static ItemModule nextItems; + public @Load(value = "@-thruster1", fallback = "clear-effect") TextureRegion thruster1; //top right + public @Load(value = "@-thruster2", fallback = "clear-effect") TextureRegion thruster2; //bot left + public float thrusterLength = 14f/4f; + public UnitType unitType = UnitTypes.alpha; - public final int timerResupply = timers++; - - public int ammoAmount = 5; - public float resupplyRate = 10f; - public float resupplyRange = 60f; public float captureInvicibility = 60f * 15f; - public Item resupplyItem = Items.copper; public CoreBlock(String name){ super(name); @@ -183,6 +180,35 @@ public class CoreBlock extends StorageBlock{ public boolean noEffect = false; public Team lastDamage = Team.derelict; public float iframes = -1f; + public float thrusterTime = 0f; + + @Override + public void draw(){ + //draw thrusters when just landed + if(thrusterTime > 0){ + float frame = thrusterTime; + + Draw.alpha(1f); + drawThrusters(frame); + Draw.rect(block.region, x, y); + Draw.alpha(Interp.pow4In.apply(frame)); + drawThrusters(frame); + Draw.reset(); + + drawTeamTop(); + }else{ + super.draw(); + } + } + + public void drawThrusters(float frame){ + float length = thrusterLength * (frame - 1f) - 1f/4f; + for(int i = 0; i < 4; i++){ + var reg = i >= 2 ? thruster2 : thruster1; + float dx = Geometry.d4x[i] * length, dy = Geometry.d4y[i] * length; + Draw.rect(reg, x + dx, y + dy, i * 90); + } + } @Override public void damage(@Nullable Team source, float damage){ @@ -222,7 +248,7 @@ public class CoreBlock extends StorageBlock{ @Override public void onControlSelect(Player player){ Fx.spawn.at(player); - if(net.client()){ + if(net.client() && player == Vars.player){ control.input.controlledType = null; } @@ -240,13 +266,8 @@ public class CoreBlock extends StorageBlock{ @Override public void updateTile(){ - iframes -= Time.delta; - - //resupply nearby units - if(items.has(resupplyItem) && timer(timerResupply, resupplyRate) && ResupplyPoint.resupply(this, resupplyRange, ammoAmount, resupplyItem.color)){ - items.remove(resupplyItem, 1); - } + thrusterTime -= Time.delta/90f; } @Override @@ -281,7 +302,13 @@ public class CoreBlock extends StorageBlock{ @Override public void afterDestroyed(){ if(state.rules.coreCapture){ - tile.setNet(block, lastDamage, 0); + if(!net.client()){ + tile.setBlock(block, lastDamage); + } + + //delay so clients don't destroy it afterwards + Core.app.post(() -> tile.setNet(block, lastDamage, 0)); + //building does not exist on client yet if(!net.client()){ //core is invincible for several seconds to prevent recapture diff --git a/core/src/mindustry/world/blocks/storage/StorageBlock.java b/core/src/mindustry/world/blocks/storage/StorageBlock.java index 7dddce05b2..6135288c3c 100644 --- a/core/src/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/mindustry/world/blocks/storage/StorageBlock.java @@ -22,6 +22,7 @@ public class StorageBlock extends Block{ destructible = true; group = BlockGroup.transportation; flags = EnumSet.of(BlockFlag.storage); + allowResupply = true; envEnabled = Env.any; } @@ -41,7 +42,7 @@ public class StorageBlock extends Block{ } public class StorageBuild extends Building{ - protected @Nullable Building linkedCore; + public @Nullable Building linkedCore; @Override public boolean acceptItem(Building source, Item item){ diff --git a/core/src/mindustry/world/blocks/units/CommandCenter.java b/core/src/mindustry/world/blocks/units/CommandCenter.java index 5ad9de807e..3d8f9c024f 100644 --- a/core/src/mindustry/world/blocks/units/CommandCenter.java +++ b/core/src/mindustry/world/blocks/units/CommandCenter.java @@ -26,12 +26,13 @@ public class CommandCenter extends Block{ public Color topColor = null, bottomColor = Color.valueOf("5e5e5e"); public Effect effect = Fx.commandSend; public float effectSize = 150f; + public float forceRadius = 31f, forceStrength = 0.2f; public CommandCenter(String name){ super(name); flags = EnumSet.of(BlockFlag.rally); - destructible = true; + update = true; solid = true; configurable = true; drawDisabled = false; @@ -73,6 +74,22 @@ public class CommandCenter extends Block{ return team.data().command; } + @Override + public void updateTile(){ + super.updateTile(); + + //push away allied units + team.data().tree().intersect(x - forceRadius/2f, y - forceRadius/2f, forceRadius, forceRadius, u -> { + if(!u.isPlayer()){ + float dst = dst(u); + float rs = forceRadius + u.hitSize/2f; + if(dst < rs){ + u.vel.add(Tmp.v1.set(u).sub(x, y).setLength(1f - dst / rs).scl(forceStrength)); + } + } + }); + } + @Override public void draw(){ super.draw(); diff --git a/core/src/mindustry/world/blocks/units/Reconstructor.java b/core/src/mindustry/world/blocks/units/Reconstructor.java index 89ded06fef..9521a6c87a 100644 --- a/core/src/mindustry/world/blocks/units/Reconstructor.java +++ b/core/src/mindustry/world/blocks/units/Reconstructor.java @@ -116,11 +116,28 @@ public class Reconstructor extends UnitBlock{ @Override public boolean acceptPayload(Building source, Payload payload){ - return this.payload == null - && (this.enabled || source == this) - && relativeTo(source) != rotation - && payload instanceof UnitPayload pay - && hasUpgrade(pay.unit.type); + if(!(this.payload == null + && (this.enabled || source == this) + && relativeTo(source) != rotation + && payload instanceof UnitPayload pay)){ + return false; + } + + var upgrade = upgrade(pay.unit.type); + + if(upgrade != null){ + if(!upgrade.unlockedNow()){ + //flash "not researched" + pay.showOverlay(Icon.tree); + } + + if(upgrade.isBanned()){ + //flash an X, meaning 'banned' + pay.showOverlay(Icon.cancel); + } + } + + return upgrade != null && upgrade.unlockedNow() && !upgrade.isBanned(); } @Override @@ -224,7 +241,7 @@ public class Reconstructor extends UnitBlock{ public boolean hasUpgrade(UnitType type){ UnitType t = upgrade(type); - return t != null && t.unlockedNow(); + return t != null && t.unlockedNow() && !type.isBanned(); } public UnitType upgrade(UnitType type){ diff --git a/core/src/mindustry/world/blocks/units/ResupplyPoint.java b/core/src/mindustry/world/blocks/units/ResupplyPoint.java deleted file mode 100644 index aa765127a9..0000000000 --- a/core/src/mindustry/world/blocks/units/ResupplyPoint.java +++ /dev/null @@ -1,77 +0,0 @@ -package mindustry.world.blocks.units; - -import arc.func.*; -import arc.graphics.*; -import arc.struct.*; -import mindustry.content.*; -import mindustry.entities.*; -import mindustry.game.*; -import mindustry.gen.*; -import mindustry.graphics.*; -import mindustry.type.AmmoTypes.*; -import mindustry.world.*; -import mindustry.world.meta.*; - -import static mindustry.Vars.*; - -public class ResupplyPoint extends Block{ - public final int timerResupply = timers++; - - public int ammoAmount = 10; - public float resupplyRate = 5f; - public float range = 60f; - public Color ammoColor = Items.copper.color; - - public ResupplyPoint(String name){ - super(name); - solid = update = true; - hasItems = true; - flags = EnumSet.of(BlockFlag.resupply); - } - - @Override - public boolean outputsItems(){ - return false; - } - - @Override - public void drawPlace(int x, int y, int rotation, boolean valid){ - Drawf.dashCircle(x * tilesize + offset, y * tilesize + offset, range, Pal.placing); - } - - public class ResupplyPointBuild extends Building{ - - @Override - public void drawSelect(){ - Drawf.dashCircle(x, y, range, team.color); - } - - @Override - public void updateTile(){ - if(consValid() && timer(timerResupply, resupplyRate / timeScale) && resupply(this, range, ammoAmount, ammoColor)){ - consume(); - } - } - } - - /** Tries to resupply nearby units. - * @return whether resupplying was successful. If unit ammo is disabled, always returns false. */ - public static boolean resupply(Building tile, float range, float ammoAmount, Color ammoColor){ - return resupply(tile.team, tile.x, tile.y, range, ammoAmount, ammoColor, u -> true); - } - - /** Tries to resupply nearby units. - * @return whether resupplying was successful. If unit ammo is disabled, always returns false. */ - public static boolean resupply(Team team, float x, float y, float range, float ammoAmount, Color ammoColor, Boolf valid){ - if(!state.rules.unitAmmo) return false; - - Unit unit = Units.closest(team, x, y, range, u -> u.type.ammoType instanceof ItemAmmoType && u.ammo <= u.type.ammoCapacity - ammoAmount && valid.get(u)); - if(unit != null){ - Fx.itemTransfer.at(x, y, ammoAmount / 2f, ammoColor, unit); - unit.ammo = Math.min(unit.ammo + ammoAmount, unit.type.ammoCapacity); - return true; - } - - return false; - } -} diff --git a/core/src/mindustry/world/blocks/units/UnitFactory.java b/core/src/mindustry/world/blocks/units/UnitFactory.java index 8c337e9919..bbef9cb456 100644 --- a/core/src/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/mindustry/world/blocks/units/UnitFactory.java @@ -149,7 +149,7 @@ public class UnitFactory extends UnitBlock{ @Override public void buildConfiguration(Table table){ - Seq units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow()); + Seq units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow() && !u.isBanned()); if(units.any()){ ItemSelection.buildTable(table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit))); @@ -225,6 +225,12 @@ public class UnitFactory extends UnitBlock{ if(currentPlan != -1 && payload == null){ UnitPlan plan = plans.get(currentPlan); + //make sure to reset plan when the unit got banned after placement + if(plan.unit.isBanned()){ + currentPlan = -1; + return; + } + if(progress >= plan.time && consValid()){ progress %= 1f; diff --git a/core/src/mindustry/world/meta/BlockFlag.java b/core/src/mindustry/world/meta/BlockFlag.java index c68e396278..985b66c181 100644 --- a/core/src/mindustry/world/meta/BlockFlag.java +++ b/core/src/mindustry/world/meta/BlockFlag.java @@ -18,13 +18,8 @@ public enum BlockFlag{ rally, /** Block that stored power for resupply. */ battery, - /** Block used for resupply. */ - resupply, /** Any reactor block. */ reactor, - /** This flag is unused, and will be removed. */ - @Deprecated - unitModifier, /** Blocks that extinguishes fires. */ extinguisher, /** Just a launch pad. */ @@ -33,5 +28,5 @@ public enum BlockFlag{ public final static BlockFlag[] all = values(); /** Values for logic only. Filters out some internal flags. */ - public final static BlockFlag[] allLogic = {core, storage, generator, turret, factory, repair, rally, battery, resupply, reactor}; + public final static BlockFlag[] allLogic = {core, storage, generator, turret, factory, repair, rally, battery, reactor}; } diff --git a/core/src/mindustry/world/modules/LiquidModule.java b/core/src/mindustry/world/modules/LiquidModule.java index 5713129506..3f17a09940 100644 --- a/core/src/mindustry/world/modules/LiquidModule.java +++ b/core/src/mindustry/world/modules/LiquidModule.java @@ -143,11 +143,12 @@ public class LiquidModule extends BlockModule{ int count = legacy ? read.ub() : read.s(); for(int j = 0; j < count; j++){ - int liquidid = legacy ? read.ub() : read.s(); + Liquid liq = content.liquid(legacy ? read.ub() : read.s()); + int liquidid = liq.id; float amount = read.f(); liquids[liquidid] = amount; if(amount > 0){ - current = content.liquid(liquidid); + current = liq; } this.total += amount; } diff --git a/desktop/build.gradle b/desktop/build.gradle index dfcc365f79..981815b7fc 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -126,6 +126,7 @@ platforms.each{ platform -> } args += "Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1" + args += "XX:+ShowCodeDetailsInExceptionMessages" exec{ commandLine args.toList() diff --git a/desktop/src/mindustry/desktop/DesktopLauncher.java b/desktop/src/mindustry/desktop/DesktopLauncher.java index 1d289847ae..1de468f504 100644 --- a/desktop/src/mindustry/desktop/DesktopLauncher.java +++ b/desktop/src/mindustry/desktop/DesktopLauncher.java @@ -100,9 +100,6 @@ public class DesktopLauncher extends ClientLauncher{ if(SteamAPI.restartAppIfNecessary(SVars.steamID)){ System.exit(0); } - }catch(NullPointerException ignored){ - steam = false; - Log.info("Running in offline mode."); }catch(Throwable e){ steam = false; Log.err("Failed to load Steam native libraries."); diff --git a/desktop/src/mindustry/desktop/steam/SWorkshop.java b/desktop/src/mindustry/desktop/steam/SWorkshop.java index 23a22360d4..9799da60d8 100644 --- a/desktop/src/mindustry/desktop/steam/SWorkshop.java +++ b/desktop/src/mindustry/desktop/steam/SWorkshop.java @@ -33,10 +33,9 @@ public class SWorkshop implements SteamUGCCallback{ ItemInstallInfo info = new ItemInstallInfo(); ugc.getSubscribedItems(ids); - Seq folders = Seq.with(ids).map(f -> { - ugc.getItemInstallInfo(f, info); - return new Fi(info.getFolder()); - }).select(f -> f != null && f.list().length > 0); + Seq folders = Seq.with(ids) + .map(f -> !ugc.getItemInstallInfo(f, info) || info.getFolder() == null ? null : new Fi(info.getFolder())) + .select(f -> f != null && f.list().length > 0); workshopFiles.put(Map.class, folders.select(f -> f.list().length == 1 && f.list()[0].extension().equals(mapExtension)).map(f -> f.list()[0])); workshopFiles.put(Schematic.class, folders.select(f -> f.list().length == 1 && f.list()[0].extension().equals(schematicExtension)).map(f -> f.list()[0])); diff --git a/gradle.properties b/gradle.properties index ba90b53b7a..2917c3abef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,5 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xms256m -Xmx1024m --illegal-access=permit -# Don't recompute annotations if sources haven't been changed -kapt.incremental.apt = true # Multithreaded kapt.use.worker.api=true # Compilation avoidance (see https://kotlinlang.org/docs/kapt.html#compile-avoidance-for-kapt-since-1-3-20) @@ -10,4 +8,7 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=47822d851954fd2707d51731042056450f07ca8c +#used for slow jitpack builds; TODO see if this actually works +http.socketTimeout=80000 +http.connectionTimeout=80000 +archash=40c21b302ccc1e74f4c2a37f937c88acaec99254 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 69a9715077..05679dc3c1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/server/src/mindustry/server/ServerControl.java b/server/src/mindustry/server/ServerControl.java index a75cc39749..3d378f4d25 100644 --- a/server/src/mindustry/server/ServerControl.java +++ b/server/src/mindustry/server/ServerControl.java @@ -380,6 +380,8 @@ public class ServerControl implements ApplicationListener{ maps.reload(); if(maps.all().size > beforeMaps){ info("@ new map(s) found and reloaded.", maps.all().size - beforeMaps); + }else if(maps.all().size < beforeMaps){ + info("@ old map(s) deleted.", beforeMaps - maps.all().size); }else{ info("Maps reloaded."); } diff --git a/servers_v6.json b/servers_v6.json index 98a1079bd4..1c9ccc0590 100644 --- a/servers_v6.json +++ b/servers_v6.json @@ -57,11 +57,11 @@ }, { "name": "Omega", - "address": ["178.170.47.34:20204", "157.90.213.2:30308", "157.90.180.53:25738", "185.86.230.61:25578"] + "address": ["178.170.47.34:20204", "157.90.213.2:30308", "157.90.180.53:25738", "185.86.230.61:25578", "mindustry.me:7172"] }, { "name": "md.obvilionnetwork.ru", - "address": ["obvilionnetwork.ru", "obvilionnetwork.ru:7001", "obvilionnetwork.ru:7002"] + "address": ["obvilionnetwork.ru", "obvilionnetwork.ru:7001", "obvilionnetwork.ru:7002", "obvilionnetwork.ru:7003"] }, { "name": "Mindustry PLAY", @@ -77,7 +77,7 @@ }, { "name": "TSR", - "address": ["de15-3.falix.gg:27422"] + "address": ["ult4.falix.gg:26904"] }, { "name": "Sakura", diff --git a/servers_v7.json b/servers_v7.json index 9e6ad5f4ab..4e34aeb15b 100644 --- a/servers_v7.json +++ b/servers_v7.json @@ -5,19 +5,15 @@ }, { "name": "C.A.M.S.", - "address": ["baseduser.eu.org:6569", "v7.thedimas.pp.ua"] + "address": ["baseduser.eu.org:6569", "v7.thedimas.pp.ua", "mindustry.me:7000"] }, { "name": "hexpvp.ml", "address": "hexpvp.ml" }, - { - "name": "[accent]Mindustry [red]Reborn", - "address": "mindustry.me:7000" - }, { "name": "Omega", - "address": ["185.86.230.61:25571", "185.86.230.61:25570", "185.86.230.62:25572"] + "address": ["185.86.230.61:25571", "185.86.230.61:25570", "185.86.230.62:25572","mindustry.me:7175"] }, { "name": "MeowLand", diff --git a/settings.gradle b/settings.gradle index 76eaa676a6..7a19432101 100644 --- a/settings.gradle +++ b/settings.gradle @@ -22,7 +22,11 @@ if(new File(settingsDir, 'local.properties').exists()){ if(System.getenv("JITPACK") == "true") hasSdk = false if(hasSdk){ - include 'android' + //hack: pretend the Android module doesn't exist when imported through IntelliJ + //why? because IntelliJ chokes on the new version of the Android plugin + if(!System.getProperty("jna.tmpdir")?.contains("JetBrains")){ + include 'android' + } }else{ println("No Android SDK found. Skipping Android module.") } diff --git a/tests/src/test/java/power/FakeGraphics.java b/tests/src/test/java/power/FakeGraphics.java index 5f64aa61f3..4bbd0bb24c 100644 --- a/tests/src/test/java/power/FakeGraphics.java +++ b/tests/src/test/java/power/FakeGraphics.java @@ -154,7 +154,7 @@ public class FakeGraphics extends Graphics{ } @Override - public void setUndecorated(boolean undecorated){ + public void setBorderless(boolean undecorated){ } diff --git a/tools/src/mindustry/tools/Generators.java b/tools/src/mindustry/tools/Generators.java index c78e7dbb5f..b1468997f2 100644 --- a/tools/src/mindustry/tools/Generators.java +++ b/tools/src/mindustry/tools/Generators.java @@ -244,7 +244,7 @@ public class Generators{ teamr.each((x, y) -> { int color = teamr.getRaw(x, y); int index = color == 0xffffffff ? 0 : color == 0xdcc6c6ff ? 1 : color == 0x9d7f7fff ? 2 : -1; - out.setRaw(x, y, index == -1 ? teamr.getRaw(x, y) : team.palette[index].rgba()); + out.setRaw(x, y, index == -1 ? teamr.getRaw(x, y) : team.palettei[index]); }); save(out, block.name + "-team-" + team.name); @@ -390,6 +390,19 @@ public class Generators{ } }); + generate("team-icons", () -> { + for(Team team : Team.all){ + if(has("team-" + team.name)){ + int rgba = team == Team.derelict ? Color.valueOf("b7b8c9").rgba() : team.color.rgba(); + Pixmap base = get("team-" + team.name); + base.each((x, y) -> base.setRaw(x, y, Color.muli(base.getRaw(x, y), rgba))); + + delete("team-" + team.name); + save(base.outline(Pal.gray, 3), "../ui/team-" + team.name); + } + } + }); + generate("unit-icons", () -> content.units().each(type -> { if(type.isHidden()) return; //hidden units don't generate diff --git a/tools/src/mindustry/tools/ImagePacker.java b/tools/src/mindustry/tools/ImagePacker.java index 0df257f52f..68a06a2f66 100644 --- a/tools/src/mindustry/tools/ImagePacker.java +++ b/tools/src/mindustry/tools/ImagePacker.java @@ -236,6 +236,10 @@ public class ImagePacker{ base.draw(image, 0, 0, image.width, image.height, base.width/2 - wx/2, base.height/2 - wy/2, wx, wy, true, true); } + static void delete(String name){ + ((GenRegion)Core.atlas.find(name)).path.delete(); + } + static void replace(String name, Pixmap image){ Fi.get(name + ".png").writePng(image); ((GenRegion)Core.atlas.find(name)).path.delete(); diff --git a/tools/src/mindustry/tools/ScriptMainGenerator.java b/tools/src/mindustry/tools/ScriptMainGenerator.java index 14ffde2b2b..42ffc6d797 100644 --- a/tools/src/mindustry/tools/ScriptMainGenerator.java +++ b/tools/src/mindustry/tools/ScriptMainGenerator.java @@ -80,6 +80,7 @@ public class ScriptMainGenerator{ "mindustry.ai.types", "mindustry.type.weather", "mindustry.type.weapons", + "mindustry.type.ammo", "mindustry.game.Objectives", "mindustry.world.blocks", "mindustry.world.draw",