diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index eb2dcff192..71185f740f 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -22,7 +22,7 @@ jobs:
- name: Run unit tests and build JAR
run: ./gradlew desktop:dist
- name: Upload desktop JAR for testing
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Desktop JAR (zipped)
path: desktop/build/libs/Mindustry.jar
diff --git a/README.md b/README.md
index 9624632b29..30e864545c 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ See [CONTRIBUTING](CONTRIBUTING.md).
Bleeding-edge builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases).
If you'd rather compile on your own, follow these instructions.
-First, make sure you have [JDK 16-17](https://adoptium.net/archive.html?variant=openjdk17&jvmVariant=hotspot) installed. **Other JDK versions will not work.** Open a terminal in the Mindustry directory and run the following commands:
+First, make sure you have [JDK 17](https://adoptium.net/archive.html?variant=openjdk17&jvmVariant=hotspot) installed. **Other JDK versions will not work.** Open a terminal in the Mindustry directory and run the following commands:
### Windows
@@ -53,6 +53,16 @@ To debug the application on a connected device/emulator, run `gradlew android:in
If the terminal returns `Permission denied` or `Command not found` on Mac/Linux, run `chmod +x ./gradlew` before running `./gradlew`. *This is a one-time procedure.*
+#### Where is the `mindustry.gen` package?
+
+As the name implies, `mindustry.gen` is generated *at build time* based on other code. You will not find source code for this package in the repository, and it should not be edited by hand.
+
+The following is a non-exhaustive list of the "source" of generated code in `mindustry.gen`:
+
+- `Call`, `*Packet` classes: Generated from methods marked with `@Remote`.
+- All entity classes (`Unit`, `EffectState`, `Posc`, etc): Generated from component classes in the `mindustry.entities.comp` package, and combined using definitions in `mindustry.content.UnitTypes`.
+- `Sounds`, `Musics`, `Tex`, `Icon`, etc: Generated based on files in the respective asset folders.
+
---
Gradle may take up to several minutes to download files. Be patient.
diff --git a/SERVERLIST.md b/SERVERLIST.md
index f18655ff14..bdc199602b 100644
--- a/SERVERLIST.md
+++ b/SERVERLIST.md
@@ -1,3 +1,7 @@
+# Note: Server list review is currently on pause. No new servers will be merged until v8 is released!
+
+*PRs to edit addresses of existing servers will still be accepted, although very infrequently.*
+
### Adding a server to the list
Mindustry now has a public list of servers that everyone can see and connect to.
diff --git a/android/src/mindustry/android/AndroidLauncher.java b/android/src/mindustry/android/AndroidLauncher.java
index c8175aa4f0..548f1b6078 100644
--- a/android/src/mindustry/android/AndroidLauncher.java
+++ b/android/src/mindustry/android/AndroidLauncher.java
@@ -38,7 +38,7 @@ public class AndroidLauncher extends AndroidApplication{
UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler((thread, error) -> {
- CrashSender.log(error);
+ CrashHandler.log(error);
//try to forward exception to system handler
if(handler != null){
@@ -110,6 +110,7 @@ public class AndroidLauncher extends AndroidApplication{
Intent intent = new Intent(open ? Intent.ACTION_OPEN_DOCUMENT : Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(extension.equals("zip") && !open && extensions.length == 1 ? "application/zip" : "*/*");
+ intent.putExtra(Intent.EXTRA_TITLE, "export." + extension);
addResultListener(i -> startActivityForResult(intent, i), (code, in) -> {
if(code == Activity.RESULT_OK && in != null && in.getData() != null){
diff --git a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java
index 3abd583158..a6b1d95d67 100644
--- a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java
+++ b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java
@@ -445,6 +445,7 @@ public class EntityProcess extends BaseProcessor{
MethodSpec.Builder mbuilder = MethodSpec.methodBuilder(first.name()).addModifiers(first.is(Modifier.PRIVATE) ? Modifier.PRIVATE : Modifier.PUBLIC);
//if(isFinal || entry.value.contains(s -> s.has(Final.class))) mbuilder.addModifiers(Modifier.FINAL);
if(entry.value.contains(s -> s.has(CallSuper.class))) mbuilder.addAnnotation(CallSuper.class); //add callSuper here if necessary
+ if(first.has(Nullable.class)) mbuilder.addAnnotation(Nullable.class);
if(first.is(Modifier.STATIC)) mbuilder.addModifiers(Modifier.STATIC);
mbuilder.addTypeVariables(first.typeVariables().map(TypeVariableName::get));
mbuilder.returns(first.retn());
diff --git a/build.gradle b/build.gradle
index 9bca8edb25..6a49b0ce6e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -10,7 +10,7 @@ buildscript{
return "com.github.Anuken${localArc ? "" : ".Arc"}:$name:$arcHash"
}
}
-
+
repositories{
mavenLocal()
mavenCentral()
@@ -32,7 +32,7 @@ plugins{
allprojects{
apply plugin: 'maven-publish'
-
+
version = project.hasProperty("packageVersion") ? project.getProperty("packageVersion") : 'release'
group = 'com.github.Anuken'
@@ -89,6 +89,10 @@ allprojects{
return project.getProperties()["buildversion"]
}
+ getCommitHash = {
+ return 'git rev-parse --verify --short HEAD'.execute().text.trim()
+ }
+
getPackage = {
return project.ext.mainClassName.substring(0, project.ext.mainClassName.indexOf("desktop") - 1)
}
@@ -133,6 +137,10 @@ allprojects{
props["number"] = versionNumber
props["modifier"] = versionModifier
props["build"] = buildid
+ props["commitHash"] = "unknown"
+ if(project.hasProperty("showCommitHash")){
+ props["commitHash"] = getCommitHash()
+ }
props.store(pfile.newWriter(), "Autogenerated file. Do not modify.")
}
@@ -220,7 +228,7 @@ configure(subprojects - project(":annotations")){
tasks.withType(Javadoc){
options{
addStringOption('Xdoclint:none', '-quiet')
- addStringOption('-release', '16')
+ addStringOption('-release', '17')
encoding('UTF-8')
}
}
@@ -243,6 +251,7 @@ project(":desktop"){
implementation "com.github.Anuken:steamworks4j:$steamworksVersion"
implementation arcModule("backends:backend-sdl")
+ annotationProcessor 'com.github.Anuken:jabel:0.9.0'
}
}
@@ -253,7 +262,7 @@ project(":core"){
kapt{
javacOptions{
- option("-source", "16")
+ option("-source", "17")
option("-target", "1.8")
}
}
@@ -372,6 +381,7 @@ project(":server"){
dependencies{
implementation project(":core")
implementation arcModule("backends:backend-headless")
+ annotationProcessor 'com.github.Anuken:jabel:0.9.0'
}
}
@@ -408,6 +418,9 @@ project(":tools"){
implementation arcModule("natives:natives-desktop")
implementation arcModule("natives:natives-freetype-desktop")
implementation arcModule("backends:backend-headless")
+
+ implementation("com.google.guava:guava:33.3.1-jre")
+ annotationProcessor 'com.github.Anuken:jabel:0.9.0'
}
}
diff --git a/core/assets-raw/sprites/blocks/drills/cliff-crusher-top.png b/core/assets-raw/sprites/blocks/drills/cliff-crusher-top.png
index 3541f6e396..11b6823dcd 100644
Binary files a/core/assets-raw/sprites/blocks/drills/cliff-crusher-top.png and b/core/assets-raw/sprites/blocks/drills/cliff-crusher-top.png differ
diff --git a/core/assets-raw/sprites/blocks/drills/large-cliff-crusher-rotator-bottom.png b/core/assets-raw/sprites/blocks/drills/large-cliff-crusher-rotator-bottom.png
new file mode 100644
index 0000000000..6799ee0e87
Binary files /dev/null and b/core/assets-raw/sprites/blocks/drills/large-cliff-crusher-rotator-bottom.png differ
diff --git a/core/assets-raw/sprites/blocks/drills/large-cliff-crusher-rotator.png b/core/assets-raw/sprites/blocks/drills/large-cliff-crusher-rotator.png
new file mode 100644
index 0000000000..a63c5c351a
Binary files /dev/null and b/core/assets-raw/sprites/blocks/drills/large-cliff-crusher-rotator.png differ
diff --git a/core/assets-raw/sprites/blocks/drills/large-cliff-crusher-top.png b/core/assets-raw/sprites/blocks/drills/large-cliff-crusher-top.png
new file mode 100644
index 0000000000..1a9526ac5d
Binary files /dev/null and b/core/assets-raw/sprites/blocks/drills/large-cliff-crusher-top.png differ
diff --git a/core/assets-raw/sprites/blocks/drills/large-cliff-crusher.png b/core/assets-raw/sprites/blocks/drills/large-cliff-crusher.png
new file mode 100644
index 0000000000..508f4e7f22
Binary files /dev/null and b/core/assets-raw/sprites/blocks/drills/large-cliff-crusher.png differ
diff --git a/core/assets-raw/sprites/blocks/environment/remove-ore.png b/core/assets-raw/sprites/blocks/environment/remove-ore.png
new file mode 100644
index 0000000000..7b9a0a91bf
Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/remove-ore.png differ
diff --git a/core/assets-raw/sprites/blocks/environment/remove-wall.png b/core/assets-raw/sprites/blocks/environment/remove-wall.png
new file mode 100644
index 0000000000..be52153748
Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/remove-wall.png differ
diff --git a/core/assets-raw/sprites/blocks/production/small-heat-redirector-glow.png b/core/assets-raw/sprites/blocks/production/small-heat-redirector-glow.png
new file mode 100644
index 0000000000..c2888ca8d9
Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/small-heat-redirector-glow.png differ
diff --git a/core/assets-raw/sprites/blocks/production/small-heat-redirector-heat.png b/core/assets-raw/sprites/blocks/production/small-heat-redirector-heat.png
new file mode 100644
index 0000000000..4b75fbf11a
Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/small-heat-redirector-heat.png differ
diff --git a/core/assets-raw/sprites/blocks/production/small-heat-redirector-top1.png b/core/assets-raw/sprites/blocks/production/small-heat-redirector-top1.png
new file mode 100644
index 0000000000..fe05c81d2b
Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/small-heat-redirector-top1.png differ
diff --git a/core/assets-raw/sprites/blocks/production/small-heat-redirector-top2.png b/core/assets-raw/sprites/blocks/production/small-heat-redirector-top2.png
new file mode 100644
index 0000000000..4af1a77431
Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/small-heat-redirector-top2.png differ
diff --git a/core/assets-raw/sprites/blocks/production/small-heat-redirector.png b/core/assets-raw/sprites/blocks/production/small-heat-redirector.png
new file mode 100644
index 0000000000..3b51f89bbc
Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/small-heat-redirector.png differ
diff --git a/core/assets-raw/sprites/units/weapons/retusa-weapon.png b/core/assets-raw/sprites/units/weapons/retusa-weapon.png
new file mode 100644
index 0000000000..183907169c
Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/retusa-weapon.png differ
diff --git a/core/assets-raw/sprites/units/weapons/scathe-missile-phase-cell.png b/core/assets-raw/sprites/units/weapons/scathe-missile-phase-cell.png
new file mode 100644
index 0000000000..7f4d7e4c93
Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/scathe-missile-phase-cell.png differ
diff --git a/core/assets-raw/sprites/units/weapons/scathe-missile-phase.png b/core/assets-raw/sprites/units/weapons/scathe-missile-phase.png
new file mode 100644
index 0000000000..0065be21ab
Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/scathe-missile-phase.png differ
diff --git a/core/assets-raw/sprites/units/weapons/scathe-missile-surge-cell.png b/core/assets-raw/sprites/units/weapons/scathe-missile-surge-cell.png
new file mode 100644
index 0000000000..7854083dfd
Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/scathe-missile-surge-cell.png differ
diff --git a/core/assets-raw/sprites/units/weapons/scathe-missile-surge-split-cell.png b/core/assets-raw/sprites/units/weapons/scathe-missile-surge-split-cell.png
new file mode 100644
index 0000000000..7854083dfd
Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/scathe-missile-surge-split-cell.png differ
diff --git a/core/assets-raw/sprites/units/weapons/scathe-missile-surge-split.png b/core/assets-raw/sprites/units/weapons/scathe-missile-surge-split.png
new file mode 100644
index 0000000000..22d7b4a9a6
Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/scathe-missile-surge-split.png differ
diff --git a/core/assets-raw/sprites/units/weapons/scathe-missile-surge.png b/core/assets-raw/sprites/units/weapons/scathe-missile-surge.png
new file mode 100644
index 0000000000..fd05b27d08
Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/scathe-missile-surge.png differ
diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties
index 73f9afb829..f7514f0eb8 100644
--- a/core/assets/bundles/bundle.properties
+++ b/core/assets/bundles/bundle.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Enabled
mod.disabled = [red]Disabled
mod.multiplayer.compatible = [gray]Multiplayer Compatible
mod.disable = Disable
+mod.version = Version:
mod.content = Content:
mod.delete.error = Unable to delete mod. File may be in use.
@@ -197,7 +198,8 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nMore difficult. Higher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended, more content.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
-completed = [accent]Completed
+campaign.difficulty = Difficulty
+completed = [accent]Researched
techtree = Tech Tree
techtree.select = Tech Tree Selection
techtree.serpulo = Serpulo
@@ -299,13 +301,14 @@ disconnect.error = Connection error.
disconnect.closed = Connection closed.
disconnect.timeout = Timed out.
disconnect.data = Failed to load world data!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Unable to join game ([accent]{0}[]).
connecting = [accent]Connecting...
reconnecting = [accent]Reconnecting...
connecting.data = [accent]Loading world data...
server.port = Port:
-server.addressinuse = Address already in use!
server.invalidport = Invalid port number!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [scarlet]Error hosting server.
save.new = New Save
save.overwrite = Are you sure you want to overwrite\nthis save slot?
@@ -358,6 +361,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -502,6 +506,7 @@ wavemode.counts = counts
wavemode.totals = totals
wavemode.health = health
+all = All
editor.default = [lightgray]
details = Details...
edit = Edit
@@ -673,7 +678,6 @@ requirement.capture = Capture {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Launch
-research.multiplayer = Only the host can research items.
map.multiplayer = Only the host can view sectors.
uncover = Uncover
configure = Configure Loadout
@@ -717,9 +721,9 @@ objective.enemyescelating = [accent]Enemy production escalating in [lightgray]{0
objective.enemyairunits = [accent]Enemy air unit production beginning in [lightgray]{0}[]
objective.destroycore = [accent]Destroy Enemy Core
objective.command = [accent]Command Units
-objective.nuclearlaunch = [accent]\u26A0 Nuclear launch detected: [lightgray]{0}
+objective.nuclearlaunch = [accent]\u26A0 Missile launch detected: [lightgray]{0}
-announce.nuclearstrike = [red]\u26A0 NUCLEAR STRIKE INBOUND \u26A0\n[lightgray]construct backup cores immediately
+announce.nuclearstrike = [red]\u26A0 MISSILE STRIKE INBOUND \u26A0\n[lightgray]construct backup cores immediately
loadout = Loadout
resources = Resources
@@ -747,6 +751,7 @@ error.mapnotfound = Map file not found!
error.io = Network I/O error.
error.any = Unknown network error.
error.bloom = Failed to initialize bloom.\nYour device may not support it.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThis will not be fixed. There is no known workaround for this issue.
weather.rain.name = Rain
weather.snowing.name = Snow
@@ -799,6 +804,12 @@ threat.high = High
threat.extreme = Extreme
threat.eradication = Eradication
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
+
planets = Planets
planet.serpulo.name = Serpulo
@@ -820,9 +831,19 @@ sector.fungalPass.name = Fungal Pass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on.
sector.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders.
@@ -842,6 +863,20 @@ sector.impact0078.description = Here lie remnants of the interstellar transport
sector.planetaryTerminal.description = The final target.\n\nThis coastal base contains a structure capable of launching Cores to local planets. It is extremely well guarded.\n\nProduce naval units. Eliminate the enemy as quickly as possible. Research the launch structure.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+
+#do not translate
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
@@ -1041,7 +1076,8 @@ ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
-ability.stat.shield = [stat]{0}[lightgray] shield
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
+ability.stat.shield = [stat]{0}[lightgray] max shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
ability.stat.cooldown = [stat]{0} sec[lightgray] cooldown
@@ -1104,6 +1140,8 @@ bullet.healamount = [stat]{0}[lightgray] direct repair
bullet.multiplier = [stat]{0}[lightgray] ammo/item
bullet.reload = [stat]{0}%[lightgray] fire rate
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores missiles
+bullet.notargetsbuildings = [stat] ignores buildings
unit.blocks = blocks
unit.blockssquared = blocks\u00B2
@@ -1164,12 +1202,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI Scaling
setting.uiscale.description = Restart required to apply changes.
setting.swapdiagonal.name = Always Diagonal Placement
-setting.difficulty.training = Training
-setting.difficulty.easy = Easy
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Hard
-setting.difficulty.insane = Insane
-setting.difficulty.name = Difficulty:
setting.screenshake.name = Screen Shake
setting.bloomintensity.name = Bloom Intensity
setting.bloomblur.name = Bloom Blur
@@ -1261,6 +1293,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Select Region
@@ -1339,12 +1372,16 @@ rules.wavetimer = Wave Timer
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Waves
-rules.airUseSpawns = Air units use spawn points
+rules.airUseSpawns = Air Units Use Spawn Points
rules.attack = Attack Mode
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI [red](WIP)
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Squad Size
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min Attack Weight
@@ -1387,6 +1424,9 @@ rules.title.teams = Teams
rules.title.planet = Planet
rules.lighting = Lighting
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fire
rules.anyenv =
rules.explosions = Block/Unit Explosion Damage
@@ -1396,6 +1436,7 @@ rules.weather.frequency = Frequency:
rules.weather.always = Always
rules.weather.duration = Duration:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1540,6 +1581,8 @@ block.graphite-press.name = Graphite Press
block.multi-press.name = Multi-Press
block.constructing = {0} [lightgray](Constructing)
block.spawn.name = Enemy Spawn
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Core: Shard
block.core-foundation.name = Core: Foundation
block.core-nucleus.name = Core: Nucleus
@@ -1799,6 +1842,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1846,8 +1890,9 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
-block.large-plasma-bore.name = Large Plasma Bore
+block.large-plasma-bore.name = Advanced Plasma Bore
block.impact-drill.name = Impact Drill
block.eruption-drill.name = Eruption Drill
block.core-bastion.name = Core: Bastion
@@ -1999,7 +2044,7 @@ split.container = Similar to the container, units can also be transported using
item.copper.description = Used in all types of construction and ammunition.
item.copper.details = Copper. Abnormally abundant metal on Serpulo. Structurally weak unless reinforced.
item.lead.description = Used in liquid transportation and electrical structures.
-item.lead.details = Dense. Inert. Extensively used in batteries.\nNote: Likely toxic to biological life forms. Not that there are many left here.
+item.lead.details = Dense. Inert. Extensively used in batteries.\nNote: Likely toxic to biological life forms; not that there are many left here.
item.metaglass.description = Used in liquid distribution/storage structures.
item.graphite.description = Used in electrical components and turret ammunition.
item.sand.description = Used for production of other refined materials.
@@ -2080,6 +2125,10 @@ block.phase-wall.description = Protects structures from enemy projectiles, refle
block.phase-wall-large.description = Protects structures from enemy projectiles, reflecting most bullets upon impact.
block.surge-wall.description = Protects structures from enemy projectiles, periodically releasing electric arcs upon contact.
block.surge-wall-large.description = Protects structures from enemy projectiles, periodically releasing electric arcs upon contact.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = A wall that can be opened and closed.
block.door-large.description = A wall that can be opened and closed.
block.mender.description = Periodically repairs blocks in its vicinity.\nOptionally uses silicon to boost range and efficiency.
@@ -2193,7 +2242,7 @@ block.repair-turret.description = Continuously repairs the closest damaged unit
block.core-bastion.description = Core of the base. Armored. Once destroyed, the sector is lost.
block.core-citadel.description = Core of the base. Very well armored. Stores more resources than a Bastion core.
block.core-acropolis.description = Core of the base. Exceptionally well armored. Stores more resources than a Citadel core.
-block.breach.description = Fires piercing beryllium or tungsten ammunition at enemy targets.
+block.breach.description = Fires piercing bullets at enemy targets.
block.diffuse.description = Fires a burst of bullets in a wide cone. Pushes enemy targets back.
block.sublimate.description = Fires a continuous jet of flame at enemy targets. Pierces armor.
block.titan.description = Fires a massive explosive artillery shell at ground targets. Requires hydrogen.
@@ -2209,6 +2258,7 @@ block.electric-heater.description = Applies heat to structures. Requires large a
block.slag-heater.description = Applies heat to structures. Requires slag.
block.phase-heater.description = Applies heat to structures. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas. Outputs resulting gases in two opposite directions, marked by corresponding colors.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2221,6 +2271,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.\nOptionally uses hydrogen to boost efficiency.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.\nOptionally uses nitrogen to boost efficiency.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.\nOptionally uses ozone to boost efficiency.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.\nOptionally uses cyanogen to boost efficiency.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2376,13 +2427,14 @@ lst.setrate = Set processor execution speed in instructions/tick.
lst.fetch = Lookup units, cores, players or buildings by index.\nIndices start at 0 and end at their returned count.
lst.packcolor = Pack [0, 1] RGBA components into a single number for drawing or rule-setting.
lst.setrule = Set a game rule.
-lst.flushmessage = Display a message on the screen from the text buffer.\nWill wait until the previous message finishes.
+lst.flushmessage = Display a message on the screen from the text buffer.\nIf the success result variable is [accent]@wait[],\nwill wait until the previous message finishes.\nOtherwise, outputs whether displaying the message succeeded.
lst.cutscene = Manipulate the player camera.
lst.setflag = Set a global flag that can be read by all processors.
lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nLimited to 20 times a second per variable.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.\n[accent]null []values are ignored.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2562,6 +2614,8 @@ unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
+
lenum.idle = Don't move, but keep building/mining.\nThe default state.
lenum.stop = Stop moving/mining/building.
lenum.unbind = Completely disable logic control.\nResume standard AI.
diff --git a/core/assets/bundles/bundle_be.properties b/core/assets/bundles/bundle_be.properties
index 442b6afcdd..0b88c54a4b 100644
--- a/core/assets/bundles/bundle_be.properties
+++ b/core/assets/bundles/bundle_be.properties
@@ -141,6 +141,7 @@ mod.enabled = [lightgray]Уключана
mod.disabled = [scarlet]Выключана
mod.multiplayer.compatible = [gray]Многакарыстальніцка-Сумяшчальна
mod.disable = Выкл.
+mod.version = Version:
mod.content = Змест:
mod.delete.error = Немагчыма выдаліць мадыфікацыю. Магчыма, файл выкарыстоўваецца.
mod.incompatiblegame = [red]Застарэлая Версія Гульні
@@ -189,6 +190,7 @@ campaign.select = Выбраць Пачатковую Кампанію
campaign.none = [lightgray]Выберыце з якой планеты пачаць.\nГэта можна змяніць ў любы час.
campaign.erekir = Навей, больш удасканаленага кантэнту. Больш лінейнае праходжанне кампаніі.\n\nБольш якасныя карты і агульны вопыт.
campaign.serpulo = Старэйшы кантэнт; класічны вопыт. Больш адкрытая.\n\nЗусім не збалансаваныя карты і механікі кампаніі. Менш удасканаленага.
+campaign.difficulty = Difficulty
completed = [accent]Завершаны
techtree = Дрэва\n Тэхналогій
techtree.select = Выбар Дрэва Тэхналогій
@@ -288,13 +290,14 @@ disconnect.error = Памылка злучэння.
disconnect.closed = Злучэнне закрыта.
disconnect.timeout = Час чакання скончыўся.
disconnect.data = Памылка пры загрузцы дадзеных свету!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Не ўдаецца далучыцца да гульні ([accent]{0}[]).
connecting = [accent]Падключэнне…
reconnecting = [accent]Перападключэнне...
connecting.data = [accent]Загрузка дадзеных свету…
server.port = Порт:
-server.addressinuse = Дадзены адрас ужо выкарыстоўваецца!
server.invalidport = Няправільны нумар порта!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [барвовы]Памылка стварэння сервера.
save.new = Новае захаванне
save.overwrite = Вы ўпэўненыя, што жадаеце перазапісаць\nгэты слот для захавання?
@@ -347,6 +350,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -489,6 +493,7 @@ waves.units.show = Паказаць Усё
wavemode.counts = колькацсь адзінак
wavemode.totals = усяго здароўя
wavemode.health = здароўе
+all = All
editor.default = [lightgray]<Па змаўчанні>
details = Падрабязнасці...
@@ -656,7 +661,6 @@ requirement.capture = Захапіць {0}
requirement.onplanet = Кантраляваць Сектар На {0}
requirement.onsector = Прызямліцца На Сектар: {0}
launch.text = Запуск
-research.multiplayer = Толькі хасты могуць даследаваць прадметы.
map.multiplayer = Толькі хасты могуць праглядаць сектары.
uncover = Раскрыць
configure = Канфігурацыя выгрузкі
@@ -724,6 +728,7 @@ error.mapnotfound = Файл карты не знойдзены!
error.io = Сеткавая памылка ўводу-высновы.
error.any = Невядомая сеткавая памылка.
error.bloom = Не атрымалася ініцыялізаваць свячэнне (Bloom). \nМагчыма, зараз Вашая прылада не падтрымлівае яго.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Дождж
weather.snowing.name = Снег
@@ -773,6 +778,11 @@ threat.medium = Сярэдняя
threat.high = Высокая
threat.extreme = Экстрымальная
threat.eradication = Вынішчэнне
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Планеты
planet.serpulo.name = Серпуло
@@ -794,9 +804,19 @@ sector.fungalPass.name = Глыбковы Праход
sector.biomassFacility.name = Аб'ект Сінтэзу Біямасы
sector.windsweptIslands.name = Абветраныя Астравы
sector.extractionOutpost.name = Здабвываючы Фарпост
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Планетарны Пускавы Тэрмінал
sector.coastline.name = Берагавая Лінія
sector.navalFortress.name = Марская Крэпасць
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Аптымальнае месца каб пачаць. Нізкая варожая пагроза. Мала рэсурсаў.\nВазімце як мага болей свінца і медзі.\nІ рухайцеся далей.
sector.frozenForest.description = Нават тут, бліжэй да гор, распаўсюдзіліся споры. Ледзяныя тэмпературы не могуць утрымліваць іх заўсёды.\n\nПачніце выкарыстоўваць энергію. Пабудуйце генератары на цвёрдым паліве. Даведайцеся як выкарыстоуваць рэгенератары.
@@ -816,6 +836,18 @@ sector.impact0078.description = Here lie remnants of the interstellar transport
sector.planetaryTerminal.description = The final target.\n\nThis coastal base contains a structure capable of launching Cores to local planets. It is extremely well guarded.\n\nProduce naval units. Eliminate the enemy as quickly as possible. Research the launch structure.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = Пачатак
sector.aegis.name = Ахова
sector.lake.name = Рака
@@ -1012,6 +1044,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1075,6 +1108,8 @@ bullet.healamount = [stat]{0}[lightgray] напрамкавы рамонт
bullet.multiplier = [stat]{0}[lightgray]x множнік боепрыпасаў
bullet.reload = [stat]{0}[lightgray]x хуткасць стрэльбы
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = блокі
unit.blockssquared = blocks²
@@ -1135,12 +1170,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Маштаб карыстальніцкага інтэрфейсу [lightgray] (перазапусьціцца)[]
setting.uiscale.description = Каб змены ўжыліся патрабуецца перазапуск.
setting.swapdiagonal.name = Заўсёды дыяганальнае размяшчэнне
-setting.difficulty.training = Навучанне
-setting.difficulty.easy = Лёгкая
-setting.difficulty.normal = Нармальны
-setting.difficulty.hard = Складаная
-setting.difficulty.insane = Вар’яцкая
-setting.difficulty.name = Складанасць:
setting.screenshake.name = Трасяніна экрана
setting.bloomintensity.name = Інтэнсіўнасць Цвету
setting.bloomblur.name = Размыты Цвет
@@ -1230,6 +1259,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Перабудаваць Рэгіён
keybind.schematic_select.name = Абраць Вобласць
keybind.schematic_menu.name = Меню Схем
@@ -1307,12 +1337,16 @@ rules.wavetimer = Інтэрвал хваляў
rules.wavesending = Адпраўка Хваль
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Хвалі
rules.airUseSpawns = Air units use spawn points
rules.attack = Рэжым атакі
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Мінімальны Размер Атраду
rules.rtsmaxsquadsize = Максімальны Размер Атраду
rules.rtsminattackweight = Мінімальная Вага Атакі
@@ -1355,6 +1389,9 @@ rules.title.teams = Кманды
rules.title.planet = Планета
rules.lighting = Асвятленне
rules.fog = Туман Вайны
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Агонь
rules.anyenv = <Любы>
rules.explosions = Падрыўныя пашкоджанні Блока/Адзінкі
@@ -1363,6 +1400,7 @@ rules.weather = Надвор'е
rules.weather.frequency = Частата:
rules.weather.always = Заўсёды
rules.weather.duration = Працягласць:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1503,6 +1541,8 @@ block.graphite-press.name = Графітны прэс
block.multi-press.name = Мульты-прэс
block.constructing = {0} [lightgray](Будуецца)
block.spawn.name = Кропка з’яўлення ворагаў
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Ядро: «Аскепак»
block.core-foundation.name = Ядро: «Штаб»
block.core-nucleus.name = Ядро: «Атам»
@@ -1760,6 +1800,7 @@ block.electric-heater.name = Электрычны Награвацель
block.slag-heater.name = Шлакавы Награвацель
block.phase-heater.name = Фазавы Награвацель
block.heat-redirector.name = Перанакіроўшчык Цяпла
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Маршрутызатар Цяпла
block.slag-incinerator.name = Шлакавы Спальвальнік
block.carbide-crucible.name = Карбідны Тыгель
@@ -1807,6 +1848,7 @@ block.chemical-combustion-chamber.name = Хімічная Камера Згар
block.pyrolysis-generator.name = Генератар Піролізу
block.vent-condenser.name = Вентыляцыйны Кандэнсатар
block.cliff-crusher.name = Здрабняльнік Скал
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Плазменны Бур
block.large-plasma-bore.name = Вялікі Плазменны Бур
block.impact-drill.name = Ударная Буравая Усталёўка
@@ -2032,6 +2074,10 @@ block.phase-wall.description = Сцяна, пакрытая спецыяльны
block.phase-wall-large.description = Сцяна, пакрытая спецыяльным фазавым адлюстроўваюць складам. Адлюстроўвае большасць куль пры ўдары. \nРазмяшчаецца на некалькіх плітках.
block.surge-wall.description = Вельмі трывалы ахоўны блок. \nНакаплвае зарад пры кантакце з куляй, выпускаючы яго выпадковым чынам.
block.surge-wall-large.description = Вельмі трывалы ахоўны блок. \nНакаплвает зарад пры кантакце з куляй, выпускаючы яго выпадковым чынам. \nРазмяшчаецца на некалькіх плітках.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Маленькая дзверы. Можна адкрыць або зачыніць націскам.
block.door-large.description = Вялікая дзверы. Можна адкрыць і закрыць націскам. \nРазмяшчаецца на некалькіх плітках.
block.mender.description = Перыядычна рамантуе блокі ў непасрэднай блізкасці. Захоўвае сродкі абароны ў цэласнасці паміж хвалямі. \nОпцонально выкарыстоўвае крэмній для павелічэння далёкасці і эфектыўнасці.
@@ -2159,6 +2205,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2171,6 +2218,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2329,6 +2377,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2481,6 +2530,7 @@ unitlocate.building = Выводзіць зменную для выбранна
unitlocate.outx = Выводзіць X каардынату.
unitlocate.outy = Выводзіць Y каардынату.
unitlocate.group = Знаходзіць группу будынкаў.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Не рухацца, а будаваць/дабываць.\nЗвычайны стан.
lenum.stop = Перастаць рухацца/дабываць/будаваць.
lenum.unbind = Поўнасццю адключыць кантраляванне працэссарамі.\nАднавіць звычайныя паводзіны AI.
diff --git a/core/assets/bundles/bundle_bg.properties b/core/assets/bundles/bundle_bg.properties
index 7e895bada1..b0d0d498ce 100644
--- a/core/assets/bundles/bundle_bg.properties
+++ b/core/assets/bundles/bundle_bg.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Активиран
mod.disabled = [scarlet]Деактивиран
mod.multiplayer.compatible = [gray]Поддържа Мрежова Игра
mod.disable = Деактивирай
+mod.version = Version:
mod.content = Съдържание:
mod.delete.error = Неуспешно изтриване на мод. Вероятно файловете се използват.
mod.incompatiblegame = [red]Outdated Game
@@ -193,6 +194,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Завършено
techtree = Tech Tree
techtree.select = Tech Tree Selection
@@ -293,13 +295,14 @@ disconnect.error = Проблем със връзката.
disconnect.closed = Връзката приключи.
disconnect.timeout = Загубена връзка.
disconnect.data = Грешка при зареждане на информация за света!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Неуспех при свързване към игра ([accent]{0}[]).
connecting = [accent]Свързване...
reconnecting = [accent]Повторно свързване...
connecting.data = [accent]Зареждане на информация за света...
server.port = Порт:
-server.addressinuse = Адресът вече се използва!
server.invalidport = Невалиден порт!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [scarlet]Грешка при стартиране на сървър.
save.new = Нов Запис
save.overwrite = Сигурни ли сте, че искате\nда презапишете тази позиция за запиз?
@@ -352,6 +355,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -495,6 +499,7 @@ waves.units.show = Show All
wavemode.counts = бройки
wavemode.totals = общи бройки
wavemode.health = точки живот
+all = All
editor.default = [lightgray]<Стандартно>
details = Детайли...
@@ -662,7 +667,6 @@ requirement.capture = Превземете {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Изстреляй
-research.multiplayer = Само хостващият играч може да провежда изследвания.
map.multiplayer = Само хостващият играч може да преглежда секторите.
uncover = Разкрий
configure = Избор на екипировка
@@ -731,6 +735,7 @@ error.mapnotfound = Не е намерен файл с карта!
error.io = Мрежова I/O грешка.
error.any = Неизвестна мрежова грешка.
error.bloom = Неуспешно инициализиране на Сияния.\nВашето устройство може да не поддържа този ефект.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Дъжд
weather.snowing.name = Сняг
@@ -781,6 +786,11 @@ threat.medium = Средна
threat.high = Висока
threat.extreme = Екстремна
threat.eradication = Унищожителна
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Планети
@@ -803,9 +813,19 @@ sector.fungalPass.name = Гъбеният Пролом
sector.biomassFacility.name = Биосинтезиращо Съоръжение
sector.windsweptIslands.name = Ветровитите Острови
sector.extractionOutpost.name = Добивен лагер
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Терминал за космически мисии
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Перфектното място за започване отначало. Ниска заплаха. Ниски ресурси.\nСъбери колкото можеш мед и олово.\nПродължи напред.
sector.frozenForest.description = Дори тук, близо до планините, спорите са се разпространили. Мразовитите температури не могат да ги задържат вечно.\n\nОвладейте електричеството. Постройте горивни генератори. Научете се да ползвате възстрановители.
@@ -825,6 +845,18 @@ sector.impact0078.description = Тук лежат останките от пър
sector.planetaryTerminal.description = Крайна цел.\n\nТази крайбрежна база съдържа структура, създадена с цел междупланетарен транспорт на ядра, макар и само в рамките на локалната звездна система. Тази локация има изключително висока защита.\n\nИзползвайте военноморски единици. Елиминирайте врага възможно най - бързо. Проучете изстрелващата структура
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
sector.lake.name = Lake
@@ -1022,6 +1054,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1086,6 +1119,8 @@ bullet.healamount = [stat]{0}[lightgray] direct repair
bullet.multiplier = [stat]{0}[lightgray]x множител на боеприпаси
bullet.reload = [stat]{0}[lightgray]x скорост на стрелба
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = блока
unit.blockssquared = блока²
@@ -1146,12 +1181,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Размер на Интерфейсът[lightgray] (изисква рестарт)[]
setting.uiscale.description = Restart required to apply changes.
setting.swapdiagonal.name = Винаги Диагонално Поставяне
-setting.difficulty.training = Тренировка
-setting.difficulty.easy = Лесно
-setting.difficulty.normal = Нормално
-setting.difficulty.hard = Трудно
-setting.difficulty.insane = Безумно
-setting.difficulty.name = Трудност:
setting.screenshake.name = Клатене на Екрата
setting.bloomintensity.name = Bloom Intensity
setting.bloomblur.name = Bloom Blur
@@ -1241,6 +1270,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Избери Регион
keybind.schematic_menu.name = Меню със Схеми
@@ -1318,12 +1348,16 @@ rules.wavetimer = Таймер за Вълни
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Вълни
rules.airUseSpawns = Air units use spawn points
rules.attack = Режим Атака
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Squad Size
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min Attack Weight
@@ -1366,6 +1400,9 @@ rules.title.teams = Teams
rules.title.planet = Planet
rules.lighting = Светкавици
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Огън
rules.anyenv =
rules.explosions = Block/Unit Explosion Damage
@@ -1374,6 +1411,7 @@ rules.weather = Климат
rules.weather.frequency = Честота:
rules.weather.always = Винаги
rules.weather.duration = Продължителност:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1514,6 +1552,8 @@ block.graphite-press.name = Графитна Преса
block.multi-press.name = Мулти-Преса
block.constructing = {0} [lightgray](конструиране)
block.spawn.name = Вражеска Начална Точка
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Ядро: Шард
block.core-foundation.name = Core: Фондация
block.core-nucleus.name = Core: Център
@@ -1771,6 +1811,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1818,6 +1859,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2044,6 +2086,10 @@ block.phase-wall.description = Защитава структури от враж
block.phase-wall-large.description = Защитава структури от вражески огън, отразявайки повечето куршуми при удар.
block.surge-wall.description = Защитава структури от вражески огън, периодично освобождавайки волтови дъги при контакт.
block.surge-wall-large.description = Защитава структури от вражески огън, периодично освобождавайки волтови дъги при контакт.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Стена, която може да бъде отворена и затворена.
block.door-large.description = Стена, която може да бъде отворена и затворена.
block.mender.description = Периодично поправя близки блокове.\nОпционално използва силикон за да увеличи обхвата и ефективността си.
@@ -2171,6 +2217,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2183,6 +2230,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2343,6 +2391,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2510,6 +2559,7 @@ unitlocate.building = Променлива в която да запише на
unitlocate.outx = Резултатна X координата.
unitlocate.outy = Резултатна Y координата.
unitlocate.group = Група постройки за които да търси.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Не се движи, но продължи да строиш/добиваш ресурси.\nСтандартното поведение.
lenum.stop = Спри да се движиш/добиваш ресурси/строиш.
diff --git a/core/assets/bundles/bundle_ca.properties b/core/assets/bundles/bundle_ca.properties
index 3be98ea31b..f8964ad29b 100644
--- a/core/assets/bundles/bundle_ca.properties
+++ b/core/assets/bundles/bundle_ca.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Activat
mod.disabled = [scarlet]Desactivat
mod.multiplayer.compatible = [gray]Compatible amb el mode multijugador
mod.disable = Desactiva
+mod.version = Version:
mod.content = Contingut:
mod.delete.error = El mod no es pot esborrar. Potser el fitxer està en ús.
mod.incompatiblegame = [red]Versió no compatible
@@ -193,6 +194,7 @@ campaign.select = Trieu la campanya inicial
campaign.none = [lightgray]Trieu en quin planeta voleu començar.\nEs pot canviar en qualsevol moment.
campaign.erekir = [accent]Recomanat per a jugadors novells.[]\n\nContingut revisat nou. Una campanya de progressió més o menys lineal.\n\nMapes de qualitat més alta i experiència més satisfactòria.
campaign.serpulo = [scarlet]No recomanat per a jugadors novells.[]\n\nContingut antic; l’experiència clàssica. Campanya més oberta.\n\nPotser els mapes i mecàniques de la campanya no estan massa equilibrats. Contingut en general menys polit que el d’Erekir.
+campaign.difficulty = Difficulty
completed = [accent]Completat
techtree = Arbre tecnològic
techtree.select = Selecció de l’arbre tecnològic
@@ -293,13 +295,14 @@ disconnect.error = Error de connexió.
disconnect.closed = Connexió tancada.
disconnect.timeout = S’ha esgotat el temps d’espera.
disconnect.data = No s’han pogut carregar les dades del món!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = No és possible unir-se a la partida ([accent]{0}[]).
connecting = [accent]Es connecta…
reconnecting = [accent]Es torna a connectar…
connecting.data = [accent]Es carreguen les dades del món…
server.port = Port:
-server.addressinuse = L’adreça ja es fa servir!
server.invalidport = El número de port no és vàlid!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [scarlet]S’ha produït un error mentre s’allotjava el servidor.
save.new = Desa en un fitxer nou
save.overwrite = Esteu segur que voleu sobreescriure\naquesta ranura de desades?
@@ -352,6 +355,7 @@ command.enterPayload = Entra bloc
command.loadUnits = Carrega unitats
command.loadBlocks = Carrega blocs
command.unloadPayload = Descarrega
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel·la les ordres
stance.shoot = Comportament: Dispara
stance.holdfire = Comportament: Mantén el foc
@@ -495,6 +499,7 @@ waves.units.show = Mostra-les totes
wavemode.counts = comptades
wavemode.totals = totals
wavemode.health = salut
+all = All
editor.default = [lightgray]
details = Detalls
@@ -665,7 +670,6 @@ requirement.capture = Captureu {0}.
requirement.onplanet = Controleu el sector {0}.
requirement.onsector = Aterreu al sector {0}.
launch.text = Inicia el llançament
-research.multiplayer = Només l’amfitrió pot recercar tecnologies.
map.multiplayer = Només l’amfitrió pot veure els sectors.
uncover = Descobreix
configure = Configura la càrrega inicial
@@ -735,6 +739,7 @@ error.mapnotfound = El fitxer del mapa no s’ha trobat!
error.io = S’ha produït un error d’entrada/sortida de la xarxa.
error.any = S’ha produït un error de xarxa desconegut.
error.bloom = No s’ha pogut inicialitzar l’efecte «bloom».\nPotser el dispositiu no admet aquesta funció.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Pluja
weather.snowing.name = Neu
@@ -785,6 +790,11 @@ threat.medium = Mitjana
threat.high = Alta
threat.extreme = Extrema
threat.eradication = Erradicació
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planetes
@@ -807,9 +817,19 @@ sector.fungalPass.name = El port de muntanya dels fongs
sector.biomassFacility.name = Centre de síntesi de biomassa
sector.windsweptIslands.name = Les illes escombrades pel vent
sector.extractionOutpost.name = Post avançat d’extracció
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Terminal de llançament interplanetari
sector.coastline.name = Línia de costa
sector.navalFortress.name = Fortalesa naval
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = El lloc adequat per a començar de nou. Amenaça enemiga baixa. Pocs recursos.\nRecolliu tot el coure i plom que pugueu.\nDesprés, continueu en un altre sector.
sector.frozenForest.description = Les espores han arribat fins aquí, prop de les muntanyes. Les temperatures baixes no les podran contenir per sempre.\n\nComenceu el camí del poder. Construïu generadors a combustió. Apreneu a fer servir els reparadors.
@@ -829,6 +849,18 @@ sector.impact0078.description = Aquí hi ha les restes de la primera nau de tran
sector.planetaryTerminal.description = L’objectiu final.\n\nAquesta base costera conté una estructura capaç de llançar nuclis a altres planetes. Està molt ben vigilida.\n\nProduïu unitats navals, elimineu l’enemic tan aviat com pugueu i investigueu l’estructura de llançament.
sector.coastline.description = S’han detectat restes de tecnologia naval a prop. Repel·liu els atacs enemics, captureu el sector i aconseguiu la tecnologia.
sector.navalFortress.description = L’enemic ha establert una base en una illa distant amb defenses geològiques naturals. Destruïu el post avançat i aconseguiu i investigueu les seves tecnologies navals avançades.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = El principi
sector.aegis.name = L’ègida
@@ -1026,6 +1058,7 @@ ability.liquidexplode = Vessament mortal
ability.liquidexplode.description = Vessa líquid quan mor.
ability.stat.firingrate = [stat]{0}/seg[lightgray] de cadència de tir
ability.stat.regen = [stat]{0}[lightgray] de salut/seg
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] d’escut
ability.stat.repairspeed = [stat]{0}/seg[lightgray] de velocitat de reparació
ability.stat.slurpheal = [stat]{0}[lightgray] de salut/unitat de líquid
@@ -1089,6 +1122,8 @@ bullet.healamount = [stat]{0}[lightgray] de reparació directa
bullet.multiplier = [stat]{0}[lightgray]× de multiplicador de munició
bullet.reload = [stat]{0}[lightgray]× de cadència de tir
bullet.range = [stat]abast de {0}[lightgray] caselles
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blocs
unit.blockssquared = blocs²
@@ -1122,7 +1157,7 @@ category.crafting = Entrada/Sortida
category.function = Funcionament
category.optional = Millores opcionals
setting.alwaysmusic.name = Reprodueix música sempre
-setting.alwaysmusic.description = Quan està activat, la música es reproduirà en bucle durant les partides.Quan està desactivat, només es reproduirà a intervals aleatoris.
+setting.alwaysmusic.description = Quan està activat, la música es reproduirà en bucle durant les partides.\nQuan està desactivat, només es reproduirà a intervals aleatoris.
setting.skipcoreanimation.name = Omet l’animació del llançament i aterratge del nucli
setting.landscape.name = Bloca el paisatge
setting.shadows.name = Ombres
@@ -1149,12 +1184,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Escala de la interfície
setting.uiscale.description = Cal reiniciar perquè s’apliquin els canvis.
setting.swapdiagonal.name = Permet sempre construir en diagonal
-setting.difficulty.training = Entrenament
-setting.difficulty.easy = Fàcil
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Difícil
-setting.difficulty.insane = Molt difícil
-setting.difficulty.name = Dificultat:
setting.screenshake.name = Sacseig de pantalla
setting.bloomintensity.name = Intensitat de l’efecte «bloom»
setting.bloomblur.name = Desenfocament «bloom»
@@ -1244,6 +1273,7 @@ keybind.unit_command_load_units.name = Ordre d’unitat: Carrega unitats
keybind.unit_command_load_blocks.name = Ordre d’unitat: Carrega blocs
keybind.unit_command_unload_payload.name = Ordre d’unitat: Descarrega blocs
keybind.unit_command_enter_payload.name = Ordre d’unitat: Entra blocs
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Reconstrueix la regió
keybind.schematic_select.name = Selecciona una regió
keybind.schematic_menu.name = Menú de plànols
@@ -1321,12 +1351,16 @@ rules.wavetimer = Temporitzador d’onades
rules.wavesending = Enviament d’onades
rules.allowedit = Permet editar les regles
rules.allowedit.info = Quan està activat, el jugador pot editar les regles de la partida amb el botó que hi ha a la part inferior esquerra del menú de pausa.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Onades
rules.airUseSpawns = Les unitats aèries fan servir els punts d’aparició
rules.attack = Mode d’atac
rules.buildai = IA constructora de bases
rules.buildaitier = Nivell de construcció de la IA
rules.rtsai = IA avançada (RTS AI)
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Mida mínima de l’esquadró
rules.rtsmaxsquadsize = Mida màxima de l’esquadró
rules.rtsminattackweight = Pes d’atac mínim
@@ -1369,6 +1403,9 @@ rules.title.teams = Equips
rules.title.planet = Planeta
rules.lighting = Il·luminació
rules.fog = Amaga el terreny inexplorat
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Foc
rules.anyenv =
rules.explosions = Dany de les explosions als blocs/unitats
@@ -1377,6 +1414,7 @@ rules.weather = Estat meteorològic
rules.weather.frequency = Freqüència:
rules.weather.always = Sempre
rules.weather.duration = Durada:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = No es permet que els jugadors puguin posar res a prop dels edificis enemics. Quan s’intenta posar una torreta, l’abast augmenta i la torreta no podrà arribar a l’enemic.
rules.onlydepositcore.info = No es permet que les unitats deixin elements a dins dels edificis excepte els nuclis.
@@ -1521,6 +1559,8 @@ block.graphite-press.name = Premsa de grafit
block.multi-press.name = Premsa múltiple
block.constructing = {0} [lightgray](Construint)
block.spawn.name = Punt d’aparició d’enemics
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Nucli: Estella
block.core-foundation.name = Nucli: Fonament
block.core-nucleus.name = Nucli: Punt neuràlgic
@@ -1780,6 +1820,7 @@ block.electric-heater.name = Escalfador elèctric
block.slag-heater.name = Escalfador d’escòria
block.phase-heater.name = Escalfador de fase
block.heat-redirector.name = Redirector tèrmic
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Encaminador tèrmic
block.slag-incinerator.name = Incineradora d’escòria
block.carbide-crucible.name = Gresol de carbur
@@ -1827,6 +1868,7 @@ block.chemical-combustion-chamber.name = Cambra de combustió química
block.pyrolysis-generator.name = Generador pirolític
block.vent-condenser.name = Respirador de condensació
block.cliff-crusher.name = Picadora d’espadats
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Perforadora de plasma
block.large-plasma-bore.name = Perforadora de plasma grossa
block.impact-drill.name = Perforadora d’impacte
@@ -2054,6 +2096,10 @@ block.phase-wall.description = Protegeix les estructures dels projectils enemics
block.phase-wall-large.description = Protegeix les estructures dels projectils enemics, reflectint la majoria de munició que hi impacta.
block.surge-wall.description = Protegeix les estructures dels projectils enemics, alliberant descàrregues elèctriques periòdicament quan algun enemic el toca.
block.surge-wall-large.description = Protegeix les estructures dels projectils enemics, alliberant descàrregues elèctriques periòdicament quan algun enemic el toca.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Un mur que es pot obrir i tancar.
block.door-large.description = Un mur gros que es pot obrir i tancar.
block.mender.description = Repara blocs propers periòdicament.\nTambé pot usar silici per a potenciar el seu abast i eficiència.
@@ -2181,6 +2227,7 @@ block.electric-heater.description = Escalfa els blocs als que està orientat. Ne
block.slag-heater.description = Escalfa els blocs als que està orientat. Requereix escòria.
block.phase-heater.description = Escalfa els blocs als que està orientat. Requereix teixit de fase.
block.heat-redirector.description = Redirigeix l’escalfor acumulada a altres blocs.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Distribueix l’escalfor acumulada en tres direccions de sortida.
block.electrolyzer.description = Converteix l’aigua en hidrogen i gas ozó.
block.atmospheric-concentrator.description = Concentra el nitrogen de l’atmosfera. Requereix escalfor.
@@ -2193,6 +2240,7 @@ block.vent-condenser.description = Condensa els gasos procedents de conductes de
block.plasma-bore.description = Quan es posa orientat a un mur de mineral, en treu recursos indefinidament. Requereix una mica d’energia per funcionar.
block.large-plasma-bore.description = Una perforadora de plasma grossa. Pot extraure tungstè i tori. Requereix hidrogen i energia.
block.cliff-crusher.description = Trenca murs, extraient-ne sorra indefinidament. Necessita energia. La seva eficàcia depèn del tipus de mur.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = Quan es posa a sobre de minerals, n’extrau indefinidament. Necessita energia i aigua.
block.eruption-drill.description = Una perforadora d’impacte millorada. Pot extraure tori. Necessita hidrogen.
block.reinforced-conduit.description = Impulsa i fa circular els fluids. No accepta entrades des dels laterals si no és a través de conductes.
@@ -2353,6 +2401,7 @@ lst.getflag = Obtén un senyal global.
lst.setprop = Estableix una propietat d’una unitat o estructura.
lst.effect = Crea un efecte de partícula.
lst.sync = Sincronitza una variable a través de la xarxa.\nS’invoca com a molt 10 vegades per segon.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Crea una marca lògica al món.\nS’ha de donar un ID per a identificar-la.\nEs poden establir fins a 20.000 marcadors per món.
lst.setmarker = Estableix una propietat per a la marca.\nL’ID que es faci servir ha de ser el mateix que el de la instrucció de crear la marca.
lst.localeprint = Afegeix el valor d’una propietat de la traducció d’un mapa a la cua d’impressió.\nPer a establir paquets de traducció de mapes a l’editor de mapes, comproveu [accent]Informació del mapa > Paquets de traducció[].\nSi el client és un dispositiu mòbil, primer intenta imprimir una propietat que acabi en «.mobile».
@@ -2523,6 +2572,7 @@ unitlocate.building = Variable de sortida per al bloc localitzat.
unitlocate.outx = Coordenada X de la sortida.
unitlocate.outy = Coordenada Y de la sortida.
unitlocate.group = Categoria de blocs a buscar.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = La unitat no es mourà, però continuarà construint i extraient minerals.\nÉs l’estat per defecte.
lenum.stop = Para de moure, construir o extreure minerals.
diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties
index 66acc27401..7765150968 100644
--- a/core/assets/bundles/bundle_cs.properties
+++ b/core/assets/bundles/bundle_cs.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Povoleno[]
mod.disabled = [scarlet]Zakázáno[]
mod.multiplayer.compatible = [gray]Hra více hráčů komapitibilní
mod.disable = Zakázat
+mod.version = Version:
mod.content = Obsah:
mod.delete.error = Nebylo možnost smazat modifikaci. Soubor může být používán.
mod.incompatiblegame = [red]Zastaralá Hra
@@ -193,6 +194,7 @@ campaign.select = Vybrat Začínající Kampaň
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Dokončeno[]
techtree = Technologie
techtree.select = Výběr Výzkumného Stromu
@@ -293,13 +295,14 @@ disconnect.error = Chyba připojení.
disconnect.closed = Připojení bylo uzavřeno.
disconnect.timeout = Vypršel čas pro připojení.
disconnect.data = Chyba načtení dat ze serveru!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Není možno se připojit ke hře ([accent]{0}[]).
connecting = [accent]Připojuji se...[]
reconnecting = [accent]Znovu se připojuji...
connecting.data = [accent]Načítám data ze serveru...[]
server.port = Port:
-server.addressinuse = Adresu již někdo používá!
server.invalidport = Neplatné číslo portu!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [scarlet]Chyba při hostování serveru.[]
save.new = Nové uložení hry
save.overwrite = Jsi si jistý, že chceš přepsat\ntuto pozici pro uložení hry?
@@ -353,6 +356,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -496,6 +500,7 @@ waves.units.show = Zobrazit vše
wavemode.counts = počty
wavemode.totals = součty
wavemode.health = zdraví
+all = All
editor.default = [lightgray][]
details = Podrobnosti...
@@ -664,7 +669,6 @@ requirement.capture = Polap {0}
requirement.onplanet = Kontrolovat Sektor na {0}
requirement.onsector = Přistát na Sektor: {0}
launch.text = Vyslat
-research.multiplayer = Jen hostitel hry může vynalézat nové technologie.
map.multiplayer = Jen hostitel může prohlížet sektory.
uncover = Odkrýt mapu
configure = Přizpůsobit vybavení
@@ -733,6 +737,7 @@ error.mapnotfound = Soubor s mapou nebyl nalezen!
error.io = Vstupně/výstupní (I/O) chyba sítě.
error.any = Neznámá chyba sítě.
error.bloom = Chyba inicializace filtru Bloom.\nTvé zařízení ho nejspíš nepodporuje.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Déšť
weather.snowing.name = Sníh
@@ -783,6 +788,11 @@ threat.medium = Střední
threat.high = Velké
threat.extreme = Extrémní
threat.eradication = Vyhlazující
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planety
@@ -805,9 +815,19 @@ sector.fungalPass.name = Plísňový průsmyk
sector.biomassFacility.name = Zařízení pro syntézu biomasy
sector.windsweptIslands.name = Větrné ostrovy
sector.extractionOutpost.name = Extrakční základna
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetární odpalovací terminál
sector.coastline.name = Pobřežní čára
sector.navalFortress.name = Námořní pevnost
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Optimální místo, kde znovu začít. Nízký výskyt nepřátel. Několik málo surovin.\nPosbírej co nejvíce olova a mědi.\nBěž dál.
sector.frozenForest.description = Dokonce až sem, blízko hor, se dokázaly spóry rozrůst. Mráz je však nemůže zadržet navěky.\n\nPusť se do práce za pomocí energie. Stav spalovací generátory. Nauč se, jak používat opravovací věže.
@@ -827,6 +847,18 @@ sector.impact0078.description = Zde leží zbytky mezihvězdné lodi, která vst
sector.planetaryTerminal.description = Konečný cíl.\n\nTato pobřežní základna obsahuje konstrukce schopné vyslat jádra na okolní planety. Je mimořádně dobře opevněna.\n\nVyrob námořní jednotky. Odstraň nepřítele tak rychle, jak umíš. Vyzkoumej vysílací konstrukci.
sector.coastline.description = V této lokaci byly objeveny pozůstatky techniky námořních jednotek. Odražte nepřátelské útoky, dobijte tento sektor a získejte technologii.
sector.navalFortress.description = Nepřítel si vybudoval základnu na odlehlém, přírodou opevněném ostrově. Zničte tuto základnu. Získejte jejich pokročilou technologii námořních plavidel a vyzkoumejte ji.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = Nástup
sector.aegis.name = Aegis
sector.lake.name = Jezero
@@ -1024,6 +1056,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1088,6 +1121,8 @@ bullet.healamount = [stat]{0}[lightgray] přímá oprava
bullet.multiplier = [stat]{0}[lightgray]x více střel[]
bullet.reload = [stat]{0}[lightgray]x rychlost střelby[]
bullet.range = [stat]{0}[lightgray] kostek dosah
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = bloky
unit.blockssquared = bloky²
@@ -1148,12 +1183,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Škálování uživatelského rozhraní[lightgray] (je vyžadován restart)[]
setting.uiscale.description = Pro aplikování změn, je potřeba restart.
setting.swapdiagonal.name = Vždy pokládat úhlopříčně
-setting.difficulty.training = Zácviková
-setting.difficulty.easy = Lehká
-setting.difficulty.normal = Normální
-setting.difficulty.hard = Těžká
-setting.difficulty.insane = Šílená
-setting.difficulty.name = Obtížnost:
setting.screenshake.name = Chvění obrazovky
setting.bloomintensity.name = Intenzita Bloom
setting.bloomblur.name = Rozmazání Bloom
@@ -1243,6 +1272,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Přestavět Region
keybind.schematic_select.name = Vybrat oblast
keybind.schematic_menu.name = Nabídka šablon
@@ -1320,12 +1350,16 @@ rules.wavetimer = Časovač vln
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Vlny
rules.airUseSpawns = Air units use spawn points
rules.attack = Režim útoku
rules.buildai = Umělá AI staví
rules.buildaitier = Úroveň AI stavitele
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min velikost skupiny
rules.rtsmaxsquadsize = Max velikost skupiny
rules.rtsminattackweight = Min váha útoku
@@ -1368,6 +1402,9 @@ rules.title.teams = Týmy
rules.title.planet = Planeta
rules.lighting = Osvětlení
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Výstřel
rules.anyenv =
rules.explosions = Výbušné poškození bloku/jednotky
@@ -1376,6 +1413,7 @@ rules.weather = Počasí
rules.weather.frequency = Četnost:
rules.weather.always = Vždy
rules.weather.duration = Trvání:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1518,6 +1556,8 @@ block.graphite-press.name = Lis na grafit
block.multi-press.name = Všestranný lis
block.constructing = {0} [lightgray](ve výstavbě)[]
block.spawn.name = Nepřátelská líheň
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Jádro: Odštěpek
block.core-foundation.name = Jádro: Základ
block.core-nucleus.name = Jádro: Atom
@@ -1775,6 +1815,7 @@ block.electric-heater.name = Elektrický Ohřívač
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Tepelný Směrovač
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1822,6 +1863,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2049,6 +2091,10 @@ block.phase-wall.description = Chrání konstrukce před nepřátelskými střel
block.phase-wall-large.description = Chrání konstrukce před nepřátelskými střelami, reflecting most bullets upon impact.
block.surge-wall.description = Chrání konstrukce před nepřátelskými střelami. Při doteku opakovaně vydává energetické výboje.
block.surge-wall-large.description = Chrání konstrukce před nepřátelskými střelami. Při doteku opakovaně vydává energetické výboje.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Zeď, která může být otevřena a zavřena.
block.door-large.description = Zeď, která může být otevřena a zavřena.
block.mender.description = Opakovaně opravuje bloky ve svém dosahu.\nVolitelně umí použít křemík pro posílení dosahu a efektivity.
@@ -2176,6 +2222,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2188,6 +2235,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2348,6 +2396,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2518,6 +2567,7 @@ unitlocate.building = Výstup hodnot pro lokalizovanou budovu.
unitlocate.outx = Výstup X pozice.
unitlocate.outy = Výstup Y pozice.
unitlocate.group = Vyhledat skupinu budov.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Nehýbat se, ale pokračovat ve stavění/těžení.\nVýchozí stav.
lenum.stop = Přestat pohybovat se/těžit/stavět.
diff --git a/core/assets/bundles/bundle_da.properties b/core/assets/bundles/bundle_da.properties
index caac178e24..b114712702 100644
--- a/core/assets/bundles/bundle_da.properties
+++ b/core/assets/bundles/bundle_da.properties
@@ -141,6 +141,7 @@ mod.enabled = [lightgray]Aktiveret
mod.disabled = [scarlet]Deaktiveret
mod.multiplayer.compatible = [gray]Multiplayer Compatible
mod.disable = Deaktiver
+mod.version = Version:
mod.content = Indhold:
mod.delete.error = Kan ikke slette mod - tilhørende filer er muligvis i brug.
mod.incompatiblegame = [red]Outdated Game
@@ -190,6 +191,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Færdiggjort
techtree = Teknologi træ
techtree.select = Tech Tree Selection
@@ -289,13 +291,14 @@ disconnect.error = Forbindelsesfejl.
disconnect.closed = Forbindelse afbrudt.
disconnect.timeout = Maksimal ventetid overskredet.
disconnect.data = Kunne ikke indlæse bane-data!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Kunne ikke deltage i spil ([accent]{0}[]).
connecting = [accent]Forbinder...
reconnecting = [accent]Reconnecting...
connecting.data = [accent]Indlæser bane-data...
server.port = Port:
-server.addressinuse = IP-adressen er allerede i brug!
server.invalidport = Ugyldigt port-nummer!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Der skete en fejl.
save.new = Nyt gem
save.overwrite = Er du sikker på, at du vil overskrive\ndette gem?
@@ -348,6 +351,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -490,6 +494,7 @@ waves.units.show = Show All
wavemode.counts = tal
wavemode.totals = i alt
wavemode.health = liv
+all = All
editor.default = [lightgray]
details = Detaljer...
@@ -657,7 +662,6 @@ requirement.capture = Overtag {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Affyr
-research.multiplayer = Kun værten kan researche genstande.
map.multiplayer = Only the host can view sectors.
uncover = Afdæk
configure = Konfigurer udrustning
@@ -725,6 +729,7 @@ error.mapnotfound = Bane-filen er blevet væk!
error.io = Network I/O-fejl.
error.any = Ukendt netværksfejl.
error.bloom = Kunne ikke etablere bloom-effekt.\nMåske understøtter din enhed den ikke.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Regn
weather.snowing.name = Sne
@@ -774,6 +779,11 @@ threat.medium = Medium
threat.high = High
threat.extreme = Extreme
threat.eradication = Eradication
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planets
planet.serpulo.name = Serpulo
@@ -795,9 +805,19 @@ sector.fungalPass.name = Fungal Pass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on.
sector.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders.
@@ -817,6 +837,18 @@ sector.impact0078.description = Here lie remnants of the interstellar transport
sector.planetaryTerminal.description = The final target.\n\nThis coastal base contains a structure capable of launching Cores to local planets. It is extremely well guarded.\n\nProduce naval units. Eliminate the enemy as quickly as possible. Research the launch structure.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
sector.lake.name = Lake
@@ -1013,6 +1045,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1077,6 +1110,8 @@ bullet.healamount = [stat]{0}[lightgray] direct repair
bullet.multiplier = [stat]{0}[lightgray]x ammunitionsfaktor
bullet.reload = [stat]{0}[lightgray]x skydehastighed
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blokke
unit.blockssquared = blokke²
@@ -1137,12 +1172,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI-skalering[lightgray] (genstart kræves)[]
setting.uiscale.description = Restart required to apply changes.
setting.swapdiagonal.name = Altid diagonal placering
-setting.difficulty.training = Træning
-setting.difficulty.easy = Let
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Svær
-setting.difficulty.insane = Sindssyg
-setting.difficulty.name = Sværhedsgrad:
setting.screenshake.name = Skærm-ryst
setting.bloomintensity.name = Bloom Intensity
setting.bloomblur.name = Bloom Blur
@@ -1232,6 +1261,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Vælg region
keybind.schematic_menu.name = Skabelon-visning
@@ -1309,12 +1339,16 @@ rules.wavetimer = Bølge-æggeur
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Bølger
rules.airUseSpawns = Air units use spawn points
rules.attack = Angrebsmode
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Squad Size
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min Attack Weight
@@ -1357,6 +1391,9 @@ rules.title.teams = Teams
rules.title.planet = Planet
rules.lighting = Lys
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Ild
rules.anyenv =
rules.explosions = Blok/Enheds-eksplosionsskade
@@ -1365,6 +1402,7 @@ rules.weather = Vejr
rules.weather.frequency = Frekvens:
rules.weather.always = Always
rules.weather.duration = Varighed:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1505,6 +1543,8 @@ block.graphite-press.name = Grafitvalse
block.multi-press.name = Multi-valse
block.constructing = {0} [lightgray](Konstruerer)
block.spawn.name = Fjendtligt Ankomstpunkt
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Kerne: Skår
block.core-foundation.name = Kerne: Fundament
block.core-nucleus.name = Kerne: Nukleus
@@ -1762,6 +1802,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1809,6 +1850,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2032,6 +2074,10 @@ block.phase-wall.description = En væg legeret med specielt, reflekterende fase-
block.phase-wall-large.description = En væg legeret med specielt, reflekterende fase-stof. Reflekterer de fleste slags skud.\nFylder flere felter.
block.surge-wall.description = En ekstremt hård væg.\nOpbygger en ladning ved at absorbere skud. Ladningen affyres tilfældigt
block.surge-wall-large.description = En ekstremt hård væg.\nOpbygger en ladning ved at absorbere skud. Ladningen affyres tilfældigt.\nFylder flere felter.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = En bette dør. Kan åbnes og lukkes ved at trykke på den.
block.door-large.description = En stor dør. Kan åbnes og lukkes ved at trykke på den.\nFylder flere felter.
block.mender.description = Reparerer løbende blokke i nærheden. Hjælper til at holde forsvaret oppe mellem bølger.\nSilicium kan bruges til at øge rækkevidde og effektivitet.
@@ -2159,6 +2205,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2171,6 +2218,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2329,6 +2377,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2481,6 +2530,7 @@ unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Don't move, but keep building/mining.\nThe default state.
lenum.stop = Stop moving/mining/building.
lenum.unbind = Completely disable logic control.\nResume standard AI.
diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties
index 6bd88461d2..93e2ea95ee 100644
--- a/core/assets/bundles/bundle_de.properties
+++ b/core/assets/bundles/bundle_de.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Aktiviert
mod.disabled = [red]Deaktiviert
mod.multiplayer.compatible = [gray]Mehrspieler-kompatibel
mod.disable = Deaktivieren
+mod.version = Version:
mod.content = Inhalt:
mod.delete.error = Mod konnte nicht gelöscht werden. Datei könnte in Benutzung sein.
@@ -196,6 +197,7 @@ campaign.select = Startkampagne auswählen
campaign.none = [lightgray]Wähle einen Planeten, auf dem du starten möchtest.\nDies kannst du jederzeit ändern.
campaign.erekir = Neuerer, besserer Inhalt. Größtenteils linearer Fortschritt.\n\nSchwieriger. Höhere Karten- und Spielqualität.
campaign.serpulo = Ältere Inhalt; das klassische Spiel. Offener, mehr Inhalt. \n\nKarten und Spielmechanismen möglicherweise qualitativ schlechter und ohne Balance.
+campaign.difficulty = Difficulty
completed = [accent]Abgeschlossen
techtree = Forschung
techtree.select = Forschungsauswahl
@@ -296,13 +298,14 @@ disconnect.error = Verbindungsfehler.
disconnect.closed = Verbindung geschlossen.
disconnect.timeout = Zeitüberschreitung.
disconnect.data = Fehler beim Laden der Welt!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Nicht möglich beizutreten ([accent]{0}[]).
connecting = [accent] Verbinde...
reconnecting = [accent]Verbindung wird wiederhergestellt...
connecting.data = [accent] Welt wird geladen...
server.port = Port:
-server.addressinuse = Adresse bereits in Verwendung!
server.invalidport = Falscher Port!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson] Fehler beim Hosten des Servers:[accent] {0}
save.new = Neuer Spielstand
save.overwrite = Möchtest du diesen Spielstand wirklich überschreiben?
@@ -355,6 +358,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -498,6 +502,7 @@ waves.units.show = Alle anzeigen
wavemode.counts = Menge
wavemode.totals = Gesamtmenge
wavemode.health = Lebenspunkte
+all = All
editor.default = [lightgray]
details = Details
@@ -668,7 +673,6 @@ requirement.capture = Erobere {0}
requirement.onplanet = Kontrolliere Sektor auf {0}
requirement.onsector = Lande auf Sektor: {0}
launch.text = Start
-research.multiplayer = Nur der Host kann forschen.
map.multiplayer = Nur der Host kann Sektoren ansehen.
uncover = Freischalten
configure = Anfangsressourcen festlegen
@@ -742,6 +746,7 @@ error.mapnotfound = Kartendatei nicht gefunden!
error.io = Netzwerk-I/O-Fehler.
error.any = Unbekannter Netzwerkfehler.
error.bloom = Bloom konnte nicht initialisiert werden.\nEs kann sein, dass dein Gerät es nicht unterstützt.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Regen
weather.snowing.name = Schnee
@@ -793,6 +798,11 @@ threat.medium = Mittel
threat.high = Hoch
threat.extreme = Extrem
threat.eradication = Zerstörung
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planeten
@@ -815,9 +825,19 @@ sector.fungalPass.name = Infizierter Gebirgspass
sector.biomassFacility.name = Biomassensyntheselabor
sector.windsweptIslands.name = Windgepeitschte Inseln
sector.extractionOutpost.name = Extraktionsaußenposten
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetares Launchterminal
sector.coastline.name = Küstenlinie
sector.navalFortress.name = Wasserfestung
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Der optimale Ort, um anzufangen. Schwache Gegner und weniger Ressourcen.\nSammele so viel Kupfer und Blei wie möglich.\nGeh weiter.
sector.frozenForest.description = Auch hier, näher an den Bergen, sind die Sporen. Sogar die niedrigen Temperaturen können sie nicht zurückhalten.\n\nLerne, Strom zu verwenden. Baue Verbrennungsgeneratoren und Reparateure.
@@ -837,6 +857,18 @@ sector.impact0078.description = Hier liegen Reste der interplanetarischen Transp
sector.planetaryTerminal.description = Das Endziel.\n\nDiese Uferbasis besitzt ein Gerät, mit dem es möglich ist, Kerne auf andere Planeten zu schicken. Es ist [accent]sehr[] gut beschützt.\n\nStelle Wassereinheiten her. Eliminiere den Gegner so schnell wie möglich. Erforsche das Launchgerät.
sector.coastline.description = Überreste alter Schiffstechnologien wurden hier entdeckt. Wehre dich gegen die gegnischen Angriffe, erobere den Sektor und erforsche diese Technologie.
sector.navalFortress.description = Der Gegner hat auf einer abgelegenen, von Natur aus sicheren Insel eine Basis aufgebaut. Zerstöre diesen Außenposten. Finde deren fortgeschrittene Schiffstechnologien und erforsche diese weiter.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = Der Anfang
sector.aegis.name = Aegis
@@ -1035,6 +1067,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1099,6 +1132,8 @@ bullet.healamount = [stat]{0}[lightgray] direkte Reperatur
bullet.multiplier = [stat]{0}[lightgray]x Munition Multiplikator
bullet.reload = [stat]{0}%[lightgray] Feuerrate
bullet.range = [stat]{0}[lightgray] Blöcke Reichweite
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = Blöcke
unit.blockssquared = Blöcke²
@@ -1159,12 +1194,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI-Skalierung
setting.uiscale.description = Neustart erforderlich.
setting.swapdiagonal.name = Immer diagonale Platzierung
-setting.difficulty.training = Training
-setting.difficulty.easy = Leicht
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Schwer
-setting.difficulty.insane = Verrückt
-setting.difficulty.name = Schwierigkeit:
setting.screenshake.name = Wackeleffekt
setting.bloomintensity.name = Bloomstärke
setting.bloomblur.name = Bloomunschärfe
@@ -1254,6 +1283,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Region wiederaufbauen
keybind.schematic_select.name = Bereich auswählen
keybind.schematic_menu.name = Entwurfsmenü
@@ -1331,12 +1361,16 @@ rules.wavetimer = Wellen-Timer
rules.wavesending = Manuelle Wellen möglich
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Wellen
rules.airUseSpawns = Air units use spawn points
rules.attack = Angriff-Modus
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS KI [red](unfertig)
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min. Squadgröße
rules.rtsmaxsquadsize = Max. Squadgröße
rules.rtsminattackweight = Min. Attackiergewicht
@@ -1379,6 +1413,9 @@ rules.title.teams = Teams
rules.title.planet = Planet
rules.lighting = Blitze
rules.fog = Kriegsnebel
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Feuer
rules.anyenv =
rules.explosions = Explosionsschaden
@@ -1387,6 +1424,7 @@ rules.weather = Wetter
rules.weather.frequency = Häufigkeit:
rules.weather.always = Immer
rules.weather.duration = Dauer:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1531,6 +1569,8 @@ block.graphite-press.name = Graphit-Presse
block.multi-press.name = Multipresse
block.constructing = {0}\n[lightgray](Baut)
block.spawn.name = Gegnerischer Startpunkt
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Kern: Scherbe
block.core-foundation.name = Kern: Fundament
block.core-nucleus.name = Kern: Nukleus
@@ -1790,6 +1830,7 @@ block.electric-heater.name = Elektrisches Heizelement
block.slag-heater.name = Schlacke-Erhitzer
block.phase-heater.name = Phasenheizer
block.heat-redirector.name = Hitzeumleiter
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Hitzeverteiler
block.slag-incinerator.name = Schlackeverbrennungsanlage
block.carbide-crucible.name = Karbidtiegel
@@ -1837,6 +1878,7 @@ block.chemical-combustion-chamber.name = Chemische Verbrennungskammer
block.pyrolysis-generator.name = Pyrolysegenerator
block.vent-condenser.name = Schlotkondensator
block.cliff-crusher.name = Klippenbohrer
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasmabohrer
block.large-plasma-bore.name = Großer Plasmabohrer
block.impact-drill.name = Schlagbohrer
@@ -2075,6 +2117,10 @@ block.phase-wall.description = Beschützt Blöcke vor Gegnern, indem sie die mei
block.phase-wall-large.description = Beschützt Blöcke vor Gegnern, indem sie die meisten Schüsse reflektiert.
block.surge-wall.description = Beschützt Blöcke vor Gegnern und greift Gegner mit Lichtbögen an.
block.surge-wall-large.description = Beschützt Blöcke vor Gegnern und greift Gegner mit Lichtbögen an.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Ein Tor, das geöffnet und geschlossen werden kann.
block.door-large.description = Ein großes Tor, das geöffnet und geschlossen werden kann.
block.mender.description = Repariert regelmäßig Blöcke in seiner Umgebung.\nVerwendet optional Silizium, um Reichweite und Effizienz zu steigern.
@@ -2204,6 +2250,7 @@ block.electric-heater.description = Heizt Blöcke in einer bestimmten Richtung.
block.slag-heater.description = Heizt Blöcke in einer bestimmten Richtung. Benötigt Schlacke.
block.phase-heater.description = Heizt Blöcke in einer bestimmten Richtung. Benötigt Phasengewebe.
block.heat-redirector.description = Lenkt angesammelte Hitze weiter.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Verteilt angesammelte Hitze auf die 3 anderen Seiten.
block.electrolyzer.description = Spaltet Wasser in Wasserstoff und Ozon.
block.atmospheric-concentrator.description = Sammelt Stickstoff aus der Atmosphäre. Benötigt Hitze.
@@ -2216,6 +2263,7 @@ block.vent-condenser.description = Kondensiert Schlotgase zu Wasser. Verbraucht
block.plasma-bore.description = Baut unbefristet Erze aus einer Erzwand ab. Erfordert kleine Mengen an Strom.\nVerwendet optional Wasserstoff, um die Effizienz zu steigern.
block.large-plasma-bore.description = Ein größerer Plasmabohrer. Kann Wolfram und Thorium abbauen. Benötigt Wasserstoff und Strom.\nVerwendet optional Stickstoff, um die Effizienz zu steigern.
block.cliff-crusher.description = Zertrümmert Wände, um unbefristet Sand herzustellen. Benötigt Strom. Effizienz variiert je nach Wandart.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = Baut unbefristet Erze in Schüben aus dem Boden ab. Benötigt Strom und Wasser.
block.eruption-drill.description = Ein verbesserter Schlagbohrer. Kann Thorium abbauen. Benötigt Wasserstoff.
block.reinforced-conduit.description = Transportiert Flüssigkeiten. Nimmt von nicht-Kanälen nur von hinten an.
@@ -2378,6 +2426,7 @@ lst.getflag = Überprüfe, ob eine Flag gesetzt ist.
lst.setprop = Setzt eine Eigenschaft einer Einheit oder eines Blockes.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2549,6 +2598,7 @@ unitlocate.building = Variable für das Ergebnis.
unitlocate.outx = Variable für die X-Koordinate.
unitlocate.outy = Variable für die Y-Koordinate.
unitlocate.group = Gesuchter Blocktyp.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Bewegt sich nicht, baut aber weiter ab.\nDer normale Zustand.
lenum.stop = Bewegung / Abbau / Bau abbrechen.
diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties
index 93a2f0f3a4..e5090379a6 100644
--- a/core/assets/bundles/bundle_es.properties
+++ b/core/assets/bundles/bundle_es.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Activado
mod.disabled = [scarlet]Desactivado
mod.multiplayer.compatible = [gray]Compatible con multijugador
mod.disable = Desactivar
+mod.version = Version:
mod.content = Contenido:
mod.delete.error = No se pudo elminar el mod. Puede que el archivo esté en uso.
mod.incompatiblegame = [red]Juego desactualizado
@@ -193,6 +194,7 @@ campaign.select = Elegir campaña
campaign.none = [lightgray]Elige un planeta donde empezar.\nPuedes cambiar en cualquier momento.
campaign.erekir = [accent]Recomendado para nuevos jugadores.[]\n\nContenido más reciente y pulido. Progresión de campaña lineal.\n\nNiveles y experiencia de mayor calidad.
campaign.serpulo = [scarlet]No recomendado para jugadores novatos.[]\n\nContenido más antiguo; La experiencia clásica. More open-ended.\n\nNiveles y mecánicas de juego potencialmente desequilibrados.
+campaign.difficulty = Difficulty
completed = [accent]Completado
techtree = Investigaciones tecnológicas
techtree.select = Selección de esquemas de tecnologías
@@ -293,13 +295,14 @@ disconnect.error = Error de conexión.
disconnect.closed = Conexión cerrada.
disconnect.timeout = Tiempo de espera agotado.
disconnect.data = ¡Hubo un fallo al cargar los datos!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = No es posible unirse a la partida ([accent]{0}[]).
connecting = [accent]Conectando...
reconnecting = [accent]Reconectado...
connecting.data = [accent]Cargando datos del mundo...
server.port = Puerto:
-server.addressinuse = ¡La dirección ya está en uso!
server.invalidport = ¡El número de puerto no es valido!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [scarlet]Error alojando el servidor.
save.new = Nuevo archivo de guardado
save.overwrite = ¿Quieres sobrescribir\neste guardado?
@@ -352,6 +355,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -495,6 +499,7 @@ waves.units.show = Mostrar todo
wavemode.counts = limitadas
wavemode.totals = totales
wavemode.health = por salud
+all = All
editor.default = [lightgray]
details = Detalles...
@@ -665,7 +670,6 @@ requirement.capture = Capturar {0}
requirement.onplanet = Dominar sector de {0}
requirement.onsector = Aterrizar en el sector: {0}
launch.text = Lanzar
-research.multiplayer = Solo el anfitrión de la partida puede investigar nuevas tecnologías.
map.multiplayer = Solo el anfitrión de la partida puede ver los sectores del planeta.
uncover = Descubrir
configure = Configurar carga inicial
@@ -739,6 +743,7 @@ error.mapnotfound = ¡Archivo de mapa no encontrado!
error.io = Error I/O de conexión.
error.any = Error de red desconocido.
error.bloom = Error al cargar el efecto de bloom.\nPuede que tu dispositivo no sea compatible con esta característica.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Lluvia
weather.snowing.name = Nieve
@@ -789,6 +794,11 @@ threat.medium = Media
threat.high = Alta
threat.extreme = Extrema
threat.eradication = Erradicación
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planetas
@@ -811,9 +821,19 @@ sector.fungalPass.name = Desfiladero Contaminado
sector.biomassFacility.name = Centro de Sintetización de Biomasa
sector.windsweptIslands.name = Islas Windswept
sector.extractionOutpost.name = Puesto avanzado de Extracción
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Terminal de Lanzamiento Interplanetario
sector.coastline.name = Ruta Costera
sector.navalFortress.name = Fortaleza Naval
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = La ubicación adecuada para empezar una vez más. Baja amenaza enemiga. Pocos recursos.\nReúne la mayor cantidad de plomo y cobre posible y sigue adelante.
sector.frozenForest.description = Incluso aquí, cerca de las montañas, se han extendido las esporas. Las gélidas temperaturas no las contendrán para siempre.\nDescubre la energía eléctrica. Construye generadores de combustión. Aprende a usar reparadores.
@@ -833,6 +853,18 @@ sector.impact0078.description = Aquí yacen las ruinas de la primera nave de tra
sector.planetaryTerminal.description = El objetivo final.\n\nEsta base costera alberga una estructura capaz de lanzar núcleos a planeteas locales. Está extremadamente bien protegida.\n\nProduce unidades navales. Acaba con el enemigo lo antes posible. Analiza la estructura de lanzamiento.
sector.coastline.description = Se han detectado restos de tecnología de unidades navales en esta ubicación. Repele los ataques enemigos, captura este sector, y consigue esa tecnología.
sector.navalFortress.description = El enemigo ha establecido una base en una remota isla naturalmente fortificada. Destruye este puesto de avanzada. Hazte con su tecnología naval avanzada, e investígala.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = El Inicio
sector.aegis.name = Égida
@@ -1032,6 +1064,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1095,6 +1128,8 @@ bullet.healamount = [stat]{0}[lightgray] reparación en bruto
bullet.multiplier = [stat]{0}[lightgray]x multiplicador de munición
bullet.reload = [stat]{0}[lightgray]x cadencia de fuego
bullet.range = [stat]{0}[lightgray] bloques de alcance
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = bloques
unit.blockssquared = bloques²
@@ -1155,12 +1190,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Escala de interfaz
setting.uiscale.description = Es necesario reiniciar para aplicar los cambios.
setting.swapdiagonal.name = Construir siempre en diagonal
-setting.difficulty.training = Entrenamiento
-setting.difficulty.easy = Fácil
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Difícil
-setting.difficulty.insane = Demencial
-setting.difficulty.name = Dificultad:
setting.screenshake.name = Vibración de pantalla
setting.bloomintensity.name = Intensidad de desenfoque de Bloom
setting.bloomblur.name = Difuminado de puntos de luz (Bloom)
@@ -1250,6 +1279,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Reconstruir región
keybind.schematic_select.name = Seleccionar región
keybind.schematic_menu.name = Menú de esquemas
@@ -1327,12 +1357,16 @@ rules.wavetimer = Temporizador de oleadas
rules.wavesending = Envío de oleadas
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Oleadas
rules.airUseSpawns = Air units use spawn points
rules.attack = Modo de ataque
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = IA enemiga avanzada (RTS AI)
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Tamaño mínimo de escuadrón
rules.rtsmaxsquadsize = Tamaño máximo de escuadrón
rules.rtsminattackweight = Peso mínimo de ataque
@@ -1375,6 +1409,9 @@ rules.title.teams = Equipos
rules.title.planet = Planeta
rules.lighting = Iluminación
rules.fog = Ocultar terreno inexplorado (Fog of War)
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fuego
rules.anyenv =
rules.explosions = Daño de explosiones a bloques/unidades
@@ -1383,6 +1420,7 @@ rules.weather = Clima
rules.weather.frequency = Frecuencia:
rules.weather.always = Siempre
rules.weather.duration = Duracion:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Evita que las unidades depositen materiales en calquiera estructura a excepción del nucleo.
@@ -1527,6 +1565,8 @@ block.graphite-press.name = Prensa de grafito
block.multi-press.name = Multi-Prensa
block.constructing = {0} [lightgray](Construyendo)
block.spawn.name = Zona de aterrizaje enemiga
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Núcleo: Shard
block.core-foundation.name = Núcleo: Foundation
block.core-nucleus.name = Núcleo: Nucleus
@@ -1786,6 +1826,7 @@ block.electric-heater.name = Radiador eléctrico
block.slag-heater.name = Caldera de magma
block.phase-heater.name = Radiador de fase
block.heat-redirector.name = Redireccionador térmico
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Enrutador térmico
block.slag-incinerator.name = Incinerador de magma
block.carbide-crucible.name = Crisol de carburo
@@ -1833,6 +1874,7 @@ block.chemical-combustion-chamber.name = Cámara de combustión química
block.pyrolysis-generator.name = Generador pirolítico
block.vent-condenser.name = Condensador de grietas
block.cliff-crusher.name = Triturador de paredes
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Perforador de plasma
block.large-plasma-bore.name = Perforador de plasma grande
block.impact-drill.name = Taladro de impacto
@@ -2067,6 +2109,10 @@ block.phase-wall.description = Protege estructuras de proyectiles enemigos. Pued
block.phase-wall-large.description = Protege estructuras de proyectiles enemigos. Puede reflejar la mayoría de proyectiles al impactar.
block.surge-wall.description = Protege estructuras de proyectiles enemigos. Al contaco, libera arcos eléctricos periódicamente.
block.surge-wall-large.description = Protege estructuras de proyectiles enemigos. Al contaco, libera arcos eléctricos periódicamente.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Un muro que puede estar cerrado o abierto, permitiendo el paso a través de él.
block.door-large.description = Un muro que puede estar cerrado o abierto, permitiendo el paso a través de él.
block.mender.description = Repara estructuras cercanas constantemente. Puede usar silicio para potenciar su alcance y eficiencia.
@@ -2196,6 +2242,7 @@ block.electric-heater.description = Calienta los bloques a los que apunta. Requi
block.slag-heater.description = Calienta los bloques a los que apunta. Requiere magma.
block.phase-heater.description = Calienta los bloques a los que apunta. Requiere tejido de fase.
block.heat-redirector.description = Redirige el calor que acumula a otros bloques.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Distribuye el calor acumulado en tres direcciones de salida.
block.electrolyzer.description = Convierte agua en hidrógeno y gas de ozono.
block.atmospheric-concentrator.description = Concentra el nitrógeno disperso en la atmósfera. Requiere calor.
@@ -2208,6 +2255,7 @@ block.vent-condenser.description = Condensa gases en agua. Consume energía.
block.plasma-bore.description = Si se coloca mirando hacia un muro con minerales, genera objetos indefinidamente. Requiere pequeñas cantidades de energía.
block.large-plasma-bore.description = Un láser de plasma más grande, capaz de extraer tungsteno y torio. Requiere hidrógeno y energía.
block.cliff-crusher.description = Tritura paredes, extrayendo arena indefinidamente. Requiere energía. Su eficiencia depende del tipo de pared.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = Si se coloca sobre un mineral, extraerá ráfagas de objetos indefinidamente. Requiere energía y agua.
block.eruption-drill.description = Un taladro de impacto mejorado, capaz de extraer torio. Requiere hidrógeno.
block.reinforced-conduit.description = Mueve fluidos en una dirección. Sus lados no se conectarán con otros tipos de bloques, salvo que también sean tuberías.
@@ -2371,6 +2419,7 @@ lst.getflag = Comprueba si se ha establecido una etiqueta global.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2542,6 +2591,7 @@ unitlocate.building = Variable de salida para contrucciones localizadas.
unitlocate.outx = Coordenada X devuelta.
unitlocate.outy = Coordenada Y devuelta.
unitlocate.group = Grupo de bloque a buscar.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = No se mueve, pero seguirá construyendo/extrayendo minerales.\nEs el estado por defecto.
lenum.stop = Deja de moverse/extraer minerales/contruir.
diff --git a/core/assets/bundles/bundle_et.properties b/core/assets/bundles/bundle_et.properties
index f7fd198ab3..bbf3b905c8 100644
--- a/core/assets/bundles/bundle_et.properties
+++ b/core/assets/bundles/bundle_et.properties
@@ -141,6 +141,7 @@ mod.enabled = [lightgray]Enabled
mod.disabled = [scarlet]Disabled
mod.multiplayer.compatible = [gray]Multiplayer Compatible
mod.disable = Disable
+mod.version = Version:
mod.content = Content:
mod.delete.error = Unable to delete mod. File may be in use.
mod.incompatiblegame = [red]Outdated Game
@@ -190,6 +191,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Olemas
techtree = Uurimispuu
techtree.select = Tech Tree Selection
@@ -289,13 +291,14 @@ disconnect.error = Ühenduse viga.
disconnect.closed = Ühendus on suletud.
disconnect.timeout = Ühendus aegus.
disconnect.data = Maailma andmete allalaadimine ebaõnnestus!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Mänguga ei saanud liituda ([accent]{0}[]).
connecting = [accent]Ühendamine...
reconnecting = [accent]Reconnecting...
connecting.data = [accent]Maailma andmete allalaadimine...
server.port = Port:
-server.addressinuse = Aadress on juba kasutusel!
server.invalidport = Ebasobiv pordi number!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Viga serveri hostimisel.
save.new = Uus salvestis
save.overwrite = Oled kindel, et soovid selle salvestise asendada?
@@ -348,6 +351,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -490,6 +494,7 @@ waves.units.show = Show All
wavemode.counts = counts
wavemode.totals = totals
wavemode.health = health
+all = All
editor.default = [lightgray]
details = Üksikasjad...
@@ -657,7 +662,6 @@ requirement.capture = Capture {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Launch
-research.multiplayer = Only the host can research items.
map.multiplayer = Only the host can view sectors.
uncover = Ava
configure = Muuda varustust
@@ -725,6 +729,7 @@ error.mapnotfound = Maailmafaili ei leitud!
error.io = Võrgu sisend-väljundi viga.
error.any = Teadmata viga võrgus.
error.bloom = Bloom-efekti lähtestamine ebaõnnestus.\nSinu seade ei pruugi seda efekti toetada.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Rain
weather.snowing.name = Snow
@@ -774,6 +779,11 @@ threat.medium = Medium
threat.high = High
threat.extreme = Extreme
threat.eradication = Eradication
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planets
planet.serpulo.name = Serpulo
@@ -795,9 +805,19 @@ sector.fungalPass.name = Fungal Pass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on.
sector.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders.
@@ -817,6 +837,18 @@ sector.impact0078.description = Here lie remnants of the interstellar transport
sector.planetaryTerminal.description = The final target.\n\nThis coastal base contains a structure capable of launching Cores to local planets. It is extremely well guarded.\n\nProduce naval units. Eliminate the enemy as quickly as possible. Research the launch structure.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
sector.lake.name = Lake
@@ -1013,6 +1045,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1077,6 +1110,8 @@ bullet.healamount = [stat]{0}[lightgray] direct repair
bullet.multiplier = [stat]{0}[lightgray]x laskemoona kordaja
bullet.reload = [stat]{0}[lightgray]x tulistamise kiirus
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blokki
unit.blockssquared = blocks²
@@ -1137,12 +1172,6 @@ setting.fpscap.text = {0} kaadrit/s
setting.uiscale.name = Kasutajaliidese suurus[lightgray] (vajab mängu taaskäivitamist)[]
setting.uiscale.description = Restart required to apply changes.
setting.swapdiagonal.name = Paiguta alati diagonaalselt
-setting.difficulty.training = Treening
-setting.difficulty.easy = Lihtne
-setting.difficulty.normal = Keskmine
-setting.difficulty.hard = Raske
-setting.difficulty.insane = Hullumeelne
-setting.difficulty.name = Raskusaste:
setting.screenshake.name = Ekraani värisemine
setting.bloomintensity.name = Bloom Intensity
setting.bloomblur.name = Bloom Blur
@@ -1232,6 +1261,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Select Region
keybind.schematic_menu.name = Schematic Menu
@@ -1309,12 +1339,16 @@ rules.wavetimer = Kasuta taimerit
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Kasuta lahingulaineid
rules.airUseSpawns = Air units use spawn points
rules.attack = Mänguviis "Rünnak"
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Squad Size
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min Attack Weight
@@ -1357,6 +1391,9 @@ rules.title.teams = Teams
rules.title.planet = Planet
rules.lighting = Lighting
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fire
rules.anyenv =
rules.explosions = Block/Unit Explosion Damage
@@ -1365,6 +1402,7 @@ rules.weather = Weather
rules.weather.frequency = Frequency:
rules.weather.always = Always
rules.weather.duration = Duration:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1505,6 +1543,8 @@ block.graphite-press.name = Grafiidipress
block.multi-press.name = Multipress
block.constructing = {0} [lightgray](Ehitamine)
block.spawn.name = Vaenlaste maandumisala
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Tuumik: Osake
block.core-foundation.name = Tuumik: Arenenud
block.core-nucleus.name = Tuumik: Täielik
@@ -1762,6 +1802,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1809,6 +1850,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2034,6 +2076,10 @@ block.phase-wall.description = Tugev kaitsekonstruktsioon, mis on kaetud erilise
block.phase-wall-large.description = Tugev kaitsekonstruktsioon, mis on kaetud erilise faaskangapõhise peegeldava ühendiga. Pakub kaitset peaaegu kõiki tüüpi kuulide ja mürskude eest.\nUlatub üle mitme bloki.
block.surge-wall.description = Äärmiselt tugev kaitsekonstruktsioon.\nKuulidega kokkupõrkel neelab energiat, vabastades seda suvalistel hetkedel.
block.surge-wall-large.description = Äärmiselt tugev kaitsekonstruktsioon.\nKuulidega kokkupõrkel neelab energiat, vabastades seda suvalistel hetkedel.\nUlatub üle mitme bloki.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Väike uks, mida saab avada ja sulgeda sellele vajutades.
block.door-large.description = Suur uks, mida saab avada ja sulgeda sellele vajutades.\nUlatub üle mitme bloki.
block.mender.description = Parandab perioodiliselt enda ümber olevaid konstruktsioone, hoides neid lahingulainete järel töökorras ja tervena. Ulatuse ja efektiivsuse parendamiseks on võimalik kasutada räni.
@@ -2161,6 +2207,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2173,6 +2220,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2331,6 +2379,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2483,6 +2532,7 @@ unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Don't move, but keep building/mining.\nThe default state.
lenum.stop = Stop moving/mining/building.
lenum.unbind = Completely disable logic control.\nResume standard AI.
diff --git a/core/assets/bundles/bundle_eu.properties b/core/assets/bundles/bundle_eu.properties
index c2f4e97364..b0feaf9914 100644
--- a/core/assets/bundles/bundle_eu.properties
+++ b/core/assets/bundles/bundle_eu.properties
@@ -141,6 +141,7 @@ mod.enabled = [lightgray]Gaituta
mod.disabled = [scarlet]Desgaituta
mod.multiplayer.compatible = [gray]Hainbat jokalariekin bateragarria
mod.disable = Desgaitu
+mod.version = Version:
mod.content = Edukia:
mod.delete.error = Ezin izan da mod-a ezabatu. Agian fitxategia erabilia izaten ari da.
mod.incompatiblegame = [red]Outdated Game
@@ -190,6 +191,7 @@ campaign.select = Hautatu hasierako kanpaina
campaign.none = [lightgray]hautatu hasteko planeta.\nHau edonoiz aldatu daiteke.
campaign.erekir = [accent]Jokalari berrientzak aholkatua.[]\n\nEduki berriagoa eta landuagoa. Kanpaina aurreratze lineala.\n\nKalitate hobeko mapak eta esperientzia orokorra.
campaign.serpulo = [scarlet]Ez aholkatua jokalari berrientzat.[]\n\nEduki zaharra; esperientzia klasikoa. Irekiagoa.\n\nAgian desorekatuak dauden mapak eta kanpainaren mekanikak. Ez horren landua.
+campaign.difficulty = Difficulty
completed = [accent]Ikertua
@@ -291,13 +293,14 @@ disconnect.error = Konexio errorea.
disconnect.closed = Konexioa itxita.
disconnect.timeout = Denbor-muga agortuta.
disconnect.data = Huts egin du munduaren datuak eskuratzean!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Ezin izan da partidara elkartu ([accent]{0}[]).
connecting = [accent]Konektatzen...
reconnecting = [accent]Reconnecting...
connecting.data = [accent]Munduaren datuak kargatzen...
server.port = Ataka:
-server.addressinuse = Helbidea dagoeneko erabilita dago!
server.invalidport = Ataka zenbaki baliogabea!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Errorea zerbitzaria ostatatzean: [accent]{0}
save.new = Gordetako partida berria
save.overwrite = Ziur gordetzeko tarte hau gainidatzi nahi duzula?
@@ -350,6 +353,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -492,6 +496,7 @@ waves.units.show = Show All
wavemode.counts = counts
wavemode.totals = totals
wavemode.health = health
+all = All
editor.default = [lightgray]
details = Xehetasunak...
@@ -659,7 +664,6 @@ requirement.capture = Capture {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Launch
-research.multiplayer = Only the host can research items.
map.multiplayer = Only the host can view sectors.
uncover = Estalgabetu
configure = Konfiguratu zuzkidura
@@ -727,6 +731,7 @@ error.mapnotfound = Ez da mapa-fitxategia aurkitu!
error.io = Sareko irteera/sarrera errorea.
error.any = Sareko errore ezezaguna.
error.bloom = Ezin izan da distira hasieratu.\nAgian zure gailuak ez du onartzen.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Rain
weather.snowing.name = Snow
@@ -776,6 +781,11 @@ threat.medium = Medium
threat.high = High
threat.extreme = Extreme
threat.eradication = Eradication
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planets
planet.serpulo.name = Serpulo
@@ -797,9 +807,19 @@ sector.fungalPass.name = Fungal Pass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on.
sector.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders.
@@ -819,6 +839,18 @@ sector.impact0078.description = Here lie remnants of the interstellar transport
sector.planetaryTerminal.description = The final target.\n\nThis coastal base contains a structure capable of launching Cores to local planets. It is extremely well guarded.\n\nProduce naval units. Eliminate the enemy as quickly as possible. Research the launch structure.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
sector.lake.name = Lake
@@ -1015,6 +1047,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1079,6 +1112,8 @@ bullet.healamount = [stat]{0}[lightgray] direct repair
bullet.multiplier = [stat]{0}[lightgray]x munizio-biderkatzailea
bullet.reload = [stat]{0}[lightgray]x tiro tasa
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = bloke
unit.blockssquared = blocks²
@@ -1139,12 +1174,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Interfaze-eskala[lightgray] (berrabiarazi behar da)[]
setting.uiscale.description = Restart required to apply changes.
setting.swapdiagonal.name = Kokatu beti diagonalean
-setting.difficulty.training = Entrenamendua
-setting.difficulty.easy = Erraza
-setting.difficulty.normal = Arrunta
-setting.difficulty.hard = Zaila
-setting.difficulty.insane = Zoramena
-setting.difficulty.name = Zailtasuna:
setting.screenshake.name = Pantailaren astindua
setting.bloomintensity.name = Bloom Intensity
setting.bloomblur.name = Bloom Blur
@@ -1234,6 +1263,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Hautatu eskualdea
keybind.schematic_menu.name = Eskema menua
@@ -1311,12 +1341,16 @@ rules.wavetimer = Boladen denboragailua
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Boladak
rules.airUseSpawns = Air units use spawn points
rules.attack = Eraso modua
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Squad Size
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min Attack Weight
@@ -1359,6 +1393,9 @@ rules.title.teams = Teams
rules.title.planet = Planet
rules.lighting = Lighting
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fire
rules.anyenv =
rules.explosions = Block/Unit Explosion Damage
@@ -1367,6 +1404,7 @@ rules.weather = Weather
rules.weather.frequency = Frequency:
rules.weather.always = Always
rules.weather.duration = Duration:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1507,6 +1545,8 @@ block.graphite-press.name = Grafito prentsa
block.multi-press.name = Multi-prentsa
block.constructing = {0} [lightgray](Eraikitzen)
block.spawn.name = Etsai-sorrera
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Muina: Maskorra
block.core-foundation.name = Muina: Fundazioa
block.core-nucleus.name = Muina: Nukleoa
@@ -1764,6 +1804,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1811,6 +1852,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2036,6 +2078,10 @@ block.phase-wall.description = Fasez osatutako konposatu islatzaile batez estali
block.phase-wall-large.description = Fasez osatutako konposatu islatzaile batez estalitako horma bat. Talkan jasotako bala gehienak desbideratzen ditu.\nHainbat lauza hartzen ditu.
block.surge-wall.description = Defentsarako bloke nabarmen iraunkorra.\nKarga hartzen du balakadak jasotzean, hau edonora askatuz.
block.surge-wall-large.description = Defentsarako bloke nabarmen iraunkorra.\nKarga hartzen du balakadak jasotzean, edonora askatuz.\nHainbat lauza hartzen ditu.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Ate txiki bat. Sakatuz ireki eta itxi daiteke.
block.door-large.description = Ate handi bat. Sakatuz ireki eta itxi daiteke.\nHainbat lauza hartzen ditu.
block.mender.description = Aldiro inguruko blokeak konpontzen ditu. Defentsak bere onean mantentzen ditu boladen artean.\nAukeran silizioa erabili dezake irismena eta eraginkortasuna hobetzeko.
@@ -2163,6 +2209,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2175,6 +2222,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2333,6 +2381,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2485,6 +2534,7 @@ unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Don't move, but keep building/mining.\nThe default state.
lenum.stop = Stop moving/mining/building.
lenum.unbind = Completely disable logic control.\nResume standard AI.
diff --git a/core/assets/bundles/bundle_fi.properties b/core/assets/bundles/bundle_fi.properties
index 06da2a8ea5..2a5e05c5d4 100644
--- a/core/assets/bundles/bundle_fi.properties
+++ b/core/assets/bundles/bundle_fi.properties
@@ -141,6 +141,7 @@ mod.enabled = [lightgray]Käytössä
mod.disabled = [scarlet]Pois käytöstä
mod.multiplayer.compatible = [gray]Moninpelaajayhteensopiva
mod.disable = Poista käytössä
+mod.version = Version:
mod.content = Sisältö:
mod.delete.error = Modia ei pystytty poistamaan. Tiedosto voi olla käytössä.
mod.incompatiblegame = [red]Outdated Game
@@ -190,6 +191,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Suoritettu
techtree = Edistyspuu
techtree.select = Edistyspuun valinta
@@ -289,13 +291,14 @@ disconnect.error = Yhteysvirhe.
disconnect.closed = Yhteys poistettu.
disconnect.timeout = Yhteys aikakatkaistiin.
disconnect.data = Maailman tietojen lataaminen epäonnistui!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Peliin ei voitu liittyä ([accent]{0}[]).
connecting = [accent]Yhdistetään...
reconnecting = [accent]Yhdistetään uudelleen...
connecting.data = [accent]Ladataan maailman tietoja...
server.port = Portti:
-server.addressinuse = Osoite on jo käytössä!
server.invalidport = Tällä portilla ei löytynyt peliä!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Virhe palvelimen hostaamisessa: [accent]{0}
save.new = Uusi tallennus
save.overwrite = Haluatko varmasti korvata \ntämän tallennuspaikan??
@@ -348,6 +351,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -490,6 +494,7 @@ waves.units.show = Näytä kaikki
wavemode.counts = lukumäärä
wavemode.totals = yhteismäärä
wavemode.health = elämäpisteet
+all = All
editor.default = [lightgray]
details = Yksityiskohdat...
@@ -657,7 +662,6 @@ requirement.capture = Valtaa {0}
requirement.onplanet = Hallitse sektoria planeetalla {0}
requirement.onsector = Laskeudu sektorille: {0}
launch.text = Laukaise
-research.multiplayer = Vain ylläpitäjä voi tutkia tavaroita.
map.multiplayer = Vain ylläpitäjä voi katsella sektoreita.
uncover = Paljasta
configure = Muokkaa lastia
@@ -725,6 +729,7 @@ error.mapnotfound = Karttatiedostoa ei löydy!
error.io = Verkon I/O-virhe.
error.any = Tuntematon verkon virhe.
error.bloom = Bloomin initialisointi epäonnistui.\nLaitteesi ei ehkä tue sitä.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Sade
weather.snowing.name = Lumi
@@ -774,6 +779,11 @@ threat.medium = Kohtalainen
threat.high = Korkea
threat.extreme = Äärimmäinen
threat.eradication = Täystuho
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planeetat
planet.serpulo.name = Serpulo
@@ -795,9 +805,19 @@ sector.fungalPass.name = Sienirihmasto
sector.biomassFacility.name = Biomassasynteesilaitos
sector.windsweptIslands.name = Tuulenpieksemät saaret
sector.extractionOutpost.name = Kaivostukikohta
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetaarinen laukaisuterminaali
sector.coastline.name = Rantaviiva
sector.navalFortress.name = Laivastolinnoitus
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Optimaalinen sijainti aloittaa jälleen kerran. Matala vihollisuhka. Vähän resursseja.\nKerää niin paljon kuparia ja lyijyä, kuin mahdollista.\nJatka matkaa.
sector.frozenForest.description = Itiöt ovat levittäytyneet jopa tänne, lähemmäs vuoria. Jäätävät lämpötilat eivät voi torjua niitä ikuisesti.\n\nAloita seikkailusi virtaan. Rakenna polttogeneraattoreita. Opi käyttämään korjaajia.
@@ -817,6 +837,18 @@ sector.impact0078.description = Täällä lepäävät tähtienvälisen aluksen,
sector.planetaryTerminal.description = Viimeinen kohde.\n\nTämä rannikkotukikohta sisältää rakennuksen, joka pystyy laukaisemaan ytimiä paikallisille planeetoille. Se on vartioitu äärimmäisen hyvin.\n\nRakenna laivayksiköitä. Eliminoi vihollinen mahdollisimman pian. Tutki laukaisurakennus.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = Alku
sector.aegis.name = Aegis
sector.lake.name = Lake
@@ -1012,6 +1044,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1076,6 +1109,8 @@ bullet.healamount = [stat]{0}[lightgray] suora korjaus
bullet.multiplier = [stat]{0}[lightgray]x ammusmäärän kerroin
bullet.reload = [stat]{0}[lightgray]x ampumisnopeus
bullet.range = [stat]{0}[lightgray] laatan kantama
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = palikat
unit.blockssquared = palikat²
@@ -1136,12 +1171,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI Koko[lightgray] (vaatii uudelleenkäynnistyksen)[]
setting.uiscale.description = Muutosten toteuttaminen vaatii uudelleenkäynnistyksen
setting.swapdiagonal.name = Aina vino korvaus
-setting.difficulty.training = Treenaus
-setting.difficulty.easy = Huoleton
-setting.difficulty.normal = Haasteeton
-setting.difficulty.hard = Taidonnäyte
-setting.difficulty.insane = Hullun Vaikea
-setting.difficulty.name = Vaikeustaso:
setting.screenshake.name = Näytön keikkuminen
setting.bloomintensity.name = Bloom-intensiteetti
setting.bloomblur.name = Bloom-sumennus
@@ -1231,6 +1260,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Valitse alue
keybind.schematic_menu.name = Kaavio Valikko
@@ -1308,12 +1338,16 @@ rules.wavetimer = Tasojen aikaraja
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Tasot
rules.airUseSpawns = Air units use spawn points
rules.attack = Hyökkäystila
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min. hyökkäysjoukon koko
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min. hyökkäyksen paino
@@ -1356,6 +1390,9 @@ rules.title.teams = Joukkueet
rules.title.planet = Planeetta
rules.lighting = Salamointi
rules.fog = Sodan sumu (Fog of War)
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Tuli
rules.anyenv =
rules.explosions = Palikkojen/Yksikköjen räjähdysvahinko
@@ -1364,6 +1401,7 @@ rules.weather = Sää
rules.weather.frequency = Tiheys:
rules.weather.always = Aina
rules.weather.duration = Kesto:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1506,6 +1544,8 @@ block.graphite-press.name = Grafiittipuristin
block.multi-press.name = Monipuristin
block.constructing = {0} [lightgray](Rakentamassa)
block.spawn.name = Vihollisten syntymispiste
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Ydin: Siru
block.core-foundation.name = Ydin: Pohjaus
block.core-nucleus.name = Ydin: Tuma
@@ -1764,6 +1804,7 @@ block.electric-heater.name = Sähkölämmitin
block.slag-heater.name = Kuonalämmitin
block.phase-heater.name = Kiihtolämmitin
block.heat-redirector.name = Lämmönsiirtäjä
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Kuonahöyrystäjä
block.carbide-crucible.name = Karbidivalimo
@@ -1811,6 +1852,7 @@ block.chemical-combustion-chamber.name = Kemiallinen polttokammio
block.pyrolysis-generator.name = Pyrolyysigeneraattori
block.vent-condenser.name = Halkiotiivistäjä
block.cliff-crusher.name = Kallionmurskaaja
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasmapora
block.large-plasma-bore.name = Suuri plasmapora
block.impact-drill.name = Törmäyspora
@@ -2036,6 +2078,10 @@ block.phase-wall.description = Muuri, joka on päällystetty erityisellä kiihto
block.phase-wall-large.description = Muuri, joka on päällystetty erityisellä kiihtokuitupohjaisella heijastavalla yhdisteellä. Torjuu useimmat ammukset näiden törmätessä.\nKattaa useita laattoja.
block.surge-wall.description = Äärimmäisen kestävä puolustava palikka.\nVaraa jännitteen ammusten iskeytyessä, vapauttaen sen satunnaisesti.
block.surge-wall-large.description = Äärimmäisen kestävä puolustava palikka.\nVaraa jännitteen ammusten iskeytyessä, vapauttaen sen satunnaisesti.\nKattaa useita laattoja.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Pieni ovi. Voidaan avata ja sulkea painamalla.
block.door-large.description = Suuri ovi. Voidaan avata ja sulkea painamalla.\nKattaa useita laattoja.
block.mender.description = Korjaa läheisiä palikoita ajoittain. Pitää puolustuksia korjattuna tasojen aikana ja välillä.\nKäyttää valinnaisesti piitä tehostaakseen kantamaa ja tehoa.
@@ -2164,6 +2210,7 @@ block.electric-heater.description = Lämmittää päinkohdistettuja palikoita. V
block.slag-heater.description = Lämmittää päinkohdistettuja palikoita. Vaatii kuonaa.
block.phase-heater.description = Lämmittää päinkohdistettuja palikoita. Vaatii kiihtokuitua.
block.heat-redirector.description = Vaihtaa kertyneen lämmön suunnan toisiin palikoihin.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Muuttaa veden vedyksi ja otsonikaasuksi.
block.atmospheric-concentrator.description = Kerää typpeä ilmakehästä. Vaatii lämpöä.
@@ -2176,6 +2223,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2334,6 +2382,7 @@ lst.getflag = Tarkista, onko globaali tunniste asetettu.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2486,6 +2535,7 @@ unitlocate.building = Ulostulomuuttuja paikannetulle rakennukselle.
unitlocate.outx = X-koodinaatin ulostulo.
unitlocate.outy = Y-koodinaatin ulostulo.
unitlocate.group = Etsittävä rakennusjoukko.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Lopeta liikkuminen, mutta jatka rakentamista/kaivamista.\nOletustila.
lenum.stop = Lopeta liikkuminen/kaivaminen/rakentaminen.
lenum.unbind = Poista logiikkahallinta kokonaan.\nAnna hallinta tavalliselle AI:lle.
diff --git a/core/assets/bundles/bundle_fil.properties b/core/assets/bundles/bundle_fil.properties
index 466a2dd69e..8a250a8af6 100644
--- a/core/assets/bundles/bundle_fil.properties
+++ b/core/assets/bundles/bundle_fil.properties
@@ -141,6 +141,7 @@ mod.enabled = [lightgray]Gumagana
mod.disabled = [scarlet]Hindi Gumagana
mod.multiplayer.compatible = [gray]Multiplayer Compatible
mod.disable = 'Wag Paganahin
+mod.version = Version:
mod.content = Nilalaman:
mod.delete.error = 'Di matanggal ang mod. Maaaring ginagamit pa 'to.
mod.incompatiblegame = [red]Outdated Game
@@ -190,6 +191,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Completed
techtree = Tech Tree
techtree.select = Tech Tree Selection
@@ -289,13 +291,14 @@ disconnect.error = Connection error.
disconnect.closed = Connection closed.
disconnect.timeout = Na-time out.
disconnect.data = Pumalya ang pag-load ng world data!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Hindi kayant sumali sa larong ([accent]{0}[]).
connecting = [accent]Connecting...
reconnecting = [accent]Reconnecting...
connecting.data = [accent]Loading world data...
server.port = Port:
-server.addressinuse = Address already in use!
server.invalidport = Invalid port number!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [scarlet]Error hosting server.
save.new = Bagong Save
save.overwrite = Sigurado ka bang gusto mong i-overwrite ang save slot na ito?
@@ -348,6 +351,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -490,6 +494,7 @@ waves.units.show = Ipakita lahat
wavemode.counts = counts
wavemode.totals = totals
wavemode.health = health
+all = All
editor.default = [lightgray]
details = Details...
@@ -657,7 +662,6 @@ requirement.capture = Capture {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Launch
-research.multiplayer = Ang host lang ang makakapagsaliksik ng mga item.
map.multiplayer = Ang host lang ang makakatingin sa mga sektor.
uncover = Uncover
configure = I-Configure ang Loadout
@@ -725,6 +729,7 @@ error.mapnotfound = Hindi nakita ang file ng mapa!
error.io = Network I/O error.
error.any = Unknown network error.
error.bloom = Nabigong simulan ang bloom.\nMaaaring hindi ito sinusuportahan ng iyong device.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Rain
weather.snowing.name = Snow
@@ -774,6 +779,11 @@ threat.medium = Medium
threat.high = Mataas
threat.extreme = Sobra-sobra
threat.eradication = Tiyak na talo sa hind handa
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Mga planeta
planet.serpulo.name = Serpulo
@@ -795,9 +805,19 @@ sector.fungalPass.name = Fungal Pass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Ang pinakamainam na lokasyon upang magsimulang muli. Mababang banta ng kaaway. Kaunting mapagkukunan.\nMagtipon ng mas maraming tingga at tanso hangga't maaari.\nItuloy.
sector.frozenForest.description = Kahit dito, mas malapit sa mga bundok, ang mga spore ay kumalat. Ang napakalamig na temperatura ay hindi maaaring maglaman ng mga ito magpakailanman.\n\nSimulan ang pakikipagsapalaran sa kapangyarihan. Bumuo ng mga generator ng pagkasunog. Matutong gumamit ng mga mender.
@@ -817,6 +837,18 @@ sector.impact0078.description = Dito nakalatag ang mga labi ng interstellar tran
sector.planetaryTerminal.description = Ang huling target.\n\nAng coastal base na ito ay naglalaman ng isang istraktura na may kakayahang maglunsad ng mga Core sa mga lokal na planeta. Ito ay napakahusay na binabantayan.\n\nGumawa ng mga yunit ng hukbong-dagat. Tanggalin ang kalaban sa lalong madaling panahon. Magsaliksik sa istraktura ng paglulunsad.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
sector.lake.name = Lake
@@ -1012,6 +1044,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1076,6 +1109,8 @@ bullet.healamount = [stat]{0}[lightgray] direct repair
bullet.multiplier = [stat]{0}[lightgray]x ammo multiplier
bullet.reload = [stat]{0}[lightgray]x fire rate
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blocks
unit.blockssquared = blocks²
@@ -1136,12 +1171,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI Scaling[lightgray] (restart required)[]
setting.uiscale.description = Kinakailangan ang pag-restart upang mailapat ang mga pagbabago.
setting.swapdiagonal.name = Palaging Diagonal na Placement
-setting.difficulty.training = Training
-setting.difficulty.easy = Easy
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Hard
-setting.difficulty.insane = Insane
-setting.difficulty.name = Difficulty:
setting.screenshake.name = Screen Shake
setting.bloomintensity.name = Bloom Intensity
setting.bloomblur.name = Bloom Blur
@@ -1231,6 +1260,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Select Region
keybind.schematic_menu.name = Schematic Menu
@@ -1308,12 +1338,16 @@ rules.wavetimer = Wave Timer
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Waves
rules.airUseSpawns = Air units use spawn points
rules.attack = Attack Mode
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Squad Size
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min Attack Weight
@@ -1356,6 +1390,9 @@ rules.title.teams = Teams
rules.title.planet = Planet
rules.lighting = Lighting
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fire
rules.anyenv =
rules.explosions = Block/Unit Explosion Damage
@@ -1364,6 +1401,7 @@ rules.weather = Weather
rules.weather.frequency = Frequency:
rules.weather.always = Always
rules.weather.duration = Duration:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1504,6 +1542,8 @@ block.graphite-press.name = Graphite Press
block.multi-press.name = Multi-Press
block.constructing = {0} [lightgray](Constructing)
block.spawn.name = Enemy Spawn
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Core: Shard
block.core-foundation.name = Core: Foundation
block.core-nucleus.name = Core: Nucleus
@@ -1761,6 +1801,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1808,6 +1849,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2033,6 +2075,10 @@ block.phase-wall.description = Isang pader na pinahiran ng espesyal na phase-bas
block.phase-wall-large.description = Isang pader na pinahiran ng espesyal na phase-based na reflective compound. Pinapalihis ang karamihan sa mga bala kapag natamaan.\nGumagamit ng maraming tile.
block.surge-wall.description = Isang napakatibay na defensive block.\nNagpapalaki ng singil sa bullet contact, na ilalabas ito nang random.
block.surge-wall-large.description = Isang napakatibay na defensive block.\nBumubuo ng singil sa bullet contact, ilalabas ito nang random.\nGumagamit ng maraming tile.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Isang maliit na pinto. Maaaring buksan o isara sa pamamagitan ng pag-tap.
block.door-large.description = Isang malaking pinto. Maaaring buksan at isara sa pamamagitan ng pag-tap.\nSpans maramihang mga tile.
block.mender.description = Pana-panahong nag-aayos ng mga blocks sa paligid nito. Pinapanatiling maayos ang mga depensa sa pagitan ng mga alon.\nOpsyonal na gumagamit ng silicon upang palakasin ang saklaw at kahusayan.
@@ -2160,6 +2206,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2172,6 +2219,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2330,6 +2378,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2482,6 +2531,7 @@ unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Don't move, but keep building/mining.\nThe default state.
lenum.stop = Stop moving/mining/building.
lenum.unbind = Completely disable logic control.\nResume standard AI.
diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties
index 8c57d0bb1e..733a570e31 100644
--- a/core/assets/bundles/bundle_fr.properties
+++ b/core/assets/bundles/bundle_fr.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Activé
mod.disabled = [scarlet]Désactivé
mod.multiplayer.compatible = [gray]Compatible en Multijoueur
mod.disable = Désactiver
+mod.version = Version:
mod.content = Contenu :
mod.delete.error = Impossible de supprimer le mod. Le fichier est probablement en cours d'utilisation.
@@ -197,6 +198,7 @@ campaign.select = Sélectionnez la Campagne de Départ
campaign.none = [lightgray]Sélectionnez votre planète de départ.\nCela peut être changé à tout moment.
campaign.erekir = Contenu récent et mieux travaillé. Une progression dans la campagne assez linéaire.\n\nPlus difficile. Des cartes et une expérience de qualité.
campaign.serpulo = Contenu ancien, l'expérience classique de Mindustry. Avec plus de contenu et de possibilités.\n\nCartes et mécaniques de campagnes possiblement moins équilibrées. Moins travaillé.
+campaign.difficulty = Difficulty
completed = [accent]Complété
techtree = Arbre technologique
techtree.select = Sélection de l'Arbre technologique
@@ -299,13 +301,14 @@ disconnect.error = Un problème est survenu lors de la connexion.
disconnect.closed = Connexion fermée.
disconnect.timeout = Délai de connexion expiré.
disconnect.data = Les données du monde n'ont pas pu être chargées !
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Impossible de rejoindre ([accent]{0}[]).
connecting = [accent]Connexion...
reconnecting = [accent]Reconnexion...
connecting.data = [accent]Chargement des données du monde...
server.port = Port :
-server.addressinuse = Adresse déjà utilisée !
server.invalidport = Numéro de port invalide !
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [scarlet]Erreur lors de l'hébergement du serveur.
save.new = Nouvelle sauvegarde
save.overwrite = Êtes-vous sûr de vouloir\nécraser cette sauvegarde ?
@@ -358,6 +361,7 @@ command.enterPayload = Entrer dans Bloc de Transport
command.loadUnits = Transporter Unités
command.loadBlocks = Transporter Blocs
command.unloadPayload = Poser Chargement
+command.loopPayload = Loop Unit Transfer
stance.stop = Annuler les Ordres
stance.shoot = Ordre: Tirer
stance.holdfire = Ordre: Ne pas Tirer
@@ -501,6 +505,7 @@ waves.units.show = Afficher tout
wavemode.counts = compte
wavemode.totals = totaux
wavemode.health = santé
+all = All
editor.default = [lightgray]
details = Détails...
@@ -671,7 +676,6 @@ requirement.capture = Capturer {0}
requirement.onplanet = Contrôler le Secteur sur {0}
requirement.onsector = Atterrir sur le Secteur: {0}
launch.text = Décoller
-research.multiplayer = Seul l'hôte peut rechercher des objets.
map.multiplayer = Seul l'hôte peut voir les secteurs.
uncover = Découvrir
configure = Modifier le chargement
@@ -745,6 +749,7 @@ error.mapnotfound = Fichier de carte introuvable !
error.io = Erreur de Réseau (I/O)
error.any = Erreur de réseau inconnue.
error.bloom = Échec de l'initialisation du flou lumineux.\nIl se peut que votre appareil ne le prenne pas en charge.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Pluie
weather.snowing.name = Neige
@@ -796,6 +801,11 @@ threat.medium = Normale
threat.high = Grande
threat.extreme = Extrême
threat.eradication = Éradication
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planètes
@@ -818,9 +828,19 @@ sector.fungalPass.name = Fungal Pass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Un endroit optimal pour commencer. Avec une menace ennemie faible et peu de ressources disponibles.\nRassemblez autant de cuivre et de plomb que possible pour continuer votre exploration.
sector.frozenForest.description = Même ici, près des montagnes, les spores se sont propagées. Les températures glaciales ne pourront pas les contenir indéfiniment.\n\nCommencez votre production d'énergie en construisant des générateurs à combustion et apprenez à utiliser les bâtiments de soin.
@@ -840,6 +860,18 @@ sector.impact0078.description = Ici reposent les vestiges d'un vaisseau de trans
sector.planetaryTerminal.description = La cible finale.\n\nCette base côtière contient une structure capable de propulser des Noyaux sur les planètes voisines. Elle est extrêmement bien gardée.\n\nProduisez des unités navales, éliminez l’ennemi le plus rapidement possible et recherchez la structure de propulsion.
sector.coastline.description = Des restes d’unités navales ont été détectés à cet endroit. Repoussez les attaques ennemies, capturez ce secteur, et obtenez cette technologie.
sector.navalFortress.description = L’ennemi a établi une base sur une île isolée, avec des défenses naturelles. Détruisez cet avant-poste. Acquérez leur technologie navale avancée.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
@@ -1038,6 +1070,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1101,6 +1134,8 @@ bullet.healamount = [stat]{0}[lightgray] réparation directe
bullet.multiplier = [stat]{0}[lightgray]x multiplicateur de munitions
bullet.reload = [stat]{0}[lightgray]% vitesse de tir
bullet.range = [stat]{0}[lightgray] blocs de portée
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blocs
unit.blockssquared = blocs²
@@ -1161,12 +1196,6 @@ setting.fpscap.text = {0} FPS
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
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Difficile
-setting.difficulty.insane = Extrême
-setting.difficulty.name = Difficulté:
setting.screenshake.name = Tremblement de l'Écran
setting.bloomintensity.name = Intensité de l'effet de Bloom
setting.bloomblur.name = Flou de l'effet de Bloom
@@ -1257,6 +1286,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Reconstruire la Zone
keybind.schematic_select.name = Sélectionner une Région
@@ -1335,12 +1365,16 @@ rules.wavetimer = Compte à rebours des vagues
rules.wavesending = Déclenchement des Vagues
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Vagues
rules.airUseSpawns = Air units use spawn points
rules.attack = Mode « Attaque »
rules.buildai = IA de Construction de Base
rules.buildaitier = Niveau de l'IA de Construction de Base
rules.rtsai = IA de RTS [red](WIP)
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Taille Minimale d'une Escouade
rules.rtsmaxsquadsize = Taille Maximale d'une Escouade
rules.rtsminattackweight = Poids Minimum d'une Attaque
@@ -1383,6 +1417,9 @@ rules.title.teams = Équipes
rules.title.planet = Planète
rules.lighting = Éclairage
rules.fog = Brouillard de Guerre
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Feu
rules.anyenv =
rules.explosions = Dégâts d'explosion des Blocs/Unités
@@ -1391,6 +1428,7 @@ rules.weather = Météo
rules.weather.frequency = Fréquence :
rules.weather.always = Permanent
rules.weather.duration = Durée :
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1535,6 +1573,8 @@ block.graphite-press.name = Presse à Graphite
block.multi-press.name = Multi-Presse
block.constructing = {0} [lightgray](En Construction)
block.spawn.name = Point d'Apparition Ennemi
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Noyau: Fragment
block.core-foundation.name = Noyau: Fondation
block.core-nucleus.name = Noyau: Épicentre
@@ -1794,6 +1834,7 @@ block.electric-heater.name = Chauffage Électrique
block.slag-heater.name = Chauffage de Scories
block.phase-heater.name = Chauffage Phasé
block.heat-redirector.name = Redirecteur de Chaleur
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Routeur de Chaleur
block.slag-incinerator.name = Incinérateur de Scories
block.carbide-crucible.name = Grande fonderie de Carbure
@@ -1841,6 +1882,7 @@ block.chemical-combustion-chamber.name = Chambre de Combustion Chimique
block.pyrolysis-generator.name = Générateur à Pyrolyse
block.vent-condenser.name = Condenseur à Évent
block.cliff-crusher.name = Broyeur de Parois
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Foreuse à Plasma
block.large-plasma-bore.name = Grande Foreuse à Plasma
block.impact-drill.name = Foreuse à Impact
@@ -2075,6 +2117,10 @@ block.phase-wall.description = Ce mur est moins puissant qu'un mur en thorium, m
block.phase-wall-large.description = Ce mur est moins puissant qu'un mur en thorium, mais il peut dévier les balles, sauf si elles sont trop puissantes.
block.surge-wall.description = Le plus puissant bloc défensif.\nA une faible chance d'envoyer des éclairs vers les ennemis.
block.surge-wall-large.description = Le plus puissant bloc défensif.\nA une faible chance d'envoyer des éclairs vers les ennemis.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Une petite porte pouvant être ouverte et fermée en appuyant dessus.\nSi elle est ouverte, les ennemis peuvent passer à travers.
block.door-large.description = Une grande porte pouvant être ouverte et fermée en appuyant dessus.\nSi elle est ouverte, les ennemis peuvent passer à travers.
block.mender.description = Soigne périodiquement les bâtiments autour de lui, ce qui permet de remettre les défenses en bon état entre les vagues ennemies.\nPeut utiliser du silicium pour booster la portée et l'efficacité.
@@ -2204,6 +2250,7 @@ block.electric-heater.description = Applique de la chaleur aux structures. Néce
block.slag-heater.description = Applique de la chaleur structures. Nécessite des scories.
block.phase-heater.description = Applique de la chaleur aux structures. Nécessite du tissu phasé.
block.heat-redirector.description = Redirige la chaleur accumulée aux autres blocs.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Répartit la chaleur dans trois directions de sortie.
block.electrolyzer.description = Décompose l'eau en hydrogène et en ozone. Les sorties de chaque gaz sont situées de part et d'autres du bloc, marquées par leur couleur correspondante.
block.atmospheric-concentrator.description = Concentre l'azote retenu dans l'atmosphère. Requiert de la chaleur.
@@ -2216,6 +2263,7 @@ block.vent-condenser.description = Condense les gaz d'évents en eau. Consomme d
block.plasma-bore.description = Lorsqu'il est placé face à un mur de minerai, il produit des matériaux indéfiniment. Requiert peu d'énergie.\nPeut utiliser de l'hydrogène pour booster l'efficacité.
block.large-plasma-bore.description = Une foreuse à plasma plus large. Capable d'extraire du tungstène et du thorium. Nécessite de l'hydrogène et de l'énergie.\nPeut utiliser de l'azote pour booster l'efficacité.
block.cliff-crusher.description = Écrase les murs, produisant du sable indéfiniment. Nécessite de l'énergie. L'efficacité varie en fonction du type de mur.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = Lorsqu'il est placé sur du minerai, il produit des matériaux en rafales indéfiniment. Nécessite de l'énergie et de l'eau.
block.eruption-drill.description = Une foreuse à impact améliorée. Capable d'extraire du thorium. Requiert de l'hydrogène.
block.reinforced-conduit.description = Déplace les fluides. N'accepte pas les entrées sans conduit sur les côtés.
@@ -2378,6 +2426,7 @@ lst.getflag = Vérifie si une variable globale est présente.
lst.setprop = Change une propriété d'une unité ou d'un bâtiment.
lst.effect = Crée un effet de particules.
lst.sync = Synchronise une variable dans le réseau.\nLimité à 20 fois par seconde et par variable.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Crée un marqueur dans le monde.\nUn ID pour identifier le marqueur doit être donné.\nLes marqueurs sont limités à 20,000 par monde.
lst.setmarker = Change une propriété d'un marqueur.\nL'ID utilisé doit être le même que celui de l'instruction "Make Marker".
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2549,6 +2598,7 @@ unitlocate.building = Retourne une variable pour le bâtiment localisé.
unitlocate.outx = Retourne la coordonnée X.
unitlocate.outy = Retourne la coordonnée Y.
unitlocate.group = Le groupe de bâtiments à rechercher.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = L'Unité ne bouge plus, mais elle continue de construire/miner.\nL'état par défaut.
lenum.stop = Empêche l'unité de bouger/miner/construire.
diff --git a/core/assets/bundles/bundle_hu.properties b/core/assets/bundles/bundle_hu.properties
index 30fc904248..d730471f4b 100644
--- a/core/assets/bundles/bundle_hu.properties
+++ b/core/assets/bundles/bundle_hu.properties
@@ -14,7 +14,7 @@ link.f-droid.description = Listázás az F-Droidon
link.wiki.description = Hivatalos Mindustry wiki
link.suggestions.description = Új funkciók ajánlása
link.bug.description = Találtál egy szoftverhibát? Itt jelentheted
-linkopen = Ez a kiszolgáló egy hivatkozást küldött. Biztos vagy benne, hogy megnyitod?\n\n[sky]{0}
+linkopen = Ez a kiszolgáló egy hivatkozást küldött. Biztosan megnyitod?\nAkár kártékony is lehet!\n\n[sky]{0}
linkfail = Nem sikerült megnyitni a hivatkozást!\nA webcím a vágólapra lett másolva.
screenshot = Képernyőkép mentve ide: {0}
screenshot.invalid = Túl nagy a pálya, nincs elég memória a képernyőképhez.
@@ -32,10 +32,10 @@ load.image = Képek
load.content = Tartalom
load.system = Rendszer
load.mod = Modok
-load.scripts = Szkriptek
+load.scripts = Parancsfájlok
be.update = Új Bleeding Edge verzió áll rendelkezésre:
-be.update.confirm = Letöltöd és újraindítod a játékot?
+be.update.confirm = Letöltöd és frissíted a játékot?\n\nAmint kész a frissítés, a játék automatikusan újraindul.
be.updating = Frissítés...
be.ignore = Most nem
be.noupdates = Nem található frissítés.
@@ -46,7 +46,7 @@ mods.browser.selected = Mod kiválasztása
mods.browser.add = Letöltés
mods.browser.reinstall = Újratelepítés
mods.browser.view-releases = Kiadások megtekintése
-mods.browser.noreleases = [scarlet]Nem találhatóak a kiadások\n[accent]Nem találhatóak kiadások ehhez a modhoz. Nézd meg a tárolóját, hogy vannak-e kiadásai.
+mods.browser.noreleases = [scarlet]Nem találhatók a kiadások\n[accent]Nem találhatók kiadások ehhez a modhoz. Nézd meg a tárolóját, hogy vannak-e kiadásai.
mods.browser.latest = [lightgray][Legújabb]
mods.browser.releases = Kiadások
mods.github.open = Tároló
@@ -64,8 +64,8 @@ schematic.import = Vázlat importálása...
schematic.exportfile = Exportálás fájlba
schematic.importfile = Importálás fájlból
schematic.browseworkshop = Steam Műhely megtekintése
-schematic.copy = Végólapra másolás
-schematic.copy.import = Importálás vágólapról
+schematic.copy = Másolás a vágólapra
+schematic.copy.import = Importálás a vágólapról
schematic.shareworkshop = Megosztás a Steam Műhelyben
schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Vázlat tükrözése
schematic.saved = Vázlat elmentve.
@@ -76,11 +76,11 @@ schematic.disabled = [scarlet]Vázlatok letiltva[]\nNem használhatsz vázlatoka
schematic.tags = Címkék:
schematic.edittags = Címkék szerkesztése
schematic.addtag = Címke hozzáadása
-schematic.texttag = Szöveg címke
-schematic.icontag = Ikon címke
+schematic.texttag = Szövegcímke
+schematic.icontag = Ikoncímke
schematic.renametag = Címke átnevezése
schematic.tagged = {0} Címkézve
-schematic.tagdelconfirm = Teljesen törlöd ezt a címkét?
+schematic.tagdelconfirm = Biztosan törlöd ezt a címkét?
schematic.tagexists = Ez a címke már létezik.
stats = Statisztika
@@ -97,7 +97,7 @@ map.delete = Biztosan törölni akarod a(z) „[accent]{0}[]” nevű pályát?
level.highscore = Legmagasabb pontszám: [accent]{0}
level.select = Szint kiválasztása
level.mode = Játékmód:
-coreattack = < A támaszpont támadás alatt van! >
+coreattack = < A támaszpont támadás alatt áll! >
nearpoint = [[ [scarlet]AZONNAL HAGYD EL A LEDOBÁSI PONTOT![] ]\nA megsemmisülés fenyeget!
database = Támaszpont adatbázisa
database.button = Adatbázis
@@ -131,19 +131,20 @@ feature.unsupported = Ez az eszköz nem támogatja ezt a funkciót.
mods.initfailed = [red]⚠[] Az előző Mindustry példány előkészítése nem sikerült. Ezt valószínűleg egy rosszul működő mod okozta.\n\nAz ismételt összeomlások elkerülése érdekében [red]minden mod le lett tiltva.[]
mods = Modok
-mods.none = [lightgray]Nem találhatóak modok!
+mods.none = [lightgray]Nem találhatók modok!
mods.guide = Modkészítési útmutató
mods.report = Hiba jelentése
mods.openfolder = Mappa megnyitása
mods.viewcontent = Tartalom megtekintése
mods.reload = Újratöltés
-mods.reloadexit = A játék most kilép, hogy újratöltse a modokat.
+mods.reloadexit = A játék most kilép, hogy újratöltse a modokat a következő indításkor.
mod.installed = [[Telepítve]
mod.display = [gray]Mod:[orange] {0}
mod.enabled = [lightgray]Aktív
mod.disabled = [red]Inaktív
mod.multiplayer.compatible = [gray]Többjátékos kompatibilis
mod.disable = Letiltás
+mod.version = Version:
mod.content = Tartalom:
mod.delete.error = Nem lehet törölni a modot. Lehet, hogy egy másik folyamat használja.
@@ -157,7 +158,7 @@ mod.incompletedependencies = [red]Hiányos függőségek
mod.requiresversion.details = Szükséges játékverzió: [accent]{0}[]\nA játék ezen verziója elavult! A mod működéséhez újabb verzió szükséges (valószínűleg egy béta vagy alfa kiadás).
mod.outdatedv7.details = Ez a mod nem kompatibilis a játék legújabb verziójával! A mod készítőjének frissítenie kell azt és hozzá kell adnia ezt a [accent]mod.json[] fájlhoz: [accent]minGameVersion: 136[].
-mod.blacklisted.details = Ez a mod kézileg feketelistára került, mert a játék összeomlott tőle, vagy más problémát okozott. Ne használd!
+mod.blacklisted.details = Ez a mod automatikusan tiltólistára került, mert a játék összeomlott tőle, vagy más problémát okozott. Ne használd!
mod.missingdependencies.details = Ez a mod függőségeket hiányol: {0}
mod.erroredcontent.details = Ez a mod hibákat okozott a betöltésnél. Kérd meg a mod készítőjét, hogy javítsa őket.
mod.circulardependencies.details = Ennek a modnak egymástól függő függőségei vannak.
@@ -166,10 +167,10 @@ mod.incompletedependencies.details = Ez a mod nem tölthető be az érvénytelen
mod.requiresversion = Szükséges játékverzió: [red]{0}[]
mod.errors = Hiba történt a tartalom betöltése közben.
-mod.noerrorplay = [red]Hibákkal rendelkező modjaid vannak.[] Kapcsold ki, vagy javítsd ki őket a játék előtt.
+mod.noerrorplay = [red]Hibákkal rendelkező modjaid vannak.[] Kapcsold ki, vagy javítsd ki őket a játék elindítása előtt.
mod.nowdisabled = [red]A(z) „{0}” modnak nincs megfelelő függősége:[accent] {1}\n[lightgray]Ezeket előbb le kell tölteni.\nEz a mod automatikusan ki lesz kapcsolva.
mod.enable = Engedélyezés
-mod.requiresrestart = A játék kilép a módosítások alkalmazásához.
+mod.requiresrestart = A játék most kilép, hogy a módosítások érvénybe lépjenek a következő indításkor.
mod.reloadrequired = [red]Újraindítás szükséges
mod.import = Mod importálása
mod.import.file = Fájl importálása
@@ -180,8 +181,8 @@ mod.remove.confirm = Ez a mod törölve lesz.
mod.author = [lightgray]Készítő:[] {0}
mod.missing = Ez a mentés nemrég törölt vagy frissített modokat tartalmaz. Elképzelhető, hogy nem fog működni. Biztosan betöltöd?\n[lightgray]Modok:\n{0}
mod.preview.missing = Mielőtt közzéteszed ezt a modot a Steam Műhelyben, adj hozzá egy borítóképet.\nKészíts egy[accent] preview.png[] nevű képet a Mod mappájába, majd próbáld újra.
-mod.folder.missing = Csak mappa formában lehet feltölteni a Steam Műhelybe.\nHogy átalakítsd, bontsd ki a ZIP-fájlt egy mappába és töröld le a régit, majd indítsd újra a játékot, vagy töltsd újra a modokat.
-mod.scripts.disable = Ez az eszköz nem támogatja a szkriptekkel rendelkező modokat.\nA játékhoz tiltsd le ezeket a modokat.
+mod.folder.missing = Csak mappa formában lehet feltölteni a Steam Műhelybe.\nAhhoz, hogy átalakítsd, ki kell bontanod a ZIP-fájlt egy mappába és le kell törölnöd a régit, majd indítsd újra a játékot, vagy töltsd újra a modokat.
+mod.scripts.disable = Ez az eszköz nem támogatja a parancsfájlokkal rendelkező modokat.\nA játékhoz tiltsd le ezeket a modokat.
about.button = Névjegy
name = Név:
@@ -193,11 +194,12 @@ filename = Fájlnév:
unlocked = Új tartalom feloldva!
available = Új fejlesztés érhető el!
unlock.incampaign = < Oldd fel a hadjáratban a részletekért >
-campaign.select = Válassz kezdő hadjáratot
+campaign.select = Válassz ki egy kezdő hadjáratot
campaign.none = [lightgray]Válassz egy bolygót a kezdéshez.\nEzt bármikor megváltoztathatod.
campaign.erekir = Újabb, csiszoltabb tartalom. Többnyire lineáris játékmenet.\n\nSokkal nehezebb. Magasabb minőségű pályák és élmények.
campaign.serpulo = Régebbi tartalom. A klasszikus élmény. Nyíltabb végű, több tartalommal.\n\nPotenciálisan kiegyensúlyozatlan pályák és hadjárat. Kevésbé csiszolt.
-completed = [accent]Kész
+campaign.difficulty = Nehézségi szint
+completed = [accent]Kifejlesztve
techtree = Technológia fa
techtree.select = Technológia fa kiválasztása
techtree.serpulo = Serpulo
@@ -214,7 +216,7 @@ players.search = Keresés
players.notfound = [gray]Nem található játékos
server.closing = [accent]Kiszolgáló bezárása...
server.kicked.kick = Ki lettél rúgva a kiszolgálóról!
-server.kicked.whitelist = Nem vagy a fehérlistán.
+server.kicked.whitelist = Nem vagy az engedélyezési listán.
server.kicked.serverClose = A kiszolgáló be lett zárva.
server.kicked.vote = Ki lettél szavazva. Viszlát!
server.kicked.clientOutdated = Elavult játékverziót használsz! Frissítsd a játékot!
@@ -226,11 +228,11 @@ server.kicked.recentKick = Nemrég lettél kirúgva.\nVárj egy kicsit az újbó
server.kicked.nameInUse = Már van egy ilyen nevű játékos\nezen a kiszolgálón.
server.kicked.nameEmpty = A kiválasztott név érvénytelen.
server.kicked.idInUse = Már kapcsolódva vagy ehhez a kiszolgálóhoz! Nem lehet egyszerre két fiókot használni.
-server.kicked.customClient = Ez a kiszolgáló nem támogatja a saját készítésű játék-összeállításokat. Használj egy hivatalos változatot.
+server.kicked.customClient = Ez a kiszolgáló nem támogatja a saját készítésű játék-összeállításokat. Használj egy hivatalos változatot!
server.kicked.gameover = Vége a játéknak!
server.kicked.serverRestarting = Ez a kiszolgáló újraindul.
server.versions = A te játékverziód:[accent] {0}[]\nA kiszolgáló verziója:[accent] {1}[]
-host.info = A [accent]kiszolgáló indítása[] gomb egy kiszolgálót indít a [scarlet]6567-es[] porton.\nEzen a [lightgray]Wi-Fi-n vagy a helyi hálózaton[] bárki láthatja a kiszolgálót a kiszolgálólistán.\n\nHa azt szeretnéd, hogy bárhonnan, IP-címmel kapcsolódhassanak, akkor [accent]porttovábbítás[] szükséges.\n\n[lightgray]Megjegyzés: ha valakinek problémái vannak a LAN-játékhoz való kapcsolódással, győződj meg arról, hogy a tűzfal beállításaiban engedélyezted-e a Mindustry hozzáférését a helyi hálózathoz. Ne feledd, hogy a nyilvános hálózatok néha nem teszik lehetővé a kiszolgálók felderítését.
+host.info = A [accent]kiszolgáló indítása[] gomb egy kiszolgálót indít a [scarlet]6567-es[] porton.\nEzen a [lightgray]Wi-Fi-n vagy a helyi hálózaton[] bárki láthatja a kiszolgálót a kiszolgálólistán.\n\nHa azt szeretnéd, hogy bárki, aki ismeri az IP-címedet, bárhonnan kapcsolódhasson a kiszolgálódhoz, akkor a [accent]porttovábbítás[] beállítására lesz szükséged.\n\n[lightgray]Megjegyzés: ha problémáid vannak a LAN-játékhoz való kapcsolódással, győződj meg arról, hogy a tűzfal beállításaiban engedélyezted-e a Mindustry hozzáférését a helyi hálózathoz. Ne feledd, hogy a nyilvános hálózatok néha nem teszik lehetővé a kiszolgálók felderítését.
join.info = Itt megadhatod egy [accent]kiszolgáló IP-címét[] a kapcsolódáshoz, vagy felfedezhetsz [accent]helyi[] vagy [accent]globális[] kiszolgálókat.\nA LAN és WAN többjátékos mód is támogatott.\n\n[lightgray]Ha valakihez IP-cím alapján szeretnél kapcsolódni, akkor meg kell tudnod az IP-címét, amelyet például a „my ip” webes kereséssel találhatsz meg.
hostserver = Többjátékos játék
invitefriends = Barátok meghívása
@@ -274,7 +276,7 @@ player.trace = Követés
player.admin = Admin be/ki
player.team = Csapatváltás
-server.bans = Tiltások
+server.bans = Tiltólista
server.bans.none = Nincsenek tiltott játékosok!
server.admins = Adminok
server.admins.none = Nem található admin!
@@ -285,7 +287,7 @@ server.outdated = [scarlet]Elavult kiszolgáló![]
server.outdated.client = [scarlet]Elavult kliens![]
server.version = [gray]v{0} {1}
server.custombuild = [accent]Saját összeállítás
-confirmban = Biztosan tiltod a(z) „{0}[white]” nevű játékost?
+confirmban = Biztosan kitiltod a(z) „{0}[white]” nevű játékost?
confirmkick = Biztosan kirúgod a(z) „{0}[white]” nevű játékost?
confirmunban = Biztosan újra engedélyezed ezt a játékost?
confirmadmin = Biztosan előlépteted a(z) „{0}[white]” nevű játékost adminná?
@@ -299,17 +301,18 @@ disconnect.error = Kapcsolódási hiba.
disconnect.closed = Kapcsolat lezárva.
disconnect.timeout = Időtúllépés.
disconnect.data = Nem sikerült betölteni a világ adatait!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Nem sikerült kapcsolódni a(z) ([accent]{0}[]) játékhoz.
connecting = [accent]Kapcsolódás...
reconnecting = [accent]Újrakapcsolódás...
connecting.data = [accent]Világadatok betöltése...
server.port = Port:
-server.addressinuse = A cím már használatban van!
server.invalidport = Érvénytelen port!
-server.error = [scarlet]Kiszolgálási hiba.
+server.error.addressinuse = [scarlet]Nem sikerült megnyitni a kiszolgálót a 6567-es porton.[]\n\nGyőződj meg arról, hogy nem fut más Mindustry-kiszolgáló az eszközön vagy a hálózaton!
+server.error = [scarlet]Kiszolgálóhiba.
save.new = Új mentés
save.overwrite = Biztosan felülírod\nezt a mentést?
-save.nocampaign = A hadjáratból származó egyes mentési fájlok nem importálhatóak.
+save.nocampaign = A hadjáratból származó egyes mentési fájlok nem importálhatók.
overwrite = Felülírás
save.none = Nem található mentés!
savefail = Nem sikerült elmenteni a játékot!
@@ -354,10 +357,11 @@ command.rebuild = Újraépítés
command.assist = Segítség a játékosnak
command.move = Mozgás
command.boost = Erősítés
-command.enterPayload = Berakodás a rakományszállítóba
+command.enterPayload = Berakodás a raktérbe
command.loadUnits = Egységek felvétele
command.loadBlocks = Blokkok felvétele
-command.unloadPayload = Kirakodás a rakományszállítóból
+command.unloadPayload = Kirakodás a raktérből
+command.loopPayload = Folyamatos egységelszállítás
stance.stop = Parancsok visszavonása
stance.shoot = Viselkedés: lövés
stance.holdfire = Viselkedés: tüzet szüntess
@@ -376,8 +380,8 @@ data.export = Adatok exportálása
data.import = Adatok importálása
data.openfolder = Adatok mappájának megnyitása
data.exported = Adatok exportálva.
-data.invalid = Ezek nem érvényes játékadatok.
-data.import.confirm = A külső adatok importálása felülírja[scarlet] minden[] jelenlegi játékadatodat.\n[accent]Nem vonható vissza![]\n\nAmint kész az importálás, a játék azonnal kilép.
+data.invalid = Ezek érvénytelen játékadatok.
+data.import.confirm = A külső adatok importálása felülírja[scarlet] minden[] jelenlegi játékadatodat.\n[accent]Ezt a műveletet nem lehet visszavonni![]\n\nAmint kész az importálás, a játék automatikusan kilép.
quit.confirm = Biztosan kilépsz?
loading = [accent]Betöltés...
downloading = [accent]Letöltés...
@@ -408,7 +412,7 @@ saveimage = Kép mentése
unknown = Ismeretlen
custom = Egyéni
builtin = Beépített
-map.delete.confirm = Biztosan törlöd ezt a pályát? Ez a művelet nem vonható vissza!
+map.delete.confirm = Biztosan törlöd ezt a pályát? Ezt a műveletet nem lehet visszavonni!
map.random = [accent]Véletlenszerű pálya
map.nospawn = Ez a pálya nem rendelkezik támaszponttal, amellyel a játékos kezdhetne. Adj hozzá egy {0} támaszpontot a pályához a szerkesztőben.
map.nospawn.pvp = Ezen a pályán nincs ellenséges támaszpont, amellyel egy játékos kezdhet. Adj hozzá egy [scarlet]nem narancssárga[] támaszpontot a pályához a szerkesztőben.
@@ -416,15 +420,15 @@ map.nospawn.attack = Ezen a pályán nincs ellenséges támaszpont. Adj hozzá {
map.invalid = Hiba történt a pálya betöltésekor: sérült vagy érvénytelen fájl.
workshop.update = Elem frissítése
workshop.error = Hiba történt a Steam Műhely részleteinek lekérdezésekor: {0}
-map.publish.confirm = Biztos, hogy közzéteszed ezt a pályát?\n\n[lightgray]Győződj meg róla, hogy elfogadtad a Steam Műhely EULA-t, különben a pályáid nem jelennek meg.
+map.publish.confirm = Biztosan közzéteszed ezt a pályát?\n\n[lightgray]Győződj meg arról, hogy elfogadtad a Steam Műhely EULA-t, különben a pályáid nem jelennek meg.
workshop.menu = Válaszd ki, hogy mit szeretnél csinálni ezzel az elemmel.
workshop.info = Eleminformációk
-changelog = Változásnapló (nem kötelező):
+changelog = Változáslista (nem kötelező):
updatedesc = Cím és leírás felülírása
eula = Steam EULA
missing = Ezt az elemet törölték vagy áthelyezték.\n[lightgray]A Steam Műhely adatai automatikusan le lettek választva.
publishing = [accent]Közzététel...
-publish.confirm = Biztosan közzéteszed?\n\n[lightgray]Győződj meg róla, hogy elfogadtad a Steam Műhely EULA-t, különben az elemeid nem jelennek meg!
+publish.confirm = Biztosan közzéteszed ezt az elemet?\n\n[lightgray]Győződj meg arról, hogy elfogadtad a Steam Műhely EULA-t, különben az elemeid nem jelennek meg!
publish.error = Hiba az elem közzétételekor: {0}
steam.error = Nem sikerült előkészíteni a Steam szolgáltatásokat.\nHiba: {0}
@@ -447,9 +451,9 @@ editor.objectives = Célok
editor.locales = Helyi csomagok
editor.worldprocessors = Világprocesszorok
editor.worldprocessors.editname = Név szerkesztése
-editor.worldprocessors.none = [lightgray]Nem találhatóak világprocesszor blokkok!\nAdj hozzá egyet a pályaszerkesztőben, vagy használd az alábbi \ue813 hozzáadás gombot.
+editor.worldprocessors.none = [lightgray]Nem találhatók világprocesszor blokkok!\nAdj hozzá egyet a pályaszerkesztőben, vagy használd az alábbi \ue813 hozzáadás gombot.
editor.worldprocessors.nospace = Nincs szabad hely egy világprocesszor elhelyezéséhez!\nKitöltötted a pályát struktúrákkal? Miért tetted ezt?
-editor.worldprocessors.delete.confirm = Biztos, hogy törölni akarod ezt a világprocesszort?\n\nHa falakkal van körülvéve, akkor egy környezeti fal fog a helyére kerülni.
+editor.worldprocessors.delete.confirm = Biztosan törölni akarod ezt a világprocesszort?\n\nHa falakkal van körülvéve, akkor egy környezeti fal fog a helyére kerülni.
editor.ingame = Szerkesztés a játékban
editor.playtest = Teszt a játékban
editor.publish.workshop = Közzététel a Steam Műhelyben
@@ -471,12 +475,12 @@ waves.every = minden
waves.waves = hullámonként
waves.health = élet: {0}%
waves.perspawn = kezdőpontonként
-waves.shields = pajzs/hullám
+waves.shields = erőpajzs/hullám
waves.to = -
waves.spawn = kezdőpont:
waves.spawn.all =
waves.spawn.select = Kezdőpont kiválasztása
-waves.spawn.none = [scarlet]nem találhatóak kezdőpontok a pályán
+waves.spawn.none = [scarlet]nem találhatók kezdőpontok a pályán
waves.max = egységkorlát
waves.guardian = Őrző
waves.preview = Előnézet
@@ -497,16 +501,17 @@ waves.filter = Egységszűrő
waves.units.hide = Összes elrejtése
waves.units.show = Összes megjelenítése
-#these are intentionally in lower case
+#Az alábbi szövegek szándékosan vannak kisbetűvel írva
wavemode.counts = típusokra bontva
wavemode.totals = összesítés
wavemode.health = életpontok
+all = Összes
editor.default = [lightgray]
details = Részletek...
edit = Szerkesztés
variables = Változók
-logic.clear.confirm = Biztos, hogy törölni akarod az összes kódot ebből a processzorból?
+logic.clear.confirm = Biztosan törölni akarod az összes kódot ebből a processzorból?
logic.globals = Beépített változók
editor.name = Név:
@@ -551,7 +556,7 @@ editor.exportimage = Domborzati kép exportálása
editor.exportimage.description = Csak alapvető domborzatot tartalmazó képfájl exportálása
editor.loadimage = Domborzat importálása
editor.saveimage = Domborzat exportálása
-editor.unsaved = Biztos, hogy ki akarsz lépni?\n[scarlet]A nem mentett módosításaid elvesznek.
+editor.unsaved = Biztosan ki akarsz lépni?\n[scarlet]A nem mentett módosításaid elvesznek.
editor.resizemap = Pálya átméretezése
editor.mapname = Pálya neve:
editor.overwrite = [accent]Vigyázz!\nEzzel felülírsz egy már létező pályát.
@@ -575,7 +580,7 @@ toolmode.fillerase = Kitöltés törlése
toolmode.fillerase.description = Az azonos típusú blokkok törlése.
toolmode.drawteams = Csapatok rajzolása
toolmode.drawteams.description = Csapatok rajzolása blokkok helyett.
-#unused
+#Nem használt szövegek
toolmode.underliquid = Folyadékok alá
toolmode.underliquid.description = Padlók rajzolása a folyadékblokkok alá.
@@ -624,8 +629,8 @@ filter.option.percentile = Százalék
filter.option.code = Kód
filter.option.loop = Hurok
-locales.info = Itt adhatsz hozzá különböző nyelvi csomagokat a pályádhoz. A nyelvi csomagokban minden tulajdonságnak van egy neve és egy értéke. Ezeket a tulajdonságokat a világprocesszorok és a célkitűzések is használhatják a saját neveikkel. Támogatják a szövegformázást (a helyőrzőket a tényleges értékükkel helyettesítik).\n\n[cyan]Példa tulajdonság:\n[]name: [accent]időzítő[]\nvalue: [accent]Példa időzítő, hátralévő idő: {0}[]\n\n[cyan]Használat:\n[]Beállítás célkitűzés szövegeként: [accent]@időzítő\n\n[]Írd be egy világprocesszorba:\n[accent]localeprint "időzítő"\nformat time\n[gray](ahol az idő egy külön számított változó)
-locales.deletelocale = Biztos, hogy törölni akarod ezt a nyelvi csomagot?
+locales.info = Itt adhatsz hozzá különböző nyelvi csomagokat a pályádhoz. A nyelvi csomagokban minden tulajdonságnak van egy neve és egy értéke. Ezeket a tulajdonságokat a világprocesszorok és a pálya célkitűzései is használhatják a saját neveikkel. Támogatják a szövegformázást (a helyőrzőket a tényleges értékükkel helyettesítik).\n\n[cyan]Példa tulajdonság:\n[]name: [accent]időzítő[]\nvalue: [accent]Példa időzítő, hátralévő idő: {0}[]\n\n[cyan]Használat:\n[]Beállítás a pálya célkitűzésének szövegeként: [accent]@időzítő\n\n[]Írd be egy világprocesszorba:\n[accent]localeprint „időzítő”\nformat time\n[gray](ahol az idő egy külön számított változó)
+locales.deletelocale = Biztosan törölni akarod ezt a nyelvi csomagot?
locales.applytoall = Változások alkalmazása az összes nyelvi csomagra
locales.addtoother = Hozzáadás más nyelvi csomagokhoz
locales.rollback = Visszaállítás az utoljára elfogadottra
@@ -673,7 +678,6 @@ requirement.capture = Foglald el a(z) {0} szektort
requirement.onplanet = Szektor elfoglalása a(z) {0} bolygón
requirement.onsector = Landolj a(z) {0} szektorban
launch.text = Kilövés
-research.multiplayer = Csak a kiszolgáló fedezhet fel nyersanyagokat.
map.multiplayer = Csak a kiszolgáló tekintheti meg a szektorokat.
uncover = Felfedés
configure = Rakomány szerkesztése
@@ -717,9 +721,9 @@ objective.enemyescelating = [accent]Az ellenséges gyártás fokozódik: [lightg
objective.enemyairunits = [accent]Az ellenséges légi egységek gyártása elkezdődik: [lightgray]{0}[] mp múlva
objective.destroycore = [accent]Semmisítsd meg az ellenséges támaszpontot
objective.command = [accent]Irányítsd az egységeket
-objective.nuclearlaunch = [accent]⚠ Nukleáris kilövés észlelve: [lightgray]{0}
+objective.nuclearlaunch = [accent]⚠ Rakétakilövés észlelve: [lightgray]{0}
-announce.nuclearstrike = [red]⚠ BEÉRKEZŐ NUKLEÁRIS CSAPÁS ⚠\n[lightgray]Azonnal építs tartalék támaszpontokat!
+announce.nuclearstrike = [red]⚠ BEÉRKEZŐ RAKÉTACSAPÁS ⚠\n[lightgray]Azonnal építs tartalék támaszpontokat!
loadout = Rakomány
resources = Nyersanyagok
@@ -727,12 +731,12 @@ resources.max = Maximum
bannedblocks = Tiltott épületek
objectives = Feladatok
bannedunits = Tiltott egységek
-bannedunits.whitelist = Tiltott egységek fehérlistára
-bannedblocks.whitelist = Tiltott blokkok fehérlistára
+bannedunits.whitelist = Tiltott egységek engedélyezése
+bannedblocks.whitelist = Tiltott épületek engedélyezése
addall = Összes hozzáadása
launch.from = Kilövés a(z) [accent]{0} szektorból
launch.capacity = Nyersanyag-kapacitás a kilövéskor: [accent]{0}
-launch.destination = Úticél: {0}
+launch.destination = Úti cél: {0}
configure.invalid = A mennyiségnek 0 és {0} között kell lennie.
add = Hozzáadás...
guardian = Őrző
@@ -740,13 +744,14 @@ guardian = Őrző
connectfail = [scarlet]Kapcsolódási hiba:\n\n[accent]{0}
error.unreachable = A kiszolgálót nem lehet elérni.\nBiztosan jól írtad be a címet?
error.invalidaddress = Érvénytelen cím.
-error.timedout = Időtúllépés!\nGyőződj meg róla, hogy a porttovábbítás be van kapcsolva a kiszolgálógépen, és a cím helyes!
-error.mismatch = Csomaghiba:\nLehetséges kliens- vagy kiszolgálóverzió-eltérés.\nGyőződj meg róla, hogy te és a kiszolgáló is a Mindustry legfrissebb verzióját használjátok!
+error.timedout = Időtúllépés!\nGyőződj meg arról, hogy a porttovábbítás be van kapcsolva a kiszolgálógépen, és a cím helyes!
+error.mismatch = Csomaghiba:\nLehetséges kliens- vagy kiszolgálóverzió-eltérés.\nGyőződj meg arról, hogy te és a kiszolgáló is a Mindustry legfrissebb verzióját használjátok!
error.alreadyconnected = Már kapcsolódva vagy.
error.mapnotfound = A pályafájl nem található!
error.io = Internet I/O hiba.
error.any = Ismeretlen hálózati hiba.
error.bloom = A bloom hatás előkészítése nem sikerült.\nElőfordulhat, hogy az eszköz nem támogatja.
+error.moddex = A Mindustry nem tudja betölteni ezt a modot.\nAz eszközöd blokkolja a Java modok importálását az Android legújabb változásai miatt.\nNincs ismert megoldás erre a problémára.
weather.rain.name = Eső
weather.snowing.name = Hóesés
@@ -755,7 +760,7 @@ weather.sporestorm.name = Spóravihar
weather.fog.name = Köd
campaign.playtime = \uf129 [lightgray]Játékidő a szektorban: {0}
-campaign.complete = [accent]Gratulálunk.\n\nAz ellenség legyőzve a(z) {0} bolygón.\n[lightgray]Az utolsó szektor meghódítása megtörtént.
+campaign.complete = [accent]Gratulálunk!\n\nLegyőzted az ellenséget a(z) {0} bolygón.\n[lightgray]Meghódítottad az utolsó szektor is.
sectorlist = Szektorok
sectorlist.attacked = {0} támadás alatt
@@ -780,7 +785,7 @@ sectors.underattack.nodamage = [scarlet]Nincs meghódítva
sectors.survives = [accent]Túlél {0} hullámot
sectors.go = Visszatérés
sector.abandon = Elhagyás
-sector.abandon.confirm = Ennek a szektornak a támaszpontjai önmegsemmisítésre kerülnek.\nFolytatod?
+sector.abandon.confirm = Ebben a szektorban minden támaszpontod megsemmisül.\nBiztosan feladod ezt a szektort?
sector.curcapture = A szektor elfoglalva
sector.curlost = A szektor elveszett
sector.missingresources = [scarlet]Nincs elég nyersanyag
@@ -799,6 +804,12 @@ threat.high = Magas
threat.extreme = Extrém
threat.eradication = Irtózatos
+difficulty.casual = Laza
+difficulty.easy = Könnyű
+difficulty.normal = Normál
+difficulty.hard = Nehéz
+difficulty.eradication = Irtózatos
+
planets = Bolygók
planet.serpulo.name = Serpulo
@@ -820,9 +831,19 @@ sector.fungalPass.name = Gombahágó
sector.biomassFacility.name = Biomassza szintetizáló létesítmény
sector.windsweptIslands.name = Szélfútta szigetek
sector.extractionOutpost.name = Kivonási helyőrség
+sector.facility32m.name = 32M-es létesítmény
+sector.taintedWoods.name = Szennyezett fák
+sector.infestedCanyons.name = Fertőzött kanyonok
sector.planetaryTerminal.name = Bolygó körüli kilövőállás
sector.coastline.name = Partvonal
-sector.navalFortress.name = Tengerészeti erőd
+sector.navalFortress.name = Haditengerészeti erőd
+sector.polarAerodrome.name = Sarkvidéki légikikötő
+sector.atolls.name = Atollok
+sector.testingGrounds.name = Gyakorlótér
+sector.seaPort.name = Tengeri kikötő
+sector.weatheredChannels.name = Viharvert csatornák
+sector.mycelialBastion.name = Micéliumbástya
+sector.frontier.name = Frontvidék
sector.groundZero.description = Az ideális helyszín, hogy ismét belekezdjünk. Alacsony ellenséges fenyegetés. Kevés nyersanyag.\nGyűjts annyi rezet és ólmot, amennyit csak tudsz.\nHaladj tovább.
sector.frozenForest.description = Még itt, a hegyekhez közel is elterjedtek a spórák. A fagypont alatti hőmérséklet nem tudja örökké fogva tartani őket.\n\nFedezd fel az elektromosság erejét! Építs égetőerőműveket! Tanuld meg a foltozók használatát!
@@ -831,7 +852,7 @@ sector.craters.description = Víz gyűlt össze ebben a kráterben, amely régi
sector.ruinousShores.description = A pusztaság mögött a partvonal húzódik. Valaha ezen a helyen egy partvédelmi rendszer állt. Nem sok minden maradt belőle. Csak a legalapvetőbb védelmi szerkezetek maradtak érintetlenül, minden más csak törmelék lett.\nFolytasd a terjeszkedést! Fedezd fel újra a technológiát!
sector.stainedMountains.description = Mélyebben a szárazföldön fekszenek a hegyek, a spóráktól még érintetlenül.\nTermeld ki a bőséges titán készleteket a körzetben. Tanuld meg felhasználni!.\n\nAz ellenség itt nagyobb létszámban van jelen. Ne hagyj nekik időt, hogy a legerősebb egységeiket hadba állíthassák!
sector.overgrowth.description = Ez a terület közelebb esik a spórák forrásához, a spórák már kinőtték.\nAz ellenség egy helyőrséget létesített itt. Építs Mace egységeket! Pusztítsd el a bázist!
-sector.tarFields.description = Egy olajtermelő övezet peremvidéke a hegyek és a sivatag között. Egy azon kevés szektorok közül, ahol még hasznosítható kátránykészletek találhatóak.\nBár a terület elhagyatott, veszélyes ellenséges erők fészkelnek a közelben. Ne becsüld alá őket!\n\n[lightgray]Fedezd fel az olajfeldolgozási lehetőségeket, ha tudod!
+sector.tarFields.description = Egy olajtermelő övezet peremvidéke a hegyek és a sivatag között. Egy azon kevés szektorok közül, ahol még hasznosítható kátránykészletek találhatók.\nBár a terület elhagyatott, veszélyes ellenséges erők fészkelnek a közelben. Ne becsüld alá őket!\n\n[lightgray]Fedezd fel az olajfeldolgozási lehetőségeket, ha tudod!
sector.desolateRift.description = Egy extrém veszélyes zóna. Nyersanyagokban gazdag, de szűkös a hely. Magas a kockázat. Építs szárazföldi és légvédelmet, amint csak tudsz. Ne tévesszen meg a hosszú szünet az ellenség támadásai között.
sector.nuclearComplex.description = Egy néhai tóriumkitermelő és feldolgozó létesítmény, romokban.\n[lightgray]Fedezd fel a tóriumot és a sokrétű felhasználását!\n\nAz ellenség nagy létszámban van jelen, és folyamatosan megfigyelés alatt tartják a környéket.
sector.fungalPass.description = Átmeneti terület a magas hegyek és a mélyebben fekvő, spórák uralta lapály között. Egy kisebb ellenséges megfigyelő állomás található itt.\nSemmisítsd meg!\nHasználj Dagger és Crawler egységeket! Pusztítsd el a két támaszpontot!
@@ -839,9 +860,23 @@ sector.biomassFacility.description = A spórák származási helye. Ebben a lét
sector.windsweptIslands.description = Távolabb, a partvonalon túl fekszik ez az elszigetelt szigetcsoport. A feljegyzések szerint egykor [accent]műanyagot[] gyártottak itt.\n\nVerd vissza az ellenség vízi egységeit! Állíts fel egy bázist a szigeteken! Fedezd fel az itt talált gyárakat!
sector.extractionOutpost.description = Egy távoli ellenséges támaszpont, amelyet az ellenség azért épített, hogy nyersanyagokat juttasson el más szektorokba.\n\nA szektorok közötti szállítási technológia elengedhetetlen a további hódításhoz. Pusztítsd el a bázist. Fejleszd ki a kilövőállást.
sector.impact0078.description = Itt nyugszanak az ebbe a csillagrendszerbe érkező első csillagközi űrhajó maradványai.\n\nMents ki a romok alól mindent amit csak tudsz. Fedezd fel az épen maradt technológiákat.
-sector.planetaryTerminal.description = A végső célpont.\n\nEzen a vízparti bázison egy olyan építmény található, amely képes támaszpontokat kilőni a közeli bolygókra. Rendkívül jól őrzik.\n\nKészíts vízi egységeket! Ártalmatlanítsd az ellenséget, amilyen gyorsan csak tudod! Találd meg a kilövőszerkezetet!
+sector.planetaryTerminal.description = A végső célpont.\n\nEzen a vízparti bázison egy olyan építmény található, amely képes támaszpontokat kilőni a közeli bolygókra. Rendkívül jól őrzik.\n\nGyárts vízi egységeket! Ártalmatlanítsd az ellenséget, amilyen gyorsan csak tudod! Találd meg a kilövőszerkezetet!
sector.coastline.description = Ezen a helyen egy haditengerészeti egység technológiájának maradványait azonosították. Verd vissza az ellenséges támadásokat, foglald el ezt a szektort, és szerezd meg a technológiát.
sector.navalFortress.description = Az ellenség bázist létesített egy távoli, természetes erődítményes szigeten. Pusztítsd el ezt az előőrsöt. Szerezd meg a fejlett hadihajó-technológiájukat, és fejleszd ki te is.
+sector.cruxscape.name = Zord vidék
+sector.geothermalStronghold.name = Geotermikus erődítmény
+
+#A következő sorokat ne fordítsd le!
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = A kezdet
sector.aegis.name = Égisz
@@ -862,20 +897,20 @@ sector.karst.name = Karszt
sector.origin.name = Eredet
sector.onset.description = Kezdd meg az Erekir meghódítását. Gyűjts nyersanyagokat, állíts elő egységeket, és kezdd el a technológiai fejlesztéseket.
-sector.aegis.description = Ez a szektor volfrám-lelőhelyeket tartalmaz.\nFejleszd ki az [accent]Ütvefúrót[], hogy ki tudd bányászni ezt a nyersanyagot, és pusztítsd el az ellenséges bázist a szektorban.
-sector.lake.description = Az ebben a szektorban lévő salakos tó nagymértékben korlátozza a használható egységeket. A lebegőegységek használata az egyetlen lehetőség.\nFejleszd ki a [accent]Repülőgépgyártót[], és állíts elő egy [accent]Elude[] egységet, amilyen hamar csak lehet.
-sector.intersect.description = A letapogatások arra utalnak, hogy ezt a szektort a leszállás után hamarosan több oldalról is megtámadják.\nÁllítsd fel gyorsan a védelmedet, és terjeszkedj minél hamarabb.\n[accent]Mech[] egységekre lesz szükség a terület zord terepviszonyai miatt.
-sector.atlas.description = Ez a szektor változatos terepet tartalmaz, és az ütőképes támadáshoz többféle egységre lesz szükség.\nAz itt felfedezett ellenséges bázisok némelyikén való átjutáshoz is továbbfejlesztett egységekre lehet szükség.\nFejleszd ki az [accent]Elektrolizátort[] és a [accent]Tankújratervezőt[].
+sector.aegis.description = Ez a szektor volfrám-lelőhelyeket tartalmaz.\nFejleszd ki az [accent]ütvefúrót[], hogy ki tudd bányászni ezt a nyersanyagot, és pusztítsd el az ellenséges bázist a szektorban.
+sector.lake.description = Az ebben a szektorban lévő salakos tó nagymértékben korlátozza a használható egységeket. A lebegőegységek használata az egyetlen lehetőség.\nFejleszd ki a [accent]repülőgépgyártót[], és állíts elő egy [accent]Elude[] egységet, amilyen hamar csak lehet.
+sector.intersect.description = A letapogatások arra utalnak, hogy ezt a szektort a leszállás után hamarosan több oldalról is megtámadják.\nÁllítsd fel gyorsan a védelmedet, és terjeszkedj minél gyorsabban.\n[accent]Mech[] egységekre lesz szükség a terület zord terepviszonyai miatt.
+sector.atlas.description = Ez a szektor változatos tereppel rendelkezik, ezért az ütőképes támadáshoz többféle egységre lesz szükség.\nAz itt felfedezett ellenséges bázisok némelyikén való átjutáshoz is továbbfejlesztett egységekre lehet szükség.\nFejleszd ki az [accent]elektrolizátort[] és a [accent]Tankújratervezőt[].
sector.split.description = A minimális ellenséges jelenlét miatt ez a szektor tökéletes az új nyersanyagszállító technológiák tesztelésére.
sector.basin.description = Jelentős ellenséges jelenlét lett érzékelve ebben a szektorban.\nÉpíts gyorsan egységeket, és foglald el az ellenséges támaszpontokat, hogy megvethesd a lábad.
-sector.marsh.description = Ebben a szektorban rengeteg arkicit található, de kevés a kürtő.\nÉpíts [accent]Kémiai égetőkamrát[] az áramfejlesztéshez.
+sector.marsh.description = Ebben a szektorban rengeteg arkicit található, de kevés a kürtő.\nÉpíts [accent]kémiai égetőkamrát[] az áramfejlesztéshez.
sector.peaks.description = A hegyvidéki terep ebben a szektorban a legtöbb egységet használhatatlanná teszi. Légi egységekre lesz szükség.\nVigyázz az ellenséges légvédelmi létesítményekkel. Lehetséges, hogy az ilyen létesítményeket hatástalanítani lehet a támogató épületeik célba vételével.
sector.ravine.description = A szektorban nem észlelhető ellenséges támaszpont, de ez egy fontos szállítási útvonal az ellenség számára, így változatos ellenséges erőkkel kell számolni.\nTermelj [accent]elektrometált[]. Építs [accent]Afflict[] lövegtornyokat.
-sector.caldera-erekir.description = Ebben a szektorban a feltárható nyersanyagok több szigeten szétszóródva találhatóak.\nFejleszd ki és helyezd üzembe a drónalapú szállítmányozást.
+sector.caldera-erekir.description = Ebben a szektorban a feltárható nyersanyagok több szigeten szétszóródva találhatók.\nFejleszd ki és helyezd üzembe a drónalapú szállítmányozást.
sector.stronghold.description = A nagy ellenséges tábor ebben a szektorban jelentős mennyiségű [accent]tóriumot[] őriz.\nHasználd magasabb szintű egységek és lövegtornyok fejlesztésére.
-sector.crevice.description = Ebben a szektorban az ellenség kegyetlen támadóerőket fog mozgósítani, hogy kiiktassa a bázisodat.\nA [accent]karbid[] és a [accent]Pirolízis-erőmű[] kifejlesztése nélkülözhetetlen lehet a túléléshez.
-sector.siege.description = Ebben a szektorban két párhuzamos kanyon található, amelyek két irányból érkező támadásokat tesznek lehetővé.\nFejleszd ki a [accent]diciánt[], hogy még erősebb tankegységeket hozhass létre.\nVigyázat: ellenséges, nagy hatótávolságú rakéták észlelve. A rakéták a becsapódásuk előtt megsemmisíthetőek.
-sector.crossroads.description = Az ellenséges támaszpontok ebben a szektorban változó terepviszonyok között alakultak ki. Ahhoz, hogy alkalmazkodni tudj, fejlessz ki különböző egységeket.\nEzenkívül egyes bázisokat pajzsok védenek. Találd ki, hogyan táplálják őket.
+sector.crevice.description = Ebben a szektorban az ellenség kegyetlen támadóerőket fog mozgósítani, hogy kiiktassa a bázisodat.\nA [accent]karbid[] és a [accent]pirolízis-erőmű[] kifejlesztése nélkülözhetetlen lehet a túléléshez.
+sector.siege.description = Ebben a szektorban két párhuzamos kanyon található, amelyek két irányból érkező támadásokat tesznek lehetővé.\nFejleszd ki a [accent]diciánt[], hogy még erősebb tankegységeket hozhass létre.\nVigyázat: ellenséges, nagy hatótávolságú rakéták észlelve. A rakéták a becsapódásuk előtt megsemmisíthetők.
+sector.crossroads.description = Az ellenséges támaszpontok ebben a szektorban változó terepviszonyok között alakultak ki. Ahhoz, hogy alkalmazkodni tudj, fejlessz ki különböző egységeket.\nEzenkívül egyes bázisokat erőpajzsok védenek. Találd ki, hogyan táplálják őket.
sector.karst.description = Ez a szektor gazdag a nyersanyagokban, de amint egy új támaszpont leszáll, az ellenség megtámadja azt.\nHasználd ki a nyersanyagokat és fedezd fel a [accent]tóritkvarcot[].
sector.origin.description = Az utolsó szektor, jelentős ellenséges jelenléttel.\nNem valószínű, hogy maradtak további fejlesztési lehetőségek – koncentrálj az ellenséges támaszpontok elpusztítására.
@@ -905,7 +940,7 @@ settings.game = Játék
settings.sound = Hangok
settings.graphics = Grafika
settings.cleardata = Játékadatok törlése...
-settings.clear.confirm = Biztosan törlöd ezeket az adatokat?\nA műveletet nem lehet visszavonni!
+settings.clear.confirm = Biztosan törlöd ezeket az adatokat?\nEzt a műveletet nem lehet visszavonni!
settings.clearall.confirm = [scarlet]FIGYELEM![]\nEz törli az összes adatot, beleértve a mentéseket, pályákat, felfedezéseket és a billentyűbeállításokat.\nAz „OK” gomb megnyomásával a játék minden adatot töröl, és automatikusan kilép.
settings.clearsaves.confirm = Biztosan törlöd az összes mentést?
settings.clearsaves = Mentések törlése
@@ -951,7 +986,7 @@ stat.powerrange = Hatótávolság
stat.linkrange = Kapcsolat hatótávolsága
stat.instructions = Utasítások
stat.powerconnections = Max. kapcsolatok
-stat.poweruse = Áramhasználat
+stat.poweruse = Áramfogyasztás
stat.powerdamage = Áram/sebzés
stat.itemcapacity = Nyersanyag-kapacitás
stat.memorycapacity = Memóriakapacitás
@@ -965,7 +1000,7 @@ stat.moduletier = Modul szintje
stat.unittype = Egység típusa
stat.speedincrease = Gyorsítás
stat.range = Hatótávolság
-stat.drilltier = Kitermelhetőek
+stat.drilltier = Kitermelhetők
stat.drillspeed = Alap termelési sebesség
stat.boosteffect = Erősítés hatása
stat.maxunits = Max. aktív egységek
@@ -978,7 +1013,7 @@ stat.inaccuracy = Pontatlanság
stat.shots = Lövések
stat.reload = Tüzelési sebesség
stat.ammo = Lőszer
-stat.shieldhealth = Pajzs életereje
+stat.shieldhealth = Erőpajzs életereje
stat.cooldowntime = Újratöltés időtartama
stat.explosiveness = Robbanékonyság
stat.basedeflectchance = Alap hárítási esély
@@ -994,7 +1029,7 @@ stat.speed = Sebesség
stat.buildspeed = Építési sebesség
stat.minespeed = Termelési sebesség
stat.minetier = Termelési szint
-stat.payloadcapacity = Rakománykapacitás
+stat.payloadcapacity = Raktérkapacitás
stat.abilities = Képességek
stat.canboost = Erősíthető
stat.flying = Repül
@@ -1009,22 +1044,22 @@ stat.reactive = Reakciók
stat.immunities = Immunitások
stat.healing = Gyógyulás
-ability.forcefield = Erőtér
-ability.forcefield.description = Erőteret vetít ki, mely elnyeli a lövedékeket
+ability.forcefield = Erőpajzs
+ability.forcefield.description = Olyan erőpajzsot vetít ki, amely elnyeli a lövedékeket
ability.repairfield = Javító mező
ability.repairfield.description = Megjavítja a közeli egységeket
ability.statusfield = Állapotmező
ability.statusfield.description = Állapothatást alkalmaz a közeli egységekre
ability.unitspawn = Gyár
ability.unitspawn.description = Egységeket gyárt
-ability.shieldregenfield = Pajzsregeneráló mező
-ability.shieldregenfield.description = Regenerálja a közeli egységek pajzsát
+ability.shieldregenfield = Erőpajzs-regeneráló mező
+ability.shieldregenfield.description = Regenerálja a közeli egységek erőpajzsát
ability.movelightning = Villámcsapás
ability.movelightning.description = Mozgás közben villámokat bocsát ki
ability.armorplate = Páncéllemez
ability.armorplate.description = Csökkenti a kapott sebzést lövés közben
-ability.shieldarc = Pajzs ív
-ability.shieldarc.description = Erőteret vetít ki egy ívben, mely elnyeli a lövedékeket
+ability.shieldarc = Erőpajzs-ív
+ability.shieldarc.description = Olyan erőpajzsot vetít ki egy ívben, amely elnyeli a lövedékeket
ability.suppressionfield = Javítás elnyomása
ability.suppressionfield.description = Leállítja a közeli javítóépületeket
ability.energyfield = Energiamező
@@ -1041,23 +1076,24 @@ ability.liquidexplode.description = Megsemmisülésekor folyadék ömlik ki bel
ability.stat.firingrate = [stat]{0}/mp[lightgray] tüzelési sebesség
ability.stat.regen = [stat]{0}[lightgray] életerő/mp
-ability.stat.shield = [stat]{0}[lightgray] pajzs
+ability.stat.pulseregen = [stat]{0}[lightgray] életerő/impulzus
+ability.stat.shield = [stat]{0}[lightgray] maximális pajzs
ability.stat.repairspeed = [stat]{0}/mp[lightgray] javítási sebesség
ability.stat.slurpheal = [stat]{0}[lightgray] életerő/folyadékegység
ability.stat.cooldown = [stat]{0} mp[lightgray] újratöltődés
ability.stat.maxtargets = [stat]{0}[lightgray] max. célpont
ability.stat.sametypehealmultiplier = [stat]{0}%[lightgray] javítási mennyiség (azonos típusnál)
ability.stat.damagereduction = [stat]{0}%[lightgray] sebzéscsökkentés
-ability.stat.minspeed = [stat]{0} csempe/mp[lightgray] min. sebesség
+ability.stat.minspeed = [stat]{0} mező/mp[lightgray] min. sebesség
ability.stat.duration = [stat]{0} mp[lightgray] időtartam
ability.stat.buildtime = [stat]{0} mp[lightgray] építési idő
-bar.onlycoredeposit = Csak a támaszpont elhelyezése megengedett
+bar.onlycoredeposit = Nyersanyagtárolás csak a támaszpontban.
bar.drilltierreq = Erősebb fúró szükséges
bar.noresources = Hiányzó nyersanyagok
bar.corereq = Támaszpont szükséges
-bar.corefloor = Támaszpont zónacsempe szükséges
-bar.cargounitcap = A rakományszállító egység teljes kapacitáson
+bar.corefloor = Támaszpont-zónamező szükséges
+bar.cargounitcap = Az egység raktere megtelt
bar.drillspeed = Termelés: {0}/mp
bar.pumpspeed = Termelés: {0}/mp
bar.efficiency = Hatásfok: {0}%
@@ -1086,12 +1122,12 @@ bar.strength = [stat]{0}[lightgray]x erő
units.processorcontrol = [lightgray]Processzorvezérelt
bullet.damage = [stat]{0}[lightgray] sebzés
-bullet.splashdamage = [stat]{0}[lightgray] területi sebzés ~[stat] {1}[lightgray] csempe
+bullet.splashdamage = [stat]{0}[lightgray] területi sebzés ~[stat] {1}[lightgray] mező
bullet.incendiary = [stat]gyújtó
bullet.homing = [stat]nyomkövető
bullet.armorpierce = [stat]páncéltörő
bullet.maxdamagefraction = [stat]{0}%[lightgray] sebzési határérték
-bullet.suppression = [stat]{0} mp[lightgray] javításelnyomás ~[stat]{1}[lightgray] csempe
+bullet.suppression = [stat]{0} mp[lightgray] javításelnyomás ~[stat]{1}[lightgray] mező
bullet.interval = [stat]{0}/mp[lightgray] gyakoriságú lövedékek:
bullet.frags = [stat]{0}[lightgray]db repeszlövedék:
bullet.lightning = [stat]{0}[lightgray]db villámcsapás ~[stat]{1}[lightgray] sebzés
@@ -1103,12 +1139,14 @@ bullet.healpercent = [stat]{0}%[lightgray] javítás
bullet.healamount = [stat]{0}[lightgray] közvetlen javítás
bullet.multiplier = [stat]{0}[lightgray] lőszer/nyersanyag
bullet.reload = [stat]{0}%[lightgray] tüzelési sebesség
-bullet.range = [stat]{0}[lightgray] csempés hatótávolság
+bullet.range = [stat]{0}[lightgray] mezős hatótávolság
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blokk
unit.blockssquared = blokk²
unit.powersecond = áramegység/mp
-unit.tilessecond = csempe/mp
+unit.tilessecond = mező/mp
unit.liquidsecond = folyadékegység/mp
unit.itemssecond = nyersanyag/mp
unit.liquidunits = folyadékegység
@@ -1121,7 +1159,7 @@ unit.persecond = /mp
unit.perminute = /perc
unit.timesspeed = x sebesség
unit.percent = %
-unit.shieldhealth = pajzs életereje
+unit.shieldhealth = erőpajzs életereje
unit.items = nyersanyag
unit.thousands = k
unit.millions = mil
@@ -1137,7 +1175,7 @@ category.crafting = Bemenet/kimenet
category.function = Funkció
category.optional = Lehetséges fejlesztések
setting.alwaysmusic.name = Folyamatos zenelejátszás
-setting.alwaysmusic.description = Ha engedélyezve van, akkor a zene folyamatosan szól a játékban.\nHa ki van kapcsolva, akkor csak véletlenszerű időközönként szólal meg.
+setting.alwaysmusic.description = Amikor engedélyezve van, akkor a zene folyamatosan szól a játékban.\nHa ki van kapcsolva, akkor csak véletlenszerű időközönként szólal meg.
setting.skipcoreanimation.name = Támaszpont kilövés/leszállás animáció kihagyása
setting.landscape.name = Fekvő mód zárolása
setting.shadows.name = Árnyékok
@@ -1152,7 +1190,7 @@ setting.commandmodehold.name = Lenyomva tartás a parancs módhoz
setting.distinctcontrolgroups.name = Egységenként legfeljebb egy vezérlőcsoport
setting.modcrashdisable.name = Modok letiltása indításkori összeomláskor
setting.animatedwater.name = Animált felületek
-setting.animatedshields.name = Animált pajzsok
+setting.animatedshields.name = Animált erőpajzsok
setting.playerindicators.name = Játékosjelzők
setting.indicators.name = Ellenségjelzők
setting.autotarget.name = Automatikus célzás
@@ -1162,14 +1200,8 @@ setting.fpscap.name = FPS-korlát
setting.fpscap.none = Nincs
setting.fpscap.text = {0} FPS
setting.uiscale.name = Felület méretezése
-setting.uiscale.description = A módosítások alkalmazásához újraindítás szükséges.
+setting.uiscale.description = A módosítások érvénybe lépéséhez újraindítás szükséges.
setting.swapdiagonal.name = Mindig átlós elhelyezés
-setting.difficulty.training = Kiképzés
-setting.difficulty.easy = Könnyű
-setting.difficulty.normal = Normál
-setting.difficulty.hard = Nehéz
-setting.difficulty.insane = Őrült
-setting.difficulty.name = Nehézség:
setting.screenshake.name = Képernyő rázkódása
setting.bloomintensity.name = Bloom intenzitása
setting.bloomblur.name = Bloom elmosása
@@ -1209,14 +1241,14 @@ setting.chatopacity.name = Csevegő átlátszatlansága
setting.lasersopacity.name = Villanyvezeték átlátszatlansága
setting.bridgeopacity.name = Híd átlátszatlansága
setting.playerchat.name = Játékosok csevegőbuborékainak megjelenítése
-setting.showweather.name = Időjárásgrafika megjelenítése
+setting.showweather.name = Időjárás-grafika megjelenítése
setting.hidedisplays.name = Logikai kijelzők elrejtése
setting.macnotch.name = A felület igazítása a kijelző bevágásához
setting.macnotch.description = A változtatások érvénybe lépéséhez újraindítás szükséges
steam.friendsonly = Csak barátok
steam.friendsonly.tooltip = Csak a Steam-barátok tudnak kapcsolódni a játékodhoz.\nHa nem jelölöd be ezt a négyzetet, a játékod nyilvános lesz – bárki kapcsolódhat hozzá.
public.beta = Ne feledd, hogy a játék béta verziójában nem tudsz nyilvános szobát nyitni.
-uiscale.reset = A felület mérete megváltozott.\nAz „OK” gombbal megerősítheted ezt a méretet.\n[scarlet]Visszavonás és kilépés [accent] {0}[] másodperc múlva...
+uiscale.reset = A felület mérete megváltozott.\nAz „OK” gombbal megerősítheted ezt a méretet.\n[scarlet]Automatikus visszavonás és kilépés [accent] {0}[] másodperc múlva...
uiscale.cancel = Mégse és kilépés
setting.bloom.name = Bloom
keybind.title = Billentyűk átállítása
@@ -1261,6 +1293,7 @@ keybind.unit_command_load_units.name = Egységparancs: egységek berakodása
keybind.unit_command_load_blocks.name = Egységparancs: blokkok berakodása
keybind.unit_command_unload_payload.name = Egységparancs: kirakodás
keybind.unit_command_enter_payload.name = Egységparancs: berakodás
+keybind.unit_command_loop_payload.name = Egységparancs: folyamatos egységelszállítás
keybind.rebuild_select.name = Régió újraépítése
keybind.schematic_select.name = Terület kijelölése
@@ -1290,7 +1323,7 @@ keybind.pick.name = Blokk kiválasztása
keybind.break_block.name = Blokk törlése
keybind.select_all_units.name = Összes egység kijelölése
keybind.select_all_unit_factories.name = Összes egységgyár kijelölése
-keybind.deselect.name = Blokkkijelölés törlése
+keybind.deselect.name = Blokk-kijelölés törlése
keybind.pickupCargo.name = Rakomány felvétele
keybind.dropCargo.name = Rakomány lerakása
keybind.shoot.name = Lövés
@@ -1327,7 +1360,7 @@ mode.attack.description = Pusztítsd el az ellenség bázisát. \n[gray]Piros t
mode.custom = Egyéni szabályok
rules.invaliddata = Érvénytelen adatok vannak a vágólapon.
-rules.hidebannedblocks = Tiltott blokkok elrejtése
+rules.hidebannedblocks = Tiltott épületek elrejtése
rules.infiniteresources = Végtelen nyersanyagforrás
rules.onlydepositcore = Csak a támaszpontok elhelyezése engedélyezett
rules.derelictrepair = Az elhagyatott épületek javításának engedélyezése
@@ -1338,13 +1371,17 @@ rules.schematic = Vázlatok engedélyezése
rules.wavetimer = Hullámok időzítése
rules.wavesending = Hullámok küldése
rules.allowedit = Szabályok szerkesztésének engedélyezése
-rules.allowedit.info = Ha engedélyezve van, a játékos szerkesztheti a szabályokat a játékban a Szünet menü bal alsó sarkában található gomb segítségével.
+rules.allowedit.info = Amikor engedélyezve van, akkor a játékos szerkesztheti a szabályokat a játékban a „Szünet” menü bal alsó sarkában található gomb segítségével.
+rules.alloweditworldprocessors = Világprocesszorok szerkesztésének engedélyezése
+rules.alloweditworldprocessors.info = Amikor engedélyezve van, a világlogikai blokkok a szerkesztőn kívül is elhelyezhetők és szerkeszthetők.
rules.waves = Hullámok
rules.airUseSpawns = A légi egységek használjanak kezdőpontokat
rules.attack = Támadási mód
rules.buildai = Bázisépítő MI
rules.buildaitier = Építő MI szintje
rules.rtsai = RTS MI [red](WIP)
+rules.rtsai.campaign = RTS Támadó MI
+rules.rtsai.campaign.info = A „támadó” pályákon (ahol az ellenség is rendelkezik támaszponttal) az MI által irányított\negységek csoportosulnak, és intelligensebb módon támadják a játékosok bázisait.
rules.rtsminsquadsize = Minimális osztagméret
rules.rtsmaxsquadsize = Maximális osztagméret
rules.rtsminattackweight = Minimális támadási súly
@@ -1365,16 +1402,16 @@ rules.unitcapvariable = A támaszpontok befolyásolják a gyártható egységek
rules.unitpayloadsexplode = A szállított rakományok az egységgel együtt felrobbannak
rules.unitcap = Alap egységdarabszám
rules.limitarea = Játékterület korlátozása
-rules.enemycorebuildradius = Ellenséges támaszpont körüli tiltott zóna sugara:[lightgray] (csempe)
+rules.enemycorebuildradius = Ellenséges támaszpont körüli tiltott zóna sugara:[lightgray] (mező)
rules.wavespacing = A hullámok közötti szünetek ideje:[lightgray] (mp)
rules.initialwavespacing = Az első hullám előtti szünet ideje:[lightgray] (mp)
rules.buildcostmultiplier = Építési költség szorzója
rules.buildspeedmultiplier = Építési sebesség szorzója
rules.deconstructrefundmultiplier = Bontási visszatérítés szorzója
rules.waitForWaveToEnd = Az ellenség kivárja a korábbi hullám végét
-rules.wavelimit = A pálya az utolsó hullám után ér véget
-rules.dropzoneradius = A ledobási zóna sugara:[lightgray] (csempe)
-rules.unitammo = Az egységeknek lőszer kell [red](törölhető)
+rules.wavelimit = A pálya érjen véget ennyi hullám után
+rules.dropzoneradius = A ledobási zóna sugara:[lightgray] (mező)
+rules.unitammo = Az egységeknek lőszer kell [red](eltávolítható)
rules.enemyteam = Ellenséges csapat
rules.playerteam = Saját csapat
rules.title.waves = Hullámok
@@ -1386,7 +1423,10 @@ rules.title.environment = Környezet
rules.title.teams = Csapatok
rules.title.planet = Bolygó
rules.lighting = Világítás
-rules.fog = Köd
+rules.fog = A háború köde
+rules.invasions = Ellenséges szektorokból érkező inváziók
+rules.showspawns = Ellenséges kezdőpontok megjelenítése a minitérképen
+rules.randomwaveai = Kiszámíthatatlan ellenséges támadások (MI)
rules.fire = Tűz
rules.anyenv =
rules.explosions = Épület/egység robbanási sebzése
@@ -1396,7 +1436,8 @@ rules.weather.frequency = Gyakoriság:
rules.weather.always = Mindig
rules.weather.duration = Időtartam:
-rules.placerangecheck.info = Megakadályozza, hogy a játékosok lövegtornyokat helyezzenek el az ellenséges épületek közelében. Amikor megpróbálnak egy lövegtornyot elhelyezni, az építési távolság megnő, így a lövegtorony nem fogja elérni az ellenséget.
+rules.randomwaveai.info = A hullámokban érkező egységek a támaszpont vagy az áramfejlesztők\nközvetlen támadása helyett véletlenszerű építményeket vesznek célba.
+rules.placerangecheck.info = Megakadályozza, hogy a játékosok lövegtornyokat helyezzenek el az ellenséges épületek közelében.\nAmikor megpróbálnak egy lövegtornyot elhelyezni, az építési távolság megnő, így a lövegtorony nem fogja elérni az ellenséget.
rules.onlydepositcore.info = Megakadályozza, hogy az egységek nyersanyagokat helyezzenek el a támaszponton kívül más épületekbe.
content.item.name = Nyersanyagok
@@ -1540,9 +1581,11 @@ block.graphite-press.name = Grafitprés
block.multi-press.name = Grafitsajtoló
block.constructing = {0} [lightgray](építés alatt)
block.spawn.name = Ellenséges kezdőpont
-block.core-shard.name = Támaszpont: Szilánk
-block.core-foundation.name = Támaszpont: Alapítvány
-block.core-nucleus.name = Támaszpont: Atommag
+block.remove-wall.name = Fal eltávolítása
+block.remove-ore.name = Érc eltávolítása
+block.core-shard.name = Szilánk
+block.core-foundation.name = Alapítvány
+block.core-nucleus.name = Atommag
block.deep-water.name = Mély víz
block.shallow-water.name = Víz
block.tainted-water.name = Szennyezett víz
@@ -1623,12 +1666,12 @@ block.world-switch.name = Világkapcsoló
block.illuminator.name = Világítótest
block.overflow-gate.name = Túlcsorduló kapu
block.underflow-gate.name = Alulcsorduló kapu
-block.silicon-smelter.name = Szilícium kohó
+block.silicon-smelter.name = Szilíciumkohó
block.phase-weaver.name = Tóritkvarcképző
-block.pulverizer.name = Porlasztó
+block.pulverizer.name = Törmelékdaráló
block.cryofluid-mixer.name = Hűtőfolyadék-keverő
block.melter.name = Olvasztó
-block.incinerator.name = Törmelékégető
+block.incinerator.name = Égetőkamra
block.spore-press.name = Spóraprés
block.separator.name = Leválasztó
block.coal-centrifuge.name = Széncentrifuga
@@ -1645,7 +1688,7 @@ block.impact-reactor.name = Ütközéses erőmű
block.mechanical-drill.name = Mechanikus fúró
block.pneumatic-drill.name = Pneumatikus fúró
block.laser-drill.name = Lézerfúró
-block.water-extractor.name = Vízkinyerő
+block.water-extractor.name = Kútfúró torony
block.cultivator.name = Betakarító
block.conduit.name = Csővezeték
block.mechanical-pump.name = Mechanikus szivattyú
@@ -1669,7 +1712,7 @@ block.pyratite-mixer.name = Piratitkeverő
block.blast-mixer.name = Robbanóelegy-keverő
block.solar-panel.name = Napelem
block.solar-panel-large.name = Nagy napelem
-block.oil-extractor.name = Olajleválasztó
+block.oil-extractor.name = Olajfúró torony
block.repair-point.name = Javítási pont
block.repair-turret.name = Javítótorony
block.pulse-conduit.name = Impulzus-csővezeték
@@ -1677,7 +1720,7 @@ block.plated-conduit.name = Lemezelt csővezeték
block.phase-conduit.name = Tóritkvarc-csővezeték
block.liquid-router.name = Folyadékelosztó
block.liquid-tank.name = Folyadéktartály
-block.liquid-container.name = Folyadéktároló
+block.liquid-container.name = Folyadéktározó
block.liquid-junction.name = Csővezeték-átkötés
block.bridge-conduit.name = Csővezetékhíd
block.rotary-pump.name = Fogaskerekes szivattyú
@@ -1688,16 +1731,16 @@ block.impulse-pump.name = Impulzusszivattyú
block.thermal-generator.name = Hőerőmű
block.surge-smelter.name = Elektrometál-olvasztó
block.mender.name = Foltozó
-block.mend-projector.name = Foltozó projektor
+block.mend-projector.name = Foltozó-kivetítő
block.surge-wall.name = Elektrometálfal
block.surge-wall-large.name = Nagy elektrometálfal
block.cyclone.name = Cyclone
block.fuse.name = Fuse
block.shock-mine.name = Sokkoló taposóakna
block.overdrive-projector.name = Túlhajtó kivetítő
-block.force-projector.name = Erőkivetítő
+block.force-projector.name = Erőpajzs-kivetítő
block.arc.name = Arc
-block.rtg-generator.name = RTG erőmű
+block.rtg-generator.name = R. T. Generátor
block.spectre.name = Spectre
block.meltdown.name = Meltdown
block.foreshadow.name = Foreshadow
@@ -1724,10 +1767,10 @@ block.silicon-crucible.name = Szilíciumolvasztó
block.overdrive-dome.name = Túlhajtó búra
block.interplanetary-accelerator.name = Bolygóközi gyorsító
block.constructor.name = Építő
-block.constructor.description = Legfeljebb 2×2-es csempeméretű épületeket gyárt.
+block.constructor.description = Legfeljebb 2×2-es mezőméretű épületeket gyárt.
block.large-constructor.name = Nagy építő
-block.large-constructor.description = Akár 4×4-es csempeméretű épületeket is gyárt.
-block.deconstructor.name = Lebontó
+block.large-constructor.description = Akár 4×4-es mezőméretű épületeket is gyárt.
+block.deconstructor.name = Nagy lebontó
block.deconstructor.description = Lebontja az épületeket és az egységeket. Visszaadja az építési költség 100%-át.
block.payload-loader.name = Rakománycsomagoló
block.payload-loader.description = A folyadékokat és a nyersanyagokat blokkokba csomagolja.
@@ -1765,19 +1808,19 @@ block.bluemat.name = Kék padló
block.core-zone.name = Támaszpontzóna
block.regolith-wall.name = Regolitfal
block.yellow-stone-wall.name = Sárgakő-fal
-block.rhyolite-wall.name = Riolit fal
+block.rhyolite-wall.name = Riolitfal
block.carbon-wall.name = Szénfal
block.ferric-stone-wall.name = Vasaskő-fal
block.beryllic-stone-wall.name = Berilliumoskő-fal
block.arkyic-wall.name = Arkicites fal
-block.crystalline-stone-wall.name = Kristályos kőFal
+block.crystalline-stone-wall.name = Kristályos kőfal
block.red-ice-wall.name = Vörösjég-fal
block.red-stone-wall.name = Vöröskő-fal
block.red-diamond-wall.name = Vörösgyémánt-fal
block.redweed.name = Vörös fű
block.pur-bush.name = Lila bokor
block.yellowcoral.name = Sárga korall
-block.carbon-boulder.name = Szén szikla
+block.carbon-boulder.name = Szénszikla
block.ferric-boulder.name = Vasas szikla
block.beryllic-boulder.name = Berilliumos szikla
block.yellow-stone-boulder.name = Sárgakő-szikla
@@ -1788,10 +1831,10 @@ block.crystal-blocks.name = Kristályblokkok
block.crystal-orbs.name = Kristálygömbök
block.crystalline-boulder.name = Kristályos szikla
block.red-ice-boulder.name = Vörösjég-szikla
-block.rhyolite-boulder.name = Riolit szikla
+block.rhyolite-boulder.name = Riolitszikla
block.red-stone-boulder.name = Vöröskő-szikla
-block.graphitic-wall.name = Grafit fal
-block.silicon-arc-furnace.name = Szilícium ívkemence
+block.graphitic-wall.name = Grafitfal
+block.silicon-arc-furnace.name = Szilícium-ívkemence
block.electrolyzer.name = Elektrolizátor
block.atmospheric-concentrator.name = Atmoszferikus sűrítő
block.oxidation-chamber.name = Oxidációs kamra
@@ -1799,8 +1842,9 @@ block.electric-heater.name = Elektromos fűtőtest
block.slag-heater.name = Salakos fűtőtest
block.phase-heater.name = Tóritkvarcos fűtőtest
block.heat-redirector.name = Hőelvezető
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Hőelosztó
-block.slag-incinerator.name = Salakégető kemence
+block.slag-incinerator.name = Salakos égetőkamra
block.carbide-crucible.name = Karbidolvasztó
block.slag-centrifuge.name = Salakcentrifuga
block.surge-crucible.name = Elektrometál-olvasztó
@@ -1821,11 +1865,11 @@ block.radar.name = Radar
block.build-tower.name = Építőtorony
block.regen-projector.name = Regeneráló kivetítő
block.shockwave-tower.name = Sokkhullámtorony
-block.shield-projector.name = Pajzskivetítő
-block.large-shield-projector.name = Nagy pajzskivetítő
+block.shield-projector.name = Erőpajzs-kivetítő
+block.large-shield-projector.name = Nagy erőpajzs-kivetítő
block.armored-duct.name = Páncélozott szállítószalag
-block.overflow-duct.name = Túlcsorduló szállítószalag
-block.underflow-duct.name = Alulcsorduló szállítószalag
+block.overflow-duct.name = Túlcsorduló kapu
+block.underflow-duct.name = Alulcsorduló kapu
block.duct-unloader.name = Szállítószalag-kirakodó
block.surge-conveyor.name = Elektrometál-szállítószalag
block.surge-router.name = Elektrometál-elosztó
@@ -1836,7 +1880,7 @@ block.reinforced-conduit.name = Megerősített csővezeték
block.reinforced-liquid-junction.name = Megerősített folyadékátkötés
block.reinforced-bridge-conduit.name = Megerősített csővezetékhíd
block.reinforced-liquid-router.name = Megerősített folyadékelosztó
-block.reinforced-liquid-container.name = Megerősített folyadékkonténer
+block.reinforced-liquid-container.name = Megerősített folyadéktározó
block.reinforced-liquid-tank.name = Megerősített folyadéktartály
block.beam-node.name = Sugárcsomópont
block.beam-tower.name = Sugártorony
@@ -1846,6 +1890,7 @@ block.chemical-combustion-chamber.name = Kémiai égetőkamra
block.pyrolysis-generator.name = Pirolízis-erőmű
block.vent-condenser.name = Vízleválasztó
block.cliff-crusher.name = Sziklazúzó
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plazmafúró
block.large-plasma-bore.name = Nagy plazmafúró
block.impact-drill.name = Ütvefúró
@@ -1854,7 +1899,7 @@ block.core-bastion.name = Bástya
block.core-citadel.name = Citadella
block.core-acropolis.name = Akropolisz
block.reinforced-container.name = Megerősített konténer
-block.reinforced-vault.name = Megerősített tároló
+block.reinforced-vault.name = Megerősített raktár
block.breach.name = Breach
block.sublimate.name = Sublimate
block.titan.name = Titan
@@ -1910,34 +1955,34 @@ hint.desktopShoot = Használd a [accent]bal egérgombot[] a lövéshez.
hint.depositItems = A nyersanyagokat húzással helyezheted át a drónból a támaszpontba.
hint.respawn = Ahhoz, hogy drónként újraéledj, nyomd meg a [accent][[V][] gombot.
hint.respawn.mobile = Átvetted az irányítást egy egység vagy épület felett. Ahhoz, hogy drónként újraéledj, [accent]koppints a profilképre a bal felső sarokban.[]
-hint.desktopPause = Nyomd meg a [accent][[Szóközt][] a játék szüneteltetéséhez vagy folytatásához.
+hint.desktopPause = Nyomd meg a [accent][[szóközt][] a játék szüneteltetéséhez vagy folytatásához.
hint.breaking = [accent]Jobb egérgombbal[] és húzással lebonthatod a blokkokat.
hint.breaking.mobile = Használd a jobb alsó sarokban lévő \ue817 [accent]kalapács[] gombot a blokkok törléséhez.\n\nTartsd lenyomva az ujjad és húzd, hogy nagyobb területet tudj kijelölni.
hint.blockInfo = Egy blokk információinak megtekintéséhez válaszd ki az épületet az [accent]építési menüben[], majd válaszd a [accent][[?][] gomb jobb oldalt.
hint.derelict = Az [accent]elhagyatott[] szerkezetek régi bázisok maradványai, amelyek már nem működnek.\n\nEzeket az épületeket le lehet [accent]bontani[] nyersanyagokért, vagy meg is lehet javítani őket.
-hint.research = Használd a \ue875 [accent]Technológia fa[] gombot, hogy új technológiákat fedezz fel.
-hint.research.mobile = Használd a \ue875 [accent]Technológia fa[] gombot a \ue88c [accent]menüben[], hogy új technológiákat fedezz fel.
+hint.research = Használd a \ue875 [accent]technológia fa[] gombot, hogy új technológiákat fedezz fel.
+hint.research.mobile = Használd a \ue875 [accent]technológia fa[] gombot a \ue88c [accent]menüben[], hogy új technológiákat fedezz fel.
hint.unitControl = Nyomd le a [accent][[bal Ctrl][] gombot, és kattints [accent]jobb egérgombbal[] a baráti egység vagy lövegtorony irányításához.
-hint.unitControl.mobile = [accent][[Dupla koppintással][] a szövetséges egységek vagy lövegtornyok kézileg irányíthatóak.
-hint.unitSelectControl = Az egységek irányításához lépj be [accent]parancs módba[] a [accent]bal Shift[] lenyomva tartásával.\nParancs módban az egységek kijelöléséhez kattints, és húzd az egeret. A [accent]jobb egérgombbal[] küldd az egységeket a helyszínre vagy a célponthoz.
+hint.unitControl.mobile = [accent][[Dupla koppintással][] a szövetséges egységek vagy lövegtornyok kézileg irányíthatók.
+hint.unitSelectControl = Az egységek irányításához lépj be [accent]parancs módba[] a [accent]bal shift[] lenyomva tartásával.\nParancs módban az egységek kijelöléséhez kattints, és húzd az egeret. A [accent]jobb egérgombbal[] küldd az egységeket a helyszínre vagy a célponthoz.
hint.unitSelectControl.mobile = Az egységek irányításához lépj be [accent]parancs módba[] a bal alsó sarokban lévő [accent]parancs[] gombbal.\nParancs módban az egységek kiválasztásához érintsd meg a kijelzőt és húzással jelöld ki az egységeket. Koppintással küldd az egységeket a helyszínre vagy a célponthoz.
-hint.launch = Ha elegendő nyersanyagot gyűjtöttél össze, akkor [accent]lődd ki[] a támaszpontot a következő szektorba, úgy, hogy megnyitod a \ue827 [accent]Bolygótérképet[] a jobb alsó sarokban, és átforgatod az új helyszínre.
-hint.launch.mobile = Ha elegendő nyersanyagot gyűjtöttél össze, akkor [accent]lődd ki[] a támaszpontot egy közeli szektorba, úgy, hogy kiválasztasz egy szektort a \ue88c [accent]Menüben[] a \ue827 [accent]Bolygótérképről[].
+hint.launch = Ha elegendő nyersanyagot gyűjtöttél össze, akkor [accent]lődd ki[] a támaszpontot a következő szektorba, úgy, hogy megnyitod a \ue827 [accent]bolygótérképet[] a jobb alsó sarokban, és átforgatod az új helyszínre.
+hint.launch.mobile = Ha elegendő nyersanyagot gyűjtöttél össze, akkor [accent]lődd ki[] a támaszpontot egy közeli szektorba, úgy, hogy kiválasztasz egy szektort a \ue88c [accent]menüben[] a \ue827 [accent]bolygótérképről[].
hint.schematicSelect = Tartsd nyomja az [accent][[F][] gombot több épület kijelöléséhez és másolásához.\n\n[accent][[Középső kattintással][] egy adott blokktípus másolható.
hint.rebuildSelect = Tartsd nyomva a [accent][[B][] gombot és húzással jelöld ki a megsemmisített blokkterveket.\nEz automatikusan újraépíti őket.
hint.rebuildSelect.mobile = Válaszd a \ue874 másolás gombot, majd koppints az \ue80f újraépítés gombra, és húzd a megsemmisült blokktervek kijelöléséhez.\nEz automatikusan újraépíti őket.
-hint.conveyorPathfind = Tartsd nyomva a [accent][[bal Ctrl][] gombot a szállítószalagok lerakása közben, hogy a játék útvonalat állítson elő.
+hint.conveyorPathfind = Tartsd nyomva a [accent][[bal ctrl][] gombot a szállítószalagok lerakása közben, hogy a játék útvonalat állítson elő.
hint.conveyorPathfind.mobile = Engedélyezd az \ue844 [accent]átlós módot[], és tegyél le egyszerre több szállítószalagot, hogy a játék útvonalat állítson elő.
-hint.boost = Tartsd nyomva a [accent][[bal Shift][] gombot, hogy átrepülj az akadályok felett.\n\nErre csak néhány földi egység képes.
+hint.boost = Tartsd nyomva a [accent][[bal shift][] gombot, hogy átrepülj az akadályok felett.\n\nErre csak néhány földi egység képes.
hint.payloadPickup = Nyomd meg a [accent][[[] gombot a kis blokkok vagy egységek felemeléséhez.
hint.payloadPickup.mobile = [accent]Koppints és tartsd lenyomva az ujjad[] egy kis blokk vagy egység felemeléséhez.
hint.payloadDrop = Nyomd le a [accent]][] gombot a rakomány lerakásához.
hint.payloadDrop.mobile = [accent]Koppints és tartsd lenyomva az ujjad[] egy üres területen a rakomány lerakásához.
hint.waveFire = A vizet lőszerként használó [accent]Wave[] lövegtornyok automatikusan eloltják a közeli tüzeket.
-hint.generator = Az \uf879 [accent]égetőerőmű[] szenet éget, és áramot ad át a vele érintkező épületeknek.\n\nAz áramszállítás távolsága [accent]villanyoszlopokkal[] növelhető.
-hint.guardian = Az [accent]Őrzők[] páncélozottak. A gyenge lövedékek, mint a [accent]réz[] vagy az [accent]ólom[] [scarlet]nem hatásosak[] az Őrző páncéljával szemben.\n\nHasználj magasabb szintű lövegtornyokat, vagy \uf835 [accent]grafitot[] a Duo/\uf859Salvo lövegtornyokban, hogy leszedd az Őrzőket.
+hint.generator = Az \uf879 [accent]égetőerőmű[] szenet éget, és áramot ad át a vele érintkező épületeknek.\n\nAz áramszállítás távolsága további \uf87f [accent]villanyoszlopokkal[] növelhető.
+hint.guardian = Az [accent]őrzők[] páncélozottak. A gyenge lövedékek, mint a [accent]réz[] vagy az [accent]ólom[] [scarlet]nem hatásosak[] az Őrző páncéljával szemben.\n\nHasználj magasabb szintű lövegtornyokat, vagy juttass \uf835 [accent]grafitot[] a \uf861 Duo / \uf859 Salvo lövegtornyokba, hogy leszedd az őrzőket.
hint.coreUpgrade = A támaszpont úgy fejleszthető, hogy [accent]magasabb szintű támaszpontot teszel rá[].\n\nHelyezz egy \uf868 [accent]Alapítvány[] támaszpontot a \uf869 [accent]Szilánk[] támaszpontra. Figyelj rá, hogy ne legyenek az új támaszpont területén épületek.
-hint.presetLaunch = A szürke [accent]landolási zónát tartalmazó szektorokba[], amilyen például a [accent]Fagyott erdő[], bárhonnan kilőhetsz. Nem szükséges hozzá szomszédos területet elfoglalnod.\n\nA [accent]számozott szektorok[], mint ez is, [accent]nem kötelezők[].
+hint.presetLaunch = A szürke [accent]landolási zónát tartalmazó szektorokba[], amilyen például a [accent]Fagyott erdő[], bárhonnan kilőhetsz. Nem szükséges hozzá szomszédos területet elfoglalnod.\n\nA [accent]számozott szektorokat[], mint ez is, a játékmenet szempontjából [accent]nem fontos[] elfoglalni.
hint.presetDifficulty = Ebben a szektorban [scarlet]magas az ellenséges fenyegetettségi szint[].\nAz ilyen szektorokba való indulás [accent]nem ajánlott[] megfelelő technológia és felkészülés nélkül.
hint.coreIncinerate = Ha a támaszpont egy nyersanyagból elérte a maximumot, a beérkező további nyersanyagok azonnal [accent]megsemmisítésre kerülnek[].
hint.factoryControl = Egy egységgyár [accent]kimeneti célpontjának[] beállításához kattints parancs módban egy gyárépületre, majd kattints jobb egérgombbal egy helyre.\nAz előállított egységek automatikusan odamennek.
@@ -1945,14 +1990,14 @@ hint.factoryControl.mobile = Egy egységgyár [accent]kimeneti célpontjának[]
gz.mine = Menj a földön lévő \uf8c4 [accent]rézérc[] közelébe, és kattints a bányászat megkezdéséhez.
gz.mine.mobile = Menj a földön lévő \uf8c4 [accent]rézérc[] közelébe, és koppints a bányászat megkezdéséhez.
-gz.research = Nyisd meg a \ue875 Technológia fát.\nFejleszd ki a \uf870 [accent]Mechanikus fúrót[], majd válaszd ki a jobb alsó sarokban lévő menüből.\nKattints egy rézfoltra az elhelyezéséhez.
-gz.research.mobile = Nyisd meg a \ue875 Technológia fát.\nFejleszd ki a \uf870 [accent]Mechanikus fúrót[], majd válaszd ki a jobb alsó sarokban lévő menüből.\nKattints egy rézfoltra az elhelyezéséhez.\n\nA megerősítéshez nyomd meg a jobb alsó sarokban lévő \ue800 [accent]pipát[].
-gz.conveyors = Fejleszd ki, és építs \uf896 [accent]Szállítószalagokat[], hogy a kitermelt\nnyersanyagokat eljuttasd a fúróktól a támaszpontba.\n\nKattints és húzd az egeret, hogy több szállítószalagot helyezz el.\nHasználd a [accent]görgőt[] a forgatáshoz.
+gz.research = Nyisd meg a \ue875 Technológia fát.\nFejleszd ki a \uf870 [accent]mechanikus fúrót[], majd válaszd ki a jobb alsó sarokban lévő \ue85e menüből.\nKattints egy rézfoltra az elhelyezéséhez.
+gz.research.mobile = Nyisd meg a \ue875 Technológia fát.\nFejleszd ki a \uf870 [accent]mechanikus fúrót[], majd válaszd ki a jobb alsó sarokban lévő \ue85e menüből.\nKattints egy rézfoltra az elhelyezéséhez.\n\nA megerősítéshez nyomd meg a jobb alsó sarokban lévő \ue800 [accent]pipát[].
+gz.conveyors = Fejleszd ki, és építs \uf896 [accent]szállítsszalagokat[], hogy a kitermelt\nnyersanyagokat eljuttasd a fúróktól a támaszpontba.\n\nKattints és húzd az egeret, hogy több szállítószalagot helyezz el.\nHasználd a [accent]görgőt[] a forgatáshoz.
gz.conveyors.mobile = Fejleszd ki, és építs \uf896 [accent]Szállítószalagokat[], hogy a kitermelt\nnyersanyagokat eljuttasd a fúróktól a támaszpontba.\n\nTartsd lenyomva az ujjad és húzd el, hogy több szállítószalagot helyezz el.
gz.drills = Bővítsd a bányászati kapacitást.\nÉpíts több mechanikus fúrót.\nBányássz 100 rezet.
gz.lead = Az \uf837 [accent]ólom[] egy másik gyakran használt nyersanyag.\nÉpíts fúrókat az ólom kitermelésére.
gz.moveup = \ue804 Menj tovább a további utasításokért.
-gz.turrets = Fejleszd ki, és építs két \uf861 [accent]Duo[] lövegtornyot, hogy megvédd a támaszpontot.\nA Duo lövegtornyoknak \uf838 [accent]lőszerre[] van szükségük, mely szállítószalaggal juttatható el hozzájuk.
+gz.turrets = Fejleszd ki, és építs két \uf861 [accent]Duo[] lövegtornyot, hogy megvédd a támaszpontot.\nA Duo lövegtornyoknak \uf838 [accent]lőszerre[] van szükségük, amelyet szállítószalaggal juttathatsz el hozzájuk.
gz.duoammo = Szállítószalagok segítségével lásd el [accent]rézzel[] a Duo lövegtornyokat.
gz.walls = A [accent]falak[] megakadályozhatják, hogy az épületekben károk keletkezzenek.\nÉpíts \uf8ae [accent]Rézfalakat[] a lövegtornyok köré.
gz.defend = Az ellenség közeledik, készülj fel a védekezésre.
@@ -1961,45 +2006,45 @@ gz.scatterammo = Szállítószalagok segítségével lásd el \uf837 [accent]ól
gz.supplyturret = [accent]Lövegtorony ellátása
gz.zone1 = Ez az ellenség leszállóhelye.
gz.zone2 = Bármi, ami a hatósugarában épült, elpusztul, amikor egy hullám elindul.
-gz.zone3 = Egy hullám most kezdődik.\nKészülj fel.
+gz.zone3 = Egy hullám most kezdődik.\nKészülj fel!
gz.finish = Építs több lövegtornyot, bányássz több nyersanyagot,\nés védekezz az ellenséges hullámok ellen, hogy [accent]elfoglald a szektort[].
onset.mine = Kattints bal egérgombbal a \uf748 [accent]berillium[] kibányászáshoz a falakból.\n\nA mozgáshoz használd a [accent][[WASD] gombokat.
onset.mine.mobile = Koppints a \uf748 [accent]berillium[] kibányászáshoz a falakból.
-onset.research = Nyisd meg a \ue875 Technológia fát.\nFejleszd ki, és építs egy \uf73e [accent]Kondenzációs turbinát[] a kürtőn.\nEz [accent]áramot[] fog termelni.
-onset.bore = Fejleszd ki, és építs egy \uf741 [accent]Plazmafúrót[].\nEz automatikusan bányássza ki a nyersanyagokat a falakból.
-onset.power = Ahhoz, hogy [accent]árammal[] lásd el a plazmafúrót, fejleszd ki, és helyezz el egy \uf73d [accent]Sugárcsomópontot[].\nSegítségükkel összekötheted a kondenzációs turbinát a plazmafúróval.
-onset.ducts = Fejleszd ki, és építs \uf799 [accent]Szállítószalagot[], hogy a kitermelt nyersanyagokat eljuttasd a plazmafúrótól a támaszpontba.\nKattints, és húzd az egeret több szállítószalag elhelyezéséhez.\nHasználd a [accent]görgőt[] a forgatáshoz.
-onset.ducts.mobile = Fejleszd ki, és építs \uf799 [accent]Szállítószalagot[], hogy a kitermelt nyersanyagokat eljuttasd a plazmafúrótól a támaszpontba.\n\nTartsd lenyomva az ujjad és húzd el, hogy több szállítószalagot helyezz el.
+onset.research = Nyisd meg a \ue875 Technológia fát.\nFejleszd ki, és építs egy \uf73e [accent]kondenzációs turbinát[] a kürtőn.\nEz [accent]áramot[] fog termelni.
+onset.bore = Fejleszd ki, és építs egy \uf741 [accent]plazmafúrót[].\nEz automatikusan bányássza ki a nyersanyagokat a falakból.
+onset.power = Ahhoz, hogy [accent]árammal[] lásd el a plazmafúrót, fejleszd ki, és helyezz el egy \uf73d [accent]sugárcsomópontot[].\nSegítségükkel összekötheted a kondenzációs turbinát a plazmafúróval.
+onset.ducts = Fejleszd ki, és építs \uf799 [accent]szállítószalagot[], hogy a kitermelt nyersanyagokat eljuttasd a plazmafúrótól a támaszpontba.\nKattints, és húzd az egeret több szállítószalag elhelyezéséhez.\nHasználd a [accent]görgőt[] a forgatáshoz.
+onset.ducts.mobile = Fejleszd ki, és építs \uf799 [accent]szállítószalagot[], hogy a kitermelt nyersanyagokat eljuttasd a plazmafúrótól a támaszpontba.\n\nTartsd lenyomva az ujjad és húzd el, hogy több szállítószalagot helyezz el.
onset.moremine = Bővítsd a bányászati kapacitást.\nHelyezz el több plazmavágót, és a támogatásukhoz használj sugárcsomópontokat és szállítószalagokat.\nBányássz 200 berilliumot.
onset.graphite = Az összetettebb épületekhez \uf835 [accent]grafit[] szükséges.\nÉpíts plazmavágókat a grafit kibányászásához.
-onset.research2 = Kezdd el a [accent]gyárak[] fejlesztését.\nFejleszd ki a \uf74d [accent]Sziklazúzót[] és a \uf779 [accent]Szilícium ívkemencét[].
-onset.arcfurnace = A szilícium ívkemencének \uf834 [accent]homokra[] és \uf835 [accent]grafitra[] van szüksége, hogy \uf82f [accent]szilíciumot[] gyártson.\nTovábbá [accent]áram[] is szükséges a működéséhez.
-onset.crusher = Használj \uf74d [accent]Sziklazúzókat[], hogy homokot bányász.
-onset.fabricator = Használd az [accent]egységeket[], hogy felfedezd a pályát, megvédd az épületeket, és megtámadhasd velük az ellenséget. Fejleszd ki, és helyezz el egy \uf6a2 [accent]Tankgyártót[].
+onset.research2 = Kezdd el a [accent]gyárak[] fejlesztését.\nFejleszd ki a \uf74d [accent]sziklazúzót[] és a \uf779 [accent]szilícium-ívkemencét[].
+onset.arcfurnace = A szilícium-ívkemencének \uf834 [accent]homokra[] és \uf835 [accent]grafitra[] van szüksége, hogy \uf82f [accent]szilíciumot[] gyártson.\nTovábbá [accent]áram[] is szükséges a működéséhez.
+onset.crusher = Használj \uf74d [accent]sziklazúzókat[], hogy homokot bányássz.
+onset.fabricator = Használd az [accent]egységeket[], hogy felfedezd a pályát, megvédd az épületeket, és megtámadhasd velük az ellenséget. Fejleszd ki, és helyezz el egy \uf6a2 [accent]tankgyártót[].
onset.makeunit = Állíts elő egy egységet.\nHasználd a „?” gombot, hogy megnézd a kiválasztott gyár követelményeit.
onset.turrets = Az egységek hatékonyak, de hatásosan alkalmazva a [accent]lövegtornyok[] jobb védelmi képességeket biztosítanak.\nHelyezz el egy \uf6eb [accent]Breach[] lövegtornyot.\nA lövegtornyoknak \uf748 [accent]lőszerre[] van szüksége.
onset.turretammo = Szállítótalagok használatával lásd el a lövegtornyokat [accent]berillium[] lőszerrel.
-onset.walls = A [accent]falak[] megakadályozhatják, hogy az épületekben károk keletkezzenek.\nÉpíts \uf6ee [accent]Berillium falakat[] a lövegtornyok körül.
+onset.walls = A [accent]falak[] megakadályozhatják, hogy az épületekben károk keletkezzenek.\nÉpíts \uf6ee [accent]berilliumfalakat[] a lövegtornyok körül.
onset.enemies = Az ellenség közeledik, készülj fel a védekezésre.
onset.defenses = [accent]Állíts fel védelmet:[lightgray] {0}
-onset.attack = Az ellenség most sebezhető. Indíts ellentámadást.
-onset.cores = Új támaszpont csak a [accent]támaszpontcsempére[] helyezhető.\nAz új támaszpontok előretolt bázisként működnek, és megosztják a nyersanyagkészletüket más támaszpontokkal.\nHelyezz el egy \uf725 támaszpontot.
+onset.attack = Az ellenség most sebezhető. Indíts ellentámadást!
+onset.cores = Új támaszpont csak a [accent]támaszpontmezőre[] helyezhető.\nAz új támaszpontok előretolt bázisként működnek, és megosztják a nyersanyagkészletüket más támaszpontokkal.\nHelyezz el egy \uf725 támaszpontot.
onset.detect = Az ellenség 2 percen belül észrevesz téged.\nÁllíts fel védelmet, bányászatot és termelést.
-onset.commandmode = Tartsd nyomva a [accent]Shift[] gombot, hogy [accent]parancs módba[] lépj.\n[accent]Bal egérgombbal és húzással[] lehet egységeket kijelölni.\n[accent]Jobb egérgombbal[] az egységek mozgásra vagy támadásra utasíthatóak.
-onset.commandmode.mobile = Nyomd meg a [accent]parancs gombot[], hogy [accent]parancs módba[] lépj.\nTartsd nyomva az ujjad, majd [accent]húzd[] az egységek kiválasztásához.\n[accent]Koppintással[] az egységek mozgásra vagy támadásra utasíthatóak.
-aegis.tungsten = Volfrámot [accent]Ütvefúróval[] lehet bányászni.\nEnnek az épületnek [accent]vízre[] és [accent]áramra[] van szüksége.
+onset.commandmode = Tartsd nyomva a [accent]shift[] gombot, hogy [accent]parancs módba[] lépj.\n[accent]Bal egérgombbal és húzással[] lehet egységeket kijelölni.\n[accent]Jobb egérgombbal[] az egységek mozgásra vagy támadásra utasíthatók.
+onset.commandmode.mobile = Nyomd meg a [accent]parancs gombot[], hogy [accent]parancs módba[] lépj.\nTartsd nyomva az ujjad, majd [accent]húzd[] az egységek kiválasztásához.\n[accent]Koppintással[] az egységek mozgásra vagy támadásra utasíthatók.
+aegis.tungsten = Volfrámot [accent]ütvefúróval[] lehet bányászni.\nEnnek az épületnek [accent]vízre[] és [accent]áramra[] van szüksége.
-split.pickup = Egyes blokkok a támaszpont drónjával is felvehetőek.\nVedd fel ezt a [accent]konténert[] és helyezd egy [accent]rakománycsomagolóba[].\n(A felvétel és lerakás alapértelmezett gombjai: [[ és ].)
-split.pickup.mobile = Egyes blokkok a támaszpont drónjával is felvehetőek.\nVedd fel ezt a [accent]konténert[] és helyezd egy [accent]rakománycsomagolóba[].\n(A felvételhez és lerakáshoz nyomd meg hosszan.)
+split.pickup = Egyes blokkok a támaszpont drónjával is felvehetők.\nVedd fel ezt a [accent]konténert[] és helyezd egy [accent]rakománycsomagolóba[].\n(A felvétel és lerakás alapértelmezett gombjai: [[ és ].)
+split.pickup.mobile = Egyes blokkok a támaszpont drónjával is felvehetők.\nVedd fel ezt a [accent]konténert[] és helyezd egy [accent]rakománycsomagolóba[].\n(A felvételhez és lerakáshoz nyomd meg hosszan.)
split.acquire = Az egységek építéséhez volfrámot kell szerezned.
-split.build = Az egységeket a fal másik oldalára kell eljuttatni.\nÉpíts két [accent]Rakomány-tömegmozgatót[], egyet-egyet a fal mindkét oldalán.\nÁllítsd be a szállítási kapcsolatukat úgy, hogy kiválasztod az egyiket, majd kiválasztod a másikat.
-split.container = A konténerekhez hasonlóan, az egységek is szállíthatóak a [accent]Rakomány-tömegmozgatóval[].\nÉpíts egy egységgyárat egy tömegmozgató mellé, hogy feltöltsd őket, majd küldd át őket a falon, hogy megtámadják az ellenséges bázist.
+split.build = Az egységeket a fal másik oldalára kell eljuttatni.\nÉpíts két [accent]rakomány-tömegmozgatót[], egyet-egyet a fal mindkét oldalán.\nÁllítsd be a szállítási kapcsolatukat úgy, hogy kiválasztod az egyiket, majd kiválasztod a másikat.
+split.container = A konténerekhez hasonlóan, az egységek is szállíthatók a [accent]rakomány-tömegmozgatóval[].\nÉpíts egy egységgyárat egy tömegmozgató mellé, hogy feltöltsd őket, majd küldd át őket a falon, hogy megtámadják az ellenséges bázist.
item.copper.description = Széleskörűen használatos építkezésnél és lőszerként.
item.copper.details = Réz. Szokatlanul bőségesen elterjedt fém a Serpulón. Megerősítés nélkül strukturálisan gyenge.
item.lead.description = Folyadékszállításnál és elektromos eszközökben használatos.
-item.lead.details = Sűrű. Közömbös. Széles körben használatos az akkumulátorokban.\nMegjegyzés: Valószínűleg mérgező a biológiai életformákra. Nem mintha sok maradt volna errefelé.
+item.lead.details = Sűrű. Közömbös. Széleskörűen használatos az akkumulátorokban.\nMegjegyzés: Valószínűleg mérgező a biológiai életformákra; nem mintha sok maradt volna errefelé.
item.metaglass.description = Folyadékszállító és -tárolóépületeknél használatos.
item.graphite.description = Elektromos alkatrészekben és lőszerként használatos.
item.sand.description = Egyéb finomított nyersanyagok gyártása során használatos.
@@ -2025,7 +2070,7 @@ item.oxide.description = Hővezetőként és szigetelőként is használatos az
item.carbide.description = Fejlett szerkezetekben, nehezebb egységekhez és lőszerként használatos.
liquid.water.description = Gépek hűtéséhez és törmelékfeldolgozáshoz használatos.
-liquid.slag.description = Leválasztóban alkotófémekre finomítható. Folyadékot használó tornyokban lőszerként használható.
+liquid.slag.description = Leválasztókban alkotófémekre finomítható. A folyadékot lőszerként használó tornyokban használható, például: Wave, Tsunami.
liquid.oil.description = Fejlett nyersanyagok gyártásához és gyújtólövedékhez használatos.
liquid.cryofluid.description = Reaktorokban, lövegtornyokban és gyárakban használatos hűtőfolyadékként.
@@ -2035,8 +2080,8 @@ liquid.ozone.description = Az anyaggyártásban oxidálószerként, illetve üze
liquid.hydrogen.description = A nyersanyagok kitermelésében, egységgyártásban és szerkezetjavításban használatos. Gyúlékony.
liquid.cyanogen.description = Lőszerként, fejlett egységek építéséhez és különböző reakciókhoz használatos a fejlett blokkokban. Erősen gyúlékony.
liquid.nitrogen.description = A nyersanyagok kitermelésénél, gáztermelésnél és egységgyártásnál is használatos. Semleges gáz.
-liquid.neoplasm.description = A neoplázia reaktor veszélyes biológiai mellékterméke. Gyorsan átterjed minden szomszédos víztartalmú blokkra, amelyhez hozzáér, és közben károsítja azokat. Sűrű folyadék.
-liquid.neoplasm.details = Neoplazma. Egy kontrollálhatatlan, gyorsan osztódó, iszap állagú, szintetikus sejtmassza. Hőálló. Rendkívül veszélyes minden vízzel kapcsolatos szerkezetre.\n\nTúl összetett és instabil a szabványos elemzésekhez. Potenciális alkalmazási területe ismeretlen. A salakmedencékben való elégetés ajánlott.
+liquid.neoplasm.description = A neopláziareaktor veszélyes biológiai mellékterméke. Gyorsan átterjed minden szomszédos víztartalmú blokkra, amelyhez hozzáér, és közben károsítja azokat. Sűrű folyadék.
+liquid.neoplasm.details = Neoplazma. Egy kontrollálhatatlan, gyorsan osztódó, iszap állagú, szintetikus sejtmassza. Hőálló. Rendkívül veszélyes minden vízzel kapcsolatos szerkezetre.\n\nTúl összetett és instabil a szabványos elemzésekhez. Potenciális alkalmazási területe ismeretlen. Ajánlott elégetni a salakos égetőkamrákban.
block.derelict = \uf77e [lightgray]Elhagyatott
block.armored-conveyor.description = Nyersanyagokat szállít. Nem fogad el oldalról nem szállítószalagról érkező nyersanyagot.
@@ -2045,19 +2090,19 @@ block.message.description = Üzenetet tárol a szövetségesek kommunikációjá
block.reinforced-message.description = Üzenetet tárol a szövetségesek közötti kommunikációhoz.
block.world-message.description = A pályakészítésben használható üzenetblokk. Nem lehet megsemmisíteni.
block.graphite-press.description = Grafittá préseli a szenet.
-block.multi-press.description = Grafittá sajtolja a szenet. Hűtéséhez viz szükséges.
+block.multi-press.description = Grafittá sajtolja a szenet. Hűtéséhez víz szükséges.
block.silicon-smelter.description = A homokot és a szenet szilíciummá finomítja.
block.kiln.description = Ólomüveget olvaszt az ólomból és a homokból.
block.plastanium-compressor.description = Olaj és titán felhasználásával műanyagot gyárt.
block.phase-weaver.description = Tórium és homok keverékéből tóritkvarcot állít elő.
block.surge-smelter.description = Titán, ólom, szilícium és réz ötvözésével elektrometált állít elő.
block.cryofluid-mixer.description = Finom titánpor vízhez keverésével hűtőfolyadékot állít elő.
-block.blast-mixer.description = Robbanóelegyet készít a piratitból és a spórakapszulákból.
+block.blast-mixer.description = Robbanóelegyet gyárt piratitból és spórakapszulából.
block.pyratite-mixer.description = Piratittá vegyíti a szenet, a homokot és az ólmot.
block.melter.description = Salakká olvasztja a törmeléket.
block.separator.description = Ásványi összetevőire bontja a salakot.
block.spore-press.description = Olajat sajtol a spórakapszulából.
-block.pulverizer.description = Finom homokká őrli a törmeléket.
+block.pulverizer.description = Finom homokká darálja a törmeléket.
block.coal-centrifuge.description = Szénné alakítja az olajat.
block.incinerator.description = Megsemmisít minden nyersanyagot és folyadékot.
block.power-void.description = Elnyel minden áramot. Csak homokozó módban.
@@ -2080,19 +2125,23 @@ block.phase-wall.description = Megvédi az épületeket az ellenséges lövedék
block.phase-wall-large.description = Megvédi az épületeket az ellenséges lövedékektől, a legtöbb lövedék visszapattan róla.
block.surge-wall.description = Megvédi az épületeket az ellenséges lövedékektől, periodikusan elektromos kisüléseket generál, ha hozzáérnek.
block.surge-wall-large.description = Megvédi az épületeket az ellenséges lövedékektől, periodikusan elektromos kisüléseket generál, ha hozzáérnek.
+block.scrap-wall.description = Megvédi az épületeket az ellenséges lövedékektől.
+block.scrap-wall-large.description = Megvédi az épületeket az ellenséges lövedékektől.
+block.scrap-wall-huge.description = Megvédi az épületeket az ellenséges lövedékektől.
+block.scrap-wall-gigantic.description = Megvédi az épületeket az ellenséges lövedékektől.
block.door.description = Nyitható és zárható fal.
block.door-large.description = Nyitható és zárható fal.
block.mender.description = Időnként javítja a közeli épületeket.\nSzilíciummal növelhető a hatósugara és hatékonysága.
block.mend-projector.description = Javítja a közeli épületeket.\nTóritkvarccal növelhető a hatósugara és hatékonysága.
-block.overdrive-projector.description = Növeli a közeli épületek termelési sebességét.\nTóritkvarccal növelhető a hatósugara és hatékonysága.
-block.force-projector.description = Hatszögletű erőteret hoz létre maga körül, amely megvédi az épületeket és a benne lévő egységeket a sérüléstől.\nTúlmelegszik, ha túl sok sérülést szenved. Hűtőfolyadékot használva megakadályozható a túlmelegedés. A tóritkvarc növeli a pajzs méretét.
+block.overdrive-projector.description = Megöveli a környező épületek termelési sebességét.\nTóritkvarccal növelhető a hatósugara és hatékonysága.
+block.force-projector.description = Hatszögletű erőpajzsot hoz létre maga körül, amely megvédi a benne lévő épületeket és egységeket a sérüléstől.\nTúlmelegszik, ha túl sok sérülést szenved. Hűtőfolyadék használatával megakadályozható a túlmelegedés. A tóritkvarc megnöveli az erőpajzs méretét.
block.shock-mine.description = Elektromos kisülést hoz létre, ha ellenséggel érintkezik.
block.conveyor.description = Nyersanyagokat szállít.
block.titanium-conveyor.description = Nyersanyagokat szállít. Gyorsabb a sima szállítószalagnál.
block.plastanium-conveyor.description = Nyersanyagokat szállít tömbösítve. Hátulról fogadja a nyersanyagokat, elöl három irányba osztja szét őket. Több kezdő- és végponttal növelhető az áteresztőképessége.
block.junction.description = Hídként működik két egymást keresztező szállítószalag között.
block.bridge-conveyor.description = Nyersanyagokat szállít épületek és terepakadályok fölött.
-block.phase-conveyor.description = Nyersanyagokat szállít épületek és terepakadályok fölött. Nagyobb távolságra ér, mint a sima szállítószalaghíd, de áramot igényel.
+block.phase-conveyor.description = Nyersanyagokat szállít épületek és terepakadályok fölött. Nagyobb távolságra ér, mint a sima szállítószalaghíd, de áramot fogyaszt.
block.sorter.description = Csak a kiválasztott nyersanyagot engedi tovább egyenesen, minden mást oldalra ad ki.
block.inverted-sorter.description = Hasonló a szokásos válogatóhoz, de a kiválasztott nyersanyagot oldalra adja ki.
block.router.description = Egyenletesen háromfelé osztja szét a beérkező nyersanyagokat.
@@ -2101,8 +2150,8 @@ block.distributor.description = Egyenletesen hétfelé osztja szét a beérkező
block.overflow-gate.description = Csak akkor ad ki nyersanyagot oldalra, ha előrefelé már nem tud.
block.underflow-gate.description = A túlcsorduló kapu ellentettje. Csak akkor ad ki nyersanyagot előrefelé, ha oldalra már nem tud.
block.mass-driver.description = Nagy hatótávolságú nyersanyagszállító eszköz. Rakományokat gyűjt össze, és átlövi egy másik, hozzákapcsolt tömegmozgatónak.
-block.mechanical-pump.description = Folyadékot szivattyúz és ad ki. Nem igényel áramot.
-block.rotary-pump.description = Folyadékot szivattyúz és ad ki. Áramot igényel.
+block.mechanical-pump.description = Folyadékot szivattyúz és ad ki. Nem fogyaszt áramot.
+block.rotary-pump.description = Folyadékot szivattyúz és ad ki. Áramot fogyaszt.
block.impulse-pump.description = Folyadékot szivattyúz és ad ki.
block.conduit.description = Folyadékot szállít. Szivattyúkkal és egyéb csővezetékekkel együtt használatos.
block.pulse-conduit.description = Folyadékot szállít. Gyorsabban szállít, és nagyobb tárolókapacitású, mint a szokásos csővezeték.
@@ -2112,11 +2161,11 @@ block.liquid-container.description = Jelentős mennyiségű folyadékot tárol.
block.liquid-tank.description = Nagy mennyiségű folyadékot tárol. Minden oldalon kiadja, hasonlóan a folyadékelosztóhoz.
block.liquid-junction.description = Hídként működik két egymást keresztező csővezeték között.
block.bridge-conduit.description = Folyadékot szállít épületek és terepakadályok fölött.
-block.phase-conduit.description = Folyadékot szállít épületek és terepakadályok fölött. Nagyobb távolságra ér, mint a sima csővezetékhíd, de áramot igényel.
-block.power-node.description = Áramot vezet az összekapcsolt csomópontokhoz. A szomszédos blokkokkal automatikusan kapcsolatban van.
+block.phase-conduit.description = Folyadékot szállít épületek és terepakadályok fölött. Nagyobb távolságra ér, mint a sima csővezetékhíd. Áramot fogyaszt.
+block.power-node.description = Áramot vezet az összekapcsolt csomópontokhoz. A szomszédos blokkokkal automatikusan kapcsolatba kerül megépítéskor.
block.power-node-large.description = Nagyobb villanyoszlop, nagyobb hatótávolsággal.
block.surge-tower.description = Hosszútávú villanyoszlop, kevesebb elérhető kapcsolattal.
-block.diode.description = Az eltárolt áramot irányítja egy irányba továbbítja, de csak akkor, ha a fogadó oldalon kevesebb van tárolva.
+block.diode.description = Az eltárolt áramot egy irányba engedi át, de csak akkor, ha a fogadó oldalon kevesebb van tárolva.
block.battery.description = Áramot tárol el, ha túltermelés van. Leadja az áramot, ha hiány van.
block.battery-large.description = Áramot tárol el, ha túltermelés van. Leadja az áramot, ha hiány van. Nagyobb kapacitású a szokásos akkumulátornál.
block.combustion-generator.description = Áramot termel éghető anyagok, például szén, elégetésével.
@@ -2126,24 +2175,24 @@ block.differential-generator.description = Nagy mennyiségű áramot termel. A h
block.rtg-generator.description = A radioaktív bomlás energiáját hasznosítja, hogy lassan, de biztosan áramot termeljen.
block.solar-panel.description = Napfényből állít elő kevés áramot.
block.solar-panel-large.description = Napfényből állít elő kevés áramot. Hatékonyabb a szokásos napelemnél.
-block.thorium-reactor.description = Jelentős mennyiségű áramot állít elő tóriumból. Állandó hűtést igényel. Ha nincs megfelelően hűtőfolyadékkal ellátva, akkor felrobban.
-block.impact-reactor.description = Csúcsra járatva rengeteg áramot termel. A reakció beindítása jelentős árambefektetést igényel.
+block.thorium-reactor.description = Jelentős mennyiségű áramot termel tóriumból. Állandó hűtést igényel. Ha nincs megfelelően hűtőfolyadékkal ellátva, akkor felrobban.
+block.impact-reactor.description = Csúcsra járatva rengeteg áramot termel. A reakció beindítása jelentős áramfogyasztással jár.
block.mechanical-drill.description = Ércre helyezve lassú tempóban termeli ki az adott nyersanyagot. Csak alapvető nyersanyagok kitermelésére képes.
-block.pneumatic-drill.description = Egy fejlettebb fúró, mely titán kitermelésére is képes. Gyorsabban dolgozik a mechanikus fúrónál.
-block.laser-drill.description = Lézerek használatával még gyorsabban tud dolgozni, de áramot igényel. Képes tóriumot kitermelni.
-block.blast-drill.description = A technológia csúcsa. Nagy mennyiségű áramot igényel.
+block.pneumatic-drill.description = Egy olyan, fejlettebb fúró, amely titán kitermelésére is alkalmas. Gyorsabban dolgozik a mechanikus fúrónál.
+block.laser-drill.description = Lézerek használatával még gyorsabban tud dolgozni. Áramot fogyaszt. Képes tóriumot kitermelni.
+block.blast-drill.description = A technológia csúcsa. Nagy mennyiségű áramot fogyaszt.
block.water-extractor.description = Kiszivattyúzza a talajvizet. Olyan helyeken használatos, ahol nem érhető el felszíni vízforrás.
block.cultivator.description = A légkörben szálló spórákat kapszulákba sűríti.
block.cultivator.details = Visszaszerzett technológia. Hatalmas tömegű biomassza gyártására alkalmas a lehető leghatékonyabban. Valószínűleg a Serpulo felszínét ma borító spórák kezdeti inkubátora.
-block.oil-extractor.description = Nagy mennyiségű áramot, homokot és vizet használ, hogy olajat fúrjon.
+block.oil-extractor.description = Nagy mennyiségű áramot fogyaszt, továbbá homokot és vizet igényel az olajfúráshoz.
block.core-shard.description = Támaszpont. Ha elpusztul, a szektor elveszett.
block.core-shard.details = Az első modell. Kompakt. Önsokszorosító. Egyszer használatos gyorsítórakétákkal van felszerelve, nem bolygóközi utazásra tervezték.
block.core-foundation.description = Támaszpont. Jól páncélozott. Több nyersanyagot tárol, mint a Szilánk.
block.core-foundation.details = A második modell.
block.core-nucleus.description = Támaszpont. Rendkívül jól páncélozott. Hatalmas mennyiségű nyersanyag tárolására képes.
block.core-nucleus.details = A harmadik, végső modell.
-block.vault.description = Nagy mennyiséget tárol minden nyersanyagtípusból. Bővíti a raktárat, ha egy támaszpont mellé van helyezve. A tartalma kirakodó segítségével nyerhető ki.
-block.container.description = Kis mennyiséget tárol minden nyersanyagtípusból. Bővíti a raktárat, ha egy támaszpont mellé van helyezve. A tartalma kirakodó segítségével nyerhető ki.
+block.vault.description = Nagy mennyiséget tárol minden nyersanyagtípusból. Növeli a támaszpont tárolókapacitását, ha egy támaszpont mellé van helyezve. A tartalma kirakodó segítségével nyerhető ki.
+block.container.description = Kis mennyiséget tárol minden nyersanyagtípusból. Növeli a támaszpont tárolókapacitását, ha egy támaszpont mellé van helyezve. A tartalma kirakodó segítségével nyerhető ki.
block.unloader.description = Kirakodja a szomszédos épületekből a kiválasztott nyersanyagot.
block.launch-pad.description = Nyersanyagokat juttat el más szektorokba.
block.launch-pad.details = Szuborbitális rendszer a nyersanyagok szektorok között történő szállítására. A teherkapszulák törékenyek, ezért nem képesek túlélni a légkörbe való visszatérést.
@@ -2162,18 +2211,18 @@ block.cyclone.description = Robbanó lövedékeket lő közeli ellenségekre.
block.spectre.description = Nagy lövedékekkel tüzel légi és földi célpontokra.
block.meltdown.description = Feltöltődés után folyamatos lézersugarat lő a közeli ellenségekre. A működéséhez hűtőfolyadékot igényel.
block.foreshadow.description = Egy nagy villámot lő ki egy nagy távolságra lévő célpontra. A magasabb maximális életerővel rendelkező ellenségeket részesíti előnyben.
-block.repair-point.description = Folyamatosan javítja a legközelebbi sérült egységet a közelében.
+block.repair-point.description = Folyamatosan javítja a hatósugarában lévő legközelebbi sérült egységet.
block.segment.description = Megsemmisíti a beérkező lövedékeket. A lézerrel szemben hatástalan.
block.parallax.description = Vonónyalábot bocsát ki, amivel magához vonzza, és közben sebzi a légi egységeket.
block.tsunami.description = Erős folyadékhullámot lő az ellenségre. Eloltja a tüzeket, ha vízzel van ellátva.
-block.silicon-crucible.description = Szilíciumot finomít homokból és szénből, piratitot használ kiegészítő hőforrásként. Forró környezetben még hatékonyabb.
+block.silicon-crucible.description = Szilíciumot finomít homokból és szénből, piratitot igényel kiegészítő hőforrásként. Forró környezetben még hatékonyabb.
block.disassembler.description = Ritka ásványi összetevőire bontja le a salakot, alacsony hatékonysággal. Képes tóriumot kinyerni.
block.overdrive-dome.description = Megnöveli a környező épületek termelési sebességét. A működtetése tóritkvarcot és szilíciumot igényel.
block.payload-conveyor.description = Nagy méretű terhet mozgat, például gyárakból érkező egységeket. Mágneses. Használható súlytalanságban.
block.payload-router.description = Háromfelé osztja szét a beérkező terhet. Rendezőként is szolgál, ha van megadva szűrő. Mágneses. Használható súlytalanságban.
-block.ground-factory.description = Földi egységeket gyárt. Az elkészült egységek azonnal hadra foghatóak, vagy újratervezőkben továbbfejleszthetőek.
-block.air-factory.description = Légi egységeket gyárt. Az elkészült egységek azonnal hadra foghatóak, vagy újratervezőkben továbbfejleszthetőek.
-block.naval-factory.description = Vízi egységeket gyárt. Az elkészült egységek azonnal hadra foghatóak, vagy újratervezőkben továbbfejleszthetőek.
+block.ground-factory.description = Földi egységeket gyárt. Az elkészült egységek azonnal hadra foghatók, vagy újratervezőkben továbbfejleszthetők.
+block.air-factory.description = Légi egységeket gyárt. Az elkészült egységek azonnal hadra foghatók, vagy újratervezőkben továbbfejleszthetők.
+block.naval-factory.description = Vízi egységeket gyárt. Az elkészült egységek azonnal hadra foghatók, vagy újratervezőkben továbbfejleszthetők.
block.additive-reconstructor.description = Kettes szintre fejleszti a beérkező egységeket.
block.multiplicative-reconstructor.description = Hármas szintre fejleszti a beérkező egységeket.
block.exponential-reconstructor.description = Négyes szintre fejleszti a beérkező egységeket.
@@ -2187,7 +2236,7 @@ block.memory-bank.description = Információt tárol egy logikai processzor szá
block.logic-display.description = Tetszőleges ábrákat jelenít meg egy logikai processzor alapján.
block.large-logic-display.description = Tetszőleges ábrákat jelenít meg egy logikai processzor alapján.
block.interplanetary-accelerator.description = Hatalmas elektromágneses sínágyútorony. Képes a támaszpontokat szökési sebességre gyorsítani a bolygóközi bevetéshez.
-block.repair-turret.description = Folyamatosan javítja a közelében lévő legközelebbi sérült egységet. Opcionálisan elfogad hűtőfolyadékot.
+block.repair-turret.description = Folyamatosan javítja a hatósugarában lévő legközelebbi sérült egységet. Opcionálisan elfogad hűtőfolyadékot.
#Erekir
block.core-bastion.description = Támaszpont. Páncélozott. Ha elpusztul, a szektor elveszett.
@@ -2205,23 +2254,25 @@ block.smite.description = Átütő erejű, villámló lövedékeket lő ki.
block.malign.description = Lézertöltetekből álló célzott sortüzet zúdít az ellenséges célpontokra. Jelentős fűtést igényel.
block.silicon-arc-furnace.description = A homokot és a grafitot szilíciummá finomítja.
block.oxidation-chamber.description = A berilliumot és az ózont oxiddá alakítja. Melléktermékként hőt bocsát ki.
-block.electric-heater.description = Fűti a vele szemben álló épületeket. Nagy mennyiségű áramot igényel.
+block.electric-heater.description = Fűti a vele szemben álló épületeket. Nagy mennyiségű áramot fogyaszt.
block.slag-heater.description = Fűti a vele szemben álló épületeket. Salakot igényel.
block.phase-heater.description = Fűti a vele szemben álló épületeket. Tóritkvarcot igényel.
block.heat-redirector.description = Más blokkokba irányítja a felgyülemlett hőt.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = A felgyülemlett hőt három kimeneti irányba osztja.
-block.electrolyzer.description = A vizet hidrogénné és ózonná alakítja. A keletkező gázokat két ellentétes irányba adja ki, melyeket a megfelelő színek jelölik.
+block.electrolyzer.description = A vizet hidrogénné és ózonná alakítja. A keletkező gázokat két ellentétes irányba adja ki, amelyek a megfelelő színnel vannak jelölve.
block.atmospheric-concentrator.description = Koncentrálja a légkörben lévő nitrogént. Hőt igényel.
block.surge-crucible.description = Salakból és szilíciumból elektrometált olvaszt. Hőt igényel.
block.phase-synthesizer.description = Tóriumból, homokból és ózonból tóritkvarcot szintetizál. Hőt igényel.
block.carbide-crucible.description = A grafitot és a volfrámot karbiddá olvasztja. Hőt igényel.
block.cyanogen-synthesizer.description = Arkicitből és grafitból diciánt szintetizál. Hőt igényel.
block.slag-incinerator.description = Elégeti a nem illékony nyersanyagokat vagy folyadékokat. Salakot igényel.
-block.vent-condenser.description = A kürtőkből kiáramló gázokat vízzé kondenzálja. Áramot igényel.
-block.plasma-bore.description = Ércfallal szemben elhelyezve, korlátlanul termel nyersanyagokat. Kis mennyiségű áramot igényel.\nHidrogén felhasználásával növelhető a hatékonysága.
-block.large-plasma-bore.description = Egy nagyobb plazmafúró. Képes a volfrám és a tórium bányászatára. Hidrogént és áramot igényel.\nNitrogén felhasználásával növelhető a hatékonysága.
-block.cliff-crusher.description = Felőrli a falakat, és korlátlan mennyiségű homokot termel. Áramot igényel. A hatékonysága a fal típusától függően változik.
-block.impact-drill.description = Ha ércre helyezik, korlátlan ideig, sorozatokban termeli ki a nyersanyagokat. Áramot és vizet igényel.
+block.vent-condenser.description = A kürtőkből kiáramló gázokat vízzé kondenzálja. Áramot fogyaszt.
+block.plasma-bore.description = Ércfallal szemben elhelyezve, korlátlanul termel nyersanyagokat. Kis mennyiségű áramot fogyaszt.\nHidrogén felhasználásával növelhető a hatékonysága.
+block.large-plasma-bore.description = Egy nagyobb plazmafúró. Képes a volfrám és a tórium bányászatára. Hidrogént igényel és áramot fogyaszt.\nNitrogén felhasználásával növelhető a hatékonysága.
+block.cliff-crusher.description = Felőrli a falakat, és korlátlan mennyiségű homokot termel. Áramot fogyaszt. A hatékonysága a fal típusától függően változik.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
+block.impact-drill.description = Ha ércre helyezik, korlátlan ideig, sorozatokban termeli ki a nyersanyagokat. Áramot fogyaszt és vizet igényel.
block.eruption-drill.description = Továbbfejlesztett ütvefúró. Képes tóriumot bányászni. Hidrogént igényel.
block.reinforced-conduit.description = Előre szállítja a folyadékokat. Nem fogad nem csővezetékes bemeneteket oldalról.
block.reinforced-liquid-router.description = Egyenletesen osztja el a folyadékokat minden oldalra.
@@ -2237,18 +2288,18 @@ block.carbide-wall.description = Megvédi az építményeket az ellenséges löv
block.carbide-wall-large.description = Megvédi az építményeket az ellenséges lövedékektől.
block.reinforced-surge-wall.description = Megvédi az építményeket az ellenséges lövedékektől, a lövedékekkel való érintkezésekor időszakosan elektromos íveket bocsát ki.
block.reinforced-surge-wall-large.description = Megvédi az építményeket az ellenséges lövedékektől, a lövedékekkel való érintkezésekor időszakosan elektromos íveket bocsát ki.
-block.shielded-wall.description = Megvédi az építményeket az ellenséges lövedékektől. Olyan pajzsot képez, amely a legtöbb lövedéket elnyeli, ha az áramellátás biztosítva van. Vezeti az áramot.
+block.shielded-wall.description = Megvédi az építményeket az ellenséges lövedékektől. Olyan erőpajzsot képez, amely a legtöbb lövedéket elnyeli, ha az áramellátás biztosítva van. Vezeti az áramot.
block.blast-door.description = Egy fal, amely kinyílik, ha szövetséges földi egységek vannak a közelében. Kézzel nem irányítható.
block.duct.description = Előre mozgatja a nyersanyagokat. Csak egyetlen nyersanyag tárolására alkalmas.
block.armored-duct.description = Előre mozgatja a nyersanyagokat. Csak szállítószalagos bemeneteket fogad el oldalról.
-block.duct-router.description = A nyersanyagokat egyenlően osztja el három irányba. Csak hátulról fogad el nyersanyagokat. Nyersanyagválogatóként is beállítható.
+block.duct-router.description = A nyersanyagokat egyenlően osztja el három irányba. Csak hátulról fogad el nyersanyagokat. Nyersanyag-válogatóként is beállítható.
block.overflow-duct.description = Csak akkor ad ki nyersanyagot oldalra, ha előrefelé már nem tud.
block.duct-bridge.description = Nyersanyagokat szállít épületek és terepakadályok fölött.
block.duct-unloader.description = A kiválasztott nyersanyagokat kirakodja a mögötte lévő épületekből. Támaszpontokból nem tud kirakodni.
-block.underflow-duct.description = A túlcsorduló szállítószalag ellentettje. Csak akkor ad ki nyersanyagot előrefelé, ha oldalra már nem tud.
+block.underflow-duct.description = A túlcsorduló kapu ellentettje. Csak akkor ad ki nyersanyagot előrefelé, ha oldalra már nem tud.
block.reinforced-liquid-junction.description = Csomópontként működik két egymást keresztező csővezeték között.
block.surge-conveyor.description = A nyersanyagokat rakományokban mozgatja. Árammal felgyorsítható. Vezeti az áramot.
-block.surge-router.description = Egyenletesen osztja el a nyersanyagokat három irányba az elektrometál-szállítószalagról. Árammal felgyorsítható. Vezeti az Áramot.
+block.surge-router.description = Egyenletesen osztja el a nyersanyagokat három irányba az elektrometál-szállítószalagról. Árammal felgyorsítható. Vezeti az áramot.
block.unit-cargo-loader.description = Teherszállító drónokat épít. A drónok automatikusan szétosztják a nyersanyagokat a megfelelő szűrővel rendelkező kirakodási pontokra.
block.unit-cargo-unload-point.description = A teherszállító drónok kirakodási pontjaként működik. Csak a kiválasztott szűrőnek megfelelő nyersanyagokat fogadja be.
block.beam-node.description = Merőlegesen áramot vezet a többi blokkhoz. Kis mennyiségű áramot tárol.
@@ -2262,9 +2313,9 @@ block.build-tower.description = Automatikusan újjáépíti a hatósugarában l
block.regen-projector.description = Lassan javítja a szövetséges építményeket egy négyzet alakú területen. Hidrogént igényel.\nTóritkvarc felhasználásával növelhető a hatékonysága.
block.reinforced-container.description = Kis mennyiségű nyersanyagot tud tárolni. A tartalma kirakodók segítségével nyerhető ki. Nem növeli a támaszpont tárolókapacitását.
block.reinforced-vault.description = Nagy mennyiségű nyersanyagot tud tárolni. A tartalma kirakodók segítségével nyerhető ki. Nem növeli a támaszpont tárolókapacitását.
-block.tank-fabricator.description = Stell egységeket épít. Az elkészült egységek azonnal hadra foghatóak, vagy újratervezőkben továbbfejleszthetőek.
-block.ship-fabricator.description = Elude egységeket épít. Az elkészült egységek azonnal hadra foghatóak, vagy újratervezőkben továbbfejleszthetőek.
-block.mech-fabricator.description = Merui egységeket épít. Az elkészült egységek azonnal hadra foghatóak, vagy újratervezőkben továbbfejleszthetőek.
+block.tank-fabricator.description = Stell egységeket épít. Az elkészült egységek azonnal hadra foghatók, vagy újratervezőkben továbbfejleszthetők.
+block.ship-fabricator.description = Elude egységeket épít. Az elkészült egységek azonnal hadra foghatók, vagy újratervezőkben továbbfejleszthetők.
+block.mech-fabricator.description = Merui egységeket épít. Az elkészült egységek azonnal hadra foghatók, vagy újratervezőkben továbbfejleszthetők.
block.tank-assembler.description = Nagy méretű tankokat állít össze a beadott blokkokból és egységekből. A kimeneti szint modulok hozzáadásával növelhető.
block.ship-assembler.description = Nagy méretű repülőgépeket állít össze a beadott blokkokból és egységekből. A kimeneti szint modulok hozzáadásával növelhető.
block.mech-assembler.description = Nagy méretű mecheket állít össze a beadott blokkokból és egységekből. A kimeneti szint modulok hozzáadásával növelhető.
@@ -2272,14 +2323,14 @@ block.tank-refabricator.description = Kettes szintre fejleszti a beérkező tank
block.ship-refabricator.description = Kettes szintre fejleszti a beérkező repülőgép típusú egységeket.
block.mech-refabricator.description = Kettes szintre fejleszti a beérkező mech típusú egységeket.
block.prime-refabricator.description = Hármas szintre fejleszti a beérkező tank típusú egységeket.
-block.basic-assembler-module.description = Növeli az összeszerelő szintjét, ha annak az építési határvonala mellé helyezik. Áramot igényel. Használható nyersanyagrakomány-bemenetként.
+block.basic-assembler-module.description = Növeli az összeszerelő szintjét, ha annak az építési határvonala mellé helyezik. Áramot fogyaszt. Használható nyersanyagrakomány-bemenetként.
block.small-deconstructor.description = Lebontja a beadott építményeket és egységeket. Visszaadja az építési költség 100%-át.
block.reinforced-payload-conveyor.description = Előre mozgatja a rakományokat.
block.reinforced-payload-router.description = A rakományokat szomszédos a blokkokba osztja szét. Szűrő beállítása esetén válogatóként működik.
block.payload-mass-driver.description = Nagy hatótávolságú rakományszállító épület. A kapott rakományokat egy másik, hozzákapcsolt rakomány-tömegmozgatónak lövi át.
block.large-payload-mass-driver.description = Nagy hatótávolságú rakományszállító épület. A kapott rakományokat egy másik, hozzákapcsolt rakomány-tömegmozgatónak lövi át.
block.unit-repair-tower.description = Javítja a közelében lévő összes egységet. Ózont igényel.
-block.radar.description = Fokozatosan feltárja a terepet és az ellenséges egységeket egy nagy sugarú körben. Áramot igényel.
+block.radar.description = Fokozatosan feltárja a terepet és az ellenséges egységeket egy nagy sugarú körben. Áramot fogyaszt.
block.shockwave-tower.description = Sérülést okoz és megsemmisíti az ellenséges lövedékeket egy körön belül. Diciánt igényel.
block.canvas.description = Egy egyszerű képet jelenít meg egy előre meghatározott palettával. Szerkeszthető.
@@ -2290,7 +2341,7 @@ unit.scepter.description = Töltött lövedékek záporát lövi közeli ellens
unit.reign.description = Méretes átütő erejű lövedékeket zúdít minden közeli ellenségre.
unit.nova.description = Lézerlövedékeket lő ki, amelyek sebzik az ellenséges célpontokat, és megjavítják a szövetséges épületeket. Repülésre alkalmas.
unit.pulsar.description = Elektromos szikrákat szór, amelyek sebzik az ellenséges célpontokat, és megjavítják a szövetséges épületeket. Repülésre alkalmas.
-unit.quasar.description = Átütő erejű lézersugarakat lő, amelyek sebzik az ellenséges célpontokat, és megjavítják a szövetséges épületeket. Repülésre alkalmas. Pajzsa van.
+unit.quasar.description = Átütő erejű lézersugarakat lő, amelyek sebzik az ellenséges célpontokat, és megjavítják a szövetséges épületeket. Repülésre alkalmas. Erőpajzsa van.
unit.vela.description = Folyamatos lézernyalábot bocsát ki, amelyek sebzik az ellenséges célpontokat, tüzet okoznak, és megjavítják a szövetséges épületeket. Repülésre alkalmas.
unit.corvus.description = Hatalmas lézersugarat lő, amelyek sebzik az ellenséges célpontokat, és megjavítják a szövetséges épületeket. Átlépi a legtöbb terepakadályt.
unit.crawler.description = Az ellenséghez rohan és megsemmisíti önmagát, nagy robbanást okozva.
@@ -2304,10 +2355,10 @@ unit.zenith.description = Rakétasorozatokat lő közeli ellenségekre.
unit.antumbra.description = Lövedékek záporát zúdítja minden közeli ellenségre.
unit.eclipse.description = Két átütő erejű lézersugarat és rengeteg lövedéket zúdít minden közeli ellenségre.
unit.mono.description = Automatikusan rezet és ólmot bányászik, a támaszpontba juttatva őket.
-unit.poly.description = Automatikusan újjáépíti az elpusztult épületeket és segít más egységeknek az építkezésben.
-unit.mega.description = Automatikusan javítja a sérült épületeket. Kis blokkok és földi egységek szállítására képes.
-unit.quad.description = Plazmabombákat szór földi célpontokra, amelyek sebzik az ellenséget, de javítják a szövetséges épületeket. Közepes méretű földi egységek szállítására képes.
-unit.oct.description = Megvédi a közeli szövetségeseket egy regeneráló pajzssal. A legtöbb földi egység szállítására képes.
+unit.poly.description = Automatikusan újjáépíti a lerombolt épületeket és segít más egységeknek az építkezésben.
+unit.mega.description = Automatikusan javítja a sérült épületeket. Kis blokkok és földi egységek szállítására is alkalmas.
+unit.quad.description = Plazmabombákat szór földi célpontokra, amelyek sebzik az ellenséget, de javítják a szövetséges épületeket. Közepes méretű földi egységek szállítására is alkalmas.
+unit.oct.description = Megvédi a közeli szövetségeseket egy regeneráló pajzzsal. A legtöbb földi egység szállítására is alkalmas.
unit.risso.description = Rakéták és lövedékek záporát zúdítja minden közeli ellenségre.
unit.minke.description = Tüzérségi és szokásos lövedékeket lő közeli földi célpontokra.
unit.bryde.description = Nagy távolságú tüzérségi lövedékeket és rakétákat lő az ellenségre.
@@ -2315,11 +2366,11 @@ unit.sei.description = Rakéták és páncéltörő lövedékek záporát zúdí
unit.omura.description = Nagy hatótávolságú átütő erejű lövedékeket lő az ellenségre. Flare egységeket gyárt.
unit.alpha.description = Megvédi a Szilánk támaszpontot az ellenségtől. Épületeket épít.
unit.beta.description = Megvédi az Alapítvány támaszpontot az ellenségtől. Épületeket épít.
-unit.gamma.description = Megvédi at Atommag támaszpontot az ellenségtől. Épületeket épít.
+unit.gamma.description = Megvédi az Atommag támaszpontot az ellenségtől. Épületeket épít.
unit.retusa.description = Célkövető torpedókat lő ki minden közeli ellenségre. Javítja a szövetséges egységeket.
unit.oxynoe.description = Épületjavító lángcsóvát lő az ellenséges célpontokra. Célba veszi az ellenséges lövedékeket egy pontvédelmi toronnyal.
unit.cyerce.description = Célkereső kazettás rakétákat lő ki az ellenségre. Javítja a szövetséges egységeket.
-unit.aegires.description = Elektromosan sokkolja az összes ellenséges egységet és építményt, amely az energiamezőjébe lép. Javítja az összes szövetségest.
+unit.aegires.description = Elektromosan sokkolja az összes ellenséges egységet és építményt, amely az energiamezejébe lép. Javítja az összes szövetségest.
unit.navanax.description = Robbanékony EMI-lövedékeket lő ki, jelentős károkat okozva az ellenséges energiahálózatokban, és megjavítva a szövetségesek építményeit. Szétolvasztja a közeli ellenséges célpontokat a 4 autonóm lézertornyával.
#Erekir
@@ -2338,14 +2389,14 @@ unit.avert.description = Forgó lövedékpárokat lő ki az ellenséges célpont
unit.obviate.description = Forgó, páros villámgömböket lő ki az ellenséges célpontokra.
unit.quell.description = Nagy hatótávolságú célkövető rakétát lő ki az ellenséges célpontokra. Elnyomja az ellenséges szerkezetjavító épületeket. Csak földi célpontokat támad.
unit.disrupt.description = Nagy hatótávolságú célkövető elnyomó rakétát lő ki az ellenséges célpontokra. Elnyomja az ellenséges szerkezetjavító épületeket. Csak földi célpontokat támad.
-unit.evoke.description = A Bástya védelmére szolgáló építményeket épít. Sugárral javítja az építményeket. 2×2-es épületek szállítására képes.
-unit.incite.description = A Citadella védelmére szolgáló építményeket épít. Sugárral javítja az építményeket. 2×2-es épületek szállítására képes.
-unit.emanate.description = Az Akropolisz védelmére szolgáló építményeket épít. Sugárral javítja az építményeket. 2×2-es épületek szállítására képes.
+unit.evoke.description = A Bástya védelmére szolgáló építményeket épít. Sugárral javítja az építményeket. 2×2-es épületek szállítására is alkalmas.
+unit.incite.description = A Citadella védelmére szolgáló építményeket épít. Sugárral javítja az építményeket. 2×2-es épületek szállítására is alkalmas.
+unit.emanate.description = Az Akropolisz védelmére szolgáló építményeket épít. Sugárral javítja az építményeket. 2×2-es épületek szállítására is alkalmas.
lst.read = Szám kiolvasása egy összekapcsolt memóriacellából.
lst.write = Szám beírása egy összekapcsolt memóriacellába.
-lst.print = Szöveg hozzáadása a nyomtatási pufferhez.\nA [accent]Print Flush[] használatáig nem jelenít meg semmit.
-lst.format = A szövegpufferben lévő következő helyőrző cseréje egy értékre.\nNem csinál semmit, ha a helyőrzőminta érvénytelen.\nHelyőrzőminta: "{[accent]number 0-9[]}"\nPélda:\n[accent]print "test {0}"\nformat "example"
+lst.print = Szöveg hozzáadása a kiírási pufferhez.\nA [accent]Print Flush[] használatáig nem jelenít meg semmit.
+lst.format = A szövegpufferben lévő következő helyőrző cseréje egy értékre.\nNem csinál semmit, ha a helyőrzőminta érvénytelen.\nHelyőrzőminta: „{[accent]number 0-9[]}”\nPélda:\n[accent]print „test {0}”\nformat „example”
lst.draw = Művelet hozzáadása a rajzpufferhez.\nA [accent]Draw Flush[] használatáig nem jelenít meg semmit.
lst.drawflush = Sorba állított [accent]Draw[] műveletek megjelenítése a kijelzőn.
lst.printflush = Sorba állított [accent]Print[] műveletek kiírása egy üzenetblokkba.
@@ -2364,8 +2415,8 @@ lst.unitbind = Összekapcsolás a következő egységtípussal, és tárolás a
lst.unitcontrol = A jelenleg összekapcsolt egység vezérlése.
lst.unitradar = Egységek keresése a jelenleg összekapcsolt egység körül.
lst.unitlocate = Egy adott típusú pozíció/épület keresése bárhol a pályán.\nÖsszekapcsolt egységet igényel.
-lst.getblock = Csempeadatok lekérdezése tetszőleges helyen.
-lst.setblock = Csempeadatok beállítása tetszőleges helyen.
+lst.getblock = Mezőadatok lekérdezése tetszőleges helyen.
+lst.setblock = Mezőadatok beállítása tetszőleges helyen.
lst.spawnunit = Egység lerakása az adott helyen.
lst.applystatus = Állapothatás alkalmazása vagy törlése egy egységről.
lst.weathersense = Ellenőrzés, hogy egy bizonyos típusú időjárás aktív-e.
@@ -2376,33 +2427,34 @@ lst.setrate = A processzor végrehajtási sebességének beállítása utasítá
lst.fetch = Egységek, támaszpontok, játékosok, vagy épületek keresése index szerint.\nAz indexek 0-tól indulnak és a visszaadott számuknál végződnek.
lst.packcolor = Egyetlen számba tömöríti a [0, 1] RGBA komponenseket a rajzoláshoz vagy szabálymeghatározáshoz.
lst.setrule = Játékszabály beállítása.
-lst.flushmessage = Üzenet megjelenítése a képernyőn a szövegpufferből.\nMegvárja, amíg az előző üzenet befejeződik.
+lst.flushmessage = Üzenet megjelenítése a képernyőn a szövegpufferből. Ha a sikeres válasz változója [accent]@wait[],\nakkor, megvárja, amíg az előző üzenet befejeződik.\nMáskülönben azt adja ki, hogy az üzenet megjelenítése sikeres volt-e.
lst.cutscene = A játékos kamerájának mozgatása.
lst.setflag = Egy globális jelölő beállítása, amely minden processzor által olvasható.
lst.getflag = Ellenőrzés, hogy egy globális jelölő be van-e állítva.
lst.setprop = Beállítja egy egység vagy épület tulajdonságát.
lst.effect = Részecskehatás létrehozása.
lst.sync = Egy változó szinkronizálása a hálózaton keresztül.\nMásodpercenként legfeljebb 20-szor hívható meg.
+lst.playsound = Egy hangot játszik le.\nA hangerő és a panoráma lehet globális érték, vagy a pozíció alapján kiszámított érték.
lst.makemarker = Új logikai jelölő létrehozása a világban.\nMeg kell adni egy azonosítót a jelölő azonosításához.\nA jelölők száma jelenleg világonként 20 000-re van korlátozva.
lst.setmarker = Egy jelölő tulajdonságának beállítása.\nA használt azonosítónak meg kell egyeznie a Make Marker utasításban megadottal.\nA [accent]null []értékek figyelmen kívül lesznek hagyva.
-lst.localeprint = Hozzáadja a pálya nyelvi csomagjainak tulajdonságértékét a szövegpufferhez.\nA pálya nyelvi csomagjainak beállításait a térképszerkesztőben ellenőrizheted: [accent]Pályainformációk > Nyelvi csomagok[].\nHa a kliens egy mobileszköz, akkor először próbáld kiíratni a „.mobile” végződésű tulajdonságot.
+lst.localeprint = Hozzáadja a pálya nyelvi csomagjainak tulajdonságértékét a szövegpufferhez.\nA pálya nyelvi csomagjainak beállításait a térképszerkesztőben ellenőrizheted: [accent]pályainformációk > nyelvi csomagok[].\nHa a kliens egy hordozható eszköz, akkor először próbáld kiíratni a „.mobile” végződésű tulajdonságot.
lglobal.false = 0
lglobal.true = 1
lglobal.null = null
-lglobal.@pi = A pí matematikai állandó (3.141...)
+lglobal.@pi = A pi matematikai állandó (3.141...)
lglobal.@e = Az e matematikai állandó (2.718...)
lglobal.@degToRad = Ezzel a számmal szoroz a fok radiánra való átalakításához
lglobal.@radToDeg = Ezzel a számmal szoroz a radián fokra való átalakításához
-lglobal.@time = A jelenelgi mentés játékideje ezredmásodpercben
+lglobal.@time = A jelenlegi mentés játékideje ezredmásodpercben
lglobal.@tick = Az aktuális mentés játékideje, órajelciklusban (1 másodperc = 60 órajelciklus)
-lglobal.@second = A jelenelgi mentés játékideje másodpercben
-lglobal.@minute = A jelenelgi mentés játékideje percben
+lglobal.@second = A jelenlegi mentés játékideje másodpercben
+lglobal.@minute = A jelenlegi mentés játékideje percben
lglobal.@waveNumber = A jelenlegi hullám száma, ha a hullámok engedélyezve vannak
lglobal.@waveTime = Visszaszámláló a hullámokhoz, másodpercben
-lglobal.@mapw = A pálya szélessége csempékben
-lglobal.@maph = A pálya magassága csempékben
+lglobal.@mapw = A pálya szélessége mezőben
+lglobal.@maph = A pálya magassága mezőben
lglobal.sectionMap = Pálya
lglobal.sectionGeneral = Általános
@@ -2428,7 +2480,7 @@ lglobal.@clientLocale = A kódot futtató kliens területi beállítása. Péld
lglobal.@clientUnit = A kódot futtató kliens egysége
lglobal.@clientName = A kódot futtató kliens játékosneve
lglobal.@clientTeam = A kódot futtató kliens csapatazonosítója
-lglobal.@clientMobile = Igaz, ha a kódot futtató kliens egy mobil eszköz, egyébként hamis
+lglobal.@clientMobile = Igaz, ha a kódot futtató kliens egy hordozható eszköz, egyébként hamis
logic.nounitbuild = [red]Az egységépítési logika itt nem megengedett.
@@ -2441,10 +2493,10 @@ laccess.currentammotype = Egy lövegtorony jelenlegi lőszer nyersanyaga/folyad
laccess.color = Megvilágítás színe.
laccess.controller = Egységvezérlő. Ha processzor vezérli, akkor a processzort adja vissza.\nKülönben magát az egységet adja vissza.
-laccess.dead = Egy épület/egység halott-e, vagy már nem érvényes-e.
+laccess.dead = Egy épület/egység megsemmisült-e, vagy érvénytelen-e.
laccess.controlled = Ezt adja vissza:\n[accent]@ctrlProcessor[], ha az egységvezérlő egy processzor\n[accent]@ctrlPlayer[], ha az egység/épület vezérlője a játékos\n[accent]@ctrlFormation[], ha az egység formációban van\nKülönben 0.
laccess.progress = Művelet előrehaladása, 0 és 1 között.\nA termelés, a lövegtorony-újratöltés vagy az építés előrehaladását adja vissza.
-laccess.speed = Az egység legnagyobb sebessége, csempe/mp-ben.
+laccess.speed = Az egység legnagyobb sebessége, mező/mp-ben.
laccess.id = Egy egység/blokk/nyersanyag/folyadék azonosítója.\nEz a keresési művelet fordítottja.
lcategory.unknown = Ismeretlen
@@ -2473,7 +2525,7 @@ graphicstype.poly = Egy szabályos sokszög kitöltése.
graphicstype.linepoly = Szabályos sokszög körvonalának rajzolása.
graphicstype.triangle = Egy háromszög kitöltése.
graphicstype.image = Kép rajzolása valamilyen tartalomról.\nPéldául: [accent]@router[] vagy [accent]@dagger[].
-graphicstype.print = Szöveget rajzol a kiírási pufferből.\nCsak ASCII karakterek használhatóak.\nTörli a kiírás puffert.
+graphicstype.print = Szöveget rajzol a kiírási pufferből.\nCsak ASCII karakterek használhatók.\nTörli a kiírás puffert.
lenum.always = Mindig igaz.
lenum.idiv = Egész osztás.
@@ -2504,7 +2556,7 @@ lenum.asin = Arkusz szinusz, fokban.
lenum.acos = Arkusz koszinusz, fokban.
lenum.atan = Arkusz tangens, fokban.
-#not a typo, look up 'range notation'
+#Az alábbi zárójel nem elírás, nézz utána a „nyitott/zárt intervallum/tartomány jelöléseknek”
lenum.rand = Véletlenszerű decimális szám a [0, érték) tartományban.
lenum.log = Természetes logaritmus (ln).
lenum.log10 = 10-es alapú logaritmus.
@@ -2527,12 +2579,12 @@ lenum.spawn = Ellenséges kezdőpont.\nLehet támaszpont vagy pozíció.
lenum.building = Épület egy adott csoportban.
lenum.core = Bármilyen támaszpont.
-lenum.storage = Raktárépület, például tároló.
+lenum.storage = Raktárépület, például raktár.
lenum.generator = Energiát termelő épületek.
lenum.factory = Nyersanyagokat feldolgozó épületek.
lenum.repair = Javítási pontok.
lenum.battery = Bármilyen akkumulátor.
-lenum.resupply = Utánpótlási pontok.\nCsak akkor van jelentősége, ha az [accent]„egység lőszere”[] engedélyezve van.
+lenum.resupply = Utánpótlási pontok.\nCsak akkor van jelentősége, amikor az [accent]„egység lőszere”[] engedélyezve van.
lenum.reactor = Ütközéses- vagy tóriumerőmű.
lenum.turret = Bármilyen lövegtorony.
@@ -2562,9 +2614,11 @@ unitlocate.outx = Kimenet X koordinátája.
unitlocate.outy = Kimenet Y koordinátája.
unitlocate.group = Keresendő épületcsoport.
+playsound.limit = Ha igaz, megakadályozza a hang lejátszását,\nha már lejátszották ugyanabban a keretben.
+
lenum.idle = Ne mozdulj, de folytasd az építkezést/bányászatot.\nAz alapértelmezett állapot.
lenum.stop = Mozgás/bányászás/építés leállítása.
-lenum.unbind = A logikai vezérlés teljes kikapcsolása.\nSzokásos mesterséges intelligencia folytatása.
+lenum.unbind = A logikai vezérlés teljes kikapcsolása.\nA szokásos mesterséges intelligencia használatának folytatása.
lenum.move = Mozgás a pontos pozícióba.
lenum.approach = Egy pozíció megközelítése egy sugárral.
lenum.pathfind = Útkeresés a megadott pozícióhoz.
@@ -2585,7 +2639,7 @@ lenum.boost = Erősítés indítása/leállítása.
lenum.flushtext = Az írási puffer tartalmának ürítése a jelölőre, ha alkalmazható.\nHa a „fetch” igaz, akkor megpróbálja lekérni a tulajdonságokat a pálya nyelvi csomagjából vagy a játék csomagjából.
lenum.texture = A textúra neve közvetlenül a játék textúraatlaszából (ún. kebab-case elnevezési stílus használatával).\nHa a „printFlush” igaz, akkor a szöveges puffer tartalmát használja szöveges argumentumként.
-lenum.texturesize = A textúra mérete csempékben. A nulla érték a jelölő szélességét az eredeti textúra méretére skálázza.
+lenum.texturesize = A textúra mérete mezőben. A nulla érték a jelölő szélességét az eredeti textúra méretére skálázza.
lenum.autoscale = Skálázva legyen-e a jelölő a játékos nagyítási szintjének megfelelően.
lenum.posi = Indexelt pozíció, vonal- és négyszögjelzőkhöz használatos, ahol a nulla az első pozíció.
lenum.uvi = A textúra pozíciója nullától egyig, négyzetjelölőkhöz használatos.
diff --git a/core/assets/bundles/bundle_id_ID.properties b/core/assets/bundles/bundle_id_ID.properties
index 9c058872ca..15651bba05 100644
--- a/core/assets/bundles/bundle_id_ID.properties
+++ b/core/assets/bundles/bundle_id_ID.properties
@@ -2,10 +2,10 @@ credits.text = Diciptakan oleh [royal]Anuken[] - [sky]anukendev@gmail.com[]
credits = Kredit
contributors = Penerjemah dan Kontributor
discord = Bergabung di Discord Mindustry!
-link.discord.description = Discord Mindustry Resmi
+link.discord.description = Discord Mindustry resmi
link.reddit.description = Subreddit Mindustry
-link.github.description = Sumber Kode Permainan
-link.changelog.description = Daftar Rekam Pembaruan
+link.github.description = Sumber kode permainan
+link.changelog.description = Daftar rekam pembaruan
link.dev-builds.description = Bentuk pengembangan kurang stabil
link.trello.description = Papan Trello resmi untuk fitur terencana
link.itch.io.description = Halaman itch.io dengan unduhan PC
@@ -15,8 +15,8 @@ link.wiki.description = Wiki Mindustry resmi
link.suggestions.description = Saran fitur baru
link.bug.description = Menemukan bug? Laporkan di sini
linkopen = Server ini mengirimkan Anda sebuah tautan. Apakah Anda yakin ingin membukanya?\n\n[sky]{0}
-linkfail = Gagal membuka tautan!\nURL disalin ke papan salin.
-screenshot = Tangkapan layar disimpan di {0}
+linkfail = Gagal membuka tautan!\nURL disalin ke papan klip.
+screenshot = Tangkapan layar tersimpan di {0}
screenshot.invalid = Peta terlalu besar, tidak cukup memori untuk menangkap layar.
gameover = Permainan Selesai
gameover.disconnect = Jaringan Terputus
@@ -24,7 +24,7 @@ gameover.pvp = Tim[accent] {0}[] menang!
gameover.waiting = [accent]Menunggu peta selanjutnya...
highscore = [accent]Rekor baru!
copied = Tersalin.
-indev.notready = Bagian tersebut saat ini belum siap
+indev.notready = Bagian permainan saat ini belum siap
load.sound = Suara
load.map = Peta
@@ -35,11 +35,11 @@ load.mod = Mod
load.scripts = Skrip
be.update = Versi Bleeding Edge terbaru tersedia:
-be.update.confirm = Unduh dan ulang kembali sekarang?
+be.update.confirm = Unduh dan mulai ulang sekarang?
be.updating = Memperbarui...
be.ignore = Abaikan
be.noupdates = Tidak ada pembaruan yang ditemukan.
-be.check = Cek versi baru
+be.check = Periksa pembaruan
mods.browser = Browser Mod
mods.browser.selected = Mod yang Dipilih
@@ -47,49 +47,49 @@ mods.browser.add = Pasang mod
mods.browser.reinstall = Pasang kembali
mods.browser.view-releases = Lihat Rilis
mods.browser.noreleases = [scarlet]Tidak Ada Rilis Ditemukan\n[accent]Tidak dapat menemukan rilis untuk mod ini. Periksa apakah repositori mod memiliki rilis publik.
-mods.browser.latest =
+mods.browser.latest = [lightgray][Terbaru]
mods.browser.releases = Rilis
mods.github.open = Repo
mods.github.open-release = Laman Rilis
mods.browser.sortdate = Urut berdasarkan waktu
mods.browser.sortstars = Urut berdasarkan bintang
-schematic = Bagan
-schematic.add = Menyimpan bagan...
-schematics = Kumpulan bagan
-schematic.search = Search schematics...
-schematic.replace = Bagan dengan nama tersebut sudah ada. Ganti dengan yang baru?
-schematic.exists = Sebuah bagan dengan nama tersebut sudah ada.
-schematic.import = Mengimpor bagan...
-schematic.exportfile = Ekspor File
-schematic.importfile = Impor File
+schematic = Skema
+schematic.add = Menyimpan skema...
+schematics = Kumpulan skema
+schematic.search = Cari skema...
+schematic.replace = Skema dengan nama tersebut sudah ada. Ganti dengan yang baru?
+schematic.exists = Skema dengan nama tersebut sudah ada.
+schematic.import = Mengimpor skema...
+schematic.exportfile = Ekspor Berkas
+schematic.importfile = Impor Berkas
schematic.browseworkshop = Cari di Workshop
schematic.copy = Salin ke papan klip
schematic.copy.import = Impor dari papan klip
schematic.shareworkshop = Bagikan di Workshop
-schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Balik Bagan
-schematic.saved = Bagan telah disimpan.
-schematic.delete.confirm = Bagan ini akan benar-benar dihapus.
-schematic.edit = Edit Schematic
+schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Balik Skema
+schematic.saved = Skema telah disimpan.
+schematic.delete.confirm = Skema ini akan benar-benar dihapus.
+schematic.edit = Sunting Skema
schematic.info = {0}x{1}, {2} blok
-schematic.disabled = [scarlet]Bagan dilarang[]\nAnda tidak diperbolehkan untuk menggunakan bagan di [accent]peta[] atau [accent]server ini.
+schematic.disabled = [scarlet]Skema dimatikan[]\nPenggunaan skema tidak diperbolehkan di [accent]peta[] atau [accent]server[] ini.
schematic.tags = Tanda:
schematic.edittags = Ubah Tanda
schematic.addtag = Tambah Tanda
-schematic.texttag = Teks Tanda
-schematic.icontag = Ikon Tanda
+schematic.texttag = Tanda Teks
+schematic.icontag = Tanda Ikon
schematic.renametag = Ubah Nama Tanda
-schematic.tagged = {0} tagged
-schematic.tagdelconfirm = Hapus tanda ini sepenuhnya?
+schematic.tagged = {0} ditandai
+schematic.tagdelconfirm = Ingin menghapus tanda ini?
schematic.tagexists = Tanda tersebut sudah ada.
stats = Statistik
stats.wave = Gelombang Terkalahkan
stats.unitsCreated = Unit Terbentuk
-stats.enemiesDestroyed = Musuh Terhancurkan
+stats.enemiesDestroyed = Musuh yang Dihancurkan
stats.built = Jumlah Blok yang Dibangun
stats.destroyed = Jumlah Blok Dihancurkan Musuh
-stats.deconstructed = Jumlah Blok Dihancurkan Pemain
+stats.deconstructed = Jumlah Blok yang Dihancurkan Pemain
stats.playtime = Waktu Bermain
globalitems = [accent]Bahan Keseluruhan
@@ -98,13 +98,13 @@ level.highscore = Nilai Tertinggi: [accent]{0}
level.select = Pilih Level
level.mode = Mode Permainan:
coreattack = < Inti sedang diserang! >
-nearpoint = [[ [scarlet]TINGGALKAN TITIK JATUH SEGERA[] ]\npenghancuran akan terjadi
+nearpoint = [[ [scarlet]TINGGALKAN ZONA PENDARATAN SEGERA[] ]\npenghancuran akan terjadi
database = Basis Data Inti
database.button = Basis Data
savegame = Simpan Permainan
loadgame = Muat Permainan
-joingame = Bermain Bersama
-customgame = Permainan Modifikasi
+joingame = Gabung Permainan
+customgame = Permainan Kustom
newgame = Permainan Baru
none =
none.found = [lightgray]
@@ -112,14 +112,14 @@ none.inmap = [lightgray]
minimap = Peta Kecil
position = Posisi
close = Tutup
-website = Situs Jaringan
+website = Situs Web
quit = Keluar
save.quit = Simpan & Keluar
maps = Peta
maps.browse = Cari Peta
continue = Lanjutkan
maps.none = [lightgray]Peta tidak ditemukan!
-invalid = Tidak valid
+invalid = Tidak Valid
pickcolor = Pilih Warna
preparingconfig = Menyiapkan Konfigurasi
preparingcontent = Menyiapkan Konten
@@ -129,59 +129,64 @@ committingchanges = Membuat Perubahan
done = Selesai
feature.unsupported = Perangkat Anda tidak mendukung fitur ini.
-mods.initfailed = [red]⚠[] Proses Mindustry sebelumnya gagal untuk dimulai. Kemungkinan besar disebabkan oleh mod yang bermasalah.\n\nUntuk menghindari kesalahan berulang, [red]semua mod telah dinonaktifkan.[]
+mods.initfailed = [red]⚠[] Proses Memuat Mindustry sebelumnya gagal untuk dimulai. Kemungkinan besar disebabkan oleh mod yang bermasalah.\n\nUntuk menghindari kesalahan berulang, [red]semua mod telah dinonaktifkan.[]
mods = Mod
mods.none = [lightgray]Tidak ada mod yang ditemukan!
-mods.guide = Panduan Memodifikasi
-mods.report = Lapor Bug
+mods.guide = Panduan Modifikasi
+mods.report = Laporkan Bug
mods.openfolder = Buka Folder Mod
mods.viewcontent = Buka Konten
mods.reload = Muat Ulang
-mods.reloadexit = Game akan keluar, untuk mengulang mod.
+mods.reloadexit = Game akan ditutup, untuk memuat ulang mod.
mod.installed = [[Terpasang]
mod.display = [gray]Mod:[orange] {0}
mod.enabled = [lightgray]Aktif
-mod.disabled = [scarlet]Nonaktif
-mod.multiplayer.compatible = [gray]Bisa Digunakan dalam Multiplayer
+mod.disabled = [red]Nonaktif
+mod.multiplayer.compatible = [gray]Kompatibel dalam Multipemain
mod.disable = Nonaktifkan
+mod.version = Version:
mod.content = Konten:
mod.delete.error = Tidak dapat menghapus mod. File mungkin sedang digunakan.
-mod.incompatiblegame = [red]Outdated Game
-mod.incompatiblemod = [red]Incompatible
-mod.blacklisted = [red]Unsupported
-mod.unmetdependencies = [red]Unmet Dependencies
+
+mod.incompatiblegame = [red]Game telah Kedaluwarsa
+mod.incompatiblemod = [red]Tidak Kompatibel
+mod.blacklisted = [red]Tidak Didukung
+mod.unmetdependencies = [red]Dependensi Tidak Terpenuhi
mod.erroredcontent = [scarlet]Konten Mengalami Kesalahan
-mod.circulardependencies = [red]Circular Dependencies
-mod.incompletedependencies = [red]Incomplete Dependencies
-mod.requiresversion.details = Requires game version: [accent]{0}[]\nYour game is outdated. This mod requires a newer version of the game (possibly a beta/alpha release) to function.
-mod.outdatedv7.details = This mod is incompatible with the latest version of the game. The author must update it, and add [accent]minGameVersion: 136[] to its [accent]mod.json[] file.
-mod.blacklisted.details = This mod has been manually blacklisted for causing crashes or other issues with this version of the game. Do not use it.
-mod.missingdependencies.details = This mod is missing dependencies: {0}
-mod.erroredcontent.details = This game caused errors when loading. Ask the mod author to fix them.
-mod.circulardependencies.details = This mod has dependencies that depends on each other.
-mod.incompletedependencies.details = This mod is unable to be loaded due to invalid or missing dependencies: {0}.
-mod.requiresversion = Requires game version: [red]{0}
+mod.circulardependencies = [red]Dependensi Sirkular
+mod.incompletedependencies = [red]Dependensi Tidak Lengkap
+
+mod.requiresversion.details = Membutuhkan versi game: [accent]{0}[]\nGame Anda telah kadaluarsa. Mod ini membutuhkan versi game yang lebih baru (kemungkinan versi beta/alpha) untuk berfungsi.
+mod.outdatedv7.details = Mod ini tidak kompatibel dengan versi game ini. Pencipta harus memperbaruinya, and add [accent]minGameVersion: 136[] ke dalam file [accent]mod.json[].
+mod.blacklisted.details = Mod ini terdapat di dalam blacklist karena menyebabkan crash atau masalah lain dengan versi game saat ini. Mohon jangan dipakai.
+mod.missingdependencies.details = Mod ini kekurangan dependensi: {0}
+mod.erroredcontent.details = Mod ini menimbulkan masalah pada saat proses memuat. Tanyakan pembuat mod untuk memperbaikinya.
+mod.circulardependencies.details = Mod ini memiliki dependensi yang membutuhkan satu sama lain.
+mod.incompletedependencies.details = Mod ini gagal memuat karena kekurangan dependensi atau tidak valid: {0}.
+
+mod.requiresversion = Membutuhkan versi game: [red]{0}
+
mod.errors = Terjadi kesalahan saat memuat konten.
mod.noerrorplay = [scarlet]Anda memiliki mod dengan suatu kesalahan.[] Nonaktifkan mod yang bersangkutan atau perbaiki kesalahan tersebut sebelum bermain.
-mod.nowdisabled = [scarlet]Mod '{0}' tidak memiliki ketergantungan:[accent] {1}\n[lightgray]Mod ini harus diunduh terlebih dahulu.\nMod ini akan dinonaktifkan secara otomatis.
+mod.nowdisabled = [scarlet]Mod '{0}' tidak memiliki dependensi:[accent] {1}\n[lightgray]Mod ini harus diunduh terlebih dahulu.\nMod ini akan dinonaktifkan secara otomatis.
mod.enable = Aktifkan
-mod.requiresrestart = Game akan keluar untuk mengaktifkan perubahan mod.
-mod.reloadrequired = [scarlet]Muat Ulang Diperlukan
+mod.requiresrestart = Game akan ditutup untuk mengaktifkan perubahan mod.
+mod.reloadrequired = [scarlet]Mulai Ulang Dibutuhkan
mod.import = Impor Mod
mod.import.file = Impor File
mod.import.github = Impor dari GitHub
mod.jarwarn = [scarlet]Mod dari JAR sebenarnya tidak aman.[]\nPastikan Anda mengimpor mod dari sumber terpercaya!
-mod.item.remove = Item ini merupakan bagian dari mod[accent] '{0}'[]. Untuk dihilangkan, hapus mod ini.
+mod.item.remove = Konten ini merupakan bagian dari mod[accent] '{0}'[]. Untuk menghilangkannya, hapus mod yang tersebut.
mod.remove.confirm = Mod ini akan dihapus.
mod.author = [lightgray]Pencipta:[] {0}
-mod.missing = Simpanan ini mengandung mod yang telah diperbarui atau sudah lama tidak dipasang. Kemungkinan akan terjadi perubahan. Apakah Anda yakin untuk memuatnya?\n[lightgray]Mods:\n{0}
-mod.preview.missing = Sebelum memposting mod di workshop, kamu harus memberi foto pratinjau.\nBeri sebuah foto berformat[accent] preview.png[] ke dalam folder mod dan ulang kembali.
-mod.folder.missing = Hanya mod dengan format folder yang dapat diposting di workshop.\nUntuk mengubah mod menjadi folder, ekstrak file mod tersebut dan pastikan berbentuk sebuah folder, kemudian ulang game Anda atau mod Anda.
-mod.scripts.disable = Perangkat anda tidak mendukung mod berformat skrip/JS. Anda harus menonaktifkan mod untuk lanjut bermain!
+mod.missing = Simpanan ini berisikan mod yang telah diperbarui atau sudah lama tidak dipasang. Kerusakan simpanan dapat terjadi. Apakah Anda yakin ingin memuatnya?\n[lightgray]Mod:\n{0}
+mod.preview.missing = Sebelum mengunggah mod ini ke workshop, Anda harus memberi gambar pratinjau.\nBeri sebuah gambar bernama[accent] preview.png[] ke dalam folder mod dan coba lagi.
+mod.folder.missing = Hanya mod dengan format folder yang dapat diunggah ke workshop.\nUntuk mengubah mod menjadi folder, ekstrak mod dalam folder dan hapus arsip zip, kemudian mulai ulang game atau mod Anda.
+mod.scripts.disable = Perangkat Anda tidak mendukung mod dengan skrip/JS. Anda harus menonaktifkan mod tersebut untuk dapat bermain.
about.button = Tentang
name = Nama:
-noname = Pilih[accent] nama pemain[] dahulu.
+noname = Masukkan[accent] nama pemain[] dahulu.
search = Cari:
planetmap = Peta Planet
launchcore = Luncurkan Inti
@@ -189,17 +194,18 @@ filename = Nama File:
unlocked = Konten baru terbuka!
available = Penelitian baru tersedia!
unlock.incampaign = < Buka dalam kampanye untuk detail lebih lanjut >
-campaign.select = Select Starting Campaign
-campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
-campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
-campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.select = Pilih untuk Memulai Kampanye
+campaign.none = [lightgray]Pilih planet untuk memulai.\nPilihan ini dapat diubah setiap saat.
+campaign.erekir = Konten baru yang disempurnakan. Kemajuan kampanye lebih linier.\n\nKualitas peta yang tinggi dan pengalaman lebih mantap.
+campaign.serpulo = Konten lawas; pengalaman klasik. Lebih terbuka dan banyak konten.\n\nPeta dan mekanisme kampanye yang berpotensi tidak seimbang. Kurang halus
+campaign.difficulty = Difficulty
completed = [accent]Terselesaikan
techtree = Pohon Teknologi
techtree.select = Pemilihan Pohon Teknologi
techtree.serpulo = Serpulo
techtree.erekir = Erekir
research.load = Muat
-research.discard = Abaikan
+research.discard = Buang
research.list = [lightgray]Penelitian:
research = Penelitian
researched = [lightgray]{0} telah diteliti.
@@ -213,32 +219,32 @@ server.kicked.kick = Anda telah dikeluarkan dari server!
server.kicked.whitelist = Anda tidak ada di dalam whitelist.
server.kicked.serverClose = Server ditutup.
server.kicked.vote = Anda dipilih untuk dikeluarkan. Sampai jumpa.
-server.kicked.clientOutdated = Klien kadaluarsa! Perbarui game Anda!
-server.kicked.serverOutdated = Server kadaluarsa! Tanya host untuk memperbarui!
+server.kicked.clientOutdated = Klien kedaluwarsa! Perbarui game Anda!
+server.kicked.serverOutdated = Server kedaluwarsa! Tanyakan host untuk memperbarui!
server.kicked.banned = Anda telah dilarang untuk memasuki server ini.
server.kicked.typeMismatch = Server ini tidak cocok dengan versi build Anda.
server.kicked.playerLimit = Server ini penuh. Tunggu slot kosong.
server.kicked.recentKick = Anda baru saja dikeluarkan dari server ini.\nTunggu sesaat sebelum masuk lagi.
server.kicked.nameInUse = Sudah ada pemain dengan nama tersebut\ndi server ini.
server.kicked.nameEmpty = Nama yang dipilih tidak valid.
-server.kicked.idInUse = Anda telah berada di server ini! Memasuki dengan dua akun tidak diizinkan.
-server.kicked.customClient = Server ini tidak mendukung versi modifikasi. Unduh versi resmi.
+server.kicked.idInUse = Anda telah berada di server ini! Menghubungkan dengan dua akun tidak diizinkan.
+server.kicked.customClient = Server ini tidak mendukung build kostum. Unduh versi resmi.
server.kicked.gameover = Permainan telah berakhir!
-server.kicked.serverRestarting = Server sedang mengulang kembali.
+server.kicked.serverRestarting = Server sedang dimulai ulang.
server.versions = Versi Anda:[accent] {0}[]\nVersi server:[accent] {1}[]
-host.info = Tombol [accent]host[] akan membuat server sementara di port [scarlet]6567[]. \nSemua orang yang memiliki [lightgray]Wi-Fi atau jaringan lokal[] akan bisa melihat server Anda di daftar server mereka.\n\nJika Anda ingin pemain dari mana saja memasuki server Anda dengan IP, [accent]port forwarding[] sangat diperlukan.\n\n[lightgray]Catatan: Jika seseorang mengalami masalah memasuki permainan lokal Anda, pastikan Anda telah mengizinkan Mindustry akses ke jaringan lokalmu di pengaturan firewall. Perlu diingat bahwa jaringan publik terkadang tidak mengizinkan pencarian server.
-join.info = Di sini, Anda bisa memasukkan [accent]IP server[] untuk dihubungkan, serta mencari [accent]jaringan lokal[] atau server [accent]global[] untuk dihubungkan.\nLAN dan WAN mendukung permainan bersama.\n\n[lightgray]Jika Anda ingin bergabung dengan seseorang melalui IP, Anda perlu menanyakan host tentang IP mereka, yang dapat dicari dengan meng-google "my ip" melalui perangkat mereka.
-hostserver = Host Permainan
+host.info = Tombol [accent]host[] akan membuat server sementara di port [scarlet]6567[]. \nSemua orang di dalam [lightgray]Wi-Fi atau jaringan lokal[] yang sama dapat melihat server Anda di daftar server mereka.\n\nJika Anda ingin pemain dari mana saja memasuki server Anda dengan IP, [accent]port forwarding[] sangat dibutuhkan.\n\n[lightgray]Catatan: Jika seseorang mengalami masalah memasuki permainan lokal Anda, pastikan Mindustry memiliki akses ke jaringan lokal di pengaturan firewall Anda. Perlu diingat jaringan publik terkadang tidak mengizinkan pencarian server.
+join.info = Di sini, Anda bisa memasukkan [accent]IP server[] untuk dihubungkan, serta mencari [accent]jaringan lokal[] atau server [accent]global[] untuk dihubungkan.\nLAN dan WAN mendukung multipemain.\n\n[lightgray]Jika Anda ingin bergabung dengan seseorang melalui IP, Anda perlu menanyakan host tentang IP mereka, yang dapat dicari dengan meng-google "my ip" melalui perangkat mereka.
+hostserver = Host Permainan Multi Pemain
invitefriends = Undang Teman
hostserver.mobile = Host\nPermainan
host = Host
hosting = [accent]Membuka server...
-hosts.refresh = Muat Ulang
+hosts.refresh = Segarkan
hosts.discovering = Mencari permainan lokal
hosts.discovering.any = Mencari permainan
server.refreshing = Memuat ulang server
hosts.none = [lightgray]Permainan lokal tidak ditemukan!
-host.invalid = [scarlet]Tidak bisa menyambung dengan pemilik.
+host.invalid = [scarlet]Tidak dapat menyambung ke host.
servers.local = Server Lokal
servers.local.steam = Permainan Publik & Server Lokal
@@ -255,28 +261,30 @@ trace = Lacak Pemain
trace.playername = Nama pemain: [accent]{0}
trace.ip = IP: [accent]{0}
trace.id = ID: [accent]{0}
-trace.language = Language: [accent]{0}
-trace.mobile = Client Mobile: [accent]{0}
-trace.modclient = Client Modifikasi: [accent]{0}
+trace.language = Bahasa: [accent]{0}
+trace.mobile = Klien Mobile: [accent]{0}
+trace.modclient = Klien Modifikasi: [accent]{0}
trace.times.joined = Total Bergabung: [accent]{0}
trace.times.kicked = Total Dikeluarkan: [accent]{0}
-trace.ips = IPs:
-trace.names = Names:
-invalidid = ID client tidak valid! Kirimkan laporan bug.
+trace.ips = IP:
+trace.names = Nama:
+invalidid = ID klien tidak valid! Kirimkan laporan bug.
+
player.ban = Ban
-player.kick = Kick
-player.trace = Trace
-player.admin = Toggle Admin
-player.team = Change Team
+player.kick = Keluarkan
+player.trace = lacak
+player.admin = Beri/Lepas Admin
+player.team = Ganti Tim
+
server.bans = Pemain Dilarang Masuk
-server.bans.none = Tidak ada pemain yang tidak diberi izin masuk!
+server.bans.none = Tidak ada pemain yang tidak diizinkan masuk!
server.admins = Admin
server.admins.none = Tidak ada admin ditemukan!
server.add = Tambah Server
server.delete = Anda yakin ingin menghapus server ini?
server.edit = Sunting Server
-server.outdated = [scarlet]Server Kadaluarsa![]
-server.outdated.client = [scarlet]Client Kadaluarsa![]
+server.outdated = [scarlet]Server Kedaluwarsa![]
+server.outdated.client = [scarlet]Klien Kedaluwarsa![]
server.version = [gray]v{0} {1}
server.custombuild = [accent]Bentuk Modifikasi
confirmban = Anda yakin ingin melarang pemain ini untuk masuk lagi?
@@ -284,27 +292,28 @@ confirmkick = Anda yakin ingin mengeluarkan pemain ini?
confirmunban = Anda yakin ingin mengizinkan pemain ini untuk masuk lagi?
confirmadmin = Anda yakin ingin membuat pemain ini sebagai admin?
confirmunadmin = Anda yakin ingin menghapus status admin dari pemain ini?
-votekick.reason = Vote-Kick Reason
-votekick.reason.message = Are you sure you want to vote-kick "{0}[white]"?\nIf yes, please enter the reason:
-joingame.title = Bermain Bersama
+votekick.reason = Pilih-Alasan dikeluarkan
+votekick.reason.message = Anda yakin ingin memulai pemungutan suara untuk mengeluarkan "{0}[white]"?\nJika ya, masukkan alasan:
+joingame.title = Gabung Permainan
joingame.ip = Alamat:
disconnect = Terputus.
-disconnect.error = Koneksi bermasalah.
-disconnect.closed = Koneksi ditutup.
-disconnect.timeout = Waktu habis.
+disconnect.error = Sambungan bermasalah.
+disconnect.closed = Sambungan ditutup.
+disconnect.timeout = Waktu koneksi habis.
disconnect.data = Gagal memuat data dunia!
-cantconnect = Gagal menyambungkan ke permainan ([accent]{0}[]).
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
+cantconnect = Gagal tersambung ke permainan ([accent]{0}[]).
connecting = [accent]Menghubungkan...
reconnecting = [accent]Menghubungkan kembali...
connecting.data = [accent]Memuat data dunia...
server.port = Port:
-server.addressinuse = Alamat sudah dipakai!
-server.invalidport = Nomor port tidak sah!
-server.error = [crimson]Terjadi kesalahan saat menghosting server: [accent]{0}
+server.invalidport = Nomor port tidak valid!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
+server.error = [scarlet]Terjadi kesalahan saat menghosting server: [accent]{0}
save.new = Simpanan Baru
-save.overwrite = Anda yakin ingin menindih \ntempat simpanan ini?
-save.nocampaign = Individual save files from the campaign cannot be imported.
-overwrite = Tindih
+save.overwrite = Anda yakin ingin menimpa \nsimpanan ini?
+save.nocampaign = File simpanan individual dari kampanye tidak dapat diimpor.
+overwrite = Timpa
save.none = Tidak ada simpanan!
savefail = Gagal menyimpan permainan!
save.delete.confirm = Anda yakin ingin menghapus simpanan ini?
@@ -320,7 +329,7 @@ save.rename.text = Nama baru:
selectslot = Pilih simpanan.
slot = [accent]Tempat {0}
editmessage = Atur Pesan
-save.corrupted = [accent]File simpanan rusak atau tidak sah!\nJika Anda baru saja memperbarui permainannya, ini karena perubahan di format penyimpanan dan [scarlet]bukan[] sebuah isu.
+save.corrupted = File simpanan rusak atau tidak valid!
empty =
on = Aktif
off = Nonaktif
@@ -341,37 +350,38 @@ open = Buka
customize = Sunting Peraturan
cancel = Batal
command = Perintah
-command.queue = [lightgray][Queuing]
+command.queue = Antrian
command.mine = Tambang
command.repair = Perbaiki
command.rebuild = Bangun Kembali
command.assist = Bantu Pemain
command.move = Maju
-command.boost = Boost
-command.enterPayload = Enter Payload Block
-command.loadUnits = Load Units
-command.loadBlocks = Load Blocks
-command.unloadPayload = Unload Payload
-stance.stop = Cancel Orders
-stance.shoot = Stance: Shoot
-stance.holdfire = Stance: Hold Fire
-stance.pursuetarget = Stance: Pursue Target
-stance.patrol = Stance: Patrol Path
-stance.ram = Stance: Ram\n[lightgray]Straight line movement, no pathfinding
+command.boost = Pendorongan
+command.enterPayload = Masukkan Muatan Blok
+command.loadUnits = Muat Unit
+command.loadBlocks = Muat Blok
+command.unloadPayload = Turunkan Muatan
+command.loopPayload = Loop Unit Transfer
+stance.stop = Batalkan Perintah
+stance.shoot = Posisi Unit: Menembak
+stance.holdfire = Posisi Unit: Gencatan Senjata
+stance.pursuetarget = Posisi Unit: Kejar Target
+stance.patrol = Posisi Unit: Patroli Jalur
+stance.ram = Posisi Unit: Seruduk\n[lightgray]Pergerakan lurus, tanpa pathfinding
openlink = Buka Tautan
copylink = Salin Tautan
back = Kembali
-max = Batas
+max = Batas Maximum
objective = Peta Tujuan
-crash.export = Ekspor Crash Log
-crash.none = Tidak ada crash log ditemukan.
-crash.exported = Crash log diekspor.
+crash.export = Ekspor Laporan Error
+crash.none = Tidak ada Laporan Error ditemukan.
+crash.exported = Laporan Error diekspor.
data.export = Ekspor Data
data.import = Impor Data
data.openfolder = Buka Folder Data
-data.exported = Data telah di ekspor.
-data.invalid = Data permainan ini tidak sah.
-data.import.confirm = Mengimpor data eksternal akan menghapus [scarlet] semua[] data yang tersimpan.\n[accent]Tidak dapat diundur lagi![]\n\nSetelah data diimpor, game akan segera ditutup.
+data.exported = Data telah diekspor.
+data.invalid = Data permainan ini tidak valid.
+data.import.confirm = Mengimpor data eksternal akan menghapus [scarlet] semua[] data yang tersimpan.\n[accent]Ini tidak dapat dibatalkan![]\n\nSetelah data diimpor, game akan segera keluar.
quit.confirm = Apakah Anda yakin ingin keluar?
loading = [accent]Memuat...
downloading = [accent]Mengunduh...
@@ -383,8 +393,8 @@ pausebuilding = [accent][[{0}][] untuk jeda membangun
resumebuilding = [scarlet][[{0}][] untuk lanjut membangun
enablebuilding = [scarlet][[{0}][] untuk mulai membangun
showui = UI disembunyikan.\nTekan [accent][[{0}][] untuk menampilkan UI.
-commandmode.name = [accent]Command Mode
-commandmode.nounits = [no units]
+commandmode.name = [accent]Mode Perintah
+commandmode.nounits = [unit kosong]
wave = [accent]Gelombang {0}
wave.cap = [accent]Gelombang {0}/{1}
wave.waiting = [lightgray]Gelombang di {0}
@@ -399,54 +409,54 @@ wave.guardianwarn = Penjaga akan tiba dalam [accent]{0}[] gelombang.
wave.guardianwarn.one = Penjaga akan tiba dalam [accent]{0}[] gelombang.
loadimage = Memuat Gambar
saveimage = Simpan Gambar
-unknown = Tak diketahui
+unknown = Tidak diketahui
custom = Modifikasi
-builtin = Terpasang
-map.delete.confirm = Anda yakin ingin menghapus peta ini? Aksi ini tidak bisa diubah!
+builtin = Bawaan
+map.delete.confirm = Anda yakin ingin menghapus peta ini? Tindakan ini tidak bisa diubah!
map.random = [accent]Peta Acak
-map.nospawn = Peta ini tidak memiliki inti agar pemain bisa muncul! Tambahkan inti {0} ke dalam peta di penyunting.
-map.nospawn.pvp = Peta ini tidak memiliki inti agar pemain lawan bisa muncul! Tambahkan inti [scarlet]selain jingga[] ke dalam peta di penyunting.
-map.nospawn.attack = Peta ini tidak memiliki inti musuh agar pemain bisa menyerang! Tambahkan inti {0} ke dalam peta di penyunting.
+map.nospawn = Peta ini tidak memiliki inti agar pemain bisa muncul! Tambahkan inti [#{0}]{1}[] ke dalam peta di penyunting.
+map.nospawn.pvp = Peta ini tidak memiliki inti agar pemain lawan bisa muncul! Tambahkan inti[scarlet] selain jingga[] ke dalam peta di penyunting.
+map.nospawn.attack = Peta ini tidak memiliki inti musuh agar pemain bisa menyerang! Tambahkan inti [#{0}]{1}[] ke dalam peta di penyunting.
map.invalid = Terjadi kesalahan saat memuat peta: rusak atau file peta tidak valid.
-workshop.update = Perbarui Item
+workshop.update = Perbarui Konten
workshop.error = Terjadi kesalahan saat mengambil detail workshop: {0}
-map.publish.confirm = Apakah Anda yakin untuk menerbitkan peta ini?\n\n[lightgray]Pastikan Anda setuju dengan Workshop EULA terlebih dahulu, atau peta anda tidak akan muncul!
-workshop.menu = Pilih apa yang Anda ingin lakukan dengan item ini.
-workshop.info = Informasi item
+map.publish.confirm = Apakah Anda yakin untuk menerbitkan peta ini?\n\n[lightgray]Pastikan Anda setuju dengan Workshop EULA terlebih dahulu, atau peta Anda tidak akan muncul!
+workshop.menu = Pilih apa yang Anda ingin lakukan dengan konten ini.
+workshop.info = Informasi Konten
changelog = Catatan Pembaruan (opsional):
updatedesc = Timpa Judul & Deskripsi
eula = EULA Steam
-missing = Item ini telah dihapus atau dipindah.\n[lightgray]Daftar Workshop sekarang telah tidak terhubung secara otomatis.
+missing = Konten ini telah dihapus atau dipindah.\n[lightgray]Daftar Workshop sekarang telah tidak terhubung secara otomatis.
publishing = [accent]Menerbitkan...
-publish.confirm = Apakah Anda yakin untuk menerbitkan ini?\n\n[lightgray]Pastikan Anda setuju dengan EULA Workshop terlebih dahulu, atau item Anda tidak akan muncul!
-publish.error = Terjadi kesalahan saat menerbitkan item: {0}
+publish.confirm = Apakah Anda yakin untuk menerbitkan ini?\n\n[lightgray]Pastikan Anda setuju dengan EULA Workshop terlebih dahulu, atau konten Anda tidak akan muncul!
+publish.error = Terjadi kesalahan saat menerbitkan konten: {0}
steam.error = Gagal untuk menjalankan layanan Steam.\nKesalahan: {0}
editor.planet = Planet:
editor.sector = Sektor:
editor.seed = Benih:
-editor.cliffs = Dinding Ke Jurang
+editor.cliffs = Dinding Ke Tebing
editor.brush = Kuas
-editor.openin = Buka di Penyunting
+editor.openin = Buka di Penyuntingan
editor.oregen = Generasi Sumber Daya
editor.oregen.info = Generasi Sumber Daya:
editor.mapinfo = Info Peta
editor.author = Pencipta:
editor.description = Deskripsi:
-editor.nodescription = Setiap peta harus memiliki sebuah deskripsi setidaknya 4 karakter sebelum diterbitkan.
+editor.nodescription = Setiap peta harus memiliki deskripsi setidaknya 4 huruf sebelum diunggah.
editor.waves = Gelombang:
editor.rules = Peraturan:
editor.generation = Generasi:
editor.objectives = Tujuan
-editor.locales = Locale Bundles
-editor.worldprocessors = World Processors
-editor.worldprocessors.editname = Edit Name
-editor.worldprocessors.none = [lightgray]No world processor blocks found!\nAdd one in the map editor, or use the \ue813 Add button below.
-editor.worldprocessors.nospace = No free space to place a world processor!\nDid you fill the map with structures? Why would you do this?
-editor.worldprocessors.delete.confirm = Are you sure you want to delete this world processor?\n\nIf it is surrounded by walls, it will be replaced by an environmental wall.
+editor.locales = Paket Lokal
+editor.worldprocessors = Prosesor Dunia
+editor.worldprocessors.editname = Sunting Nama
+editor.worldprocessors.none = [lightgray]Tidak ada blok prosesor dunia yang ditemukan!\nTambahkan satu di penyunting peta, atau gunakan \ue813 tombol Tambah di bawah.
+editor.worldprocessors.nospace = Tidak ada ruang kosong untuk menempatkan prosesor dunia!\nApakah Anda mengisi peta dengan bangunan? Mengapa Anda melakukan ini?
+editor.worldprocessors.delete.confirm = Apakah Anda yakin ingin menghapus prosesor dunia ini?\n\nJika dikelilingi tembok maka akan diganti dengan tembok lingkungan.
editor.ingame = Sunting dalam Permainan
editor.playtest = Tes Bermain
-editor.publish.workshop = Terbitkan di Workshop
+editor.publish.workshop = Unggah ke Workshop
editor.newmap = Peta Baru
editor.center = Pusat
editor.search = Cari peta...
@@ -469,15 +479,15 @@ waves.shields = perisai/gelombang
waves.to = sampai
waves.spawn = muncul:
waves.spawn.all =
-waves.spawn.select = Pilih tempat Muncul
-waves.spawn.none = [scarlet]tidak ada tempat muncul di peta
+waves.spawn.select = Pilih Tempat Pendaratan Musuh
+waves.spawn.none = [scarlet]tidak ada tempat pendaratan musuh di peta
waves.max = unit maks
waves.guardian = Penjaga
waves.preview = Pratinjau
waves.edit = Sunting...
-waves.random = Random
-waves.copy = Salin ke Papan klip
-waves.load = Tempel dari Papan klip
+waves.random = Acak
+waves.copy = Salin ke Papan Klip
+waves.load = Tempel dari Papan Klip
waves.invalid = Gelombang tidak valid di papan klip.
waves.copied = Gelombang tersalin.
waves.none = Tidak ada musuh yang didefinisikan.\nIngat bahwa susunan gelombang yang kosong akan diubah menjadi susunan gelombang standar secara otomatis.
@@ -486,35 +496,37 @@ waves.sort.reverse = Urut Balik
waves.sort.begin = Mulai
waves.sort.health = Darah
waves.sort.type = Tipe
-waves.search = Search waves...
-waves.filter = Unit Filter
+waves.search = Cari gelombang...
+waves.filter = Filter Unit
waves.units.hide = Sembunyikan Semua
-waves.units.show = Lihat Semua
+waves.units.show = Perlihatkan Semua
#these are intentionally in lower case
wavemode.counts = jumlah
wavemode.totals = total
wavemode.health = darah
+all = All
editor.default = [lightgray]
details = Detail...
-edit = Sunting...
+edit = Sunting
variables = Vars
-logic.clear.confirm = Are you sure you want to clear all code from this processor?
-logic.globals = Built-in Variables
+logic.clear.confirm = Apakah Anda yakin ingin menghapus semua kode dari prosesor ini?
+logic.globals = Variabel Bawaan
+
editor.name = Nama:
editor.spawn = Munculkan Unit
editor.removeunit = Hapus Unit
editor.teams = Tim
editor.errorload = Terjadi kesalahan saat memuat file.
editor.errorsave = Terjadi kesalahan saat menyimpan file.
-editor.errorimage = Itu gambar biasa, bukan peta.
+editor.errorimage = Itu gambar, bukan peta.
editor.errorlegacy = Peta ini terlalu tua, dan memakai format peta "legacy" yang tidak didukung lagi.
-editor.errornot = Ini bukan merupakan file peta.
-editor.errorheader = File peta ini bisa jadi tidak sah atau rusak.
+editor.errornot = Ini bukan file peta.
+editor.errorheader = File peta ini Kemungkinan tidak valid atau rusak.
editor.errorname = Peta tidak ada nama. Apakah Anda mencoba untuk memuat file simpanan?
-editor.errorlocales = Error reading invalid locale bundles.
-editor.update = Perbaruan
+editor.errorlocales = Terjadi kesalahan saat membaca paket lokal yang tidak valid.
+editor.update = Perbarui
editor.randomize = Acak
editor.moveup = Pindah Ke Atas
editor.movedown = Pindah Ke Bawah
@@ -525,54 +537,54 @@ editor.sectorgenerate = Generasi Sektor
editor.resize = Ubah Ukuran
editor.loadmap = Memuat Peta
editor.savemap = Simpan Peta
-editor.savechanges = [scarlet]You have unsaved changes!\n\n[]Do you want to save them?
+editor.savechanges = [scarlet]Anda memiliki perubahan yang belum disimpan!\n\n[]Apakah Anda ingin menyimpannya?
editor.saved = Tersimpan!
editor.save.noname = Peta Anda tidak ada nama! Tambahkan di menu 'info peta'.
-editor.save.overwrite = Peta ini menindih peta built-in! Pilih nama yang berbeda di menu 'info peta'.
-editor.import.exists = [scarlet]Tidak bisa mengimpor:[] peta built-in bernama '{0}' sudah ada!
+editor.save.overwrite = Peta ini menimpa peta bawaan! Pilih nama yang berbeda di menu 'info peta'.
+editor.import.exists = [scarlet]Tidak bisa mengimpor:[] peta bawaan bernama '{0}' sudah ada!
editor.import = Mengimpor...
editor.importmap = Impor Peta
editor.importmap.description = Mengimpor peta yang telah ada
editor.importfile = Impor File
-editor.importfile.description = Mengimpor file peta dari luar
+editor.importfile.description = Mengimpor file peta eksternal
editor.importimage = Impor File Gambar
-editor.importimage.description = Mengimpor file peta berbentuk gambar dari luar
+editor.importimage.description = Mengimpor file peta eksternal berbentuk gambar
editor.export = Ekspor...
editor.exportfile = Ekspor File
editor.exportfile.description = Mengekspor sebuah file peta
-editor.exportimage = Expor Gambar Dunia
+editor.exportimage = Ekspor Gambar Medan
editor.exportimage.description = Ekspor sebuah file gambar peta
-editor.loadimage = Impor Dunia
-editor.saveimage = Ekspor Dunia
+editor.loadimage = Impor Medan
+editor.saveimage = Ekspor Medan
editor.unsaved = Yakin ingin keluar?\n[scarlet]Perubahan yang belum disimpan akan hilang.
editor.resizemap = Ubah Ukuran Peta
editor.mapname = Nama Peta:
-editor.overwrite = [accent]Peringatan!\nIni akan menindih peta yang telah ada.
-editor.overwrite.confirm = [scarlet]Peringatan![] Peta dengan nama ini sudah ada. Yakin ingin menindihnya?\n"[accent]{0}[]"
+editor.overwrite = [accent]Peringatan!\nIni akan menimpa peta yang telah ada.
+editor.overwrite.confirm = [scarlet]Peringatan![] Peta dengan nama ini sudah ada. Yakin ingin menimpanya?\n"[accent]{0}[]"
editor.exists = Sebuah peta dengan nama ini sudah ada.
editor.selectmap = Pilih peta untuk dimuat:
toolmode.replace = Ganti
-toolmode.replace.description = Hanya dapat digambar pada balok padat.
+toolmode.replace.description = Menggambar pada blok padat.
toolmode.replaceall = Ganti Semua
-toolmode.replaceall.description = Ganti semua balok di peta.
+toolmode.replaceall.description = Ganti semua blok di peta.
toolmode.orthogonal = Ortogonal
-toolmode.orthogonal.description = Hanya menggambar garis ortogonal.
+toolmode.orthogonal.description = Menggambar dalam garis ortogonal.
toolmode.square = Persegi
-toolmode.square.description = Sikat bangun persegi.
+toolmode.square.description = Bangun persegi.
toolmode.eraseores = Hapus Bijih
-toolmode.eraseores.description = Hanya menghapus bijih.
+toolmode.eraseores.description = Menghapus bijih.
toolmode.fillteams = Isi Tim
toolmode.fillteams.description = Mengisi tim bukannya blok.
-toolmode.fillerase = Fill Erase
-toolmode.fillerase.description = Erase blocks of the same type.
+toolmode.fillerase = Hapus
+toolmode.fillerase.description = Hapus blok dengan tipe yang sama.
toolmode.drawteams = Gambar Tim
toolmode.drawteams.description = Menggambar tim bukannya blok.
#unused
toolmode.underliquid = Di Bawah Cairan
toolmode.underliquid.description = Gambarlah lantai di bawah ubin cair.
-filters.empty = [lightgray]Tidak ada filter! Tambahkan dengan tombol dibawah.
+filters.empty = [lightgray]Tidak ada penyaring! Tambahkan dengan tombol di bawah.
filter.distort = Kerusakkan
filter.noise = Kebisingan
@@ -582,7 +594,7 @@ filter.corespawn = Pilih Inti
filter.median = Median
filter.oremedian = Median Bijih
filter.blend = Campur
-filter.defaultores = Bijih Standar
+filter.defaultores = Sumber Daya Bawaan
filter.ore = Sumber Daya
filter.rivernoise = Kebisingan Sungai
filter.mirror = Cermin
@@ -590,7 +602,7 @@ filter.clear = Bersih
filter.option.ignore = Biarkan
filter.scatter = Penebaran
filter.terrain = Lahan
-filter.logic = Logic
+filter.logic = Logika
filter.option.scale = Ukuran
filter.option.chance = Kemungkinan
@@ -614,25 +626,26 @@ filter.option.floor2 = Lantai Sekunder
filter.option.threshold2 = Ambang Sekunder
filter.option.radius = Radius
filter.option.percentile = Perseratus
-filter.option.code = Code
-filter.option.loop = Loop
-locales.info = Here, you can add locale bundles for specific languages to your map. In locale bundles, each property has a name and a value. These properties can be used by world processors and objectives using their names. They support text formatting (replacing placeholders with actual values).\n\n[cyan]Example property:\n[]name: [accent]timer[]\nvalue: [accent]Example timer, time left: {0}[]\n\n[cyan]Usage:\n[]Set it as objective's text: [accent]@timer\n\n[]Print it in a world processor:\n[accent]localeprint "timer"\nformat time\n[gray](where time is a separately calculated variable)
-locales.deletelocale = Are you sure you want to delete this locale bundle?
-locales.applytoall = Apply Changes To All Locales
-locales.addtoother = Add To Other Locales
-locales.rollback = Rollback to last applied
-locales.filter = Property filter
-locales.searchname = Search name...
-locales.searchvalue = Search value...
-locales.searchlocale = Search locale...
-locales.byname = By name
-locales.byvalue = By value
-locales.showcorrect = Show properties that are present in all locales and have unique values everywhere
-locales.showmissing = Show properties that are missing in some locales
-locales.showsame = Show properties that have same values in different locales
-locales.viewproperty = View in all locales
-locales.viewing = Viewing property "{0}"
-locales.addicon = Add Icon
+filter.option.code = Kode
+filter.option.loop = Perulangan
+
+locales.info = Di sini, Anda dapat menambahkan paket lokal untuk bahasa tertentu ke peta Anda. Dalam paket lokal, setiap properti memiliki nama dan nilai. Properti ini dapat digunakan prosesor dunia dan tujuan dengan menggunakan namanya. Mereka mendukung pemformatan teks (mengganti placeholder dengan nilai sebenarnya).\n\n[cyan]Contoh properti:\n[]nama: [accent]waktu[]\nnilai: [accent]Contoh pengatur waktu, waktu tersisa: {0}[]\n\n[cyan]Penggunaan:\n[]Tetapkan sebagai teks tujuan: [accent]@timer\n\n[]Cetak dalam prosesor dunia:\n[accent]cetak lokal "timer"\nformat time\n[gray](di mana waktu adalah variabel yang dihitung secara terpisah)
+locales.deletelocale = Apakah Anda yakin ingin menghapus paket lokal ini?
+locales.applytoall = Terapkan Perubahan Ke Semua Paket Lokal
+locales.addtoother = Tambahkan Ke Paket Lokal Lain
+locales.rollback = Kembalikan ke yang terakhir diterapkan
+locales.filter = Filter properti
+locales.searchname = Cari nama...
+locales.searchvalue = Cari nilai...
+locales.searchlocale = Cari lokal...
+locales.byname = Dengan nama
+locales.byvalue = Dengan nilai
+locales.showcorrect = Tampilkan properti yang ada di semua paket lokal dan memiliki nilai unik di mana pun
+locales.showmissing = Tampilkan properti yang tidak ada di beberapa paket lokal
+locales.showsame = Tampilkan properti yang memiliki nilai yang sama di lokasi berbeda
+locales.viewproperty = Lihat di semua paket lokal
+locales.viewing = Melihat properti "{0}"
+locales.addicon = Tambahkan Ikon
width = Lebar:
height = Tinggi:
@@ -646,34 +659,33 @@ ping = Ping: {0}ms
tps = TPS: {0}
memory = Mem: {0}mb
memory2 = Mem:\n {0}mb +\n {1}mb
-language.restart = Silahkan mengulang kembali permainan agar pengaturan bahasa berpengaruh.
+language.restart = Silahkan memulai ulang game agar pengaturan bahasa diterapkan
settings = Pengaturan
tutorial = Tutorial
-tutorial.retake = Ulang Tutorial
+tutorial.retake = Ulangi Tutorial
editor = Penyunting
mapeditor = Penyunting Peta
abandon = Tinggalkan
-abandon.text = Zona ini dan semua sumber daya didalamnya akan berada di tangan musuh.
+abandon.text = Zona ini dan semua sumber daya di dalamnya akan berada di tangan musuh.
locked = Terkunci
complete = [lightgray]Selesaikan:
requirement.wave = Raih gelombang {0} dalam {1}
requirement.core = Hancurkan inti musuh dalam {0}
-requirement.research = Kembangkan {0}
+requirement.research = Riset {0}
requirement.produce = Produksi {0}
requirement.capture = Kuasai {0}
-requirement.onplanet = Kendalikan Sektor Dalam {0}
+requirement.onplanet = Kendalikan Sektor Di {0}
requirement.onsector = Mendarat Di Sektor: {0}
launch.text = Luncurkan
-research.multiplayer = Hanya host yang dapat meneliti barang.
map.multiplayer = Hanya host yang dapat melihat sektor.
uncover = Buka
configure = Konfigurasi Muatan
objective.research.name = Riset
objective.produce.name = Peroleh
-objective.item.name = Peroleh Barang
-objective.coreitem.name = Barang Inti
+objective.item.name = Peroleh Suatu Bahan
+objective.coreitem.name = Bahan Inti
objective.buildcount.name = Jumlah Bangunan
objective.unitcount.name = Jumlah Unit
objective.destroyunits.name = Hancurkan Unit
@@ -685,42 +697,42 @@ objective.commandmode.name = Mode Perintah
objective.flag.name = Bendera
marker.shapetext.name = Teks Berbentuk
-marker.point.name = Point
+marker.point.name = Titik
marker.shape.name = Bentuk
marker.text.name = Teks
-marker.line.name = Line
-marker.quad.name = Quad
-marker.texture.name = Texture
+marker.line.name = Garis
+marker.quad.name = Segi empat
+marker.texture.name = Tekstur
marker.background = Latar Belakang
marker.outline = Garis Luar
objective.research = [accent]Riset:\n[]{0}[lightgray]{1}
-objective.produce = [accent]Memperoleh:\n[]{0}[lightgray]{1}
+objective.produce = [accent]Peroleh:\n[]{0}[lightgray]{1}
objective.destroyblock = [accent]Hancurkan:\n[]{0}[lightgray]{1}
objective.destroyblocks = [accent]Hancurkan: [lightgray]{0}[white]/{1}\n{2}[lightgray]{3}
-objective.item = [accent]Memperoleh: [][lightgray]{0}[]/{1}\n{2}[lightgray]{3}
+objective.item = [accent]Peroleh: [][lightgray]{0}[]/{1}\n{2}[lightgray]{3}
objective.coreitem = [accent]Pindahkan ke Inti:\n[][lightgray]{0}[]/{1}\n{2}[lightgray]{3}
objective.build = [accent]Bangun: [][lightgray]{0}[]x\n{1}[lightgray]{2}
-objective.buildunit = [accent]Bangun Unit: [][lightgray]{0}[]x\n{1}[lightgray]{2}
+objective.buildunit = [accent]Buat Unit: [][lightgray]{0}[]x\n{1}[lightgray]{2}
objective.destroyunits = [accent]Hancurkan: [][lightgray]{0}[]x Units
-objective.enemiesapproaching = [accent]Musuh akan datang pada [lightgray]{0}[]
-objective.enemyescelating = [accent]Enemy production escalating in [lightgray]{0}[]
-objective.enemyairunits = [accent]Enemy air unit production beginning in [lightgray]{0}[]
+objective.enemiesapproaching = [accent]Musuh akan datang dalam [lightgray]{0}[]
+objective.enemyescelating = [accent]Produksi musuh meningkat dalam [lightgray]{0}[]
+objective.enemyairunits = [accent]Produksi pasukan udara musuh dimulai dalam [lightgray]{0}[]
objective.destroycore = [accent]Hancurkan Inti Musuh
objective.command = [accent]Perintahkan Unit
objective.nuclearlaunch = [accent]⚠ Terdeteksi peluncuran nuklir: [lightgray]{0}
-announce.nuclearstrike = [red]⚠ SERANGAN NUKLIR ⚠
+announce.nuclearstrike = [red]⚠ SERANGAN NUKLIR ⚠\n[lightgray]bangun inti cadangan sesegera mungkin
loadout = Muatan
resources = Sumber Daya
resources.max = Maks
-bannedblocks = Balok yang Dilarang
+bannedblocks = Blok yang Dilarang
objectives = Tujuan
bannedunits = Unit yang Dilarang
-bannedunits.whitelist = Banned Units As Whitelist
-bannedblocks.whitelist = Banned Blocks As Whitelist
+bannedunits.whitelist = Unit yang Dilarang Sebagai Whitelist
+bannedblocks.whitelist = Blok yang Dilarang Sebagai Whitelist
addall = Tambah Semua
launch.from = Meluncurkan Dari: [accent]{0}
launch.capacity = Kapasitas Barang yang Diluncurkan: [accent]{0}
@@ -732,21 +744,23 @@ guardian = Penjaga
connectfail = [scarlet]Gagal menyambung ke server:\n\n[accent]{0}
error.unreachable = Server tidak dapat dihubungi.\nApakah alamatnya benar?
error.invalidaddress = Alamat tidak valid.
-error.timedout = Kehabisan waktu!\nPastikan pemilik mempunyai port forwarding, dan alamatnya benar!
-error.mismatch = Paket terjadi kekeliruan:\nbisa terjadi apabila versi client/server berbeda.\nPastikan Anda dan host mempunyai versi terbaru Mindustry!
+error.timedout = Kehabisan waktu!\nPastikan pemilik mempunyai port penerusan, dan alamatnya benar!
+error.mismatch = Paket bermasalah:\nkemungkinan versi client/server berbeda.\nPastikan Anda dan host mempunyai versi terbaru Mindustry!
error.alreadyconnected = Sudah tersambung.
error.mapnotfound = File peta tidak ditemaukan!
error.io = Terjadi kesalahan jaringan I/O.
error.any = Terjadi kesalahan Jaringan tidak diketahui.
-error.bloom = Gagal untuk menjalankan bloom.\nPerangkat Anda mungkin tidak mendukung fitur ini.
+error.bloom = Gagal untuk menjalankan efek bloom.\nPerangkat Anda mungkin tidak mendukung fitur ini.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Hujan
weather.snowing.name = Salju
weather.sandstorm.name = Badai Pasir
weather.sporestorm.name = Badai Spora
weather.fog.name = Kabut
-campaign.playtime = \uf129 [lightgray]Sector Playtime: {0}
-campaign.complete = [accent]Congratulations.\n\nThe enemy on {0} has been defeated.\n[lightgray]The final sector has been conquered.
+
+campaign.playtime = \uf129 [lightgray]Waktu bermain di sektor: {0}
+campaign.complete = [accent]Selamat.\n\nMusuh di {0} telah dikalahkan.\n[lightgray]Sektor terakhir telah dikuasai.
sectorlist = Sektor
sectorlist.attacked = {0} sedang diserang
@@ -762,12 +776,12 @@ sectors.stored = Terisi:
sectors.resume = Lanjutkan
sectors.launch = Luncurkan
sectors.select = Pilih
-sectors.nonelaunch = [lightgray]tidak ada (matahari)
+sectors.nonelaunch = [lightgray]nihil (matahari)
sectors.rename = Ganti Nama Sektor
sectors.enemybase = [scarlet]Markas Musuh
sectors.vulnerable = [scarlet]Rawan diserang
sectors.underattack = [scarlet]Dalam Serangan! [accent]Kerusakan sebesar {0}%
-sectors.underattack.nodamage = [scarlet]Belum Ditaklukkan
+sectors.underattack.nodamage = [scarlet]Belum Dikuasai
sectors.survives = [accent]Bertahan sebanyak {0} gelombang
sectors.go = Mulai
sector.abandon = Tinggalkan
@@ -777,11 +791,11 @@ sector.curlost = Sektor Gagal Bertahan
sector.missingresources = [scarlet]Sumber Daya Inti Tidak Cukup
sector.attacked = Sektor [accent]{0}[white] sedang diserang!
sector.lost = Sektor [accent]{0}[white] telah dihancurkan!
-sector.capture = Sector [accent]{0}[white]Captured!
-sector.capture.current = Sector Captured!
+sector.capture = Sector [accent]{0}[white]Dikuasai!
+sector.capture.current = Sektor Dikuasai!
sector.changeicon = Ubah Ikon
-sector.noswitch.title = Tidak Dapat beralih Sektor
-sector.noswitch = Andak tidak boleh berpindah sektor jika salah satu sektor terkena serangan.\nSektor: [accent]{0}[] di [accent]{1}[]
+sector.noswitch.title = Tidak Dapat berpindah Sektor
+sector.noswitch = Anda tidak boleh berpindah sektor jika salah satu sektor sedang di serang.\nSektor: [accent]{0}[] di [accent]{1}[]
sector.view = Lihat Sektor
threat.low = Rendah
@@ -789,6 +803,11 @@ threat.medium = Sedang
threat.high = Tinggi
threat.extreme = Berbahaya
threat.eradication = Pemusnahan
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planet
@@ -811,78 +830,99 @@ sector.fungalPass.name = Lintasan Spora
sector.biomassFacility.name = Pabrik Sintesis Biomassa
sector.windsweptIslands.name = Pulau Bersemilir
sector.extractionOutpost.name = Pos Ekstraksi Terdepan
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Pusat Peluncuran Planet
sector.coastline.name = Tepi Pantai
sector.navalFortress.name = Benteng Laut
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
-sector.groundZero.description = Lokasi yang optimal untuk bermain satu kali lagi. Sangat sedikit musuh. Beberapa sumber daya dapat dikumpulkan.\nKumpulkan timah dan tembaga sebanyak yang kamu bisa.\nMulai dari sini.
-sector.frozenForest.description = Disini, dekat dengan gunung, spora sudah menyebar. Suhu dingin tidak dapat menahannya.\n\nHasilkan listrik. Bangun generator pembakar. Pelajari cara menggunakan mender.
-sector.saltFlats.description = Di pinggiran padang pasir terdapat Daratan Garam. Beberapa sumber daya dapat ditemukan disini.\n\nMusuh telah membangun gudang disini. Hancurkan inti mereka. Jangan biarkan satupun tersisa.
+sector.groundZero.description = Lokasi yang optimal untuk bermain satu kali lagi. Sangat sedikit musuh. Sedikit sumber daya.\nKumpulkan timah dan tembaga sebanyak yang Anda bisa.\nMulai dari sini.
+sector.frozenForest.description = Di sini, dekat dengan gunung, spora sudah menyebar. Suhu dingin tidak dapat menahannya.\n\nMulailah hasilkan listrik. Bangun generator pembakar. Pelajari cara menggunakan mender.
+sector.saltFlats.description = Di pinggiran padang pasir terdapat Daratan Garam. Beberapa sumber daya dapat ditemukan di sini.\n\nMusuh telah mendirikan penyimpanan sumber daya kompleks di sini. Hancurkan inti mereka. Jangan biarkan satupun tersisa.
sector.craters.description = Air banyak terkumpul di kawah ini, sebuah peninggalan dari perang masa lalu. Klaim area ini lagi. Kumpulkan pasir. Lebur metaglass. Pompa air untuk mendinginkan turret dan bor.
-sector.ruinousShores.description = Keluar dari lembah gunung, terdapat garis pantai. Sebelumnya, area ini adalah garis pertahanan pantai. Sekarang tidak banyak yang tersisa. Hanya pertahanan dasar yang tersisa, yang lain hancur berkeping keping.\nBangun kembali pertahanan di sini. Pelajari lebih banyak teknologi.
-sector.stainedMountains.description = Area ini terletak di dekat pegunungan, namun belum tersentuh oleh spora.\nTambang titanium yang ada di area ini. Pelajari fungsinya.\n\nMusuh jauh lebih kuat disini. Jangan biarkan mereka meluncurkan unit yang lebih kuat.
-sector.overgrowth.description = Area ini banyak ditumbuhi spora, karena dekat dengan sumber spora.\nMusuh telah membangun basis disini. Bangun unit Mace. Hancurkan mereka. Klaim apapun yang tersisa.
-sector.tarFields.description = Terletak di pinggiran zona produksi minyak, diantara gunung dan padang pasir. Salah satu dari beberapa area yang memiliki cadangan minyak yang dapat digunakan.\nMeskipun ditinggalkan, area ini terdapat pertahanan musuh yang sangat kuat disekitarnya. Jangan meremehkan mereka.\n\n[lightgray]Pelajari proses penyulingan minyak bila memungkinkan.
-sector.desolateRift.description = Zona yang sangat berbahaya. Banyak sumber daya, tetapi terdapat sedikit ruang. Sangat beresiko tinggi untuk dihancurkan. Buatlah pertahanan udara dan darat secepat yang kamu bisa. Jangan terlena karena waktu antara gelombang yang lama.
-sector.nuclearComplex.description = Sebuah fasilitas untuk memproduksi dan memproses thorium, telah hancur.\n[lightgray]Pelajari thorium dan cara penggunaanya.\n\nMusuh disini menyerang dalam jumlah besar, yang siap untuk menghadapi siapapun.
-sector.fungalPass.description = Area ini terdapat diantara pegunungan yang lebih tinggi dengan yang lebih rendah, juga daerah yang dipenuhi spora. Musuh membangun basis kecil disini.\nHancurkan itu.\nGunakan unit Dagger dan Crawler. Hancurkan dua inti mereka.
+sector.ruinousShores.description = Keluar dari lembah gunung, terdapat garis pantai. Sebelumnya, area ini adalah garis pertahanan pantai. Sekarang tidak banyak yang tersisa. Hanya pertahanan dasar yang tersisa, yang lain telah hancur berkeping keping.\nBangun kembali pertahanan di sini. Pelajari lebih banyak teknologi.
+sector.stainedMountains.description = Area ini terletak di dekat pegunungan, namun belum tersentuh oleh spora.\nTambang titanium yang ada di area ini. Pelajari fungsinya.\n\nMusuh jauh lebih kuat di sini. Jangan biarkan mereka meluncurkan unit yang lebih kuat.
+sector.overgrowth.description = Area ini banyak ditumbuhi spora, karena dekat dengan sumber spora.\nMusuh telah membangun pangkalan di sini. Buat unit Mace. Hancurkan mereka. Klaim apapun yang tersisa.
+sector.tarFields.description = Terletak di pinggiran zona produksi minyak, di antara gunung dan padang pasir. Salah satu dari beberapa area yang memiliki cadangan minyak yang dapat digunakan.\nMeskipun ditinggalkan, area ini terdapat pasukan musuh yang berbahaya di sekitarnya. Jangan meremehkan mereka.\n\n[lightgray]Pelajari proses penyulingan minyak bila memungkinkan.
+sector.desolateRift.description = Zona yang sangat berbahaya. Banyak sumber daya, tetapi terdapat sedikit ruang. Sangat resiko kehancuran sangat tinggi. Buatlah pertahanan udara dan darat secepat yang Anda bisa. Jangan terlena dengan waktu antar gelombang yang lama.
+sector.nuclearComplex.description = Sebuah fasilitas untuk memproduksi dan memproses torium, yang telah hancur.\n[lightgray]Pelajari torium dan cara penggunaanya.\n\nMusuh yang hadir di sini menyerang dalam jumlah besar, tak henti mengintai penyerang.
+sector.fungalPass.description = Area ini terdapat di antara pegunungan yang lebih tinggi dengan yang lebih rendah, juga daerah yang dipenuhi spora. Musuh membangun markas pengintaian kecil di sini.\nHancurkan itu.\nGunakan unit Dagger dan Crawler. Hancurkan dua inti mereka.
sector.biomassFacility.description = Asal dari semua spora di planet ini. Tempat ini adalah fasilitas dimana spora dipelajari dan diproduksi.\nPelajari teknologi yang terkait dengannya. Budi dayakan spora untuk memproduksi bahan bakar dan plastik.\n\n[lightgray]Setelah fasilitas ini hancur, spora menyebar. Tidak ada di ekosistem lokal yang dapat bersaing dengan organisme invasif seperti itu.
-sector.windsweptIslands.description = Jauh dari pantai terdapat sekumpulan pulau. Catatan yang ada mengatakan bahwa mereka memiliki struktur untuk memproduksi [accent]Plastanium[].\n\nKalahkan unit laut musuh. Bangun basis di kepulauan ini. Pelajari pabriknya.
-sector.extractionOutpost.description = Sebuah pos jarak jauh, dibangun musuh untuk meluncurkan sumber daya ke sektor yang lain.\n\nTeknologi tarnsportasi antar sektor dapat memudahkan untuk menaklukan lebih banyak sektor. Hancurkan basis itu. Pelajari Alas Peluncur mereka.
+sector.windsweptIslands.description = Jauh dari pantai terdapat sekumpulan pulau. Catatan yang ada mengatakan bahwa mereka memiliki struktur untuk memproduksi [accent]Plastanium[].\n\nKalahkan unit laut musuh. Bangun markas di kepulauan ini. Pelajari pabriknya.
+sector.extractionOutpost.description = Sebuah pos jarak jauh, dibangun musuh untuk meluncurkan sumber daya ke sektor yang lain.\n\nTeknologi transportasi antar sektor dapat memudahkan untuk menaklukan lebih banyak sektor. Hancurkan markasnya . Pelajari Alas Peluncur mereka.
sector.impact0078.description = Di sini terletak sisa-sisa pesawat antarbintang yang pertama kali memasuki sistem ini.\n\nSelamatkan apapun yang ada dari sisa-sisa pesawat. Pelajari teknologi apa pun yang utuh.
-sector.planetaryTerminal.description = Target terakhir.\n\nBasis pantai ini memiliki struktur yang dapat meluncurkan inti ke planet disekitarnya. Memiliki pertahanan yang sangat bagus.\n\nProduksi unit laut. Hancurkan musuh secepat mungkin. Pelajari struktur peluncuran mereka.
-sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
-sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.planetaryTerminal.description = Target terakhir.\n\nMarkas pesisir pantai ini memiliki struktur yang dapat meluncurkan inti ke planet di sekitarnya. Memiliki pertahanan yang sangat bagus.\n\nProduksi unit laut. Hancurkan musuh secepat mungkin. Pelajari struktur peluncuran mereka.
+sector.coastline.description = Sisa-sisa teknologi Unit Laut telah terdeteksi di lokasi ini. Tolak serangan musuh, rebut sektor ini, dan dapatkan teknologinya.
+sector.navalFortress.description = Musuh telah mendirikan markas di sebuah pulau terpencil, dibentengi secara alami. Hancurkan pangkalan ini. Dapatkan teknologi Unit Laut mereka yang canggih, dan telitilah
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
-sector.onset.name = Pemulaan
+sector.onset.name = Serangan Awal
sector.aegis.name = Aegis
sector.lake.name = Danau
sector.intersect.name = Perempatan
sector.atlas.name = Atlas
-sector.split.name = Split
-sector.basin.name = Basin
-sector.marsh.name = Marsh
-sector.peaks.name = Peaks
-sector.ravine.name = Ravine
-sector.caldera-erekir.name = Caldera
-sector.stronghold.name = Stronghold
-sector.crevice.name = Crevice
-sector.siege.name = Siege
-sector.crossroads.name = Crossroads
-sector.karst.name = Karst
+sector.split.name = Pisahan
+sector.basin.name = Cekungan
+sector.marsh.name = Rawa
+sector.peaks.name = Puncak
+sector.ravine.name = Jurang
+sector.caldera-erekir.name = Kaldera
+sector.stronghold.name = Benteng
+sector.crevice.name = Retakan
+sector.siege.name = Pengepungan
+sector.crossroads.name = Simpangan
+sector.karst.name = Kars
sector.origin.name = Origin
-sector.onset.description = Sektor latihan. Tujuan ini belum dibuat. Tunggu informasi selanjutnya.
-#TODO - no shield breaker anymore.
-sector.aegis.description = Musuh dilindungi oleh perisai. Modul pemutus pelindung eksperimental telah terdeteksi di sektor ini.\nTemukan struktur ini. Pasok dengan amunisi tungsten dan hancurkan markas musuh.
-sector.lake.description = Danau terak di sektor ini sangat membatasi pilihan unit yang kita gunakan. Pilihan satu-satunya dengan menggunakan unit amphibi.\nRiset [accent]fabrikator kapal[] dan buat unit [accent]elude[] secepat mungkin.
-sector.intersect.description = Pemindai mensugesti bahwa sektor ini akan diserang dari berbagai arah setelah kita mendarat.\nSegera siapkan pertahanan dan perluas wilayah secepat mungkin.\nUnit [accent]meka[] akan diperlukan untuk dataran yang sulit dilalui.
-sector.atlas.description = Sektor ini memiliki dataran yang unik dan akan memerlukan beraneka ragam unit untuk menyerang secara efektif.\nUnit tingkat lanjut dapat diperlukan untuk melewati beberapa markas musuh yang kuat di sekitar sini.\nRiset [accent]Elektroliser[] dan [accent]Refabrikator Tank[].
+sector.onset.description = Permulaan Penaklukan Erekir. Kumpulkan sumber daya, produksi unit, dan mulailah meneliti teknologi.
+sector.aegis.description = Sektor ini mengandung deposit Tungsten.\nRiset [accent]Bor Tumbukan[] untuk menambang sumber daya ini, dan hancurkan markas musuh di area tersebut.
+sector.lake.description = Danau lava di sektor ini sangat membatasi pilihan unit yang kita gunakan. Unit Kapal adalah satu-satunya pilihan.\nRiset [accent]fabrikator kapal[] dan produksi unit [accent]elude[] secepat mungkin.
+sector.intersect.description = Pemindai menunjukkan bahwa sektor ini akan diserang dari berbagai arah setelah kita mendarat.\nSegera siapkan pertahanan dan perluas wilayah secepat mungkin.\nUnit [accent]mech[] akan dibutuhkan untuk dataran yang sulit dilalui.
+sector.atlas.description = Sektor ini memiliki dataran yang unik dan akan membutuhkan beraneka ragam unit untuk menyerang secara efektif.\nUnit yang ditingkatkan mungkin dibutuhkan untuk melewati beberapa markas musuh yang kuat di sekitar sini.\nRiset [accent]Elektroliser[] dan [accent]Refabrikator Tank[].
sector.split.description = Keberadaan musuh yang minim di sektor ini sangat bagus untuk menguji coba teknologi transportasi baru.
-sector.basin.description = {Temporary}\n\nSektor terakhir untuk saat ini. Anggap ini sebagai level tantangan!
-sector.marsh.description = This sector has an abundance of arkycite, but has limited vents.\nBuild [accent]Chemical Combustion Chambers[] to generate power.
-sector.peaks.description = The mountainous terrain in this sector make most units useless. Flying units will be required.\nBe aware of enemy anti-air installations. It may be possible to disable some of these installations by targeting their supporting buildings.
-sector.ravine.description = Tidak ada inti musuh yang ditemukan di sini, namun sangat penting sebagai rute transportasi untuk musuh. Expect berbagai jenis musuh.\nProduksi [accent]surge alloy[]. Bangun menara [accent]Afflict[].
-sector.caldera-erekir.description = The resources detected in this sector are scattered across several islands.\nResearch and deploy drone-based transportation.
-sector.stronghold.description = The large enemy encampment in this sector guards significant deposits of [accent]thorium[].\nUse it to develop higher tier units and turrets.
-sector.crevice.description = The enemy will send fierce attack forces to take out your base in this sector.\nDeveloping [accent]carbide[] and the [accent]Pyrolysis Generator[] may be imperative for survival.
-sector.siege.description = This sector features two parallel canyons that will force a two-pronged attack.\nResearch [accent]cyanogen[] to gain the capability to create even stronger tank units.\nCaution: enemy long-range missiles have been detected. The missiles may be shot down before impact.
-sector.crossroads.description = The enemy bases in this sector have been established in varying terrain. Research different units to adapt.\nAdditionally, some bases are protected by shields. Figure out how they are powered.
-sector.karst.description = This sector is rich in resources, but will be attacked by the enemy once a new core lands.\nTake advantage of the resources and research [accent]phase fabric[].
-sector.origin.description = The final sector with a significant enemy presence.\nNo probable research opportunities remain - focus solely on destroying all enemy cores.
+sector.basin.description = Kehadiran musuh dalam jumlah besar terdeteksi di sektor ini.\nBangun unit dengan cepat dan Kuasai inti musuh untuk mendapatkan pijakan
+sector.marsh.description = Sektor ini memiliki kelimpahan arkisit, namun memiliki ventilasi yang terbatas.\nBangun [accent]Ruang Pembakaran Kimia[] untuk menghasilkan tenaga.
+sector.peaks.description = Medan pegunungan di sektor ini membuat sebagian besar unit tidak berguna. Unit terbang akan dibutuhkan.\nWaspadai instalasi anti-udara yang dimiliki musuh. Beberapa instalasi ini mungkin dapat dinonaktifkan dengan menargetkan bangunan pendukungnya.
+sector.ravine.description = Jalur transportasi penting bagi musuh. Tidak ada inti musuh yang ditemukan di sini, namun hati-hati terhadap berbagai jenis musuh.\nProduksi [accent]Paduan Logam[]. Bangun menara [accent]Afflict[].
+sector.caldera-erekir.description = Sumber daya yang terdeteksi di sektor ini tersebar di beberapa pulau.\nRiset dan sebarkan transportasi berbasis drone.
+sector.stronghold.description = Markas musuh yang besar di sektor ini menjaga simpanan [accent]torium[] dalam jumlah besar .\nGunakan itu untuk mengembangkan unit dan menara ke tingkat yang lebih tinggi.
+sector.crevice.description = Musuh akan mengirimkan pasukan serangan yang hebat untuk menghancurkan markasmu di sektor ini.\nKembangkan [accent]karbit[] dan [accent]Generator Pirolisis[] mungkin imperatif untuk bertahan hidup.
+sector.siege.description = Sektor ini memiliki dua ngarai paralel yang akan memaksa serangan dari dua arah.\nRiset [accent]sianogen[] untuk mendapatkan kemampuan untuk membuat unit tank yang lebih kuat.\nPeringatan: Rudal jarak jauh milik musuh telah terdeteksi. Rudal tersebut mungkin ditembak jatuh sebelum terjadi benturan.
+sector.crossroads.description = Pangkalan musuh di sektor ini telah didirikan di berbagai medan. Riset unit yang berbeda untuk beradaptasi.\nSelain itu, beberapa markas telah dilindungi oleh perisai. Cari tahu bagaimana mereka diberi daya.
+sector.karst.description = Sektor ini kaya akan sumber daya, namun akan diserang oleh musuh begitu inti baru mendarat.\nManfaatkan sumber daya dan riset [accent]Phase Fabric[].
+sector.origin.description = Sektor terakhir dengan kehadiran musuh yang signifikan.\nTidak ada peluang penelitian yang tersisa - fokuslah pada menghancurkan semua inti musuh.
status.burning.name = Terbakar
status.freezing.name = Membeku
status.wet.name = Basah
status.muddy.name = Berlumpur
status.melting.name = Meleleh
-status.sapped.name = Terlemahkan
-status.electrified.name = Dialiri Listrik
+status.sapped.name = Melemah
+status.electrified.name = Terkena Listrik
status.spore-slowed.name = Spora Melambat
status.tarred.name = Berminyak
status.overdrive.name = Dipercepat
status.overclock.name = Melebihi Batas
-status.shocked.name = Mengkejut
+status.shocked.name = Tersengat
status.blasted.name = Meledak
status.unmoving.name = Terdiam
status.boss.name = Penjaga
@@ -897,7 +937,7 @@ settings.game = Permainan
settings.sound = Suara
settings.graphics = Grafik
settings.cleardata = Menghapus Data Permainan...
-settings.clear.confirm = Anda yakin ingin menghapus data ini?\nWaktu tidak bisa diulang kembali!
+settings.clear.confirm = Anda yakin ingin menghapus data ini?\nApa yang sudah dilakukan tidak dapat dibatalkan!
settings.clearall.confirm = [scarlet]PERINGATAN![]\nIni akan menghapus semua data permainan, termasuk simpanan, peta, bukaan dan keybind.\nSetelah Anda menekan 'ok' permainan akan menghapus semua data dan keluar otomatis.
settings.clearsaves.confirm = Anda yakin ingin menghapus semua simpanan?
settings.clearsaves = Bersihkan Simpanan
@@ -919,22 +959,22 @@ lastaccessed = [lightgray]Terakhir Diakses: {0}
lastcommanded = [lightgray]Terakhir Diperintah: {0}
block.unknown = [lightgray]???
-stat.showinmap =
+stat.showinmap =
stat.description = Kegunaan
-stat.input = Masukan
+stat.input = Pemasukan
stat.output = Pengeluaran
stat.maxefficiency = Batas Efisiensi
stat.booster = Pendorong
-stat.tiles = Petak yang Diperlukan
+stat.tiles = Ubin yang Diperlukan
stat.affinities = Kecocokan
stat.opposites = Bertentangan
stat.powercapacity = Kapasitas Tenaga
stat.powershot = Tenaga/Tembakan
-stat.damage = Kerusakan
-stat.targetsair = Sasaran Udara
-stat.targetsground = Sasaran Darat
-stat.itemsmoved = Kecepatan Gerak
-stat.launchtime = Waktu Diantara Peluncuran
+stat.damage = Damage
+stat.targetsair = Target Udara
+stat.targetsground = Target Darat
+stat.itemsmoved = Kecepatan Barang
+stat.launchtime = Waktu Antara Peluncuran
stat.shootrange = Jarak
stat.size = Ukuran
stat.displaysize = Ukuran Tampilan
@@ -944,21 +984,21 @@ stat.linkrange = Jarak Tautan
stat.instructions = Instruksi
stat.powerconnections = Batas Sambungan
stat.poweruse = Penggunaan Tenaga
-stat.powerdamage = Tenaga/Pukulan
+stat.powerdamage = Tenaga/Tembakan
stat.itemcapacity = Kapasitas Bahan
stat.memorycapacity = Kapasitas Memori
-stat.basepowergeneration = Basis Generasi Tenaga
+stat.basepowergeneration = Dasar Generasi Tenaga
stat.productiontime = Waktu Produksi
-stat.repairtime = Waktu Memperbaiki Blok Penuh
-stat.repairspeed = Kecepatan Memperbaiki
+stat.repairtime = Waktu Perbaikan Blok Penuh
+stat.repairspeed = Kecepatan Perbaikan
stat.weapons = Senjata
stat.bullet = Peluru
stat.moduletier = Tingkatan Modul
-stat.unittype = Unit Type
-stat.speedincrease = Tambahan Kecepatan
+stat.unittype = Jenis Unit
+stat.speedincrease = Peningkatan Kecepatan
stat.range = Jarak
stat.drilltier = Sumber Daya yang Ditambang
-stat.drillspeed = Basis Kecepatan Bor
+stat.drillspeed = Kecepatan Bor Dasar
stat.boosteffect = Efek Pendorong
stat.maxunits = Batas Unit Aktif
stat.health = Darah
@@ -968,14 +1008,14 @@ stat.maxconsecutive = Batas Konsekutif
stat.buildcost = Biaya Bangunan
stat.inaccuracy = Jarak Melenceng
stat.shots = Tembakan
-stat.reload = Kecepatan Tembakan
+stat.reload = Kecepatan Penembakan
stat.ammo = Amunisi
stat.shieldhealth = Darah Perisai
stat.cooldowntime = Waktu Pendinginan
stat.explosiveness = Daya Ledak
stat.basedeflectchance = Peluang Defleksi Dasar
stat.lightningchance = Peluang Menghasilkan Petir
-stat.lightningdamage = Kerusakan Petir
+stat.lightningdamage = Damage Petir
stat.flammability = Daya Bakar
stat.radioactivity = Daya Radioaktif
stat.charge = Setruman
@@ -985,74 +1025,76 @@ stat.temperature = Suhu
stat.speed = Kecepatan
stat.buildspeed = Kecepatan Membangun
stat.minespeed = Kecepatan Menambang
-stat.minetier = Tingkat Menambang
+stat.minetier = Tingkat Tambang
stat.payloadcapacity = Kapasitas Muatan
stat.abilities = Kemampuan
-stat.canboost = Dapat Dipercepat
+stat.canboost = Memiliki Pendorong
stat.flying = Terbang
stat.ammouse = Penggunaan Amunisi
-stat.ammocapacity = Ammo Capacity
+stat.ammocapacity = Kapasitas Amunisi
stat.damagemultiplier = Penggandaan Kekuatan (dmg)
stat.healthmultiplier = Penggandaan Darah
stat.speedmultiplier = Penggandaan Kecepatan
stat.reloadmultiplier = Penggandaan Isi Ulang
stat.buildspeedmultiplier = Penggandaan Kecepatan Membangun
-stat.reactive = Reaktif
+stat.reactive = Reaksi
stat.immunities = Kekebalan
stat.healing = Menyembuhkan
ability.forcefield = Bidang Kekuatan
-ability.forcefield.description = Projects a force shield that absorbs bullets
+ability.forcefield.description = Memproyeksikan perisai kekuatan yang menyerap peluru
ability.repairfield = Bidang Perbaikan
-ability.repairfield.description = Repairs nearby units
+ability.repairfield.description = Memperbaiki unit terdekat
ability.statusfield = Bidang Status
-ability.statusfield.description = Applies a status effect to nearby units
+ability.statusfield.description = Menerapkan efek status ke unit terdekat
ability.unitspawn = Pabrik
-ability.unitspawn.description = Constructs units
+ability.unitspawn.description = Membangun unit
ability.shieldregenfield = Bidang Regenerasi Perisai
-ability.shieldregenfield.description = Regenerates shields of nearby units
+ability.shieldregenfield.description = Meregenerasi perisai unit di sekitar
ability.movelightning = Pergerakan Petir
-ability.movelightning.description = Releases lightning while moving
-ability.armorplate = Armor Plate
-ability.armorplate.description = Reduces damage taken while shooting
-ability.shieldarc = Shield Arc
-ability.shieldarc.description = Projects a force shield in an arc that absorbs bullets
-ability.suppressionfield = Regen Suppression Field
-ability.suppressionfield.description = Stops nearby repair buildings
-ability.energyfield = Bidang Tenaga
-ability.energyfield.description = Zaps nearby enemies
-ability.energyfield.healdescription = Zaps nearby enemies and heals allies
-ability.regen = Regeneration
-ability.regen.description = Regenerates own health over time
-ability.liquidregen = Liquid Absorption
-ability.liquidregen.description = Absorbs liquid to heal itself
-ability.spawndeath = Death Spawns
-ability.spawndeath.description = Releases units on death
-ability.liquidexplode = Death Spillage
-ability.liquidexplode.description = Spills liquid on death
-ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
-ability.stat.regen = [stat]{0}[lightgray] health/sec
-ability.stat.shield = [stat]{0}[lightgray] shield
-ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
-ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
-ability.stat.cooldown = [stat]{0} sec[lightgray] cooldown
-ability.stat.maxtargets = [stat]{0}[lightgray] max targets
-ability.stat.sametypehealmultiplier = [stat]{0}%[lightgray] same type repair amount
-ability.stat.damagereduction = [stat]{0}%[lightgray] damage reduction
-ability.stat.minspeed = [stat]{0} tiles/sec[lightgray] min speed
-ability.stat.duration = [stat]{0} sec[lightgray] duration
-ability.stat.buildtime = [stat]{0} sec[lightgray] build time
+ability.movelightning.description = Melepaskan petir sambil bergerak
+ability.armorplate = Pelindung Baja
+ability.armorplate.description = Mengurangi kerusakan yang diterima saat menembak
+ability.shieldarc = Perisai Busur
+ability.shieldarc.description = Memproyeksikan perisai kekuatan dalam busur yang menyerap peluru
+ability.suppressionfield = Bidang Penahan Regen
+ability.suppressionfield.description = Menghentikan bangunan perbaikan di dekatnya
+ability.energyfield = Bidang Energi
+ability.energyfield.description = Menyengat musuh di sekitar
+ability.energyfield.healdescription = Menyengat musuh di sekitar dan menyembuhkan sekutu
+ability.regen = Regenerasi Diri Sendiri
+ability.regen.description = Meregenerasi darah sendiri secara terus menerus
+ability.liquidregen = Penyerapan Cairan
+ability.liquidregen.description = Menyerap cairan untuk menyembuhkan dirinya sendiri
+ability.spawndeath = Kematian-Munculkan
+ability.spawndeath.description = Melepaskan unit saat mati
+ability.liquidexplode = Kematian-Tumpahkan
+ability.liquidexplode.description = Menumpahkan cairan saat mati
+
+ability.stat.firingrate = [stat]{0}/sec[lightgray] laju penembakan
+ability.stat.regen = [stat]{0}[lightgray] darah/detik
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
+ability.stat.shield = [stat]{0}[lightgray] perisai
+ability.stat.repairspeed = [stat]{0}/sec[lightgray] kecepatan perbaikan
+ability.stat.slurpheal = [stat]{0}[lightgray] darah/unit cair
+ability.stat.cooldown = [stat]{0} sec[lightgray] waktu jeda
+ability.stat.maxtargets = [stat]{0}[lightgray] target maksimal
+ability.stat.sametypehealmultiplier = [stat]{0}%[lightgray] jumlah jenis perbaikan yang sama
+ability.stat.damagereduction = [stat]{0}%[lightgray] pengurangan kerusakan
+ability.stat.minspeed = [stat]{0} tiles/sec[lightgray] kecepatan minimal
+ability.stat.duration = [stat]{0} sec[lightgray] durasi
+ability.stat.buildtime = [stat]{0} sec[lightgray] waktu membangun
bar.onlycoredeposit = Hanya Penyetoran Inti yang Diizinkan
bar.drilltierreq = Membutuhkan Bor yang Lebih Baik
-bar.noresources = Sumber Daya Tidak Ditemukan
-bar.corereq = Memerlukan Inti Dasar
+bar.noresources = Sumber Daya Tidak Cukup
+bar.corereq = Membutuhkan Inti Markas
bar.corefloor = Ubin Zona Inti Dibutuhkan
-bar.cargounitcap = Kapasitas Kargo Unit Melebihi Batas
+bar.cargounitcap = Kapasitas Unit Kargo Telah Mencapai Batas
bar.drillspeed = Kecepatan Bor: {0}/s
bar.pumpspeed = Kecepatan Pompa: {0}/s
-bar.efficiency = Daya Guna: {0}%
-bar.boost = Percepatan: +{0}%
+bar.efficiency = Efisiensi: {0}%
+bar.boost = Pendorongan: +{0}%
bar.powerbalance = Tenaga: {0}/s
bar.powerstored = Disimpan: {0}/{1}
bar.poweramount = Tenaga: {0}
@@ -1067,9 +1109,9 @@ bar.instability = Instabilitas
bar.heatamount = Panas: {0}
bar.heatpercent = Panas: {0} ({1}%)
bar.power = Tenaga
-bar.progress = Perkembangan Pembangunan
-bar.loadprogress = Kemajuan
-bar.launchcooldown = Pendinginan Peluncuran
+bar.progress = Proses Pembangunan
+bar.loadprogress = Proses Muatan
+bar.launchcooldown = Waktu Jeda Peluncuran
bar.input = Masukan
bar.output = Keluaran
bar.strength = [stat]{0}[lightgray]x penguatan
@@ -1080,26 +1122,28 @@ bullet.damage = [stat]{0}[lightgray] kekuatan (dmg)
bullet.splashdamage = [stat]{0}[lightgray] kekuatan percikan~[stat] {1}[lightgray] kotak
bullet.incendiary = [stat]membakar
bullet.homing = [stat]mengejar
-bullet.armorpierce = [stat]menembus baju besi
-bullet.maxdamagefraction = [stat]{0}%[lightgray] damage limit
-bullet.suppression = [stat]{0} sec[lightgray] repair suppression ~ [stat]{1}[lightgray] tiles
-bullet.interval = [stat]{0}/sec[lightgray] interval bullets:
+bullet.armorpierce = [stat]menembus pelindung
+bullet.maxdamagefraction = [stat]{0}%[lightgray] batas kerusakan
+bullet.suppression = [stat]{0}[lightgray] detik penahanan perbaikan ~ [stat]{1}[lightgray] ubin
+bullet.interval = [stat]{0}/detik[lightgray] jarak antar peluru:
bullet.frags = [stat]{0}[lightgray]x pecahan:
-bullet.lightning = [stat]{0}[lightgray]x petir ~ [stat]{1}[lightgray] kerusakan
-bullet.buildingdamage = [stat]{0}%[lightgray] kerusakan bangunan
+bullet.lightning = [stat]{0}[lightgray]x petir ~ [stat]{1}[lightgray] damage
+bullet.buildingdamage = [stat]{0}%[lightgray] damage bangunan
bullet.knockback = [stat]{0}[lightgray] terdorong
bullet.pierce = [stat]{0}[lightgray]x tembus
-bullet.infinitepierce = [stat]menembus
+bullet.infinitepierce = [stat]tembus
bullet.healpercent = [stat]{0}[lightgray]% menyembuhkan
bullet.healamount = [stat]{0}[lightgray] perbaikan langsung
bullet.multiplier = [stat]{0}[lightgray]x penggandaan amunisi
bullet.reload = [stat]{0}[lightgray]x laju tembakan
bullet.range = [stat]{0}[lightgray] jarak ubin
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blok
unit.blockssquared = blok²
unit.powersecond = unit tenaga/detik
-unit.tilessecond = petak/detik
+unit.tilessecond = ubin/detik
unit.liquidsecond = unit zat cair/detik
unit.itemssecond = bahan/detik
unit.liquidunits = unit zat cair
@@ -1127,26 +1171,26 @@ category.items = Barang
category.crafting = Pemasukan/Pengeluaran
category.function = Fungsi
category.optional = Peningkatan Opsional
-setting.alwaysmusic.name = Always Play Music
-setting.alwaysmusic.description = When enabled, music will always play on loop in-game.\nWhen disabled, it only plays at random intervals.
-setting.skipcoreanimation.name = Lewati Animasi Peluncuran/Pendaratan Inti
+setting.alwaysmusic.name = Selalu Putar Musik
+setting.alwaysmusic.description = Saat diaktifkan, musik akan selalu diputar berulang-ulang di dalam game. Saat dinonaktifkan, musik hanya diputar secara acak.
+setting.skipcoreanimation.name = Lewati Animasi Peluncuran atau Pendaratan Inti
setting.landscape.name = Kunci Pemandangan
setting.shadows.name = Bayangan
-setting.blockreplace.name = Usulan Blok Otomatis
-setting.linear.name = Filter Bergaris
+setting.blockreplace.name = Saran Blok Otomatis
+setting.linear.name = Filter Linear
setting.hints.name = Petunjuk
setting.logichints.name = Petunjuk Logika
setting.backgroundpause.name = Jeda di Latar
-setting.buildautopause.name = Jeda Otomatis saat Membangun
-setting.doubletapmine.name = Dua-kali Sentuh untuk Menambang
+setting.buildautopause.name = Jeda Otomatis ketika Membangun
+setting.doubletapmine.name = Ketuk Dua Kali untuk Menambang
setting.commandmodehold.name = Tahan Untuk Mode Perintah
-setting.distinctcontrolgroups.name = Limit One Control Group Per Unit
-setting.modcrashdisable.name = Matikan Mod Ketika Ada Masalah Saat Memulai Permainan
+setting.distinctcontrolgroups.name = Batasi Satu Grup Kontrol Per Unit
+setting.modcrashdisable.name = Matikan Mod Ketika Ada Masalah Saat Memulai Game
setting.animatedwater.name = Animasi Perairan
setting.animatedshields.name = Animasi Perisai
setting.playerindicators.name = Indikasi Pemain
-setting.indicators.name = Indikasi Musuh/Teman Lain
-setting.autotarget.name = Target Secara Otomatis
+setting.indicators.name = Indikasi Musuh
+setting.autotarget.name = Bidik Musuh Secara Otomatis
setting.keyboard.name = Kontrol Tetikus+Papan Ketik
setting.touchscreen.name = Kontrol Layar Sentuh
setting.fpscap.name = Batas FPS
@@ -1154,20 +1198,14 @@ setting.fpscap.none = Tidak Ada
setting.fpscap.text = {0} FPS
setting.uiscale.name = Skala UI
setting.uiscale.description = Mulai ulang diperlukan untuk menerapkan perubahan.
-setting.swapdiagonal.name = Selalu Penaruhan Diagonal
-setting.difficulty.training = Latihan
-setting.difficulty.easy = Mudah
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Susah
-setting.difficulty.insane = Sangat sulit
-setting.difficulty.name = Tingkat Kesulitan:
+setting.swapdiagonal.name = Penaruhan Selalu Diagonal
setting.screenshake.name = Layar Getar
setting.bloomintensity.name = Intensitas Bloom
setting.bloomblur.name = Blur Bloom
setting.effects.name = Munculkan Efek
setting.destroyedblocks.name = Tunjukkan Blok yang Telah Hancur
setting.blockstatus.name = Tunjukan Status Blok
-setting.conveyorpathfinding.name = Navigasi Pengantar Otomatis
+setting.conveyorpathfinding.name = Navigasi Konveyor/Pipa Otomatis
setting.sensitivity.name = Sensitivitas Kontroler
setting.saveinterval.name = Jarak Menyimpan
setting.seconds = {0} detik
@@ -1187,26 +1225,26 @@ setting.position.name = Tunjukkan Posisi Pemain
setting.mouseposition.name = Tunjukkan Posisi Tetikus
setting.musicvol.name = Volume Musik
setting.atmosphere.name = Tunjukkan Atmosfer Planet
-setting.drawlight.name = Draw Darkness/Lighting
+setting.drawlight.name = Gambar Kegelapan atau Pencahayaan
setting.ambientvol.name = Volume Sekeliling
-setting.mutemusic.name = Diamkan Musik
-setting.sfxvol.name = Volume Efek Suara
-setting.mutesound.name = Diamkan Suara
-setting.crashreport.name = Laporkan Masalah
+setting.mutemusic.name = Bisukan Musik
+setting.sfxvol.name = Volume Suara Efek
+setting.mutesound.name = Bisukan Suara
+setting.crashreport.name = Laporkan Masalah Secara Anonim
setting.savecreate.name = Otomatis Menyimpan
-setting.steampublichost.name = Public Game Visibility
+setting.steampublichost.name = Visibilitas Game Publik
setting.playerlimit.name = Batas pemain
setting.chatopacity.name = Jelas-Beningnya Pesan
-setting.lasersopacity.name = Jelas-Beningnya Tenaga Laser
+setting.lasersopacity.name = Jelas-Beningnya Laser Tenaga
setting.bridgeopacity.name = Jelas-Beningnya Jembatan
-setting.playerchat.name = Tunjukkan Pesan dalam Permainan
+setting.playerchat.name = Tunjukkan Pesan Pemain
setting.showweather.name = Perlihatkan Cuaca
setting.hidedisplays.name = Sembunyikan Tampilan Logika
-setting.macnotch.name = Sesuaikan antarmuka untuk menampilkan takik
+setting.macnotch.name = Sesuaikan tampilan dengan batas layar
setting.macnotch.description = Mulai ulang diperlukan untuk menerapkan perubahan
-steam.friendsonly = Friends Only
-steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join.
-public.beta = Ingat bahwa game versi beta tidak dapat membuat lobi publik.
+steam.friendsonly = Hanya Teman
+steam.friendsonly.tooltip = Mengatur bisa atau tidaknya teman Steam bergabung ke permainanmu.\nMenghapus centang pada kotak ini akan membuat permainan Anda menjadi publik - siapa saja dapat bergabung.
+public.beta = Ingat bahwa game dalam versi beta tidak dapat membuat lobi publik.
uiscale.reset = Skala UI telah diubah.\nTekan "OK" untuk mengonfirmasi.\n[scarlet]Kembali dan keluar di[accent] {0}[] pengaturan...
uiscale.cancel = Batal & Keluar
setting.bloom.name = Bloom
@@ -1214,7 +1252,7 @@ keybind.title = Ganti Tombol
keybinds.mobile = [scarlet]Mayoritas tombol tidak didukung oleh perangkat ponsel. Hanya gerakan dasar yang didukung.
category.general.name = Umum
category.view.name = Melihat
-category.command.name = Unit Command
+category.command.name = Perintah Unit
category.multiplayer.name = Bermain Bersama
category.blocks.name = Pilih Blok
placement.blockselectkeys = \n[lightgray]Tombol: [{0},
@@ -1224,7 +1262,7 @@ keybind.clear_building.name = Hapus Bangunan
keybind.press = Tekan tombol...
keybind.press.axis = Tekan sumbu atau tombol...
keybind.screenshot.name = Tangkapan Layar Peta
-keybind.toggle_power_lines.name = Aktifkan Tenaga Laser
+keybind.toggle_power_lines.name = Aktifkan Laser Tenaga
keybind.toggle_block_status.name = Status Blok
keybind.move_x.name = Pindah X
keybind.move_y.name = Pindah Y
@@ -1232,14 +1270,15 @@ keybind.mouse_move.name = Ikuti Tetikus
keybind.pan.name = Tampilan Geser
keybind.boost.name = Dorongan
keybind.command_mode.name = Mode Perintah
-keybind.command_queue.name = Unit Command Queue
-keybind.create_control_group.name = Create Control Group
-keybind.cancel_orders.name = Cancel Orders
-keybind.unit_stance_shoot.name = Unit Stance: Shoot
-keybind.unit_stance_hold_fire.name = Unit Stance: Hold Fire
-keybind.unit_stance_pursue_target.name = Unit Stance: Pursue Target
-keybind.unit_stance_patrol.name = Unit Stance: Patrol
-keybind.unit_stance_ram.name = Unit Stance: Ram
+keybind.command_queue.name = Antrian Perintah Unit
+keybind.create_control_group.name = Buat Grup Kendali
+keybind.cancel_orders.name = Batalkan Perintah
+
+keybind.unit_stance_shoot.name = Posisi Unit: Tembak
+keybind.unit_stance_hold_fire.name = Posisi Unit: Tahan Tembakan
+keybind.unit_stance_pursue_target.name = Posisi Unit: Mengejar Target
+keybind.unit_stance_patrol.name = Posisi Unit: Patroli
+keybind.unit_stance_ram.name = Posisi Unit: Tabrak
keybind.unit_command_move.name = Unit Command: Move
keybind.unit_command_repair.name = Unit Command: Repair
keybind.unit_command_rebuild.name = Unit Command: Rebuild
@@ -1249,12 +1288,14 @@ keybind.unit_command_boost.name = Unit Command: Boost
keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
-keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
-keybind.rebuild_select.name = Rebuild Region
+keybind.unit_command_enter_payload.name = Perintah Unit: Masuk ke Muatan
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
+
+keybind.rebuild_select.name = Membangun Wilayah Kembali
keybind.schematic_select.name = Pilih Daerah
keybind.schematic_menu.name = Menu Skema
-keybind.schematic_flip_x.name = Balik Skema X
-keybind.schematic_flip_y.name = Balik Skema Y
+keybind.schematic_flip_x.name = Balik Skematik Horizontal
+keybind.schematic_flip_y.name = Balik Skematik Vertikal
keybind.category_prev.name = Kategori Sebelumnya
keybind.category_next.name = Kategori Selanjutnya
keybind.block_select_left.name = Pilih Blok Kiri
@@ -1276,8 +1317,8 @@ keybind.select.name = Pilih/Tembak
keybind.diagonal_placement.name = Penaruhan Diagonal
keybind.pick.name = Memilih Blok
keybind.break_block.name = Menghancurkan Blok
-keybind.select_all_units.name = Select All Units
-keybind.select_all_unit_factories.name = Select All Unit Factories
+keybind.select_all_units.name = Pilih Semua Unit
+keybind.select_all_unit_factories.name = Pilih Semua Pabrik Unit
keybind.deselect.name = Batal Memilih
keybind.pickupCargo.name = Angkat Muatan
keybind.dropCargo.name = Turunkan Muatan
@@ -1291,78 +1332,82 @@ keybind.planet_map.name = Peta Planet
keybind.research.name = Penelitian
keybind.block_info.name = Info Blok
keybind.chat.name = Pesan
-keybind.player_list.name = Daftar pemain
+keybind.player_list.name = Daftar Pemain
keybind.console.name = Papan Konsol
keybind.rotate.name = Putar
-keybind.rotateplaced.name = Putar yang ada (Tekan dan Tahan)
-keybind.toggle_menus.name = Muncul Tidaknya Menu
+keybind.rotateplaced.name = Putar yang telah Dibangun (Tekan dan Tahan)
+keybind.toggle_menus.name = Aktifkan Menu
keybind.chat_history_prev.name = Sejarah Pesan Sebelumnya
keybind.chat_history_next.name = Sejarah Pesan Setelahnya
-keybind.chat_scroll.name = Scroll Pesan
+keybind.chat_scroll.name = Gulir Pesan
keybind.chat_mode.name = Ubah Mode Pesan
-keybind.drop_unit.name = Jatuhkan Unit
+keybind.drop_unit.name = Turunkan Unit
keybind.zoom_minimap.name = Perbesar Peta Kecil
-mode.help.title = Deskripsi mode
+mode.help.title = Deskripsi mode permainan
mode.survival.name = Bertahan Hidup
-mode.survival.description = Mode normal. Sumber daya terbatas dan gelombang otomatis.\n[gray]Membutuhkan titik munculnya musuh di dalam peta untuk main.
-mode.sandbox.name = Mode Sandbox/Bebas
+mode.survival.description = Mode normal. Sumber daya terbatas dan gelombang otomatis.\n[gray]Membutuhkan zona pendaratan musuh di dalam peta untuk bermain.
+mode.sandbox.name = Sandbox/Bebas
mode.sandbox.description = Sumber daya tak terbatas dan tidak ada gelombang otomatis.
mode.editor.name = Penyunting
mode.pvp.name = PvP
-mode.pvp.description = Melawan pemain lain.\n[gray]Membutuhkan setidaknya 2 inti berbeda warna di dalam peta untuk main.
+mode.pvp.description = Lawan pemain lain dalam permainan lokal.\n[gray]Membutuhkan setidaknya 2 inti dengan warna berbeda di dalam peta untuk bermain.
mode.attack.name = Penyerangan
mode.attack.description = Hancurkan markas musuh. Membutuhkan inti merah di dalam peta untuk main.
mode.custom = Pengaturan Modifikasi
-rules.invaliddata = Invalid clipboard data.
-rules.hidebannedblocks = Hide Banned Blocks
+rules.invaliddata = Data papan klip tidak valid.
+rules.hidebannedblocks = Sembunyikan Blok Terlarang
rules.infiniteresources = Sumber Daya Tak Terbatas
rules.onlydepositcore = Hanya Izinkan Penyetoran Inti
-rules.derelictrepair = Allow Derelict Block Repair
+rules.derelictrepair = Izinkan Perbaikan Blok
rules.reactorexplosions = Ledakan Reaktor
rules.coreincinerates = Penghangusan Luapan Inti
rules.disableworldprocessors = Nonaktifkan Prosesor Dunia
-rules.schematic = Bagan Diperbolehkan
+rules.schematic = Skema Diperbolehkan
rules.wavetimer = Pengaturan Waktu Gelombang
-rules.wavesending = Wave Sending
-rules.allowedit = Allow Editing Rules
-rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.wavesending = Pengiriman Gelombang
+rules.allowedit = Izinkan Aturan Pengeditan
+rules.allowedit.info = Ketika diaktifkan, pemain dapat mengedit aturan dalam game melalui tombol di sudut kiri bawah pada menu Jeda.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Gelombang
-rules.airUseSpawns = Air units use spawn points
+rules.airUseSpawns = Unit udara menggunakan titik muncul
rules.attack = Mode Penyerangan
-rules.buildai = Base Builder AI
-rules.buildaitier = Builder AI Tier
-rules.rtsai = A.I. RTS
+rules.buildai = A.I. Pembangun Markas
+rules.buildaitier = Tingkat A.I. Pembangun
+rules.rtsai = A.I. RTS [red](WIP)
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Ukuran Regu Minimum
rules.rtsmaxsquadsize = Ukuran Regu Maksimum
rules.rtsminattackweight = Berat Serangan Minimum
rules.cleanupdeadteams = Bersihkan Bangunan Tim yang Kalah (PvP)
-rules.corecapture = Tangkap Inti Saat Kehancuran
+rules.corecapture = Kuasai Inti Saat Penghancuran
rules.polygoncoreprotection = Poligon Pelindung Inti
-rules.placerangecheck = Pemeriksaan Rentang Penempatan
-rules.enemyCheat = Sumber Daya A.I. (Tim Merah) Tak Terbatas
+rules.placerangecheck = Pemeriksaan Jarak Penempatan
+rules.enemyCheat = Sumber Daya Musuh Tak Terbatas
rules.blockhealthmultiplier = Penggandaan Darah Blok
rules.blockdamagemultiplier = Penggandaan Kekuatan Blok
rules.unitbuildspeedmultiplier = Penggandaan Kecepatan Munculnya Unit
-rules.unitcostmultiplier = Unit Cost Multiplier
+rules.unitcostmultiplier = Penggandaan Bahan Pembuatan Unit
rules.unithealthmultiplier = Penggandaan Darah Unit
rules.unitdamagemultiplier = Penggandaan Kekuatan Unit
-rules.unitcrashdamagemultiplier = Unit Crash Damage Multiplier
+rules.unitcrashdamagemultiplier = Penggandaan Kerusakan Jatuhnya Unit
rules.solarmultiplier = Penggandaan Tenaga Surya
rules.unitcapvariable = Inti Memengaruhi Batas Unit
-rules.unitpayloadsexplode = Carried Payloads Explode With The Unit
+rules.unitpayloadsexplode = Muatan yang Dibawa Meledak Bersama Unit
rules.unitcap = Batas Unit Dasar
rules.limitarea = Batas Area Peta
-rules.enemycorebuildradius = Dilarang Membangun Radius Inti Musuh :[lightgray] (blok)
+rules.enemycorebuildradius = Dilarang Membangun di Radius Inti Musuh :[lightgray] (ubin)
rules.wavespacing = Jarak Gelombang:[lightgray] (detik)
-rules.initialwavespacing = Rentang Gelombang Awal:[lightgray] (sec)
+rules.initialwavespacing = Jarak Gelombang Awal:[lightgray] (detik)
rules.buildcostmultiplier = Penggandaan Harga Bangunan
-rules.buildspeedmultiplier = Penggandaan Waktu Pembuatan Bangunan
+rules.buildspeedmultiplier = Penggandaan Waktu Pembangunan
rules.deconstructrefundmultiplier = Penggandaan Kembalinya Bahan Bangunan yang Dihancurkan
rules.waitForWaveToEnd = Gelombang Menunggu Musuh
-rules.wavelimit = Map Ends After Wave
-rules.dropzoneradius = Radius Titik Muncul:[lightgray] (ubin)
-rules.unitammo = Unit Membutuhkan Amunisi
+rules.wavelimit = Peta Berakhir Setelah Gelombang
+rules.dropzoneradius = Radius Zona Pendaratan :[lightgray] (ubin)
+rules.unitammo = Unit Membutuhkan Amunisi [red](mungkin dihapus)
rules.enemyteam = Tim Musuh
rules.playerteam = Tim Pemain
rules.title.waves = Gelombang
@@ -1375,16 +1420,21 @@ rules.title.teams = Tim
rules.title.planet = Planet
rules.lighting = Penerangan
rules.fog = Kabut Perang
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Api
rules.anyenv =
rules.explosions = Kekuatan Ledakan Blok/Unit
-rules.ambientlight = Sinar Disekeliling
+rules.ambientlight = Cahaya Di Sekeliling
rules.weather = Cuaca
rules.weather.frequency = Frekuensi:
rules.weather.always = Selalu
rules.weather.duration = Durasi:
-rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
-rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
+
+rules.placerangecheck.info = Mencegah pemain menempatkan apa pun di dekat bangunan musuh. Ketika mencoba memasang menara, jangkauannya akan ditingkatkan sehingga menara tidak akan bisa menjangkau musuh.
+rules.onlydepositcore.info = Mencegah unit menyimpan bahan ke dalam bangunan apa pun kecuali inti.
content.item.name = Bahan
content.liquid.name = Zat Cair
@@ -1404,15 +1454,15 @@ item.titanium.name = Titanium
item.thorium.name = Torium
item.silicon.name = Silikon
item.plastanium.name = Plastanium
-item.phase-fabric.name = Kain Phase
-item.surge-alloy.name = Campuran Logam
+item.phase-fabric.name = Phase Fabric
+item.surge-alloy.name = Paduan Logam
item.spore-pod.name = Polong Spora
item.sand.name = Pasir
item.blast-compound.name = Senyawa Peledak
item.pyratite.name = Pyratit
item.metaglass.name = Metaglass
item.scrap.name = Rongsokan
-item.fissile-matter.name = Materi Fissil
+item.fissile-matter.name = Bahan Fisil
item.beryllium.name = Berilium
item.tungsten.name = Tungsten
item.oxide.name = Oksida
@@ -1422,9 +1472,9 @@ item.dormant-cyst.name = Kista Nonaktif
liquid.water.name = Air
liquid.slag.name = Lava
liquid.oil.name = Minyak
-liquid.cryofluid.name = Cairan Dingin
+liquid.cryofluid.name = Kriogenik
liquid.neoplasm.name = Neoplasma
-liquid.arkycite.name = Arkisit
+liquid.arkycite.name = Arkycite
liquid.gallium.name = Galium
liquid.ozone.name = Ozon
liquid.hydrogen.name = Hidrogen
@@ -1499,7 +1549,7 @@ block.sand-boulder.name = Batu Pasir Besar
block.basalt-boulder.name = Batu Basal Besar
block.grass.name = Rumput
block.molten-slag.name = Lahar
-block.pooled-cryofluid.name = Cairan Dingin
+block.pooled-cryofluid.name = Kriogenik
block.space.name = Luar Angkasa
block.salt.name = Garam
block.salt-wall.name = Bukit Garam
@@ -1522,19 +1572,21 @@ block.scrap-wall-large.name = Dinding Rongsokan Besar
block.scrap-wall-huge.name = Dinding Rongsokan Sangat Besar
block.scrap-wall-gigantic.name = Dinding Rongsokan Raksasa
block.thruster.name = Pendorong
-block.kiln.name = Pengeringan
+block.kiln.name = Pembakar
block.graphite-press.name = Pencetak Grafit
block.multi-press.name = Multi-Cetak
-block.constructing = {0} [lightgray](Konstruksi)
-block.spawn.name = Muncul Musuh
-block.core-shard.name = Inti: Bagian
-block.core-foundation.name = Inti: Pondasi
-block.core-nucleus.name = Inti: Nukleus
-block.deep-water.name = Air Dalam
+block.constructing = {0} [lightgray](Membangun)
+block.spawn.name = Titik Musuh Muncul
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
+block.core-shard.name = Inti: Shard
+block.core-foundation.name = Inti: Foundation
+block.core-nucleus.name = Inti: Nucleus
+block.deep-water.name = Air yang Dalam
block.shallow-water.name = Air
-block.tainted-water.name = Air Ternoda
-block.deep-tainted-water.name = Air Dalam Ternoda
-block.darksand-tainted-water.name = Air Ternodai Pasir Hitam
+block.tainted-water.name = Air Tercemar
+block.deep-tainted-water.name = Air Tercemar yang Dalam
+block.darksand-tainted-water.name = Air Tercemar pada Pasir Hitam
block.tar.name = Minyak Mentah
block.stone.name = Batu
block.sand-floor.name = Pasir
@@ -1542,8 +1594,8 @@ block.darksand.name = Pasir Hitam
block.ice.name = Es
block.snow.name = Salju
block.crater-stone.name = Kawah
-block.sand-water.name = Air Pasir
-block.darksand-water.name = Air Pasir Hitam
+block.sand-water.name = Air pada Pasir
+block.darksand-water.name = Air pada Pasir Hitam
block.char.name = Bara
block.dacite.name = Dasit
block.rhyolite.name = Riolit
@@ -1585,39 +1637,39 @@ block.plastanium-wall.name = Dinding Plastanium
block.plastanium-wall-large.name = Dinding Plastanium Besar
block.phase-wall.name = Dinding Phase
block.phase-wall-large.name = Dinding Phase Besar
-block.thorium-wall.name = Dinding Thorium
-block.thorium-wall-large.name = Dinding Thorium Besar
+block.thorium-wall.name = Dinding Torium
+block.thorium-wall-large.name = Dinding Torium Besar
block.door.name = Pintu
block.door-large.name = Pintu Besar
block.duo.name = Duo
-block.scorch.name = Penyembur Api
-block.scatter.name = Penghambur
-block.hail.name = Penghujan
+block.scorch.name = Scorch
+block.scatter.name = Scatter
+block.hail.name = Hail
block.lancer.name = Lancer
-block.conveyor.name = Pengantar
-block.titanium-conveyor.name = Pengantar Berbahan Titanium
-block.plastanium-conveyor.name = Pengantar Berbahan Plastanium
-block.armored-conveyor.name = Pengantar Berlapis Pelindung
+block.conveyor.name = Konveyor
+block.titanium-conveyor.name = Konveyor Berbahan Titanium
+block.plastanium-conveyor.name = Konveyor Berbahan Plastanium
+block.armored-conveyor.name = Konveyor Berlapis Baja
block.junction.name = Simpangan
block.router.name = Pengarah
block.distributor.name = Distributor
block.sorter.name = Penyortir
block.inverted-sorter.name = Penyortir Terbalik
block.message.name = Pesan
-block.reinforced-message.name = Reinforced Message
-block.world-message.name = World Message
-block.world-switch.name = World Switch
+block.reinforced-message.name = Pesan yang Diperkuat
+block.world-message.name = Pesan Dunia
+block.world-switch.name = Saklar Dunia
block.illuminator.name = Lampu
block.overflow-gate.name = Gerbang Luap
block.underflow-gate.name = Gerbang Luap Terbalik
block.silicon-smelter.name = Pelebur Silikon
-block.phase-weaver.name = Pengrajut Phase
+block.phase-weaver.name = Pengerajut Phase
block.pulverizer.name = Penghancur
-block.cryofluid-mixer.name = Penyampur Cairan Dingin
+block.cryofluid-mixer.name = Pencampur Kriogenik
block.melter.name = Pencair
-block.incinerator.name = Penghangus
+block.incinerator.name = Insinerator
block.spore-press.name = Penekan Spora
-block.separator.name = Pemisah
+block.separator.name = Pemisah Rongsokan
block.coal-centrifuge.name = Sentrifugal Batu Bara
block.power-node.name = Simpul Tenaga
block.power-node-large.name = Simpul Tenaga Besar
@@ -1627,70 +1679,70 @@ block.battery.name = Baterai
block.battery-large.name = Baterai Besar
block.combustion-generator.name = Generator Pembakar
block.steam-generator.name = Generator Uap
-block.differential-generator.name = Generator Majemuk
+block.differential-generator.name = Generator Diferensial
block.impact-reactor.name = Reaktor Tumbukan
-block.mechanical-drill.name = Bor Mekanik
+block.mechanical-drill.name = Bor Mekanis
block.pneumatic-drill.name = Bor Pneumatik
block.laser-drill.name = Bor Laser
block.water-extractor.name = Pengekstrak Air
block.cultivator.name = Pembudidaya
-block.conduit.name = Pipa
-block.mechanical-pump.name = Pompa Mekanik
+block.conduit.name = Saluran
+block.mechanical-pump.name = Pompa Mekanis
block.item-source.name = Sumber Bahan
block.item-void.name = Penghilang Bahan
block.liquid-source.name = Sumber Zat Cair
block.liquid-void.name = Penghilang Zat Zair
block.power-void.name = Penghilang Tenaga
block.power-source.name = Sumber Tenaga
-block.unloader.name = Pembongkar Muatan
+block.unloader.name = Pembongkar
block.vault.name = Gudang
-block.wave.name = Penyemprot
+block.wave.name = Wave
block.tsunami.name = Tsunami
-block.swarmer.name = Peluncur Misil
+block.swarmer.name = Swarmer
block.salvo.name = Salvo
-block.ripple.name = Mortir
-block.phase-conveyor.name = Pengantar Berbahan Phase
-block.bridge-conveyor.name = Jembatan Pengantar
+block.ripple.name = Ripple
+block.phase-conveyor.name = Konveyor Berbahan Phase
+block.bridge-conveyor.name = Jembatan Konvenyor
block.plastanium-compressor.name = Kompresor Plastanium
-block.pyratite-mixer.name = Penyampur Pyratit
-block.blast-mixer.name = Penyampur Bahan Peledak
+block.pyratite-mixer.name = Pencampur Pyratit
+block.blast-mixer.name = Pencampur Bahan Peledak
block.solar-panel.name = Panel Surya
block.solar-panel-large.name = Panel Surya Besar
block.oil-extractor.name = Pengekstrak Minyak
-block.repair-point.name = Tempat Perbaikan
-block.repair-turret.name = Menara Pembaikan
-block.pulse-conduit.name = Selang Denyut
-block.plated-conduit.name = Pipa Terlapis
-block.phase-conduit.name = Selang Phase
+block.repair-point.name = Titik Perbaikan
+block.repair-turret.name = Menara Perbaikan
+block.pulse-conduit.name = Saluran Denyut
+block.plated-conduit.name = Saluran Terlapis
+block.phase-conduit.name = Saluran Phase
block.liquid-router.name = Pengarah Cairan
block.liquid-tank.name = Tangki Cairan
block.liquid-container.name = Kontainer Cairan
block.liquid-junction.name = Simpangan Cairan
block.bridge-conduit.name = Jembatan Saluran
block.rotary-pump.name = Pompa Putaran
-block.thorium-reactor.name = Reaktor Thorium
-block.mass-driver.name = Penggerak Massal
+block.thorium-reactor.name = Reaktor Torium
+block.mass-driver.name = Penembak Massal
block.blast-drill.name = Bor Ledakan Udara
block.impulse-pump.name = Pompa Suhu Panas
block.thermal-generator.name = Generator Panas
block.surge-smelter.name = Pelebur Paduan Logam
block.mender.name = Mender
-block.mend-projector.name = Mender Projektor
-block.surge-wall.name = Dinding Listrik
-block.surge-wall-large.name = Dinding Listrik Besar
-block.cyclone.name = Topan
-block.fuse.name = Murang
-block.shock-mine.name = Ranjau Listrik
-block.overdrive-projector.name = Projektor Pemercepat
-block.force-projector.name = Projektor Pelindung
-block.arc.name = Busur Petir
+block.mend-projector.name = Proyektor Mender
+block.surge-wall.name = Dinding Logam
+block.surge-wall-large.name = Dinding Logam Besar
+block.cyclone.name = Cyclone
+block.fuse.name = Fuse
+block.shock-mine.name = Ranjau Kejut
+block.overdrive-projector.name = Proyektor Pemercepat
+block.force-projector.name = Proyektor Pelindung
+block.arc.name = Arc
block.rtg-generator.name = Generator Radiasi
-block.spectre.name = Momok
-block.meltdown.name = Pelumer
+block.spectre.name = Spectre
+block.meltdown.name = Meltdown
block.foreshadow.name = Foreshadow
block.container.name = Kontainer
block.launch-pad.name = Alas Peluncur
-block.segment.name = Segmen
+block.segment.name = Segment
block.ground-factory.name = Pabrik Unit Darat
block.air-factory.name = Pabrik Unit Udara
block.naval-factory.name = Pabrik Unit Laut
@@ -1698,28 +1750,28 @@ block.additive-reconstructor.name = Rekonstruktor Aditif
block.multiplicative-reconstructor.name = Rekonstruktor Multiplikatif
block.exponential-reconstructor.name = Rekonstruktor Eksponensial
block.tetrative-reconstructor.name = Rekonstruktor Tetratif
-block.payload-conveyor.name = Pengantar Massa
-block.payload-router.name = Pengarah Massa
-block.duct.name = Saluran
-block.duct-router.name = Pengarah Saluran
-block.duct-bridge.name = Jembatan Saluran
-block.large-payload-mass-driver.name = Large Payload Mass Driver
+block.payload-conveyor.name = Konveyor Muatan
+block.payload-router.name = Pengarah Muatan
+block.duct.name = Pipa
+block.duct-router.name = Pengarah Pipa
+block.duct-bridge.name = Jembatan Pipa
+block.large-payload-mass-driver.name = Penembak Muatan Massal Besar
block.payload-void.name = Penghilang Muatan
block.payload-source.name = Sumber Muatan
-block.disassembler.name = Pembongkar
-block.silicon-crucible.name = Pelebur Raksasa
-block.overdrive-dome.name = Kubah Projektor Pemercepat
+block.disassembler.name = Pembongkar Rongsokan
+block.silicon-crucible.name = Tungku Peleburan Silikon
+block.overdrive-dome.name = Kubah Proyektor Pemercepat
block.interplanetary-accelerator.name = Akselerator Antarplanet
block.constructor.name = Konstruktor
-block.constructor.description = Membuat struktur hingga ubin berukuran 2x2.
+block.constructor.description = Membuat bangunan hingga ubin berukuran 2x2.
block.large-constructor.name = Konstruktor Besar
-block.large-constructor.description = Membuat struktur hingga ubin berukuran 4x4.
-block.deconstructor.name = Deskontruktor
+block.large-constructor.description = Membuat bangunan hingga ubin berukuran 4x4.
+block.deconstructor.name = Dekonstruktor Besar
block.deconstructor.description = Mendekonstruksi bangunan dan unit. Mengembalikan 100% dari biaya bahan.
-block.payload-loader.name = Pemuat Blok
-block.payload-loader.description = Memuat cairan dan item ke dalam blok.
-block.payload-unloader.name = Pembongkar Blok
-block.payload-unloader.description = Membongkar cairan dan item dari blok.
+block.payload-loader.name = Pemuat Muatan
+block.payload-loader.description = Memuat cairan dan bahan ke dalam blok.
+block.payload-unloader.name = Pembongkar Muatan
+block.payload-unloader.description = Membongkar cairan dan bahan dari blok.
block.heat-source.name = Sumber Panas
block.heat-source.description = Blok ukuran 1x1 yang memberikan panas tak terhingga.
@@ -1746,7 +1798,7 @@ block.carbon-vent.name = Ventilasi Karbon
block.arkyic-vent.name = Ventilasi Arkisit
block.yellow-stone-vent.name = Ventilasi Batu Kuning
block.red-stone-vent.name = Ventilasi Batu Merah
-block.crystalline-vent.name = Crystalline Vent
+block.crystalline-vent.name = Ventilasi Kristal
block.redmat.name = Matras Merah
block.bluemat.name = Matras Biru
block.core-zone.name = Zona Inti
@@ -1782,42 +1834,43 @@ block.silicon-arc-furnace.name = Tungku Listrik Silikon
block.electrolyzer.name = Elektroliser
block.atmospheric-concentrator.name = Konsentrator Atmosfer
block.oxidation-chamber.name = Ruangan Oksidasi
-block.electric-heater.name = Penghangat Listrik
-block.slag-heater.name = Penghangat Terak
-block.phase-heater.name = Penghangat Phase
-block.heat-redirector.name = Pengatur Panas
-block.heat-router.name = Heat Router
-block.slag-incinerator.name = Insinerator Terak
-block.carbide-crucible.name = Pelembur Karbit Raksasa
-block.slag-centrifuge.name = Sentrifugal Terak
-block.surge-crucible.name = Pelembur Surge Raksasa
-block.cyanogen-synthesizer.name = Sintesiser Sianogen
-block.phase-synthesizer.name = Sintetiser Phase
+block.electric-heater.name = Pemanas Listrik
+block.slag-heater.name = Pemanas Lava
+block.phase-heater.name = Pemanas Phase
+block.heat-redirector.name = Pengalih Panas
+block.small-heat-redirector.name = Small Heat Redirector
+block.heat-router.name = Pengarah Panas
+block.slag-incinerator.name = Insinerator Lava
+block.carbide-crucible.name = Tungku Peleburan Karbit
+block.slag-centrifuge.name = Sentrifugal Lava
+block.surge-crucible.name = Tungku Peleburan Logam
+block.cyanogen-synthesizer.name = Penyintesis Sianogen
+block.phase-synthesizer.name = Penyintesis Phase
block.heat-reactor.name = Reaktor Panas
block.beryllium-wall.name = Dinding Berilium
block.beryllium-wall-large.name = Dinding Berilium Besar
-block.tungsten-wall.name = Dingding Tungsten
+block.tungsten-wall.name = Dinding Tungsten
block.tungsten-wall-large.name = Dinding Tungsten Besar
block.blast-door.name = Pintu Blast
block.carbide-wall.name = Dinding Karbit
-block.carbide-wall-large.name = Dinding Karbit Raksasa
-block.reinforced-surge-wall.name = Dinding Surge yang Diperkuat
-block.reinforced-surge-wall-large.name = Dinding Surge Besar yang Diperkuat
-block.shielded-wall.name = Shielded Wall
+block.carbide-wall-large.name = Dinding Karbit Besar
+block.reinforced-surge-wall.name = Dinding Logam yang Diperkuat
+block.reinforced-surge-wall-large.name = Dinding Logam Besar yang Diperkuat
+block.shielded-wall.name = Dinding Berperisai
block.radar.name = Radar
-block.build-tower.name = Menara Pembangunan
+block.build-tower.name = Menara Pembangun
block.regen-projector.name = Proyektor Penyembuhan
-block.shockwave-tower.name = Shockwave Tower
-block.shield-projector.name = Proyektor Pelindung
-block.large-shield-projector.name = Proyektor Pelindung Besar
+block.shockwave-tower.name = Menara Gelombang Kejut
+block.shield-projector.name = Proyektor Perisai
+block.large-shield-projector.name = Proyektor Perisai Besar
block.armored-duct.name = Pipa Lapis Baja
block.overflow-duct.name = Pipa Luapan
block.underflow-duct.name = Pipa Arus Bawah
block.duct-unloader.name = Pipa Pembongkar Muatan
-block.surge-conveyor.name = Konveyor Surge
-block.surge-router.name = Pengarah Surge
-block.unit-cargo-loader.name = Pemuat Kargo Unit
-block.unit-cargo-unload-point.name = Titik Pembongkaran Kargo Unit
+block.surge-conveyor.name = Konveyor Berbahan Logam
+block.surge-router.name = Pengarah Berbahan Logam
+block.unit-cargo-loader.name = Pemuat Unit Kargo
+block.unit-cargo-unload-point.name = Titik Bongkar Muatan Unit Kargo
block.reinforced-pump.name = Pompa yang Diperkuat
block.reinforced-conduit.name = Saluran yang Diperkuat
block.reinforced-liquid-junction.name = Persimpangan Cairan yang Diperkuat
@@ -1833,13 +1886,14 @@ block.chemical-combustion-chamber.name = Ruang Pembakaran Kimia
block.pyrolysis-generator.name = Generator Pirolisis
block.vent-condenser.name = Kondensor Ventilasi
block.cliff-crusher.name = Penghancur Tebing
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Bor Plasma
block.large-plasma-bore.name = Bor Plasma Besar
block.impact-drill.name = Bor Tumbukan
block.eruption-drill.name = Bor Erupsi
-block.core-bastion.name = Inti: Baluarti
-block.core-citadel.name = Inti: Kastel
-block.core-acropolis.name = Inti: Akropolis
+block.core-bastion.name = Inti: Bastion
+block.core-citadel.name = Inti: Citadel
+block.core-acropolis.name = Inti: Acropolis
block.reinforced-container.name = Kontainer yang Diperkuat
block.reinforced-vault.name = Gudang yang Diperkuat
block.breach.name = Breach
@@ -1849,25 +1903,25 @@ block.disperse.name = Disperse
block.afflict.name = Afflict
block.lustre.name = Lustre
block.scathe.name = Scathe
-block.tank-refabricator.name = Refabrikator Tank
-block.mech-refabricator.name = Refabrikator Mech
-block.ship-refabricator.name = Refabrikator Kapal
+block.tank-refabricator.name = Pabrikator Ulang Tank
+block.mech-refabricator.name = Pabrikator Ulang Mech
+block.ship-refabricator.name = Pabrikator Ulang Kapal
block.tank-assembler.name = Perakitan Tank
block.ship-assembler.name = Perakitan Kapal
block.mech-assembler.name = Perakitan Mech
block.reinforced-payload-conveyor.name = Konveyor Muatan yang Diperkuat
block.reinforced-payload-router.name = Pengarah Muatan yang Diperkuat
-block.payload-mass-driver.name = Penggerak Massal Muatan
-block.small-deconstructor.name = Dekonstruktor Kecil
+block.payload-mass-driver.name = Penembak Muatan Massal
+block.small-deconstructor.name = Dekonstruktor
block.canvas.name = Kanvas
block.world-processor.name = Prosessor Dunia
block.world-cell.name = Sel Dunia
-block.tank-fabricator.name = Fabrikator Tank
-block.mech-fabricator.name = Fabrikator Mech
-block.ship-fabricator.name = Fabrikator Kapal
-block.prime-refabricator.name = Refabrikator Perdana
+block.tank-fabricator.name = Pabrikator Tank
+block.mech-fabricator.name = Pabrikator Mech
+block.ship-fabricator.name = Pabrikator Kapal
+block.prime-refabricator.name = Pabrikator Ulang Perdana
block.unit-repair-tower.name = Menara Perbaikan Unit
-block.diffuse.name = Pembaur
+block.diffuse.name = Diffuse
block.basic-assembler-module.name = Modul Perakitan Dasar
block.smite.name = Smite
block.malign.name = Malign
@@ -1886,115 +1940,116 @@ block.memory-bank.name = Bank Memori
team.malis.name = Malis
team.crux.name = Crux
team.sharded.name = Sharded
-team.derelict.name = Derelict
+team.derelict.name = Derelik
team.green.name = Hijau
team.blue.name = Biru
hint.skip = Lewati
-hint.desktopMove = Tekan [accent][[WASD][] untuk bergerak.
-hint.zoom = [accent]Skrol[] untuk membesarkan atau mengecilkan layar.
-hint.desktopShoot = [accent][[Klik][] untuk menembak.
-hint.depositItems = Untuk memindahkan bahan, tarik bahan dari pesawatmu ke inti.
+hint.desktopMove = Gunakan [accent][[WASD][] untuk bergerak.
+hint.zoom = [accent]Gulir[] untuk membesarkan atau mengecilkan layar.
+hint.desktopShoot = [accent][[Klik Kanan][] untuk menembak.
+hint.depositItems = Untuk memindahkan bahan, seret dari pesawatmu ke inti.
hint.respawn = Untuk muncul kembali seperti awal, tekan [accent][[V][].
-hint.respawn.mobile = Kamu telah mengambil alih kendali dari sebuah unit/struktur. Untuk muncul kembali, [accent]tekan avatar di kiri atas.[]
+hint.respawn.mobile = Anda telah mengambil alih kendali dari sebuah unit atau bangunan. Untuk muncul kembali sebagai pesawat, [accent]ketuk avatar di kiri atas.[]
hint.desktopPause = Tekan [accent][[Spasi][] untuk menjeda dan menghentikan jeda permainan.
hint.breaking = [accent]Klik kanan[] dan tarik untuk menghancurkan blok.
-hint.breaking.mobile = Aktifkan \ue817 [accent]palu[] di kanan bawah dan tekan untuk menghancurkan blok.\n\nTahan jari kamu sebentar dan seret untuk menghancurkannya.
+hint.breaking.mobile = Aktifkan \ue817 [accent]palu[] di kanan bawah dan ketuk untuk menghancurkan blok.\n\nTahan jari Anda untuk beberapa saat lalu seret pada bagian yang dipilih untuk menghancurkannya.
hint.blockInfo = Lihat informasi dari sebuah blok dengan memilihnya di [accent]menu bangun[], lalu pilih tombol [accent][[?][] di sebelah kanan.
hint.derelict = Bangunan berwarna [accent]abu-abu[] adalah sisa-sisa dari markas lama yang hancur dan tidak dapat berfungsi kembali.\n\nBangunan tersebut dapat [accent]didekonstruksi[] menjadi sumber daya.
-hint.research = Gunakan tombol \ue875 [accent]Riset[] untuk mempelajari teknologi baru.
+hint.research = Gunakan tombol \ue875 [accent]Penelitian[] untuk mempelajari teknologi baru.
hint.research.mobile = Gunakan tombol \ue875 [accent]Riset[] di \ue88c [accent]Menu[] untuk mempelajari teknologi baru.
-hint.unitControl = Tahan [accent][[L-ctrl][] dan [accent]klik[] untuk mengendalikan unit atau turret teman.
-hint.unitControl.mobile = [accent][Klik dua kali[] untuk mengendalikan unit atau turret teman.
-hint.unitSelectControl = To control units, enter [accent]command mode[] by holding [accent]L-shift.[]\nWhile in command mode, click and drag to select units. [accent]Right-click[] a location or target to command units there.
-hint.unitSelectControl.mobile = To control units, enter [accent]command mode[] by pressing the [accent]command[] button in the bottom left.\nWhile in command mode, long-press and drag to select units. Tap a location or target to command units there.
-hint.launch = Ketika sumber daya sudah mencukupi, kamu bisa [accent]Meluncurkan[] dengan memilih sektor terdekat dari \ue827 [accent]Map[] di kanan bawah.
-hint.launch.mobile = Ketika sumber daya sudah mencukupi, kamu bisa [accent]Meluncurkan[] dengan memilih sektor terdekat dari \ue827 [accent]Map[] di \ue88c [accent]Menu[].
-hint.schematicSelect = Tahan [accent][[F][] dan tarik ke bangunan untuk menyalin bangunan.\n\n[accent][[Klik tengah][] untuk menyalin blok setipe.
-hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
-hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
-hint.conveyorPathfind = Tahan [accent][[L-Ctrl][] ketika menarik pengantar untuk membuat jalur secara otomatis.
-hint.conveyorPathfind.mobile = Aktifkan \ue844 [accent]diagonal mode[] dan tarik pengantar untuk membuat jalur secara otomatis.
-hint.boost = Tahan [accent][[L-Shift][] untuk terbang dengan unit sekarang.\n\nHanya beberapa unit darat yang memiliki pendorong.
-hint.payloadPickup = Tekan [accent][[[] untuk membawa blok kecil atau unit.
-hint.payloadPickup.mobile = [accent]Tekan dan tahan[] untuk membawa blok kecil atau unit.
+hint.unitControl = Tekan dan Tahan [accent][[L-ctrl][] dan [accent]klik[] untuk mengendalikan unit atau turret sekutu.
+hint.unitControl.mobile = [accent][Ketuk dua kali[] untuk mengendalikan unit atau turret sekutu.
+hint.unitSelectControl = Untuk mengendalikan unit, masuki [accent]mode perintah[] dengan menahan tombol [accent]L-shift.[]\nDalam mode perintah, klik dan seret untuk memilih unit. [accent]Klik Kanan[] pada suatu lokasi atau target untuk memerintahkan unit.
+hint.unitSelectControl.mobile = Untuk mengendalikan unit, masuki [accent]mode perintah[] dengan menekan tombol [accent]perintah[] di pojok kanan bawah.\nDalam mode perintah, tekan layar untuk beberapa saat dan seret untuk memilih unit. ketuk pada suatu lokasi atau target untuk memerintahkan unit.
+hint.launch = Ketika sumber daya sudah mencukupi, Anda dapat [accent]Meluncurkan Inti[] dengan memilih sektor terdekat dari \ue827 [accent]Peta[] di kanan bawah.
+hint.launch.mobile = Ketika sumber daya sudah mencukupi, Anda bisa [accent]Meluncurkan Inti[] dengan memilih sektor terdekat dari \ue827 [accent]Peta[] dibagian \ue88c [accent]Menu[].
+hint.schematicSelect = Tahan tombol [accent][[F][] dan seret ke bangunan untuk menyalin bangunan.\n\n[accent][[Klik tengah][] untuk menyalin satu jenis blok.
+hint.rebuildSelect = Tahan tombol [accent][[B][] dan seret untuk memilih bagian blok yang hancur.\nIni akan membangunnya kembali secara otomatis.
+hint.rebuildSelect.mobile = Pilih Tombol \ue874 salin, lalu ketuk tombol \ue80f bangun kembali dan seret untuk memilih blok yang hancur.\nIni akan membangun ulang secara otomatis.
+hint.conveyorPathfind = Tahan [accent][[L-Ctrl][] ketika menarik konveyor untuk membuat jalur secara otomatis.
+hint.conveyorPathfind.mobile = Ketuk \ue844 [accent]mode diagonal[] dan tarik konveyor untuk membuat jalur secara otomatis.
+hint.boost = Tahan [accent][[L-Shift][] untuk terbang dengan unit.\n\nHanya beberapa unit darat yang memiliki pendorong.
+hint.payloadPickup = Tekan [accent][[[] untuk mengambil blok kecil atau unit.
+hint.payloadPickup.mobile = [accent]Ketuk dan tahan[] untuk mengambil blok kecil atau unit.
hint.payloadDrop = Tekan [accent]][] untuk menurunkan muatan.
hint.payloadDrop.mobile = [accent]Tekan dan tahan[] di lokasi yang kosong untuk menurunkan muatan.
hint.waveFire = [accent]Wave[] yang terisi dengan air akan memadamkan air dalam jangkauannya.
-hint.generator = \uf879 [accent]Generator Pembakar[] membakar batu bara dan menghasilkan energik ke blok yang berdekatan.\n\nTransmisi energi dapat diperluas menggunakan \uf87f [accent]Tiang Listrik[].
+hint.generator = \uf879 [accent]Generator Pembakar[] membakar batu bara dan menghasilkan energi ke blok yang berdekatan.\n\nTransmisi energi dapat diperluas dengan \uf87f [accent]Simpul Daya[].
hint.guardian = Unit [accent]Penjaga[] adalah unit yang diperkuat. Amunisi lemah seperti [accent]Tembaga[] dan [accent]Timah[] [scarlet]tidak efektif[].\n\nGunakan menara yang lebih bagus atau amunisi yang lebih kuat seperti \uf835 [accent]Grafit[] \uf861Duo/\uf859Salvo untuk menghancurkan Penjaga.
-hint.coreUpgrade = Inti dapat ditingkatkan dengan cara [accent]meletakkan yang lebih besar diatasnya[].\n\nLetakan sebuah inti \uf868 [accent]Fondasi[] diatas inti \uf869 [accent]Shard[]. Pastikan terdapat ruang kosong dari bangunan yang lain.
-hint.presetLaunch = [accent]Zona pendaratan[] yang berwarna abu-abu, seperti [accent]Hutan yang Beku[], dapat diluncurkan dari mana saja. Sektor seperti ini tidak perlu diluncurkan dari sektor terdekat milik kamu.\n\n[accent]Sektor yang bernomor[], seperti yang ini, bisa [accent]dikuasai atau diabaikan[].
-hint.presetDifficulty = Sektor ini memiliki [scarlet]ancaman bahaya musuh yang tinggi[].\nMeluncurkan ke sektor tersebut [accent]tidak disarankan[] tanpa teknologi yang sesuai dan persiapan yang matang.
-hint.coreIncinerate = Setelah inti penuh dengan suatu barang, barang yang setipe akan [accent]dihancurkan[].
+hint.coreUpgrade = Inti dapat ditingkatkan dengan cara [accent]meletakkan Inti yang lebih besar di atasnya[].\n\nLetakan sebuah inti \uf868 [accent]Foundation[] diatas inti \uf869 [accent]Shard[]. Pastikan terdapat ruang kosong dari bangunan yang lain.
+hint.presetLaunch = [accent]Zona pendaratan[] yang berwarna abu-abu, seperti [accent]Hutan yang Beku[], dapat diluncurkan dari mana saja. Sektor seperti ini tidak perlu diluncurkan dari sektor terdekat milik Anda.\n\n[accent]Sektor yang bernomor[], seperti yang ini, bersifat [accent]opsional[].
+hint.presetDifficulty = Sektor ini memiliki [scarlet]tingkat ancaman musuh yang tinggi[].\nMeluncurkan ke sektor tersebut [accent]tidak disarankan[] tanpa teknologi yang sesuai dan persiapan yang matang.
+hint.coreIncinerate = Setelah inti penuh dengan suatu barang, barang yang sejenis akan [accent]dihanguskan[].
hint.factoryControl = Untuk menentukan [accent]tempat keluar[] unit pabrik, klik blok pabrik ketika dalam mode perintah, lalu klik kanan lokasi yang diinginkan.\nUnit yang diproduksi akan langsung bergerak ke tempat yang ditentukan.
-hint.factoryControl.mobile = Untuk menentukan [accent]tempat keluar[] unit pabrik, tekan blok pabrik ketika dalam mode perintah, lalu tekan lokasi yang diinginkan.\nUnit yang diproduksi akan langsung bergerak ke tempat yang ditentukan.
-gz.mine = Move near the \uf8c4 [accent]copper ore[] on the ground and click to begin mining.
-gz.mine.mobile = Move near the \uf8c4 [accent]copper ore[] on the ground and tap it to begin mining.
-gz.research = Open the \ue875 tech tree.\nResearch the \uf870 [accent]Mechanical Drill[], then select it from the menu in the bottom right.\nClick on a copper patch to place it.
-gz.research.mobile = Open the \ue875 tech tree.\nResearch the \uf870 [accent]Mechanical Drill[], then select it from the menu in the bottom right.\nTap on a copper patch to place it.\n\nPress the \ue800 [accent]checkmark[] at the bottom right to confirm.
-gz.conveyors = Research and place \uf896 [accent]conveyors[] to move the mined resources\nfrom drills to the core.\n\nClick and drag to place multiple conveyors.\n[accent]Scroll[] to rotate.
-gz.conveyors.mobile = Research and place \uf896 [accent]conveyors[] to move the mined resources\nfrom drills to the core.\n\nHold down your finger for a second and drag to place multiple conveyors.
-gz.drills = Expand the mining operation.\nPlace more Mechanical Drills.\nMine 100 copper.
-gz.lead = \uf837 [accent]Lead[] is another commonly used resource.\nSet up drills to mine lead.
-gz.moveup = \ue804 Move up for further objectives.
-gz.turrets = Research and place 2 \uf861 [accent]Duo[] turrets to defend the core.\nDuo turrets require \uf838 [accent]ammo[] from conveyors.
-gz.duoammo = Supply the Duo turrets with [accent]copper[], using conveyors.
-gz.walls = [accent]Walls[] can prevent oncoming damage from reaching buildings.\nPlace \uf8ae [accent]copper walls[] around the turrets.
-gz.defend = Enemy incoming, prepare to defend.
-gz.aa = Flying units cannot easily be dispatched with standard turrets.\n\uf860 [accent]Scatter[] turrets provide excellent anti-air, but require \uf837 [accent]lead[] as ammo.
-gz.scatterammo = Supply the Scatter turret with [accent]lead[], using conveyors.
-gz.supplyturret = [accent]Supply Turret
-gz.zone1 = This is the enemy drop zone.
-gz.zone2 = Anything built in the radius is destroyed when a wave starts.
-gz.zone3 = A wave will begin now.\nGet ready.
-gz.finish = Build more turrets, mine more resources,\nand defend against all the waves to [accent]capture the sector[].
-onset.mine = Click to mine \uf748 [accent]beryllium[] from walls.\n\nUse [accent][[WASD] to move.
-onset.mine.mobile = Tap to mine \uf748 [accent]beryllium[] from walls.
-onset.research = Open the \ue875 tech tree.\nResearch, then place a \uf73e [accent]turbine condenser[] on the vent.\nThis will generate [accent]power[].
-onset.bore = Research and place a \uf741 [accent]plasma bore[].\nThis automatically mines resources from walls.
-onset.power = To [accent]power[] the plasma bore, research and place a \uf73d [accent]beam node[].\nConnect the turbine condenser to the plasma bore.
-onset.ducts = Research and place \uf799 [accent]ducts[] to move the mined resources from the plasma bore to the core.\nClick and drag to place multiple ducts.\n[accent]Scroll[] to rotate.
-onset.ducts.mobile = Research and place \uf799 [accent]ducts[] to move the mined resources from the plasma bore to the core.\n\nHold down your finger for a second and drag to place multiple ducts.
-onset.moremine = Expand the mining operation.\nPlace more Plasma Bores and use beam nodes and ducts to support them.\nMine 200 beryllium.
-onset.graphite = More complex blocks require \uf835 [accent]graphite[].\nSet up plasma bores to mine graphite.
-onset.research2 = Begin researching [accent]factories[].\nResearch the \uf74d [accent]cliff crusher[] and \uf779 [accent]silicon arc furnace[].
-onset.arcfurnace = The arc furnace needs \uf834 [accent]sand[] and \uf835 [accent]graphite[] to create \uf82f [accent]silicon[].\n[accent]Power[] is also required.
-onset.crusher = Use \uf74d [accent]cliff crushers[] to mine sand.
-onset.fabricator = Use [accent]units[] to explore the map, defend buildings, and attack the enemy. Research and place a \uf6a2 [accent]tank fabricator[].
-onset.makeunit = Produce a unit.\nUse the "?" button to see selected factory requirements.
-onset.turrets = Units are effective, but [accent]turrets[] provide better defensive capabilities if used effectively.\nPlace a \uf6eb [accent]Breach[] turret.\nTurrets require \uf748 [accent]ammo[].
-onset.turretammo = Supply the turret with [accent]beryllium ammo.[]
-onset.walls = [accent]Walls[] can prevent oncoming damage from reaching buildings.\nPlace some \uf6ee [accent]beryllium walls[] around the turret.
-onset.enemies = Enemy incoming, prepare to defend.
-onset.defenses = [accent]Set up defenses:[lightgray] {0}
-onset.attack = The enemy is vulnerable. Counter-attack.
-onset.cores = New cores can be placed on [accent]core tiles[].\nNew cores function as forward bases and share a resource inventory with other cores.\nPlace a \uf725 core.
-onset.detect = The enemy will be able to detect you in 2 minutes.\nSet up defenses, mining, and production.
+hint.factoryControl.mobile = Untuk menentukan [accent]tempat keluar[] unit pabrik, ketuk blok pabrik ketika dalam mode perintah, lalu ketuk lokasi yang diinginkan.\nUnit yang diproduksi akan langsung bergerak ke tempat yang ditentukan.
-#Don't translate these yet!
-onset.commandmode = Hold [accent]shift[] to enter [accent]command mode[].\n[accent]Left-click and drag[] to select units.\n[accent]Right-click[] to order selected units to move or attack.
-onset.commandmode.mobile = Press the [accent]command button[] to enter [accent]command mode[].\nHold down a finger, then [accent]drag[] to select units.\n[accent]Tap[] to order selected units to move or attack.
-aegis.tungsten = Tungsten can be mined using an [accent]impact drill[].\nThis structure requires [accent]water[] and [accent]power[].
-split.pickup = Some blocks can be picked up by the core unit.\nPick up this [accent]container[] and place it onto the [accent]payload loader[].\n(Default keys are [ and ] to pick up and drop)
-split.pickup.mobile = Some blocks can be picked up by the core unit.\nPick up this [accent]container[] and place it onto the [accent]payload loader[].\n(To pick up or drop something, long-press it.)
-split.acquire = You must acquire some tungsten to build units.
-split.build = Units must be transported to the other side of the wall.\nPlace two [accent]Payload Mass Drivers[], one on each side of the wall.\nSet up the link by pressing one of them, then selecting the other.
-split.container = Similar to the container, units can also be transported using a [accent]Payload Mass Driver[].\nPlace a unit fabricator adjacent to a mass driver to load them, then send them across the wall to attack the enemy base.
+gz.mine = Bergerak di dekat \uf8c4 [accent]bijih tembaga[] di tanah dan klik untuk mulai menambang.
+gz.mine.mobile = Bergerak di dekat \uf8c4 [accent]bijih tembaga[] di tanah dan ketuk untuk mulai menambang.
+gz.research = Buka \ue875 pohon teknologi.\nRiset \uf870 [accent]Bor Mekanik[], lalu pilih dari menu di kanan bawah.\nKlik pada tambalan tembaga untuk menempatkannya.
+gz.research.mobile = Buka \ue875 pohon teknologi.\nRiset \uf870 [accent]Bor Mekanik[], lalu pilih dari menu di kanan bawah.\nKetuk pada tambalan tembaga untuk menempatkannya.\n\nKetuk \ue800 [accent]tanda centang[] di kanan bawah untuk mengonfirmasi.
+gz.conveyors = Riset dan tempatkan \uf896 [accent]konveyor[] untuk memindahkan sumber daya yang ditambang\ndari bor ke inti.\n\nKlik dan seret untuk menempatkan beberapa konveyor.\n[accent]Gulir[] untuk memutar arah konveyor
+gz.conveyors.mobile = Riset dan tempatkan \uf896 [accent]konveyor[] untuk memindahkan sumber daya yang ditambang\ndari bor ke inti.\n\nTahan jari Anda sebentar dan seret untuk menempatkan beberapa konveyor.
+gz.drills = Perluas operasi penambangan.\ntempatkan lebih banyak Bor Mekanik.\nTambang 100 tembaga.
+gz.lead = \uf837 [accent]Timah[] adalah sumber daya lain yang umum digunakan.\nSiapkan bor untuk menambang timah.
+gz.moveup = \ue804 Bergerak ke atas untuk objektif lebih lanjut.
+gz.turrets = Riset dan tempatkan 2 menara \uf861 [accent]Duo[] untuk mempertahankan inti.\nMenara Duo membutuhkan \uf838 [accent]amunisi[] dari konveyor.
+gz.duoammo = Suplai menara Duo dengan [accent]tembaga[], menggunakan konveyor.
+gz.walls = [accent]Dinding[] dapat menahan kerusakan yang mencapai bangunan.\nTempatkan \uf8ae [accent]dinding tembaga[] di sekitar menara.
+gz.defend = Musuh datang, bersiaplah untuk bertahan.
+gz.aa = Unit terbang tidak dapat dengan mudah dibunuh dengan menara standar.Menara\n\uf860 [accent]Scatter[] memberikan anti-udara yang sangat baik, tetapi membutuhkan \uf837 [accent]timah[] sebagai amunisi.
+gz.scatterammo = Suplai Menara Scatter dengan [accent]timah[], menggunakan konveyor.
+gz.supplyturret = [accent]Suplai Menara
+gz.zone1 = Ini adalah zona pendaratan musuh.
+gz.zone2 = Apa pun yang dibangun dalam radius tersebut akan hancur ketika gelombang mulai.
+gz.zone3 = Gelombang akan dimulai sekarang.Bersiap.
+gz.finish = Bangun lebih banyak menara, tambang lebih banyak sumber daya,\ndan bertahan melawan semua gelombang [accent]untuk menaklukkan sektor[].
+
+onset.mine = Klik untuk menambang \uf748 [accent]berillium[] dari dinding.\n\nGunakan tombol [accent][[WASD] untuk bergerak.
+onset.mine.mobile = Ketuk untuk menambang \uf748 [accent]berillium[] dari dinding.
+onset.research = Buka \ue875 pohon teknologi.\nRiset, dan tempatkan \uf73e [accent]kondensor turbin[] di ventilasi.\nIni akan menghasilkan [accent]tenaga[].
+onset.bore = Riset dan tempatkan \uf741 [accent]bor plasma[].\nIni secara otomatis mengekstraksi sumber daya dari dinding.
+onset.power = Untuk [accent]menyalakan[] bor plasma, riset dan tempatkan \uf73d [accent]simpul sinar[].\nHubungkan kondensor turbin ke bor plasma.
+onset.ducts = Riset dan tempatkan \uf799 [accent]pipa[] untuk memindahkan sumber daya yang ditambang dari bor plasma ke inti.\nklik dan seret untuk menempatkan beberapa saluran.\n[accent]Gulir[] untuk memutar.
+onset.ducts.mobile = Riset dan tempatkan \uf799 [accent]saluran[] untuk memindahkan sumber daya yang ditambang dari bor plasma ke inti.\n\nTahan jari Anda sebentar dan seret untuk menempatkan beberapa saluran.
+onset.moremine = Perluas operasi penambangan.\nTempatkan lebih banyak Bor Plasma dan gunakan simpul sinar dan pipa untuk menambangnya.\nTambang 200 berillium.
+onset.graphite = Blok yang lebih kompleks membutuhkan \uf835 [accent]grafit[].\nSiapkan bor plasma untuk menambang grafit.
+onset.research2 = Mulailah meneliti [accent]bangunan pabrik[].\nRiset \uf74d [accent]penghancur tebing[] dan \uf779 [accent]tungku listrik silikon[].
+onset.arcfurnace = Tungku Listrik Silikon membutuhkan \uf834 [accent]pasir[] dan \uf835 [accent]grafit[] untuk membuat \uf82f [accent]silikon[].\n[accent]Tenaga[] juga dibutuhkan.
+onset.crusher = Gunakan \uf74d [accent]penghancur tebing[] untuk menambang pasir.
+onset.fabricator = Gunakan [accent]unit[] untuk menjelajah peta, mempertahakan bangunan, dan menyerang musuh. Riset dan tempatkan \uf6a2 [accent]fabricator tank[].
+onset.makeunit = Produksi sebuah unit.\nGunakan tombol "?" untuk melihat persyaratan pabrik yang dipilih.
+onset.turrets = Unit sangatlah efektif, namun [accent]menara[] memberikan kemampuan pertahanan yang lebih baik jika digunakan secara efektif.\nTempatkan menara \uf6eb [accent]Breach[].\nMenara membutuhkan \uf748 [accent]amunisi[].
+onset.turretammo = Suplai menara dengan [accent]amunisi berillium.[]
+onset.walls = [accent]Dinding[] dapat mencegah kerusakan yang datang pada bangunan.\nTempatkan beberapa \uf6ee [accent]dinding berillium[] di sekitar menara.
+onset.enemies = Musuh datang, bersiaplah untuk bertahan.
+onset.defenses = [accent]Siapkan pertahanan:[lightgray] {0}
+onset.attack = Musuh dalam keadaan rentan diserang. Luncurkan Serangan balik.
+onset.cores = Inti baru dapat ditempatkan di [accent]ubin inti[].\nInti baru berfungsi sebagai pangkalan depan dan berbagi sumber daya dengan inti lainnya.\nTempatkan inti\uf725.
+onset.detect = Musuh akan dapat mendeteksi Anda dalam 2 menit.\nSiapkan pertahanan, penambangan, dan produksi.
+onset.commandmode = Tahan [accent]shift[] untuk masuk ke[accent]mode perintah[].\n[accent]Klik kiri dan seret[] untuk memilih unit.\n[accent]Klik kanan[] untuk memerintahkan unit yang dipilih untuk bergerak atau menyerang.
+onset.commandmode.mobile = Tekan [accent]tombol perintah[] untuk masuk ke [accent]mode perintah[].\nTekan dan tahan jari Anda, lalu [accent]seret[] untuk memilih unit.\n[accent]Ketuk[] untuk memerintahkan unit yang dipilih untuk bergerak atau menyerang.
+aegis.tungsten = Tungsten dapat ditambang menggunakan [accent]bor tumbukan[].\nBangunan ini membutuhkan [accent]air[] dan [accent]tenaga[].
+
+split.pickup = Beberapa blok dapat diambil oleh unit inti.\nAmbil [accent]kontainer ini[] dan letakan di [accent]pembongkar muatan[].\n(Tombol bawaan nya ialah [ dan ] untuk mengambil dan menurun kan)
+split.pickup.mobile = Beberapa blok dapat diambil oleh unit inti.\nAmbil [accent]kontainer ini[] dan letakan di [accent]pembongkar muatan[].\n(Untuk mengambil atau menurunkan sesuatu, tekan lama blok tersebut)
+split.acquire = Anda harus memperoleh beberapa tungsten untuk membangun unit.
+split.build = Unit harus diangkut ke sisi lain tembok.\nTempatkan dua [accent]Penembak Muatan Massal[], satu di setiap sisi dinding.\nHubungkan Penembak dengan menekan salah satunya, lalu pilih penembak yang lain.
+split.container = Mirip dengan kontainer, unit juga dapat diangkut menggunakan [accent]Penembak Muatan Massal[].\nTempatkan unit fabrikator berdekatan dengan penggerak massal untuk memuatnya, lalu kirim mereka melintasi dinding untuk menyerang markas musuh.
item.copper.description = Digunakan pada semua tipe konstruksi dan amunisi.
item.copper.details = Tembaga. Logam yang sangat melimpah di Serpulo. Lemah secara struktural kecuali jika diperkuat.
item.lead.description = Digunakan pada transportasi cairan dan bangunan listrik.
-item.lead.details = Padat. Lembam. Biasanya digunakan untuk baterai.\nCatatan: Kemungkinan beracun untuk kehidupan biologis. Bukan berarti tidak banyak disini.
-item.metaglass.description = Digunakan pada bangunan distribusi cairan/penyimpanan.
+item.lead.details = Padat. Lembam. Biasanya digunakan untuk baterai.\nCatatan: Kemungkinan beracun untuk kehidupan biologis. Bukan berarti tidak banyak di sini.
+item.metaglass.description = Digunakan pada bangunan distribusi cairan atau penyimpanan.
item.graphite.description = Digunakan pada komponen listrik dan amunisi menara.
item.sand.description = Digunakan sebagai bahan produksi untuk material yang akan dimurnikan.
item.coal.description = Digunakan sebagai bahan bakar dan memurnikan material.
-item.coal.details = Merupakan hasil dari tumbuhan yang menjadi fosil, sudah terjadi sangat lama sebelum spora-spora menyebar.
+item.coal.details = Merupakan hasil dari tumbuhan yang menjadi fosil, sudah terjadi sangat lama sebelum spora menyebar.
item.titanium.description = Digunakan pada bangunan transportasi cairan, bor dan pesawat terbang.
item.thorium.description = Digunakan pada bangunan yang kuat dan sebagai bahan bakar nuklir.
item.scrap.description = Digunakan pada Pelebur dan Penghancur untuk dimurnikan menjadi material lain.
-item.scrap.details = Sisa-sisa dari bangunan dan unit tua.
+item.scrap.details = Sisa-sisa dari unit dan bangunan tua.
item.silicon.description = Digunakan pada panel surya, bahan elektronik yang kompleks dan amunisi yang bisa mengejar.
item.plastanium.description = Digunakan dalam unit canggih, isolasi dan amunisi fragmentasi.
item.phase-fabric.description = Digunakan di elektronik canggih dan teknologi perbaikan diri sendiri.
@@ -2005,125 +2060,129 @@ item.blast-compound.description = Digunakan sebagai bom dan amunisi peledak.
item.pyratite.description = Digunakan di senjata pembakar dan generator yang membutuhkan bahan mudah terbakar.
#Erekir
-item.beryllium.description = Used in many types of construction and ammunition on Erekir.
-item.tungsten.description = Used in drills, armor and ammunition. Required in the construction of more advanced structures.
-item.oxide.description = Used as a heat conductor and insulator for power.
-item.carbide.description = Used in advanced structures, heavier units, and ammunition.
+item.beryllium.description = Digunakan pada banyak jenis konstruksi dan amunisi di Erekir.
+item.tungsten.description = Digunakan dalam bor, pelindung dan amunisi. Dibutuhkan dalam pembangunan struktur yang lebih canggih
+item.oxide.description = Digunakan sebagai konduktor panas dan isolator tenaga.
+item.carbide.description = Digunakan dalam bangunan canggih, unit yang lebih berat, dan amunisi.
liquid.water.description = Umumnya digunakan untuk mendinginkan mesin dan pengolahan limbah.
liquid.slag.description = Dapat dipadatkan menjadi logam tertentu, atau disemprotkan ke musuh sebagai senjata.
-liquid.oil.description = Digunakan di produksi material lanjutan dan sebagai amunisi yang mudah terbakar.
+liquid.oil.description = Digunakan pada produksi material canggih dan sebagai amunisi yang mudah terbakar.
liquid.cryofluid.description = Digunakan sebagai pendingin di reaktor, menara, dan pabrik.
#Erekir
-liquid.arkycite.description = Used in chemical reactions for power generation and material synthesis.
-liquid.ozone.description = Used as an oxidizing agent in material production, and as fuel. Moderately explosive.
-liquid.hydrogen.description = Used in resource extraction, unit production and structure repair. Flammable.
-liquid.cyanogen.description = Used for ammunition, construction of advanced units, and various reactions in advanced blocks. Highly flammable.
-liquid.nitrogen.description = Used in resource extraction, gas creation and unit production. Inert.
-liquid.neoplasm.description = A dangerous biological byproduct of the Neoplasia reactor. Quickly spreads to any adjacent water-containing block it touches, damaging them in the process. Viscous.
-liquid.neoplasm.details = Neoplasm. An uncontrollable mass of rapidly-dividing synthetic cells with a sludge-like consistency. Heat-resistant. Extremely dangerous to any structures involving water.\n\nToo complex and unstable for standard analysis. Potential applications unknown. Incineration in slag pools is recommended.
+liquid.arkycite.description = Digunakan dalam reaksi kimia untuk pembangkit listrik dan material sintesis.
+liquid.ozone.description = Digunakan sebagai zat pengoksidasi dalam memproduki material, dan sebagai bahan bakar. Cukup eksplosif.
+liquid.hydrogen.description = Digunakan dalam ekstraksi sumber daya, produksi unit, dan perbaikan bangunan. Mudah terbakar.
+liquid.cyanogen.description = Digunakan untuk amunisi, pembangunan unit canggih, dan berbagai reaksi pada blok canggih. Sangat mudah terbakar.
+liquid.nitrogen.description = Digunakan dalam ekstraksi sumber daya, pembuatan gas, dan produksi unit. Lembam.
+liquid.neoplasm.description = Produk sampingan biologis yang berbahaya dari reaktor Neoplasia. Sangat cepat menyebar ketika menyentuh blok yang mengandung air yang ada di dekatnya, dan merusak blok tersebut secara perlahan. Kental.
+liquid.neoplasm.details = Neoplasma. Sel sintetik Massa yang membelah dengan cepat dan tak terkendali dengan konsistensi seperti lumpur. Tahan panas. Sangat berbahaya bagi bangunan apa pun yang melibatkan air.\n\nTerlalu rumit dan tidak stabil untuk analisis standar. Potensi penerapan tidak diketahui. Dianjurkan untuk dibakar pada kolam lava.
block.derelict = \uf77e [lightgray]Derelik
block.armored-conveyor.description = Memindahkan barang ke depan. Tidak dapat menerima masukan dari samping.
block.illuminator.description = Memancarkan cahaya.
block.message.description = Menyimpan pesan untuk komunikasi antar sekutu.
-block.reinforced-message.description = Stores a message for communication between allies.
-block.world-message.description = A message block for use in mapmaking. Cannot be destroyed.
+block.reinforced-message.description = Menyimpan pesan untuk komunikasi antar sekutu.
+block.world-message.description = Blok pesan untuk digunakan dalam pembuatan peta. Tidak dapat dihancurkan.
block.graphite-press.description = Memadatkan bongkahan batu bara menjadi lempengan grafit.
block.multi-press.description = Memadatkan bongkahan batu bara menjadi lempengan grafit. Membutuhkan air sebagai pendingin.
block.silicon-smelter.description = Memproduksi silikon dari pasir dan batu bara.
block.kiln.description = Membakar pasir dan timah menjadi metaglass.
block.plastanium-compressor.description = Memproduksi plastanium dari minyak dan titanium.
-block.phase-weaver.description = Memproduksi kain phase dari thorium dan banyak pasir.
+block.phase-weaver.description = Memproduksi phase fabric dari torium dan pasir.
block.surge-smelter.description = Memproduksi campuran logam dari titanium, timah, silikon dan tembaga.
-block.cryofluid-mixer.description = Mencampur air dan titanium menjadi cairan dingin.
+block.cryofluid-mixer.description = Mencampur air dan titanium untuk memproduksi cairan dingin.
block.blast-mixer.description = Memproduksi senyawa peledak dari pyratit dan polong spora.
block.pyratite-mixer.description = Mencampur batu bara, timah dan pasir menjadi pyratit.
block.melter.description = Melelehkan rongsokan menjadi lava.
-block.separator.description = Mengekstrak komponen mineral dari lava.
+block.separator.description = Memisahkan komponen mineral dari lava.
block.spore-press.description = Menekan polong spora menjadi minyak.
block.pulverizer.description = Menghancurkan kepingan menjadi pasir.
block.coal-centrifuge.description = Memadatkan minyak menjadi bongkahan batu bara.
block.incinerator.description = Menghancurkan bahan atau zat cair yang masuk.
-block.power-void.description = Menghilangkan semua tenaga yang masuk kedalamnya. Sandbox eksklusif.
-block.power-source.description = Menghasilkan tenaga tak terhingga. Sandbox eksklusif.
-block.item-source.description = Mengeluarkan bahan tak terhingga. Sandbox eksklusif.
-block.item-void.description = Menghancurkan bahan yang masuk. Sandbox eksklusif.
-block.liquid-source.description = Mengeluarkan zat cair tak terhingga. Sandbox eksklusif.
-block.liquid-void.description = Menghancurkan zat cair yang masuk. Sandbox eksklusif.
-block.payload-source.description = Mengeluarkan muatan tak terhingga. Sandbox eksklusif.
-block.payload-void.description = Menghancurkan muatan apapun. Sandbox eksklusif.
+block.power-void.description = Menghilangkan semua tenaga yang masuk ke dalamnya. Khusus mode sandbox.
+block.power-source.description = Menghasilkan tenaga tak terhingga. Khusus mode sandbox.
+block.item-source.description = Mengeluarkan bahan tak terhingga. Khusus mode sandbox.
+block.item-void.description = Menghancurkan bahan yang masuk. Khusus mode sandbox.
+block.liquid-source.description = Mengeluarkan zat cair tak terhingga. Khusus mode sandbox.
+block.liquid-void.description = Menghancurkan zat cair yang masuk. Khusus mode sandbox.
+block.payload-source.description = Mengeluarkan muatan tak terhingga. Khusus mode sandbox.
+block.payload-void.description = Menghancurkan muatan apapun. Khusus mode sandbox.
block.copper-wall.description = Melindungi bangunan dari tembakan musuh.
block.copper-wall-large.description = Melindungi bangunan dari tembakan musuh.
block.titanium-wall.description = Melindungi bangunan dari tembakan musuh.
block.titanium-wall-large.description = Melindungi bangunan dari tembakan musuh.
-block.plastanium-wall.description = Melindungi bangunan dari tembakan musuh. Mampu menyerap laser dan listrik arca. Memblokir koneksi simpul tenaga secara otomatis.
-block.plastanium-wall-large.description = Melindungi bangunan dari tembakan musuh. Mampu menyerap laser dan listrik arca. Memblokir koneksi simpul tenaga secara otomatis.
+block.plastanium-wall.description = Melindungi bangunan dari tembakan musuh. Mampu menyerap laser dan listrik. Memblokir koneksi simpul tenaga secara otomatis.
+block.plastanium-wall-large.description = Melindungi bangunan dari tembakan musuh. Mampu menyerap laser dan listrik. Memblokir koneksi simpul tenaga secara otomatis.
block.thorium-wall.description = Melindungi bangunan dari tembakan musuh.
block.thorium-wall-large.description = Melindungi bangunan dari tembakan musuh.
block.phase-wall.description = Melindungi bangunan dari tembakan musuh, dan dapat memantulkan beberapa jenis peluru senjata.
block.phase-wall-large.description = Melindungi bangunan dari tembakan musuh, dan dapat memantulkan beberapa jenis peluru senjata.
-block.surge-wall.description = Melindungi bangunan dari tembakan musuh, dan dapat mengeluarkan setruman arca.
-block.surge-wall-large.description = Melindungi bangunan dari tembakan musuh, dan dapat mengeluarkan setruman arca.
+block.surge-wall.description = Melindungi bangunan dari tembakan musuh, dan dapat mengeluarkan setruman listrik.
+block.surge-wall-large.description = Melindungi bangunan dari tembakan musuh, dan dapat mengeluarkan setruman listrik.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Dinding yang bisa dibuka dan ditutup.
block.door-large.description = Dinding yang bisa dibuka dan ditutup.
-block.mender.description = Menyembuhkan blok di sekelilingnya secara berkala.\nDapat menggunakan silikon untuk meningkatkan jangkauan dan efisiensi.
-block.mend-projector.description = Menyembuhkan blok di sekelilingnya secara berkala.\nDapat menggunakan kain phase untuk meningkatkan jangkauan dan efisiensi.
-block.overdrive-projector.description = Menambah kecepatan bangunan sekitar.\nDapat menggunakan kain phase untuk meningkatkan jangkauan dan efisiensi.
-block.force-projector.description = Membentuk medan gaya berbentuk heksagon disekitar, melindungi bangunan dan unit didalamnya dari kerusakan.\nDapat mengalami kelebihan panas jika membendung terlalu banyak kerusakan. Dapat menggunakan cairan pendingin untuk mencegah kepanasan. Gunakan fabrik phase untuk memperbesar jangkauan.
-block.shock-mine.description = Mengeluarkan setruman listrik kepada musuh yang menginjak ranjau.
+block.mender.description = Menyembuhkan blok di sekelilingnya secara berkala.\nGunakan silikon untuk meningkatkan jangkauan dan efisiensi (Opsional).
+block.mend-projector.description = Menyembuhkan blok di sekelilingnya secara berkala.\nGunakan phase fabric untuk meningkatkan jangkauan dan efisiensi (Opsional).
+block.overdrive-projector.description = Menambah kecepatan bangunan sekitar.\nGunakan phase fabric untuk meningkatkan jangkauan dan efisiensi (Opsional).
+block.force-projector.description = Menciptakan medan gaya heksagonal di sekelilingnya, melindungi bangunan dan unit di dalamnya dari kerusakan. Terlalu panas jika menerima banyak kerusakan. Gunakan cairan pendingin untuk mencegah panas berlebih (Opsional). Phase fabric meningkatkan ukuran perisai.
+block.shock-mine.description = Mengeluarkan setruman listrik setelah di injak musuh.
block.conveyor.description = Memindahkan barang ke depan.
-block.titanium-conveyor.description = Memindahkan barang ke depan. Lebih cepat daripada pengantar biasa.
+block.titanium-conveyor.description = Memindahkan barang ke depan. Lebih cepat daripada konveyor biasa.
block.plastanium-conveyor.description = Memindahkan barang secara bertumpuk. Menerima barang dari belakang, dan membaginya ke tiga arah di depan. Membutuhkan beberapa titik pemuat dan pembongkar untuk hasil yang maksimal.
-block.junction.description = Berguna seperti jembatan untuk dua pengantar yang bersimpangan.
+block.junction.description = Bertindak sebagai jembatan untuk dua konveyor yang bersimpangan.
block.bridge-conveyor.description = Memindahkan barang melewati tanah atau bangunan.
-block.phase-conveyor.description = Memindahkan barang secara instan melewati tanah atau bangunan. Memiliki jarak yang lebih jauh daripada jembatan, namun memerlukan tenaga.
+block.phase-conveyor.description = Memindahkan barang secara instan melewati tanah atau bangunan. Memiliki jarak yang lebih jauh daripada jembatan, namun membutuhkan tenaga.
block.sorter.description = Jika barang yang masuk cocok dengan seleksi, barang akan diperbolehkan lewat ke depan. Jika tidak, barang akan dikeluarkan ke kiri dan kanan.
block.inverted-sorter.description = Sama seperti penyortir, namun mengeluarkan barang terpilih ke samping.
-block.router.description = Membagi barang ke 3 arah secara rata.
-block.router.details = Bisa sangat menggangu. Jangan meletakannya disamping input produksi, karena laju pengeluaran barang dapat tersumbat.
-block.distributor.description = Pemisah canggih yang memisah barang ke 7 arah secara rata.
+block.router.description = Mendistribusikan barang ke 3 arah secara merata.
+block.router.details = Bisa sangat menggangu. Jangan meletakannya disamping bangunan pabrik, karena laju pengeluaran barang dapat tersumbat.
+block.distributor.description = Mendistribusikan barang ke 7 arah secara merata.
block.overflow-gate.description = Hanya mengeluarkan barang ke kiri dan ke kanan jika bagian depan tertutup.
block.underflow-gate.description = Kebalikan dari gerbang luap. Mengeluarkan barang ke depan jika bagian kiri dan kanan tertutup.
-block.mass-driver.description = Blok transportasi barang jarak jauh. Membawa beberapa barang dan menembaknya ke penggerak massal lainnya.
-block.mechanical-pump.description = Memompa dan mengeluarkan cairan. Tidak memerlukan tenaga.
-block.rotary-pump.description = Memompa dan mengeluarkan cairan. Menggunakan tenaga.
-block.impulse-pump.description = Memeompa dan mengluarkan cairan.
+block.mass-driver.description = Blok transportasi barang jarak jauh. Membawa beberapa barang dan menembaknya ke penembak massal lainnya.
+block.mechanical-pump.description = Memompa dan mengeluarkan cairan. Tidak membutuhkan tenaga.
+block.rotary-pump.description = Memompa dan mengeluarkan cairan. Membutuhkan tenaga.
+block.impulse-pump.description = Memompa dan mengeluarkan cairan.
block.conduit.description = Memindahkan cairan ke depan. Digunakan dengan pompa dan saluran lainnya.
block.pulse-conduit.description = Memindahkan cairan ke depan. Mengantarkan lebih cepat dan banyak daripada saluran biasa.
block.plated-conduit.description = Memindahkan cairan ke depan. Tidak menerima cairan dari samping. Tidak bocor.
block.liquid-router.description = Menerima cairan dari satu arah dan mengeluarkannya ke 3 arah secara rata. Dapat digunakan untuk menyimpan sejumlah cairan.
block.liquid-container.description = Menyimpan jumlah cairan yang banyak. Mengeluarkan cairan ke segala arah, sama seperti pengarah cairan.
block.liquid-tank.description = Menyimpan jumlah cairan yang sangat banyak. Mengeluarkan cairan ke segala arah, sama seperti pengarah cairan.
-block.liquid-junction.description = Berguna seperti jembatan untuk dua saluran yang bersimpangan.
+block.liquid-junction.description = Bertindak sebagai jembatan untuk dua saluran yang bersimpangan.
block.bridge-conduit.description = Memindahkan cairan melewati tanah atau bangunan.
-block.phase-conduit.description = Memindahkan cairan melewati tanah atau bangunan. Memiliki jarak yang lebih jauh daripada jembatan cairan, namun memerlukan tenaga.
-block.power-node.description = Membawa tenaga ke tiang tersambung. Tiang akan menerima atau memberi tenaga ke atau dari blok yang disambung.
-block.power-node-large.description = Mempunyai radius lebih besar dari tiang listrik biasa dan bisa menyambung hingga enam sumber listrik, sambungan atau tiang lainnya.
-block.surge-tower.description = Sebuah menara listrik dengan jangkauan sangat jauh tetapi sambungan yang sedikit.
+block.phase-conduit.description = Memindahkan cairan melewati tanah atau bangunan. Memiliki jarak yang lebih jauh daripada jembatan cairan, namun membutuhkan tenaga.
+block.power-node.description = Membawa tenaga ke simpul tersambung. Simpul akan menerima atau memberi tenaga ke atau dari blok yang disambung.
+block.power-node-large.description = Mempunyai radius lebih besar dari simpul listrik biasa dan bisa menyambung hingga enam sumber listrik, sambungan atau simpul lainnya.
+block.surge-tower.description = Sebuah menara listrik dengan jangkauan sangat jauh dengan sambungan yang sedikit.
block.diode.description = Tenaga baterai dapat mengalir hanya dari satu arah, tetapi hanya jika tenaga di sebelah lebih sedikit.
-block.battery.description = Menyimpan tenaga jika ada kelebihan. Memberikan tenaga jika ada kekurangan.
-block.battery-large.description = Menyimpan tenaga jika ada kelebihan. Memberikan tenaga jika ada kekurangan. Memiliki kapasitas yang besar daripada baterai biasa.
-block.combustion-generator.description = Menghasilkan tenaga dengan membakar bahan yang mudah terbakar, seperti batu bara.
-block.thermal-generator.description = Menghasilkan tenaga saat ditaruh di lokasi yang panas.
-block.steam-generator.description = Menghasilkan tenaga dengan membakar bahan yang mudah terbakar dan mengubah air menjadi uap.
+block.battery.description = Menyimpan tenaga pada saat tenaga berlebih. Memberikan tenaga pada saat tenaga berkurang.
+block.battery-large.description = Menyimpan tenaga pada saat tenaga berlebih. Memberikan tenaga pada saat tenaga berkurang. Memiliki kapasitas yang besar daripada baterai biasa.
+block.combustion-generator.description = Menghasilkan tenaga dengan membakar material yang mudah terbakar, seperti batu bara.
+block.thermal-generator.description = Menghasilkan tenaga saat ditempatkan di lokasi yang panas.
+block.steam-generator.description = Menghasilkan tenaga dengan membakar material yang mudah terbakar dan mengubah air menjadi uap.
block.differential-generator.description = Menghasilkan tenaga dalam jumlah banyak. Memanfaatkan perbedaan suhu cairan pendingin dan pyratit yang terbakar.
block.rtg-generator.description = Menggunakan panas dari senyawa radioaktif untuk memproduksi tenaga secara perlahan.
block.solar-panel.description = Menghasilkan sedikit tenaga dari sinar matahari.
block.solar-panel-large.description = Menghasilkan sedikit tenaga dari sinar matahari. Lebih efisien daripada panel surya biasa.
-block.thorium-reactor.description = Menghasilkan tenaga yang besar dari konsumsi thorium. Membutuhkan pendinginan konstan. Akan meledak jika tidak cukup pendingin yang diterima.
-block.impact-reactor.description = Menghasilkan tenaga dengan jumlah yang sangat banyak secara efisien. Memerlukan tenaga untuk menyalakan reaktor terlebih dahulu.
-block.mechanical-drill.description = Bor murah. Saat ditaruh ditempat yang sesuai, mengeluarkan bahan dengan pelan tanpa batas.
-block.pneumatic-drill.description = Bor lebih cepat dari bor mekanik dan bisa memproses bahan lebih keras dengan menggunakan tekanan udara.
-block.laser-drill.description = Mengebor lebih cepat lewat teknologi laser, tapi membutuhkan tenaga. Dapat menambang thorium.
+block.thorium-reactor.description = Menghasilkan tenaga yang besar dari konsumsi torium. Membutuhkan pendinginan konstan. Akan meledak jika jumlah cairan pendingin yang disediakan tidak mencukupi
+block.impact-reactor.description = Menghasilkan tenaga dengan jumlah yang sangat banyak secara efisien. Membutuhkan banyak tenaga agar dapat menyalakan reaktor.
+block.mechanical-drill.description = Ketika ditempatkan pada bijih, mengeluarkan bahan dengan kecepatan lambat tanpa batas. Hanya mampu menambang sumber daya dasar.
+block.pneumatic-drill.description = Bor yang ditingkatkan, mampu menambang titanium. Menambang dengan kecepatan lebih cepat daripada bor mekanik.
+block.laser-drill.description = Mengebor lebih cepat lewat teknologi laser, tapi membutuhkan tenaga. Dapat menambang torium.
block.blast-drill.description = Bor tercanggih. Membutuhkan banyak tenaga.
block.water-extractor.description = Memompa air dari tanah. Gunakan jika tidak ada sumber air di sekitar.
block.cultivator.description = Menumbuhkan konsentrasi spora yang kecil di atmosfer menjadi polong spora.
-block.cultivator.details = Teknologi yang dipulihkan. Digunakan untuk memproduksi biomassa secara efisien. Kemungkinan merupakan inkubator awal dari spora yang sekarang menutupi Serpulo.
+block.cultivator.details = Teknologi yang dipulihkan. Digunakan untuk memproduksi biomassa dalam jumlah besar secara efisien. Kemungkinan merupakan inkubator awal dari spora yang sekarang menutupi Serpulo.
block.oil-extractor.description = Menggunakan jumlah tenaga, pasir dan air yang banyak untuk diolah menjadi minyak.
block.core-shard.description = Inti markas. Jika hancur, sektormu akan hilang.
-block.core-shard.details = Iterasi pertama. Padat. Bisa menggandakan dirinya (untuk menguasai sektor disekitarnya). Dilengkapi dengan pendorong yang sekali pakai. Tidak didesain untuk perjalanan antar planet.
+block.core-shard.details = Iterasi pertama. Padat. Bisa menggandakan dirinya (untuk menguasai sektor di sekitarnya). Dilengkapi dengan pendorong sekali pakai. Tidak didesain untuk perjalanan antar planet.
block.core-foundation.description = Inti markas. Lebih kuat. Menyimpan banyak sumber daya.
block.core-foundation.details = Iterasi kedua.
block.core-nucleus.description = Inti markas. Sangat kuat. Menyimpan sangat banyak sumber daya.
@@ -2131,39 +2190,39 @@ block.core-nucleus.details = Iterasi ketiga dan yang terakhir.
block.vault.description = Menyimpan semua tipe bahan dalam jumlah besar. Bahan dapat dikeluarkan dengan pembongkar muatan.
block.container.description = Menyimpan semua tipe bahan dalam jumlah kecil. Bahan dapat dikeluarkan dengan pembongkar muatan.
block.unloader.description = Mengeluarkan bahan yang ditentukan dari bangunan.
-block.launch-pad.description = Meluncurkan beberapa bahan ke sektor yang dipilih.
+block.launch-pad.description = Meluncurkan muatan bahan ke sektor yang dipilih.
block.launch-pad.details = Sistem sub-orbital untuk transportasi sumber daya point-to-point. Pod muatan mudah rapuh dan tidak dapat bertahan bila masuk ke tujuan.
block.duo.description = Menembakkan peluru bergantian ke musuh.
-block.scatter.description = Menembakkan gumpalan timah, rongsokan atau metaglass ke musuh udara.
+block.scatter.description = Menembakkan gumpalan timah, rongsokan atau metaglass ke target udara.
block.scorch.description = Membakar musuh darat yang dekat dengannya. Sangat efektif dalam jarak dekat.
block.hail.description = Menembakkan peluru kecil ke musuh darat dari jarak jauh.
-block.wave.description = Menembakkan aliran cairan ke musuh. Secara otomatis memadamkan api saat disuplai dengan air.
+block.wave.description = Menembakkan aliran cairan ke musuh. Secara otomatis memadamkan api bila disuplai dengan air.
block.lancer.description = Memuat dan menembakkan sinar energi yang kuat ke target darat.
-block.arc.description = Menembakkan sambaran arca ke musuh darat.
+block.arc.description = Menembakkan busur listrik ke target darat
block.swarmer.description = Menembakkan misil yang mengejar ke arah musuh.
block.salvo.description = Menembakkan peluru cepat ke arah musuh.
block.fuse.description = Menembakkan tiga penusuk tajam jarak dekat ke musuh terdekat.
-block.ripple.description = Menembakkan cangkang berkelompok ke musuh darat dari jarak jauh.
+block.ripple.description = Menembakkan gugusan peluru ke musuh darat dari jarak jauh.
block.cyclone.description = Menembakkan gumpalan peledak ke musuh terdekat.
-block.spectre.description = Menembakkan peluru besar yang menembus lapis baja ke target udara dan darat.
+block.spectre.description = Menembakkan peluru besar yang menembus pelindung ke target udara dan darat.
block.meltdown.description = Mengisi dan menembakkan sinar laser yang terus-menerus ke musuh di sekitar. Membutuhkan pendingin untuk beroperasi.
block.foreshadow.description = Menembakkan baut besar jarak jauh yang hanya menembak satu target. Mengutamakan musuh dengan batas darah tertinggi.
-block.repair-point.description = Memulihkan unit terluka disekitar secara terus-menerus.
+block.repair-point.description = Memulihkan unit yang terluka di sekitar secara terus-menerus.
block.segment.description = Merusakkan dan menghancurkan proyektil yang datang. Proyektil laser tidak akan ditargetkan.
block.parallax.description = Menembakkan laser yang menarik target udara, juga merusaknya selama dalam proses.
-block.tsunami.description = Menembakkan cairan dalam jumlah dan tekanan besar ke arah musuh. Akan memadamkan api secara otomatis jika diisi dengan air.
-block.silicon-crucible.description = Memurnikan silikon dari pasir dan batubara, menggunakan pyratit sebagai sumber panas tambahan. Lebih efesien jika diletakkan di area yang panas.
-block.disassembler.description = Memisahkan lava menjadi mineral langka dalam efesiensi rendah. Bisa memproduksi thorium.
-block.overdrive-dome.description = Menambahkan kecepatan pada bangunan disekitarnya. Membutuhkan kain phase dan silikon untuk bekerja.
+block.tsunami.description = Menembakkan cairan dalam jumlah dan tekanan besar ke arah musuh. Dapat memadamkan api secara otomatis jika diisi dengan air.
+block.silicon-crucible.description = Memurnikan silikon dari pasir dan batu bara, menggunakan pyratit sebagai sumber panas tambahan. Lebih efesien jika diletakkan di area yang panas.
+block.disassembler.description = Memisahkan lava menjadi mineral langka dalam efesiensi rendah. Bisa memproduksi torium.
+block.overdrive-dome.description = Menambahkan kecepatan pada bangunan di sekitarnya. Membutuhkan phase fabric dan silikon untuk bekerja.
block.payload-conveyor.description = Memindahkan muatan yang besar, seperti unit dari pabrik.
block.payload-router.description = Membagi muatan masukan menjadi 3 arah keluaran.
-block.ground-factory.description = Memproduksi unit darat. Hasil unit dapat digunakan secara langsung, atau dipindah ke rekonstruktor untuk ditingkatkan.
-block.air-factory.description = Memproduksi unit udara. Hasil unit dapat digunakan secara langsung, atau dipindah ke rekonstruktor untuk ditingkatkan.
-block.naval-factory.description = Memproduksi unit laut. Hasil unit dapat digunakan secara langsung, atau dipindah ke rekonstruktor untuk ditingkatkan.
-block.additive-reconstructor.description = Meningkatkan unit didalamnya menjadi tingkat dua.
-block.multiplicative-reconstructor.description = Meningkatkan unit didalamnya menjadi tingkat tiga.
-block.exponential-reconstructor.description = Meningkatkan unit didalamnya menjadi tingkat empat.
-block.tetrative-reconstructor.description = Meningkatkan unit didalamnya menjadi tingkat lima dan terakhir.
+block.ground-factory.description = Memproduksi unit darat. Hasil unit dapat digunakan secara langsung, atau dipindahkan ke rekonstruktor untuk ditingkatkan.
+block.air-factory.description = Memproduksi unit udara. Hasil unit dapat digunakan secara langsung, atau dipindahkan ke rekonstruktor untuk ditingkatkan.
+block.naval-factory.description = Memproduksi unit laut. Hasil unit dapat digunakan secara langsung, atau dipindahkan ke rekonstruktor untuk ditingkatkan.
+block.additive-reconstructor.description = Meningkatkan unit di dalamnya menjadi tingkat dua.
+block.multiplicative-reconstructor.description = Meningkatkan unit di dalamnya menjadi tingkat tiga.
+block.exponential-reconstructor.description = Meningkatkan unit di dalamnya menjadi tingkat empat.
+block.tetrative-reconstructor.description = Meningkatkan unit di dalamnya menjadi tingkat lima dan terakhir.
block.switch.description = Sakelar yang dapat dialihkan. Status dapat dibaca dan dikendalikan dengan prosesor logika.
block.micro-processor.description = Menjalankan urutan instruksi logika dalam satu lingkaran. Dapat digunakan untuk mengontrol unit dan bangunan.
block.logic-processor.description = Menjalankan urutan instruksi logika dalam satu lingkaran. Dapat digunakan untuk mengontrol unit dan bangunan. Lebih cepat dibandingkan prosesor mikro.
@@ -2173,117 +2232,119 @@ block.memory-bank.description = Menyimpan informasi untuk prosesor. Berkapasitas
block.logic-display.description = Menampilkan grafik sembarang dari prosesor.
block.large-logic-display.description = Menampilkan grafik sembarang dari prosesor. Lebih besar.
block.interplanetary-accelerator.description = Sebuah menara railgun elektromagnetik raksasa. Meluncurkan Inti dengan kecepatan tinggi untuk peluncuran antarplanet.
-block.repair-turret.description = Memperbaiki unit terdekat yang sekarat dalam jangkauan secara terus-menerus. Dapat menerima pendingin.
+block.repair-turret.description = Memulihkan unit terdekat yang sekarat dalam jangkauan secara terus-menerus. Dapat menerima pendingin (Opsional).
#Erekir
block.core-bastion.description = Inti markas. Terlindungi. Jika hancur, sektor jatuh ke tangan musuh.
-block.core-citadel.description = Inti markas. Sangat dilindungi. Menyimpan lebih banyak sumber daya dibandingkan Inti Baluarti.
-block.core-acropolis.description = Inti markas. Sangat amat dilindungi. Menyimpan lebih banyak sumber daya dibandingkan Inti Kastil.
-block.breach.description = Fires piercing beryllium or tungsten ammunition at enemy targets.
-block.diffuse.description = Fires a burst of bullets in a wide cone. Pushes enemy targets back.
-block.sublimate.description = Fires a continuous jet of flame at enemy targets. Pierces armor.
-block.titan.description = Fires a massive explosive artillery shell at ground targets. Requires hydrogen.
-block.afflict.description = Fires a massive charged orb of fragmentary flak. Requires heating.
-block.disperse.description = Fires bursts of flak at aerial targets.
-block.lustre.description = Fires a slow-moving single-target laser at enemy targets.
-block.scathe.description = Launches a powerful missile at ground targets over vast distances.
-block.smite.description = Fires bursts of piercing, lightning-emitting bullets.
-block.malign.description = Fires a barrage of homing laser charges at enemy targets. Requires extensive heating.
-block.silicon-arc-furnace.description = Refines silicon from sand and graphite.
-block.oxidation-chamber.description = Converts beryllium and ozone into oxide. Emits heat as a by-product.
-block.electric-heater.description = Heats facing blocks. Requires large amounts of power.
-block.slag-heater.description = Heats facing blocks. Requires slag.
-block.phase-heater.description = Heats facing blocks. Requires phase fabric.
-block.heat-redirector.description = Redirects accumulated heat to other blocks.
-block.heat-router.description = Spreads accumulated heat in three output directions.
-block.electrolyzer.description = Converts water into hydrogen and ozone gas.
-block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
-block.surge-crucible.description = Forms surge alloy from slag and silicon. Requires heat.
-block.phase-synthesizer.description = Synthesizes phase fabric from thorium, sand, and ozone. Requires heat.
-block.carbide-crucible.description = Fuses graphite and tungsten into carbide. Requires heat.
-block.cyanogen-synthesizer.description = Synthesizes cyanogen from arkycite and graphite. Requires heat.
-block.slag-incinerator.description = Incinerates non-volatile items or liquids. Requires slag.
-block.vent-condenser.description = Condenses vent gases into water. Consumes power.
-block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
-block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
-block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
-block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
-block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
-block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
-block.reinforced-liquid-router.description = Distributes fluids equally to all sides.
-block.reinforced-liquid-tank.description = Stores a large amount of fluids.
-block.reinforced-liquid-container.description = Stores a sizeable amount of fluids.
-block.reinforced-bridge-conduit.description = Transports fluids over structures and terrain.
-block.reinforced-pump.description = Pumps and outputs liquids. Requires hydrogen.
-block.beryllium-wall.description = Protects structures from enemy projectiles.
-block.beryllium-wall-large.description = Protects structures from enemy projectiles.
-block.tungsten-wall.description = Protects structures from enemy projectiles.
-block.tungsten-wall-large.description = Protects structures from enemy projectiles.
-block.carbide-wall.description = Protects structures from enemy projectiles.
-block.carbide-wall-large.description = Protects structures from enemy projectiles.
-block.reinforced-surge-wall.description = Protects structures from enemy projectiles, periodically launching electric arcs upon projectile contact.
-block.reinforced-surge-wall-large.description = Protects structures from enemy projectiles, periodically launching electric arcs upon projectile contact.
-block.shielded-wall.description = Protects structures from enemy projectiles. Deploys a shield that absorbs most projectiles when power is provided. Conducts power.
-block.blast-door.description = A wall that opens when allied ground units are in range. Cannot be manually controlled.
-block.duct.description = Moves items forward. Only capable of storing a single item.
-block.armored-duct.description = Moves items forward. Does not accept non-duct inputs from the sides.
-block.duct-router.description = Distributes items equally across three directions. Only accepts items from the back side. Can be configured as an item sorter.
-block.overflow-duct.description = Only outputs items to the sides if the front path is blocked.
-block.duct-bridge.description = Moves items over structures and terrain.
-block.duct-unloader.description = Unloads the selected item from the block behind it. Cannot unload from cores.
-block.underflow-duct.description = Opposite of an overflow duct. Outputs to the front if the left and right paths are blocked.
-block.reinforced-liquid-junction.description = Acts as a junction between two crossing conduits.
-block.surge-conveyor.description = Moves items in batches. Can be sped up with power. Conducts power.
-block.surge-router.description = Equally distributes items in three directions from surge conveyors. Can be sped up with power. Conducts power.
-block.unit-cargo-loader.description = Constructs cargo drones. Drones automatically distribute items to Cargo Unload Points with a matching filter.
-block.unit-cargo-unload-point.description = Acts as an unloading point for cargo drones. Accepts items that match the selected filter.
-block.beam-node.description = Transmits power to other blocks orthogonally. Stores a small amount of power.
-block.beam-tower.description = Transmits power to other blocks orthogonally. Stores a large amount of power. Long-range.
-block.turbine-condenser.description = Generates power when placed on vents. Produces a small amount of water.
-block.chemical-combustion-chamber.description = Generates power from arkycite and ozone.
-block.pyrolysis-generator.description = Generates large amounts of power from arkycite and slag. Produces water as a byproduct.
-block.flux-reactor.description = Generates large amounts of power when heated. Requires cyanogen as a stabilizer. Power output and cyanogen requirements are proportional to heat input.\nExplodes if insufficient cyanogen is provided.
-block.neoplasia-reactor.description = Uses arkycite, water and phase fabric to generate large amounts of power. Produces heat and dangerous neoplasm as a byproduct.\nExplodes violently if neoplasm is not removed from the reactor via conduits.
-block.build-tower.description = Automatically rebuilds structures in range and assists other units in construction.
-block.regen-projector.description = Slowly repairs allied structures in a square perimeter. Requires hydrogen.
-block.reinforced-container.description = Stores a small amount of items. Contents can be retrieved via unloaders. Does not increase core storage capacity.
-block.reinforced-vault.description = Stores a large amount of items. Contents can be retrieved via unloaders. Does not increase core storage capacity.
-block.tank-fabricator.description = Constructs Stell units. Outputted units can be used directly, or moved into refabricators for upgrading.
-block.ship-fabricator.description = Constructs Elude units. Outputted units can be used directly, or moved into refabricators for upgrading.
-block.mech-fabricator.description = Constructs Merui units. Outputted units can be used directly, or moved into refabricators for upgrading.
-block.tank-assembler.description = Assembles large tanks out of inputted blocks and units. Output tier may be increased by adding modules.
-block.ship-assembler.description = Assembles large ships out of inputted blocks and units. Output tier may be increased by adding modules.
-block.mech-assembler.description = Assembles large mechs out of inputted blocks and units. Output tier may be increased by adding modules.
-block.tank-refabricator.description = Upgrades inputted tank units to the second tier.
-block.ship-refabricator.description = Upgrades inputted ship units to the second tier.
-block.mech-refabricator.description = Upgrades inputted mech units to the second tier.
-block.prime-refabricator.description = Upgrades inputted units to the third tier.
-block.basic-assembler-module.description = Increases assembler tier when placed next to a construction boundary. Requires power. Can be used as a payload input.
-block.small-deconstructor.description = Deconstructs inputted structures and units. Returns 100% of the build cost.
-block.reinforced-payload-conveyor.description = Moves payloads forward.
-block.reinforced-payload-router.description = Distributes payloads into adjacent blocks. Functions as a sorter when a filter is set.
-block.payload-mass-driver.description = Long-range payload transport structure. Shoots received payloads to linked payload mass drivers.
-block.large-payload-mass-driver.description = Long-range payload transport structure. Shoots received payloads to linked payload mass drivers.
-block.unit-repair-tower.description = Repairs all units in its vicinity. Requires ozone.
-block.radar.description = Gradually uncovers terrain and enemy units in a large radius. Requires power.
-block.shockwave-tower.description = Damages and destroys enemy projectiles in a radius. Requires cyanogen.
-block.canvas.description = Displays a simple image with a pre-defined palette. Editable.
+block.core-citadel.description = Inti markas. Sangat terlindungi. Menyimpan lebih banyak sumber daya dari pada Inti Bastion.
+block.core-acropolis.description = Inti markas. Sangat amat terlindungi. Menyimpan lebih banyak sumber daya dari pada Inti Citadel.
+block.breach.description = Menembakkan amunisi berilium atau tungsten yang menusuk ke arah musuh.
+block.diffuse.description = Menembakkan semburan peluru dalam kerucut yang lebar. Mendorong musuh kebelakang.
+block.sublimate.description = Menembakkan pancaran api terus menerus ke arah musuh. Menembus pelindung.
+block.titan.description = Menembakkan peluru artileri eksplosif besar ke target darat. Membutuhkan hidrogen.
+block.afflict.description = Menembakkan bola anti-peluru fragmentaris bermuatan besar. Membutuhkan pemanasan.
+block.disperse.description = Menembakkan semburan anti-peluru ke target udara.
+block.lustre.description = Menembakkan laser target tunggal yang bergerak lambat ke arahmusuh.
+block.scathe.description = Meluncurkan rudal yang kuat ke target darat dalam jarak yang sangat jauh.
+block.smite.description = Menembakan semburan peluru yang menusuk dan menyambar.
+block.malign.description = Menembakkan rentetan muatan laser pelacak ke target musuh. Membutuhkan pemanasan ekstensif.
+block.silicon-arc-furnace.description = Memurnikan silikon dari pasir dan grafit.
+block.oxidation-chamber.description = Mengubah berilium dan ozon menjadi oksida. Memancarkan panas sebagai produk sampingan.
+block.electric-heater.description = Pemanas yang menghadap ke arah blok. Membutuhkan daya yang besar.
+block.slag-heater.description = Pemanas yang menghadap ke arah blok. Membutuhkan lava.
+block.phase-heater.description = Pemanas yang menghadap ke arah blok. Membutuhkan phase fabric.
+block.heat-redirector.description = Mengalihkan akumulasi panas ke blok lain.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
+block.heat-router.description = Menyebarkan akumulasi panas ke tiga arah.
+block.electrolyzer.description = Mengubah air menjadi gas hidrogen dan ozon.
+block.atmospheric-concentrator.description = Mengkonsentrasikan nitrogen dari atmosfer. Membutuhkan panas.
+block.surge-crucible.description = Membentuk Paduan Logam dari lava dan silikon. Membutuhkan panas.
+block.phase-synthesizer.description = Mensintesis phase fabric dari torium, pasir, dan ozon. Membutuhkan panas.
+block.carbide-crucible.description = Memadukan grafit dan tungsten menjadi karbida. Membutuhkan panas.
+block.cyanogen-synthesizer.description = Mensintesis sianogen dari arkycite dan grafit. Membutuhkan panas.
+block.slag-incinerator.description = Membakar benda atau cairan yang tidak mudah menguap. Membutuhkan lava.
+block.vent-condenser.description = Mengondensasi gas ventilasi ke dalam air. Membutuhkan tenaga.
+block.plasma-bore.description = Saat ditempatkan menghadap dinding bijih, mengeluarkan bahan tanpa batas. Membutuhkan daya dalam jumlah kecil.
+block.large-plasma-bore.description = Bor plasma yang lebih besar. Mampu menambang tungsten dan thorium. Membutuhkan hidrogen dan tenaga.
+block.cliff-crusher.description = Menghancurkan dinding, mengeluarkan pasir tanpa batas. Membutuhkan tenaga. Efisiensi bervariasi berdasarkan jenis dinding.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
+block.impact-drill.description = Saat ditempatkan pada bijih, mengeluarkan bahan dalam ledakan tanpa batas. Membutuhkan listrik dan air.
+block.eruption-drill.description = Bor tumbukan yang ditingkatkan. Mampu menambang thorium. Membutuhkan hidrogen.
+block.reinforced-conduit.description = Memindahkan cairan ke depan. Tidak menerima masukkan ke samping.
+block.reinforced-liquid-router.description = Mendistribusikan cairan secara merata ke semua sisi.
+block.reinforced-liquid-tank.description = Menyimpan sejumlah besar cairan.
+block.reinforced-liquid-container.description = Menyimpan jumlah cairan yang cukup besar.
+block.reinforced-bridge-conduit.description = Memindahkan cairan melintasi bangunan dan medan.
+block.reinforced-pump.description = Memompa dan mengeluarkan cairan. Membutuhkan hidrogen.
+block.beryllium-wall.description = Melindungi bangunan dari proyektil musuh.
+block.beryllium-wall-large.description = Melindungi bangunan dari proyektil musuh.
+block.tungsten-wall.description = Melindungi bangunan dari proyektil musuh.
+block.tungsten-wall-large.description = Melindungi bangunan dari proyektil musuh.
+block.carbide-wall.description = Melindungi bangunan dari proyektil musuh.
+block.carbide-wall-large.description = Melindungi bangunan dari proyektil musuh.
+block.reinforced-surge-wall.description = Melindungi bangunan dari proyektil musuh, melepaskan listrik secara berkala saat proyektil mengenai dinding.
+block.reinforced-surge-wall-large.description = Melindungi bangunan dari proyektil musuh, melepaskan listrik secara berkala saat proyektil mengenai dinding.
+block.shielded-wall.description = Melindungi bangunan dari proyektil musuh. Menyebarkan perisai yang menyerap sebagian besar proyektil saat daya tersedia. Menghantarkan tenaga.
+block.blast-door.description = Dinding yang terbuka ketika unit darat sekutu berada dalam jangkauan. Tidak dapat dikontrol secara manual.
+block.duct.description = Memindahkan barang ke depan. Hanya mampu menyimpan satu barang.
+block.armored-duct.description = Memindahkan barang ke depan. Tidak menerima masukan dari samping.
+block.duct-router.description = Mendistribusikan barang secara merata ke tiga arah. Hanya menerima barang dari sisi belakang. Dapat dikonfigurasi sebagai penyortir barang.
+block.overflow-duct.description = Hanya mengeluarkan barang ke samping jika jalur depan diblokir.
+block.duct-bridge.description = Memindahkan barang di atas bangunan dan medan.
+block.duct-unloader.description = Membongkarkan barang yang dipilih dari blok di belakangnya. Tidak dapat membongkar dari inti.
+block.underflow-duct.description = Di seberang saluran pelimpah. Keluaran ke depan jika jalur kiri dan kanan terhalang.
+block.reinforced-liquid-junction.description = Bertindak sebagai persimpangan antara dua saluran yang bersilangan.
+block.surge-conveyor.description = Memindahkan barang secara berkelompok. Dapat dipercepat dengan tenaga. Menghantarkan tenaga.
+block.surge-router.description = Mendistribusikan barang secara merata ke tiga arah dari konveyor lonjakan. Dapat dipercepat dengan tenaga. Menghantarkan tenaga.
+block.unit-cargo-loader.description = Membuat drone kargo. Drone secara otomatis mendistribusikan barang ke Titik Bongkar muatan Kargo dengan filter yang cocok.
+block.unit-cargo-unload-point.description = Bertindak sebagai titik bongkar muatan drone kargo. Menerima barang yang cocok dengan filter yang dipilih.
+block.beam-node.description = Mentransmisikan daya ke blok lain secara ortogonal. Menyimpan sejumlah kecil daya.
+block.beam-tower.description = Mentransmisikan daya ke blok lain secara ortogonal. Menyimpan sejumlah besar daya. Jarak jauh.
+block.turbine-condenser.description = Menghasilkan tenaga ketika ditempatkan pada ventilasi. Menghasilkan sedikit air.
+block.chemical-combustion-chamber.description = Menghasilkan tenaga dari arkycite dan ozon.
+block.pyrolysis-generator.description = Menghasilkan tenaga dalam jumlah besar dari arkisit dan terak. Menghasilkan air sebagai produk sampingan.
+block.flux-reactor.description = Menghasilkan daya dalam jumlah besar ketika dipanaskan. Membutuhkan sianogen sebagai penstabil. Daya yang dihasilkan dan kebutuhan sianogen sebanding dengan panas yang masuk.\nMeledak jika sianogen yang disediakan tidak mencukupi.
+block.neoplasia-reactor.description = Menggunakan arkisit, air, dan phase fabric untuk menghasilkan daya dalam jumlah besar. Menghasilkan panas dan neoplasma yang berbahaya sebagai produk sampingan.\nMeledak hebat jika neoplasma tidak dikeluarkan dari reaktor melalui saluran.
+block.build-tower.description = Secara otomatis membangun kembali bangunan dalam jangkauan dan membantu unit lain dalam konstruksi.
+block.regen-projector.description = Perlahan memperbaiki bangunan sekutu di perimeter persegi. Membutuhkan hidrogen. Gunakan phase fabric untuk meningkatkan efisiensi (Opsional).
+block.reinforced-container.description = Menyimpan sejumlah kecil barang. Isi kontainer dapat diambil melalui pembongkaran. Tidak dapat meningkatkan kapasitas penyimpanan inti.
+block.reinforced-vault.description = Menyimpan sejumlah besar barang. Isi gudang dapat diambil melalui pembongkaran. Tidak dapat meningkatkan kapasitas penyimpanan inti.
+block.tank-fabricator.description = Membangun unit Stell. Unit dapat digunakan secara langsung, atau dipindahkan ke pabrikator ulang untuk ditingkatkan.
+block.ship-fabricator.description = Membangun unit Elude. Unit dapat digunakan secara langsung, atau dipindahkan ke pabrikator ulang untuk ditingkatkan.
+block.mech-fabricator.description = Membangun unit Merui. Unit dapat digunakan secara langsung, atau dipindahkan ke pabrikator ulang untuk ditingkatkan.
+block.tank-assembler.description = Merakit Unit Tank besar dari blok dan unit yang dimasukkan. Tingkat keluaran dapat ditingkatkan dengan menambahkan modul.
+block.ship-assembler.description = Merakit Unit Kapal besar dari blok dan unit yang dimasukkan. Tingkat keluaran dapat ditingkatkan dengan menambahkan modul.
+block.mech-assembler.description = Merakit Unit Mech besar dari blok dan unit yang dimasukkan. Tingkat keluaran dapat ditingkatkan dengan menambahkan modul.
+block.tank-refabricator.description = Meningkatkan unit tank yang dimasukkan ke tingkat kedua.
+block.ship-refabricator.description = Meningkatkan unit kapal yang dimasukkan ke tingkat kedua.
+block.mech-refabricator.description = Meningkatkan unit mech yang dimasukkan ke tingkat kedua.
+block.prime-refabricator.description = Meningkatkan unit yang dimasukkan ke tingkat ketiga.
+block.basic-assembler-module.description = Meningkatkan tingkat perakit ketika ditempatkan di sebelah batas konstruksi. Membutuhkan tenaga. Dapat digunakan sebagai penerima muatan.
+block.small-deconstructor.description = Mendekonstruksi bangunan dan unit yang dimasukkan. Mengembalikan 100% biaya pembangunan.
+block.reinforced-payload-conveyor.description = Memindahkan muatan ke depan.
+block.reinforced-payload-router.description = Mendistribusikan muatan ke blok yang berdekatan. Berfungsi sebagai penyortir ketika filter disetel.
+block.payload-mass-driver.description = Struktur transportasi muatan jarak jauh. Menembak muatan ke penembak muatan massal yang terhubung.
+block.large-payload-mass-driver.description = Struktur transportasi muatan jarak jauh. Menembak muatan ke penembak muatan massal yang terhubung.
+block.unit-repair-tower.description = Memulihkan semua unit di sekitarnya. Membutuhkan ozon.
+block.radar.description = Secara bertahap mengungkap medan dan unit musuh dalam radius besar. Membutuhkan tenaga.
+block.shockwave-tower.description = Merusak dan menghancurkan proyektil musuh dalam radius. Membutuhkan sianogen.
+block.canvas.description = Menampilkan gambar sederhana dengan palet yang telah ditentukan sebelumnya. Dapat diedit.
unit.dagger.description = Menembak musuh terdekat dengan amunisi standar.
unit.mace.description = Menyerang musuh terdekat dengan cara membakarnya.
unit.fortress.description = Menembak musuh darat dengan artileri jarak jauh.
unit.scepter.description = Menembak semua musuh terdekat dengan rentetan peluru bermuatan listrik.
-unit.reign.description = Menembak semua musuh terdekat dengan gugusan peluru tajam dalam jumlah banyak.
-unit.nova.description = Menembak baut laser yang dapat merusak musuh dan memperbaiki bangunan teman. Dapat terbang.
-unit.pulsar.description = Menembak petir yang dapat merusak musuh dan memperbaiki bangunan teman. Dapat terbang.
-unit.quasar.description = Menembak sinar laser yang dapat menembus bangunan yang dapat merusak musuh dan memperbaiki bangunan teman. Dapat terbang. Memiliki perisai.
-unit.vela.description = Menembak sinar laser besar dan kontinu yang dapat merusak musuh, membakarnya dan memperbaiki bangunan teman. Dapat terbang.
-unit.corvus.description = Menembak sinar laser besar yang dapat merusak musuh dan memperbaiki bangunan teman. Dapat berjalan diatas hampir semua medan.
+unit.reign.description = Menembak semua musuh terdekat dengan rentetan peluru tajam dalam jumlah banyak.
+unit.nova.description = Menembak baut laser yang dapat merusak musuh dan memperbaiki bangunan sekutu. Dapat terbang.
+unit.pulsar.description = Menembak petir yang dapat merusak musuh dan memperbaiki bangunan sekutu. Dapat terbang.
+unit.quasar.description = Menembak sinar laser yang dapat menembus bangunan yang dapat merusak musuh dan memperbaiki bangunan sekutu. Dapat terbang. Memiliki perisai.
+unit.vela.description = Menembak sinar laser besar dan kontinu yang dapat merusak musuh, membakarnya dan memperbaiki bangunan sekutu. Dapat terbang.
+unit.corvus.description = Menembak sinar laser besar yang dapat merusak musuh dan memperbaiki bangunan sekutu. Dapat berjalan diatas hampir semua medan.
unit.crawler.description = Berlari menuju musuh dan menghancurkan dirinya, yang dapat menghasilkan ledakan besar.
unit.atrax.description = Menembak musuh dengan cairan lava kepada target darat. Dapat berjalan diatas hampir semua medan.
unit.spiroct.description = Menembak laser pelemah kepada musuh, dapat memperbaiki dirinya dalam proses. Dapat berjalan diatas hampir semua medan.
unit.arkyid.description = Menembak laser pelemah besar kepada musuh, dapat memperbaiki dirinya dalam proses. Dapat berjalan diatas hampir semua medan.
-unit.toxopid.description = Menembak gugusan cangkang energi besar dan laser penusuk kepada musuh. Dapat berjalan diatas hampir semua medan.
+unit.toxopid.description = Menembak gugusan peluru listrik besar dan laser penusuk kepada musuh. Dapat berjalan diatas hampir semua medan.
unit.flare.description = Menembak musuh darat terdekat dengan amunisi standar.
unit.horizon.description = Menjatuhkan gugusan bom kepada musuh darat.
unit.zenith.description = Menembak misil kepada musuh terdekat.
@@ -2292,46 +2353,46 @@ unit.eclipse.description = Menembak dua sinar laser dan rentetan peluru kepada m
unit.mono.description = Menambang tembaga dan timah secara otomatis, membawanya menuju inti.
unit.poly.description = Membangun kembali bangunan yang hancur secara otomatis dan membantu unit lain dalam pembangunan.
unit.mega.description = Memperbaiki bangunan secara otomatis. Dapat membawa bangunan dan unit darat kecil.
-unit.quad.description = Menjatuhkan bom besar kepada target darat, yang bisa memberbaiki struktur teman dan merusak musuh. Dapat membawa unit darat berukuran sedang.
-unit.oct.description = Melindungi teman disekitarnya dengan perisai yang dapat beregenerasi. Dapat membawa hampir semua unit darat.
-unit.risso.description = Menembak misil dan peluru kepada semua musuh terdekat.
+unit.quad.description = Menjatuhkan bom besar kepada target darat, yang bisa memberbaiki bangunan sekutu dan merusak musuh. Dapat membawa unit darat berukuran sedang.
+unit.oct.description = Melindungi sekutu di sekitarnya dengan perisai yang dapat beregenerasi. Dapat membawa hampir semua unit darat.
+unit.risso.description = Menembak rentetan misil dan peluru kepada semua musuh terdekat.
unit.minke.description = Menembak cangkang pembakar dan peluru standar kepada musuh darat terdekat.
unit.bryde.description = Menembak artileri jarak jauh dan misil kepada musuh.
-unit.sei.description = Menembak rentetan misil dan peluru yang dapat menembus baju besi kepada musuh.
+unit.sei.description = Menembak rentetan misil dan peluru yang dapat menembus pelindung kepada musuh.
unit.omura.description = Menembak railgun jarak jauh kepada musuh. Dapat memproduksi unit flare.
-unit.alpha.description = Melindungi Inti Bagian dari musuh. Dapat membangun.
-unit.beta.description = Melindungi Inti Fondasi dari musuh. Dapat membangun.
-unit.gamma.description = Melindungi Inti Nukleus dari musuh. Dapat membangun.
-unit.retusa.description = Menembak torpedo pelacak. Memperbaiki unit teman.
+unit.alpha.description = Melindungi Inti Bagian dari musuh. Dapat membangun struktur.
+unit.beta.description = Melindungi Inti Fondasi dari musuh. Dapat membangun struktur.
+unit.gamma.description = Melindungi Inti Nukleus dari musuh. Dapat membangun struktur.
+unit.retusa.description = Menembak torpedo pelacak. Memperbaiki unit sekutu.
unit.oxynoe.description = Menembak aliran api pada musuh terdekat. Menargetkan proyektil musuh terdekat dengan titik menara pertahanan.
-unit.cyerce.description = Menembak misil yang membidik otomatis secara beruntun pada musuh. Memperbaiki unit teman.
-unit.aegires.description = Mengkejutkan semua bangunan dan unit musuh yang ada di dalam medan energi. Memperbaiki seluruh unit teman.
-unit.navanax.description = Menembak proyektil elektromagnetik yang meledak, memberikan kerusakan yang signifikan pada jaringan tenaga musuh dan memperbaiki bangunan teman. Melelehkan musuh terdekat dengan 4 menara laser secara otomatis.
+unit.cyerce.description = Menembak misil yang membidik otomatis secara beruntun pada musuh. Memperbaiki unit sekutu.
+unit.aegires.description = Mengkejutkan semua bangunan dan unit musuh yang ada di dalam medan energi. Memperbaiki seluruh unit sekutu.
+unit.navanax.description = Menembak proyektil elektromagnetik yang meledak, memberikan kerusakan yang signifikan pada jaringan tenaga musuh dan memperbaiki bangunan sekutu. Melelehkan musuh terdekat dengan 4 menara laser secara otomatis.
#Erekir
-unit.stell.description = Fires standard bullets at enemy targets.
-unit.locus.description = Fires alternating bullets at enemy targets.
-unit.precept.description = Fires piercing cluster bullets at enemy targets.
-unit.vanquish.description = Fires large piercing splitting bullets at enemy targets.
-unit.conquer.description = Fires large piercing cascades of bullets at enemy targets.
-unit.merui.description = Fires long-range artillery at enemy ground targets. Can step over most terrain.
-unit.cleroi.description = Fires dual shells at enemy targets. Targets enemy projectiles with point defense turrets. Can step over most terrain.
-unit.anthicus.description = Fires long-range homing missiles at enemy targets. Can step over most terrain.
-unit.tecta.description = Fires homing plasma missiles at enemy targets. Protects itself with a directional shield. Can step over most terrain.
-unit.collaris.description = Fires long-range fragmenting artillery at enemy targets. Can step over most terrain.
-unit.elude.description = Fires pairs of homing bullets at enemy targets. Can float over bodies of liquid.
-unit.avert.description = Fires twisting pairs of bullets at enemy targets.
-unit.obviate.description = Fires twisting pairs of lightning orbs at enemy targets.
-unit.quell.description = Fires long-range homing missiles at enemy targets. Suppresses enemy structure repair blocks.
-unit.disrupt.description = Fires long-range homing suppression missiles at enemy targets. Suppresses enemy structure repair blocks.
-unit.evoke.description = Builds structures to defend the Bastion core. Repairs structures with a beam.
-unit.incite.description = Builds structures to defend the Citadel core. Repairs structures with a beam.
-unit.emanate.description = Builds structures to defend the Acropolis core. Repairs structures with beams.
+unit.stell.description = Menembak peluru standar pada musuh.
+unit.locus.description = Menembak peluru bergantian pada musuh.
+unit.precept.description = Menembak gugusan peluru penusuk pada musuh.
+unit.vanquish.description = Menembak peluru penusuk pemisahan besar pada musuh.
+unit.conquer.description = Menembak peluru penusuk besar yang berpancar pada musuh.
+unit.merui.description = Menembak artileri jarak jauh pada musuh di darat. Dapat melewati berbagai dataran.
+unit.cleroi.description = Menembak peluru ganda pada musuh. Menargetkan proyektil musuh terdekat dengan titik menara pertahanan. Dapat melewati berbagai dataran.
+unit.anthicus.description = Menembak misil pelacak jarak jauh pada musuh. Dapat melewati berbagai dataran.
+unit.tecta.description = Menembak misil plasma pelacak pada musuh. Melindungi diri sendiri dengan perisai searah. Dapat melewati berbagai dataran.
+unit.collaris.description = Menembak pecahan artileri jarak jauh pada musuh. Dapat melewati berbagai dataran.
+unit.elude.description = Menembak sepasang peluru pelacak pada musuh. Dapat melayang diatas permukaan cairan.
+unit.avert.description = Menembak sepasang peluru yang memutar pada musuh.
+unit.obviate.description = Menembak sepasang bola listrik yang memutar pada musuh.
+unit.quell.description = Menembak misil pelacak jarak jauh pada musuh. Menahan bangunan perbaikan musuh.
+unit.disrupt.description = Menembak misil pelacak penekanan jarak jauh pada musuh. Menahan bangunan perbaikan musuh.
+unit.evoke.description = Membangun struktur untuk melindungi inti Bastion. Memperbaiki bangunan dengan sebuah sinar. Dapat membawa bangunan hingga ukuran 2x2.
+unit.incite.description = Membangun struktur untuk melindungi inti Citadel. Memperbaiki bangunan dengan sebuah sinar. Dapat membawa bangunan hingga ukuran 2x2.
+unit.emanate.description = Membangun struktur untuk melindungi inti Acropolis. Memperbaiki bangunan dengan sebuah sinar. Dapat membawa bangunan hingga ukuran 2x2
lst.read = Membaca angka dari memori sel yang dihubungkan.
lst.write = Menulis angka ke memori sel yang dihubungkan.
lst.print = Menambahkan teks ke daftar cetak.\nTidak dapat menampilkan apapun sampai [accent]Print Flush[] dipakai.
-lst.format = Replace next placeholder in text buffer with a value.\nDoes not do anything if placeholder pattern is invalid.\nPlaceholder pattern: "{[accent]number 0-9[]}"\nExample:\n[accent]print "test {0}"\nformat "example"
+lst.format = Ganti placeholder berikutnya di buffer teks dengan sebuah nilai.\nTidak melakukan apa pun jika pola placeholder tidak valid.\nPola placeholder: "{[accent]nomor 0-9[]}"\nContoh:\n[accent]print "test {0}"\nformat "example"
lst.draw = Menambahkan perintah ke daftar gambar.\nTidak dapat menampilkan apapun sampai [accent]Draw Flush[] dipakai.
lst.drawflush = Mengeluarkan perintah [accent]Draw[] dari daftar antrean untuk ditampilkan.
lst.printflush = Mengeluarkan perintah [accent]Print[] dari daftar antrean untuk blok pesan.
@@ -2349,13 +2410,13 @@ lst.jump = Loncati secara bersyarat ke pernyataan berikutnya.
lst.unitbind = Menautkan ke unit jenis berikutnya, dan menyimpannya di [accent]@unit[].
lst.unitcontrol = Mengendalikan unit yang saat ini dihubungkan.
lst.unitradar = Mendeteksi unit lain di sekitar unit yang saat ini dihubungkan.
-lst.unitlocate = Mendeteksi sebuah tipe tertentu dari posisi/bangunan di mana saja di peta.\nMemerlukan unit yang dihubungkan.
-lst.getblock = Mendapatkan data petak di lokasi manapun.
-lst.setblock = Menentukan data petak di lokasi manapun.
+lst.unitlocate = Mendeteksi sebuah tipe tertentu dari posisi/bangunan di mana saja di peta.\nMembutuhkan unit yang dihubungkan.
+lst.getblock = Mendapatkan data ubin di lokasi manapun.
+lst.setblock = Menentukan data ubin di lokasi manapun.
lst.spawnunit = Munculkan unit pada tempat yang ditentukan.
lst.applystatus = Menerapkan atau menghapus status efek dari sebuah unit.
-lst.weathersense = Check if a type of weather is active.
-lst.weatherset = Set the current state of a type of weather.
+lst.weathersense = Periksa apakah jenis cuaca aktif.
+lst.weatherset = Tetapkan suatu keadaan pada jenis cuaca saat ini.
lst.spawnwave = Simulasikan adanya gelombang pada lokasi acak.\nTidak akan ditambahkan pada jumlah gelombang keseluruhan.
lst.explosion = Membuat sebuah ledakan pada lokasi yang ditentukan.
lst.setrate = Menentukan kecepatan eksekusi prosesor dalam instruksi per tick.
@@ -2366,65 +2427,73 @@ lst.flushmessage = Tampilkan sebuah pesan di layar dari antrian teks.\nAkan menu
lst.cutscene = Mengendalikan kamera pemain.
lst.setflag = Menentukan global flag yang dapat dibaca oleh semua prosesor.
lst.getflag = Periksa apakah ada global flag yang ditentukan.
-lst.setprop = Sets a property of a unit or building.
-lst.effect = Create a particle effect.
-lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
-lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
-lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
-lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
+lst.setprop = Menetapkan properti unit atau bangunan.
+lst.effect = Buat efek partikel.
+lst.sync = Sinkronkan variabel di seluruh jaringan.\nHanya dipanggil paling banyak 10 kali per detik.
+lst.playsound = Memutar suara. \nVolume dan kontrol suara dapat berupa nilai global, atau dihitung berdasarkan posisi.
+lst.makemarker = Buat penanda logika baru di dunia.\nSebuah ID untuk mengidentifikasi penanda ini harus disediakan.\nPenanda saat ini dibatasi hingga 20.000 per dunia.
+lst.setmarker = Tetapkan properti untuk penanda.\nID yang digunakan harus sama dengan instruksi Membuat Marker.
+lst.localeprint = Tambahkan nilai properti peta lokal ke buffer teks.\nUntuk menyetel paket peta lokal di editor peta, cek [accent]Info Peta > Paket Local[].\nJika klien adalah perangkat seluler, coba cetak properti yang diakhiri dengan ".mobile" terlebih dahulu.
+
lglobal.false = 0
lglobal.true = 1
lglobal.null = null
-lglobal.@pi = The mathematical constant pi (3.141...)
-lglobal.@e = The mathematical constant e (2.718...)
-lglobal.@degToRad = Multiply by this number to convert degrees to radians
-lglobal.@radToDeg = Multiply by this number to convert radians to degrees
-lglobal.@time = Playtime of current save, in milliseconds
-lglobal.@tick = Playtime of current save, in ticks (1 second = 60 ticks)
-lglobal.@second = Playtime of current save, in seconds
-lglobal.@minute = Playtime of current save, in minutes
-lglobal.@waveNumber = Current wave number, if waves are enabled
-lglobal.@waveTime = Countdown timer for waves, in seconds
-lglobal.@mapw = Map width in tiles
-lglobal.@maph = Map height in tiles
-lglobal.sectionMap = Map
-lglobal.sectionGeneral = General
-lglobal.sectionNetwork = Network/Clientside [World Processor Only]
-lglobal.sectionProcessor = Processor
-lglobal.sectionLookup = Lookup
-lglobal.@this = The logic block executing the code
-lglobal.@thisx = X coordinate of block executing the code
-lglobal.@thisy = Y coordinate of block executing the code
-lglobal.@links = Total number of blocks linked to this processors
-lglobal.@ipt = Execution speed of the processor in instructions per tick (60 ticks = 1 second)
-lglobal.@unitCount = Total number of types of unit content in the game; used with the lookup instruction
-lglobal.@blockCount = Total number of types of block content in the game; used with the lookup instruction
-lglobal.@itemCount = Total number of types of item content in the game; used with the lookup instruction
-lglobal.@liquidCount = Total number of types of liquid content in the game; used with the lookup instruction
-lglobal.@server = True if the code is running on a server or in singleplayer, false otherwise
-lglobal.@client = True if the code is running on a client connected to a server
-lglobal.@clientLocale = Locale of the client running the code. For example: en_US
-lglobal.@clientUnit = Unit of client running the code
-lglobal.@clientName = Player name of client running the code
-lglobal.@clientTeam = Team ID of client running the code
-lglobal.@clientMobile = True is the client running the code is on mobile, false otherwise
+lglobal.@pi = Konstan matematikal pi (3.141...)
+lglobal.@e = Konstan matematikal e (2.718...)
+lglobal.@degToRad = Mengalikan dengan angka ini untuk mengubah derajat ke radian
+lglobal.@radToDeg = Mengalikan dengan angka ini untuk mengubah radian ke derajat
-logic.nounitbuild = [red]Logika unit membangun tidak diperbolehkan di sini.
+lglobal.@time = Waktu main dari simpanan saat ini, dalam milidetik
+lglobal.@tick = Waktu main dari simpanan saat ini, dalam tick (1 detik = 60 ticks)
+lglobal.@second = Waktu main dari simpanan saat ini, dalam detik
+lglobal.@minute = Waktu main dari simpanan saat ini, dalam menit
+lglobal.@waveNumber = Angka gelombang saat ini, jika gelombang diaktifkan
+lglobal.@waveTime = Pewaktu hitung mundur untuk gelombang, dalam detik
+lglobal.@mapw = Lebar peta, dalam ubin.
+lglobal.@maph = Tinggi peta, dalam ubin.
+
+lglobal.sectionMap = Peta
+lglobal.sectionGeneral = Umum
+lglobal.sectionNetwork = Jaringan/Sisi-klien [Hanya Prosesor Dunia]
+lglobal.sectionProcessor = Prosesor
+lglobal.sectionLookup = Pencarian
+
+lglobal.@this = Blok logika yang mengeksekusi suatu kode
+lglobal.@thisx = Koordinat X dari blok yang mengeksekusi suatu kode
+lglobal.@thisy = Koordinat Y dari blok yang mengeksekusi suatu kode
+lglobal.@links = Jumlah total blok yang ditautkan ke prosesor ini
+lglobal.@ipt = Kecepatan eksekusi dari prosesor dalam intruksi per tick (60 tick = 1 detik)
+
+lglobal.@unitCount = Jumlah total dari tipe pada konten unit di dalam game; digunakan dengan intruksi pencarian
+lglobal.@blockCount = Jumlah total dari tipe pada konten blok di dalam game; digunakan dengan intruksi pencarian
+lglobal.@itemCount = Jumlah total dari tipe pada konten item di dalam game; digunakan dengan intruksi pencarian
+lglobal.@liquidCount = Jumlah total dari tipe pada konten cairan di dalam game; digunakan dengan intruksi pencarian
+
+lglobal.@server = True jika kode dijalankan di server atau di singleplayer, false sebaliknya
+lglobal.@client = True jika kode dijalankan dalam sebuah klien disambungkan ke sebuah server
+
+lglobal.@clientLocale = Lokalisasi pada klien yang menjalankan suatu kode. Untuk contoh: en_US
+lglobal.@clientUnit = Unit pada klien yang menjalankan suatu kode
+lglobal.@clientName = Nama player pada klien yang menjalankan suatu kode
+lglobal.@clientTeam = ID Tim pada klien yang menjalankan suatu kode
+lglobal.@clientMobile = True jika kode dijalankan di server atau di singleplayer, false sebaliknya
+
+logic.nounitbuild = [red]Logika unit membangun tidak diizinkan.
lenum.type = Bentuk dari bangunan/unit.\nMisalnya, untuk blok pengarah masa, akan tampil sebagai [accent]@router[].\nBukan string.
lenum.shoot = Menembak pada suatu posisi yang ditentukan.
lenum.shootp = Menembak pada unit/bangunan dengan prediksi kecepatan.
lenum.config = Pengaturan bangunan, misalnya menyortir barang.
lenum.enabled = Menentukan aktif tidaknya suatu blok.
-laccess.currentammotype = Current ammo item/liquid of a turret.
+laccess.currentammotype = Bahan amunisi/cairan menara saat ini.
laccess.color = Warna lampu.
laccess.controller = Pengendali unit. Jika dikendalikan prosesor, mengembalikan prosesor.\nJika unit dalam barisan, mengembalikan leader.\nSebaliknya, mengembalikan unit itu sendiri.
laccess.dead = Menentukan apakah unit/bangunan itu hancur atau tidak ada lagi.
laccess.controlled = Mengembalikan:\n[accent]@ctrlProcessor[] bila pengendali unit adalah prosesor\n[accent]@ctrlPlayer[] bila pengendali unit/bangunan adalah pemain\n[accent]@ctrlFormation[] bila unit dalam formasi\nSebaliknya, 0.
laccess.progress = Memeriksa hasil kemajuan, 0 sampai 1.\nMengembalikan hasil laju produksi, pengisian ulang menara atau pembangunan.
-laccess.speed = Kecepatan tertinggi dari suatu unit, dalam petak/detik.
-laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup operation.
+laccess.speed = Kecepatan tertinggi dari suatu unit, dalam ubin/detik.
+laccess.id = ID suatu unit/blok/bahan/cairan.\nIni adalah kebalikan dari operasi pencarian.
lcategory.unknown = Tak Diketahui
lcategory.unknown.description = Instruksi tanpa kategori.
@@ -2452,7 +2521,7 @@ graphicstype.poly = Mengisi sebuah poligon beraturan.
graphicstype.linepoly = Menggambar sebuah garis poligon beraturan.
graphicstype.triangle = Mengisi sebuah segitiga.
graphicstype.image = Membentuk sebuah gambar dari suatu konten.\nMisal: [accent]@router[] atau [accent]@dagger[].
-graphicstype.print = Draws text from the print buffer.\nClears the print buffer.
+graphicstype.print = Mengambar teks dari buffer cetak.\nHanya karakter ASCII yang diperbolehkan.\nMenghapus buffer cetak.
lenum.always = Selalu benar.
lenum.idiv = Pembagian integer.
@@ -2472,7 +2541,7 @@ lenum.xor = Bitwise XOR.
lenum.min = Minimum dari dua angka.
lenum.max = Maksimum dari dua angka.
lenum.angle = Sudut vektor dalam derajat.
-lenum.anglediff = Absolute distance between two angles in degrees.
+lenum.anglediff = Jarak mutlak antara dua sudut dalam derajat.
lenum.len = Panjang vektor.
lenum.sin = Sinus, dalam derajat.
@@ -2484,7 +2553,7 @@ lenum.acos = Arc kosinus, dalam derajat.
lenum.atan = Arc tangen, dalam derajat.
#bukan typo, lihat 'daerah hasil fungsi'
-lenum.rand = Angka Acak dalam jarak [0, value).
+lenum.rand = Angka acak dalam jarak [0, value).
lenum.log = Logaritma natural (ln).
lenum.log10 = Logaritma basis 10.
lenum.noise = Kebisingan simpleks 2D.
@@ -2492,7 +2561,7 @@ lenum.abs = Nilai absolut.
lenum.sqrt = Akar kuadrat.
lenum.any = Unit apapun.
-lenum.ally = Unit teman.
+lenum.ally = Unit sekutu.
lenum.attacker = Unit dengan senjata.
lenum.enemy = Unit musuh.
lenum.boss = Unit penjaga.
@@ -2501,7 +2570,7 @@ lenum.ground = Unit darat.
lenum.player = Unit yang dikendalikan oleh pemain.
lenum.ore = Bahan tambang.
-lenum.damaged = Bangunan teman yang rusak.
+lenum.damaged = Bangunan sekutu yang rusak.
lenum.spawn = Titik munculnya musuh.\nDapat berupa inti atau suatu posisi.
lenum.building = Bangunan dalam suatu kumpulan.
@@ -2512,7 +2581,7 @@ lenum.factory = Bangunan yang mengubah sumber daya.
lenum.repair = Tempat perbaikan.
lenum.battery = Baterai apapun.
lenum.resupply = Titik pemasok ulang.\nHanya berguna ketika [accent]"Amunisi Unit"[] dihidupkan.
-lenum.reactor = Reaktor Benturan/Thorium.
+lenum.reactor = Reaktor Benturan/Torium.
lenum.turret = Menara apapun.
sensor.in = Bangunan/unit yang akan dilacak.
@@ -2540,6 +2609,7 @@ unitlocate.building = Mengeluarkan variabel untuk bangunan yang terlihat.
unitlocate.outx = Mengeluarkan koordinat X.
unitlocate.outy = Mengeluarkan koordinat Y.
unitlocate.group = Kumpulan bangunan yang akan dicari.
+playsound.limit = Jika benar, cegah suara ini diputar \njika sudah diputar pada frame yang sama.
lenum.idle = Tidak bergerak, namun tetap membangun/menambang.\nSifat awalan.
lenum.stop = Berhenti bergerak/menambang/membangun.
@@ -2547,7 +2617,7 @@ lenum.unbind = Mematikan kendali logika.\nLanjutkan A.I. standar.
lenum.move = Bergerak ke posisi yang ditentukan.
lenum.approach = Mendekati posisi dalam radius.
lenum.pathfind = Mencari arah ke tempat munculnya musuh.
-lenum.autopathfind = Automatically pathfinds to the nearest enemy core or drop point.\nThis is the same as standard wave enemy pathfinding.
+lenum.autopathfind = Secara otomatis menemukan jalur ke inti atau zona pendaratan musuh terdekat.\nIni sama dengan pathfinding musuh pada gelombang standar.
lenum.target = Menembak pada posisi.
lenum.targetp = Menembak target dengan perkiraan kecepatan.
lenum.itemdrop = Menjatuhkan bahan.
@@ -2558,13 +2628,14 @@ lenum.payenter = Masuk/mendarat pada blok muatan yang saat ini unit sedang berdi
lenum.flag = Tanda numerik unit.
lenum.mine = Menambang pada sebuah posisi.
lenum.build = Membangun sebuah sttruktur.
-lenum.getblock = Fetch building, floor and block type at coordinates.\nUnit must be in range of the position, otherwise null is returned.
+lenum.getblock = Ambil tipe bangunan, lantai dan blok pada koordinat.\nUnit harus berada dalam jangkauan posisinya, jika tidak maka null akan dikembalikan.
lenum.within = Memeriksa apakah unit di dekat suatu posisi.
-lenum.boost = Mulai/berhenti mempercepat.
-lenum.flushtext = Flush print buffer's content to marker, if applicable.\nIf fetch is set to true, tries to fetch properties from map locale bundle or game's bundle.
-lenum.texture = Texture name straight from game's texture atlas (using kebab-case naming style).\nIf printFlush is set to true, consumes text buffer content as text argument.
-lenum.texturesize = Size of texture in tiles. Zero value scales marker width to original texture's size.
-lenum.autoscale = Whether to scale marker corresponding to player's zoom level.
-lenum.posi = Indexed position, used for line and quad markers with index zero being the first position.
-lenum.uvi = Texture's position ranging from zero to one, used for quad markers.
-lenum.colori = Indexed position, used for line and quad markers with index zero being the first color.
+lenum.boost = Mulai/berhenti memdorong.
+
+lenum.flushtext = Flush cetak konten buffer ke penanda, jika ada.\nJika pengambilan disetel ke true, coba ambil properti dari paket peta lokal atau paket game.
+lenum.texture = Nama tekstur langsung dari atlas tekstur game (menggunakan gaya penamaan kebab-case).\nJika printFlush disetel ke true, gunakan konten buffer teks sebagai argumen teks.
+lenum.texturesize = Ukuran tekstur pada ubin. Nilai nol mengskalakan lebar penanda ke ukuran tekstur asli.
+lenum.autoscale = Apakah akan menskalakan penanda sesuai dengan tingkat zoom pemain.
+lenum.posi = Posisi terindeks, digunakan untuk penanda garis dan segi empat dengan indeks nol sebagai posisi pertama.
+lenum.uvi = Posisi tekstur mulai dari nol hingga satu, digunakan untuk penanda segi empat.
+lenum.colori = Warna terindeks, digunakan untuk penanda garis dan segi empat dengan indeks nol sebagai warna pertama.
diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties
index 5b6dc2407d..8eaeb013db 100644
--- a/core/assets/bundles/bundle_it.properties
+++ b/core/assets/bundles/bundle_it.properties
@@ -142,6 +142,7 @@ mod.enabled = [lightgray]Abilitato
mod.disabled = [scarlet]Disabilitato
mod.multiplayer.compatible = [gray]Multiplayer Compatible
mod.disable = Disabilita
+mod.version = Version:
mod.content = Contenuto:
mod.delete.error = Impossibile eliminare questa mod. Il file potrebbe essere in uso.
mod.incompatiblegame = [red]Outdated Game
@@ -191,6 +192,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Completato
techtree = Albero Scoperte
techtree.select = Seleziona albero delle scoperte
@@ -291,13 +293,14 @@ disconnect.error = Errore di connessione.
disconnect.closed = Connessione chiusa.
disconnect.timeout = Connessione scaduta.
disconnect.data = Errore durante il caricamento del mondo!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Impossibile unirsi alla partita ([accent]{0}[]).
connecting = [accent]Connessione in corso...
reconnecting = [accent]Riconnessione in corso...
connecting.data = [accent]Caricamento del mondo...
server.port = Porta:
-server.addressinuse = Indirizzo già in uso!
server.invalidport = Numero porta non valido!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [scarlet]Errore nell'hosting del server.
save.new = Nuovo Salvataggio
save.overwrite = Sei sicuro di voler sovrascrivere questo salvataggio?
@@ -350,6 +353,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -493,6 +497,7 @@ waves.units.show = Mostra tutto
wavemode.counts = conteggi
wavemode.totals = totali
wavemode.health = salute
+all = All
editor.default = [lightgray]
details = Dettagli...
@@ -660,7 +665,6 @@ requirement.capture = Cattura {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Lancia
-research.multiplayer = Solo l'host può scoprire gli oggetti.
map.multiplayer = Solo l'host può vedere i settori.
uncover = Scopri
configure = Configura Equipaggiamento
@@ -729,6 +733,7 @@ error.mapnotfound = Mappa non trovata!
error.io = Errore I/O di rete.
error.any = Errore di rete sconosciuto.
error.bloom = Errore dell'avvio delle shaders.\nIl tuo dispositivo potrebbe non supportarle.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Pioggia
weather.snowing.name = Neve
@@ -779,6 +784,11 @@ threat.medium = Media
threat.high = Alta
threat.extreme = Estrema
threat.eradication = Catastrofe
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Pianeti
@@ -801,9 +811,19 @@ sector.fungalPass.name = Passo Fungino
sector.biomassFacility.name = Struttura di Sintesi di Biomassa
sector.windsweptIslands.name = Isole Ventose
sector.extractionOutpost.name = Avamposto di Estrazione Mineraria
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Terminale di Lancio Planetario
sector.coastline.name = Coastline
sector.navalFortress.name = Fortezza navale
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = La posizione ottimale per ricominciare. Bassa minaccia nemica. Poche risorse.\nRaccogli quanto più piombo e rame possibile.\nParti.
sector.frozenForest.description = Anche qui, più vicino alle montagne, le spore si sono diffuse. Le temperature gelide non possono contenerle per sempre.\n\nInizia l'avventura nell'energia. Costruisci generatori a combustione. Impara a usare i riparatori.
@@ -823,6 +843,18 @@ sector.impact0078.description = Qui giaciono i resti della nave da trasporto int
sector.planetaryTerminal.description = Il bersaglio finale.\n\nQuesta base costiera contiene una struttura capace di lanciare Nuclei ai pianeti locali. È estremamente protetto.\n\nProduci unità navali. Elimina il nemico il più rapidamente possibile. Scopri la struttura di lancio.
sector.coastline.description = In questo settore sono stati rilevati resti di tecnologia di unità navali. Respingi gli attacchi nemici, cattura il settore e acquisisci la tecnologia.
sector.navalFortress.description = Il nemico ha stabilito una base su un'isola remota e fortificata naturalmente. Distruggi questo avamposto. Acquisisci la loro tecnologia navale avanzata e fate ricerche.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
sector.lake.name = Nome
@@ -1018,6 +1050,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1082,6 +1115,8 @@ bullet.healamount = [stat]{0}[lightgray] quantità di cura
bullet.multiplier = [stat]{0}[lightgray]x moltiplicatore munizioni
bullet.reload = [stat]{0}%[lightgray] ricarica
bullet.range = [stat]{0}[lightgray] raggio in blocchi
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blocchi
unit.blockssquared = blocchi²
@@ -1142,12 +1177,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Ridimensionamento Interfaccia[lightgray] (richiede il riavvio)[]
setting.uiscale.description = Riavvio necessario per applicare le modifiche.
setting.swapdiagonal.name = Posizionamento Sempre Diagonale
-setting.difficulty.training = Allenamento
-setting.difficulty.easy = Facile
-setting.difficulty.normal = Normale
-setting.difficulty.hard = Difficile
-setting.difficulty.insane = Impossibile
-setting.difficulty.name = Difficoltà:
setting.screenshake.name = Movimento dello Schermo
setting.bloomintensity.name = Intensità d'illuminazione (Bloom Intensity)
setting.bloomblur.name = Illuminazione sfocata (Bloom Blur)
@@ -1237,6 +1266,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Seleziona Regione
keybind.schematic_menu.name = Menu Schematica
@@ -1314,12 +1344,16 @@ rules.wavetimer = Timer Ondate
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Ondate
rules.airUseSpawns = Air units use spawn points
rules.attack = Modalità Attacco
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Dimensione minima squadra
rules.rtsmaxsquadsize = Dimensione massima squadra
rules.rtsminattackweight = Min Attack Weight
@@ -1362,6 +1396,9 @@ rules.title.teams = squadre
rules.title.planet = pianeta
rules.lighting = Illuminazione
rules.fog = Nebbia di guerra
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fuoco
rules.anyenv =
rules.explosions = Danno da Esplosione Blocchi/Unità
@@ -1370,6 +1407,7 @@ rules.weather = Meteo
rules.weather.frequency = Frequenza:
rules.weather.always = sempre
rules.weather.duration = Durata:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1515,6 +1553,8 @@ block.graphite-press.name = Pressa per Grafite
block.multi-press.name = Multi Pressa
block.constructing = {0}\n[lightgray](In Costruzione)
block.spawn.name = Punto di Generazione Nemico
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Nucleo: Frammento
block.core-foundation.name = Nucleo: Fondamento
block.core-nucleus.name = Nucleo: Centrale
@@ -1772,6 +1812,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1819,6 +1860,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2045,6 +2087,10 @@ block.phase-wall.description = Protegge le strutture dai proiettili nemici rifle
block.phase-wall-large.description = Protegge le strutture dai proiettili nemici riflettendone la maggior parte all'impatto.
block.surge-wall.description = Protegge le strutture dai proiettili nemici rilasciando periodicamente archi elettrici al contatto.
block.surge-wall-large.description = Protegge le strutture dai proiettili nemici rilasciando periodicamente archi elettrici al contatto.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Un muro che può essere aperto o chiuso.
block.door-large.description = Un muro che può essere aperto o chiuso.
block.mender.description = Ripara periodicamente i blocchi nelle sue vicinanze.\nAccetta silicio per aumentare la portata e l'efficienza.
@@ -2172,6 +2218,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2184,6 +2231,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2343,6 +2391,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2495,6 +2544,7 @@ unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Don't move, but keep building/mining.\nThe default state.
lenum.stop = Stop moving/mining/building.
lenum.unbind = Completely disable logic control.\nResume standard AI.
diff --git a/core/assets/bundles/bundle_ja.properties b/core/assets/bundles/bundle_ja.properties
index ab9b095823..994f4f10f5 100644
--- a/core/assets/bundles/bundle_ja.properties
+++ b/core/assets/bundles/bundle_ja.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]有効
mod.disabled = [scarlet]無効
mod.multiplayer.compatible = [gray]マルチプレイに対応
mod.disable = 無効化
+mod.version = Version:
mod.content = コンテンツ:
mod.delete.error = Modを削除することができませんでした。
mod.incompatiblegame = [red]旧バージョン用
@@ -193,6 +194,7 @@ campaign.select = 開始するキャンペーンを選択
campaign.none = [lightgray]キャンペーンを始める惑星を選んでください。\n惑星はいつでも変更可能です。
campaign.erekir = より新しく、より洗練されたコンテンツ。 ほぼ一貫して進行するキャンペーン。\n\n高品質のマップと総合的な体験。
campaign.serpulo = 昔のコンテンツ。クラシックな体験。より自由な発想。\n\nマップやキャンペーンの仕組みがアンバランスになる可能性があり、あまり洗練されてない。
+campaign.difficulty = Difficulty
completed = [accent]完了
techtree = テックツリー
techtree.select = テックツリーの選択
@@ -293,13 +295,14 @@ disconnect.error = 接続にエラーが発生しました。
disconnect.closed = 接続が切断されました。
disconnect.timeout = タイムアウトしました。
disconnect.data = ワールドデータの読み込みに失敗しました!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = ゲームに参加できませんでした。 ([accent]{0}[])
connecting = [accent]接続中...
reconnecting = [accent]再接続中...
connecting.data = [accent]ワールドデータを読み込み中...
server.port = ポート:
-server.addressinuse = アドレスがすでに使用されています!
server.invalidport = 無効なポート番号です!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]サーバーのホストエラー: [accent]{0}
save.new = 新規保存
save.overwrite = このスロットに上書きしてもよろしいですか?
@@ -352,6 +355,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -495,6 +499,7 @@ waves.units.show = すべて表示
wavemode.counts = 数
wavemode.totals = 総数
wavemode.health = 総体力
+all = All
editor.default = [lightgray]<デフォルト>
details = 詳細...
@@ -664,7 +669,6 @@ requirement.capture = 制圧: {0}
requirement.onplanet = {0} の制御セクター
requirement.onsector = セクターに着陸: {0}
launch.text = 発射
-research.multiplayer = 研究できるのはホストのみです。
map.multiplayer = ホストのみがセクターを表示できます。
uncover = 開放
configure = 積み荷の設定
@@ -733,6 +737,7 @@ error.mapnotfound = マップファイルが見つかりません!
error.io = I/O ネットワークエラーです。
error.any = 不明なネットワークエラーです。
error.bloom = ブルームの初期化に失敗しました。\n恐らくあなたのデバイスではブルームがサポートされていません。
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = 雨
weather.snowing.name = 雪
@@ -783,6 +788,11 @@ threat.medium = 中
threat.high = 高
threat.extreme = 過酷
threat.eradication = 破滅的
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = 惑星
@@ -805,9 +815,19 @@ sector.fungalPass.name = 真菌の道
sector.biomassFacility.name = バイオマス研究施設
sector.windsweptIslands.name = 吹きさらしの列島
sector.extractionOutpost.name = 資源搬出前哨基地
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = 惑星間発射ターミナル
sector.coastline.name = 海岸線
sector.navalFortress.name = 海軍要塞
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = 奪回を始めるには最適な場所です。敵の脅威は小さいですが、資源が乏しいです。\nできるだけ多くの銅と鉛を集めましょう。\n始めましょう。
sector.frozenForest.description = ここでさえ、山に近づくほど胞子が広がっています。\n極寒の気候もでさえ胞子を永遠に封じ込めることはできませんでした。\n\n電気に挑みましょう。\n火力発電機を建設し、修復機の使い方を学びましょう。
@@ -827,6 +847,18 @@ sector.impact0078.description = ここには、最初にこの星系に入った
sector.planetaryTerminal.description = 最終目標です。\n\nこの沿岸基地には、コアを他の惑星に打ち上げることが出来る建造物があります。しかし、極めて堅固に守られています。\n\n海軍ユニットを生産し、可及的速やかに敵を排除してください。\nそして、発射場を研究しましょう。
sector.coastline.description = ここで、海軍の技術の残骸が発見されました。\n敵の攻撃を退け、占領し、その技術を獲得しましょう。
sector.navalFortress.description = 敵は、自然要塞化した離島に基地を設けています。この前哨基地を破壊しましょう。\n彼らの高度な艦艇技術を入手し、研究しましょう。
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = オンセット
sector.aegis.name = イージス
sector.lake.name = レイク
@@ -1024,6 +1056,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1088,6 +1121,8 @@ bullet.healamount = [stat]{0}[lightgray] 直接修理
bullet.multiplier = [stat]弾薬 {0}[lightgray]倍
bullet.reload = [stat]リロード速度 {0}[lightgray]%
bullet.range = [stat]{0}[lightgray] タイル範囲
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = ブロック
unit.blockssquared = ブロック²
@@ -1148,12 +1183,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UIサイズ
setting.uiscale.description = 再起動が必要です。
setting.swapdiagonal.name = 常に斜め設置
-setting.difficulty.training = トレーニング
-setting.difficulty.easy = イージー
-setting.difficulty.normal = ノーマル
-setting.difficulty.hard = ハード
-setting.difficulty.insane = クレイジー
-setting.difficulty.name = 難易度:
setting.screenshake.name = 画面の揺れ
setting.bloomintensity.name = きらめきの強さ
setting.bloomblur.name = 光のぼやけ
@@ -1243,6 +1272,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = リージョンの再構築
keybind.schematic_select.name = 範囲選択
keybind.schematic_menu.name = 設計図メニュー
@@ -1320,12 +1350,16 @@ rules.wavetimer = ウェーブの自動進行
rules.wavesending = ウェーブスキップ
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = ウェーブ
rules.airUseSpawns = Air units use spawn points
rules.attack = アタックモード
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = チームの最少人数
rules.rtsmaxsquadsize = チームの最大人数
rules.rtsminattackweight = 最小攻撃力
@@ -1368,6 +1402,9 @@ rules.title.teams = チーム
rules.title.planet = 惑星
rules.lighting = 霧
rules.fog = 戦場の霧
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = 火災
rules.anyenv =
rules.explosions = 爆発ダメージ
@@ -1376,6 +1413,7 @@ rules.weather = 気象
rules.weather.frequency = 頻度:
rules.weather.always = 常時
rules.weather.duration = 継続時間:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1518,6 +1556,8 @@ block.graphite-press.name = 黒鉛圧縮機
block.multi-press.name = マルチ圧縮機
block.constructing = {0}\n[lightgray](建設中)
block.spawn.name = 敵の出現場所
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = コア: シャード
block.core-foundation.name = コア: ファンデーション
block.core-nucleus.name = コア: ニュークリアス
@@ -1775,6 +1815,7 @@ block.electric-heater.name = 電気ヒーター
block.slag-heater.name = スラグヒーター
block.phase-heater.name = フェーズヒーター
block.heat-redirector.name = ヒートリダイレクター
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = ヒートルーター
block.slag-incinerator.name = スラグ焼却炉
block.carbide-crucible.name = 炭化物クルーシブル
@@ -1822,6 +1863,7 @@ block.chemical-combustion-chamber.name = 化学燃焼室
block.pyrolysis-generator.name = パイロリシス発電機
block.vent-condenser.name = ジェットコンデンサー
block.cliff-crusher.name = クリフ掘削機
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = プラズマ掘り
block.large-plasma-bore.name = 大きなプラズマ掘り
block.impact-drill.name = インパクトドリル
@@ -2049,6 +2091,10 @@ block.phase-wall.description = トリウムの壁ほど強固ではないが、
block.phase-wall-large.description = トリウムの壁ほど強固ではないが、強力な弾でなければ弾き返すことができます。
block.surge-wall.description = 最も硬い防壁ブロックです。\n攻撃されるとたまに放電して敵を攻撃します。
block.surge-wall-large.description = 最も硬い大型防壁ブロックです。\n攻撃されるとたまに放電して敵を攻撃します。
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = 小さなドアブロックです。タップすることで開閉することができます。\nただし、ドアが開いている場合、弾や敵も通過できます。
block.door-large.description = 大型のドアブロックです。タップすることで開閉することができます。\nただし、ドアが開いている場合、弾や敵も通過できます。
block.mender.description = 定期的に周囲のブロックを修復します。ウェーブの間も修復し続けます。\nオプションでシリコンを利用して、さらに効率的に修復が出来ます。
@@ -2176,6 +2222,7 @@ block.electric-heater.description = 大量の電力を消費して、向かい
block.slag-heater.description = スラグを用いて、向かい合ったブロックを加熱します。
block.phase-heater.description = フェーズファイバーを用いて、向かい合ったブロックを加熱します。
block.heat-redirector.description = 蓄積された熱を他のブロックに伝えます。
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = 蓄積された熱を3つの出力方向に分散させます。
block.electrolyzer.description = 水を電気分解して、水素とオゾンに変換します。
block.atmospheric-concentrator.description = 熱を利用して、大気中の窒素を濃縮します。
@@ -2188,6 +2235,7 @@ block.vent-condenser.description = 電力を消費して、ジェットホール
block.plasma-bore.description = 鉱石の壁に向けて配置して鉱石を掘りします。少量の電力が必要です。
block.large-plasma-bore.description = 大きくプラズマ掘り。 タングステン、トリウムの採掘が可能。 水素と電力が必要です
block.cliff-crusher.description = 電力を消費して、壁を粉砕し、砂を採掘します。 効率は壁の種類によって異なります。
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = 鉱石の上に置くと、一定の間隔でアイテムを採掘します。 電力と水が必要です。
block.eruption-drill.description = 改良されたインパクトドリルです。 トリウムの採掘が可能。 電力と水素が必要です。
block.reinforced-conduit.description = 液体または気体を輸送します。 側面からの搬入を受け入れません。
@@ -2347,6 +2395,7 @@ lst.getflag = グローバルフラグが設定されているかどうかを確
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2499,6 +2548,7 @@ unitlocate.building = 見つけた建物を出力する変数
unitlocate.outx = X座標を出力する変数
unitlocate.outy = Y座標を出力する変数
unitlocate.group = 探す建物のグループ
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = 移動はしませんが、建築・採掘は続けます。
lenum.stop = 移動・採掘・建造を中止します。
lenum.unbind = ロジック制御を完全に無効にします。\n標準的なAI制御に移行します。
diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties
index 79f23ca5ab..acd35634be 100644
--- a/core/assets/bundles/bundle_ko.properties
+++ b/core/assets/bundles/bundle_ko.properties
@@ -70,7 +70,7 @@ schematic.shareworkshop = 창작마당에 공유
schematic.flip = [accent][[{0}][]/[accent][[{1}][]: 설계도 뒤집기
schematic.saved = 설계도 저장됨
schematic.delete.confirm = 이 설계도는 완전히 삭제될 것입니다.
-schematic.edit = Edit Schematic
+schematic.edit = 설계도 수정
schematic.info = {0}x{1}, {2} 블록
schematic.disabled = [scarlet]설계도 비활성화됨[]\n이 [accent]맵[] 또는 [accent]서버[] 에서는 설계도를 사용할 수 없습니다.
schematic.tags = 태그:
@@ -79,13 +79,13 @@ schematic.addtag = 태그 추가하기
schematic.texttag = 텍스트 태그
schematic.icontag = 아이콘 태그
schematic.renametag = 태그 이름바꾸기
-schematic.tagged = {0} tagged
+schematic.tagged = {0} 태그됨
schematic.tagdelconfirm = 이 태그를 완전히 삭제하시겠습니까?
schematic.tagexists = 이 태그는 이미 존재합니다.
stats = 기록
stats.wave = 진행 단계
-stats.unitsCreated = 생성한 기체
+stats.unitsCreated = 생성한 유닛
stats.enemiesDestroyed = 파괴한 적
stats.built = 건설한 건물
stats.destroyed = 파괴한 건물
@@ -98,7 +98,7 @@ level.highscore = 최고 점수: [accent]{0}
level.select = 맵 선택
level.mode = 게임 모드:
coreattack = < 코어가 공격을 받고 있습니다! >
-nearpoint = [[ [scarlet]즉시 적 소환구역에서 떠나세요[] ]\n단계가 시작하는 순간 구역 내의 모든 건물과 기체가 파괴됩니다!
+nearpoint = [[ [scarlet]즉시 적 소환구역에서 떠나세요[] ]\n단계가 시작하는 순간 구역 내의 모든 건물과 유닛이 파괴됩니다!
database = 코어 데이터베이스
database.button = 데이터베이스
savegame = 게임 저장
@@ -144,8 +144,10 @@ mod.enabled = [lightgray]활성화됨
mod.disabled = [scarlet]비활성화됨
mod.multiplayer.compatible = [gray]멀티플레이어 호환 가능
mod.disable = 비활성화
+mod.version = Version:
mod.content = 콘텐츠:
mod.delete.error = 모드를 삭제할 수 없습니다. 파일이 사용 중일 수 있습니다.
+
mod.incompatiblegame = [red]구버전 게임
mod.incompatiblemod = [red]호환되지 않음
mod.blacklisted = [red]지원하지 않음
@@ -153,6 +155,7 @@ mod.unmetdependencies = [red]충촉되지 않은 종속성
mod.erroredcontent = [scarlet]콘텐츠 오류
mod.circulardependencies = [red]순환 의존성
mod.incompletedependencies = [red]불완전한 의존성
+
mod.requiresversion.details = 게임 버전 요구: [accent]{0}[]\n당신의 게임은 구버전입니다. 이 모드가 작동하려면 최신 버전의 게임이 필요합니다. (베타/알파 릴리즈일 가능성이 있음).
mod.outdatedv7.details = 이 모드는 최신 버전의 게임과 호환되지 않습니다. 반드시 작성자가 업데이트해야 하고, [accent]mod.json[] 파일에 [accent]최소게임버전: 136[]을 추가해야 합니다.
mod.blacklisted.details = 이 모드는 이 버전의 게임에서 충돌 또는 기타 문제를 일으키는 것으로 인해 수동으로 블랙리스트에 올라와 있습니다. 사용하지 마세요.
@@ -160,7 +163,9 @@ mod.missingdependencies.details = 이 모드에는 종속성이 없음: {0}
mod.erroredcontent.details = 이 게임은 로딩하는 동안 오류가 발생했습니다. 모드 작성자에게 수정하도록 요청하세요.
mod.circulardependencies.details = 이 모드는 서로 의존하는 의존성을 지니고 있습니다.
mod.incompletedependencies.details = 잘못되었거나 누락한 종속성으로 인해 이 모드를 불러올 수 없습니다: {0}.
+
mod.requiresversion = 필요한 게임 버전: [red]{0}
+
mod.errors = 콘텐츠를 불러오는 중에 오류가 발생함
mod.noerrorplay = [scarlet]오류가 있는 모드가 있습니다.[] 영향을 받는 모드를 비활성화하거나 플레이하기 전에 오류를 수정하세요.
mod.nowdisabled = [scarlet]모드 '{0}'에 필요한 종속성이 없습니다:[accent] {1}\n[lightgray]이 모드를 먼저 내려받아야 합니다.\n이 모드는 자동으로 비활성화됩니다.
@@ -191,8 +196,9 @@ available = 새로운 콘텐츠 해금이 가능합니다!
unlock.incampaign = < 해금 후 상세정보 열람이 가능합니다 >
campaign.select = 캠페인 시작지점 선택하기
campaign.none = [lightgray]시작할 행성을 선택하십시오.\n언제든지 전환할 수 있습니다.
-campaign.erekir = [accent]신규 플레이어에게 추천합니다.[]\n\n보다 새롭고 세련된 컨텐츠. 대부분 순차적으로 캠페인이 진행됩니다.\n\n더 높은 완성도의 지도와 다채로운 경험.
-campaign.serpulo = [scarlet]신규 플레이어에게 권장되지 않습니다.[]\n\n오래된 컨텐츠: 고전적인 경험. 좀 더 개방적이죠.\n\n잠재적으로 불균형한 지도와 캠페인 메커니즘. 덜 세련됩니다.
+campaign.erekir = [scarlet]신규 플레이어에게 권장되지 않습니다.[]\n\n보다 새롭고 세련된 컨텐츠. 대부분 순차적으로 캠페인이 진행됨.\n\n더 어렵고, 더 높은 완성도의 맵과 다채로운 경험.
+campaign.serpulo = [accent]신규 플레이어에게 추천합니다.[]\n\n오래된 콘텐츠, 고전적인 경험. 더 개방적이고, 더 많은 콘텐츠.\n\n잠재적으로 불균형한 맵과 캠페인 메커니즘. 덜 세련됨.
+campaign.difficulty = 난이도
completed = [accent]완료됨
techtree = 연구 기록
techtree.select = 연구 기록 선택
@@ -249,8 +255,8 @@ servers.disclaimer = 커뮤니티 서버는 개발자가 소유하거나 제어
servers.showhidden = 숨겨진 서버 보이기/숨기기
server.shown = 서버 숨기기
server.hidden = 서버 보이기
-viewplayer = 플레이어 보기: [accent]{0}
+viewplayer = 플레이어 보기: [accent]{0}
trace = 플레이어 정보 보기
trace.playername = 플레이어 이름: [accent]{0}
trace.ip = IP: [accent]{0}
@@ -260,14 +266,16 @@ trace.mobile = 모바일 클라이언트: [accent]{0}
trace.modclient = 사용자 지정 클라이언트: [accent]{0}
trace.times.joined = 입장 횟수: [accent]{0}
trace.times.kicked = 추방 횟수: [accent]{0}
-trace.ips = IPs:
-trace.names = Names:
+trace.ips = IP:
+trace.names = 이름:
invalidid = 잘못된 클라이언트 ID입니다! 버그 보고서를 보내주세요.
+
player.ban = 플레이어 차단
player.kick = 플레이어 강퇴
player.trace = 플레이어 찾기
player.admin = 관리자 권한 부여
player.team = 팀 변경하기
+
server.bans = 차단 목록
server.bans.none = 차단된 플레이어를 찾을 수 없습니다!
server.admins = 관리자
@@ -285,7 +293,7 @@ confirmunban = 정말로 이 플레이어를 차단 해제하시겠습니까?
confirmadmin = 정말로 "{0}[white]" 을(를) 관리자로 임명하시겠습니까?
confirmunadmin = 정말로 "{0}[white]"의 관리자를 박탈하시겠습니까?
votekick.reason = 강퇴 사유
-votekick.reason.message = "{0}[white]" 을(를) 투표 추방하시려면 해당 사유를 적어주세요 :
+votekick.reason.message = "{0}[white]" 을(를) 투표 추방하시려면 해당 사유를 적어주세요:
joingame.title = 게임 참가
joingame.ip = 주소:
disconnect = 연결이 끊어졌습니다.
@@ -293,13 +301,14 @@ disconnect.error = 연결 오류
disconnect.closed = 연결이 종료되었습니다.
disconnect.timeout = 시간 초과
disconnect.data = 맵 데이터를 로드하지 못했습니다!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = [accent]{0}[] 게임에 참여할 수 없습니다.
connecting = [accent] 연결중...
reconnecting = [accent]재접속중...
connecting.data = [accent]맵 데이터 불러오는중...
server.port = 포트:
-server.addressinuse = 이미 사용 중인 주소입니다!
server.invalidport = 잘못된 포트 번호입니다!
+server.error.addressinuse = [scarlet]포트 6567에서 서버를 열지 못했습니다.[]\n\n다른 Mindustry 서버가 귀하의 장치나 네트워크에서 실행되고 있지 않은지 확인하세요!
server.error = [scarlet]서버 호스팅 오류
save.new = 새로 저장
save.overwrite = 저장된 슬롯을 덮어쓰시겠습니까?
@@ -317,7 +326,7 @@ save.import = 저장 가져오기
save.newslot = 저장 이름:
save.rename = 이름 변경
save.rename.text = 새 이름:
-selectslot = 저장슬롯을 선택하세요.
+selectslot = 저장 슬롯을 선택하세요.
slot = [accent] 슬롯 {0}
editmessage = 메시지 편집
save.corrupted = [accent]손상되었거나 잘못된 저장 파일입니다!
@@ -341,7 +350,7 @@ open = 열기
customize = 사용자 정의 규칙
cancel = 취소
command = 명령
-command.queue = [lightgray][Queuing]
+command.queue = 대기
command.mine = 채굴
command.repair = 수리
command.rebuild = 재건
@@ -352,6 +361,7 @@ command.enterPayload = 화물 블록에 들어가기
command.loadUnits = 유닛 적재
command.loadBlocks = 블록 적재
command.unloadPayload = 화물 내려놓기
+command.loopPayload = 유닛 반복 운반
stance.stop = 명령 취소하기
stance.shoot = 명령: 사격
stance.holdfire = 명령: 사격 중지
@@ -384,14 +394,14 @@ resumebuilding = [scarlet][[{0}][] 키를 눌러 건설을 재개
enablebuilding = [scarlet][[{0}][] 키를 눌러 건설을 활성
showui = UI가 숨겨졌습니다. [accent][[{0}][] 키를 눌러 UI를 활성화하세요.
commandmode.name = [accent]명령 모드
-commandmode.nounits = [기체 없음]
+commandmode.nounits = [유닛 없음]
wave = [accent]{0}단계
wave.cap = [accent]단계 {0}/{1}
wave.waiting = 다음 단계까지[lightgray] {0}초
-wave.waveInProgress = [lightgray]단계 진행중
+wave.waveInProgress = [lightgray]단계 진행 중
waiting = [lightgray]대기중...
waiting.players = 상대 플레이어를 기다리는 중...
-wave.enemies = [lightgray]적 기체 {0}기 남음
+wave.enemies = [lightgray]적 유닛 {0}기 남음
wave.enemycores = [accent]{0}[lightgray] 적 코어들
wave.enemycore = [accent]{0}[lightgray] 적 코어
wave.enemy = [lightgray]{0}기 남음
@@ -421,6 +431,7 @@ publishing = [accent]게시 중...
publish.confirm = 이것을 게시하시겠습니까?[lightgray]창작마당 EULA에 동의해야 합니다. 그렇지 않으면 아이템이 표시되지 않습니다!
publish.error = 아이템 게시 오류: {0}
steam.error = 스팀 서비스를 초기화하지 못했습니다.\n오류: {0}
+
editor.planet = 행성:
editor.sector = 구역:
editor.seed = 시드:
@@ -437,12 +448,12 @@ editor.waves = 단계
editor.rules = 규칙
editor.generation = 지형 생성
editor.objectives = 목표
-editor.locales = Locale Bundles
-editor.worldprocessors = World Processors
-editor.worldprocessors.editname = Edit Name
-editor.worldprocessors.none = [lightgray]No world processor blocks found!\nAdd one in the map editor, or use the \ue813 Add button below.
-editor.worldprocessors.nospace = No free space to place a world processor!\nDid you fill the map with structures? Why would you do this?
-editor.worldprocessors.delete.confirm = Are you sure you want to delete this world processor?\n\nIf it is surrounded by walls, it will be replaced by an environmental wall.
+editor.locales = 번역 팩
+editor.worldprocessors = 월드 프로세서
+editor.worldprocessors.editname = 이름 수정
+editor.worldprocessors.none = [lightgray]월드 프로세서 블록을 찾을 수 없습니다!\n맵 편집기에서 추가하거나 아래의 \ue813 추가 버튼을 사용하세요.
+editor.worldprocessors.nospace = 월드 프로세서를 배치할 여유 공간이 없습니다!\n맵을 전부 구조물로 채웠나요? 왜 이렇게 했나요?
+editor.worldprocessors.delete.confirm = 이 월드 프로세서를 삭제하시겠습니까?\n\n주변이 벽으로 둘러싸여 있다면 지형 벽으로 대체될 것입니다.
editor.ingame = 인게임 편집
editor.playtest = 맵 테스트
editor.publish.workshop = 창작마당 게시
@@ -484,9 +495,9 @@ waves.sort = 정렬 기준
waves.sort.reverse = 정렬 뒤집기
waves.sort.begin = 시작 단계
waves.sort.health = 체력
-waves.sort.type = 기체 유형
-waves.search = Search waves...
-waves.filter = Unit Filter
+waves.sort.type = 유닛 유형
+waves.search = 단계 검색...
+waves.filter = 유닛 필터
waves.units.hide = 모두 숨기기
waves.units.show = 모두 보이기
@@ -495,15 +506,17 @@ wavemode.counts = 기
wavemode.totals = 총
wavemode.health = 체력
+all = 모두
editor.default = [lightgray]<기본값>
details = 설명...
edit = 편집...
variables = 변수
-logic.clear.confirm = Are you sure you want to clear all code from this processor?
-logic.globals = Built-in Variables
+logic.clear.confirm = 이 프로세서의 모든 코드를 삭제하시겠습니까?
+logic.globals = 내장 변수
+
editor.name = 이름:
-editor.spawn = 기체 생성
-editor.removeunit = 기체 삭제
+editor.spawn = 유닛 생성
+editor.removeunit = 유닛 삭제
editor.teams = 팀
editor.errorload = 파일을 불러오지 못했습니다.
editor.errorsave = 파일을 저장하지 못했습니다.
@@ -512,7 +525,7 @@ editor.errorlegacy = 이 맵은 너무 오래됐고, 더 이상 지원하지 않
editor.errornot = 맵 파일이 아닙니다.
editor.errorheader = 이 맵 파일은 유효하지 않거나 손상되었습니다.
editor.errorname = 맵에 이름이 지정되어 있지 않습니다. 저장 파일을 불러오려고 시도하는 건가요?
-editor.errorlocales = Error reading invalid locale bundles.
+editor.errorlocales = 잘못된 언어 팩을 읽는 동안 오류가 발생했습니다.
editor.update = 업데이트
editor.randomize = 무작위
editor.moveup = 위로 이동
@@ -524,7 +537,7 @@ editor.sectorgenerate = 구역 형성
editor.resize = 맵 크기조정
editor.loadmap = 맵 불러오기
editor.savemap = 맵 저장
-editor.savechanges = [scarlet]You have unsaved changes!\n\n[]Do you want to save them?
+editor.savechanges = [scarlet]저장하지 않은 변경 사항이 있습니다!\n\n[]저장하시겠습니까?
editor.saved = 저장됨!
editor.save.noname = 맵에 이름이 없습니다! '맵 정보' 메뉴에서 설정하세요.
editor.save.overwrite = 이 맵은 내장된 맵을 덮어씁니다! '맵 정보' 에서 다른 이름을 선택하세요.
@@ -563,8 +576,8 @@ toolmode.eraseores = 자원 초기화
toolmode.eraseores.description = 자원만 초기화합니다.
toolmode.fillteams = 팀 채우기
toolmode.fillteams.description = 블록의 팀을 선택한 팀으로 채웁니다.
-toolmode.fillerase = Fill Erase
-toolmode.fillerase.description = Erase blocks of the same type.
+toolmode.fillerase = 유형별 지우기
+toolmode.fillerase.description = 같은 유형의 블록을 지웁니다.
toolmode.drawteams = 팀 그리기
toolmode.drawteams.description = 블록의 팀을 선택한 팀으로 그립니다.
#unused
@@ -589,7 +602,7 @@ filter.clear = 초기화
filter.option.ignore = 무시
filter.scatter = 흩뿌리기
filter.terrain = 지형
-filter.logic = Logic
+filter.logic = 로직
filter.option.scale = 크기
filter.option.chance = 배치 빈도
@@ -615,23 +628,24 @@ filter.option.radius = 반경
filter.option.percentile = 백분율
filter.option.code = 코드
filter.option.loop = 루프
-locales.info = Here, you can add locale bundles for specific languages to your map. In locale bundles, each property has a name and a value. These properties can be used by world processors and objectives using their names. They support text formatting (replacing placeholders with actual values).\n\n[cyan]Example property:\n[]name: [accent]timer[]\nvalue: [accent]Example timer, time left: {0}[]\n\n[cyan]Usage:\n[]Set it as objective's text: [accent]@timer\n\n[]Print it in a world processor:\n[accent]localeprint "timer"\nformat time\n[gray](where time is a separately calculated variable)
-locales.deletelocale = Are you sure you want to delete this locale bundle?
-locales.applytoall = Apply Changes To All Locales
-locales.addtoother = Add To Other Locales
-locales.rollback = Rollback to last applied
-locales.filter = Property filter
-locales.searchname = Search name...
-locales.searchvalue = Search value...
-locales.searchlocale = Search locale...
-locales.byname = By name
-locales.byvalue = By value
-locales.showcorrect = Show properties that are present in all locales and have unique values everywhere
-locales.showmissing = Show properties that are missing in some locales
-locales.showsame = Show properties that have same values in different locales
-locales.viewproperty = View in all locales
-locales.viewing = Viewing property "{0}"
-locales.addicon = Add Icon
+
+locales.info = 여기에서 특정 언어에 대한 언어 팩을 맵에 추가할 수 있습니다. 언어 팩에서 각 속성에는 이름과 값이 있습니다. 이러한 속성은 이름을 사용하여 월드 프로세서와 목표에서 사용할 수 있습니다. 텍스트 서식 지정(플레이스홀더를 실제 값으로 대체)을 지원합니다.\n\n[cyan]예시 속성:\n[]이름: [accent]timer[]\n값: [accent]예시 타이머, 남은 시간: {0}[]\n\n[cyan]사용법:\n[]목표의 텍스트로 설정: [accent]@timer\n\n[]월드 프로세서에서 Print:\n[accent]localeprint "timer"\nformat time\n[gray](여기서 시간은 별도로 계산된 변수)
+locales.deletelocale = 이 언어 팩을 삭제하시겠습니까?
+locales.applytoall = 모든 언어 팩에 변경 사항 적용
+locales.addtoother = 다른 언어 팩에 추가
+locales.rollback = 마지막으로 적용된 상태로 롤백
+locales.filter = 속성 필터
+locales.searchname = 이름 검색...
+locales.searchvalue = 값 검색...
+locales.searchlocale = 언어 팩 검색...
+locales.byname = 이름으로
+locales.byvalue = 값으로
+locales.showcorrect = 모든 언어 팩에 존재하고 모든 곳에서 고유한 값을 갖는 속성을 표시
+locales.showmissing = 일부 언어 팩에서 누락된 속성 표시
+locales.showsame = 다른 언어 팩에서 동일한 값을 갖는 속성 표시
+locales.viewproperty = 모든 언어 팩에서 보기
+locales.viewing = 속성 보기 "{0}"
+locales.addicon = 아이콘 추가
width = 너비:
height = 높이:
@@ -664,30 +678,32 @@ requirement.capture = {0} 점령
requirement.onplanet = {0} 구역을 제어
requirement.onsector = {0} 구역에 착륙
launch.text = 출격
-research.multiplayer = 캠페인 멀티 플레이 시에는 해당 캠페인 서버의 호스트만 연구할 수 있습니다.
map.multiplayer = 캠페인 멀티 플레이 시에는 해당 캠페인 서버의 호스트만 다른 구역을 보고, 이동이 가능합니다.
uncover = 지역 개방
configure = 초기자원 설정
+
objective.research.name = 연구
objective.produce.name = 획득
objective.item.name = 획득한 자원
objective.coreitem.name = 코어 자원
objective.buildcount.name = 건설 횟수
-objective.unitcount.name = 기체 횟수
-objective.destroyunits.name = 기체 처치
+objective.unitcount.name = 유닛 횟수
+objective.destroyunits.name = 유닛 처치
objective.timer.name = 타이머
objective.destroyblock.name = 단일 블록 파괴
objective.destroyblocks.name = 다수 블록 파괴
objective.destroycore.name = 코어 파괴
objective.commandmode.name = 명령 모드
objective.flag.name = 플래그
+
marker.shapetext.name = 도형과 문자
-marker.point.name = Point
+marker.point.name = 포인트
marker.shape.name = 도형
marker.text.name = 문자
-marker.line.name = Line
-marker.quad.name = Quad
-marker.texture.name = Texture
+marker.line.name = 라인
+marker.quad.name = 쿼드
+marker.texture.name = 텍스처
+
marker.background = 배경
marker.outline = 외곽선
@@ -698,14 +714,15 @@ objective.destroyblocks = [accent]파괴: [lightgray]{0}[white]/{1}\n{2}[lightgr
objective.item = [accent]획득: [][lightgray]{0}[]/{1}\n{2}[lightgray]{3}
objective.coreitem = [accent]코어로 운반:\n[][lightgray]{0}[]/{1}\n{2}[lightgray]{3}
objective.build = [accent]건설: [][lightgray]{0}[]개\n{1}[lightgray]{2}
-objective.buildunit = [accent]기체 생산: [][lightgray]{0}[]기\n{1}[lightgray]{2}
-objective.destroyunits = [accent]처치: [][lightgray]{0}[]기의 기체
+objective.buildunit = [accent]유닛 생산: [][lightgray]{0}[]기\n{1}[lightgray]{2}
+objective.destroyunits = [accent]처치: [][lightgray]{0}[]기의 유닛
objective.enemiesapproaching = [accent]적이 [lightgray]{0}[]초 후에 도착합니다
objective.enemyescelating = [accent]적의 생산량이 증가하고 있습니다[lightgray]{0}[]
-objective.enemyairunits = [accent]적의 공중 기체가 생산되고 있습니다[lightgray]{0}[]
+objective.enemyairunits = [accent]적의 공중 유닛이 생산되고 있습니다[lightgray]{0}[]
objective.destroycore = [accent]적의 코어를 파괴하세요
-objective.command = [accent]기체 조종
+objective.command = [accent]유닛 조종
objective.nuclearlaunch = [accent]⚠ 핵공격이 감지되었습니다: [lightgray]{0}
+
announce.nuclearstrike = [red]⚠ 핵 공습 감지 ⚠
loadout = 출격
@@ -734,12 +751,14 @@ error.mapnotfound = 맵 파일을 찾을 수 없습니다!
error.io = 네트워크 I/O 오류
error.any = 알 수 없는 네트워크 오류
error.bloom = 블룸 그래픽 효과를 적용하지 못했습니다.\n기기가 이 기능을 지원하지 않는 것일 수도 있습니다.
+error.moddex = Mindustry가 해당 모드를 로드할 수 없습니다.\n최근 Android의 변경으로 인해 기기에서 Java 모드 가져오기가 차단되었습니다.\n 아직 이 문제에 대한 알려진 해결 방법은 없습니다.
weather.rain.name = 비
weather.snowing.name = 눈
weather.sandstorm.name = 모래 폭풍
weather.sporestorm.name = 포자 폭풍
weather.fog.name = 안개
+
campaign.playtime = \uf129 [lightgray]지역 플레이타임: {0}
campaign.complete = [accent]축하드립니다.\n\n {0} 지역의 적이 패배하였습니다\n[lightgray] 마지막 지역을 점령하였습니다.
@@ -785,6 +804,12 @@ threat.high = 높음
threat.extreme = 매우 높음
threat.eradication = 극한
+difficulty.casual = 캐주얼
+difficulty.easy = 쉬움
+difficulty.normal = 보통
+difficulty.hard = 어려움
+difficulty.eradication = 극한
+
planets = 태양계
planet.serpulo.name = 세르플로
@@ -806,16 +831,26 @@ sector.fungalPass.name = 포자 지대
sector.biomassFacility.name = 유기물 합성 시설
sector.windsweptIslands.name = 폭풍의 격전지
sector.extractionOutpost.name = 자원 추출기지
+sector.facility32m.name = 32 M 시설
+sector.taintedWoods.name = 오염된 산림
+sector.infestedCanyons.name = 감염된 깊은 협곡
sector.planetaryTerminal.name = 대행성 출격단지
sector.coastline.name = 해안선
sector.navalFortress.name = 해군 요새
+sector.polarAerodrome.name = 극지 비행장
+sector.atolls.name = 환초
+sector.testingGrounds.name = 시험장
+sector.seaPort.name = 바다 항구
+sector.weatheredChannels.name = 풍화된 수로
+sector.mycelialBastion.name = 균사 요새
+sector.frontier.name = 국경 지방
sector.groundZero.description = 이 장소는 다시 시작하기에 최적의 환경을 지녔습니다. 적은 위협적이지 않지만, 자원도 풍부하진 않습니다.\n가능한 한 많은 양의 구리와 납을 수집하십시오.\n이제 출격할 시간입니다!
sector.frozenForest.description = 산과 가까운 이곳에도, 포자가 퍼졌습니다. 혹한의 추위조차 포자가 퍼지는 것을 억누를 수 없습니다.\n화력 발전기를 건설하고, 멘더를 사용하는 방법을 배워야 합니다.
sector.saltFlats.description = 사막의 변두리에는 소금으로 이루어진 평원이 있습니다. 이곳에선 매우 적은 자원만 발견되었습니다.\n\n하지만 자원이 희소한 이곳에서도 적들의 요새가 포착되었습니다. 그들을 사막의 모래로 만들어버리세요!
sector.craters.description = 물이 가득한 이 크레이터에는 옛 전쟁의 유물들이 쌓여있습니다.\n이곳을 탈환하여 강화 유리를 제련하고, 포탑과 드릴에 물을 공급하여 더 강력한 방어선을 구축하여야 합니다.
sector.ruinousShores.description = 폐허를 지나서 나오는 해안선. 한때, 이곳에는 해안 방어기지가 있었습니다.\n많은 부분이 소실되었습니다. 기본적인 방어 시설을 제외한 모든 것이 고철 덩어리가 되었습니다. \n외부로 세력을 확장하기 위한 첫 발걸음으로, 무너진 시설을 재건하고 잃어버린 기술을 다시 회수하십시오.
-sector.stainedMountains.description = 더 내륙에는 아직 포자에 오염되지 않은 산맥이 있습니다.\n이 지역에서 티타늄을 채굴하고 이것을 어떻게 사용하는지 배우십시오.\n\n이곳은 더 강력한 적이 주둔하고 있습니다. 적이 가장 강력한 기체를 준비할 시간을 주지 마십시오.
+sector.stainedMountains.description = 더 내륙에는 아직 포자에 오염되지 않은 산맥이 있습니다.\n이 지역에서 티타늄을 채굴하고 이것을 어떻게 사용하는지 배우십시오.\n\n이곳은 더 강력한 적이 주둔하고 있습니다. 적이 가장 강력한 유닛을 준비할 시간을 주지 마십시오.
sector.overgrowth.description = 이곳은 포자들의 근원과 가까이에 있는 과성장 지대입니다. 적이 이곳에 전초기지를 설립했습니다. 대거를 생산해 적의 기지를 박살 내고 우리가 잃어버린 것을 되찾아야 합니다!
sector.tarFields.description = 산지와 사막 사이에 있는 석유 생산지의 외곽이며, 사용 가능한 타르가 매장되어 있는 희귀한 지역 중 하나입니다. 버려진 지역이지만 이곳에는 위험한 적군이 있습니다. 그들을 과소평가하지 마십시오.\n\n[lightgray]석유 가공기술을 익히는 것이 도움이 될 것입니다.
sector.desolateRift.description = 극도로 위험한 지역입니다. 자원은 풍부하지만, 사용 가능한 공간은 거의 없습니다. 적의 공격 주기가 길지만, 기지가 파괴될 위험이 높으니 가능한 한 빨리 방어시설을 구축하여야 합니다.
@@ -826,8 +861,22 @@ sector.windsweptIslands.description = 육지에서 멀리 떨어진 이곳에는
sector.extractionOutpost.description = 적이 다른 지역에 자원을 보내기 위한 용도로 건설한 보급기지입니다.\n\n강력한 적들이 지키고 있는 지역을 공격하거나, 적에게 침공당한 지역을 효과적으로 수호하기 위해서는 우리도 이 수송 기술이 필요합니다. 적의 기지를 파괴하고, 그들의 수송 기술을 강탈하십시오.
sector.impact0078.description = 이곳에는 태양계에 처음 진입한 우주 수송선의 잔해가 존재합니다.\n\n우주선이 파괴된 잔해에서 최대한 많은 자원을 회수하고, 손상되지 않은 그들의 기술을 획득하십시오.
sector.planetaryTerminal.description = 이 행성에서의 마지막 전투를 준비하십시오.\n\n적이 필사의 각오로 지키고 있는 이 해안 기지엔 우주에 코어를 발사할 수 있는 시설이 있습니다.\n\n해군을 생산하여 적을 신속하게 제거하고, 그들의 행성간 이동 기술을 강탈하십시오.\n\n[royal] 건투를 빕니다.[]
-sector.coastline.description = 이 장소에서 해상 기체 기술의 잔재가 발견되었습니다. 적의 공격을 격퇴하고, 이 지역을 점령하고, 기술을 습득하십시오.
+sector.coastline.description = 이 장소에서 해상 유닛 기술의 잔재가 발견되었습니다. 적의 공격을 격퇴하고, 이 지역을 점령하고, 기술을 습득하십시오.
sector.navalFortress.description = 적은 자연적으로 요새화된 외딴 섬에 기지를 세웠습니다. 이 전초기지를 파괴하여 적의 발전된 함선 건조 기술을 습득하고 연구하십시오.
+sector.cruxscape.name = 크럭스케이프
+sector.geothermalStronghold.name = 지열 근거지
+
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
+
sector.onset.name = 시작
sector.aegis.name = 보호
sector.lake.name = 호수
@@ -845,22 +894,23 @@ sector.siege.name = 포위
sector.crossroads.name = 교차로
sector.karst.name = 카르스트
sector.origin.name = 근원
-sector.onset.description = 튜토리얼 지역. 아직 목표가 정해지지 않았습니다. 추가적인 정보를 제공받기 위해 잠시 대기해 주세요
-sector.aegis.description = 적은 방어막으로 보호받고 있습니다. 이 구역에서 실험적인 방어막 차단기 모듈이 감지되었습니다.\n이 구조물을 찾으. 텅스텐을 공급해 방어막 차단기를 가동하고 적의 기지를 파괴하여야 합니다.
-sector.lake.description = 이 지역의 광재 호수는 기체의 활동범위를 크게 제한시킵니다. 호버링 유닛만이 유일한 선택지입니다.\n[accent]함선 재구성기[]를 연구하고 [accent]일루드[]를 가능한 한 빨리 생산하여야 합니다.
-sector.intersect.description = 정찰 결과 이 지역은 착륙 직후 여러 방향에서 공격받을 것으로 예측됩니다.\n방어선을 빠르게 구축하고 가능한 한 빠르게 확장하여야 합니다.\n이 지역의 험난한 지형을 위해서는 [accent]기계[] 기체가 필요할 것입니다.
-sector.atlas.description = 이 지역은 각기 다른 지형을 포함하고 있으며, 효과적으로 공격하기 위해서는 다양한 기체가 필요합니다.\n이곳에서 발견된 더 강력한 적의 기지를 통과하기 위해서는 상위 등급의 기체가 필요할 수도 있습니다.\n[accent]전해조[]와 [accent]전차 재조립기[]를 연구하세요.
+
+sector.onset.description = 에르키아 정복을 시작하세요. 자원을 모으고, 유닛을 생산하고, 기술 연구를 시작하세요.
+sector.aegis.description = 이 구역에는 텅스텐 매장지가 있습니다.\n[accent]충격 드릴[]을 연구해 이 자원을 채굴하고 해당 지역의 적 기지를 파괴하세요.
+sector.lake.description = 이 지역의 광재 호수는 유닛의 활동 범위를 크게 제한시킵니다. 호버링 유닛만이 유일한 선택지입니다.\n[accent]함선 재구성기[]를 연구하고 [accent]일루드[]를 가능한 한 빨리 생산하여야 합니다.
+sector.intersect.description = 정찰 결과 이 지역은 착륙 직후 여러 방향에서 공격받을 것으로 예측됩니다.\n방어선을 빠르게 구축하고 가능한 한 빠르게 확장하여야 합니다.\n이 지역의 험난한 지형을 위해서는 [accent]기계[] 유닛이 필요할 것입니다.
+sector.atlas.description = 이 지역은 각기 다른 지형을 포함하고 있으며, 효과적으로 공격하기 위해서는 다양한 기체가 필요합니다.\n이곳에서 발견된 더 강력한 적의 기지를 통과하기 위해서는 상위 등급의 유닛이 필요할 수도 있습니다.\n[accent]전해조[]와 [accent]전차 재조립기[]를 연구하세요.
sector.split.description = 이 지역에 최소한으로 존재하는 적 주둔군은 새로운 운송 기술을 시험하기에 완벽합니다.
sector.basin.description = 이 지역에는 많은 수의 적이 확인되었습니다. 발판을 마련하기 위해 신속히 유닛을 생산하여 적의 기지를 무력화 해야 합니다.
sector.marsh.description = 이 지역은 아르키사이트가 풍부하지만 분출구의 수는 한정적입니다.\n[accent]화학적 연소실[]을 건설하여 전력을 생산하세요.
-sector.peaks.description = 이 지역의 산악 지형은 대부분의 기체를 무용지물로 만들었습니다. 비행 가능한 기체가 필요합니다.\n적의 방공망에 유의하십시오. 일부 시설은 지원 건물을 공격하여 무력화시킬 수 있습니다.
+sector.peaks.description = 이 지역의 산악 지형은 대부분의 유닛을 무용지물로 만들었습니다. 비행 가능한 유닛이 필요합니다.\n적의 방공망에 유의하십시오. 일부 시설은 지원 건물을 공격하여 무력화시킬 수 있습니다.
sector.ravine.description = 적의 중요한 이동 경로이긴 하지만, 해당 구역에선 적의 기지가 감지되지 않았습니다. 다양한 적군을 맞닥뜨릴 것으로 예상됩니다.\n[accent]설금[]을 생산하여 포탑 [accent]어플릭트[]를 건설하세요.
sector.caldera-erekir.description = 이 지역에서 탐지된 자원은 여러 섬에 분산되어 있습니다 .\n드론을 기반으로 한 운송수단을 연구하고 활용하세요.
-sector.stronghold.description = 이 지역의 대규모 적 야영지에는 적들이 지키고 있는 상당한 양의 [accent]토륨[] 매장지가 있습니다.\n더 높은 등급의 기체와 포탑을 연구할 때 사용합니다.
+sector.stronghold.description = 이 지역의 대규모 적 야영지에는 적들이 지키고 있는 상당한 양의 [accent]토륨[] 매장지가 있습니다.\n더 높은 등급의 유닛과 포탑을 연구할 때 사용합니다.
sector.crevice.description = 적들은 이 지역에서 당신의 기지를 제거하기 위해 맹렬한 공격부대를 보낼 것입니다.\n[accent]탄화물[]과 [accent]열분해 발전기[]를 연구하는 것은 살아남기 위해 반드시 필요합니다.
-sector.siege.description = 이 지역은 두 갈래의 공격을 강요하는 두 개의 평행 협곡이 특징입니다.\n더 강력한 전차 기체를 만들기 위한 능력을 얻기 위해 [accent]시아노겐[]을 연구하시오.\n주의: 적의 장거리 발사체가 감지되었습니다. 미사일은 충돌 전에 격추될 수 있습니다.
-sector.crossroads.description = 이 지역의 적 기지는 다양한 지형에 위차하고 있는 것이 확인 되었으며 이로 인해 위해 다양한 기체가 필요합니다. \n또한, 일부 기지는 보호막으로 보호되고 있습니다. 그들이 어떻게 전력을 공급받는지 알아보아야 합니다.
-sector.karst.description = 이 지역은 자원이 풍부하지만, 새로운 코어가 착륙하면 적에게 공격을 받을 것입니다.\n자원의 이점을 활용하고 [accent]메타[]를 연구하세요.
+sector.siege.description = 이 지역은 두 갈래의 공격을 강요하는 두 개의 평행 협곡이 특징입니다.\n더 강력한 전차 유닛을 만들기 위한 능력을 얻기 위해 [accent]시아노겐[]을 연구하시오.\n주의: 적의 장거리 발사체가 감지되었습니다. 미사일은 충돌 전에 격추될 수 있습니다.
+sector.crossroads.description = 이 지역의 적 기지는 다양한 지형에 위차하고 있는 것이 확인 되었으며 이로 인해 다양한 유닛이 필요합니다. \n또한, 일부 기지는 보호막으로 보호되고 있습니다. 그들이 어떻게 전력을 공급받는지 알아보아야 합니다.
+sector.karst.description = 이 지역은 자원이 풍부하지만, 새로운 코어가 착륙하면 적에게 공격을 받을 것입니다.\n자원의 이점을 활용하고 [accent]위상 섬유[]를 연구하세요.
sector.origin.description = 상당한 적이 존재하는 마지막 지역입니다.\n 모든 연구를 마쳤으니 오직 모든 적의 코어를 파괴하는 데만 집중하세요.
status.burning.name = 발화
@@ -890,7 +940,7 @@ settings.sound = 소리
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 = 연구 초기화
@@ -946,13 +996,13 @@ stat.repairspeed = 수리 속도
stat.weapons = 무기
stat.bullet = 탄환
stat.moduletier = 모듈 등급
-stat.unittype = Unit Type
+stat.unittype = 유닛 유형
stat.speedincrease = 속도 증가
stat.range = 사거리
stat.drilltier = 채굴 가능
stat.drillspeed = 기본 채굴 속도
stat.boosteffect = 버프 효과
-stat.maxunits = 최대 기체 수
+stat.maxunits = 최대 유닛 수
stat.health = 체력
stat.armor = 방어력
stat.buildtime = 건설 시간
@@ -983,7 +1033,7 @@ stat.abilities = 능력
stat.canboost = 이륙 가능
stat.flying = 비행
stat.ammouse = 탄약 사용
-stat.ammocapacity = Ammo Capacity
+stat.ammocapacity = 탄약 용량
stat.damagemultiplier = 피해량 배수
stat.healthmultiplier = 체력 배수
stat.speedmultiplier = 이동속도 배수
@@ -994,46 +1044,48 @@ stat.immunities = 상태이상 면역
stat.healing = 회복량
ability.forcefield = 보호막 필드
-ability.forcefield.description = Projects a force shield that absorbs bullets
+ability.forcefield.description = 탄약을 흡수하는 보호막을 만들어냄
ability.repairfield = 수리 필드
-ability.repairfield.description = Repairs nearby units
+ability.repairfield.description = 근처 유닛을 수리함
ability.statusfield = 상태이상 필드
-ability.statusfield.description = Applies a status effect to nearby units
+ability.statusfield.description = 근처 유닛에 상태 효과를 제공함
ability.unitspawn = 공장
-ability.unitspawn.description = Constructs units
+ability.unitspawn.description = 유닛을 생산함
ability.shieldregenfield = 방어막 복구 필드
-ability.shieldregenfield.description = Regenerates shields of nearby units
+ability.shieldregenfield.description = 근처 유닛의 방어막을 재생성함
ability.movelightning = 가속 전격
-ability.movelightning.description = Releases lightning while moving
-ability.armorplate = Armor Plate
-ability.armorplate.description = Reduces damage taken while shooting
-ability.shieldarc = 방어막 아크
-ability.shieldarc.description = Projects a force shield in an arc that absorbs bullets
+ability.movelightning.description = 이동하면서 번개를 방출함
+ability.armorplate = 장갑판
+ability.armorplate.description = 사격 시 받는 피해가 감소됨
+ability.shieldarc = 호 보호막
+ability.shieldarc.description = 탄약을 흡수하는 호 형태의 보호막을 만들어냄
ability.suppressionfield = 재생성 억제 필드
-ability.suppressionfield.description = Stops nearby repair buildings
+ability.suppressionfield.description = 근처 수리 건물을 잠깐동안 억제함
ability.energyfield = 에너지 필드
-ability.energyfield.description = Zaps nearby enemies
-ability.energyfield.healdescription = Zaps nearby enemies and heals allies
-ability.regen = Regeneration
-ability.regen.description = Regenerates own health over time
-ability.liquidregen = Liquid Absorption
-ability.liquidregen.description = Absorbs liquid to heal itself
-ability.spawndeath = Death Spawns
-ability.spawndeath.description = Releases units on death
-ability.liquidexplode = Death Spillage
-ability.liquidexplode.description = Spills liquid on death
-ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
-ability.stat.regen = [stat]{0}[lightgray] health/sec
-ability.stat.shield = [stat]{0}[lightgray] shield
-ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
-ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
-ability.stat.cooldown = [stat]{0} sec[lightgray] cooldown
-ability.stat.maxtargets = [stat]{0}[lightgray] max targets
-ability.stat.sametypehealmultiplier = [stat]{0}%[lightgray] same type repair amount
-ability.stat.damagereduction = [stat]{0}%[lightgray] damage reduction
-ability.stat.minspeed = [stat]{0} tiles/sec[lightgray] min speed
-ability.stat.duration = [stat]{0} sec[lightgray] duration
-ability.stat.buildtime = [stat]{0} sec[lightgray] build time
+ability.energyfield.description = 근처 적을 감전시킴
+ability.energyfield.healdescription = 근처 적에게 전기 충격을 주고 아군을 치료함
+ability.regen = 재생
+ability.regen.description = 시간이 지남에 따라 스스로 체력을 재생함
+ability.liquidregen = 액체 흡수
+ability.liquidregen.description = 액체를 흡수하여 스스로를 치유함
+ability.spawndeath = 스폰 죽음
+ability.spawndeath.description = 사망 시 유닛을 방출함
+ability.liquidexplode = 유출 죽음
+ability.liquidexplode.description = 사망 시 액체를 쏟음
+
+ability.stat.firingrate = [stat]{0}/초[lightgray] 발사 속도
+ability.stat.regen = [stat]{0}[lightgray] 체력/초
+ability.stat.pulseregen = [stat]{0}[lightgray] 체력/파동
+ability.stat.shield = [stat]{0}[lightgray] 실드
+ability.stat.repairspeed = [stat]{0}/초[lightgray] 수리 속도
+ability.stat.slurpheal = [stat]{0}[lightgray] 체력/액체 단위
+ability.stat.cooldown = [stat]{0} 초[lightgray] 쿨타임
+ability.stat.maxtargets = [stat]{0}[lightgray] 최대 목표
+ability.stat.sametypehealmultiplier = [stat]{0}%[lightgray] 동일 유형 회복량
+ability.stat.damagereduction = [stat]{0}%[lightgray] 피해 감소
+ability.stat.minspeed = [stat]{0} tiles/초[lightgray] 최소 속도
+ability.stat.duration = [stat]{0} 초[lightgray] 지속 시간
+ability.stat.buildtime = [stat]{0} 초[lightgray] 건설 시간
bar.onlycoredeposit = 코어에만 투입할 수 있습니다
bar.drilltierreq = 더 좋은 드릴 필요
@@ -1087,6 +1139,8 @@ bullet.healamount = [stat]{0}[lightgray] 직접 수리
bullet.multiplier = [stat]{0}[lightgray]배 탄약 배수[][]
bullet.reload = [stat]{0}%[lightgray] 발사 속도[][]
bullet.range = [stat]{0}[lightgray]블록 추가 범위
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = 블록
unit.blockssquared = 블록²
@@ -1119,8 +1173,8 @@ category.items = 자원
category.crafting = 입력/출력
category.function = 기능
category.optional = 선택적 향상
-setting.alwaysmusic.name = Always Play Music
-setting.alwaysmusic.description = When enabled, music will always play on loop in-game.\nWhen disabled, it only plays at random intervals.
+setting.alwaysmusic.name = 항상 음악 재생
+setting.alwaysmusic.description = 이 기능을 활성화하면, 게임 내에서 음악이 항상 반복 재생됩니다.\n비활성화하면, 무작위 간격으로만 재생됩니다.
setting.skipcoreanimation.name = 코어 발사/착륙 애니메이션 건너뛰기
setting.landscape.name = 가로화면 잠금
setting.shadows.name = 그림자
@@ -1132,7 +1186,7 @@ setting.backgroundpause.name = 백그라운드에서 일시정지
setting.buildautopause.name = 건설 자동 일시정지
setting.doubletapmine.name = 연속 터치로 채광
setting.commandmodehold.name = 키를 누른 상태로 명령
-setting.distinctcontrolgroups.name = Limit One Control Group Per Unit
+setting.distinctcontrolgroups.name = 유닛당 하나의 제어 그룹으로 제한
setting.modcrashdisable.name = 로딩 중 충돌 시 모드 비활성화
setting.animatedwater.name = 액체 애니메이션 효과
setting.animatedshields.name = 보호막 애니메이션 효과
@@ -1147,12 +1201,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI 스케일링
setting.uiscale.description = 적용하려면 재시작이 필요합니다.
setting.swapdiagonal.name = 항상 대각선 배치
-setting.difficulty.training = 훈련
-setting.difficulty.easy = 쉬움
-setting.difficulty.normal = 보통
-setting.difficulty.hard = 어려움
-setting.difficulty.insane = 박멸
-setting.difficulty.name = 난이도:
setting.screenshake.name = 화면 흔들림
setting.bloomintensity.name = 광원 세기
setting.bloomblur.name = 광원 번짐
@@ -1186,7 +1234,7 @@ setting.sfxvol.name = 효과음 크기
setting.mutesound.name = 소리 끄기
setting.crashreport.name = 익명으로 오류 보고서 자동 전송
setting.savecreate.name = 자동 저장 활성화
-setting.steampublichost.name = Public Game Visibility
+setting.steampublichost.name = 공개 게임 가시성
setting.playerlimit.name = 플레이어 제한
setting.chatopacity.name = 채팅창 투명도
setting.lasersopacity.name = 전선 투명도
@@ -1195,7 +1243,7 @@ setting.playerchat.name = 채팅 말풍선 표시
setting.showweather.name = 날씨 그래픽 표시
setting.hidedisplays.name = 로직 디스플레이 숨김
setting.macnotch.name = 노치를 표시하도록 인터페이스 조정
-setting.macnotch.description = 적용하려면 재시작이 필요합니다
+setting.macnotch.description = 적용하려면 재시작이 필요합니다.
steam.friendsonly = 친구 전용
steam.friendsonly.tooltip = 게임에 스팀 친구만 접속할 수 있는가에 대한 여부입니다.체크를 해제하면, 누구나 접속할 수 있습니다.
public.beta = 베타 버전의 게임은 공개 서버를 만들 수 없습니다.
@@ -1206,12 +1254,12 @@ keybind.title = 조작키 설정
keybinds.mobile = [scarlet]대부분의 조작키 설정은 모바일에서 작동하지 않습니다. 기본 이동만 지원됩니다.
category.general.name = 일반
category.view.name = 보기
-category.command.name = Unit Command
+category.command.name = 유닛 지휘
category.multiplayer.name = 멀티플레이어
category.blocks.name = 블록 선택
placement.blockselectkeys = \n[lightgray]단축키: [{0},
keybind.respawn.name = 리스폰
-keybind.control.name = 기체 제어
+keybind.control.name = 유닛 제어
keybind.clear_building.name = 설계도 초기화
keybind.press = 키를 누르세요...
keybind.press.axis = 마우스 휠 또는 키를 누르세요...
@@ -1224,14 +1272,16 @@ keybind.mouse_move.name = 커서를 따라서 이동
keybind.pan.name = 팬 보기
keybind.boost.name = 이륙
keybind.command_mode.name = 명령 모드
-keybind.command_queue.name = 유닛 명령 Queue
+keybind.command_queue.name = 유닛 명령 대기
keybind.create_control_group.name = 컨트롤 그룹 만들기
keybind.cancel_orders.name = 명령 취소
+
keybind.unit_stance_shoot.name = 유닛 명령: 사격
keybind.unit_stance_hold_fire.name = 유닛 명령: 사격 중지
keybind.unit_stance_pursue_target.name = 유닛 명령: 타겟 추격
keybind.unit_stance_patrol.name = 유닛 명령: 정찰
keybind.unit_stance_ram.name = 유닛 명령: 돌격
+
keybind.unit_command_move.name = 유닛 제어: 이동
keybind.unit_command_repair.name = 유닛 제어: 수리
keybind.unit_command_rebuild.name = 유닛 제어: 재건
@@ -1242,6 +1292,8 @@ keybind.unit_command_load_units.name = 유닛 제어: 유닛 적재
keybind.unit_command_load_blocks.name = 유닛 제어: 블록 적재
keybind.unit_command_unload_payload.name = 유닛 제어: 화물 투하
keybind.unit_command_enter_payload.name = 유닛 제어: 화물 건물에 착륙/진입
+keybind.unit_command_loop_payload.name = 유닛 제어: 유닛 반복 운반
+
keybind.rebuild_select.name = 지역 재건
keybind.schematic_select.name = 영역 설정
keybind.schematic_menu.name = 설계도 메뉴
@@ -1268,8 +1320,8 @@ keybind.select.name = 선택/공격
keybind.diagonal_placement.name = 대각선 설치
keybind.pick.name = 블록 선택
keybind.break_block.name = 블록 파괴
-keybind.select_all_units.name = 전체 기체 선택
-keybind.select_all_unit_factories.name = 전체 기체 공장 선택
+keybind.select_all_units.name = 전체 유닛 선택
+keybind.select_all_unit_factories.name = 전체 유닛 공장 선택
keybind.deselect.name = 선택해제
keybind.pickupCargo.name = 화물 집기
keybind.dropCargo.name = 화물 내려놓기
@@ -1292,7 +1344,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 = 생존
@@ -1305,26 +1357,30 @@ mode.pvp.description = 다른 플레이어와 현장에서 싸우세요.\n[gray]
mode.attack.name = 공격
mode.attack.description = 적의 기지를 파괴하세요.\n[gray]플레이하려면 맵에 적 코어가 필요합니다.
mode.custom = 사용자 정의 규칙
+
rules.invaliddata = 잘못된 클립보드 데이터 입니다.
rules.hidebannedblocks = 금지된 블록 숨기기
-
rules.infiniteresources = 무한 자원
rules.onlydepositcore = 오직 코어에만 투입 가능
-rules.derelictrepair = 잔해 블록 수리 허
+rules.derelictrepair = 잔해 블록 수리 허용
rules.reactorexplosions = 원자로 폭발 허용
rules.coreincinerates = 코어 방화 비허용
rules.disableworldprocessors = 월드 프로세서 비활성화
rules.schematic = 설계도 허용
rules.wavetimer = 시간 제한이 있는 단계
rules.wavesending = 단계 넘김
-rules.allowedit = Allow Editing Rules
-rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.allowedit = 규칙 편집 허용
+rules.allowedit.info = 이 기능을 활성화하면, 플레이어는 일시 정지 메뉴의 왼쪽 하단에 있는 버튼을 통해 게임 내에서 규칙을 편집할 수 있습니다.
+rules.alloweditworldprocessors = 월드 프로세서 편집 허용
+rules.alloweditworldprocessors.info = 이 기능을 활성화하면 편집기 외부에서도 월드 로직 블록을 배치하고 편집할 수 있습니다.
rules.waves = 단계
-rules.airUseSpawns = Air units use spawn points
+rules.airUseSpawns = 공중 유닛 스폰 지점 사용
rules.attack = 공격 모드
rules.buildai = 기지 건설 AI
rules.buildaitier = 건설 AI 등급
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS 공격 AI
+rules.rtsai.campaign.info = 공격 맵에서는 유닛을 그룹화하여 더욱 지능적인 방식으로 플레이어 기지를 공격합니다.
rules.rtsminsquadsize = 최소 부대 규모
rules.rtsmaxsquadsize = 최대 부대 규모
rules.rtsminattackweight = 최소 공격 중량
@@ -1335,15 +1391,15 @@ rules.placerangecheck = 배치 거리 확인
rules.enemyCheat = 적 AI 무한자원
rules.blockhealthmultiplier = 블록 체력 배수
rules.blockdamagemultiplier = 블록 피해량 배수
-rules.unitbuildspeedmultiplier = 기체 생산속도 배수
-rules.unitcostmultiplier = 기체 비용 배수
-rules.unithealthmultiplier = 기체 체력 배수
-rules.unitdamagemultiplier = 기체 피해량 배수
-rules.unitcrashdamagemultiplier = 기체 파손 피해량 배수
+rules.unitbuildspeedmultiplier = 유닛 생산속도 배수
+rules.unitcostmultiplier = 유닛 비용 배수
+rules.unithealthmultiplier = 유닛 체력 배수
+rules.unitdamagemultiplier = 유닛 피해량 배수
+rules.unitcrashdamagemultiplier = 유닛 파손 피해량 배수
rules.solarmultiplier = 태양광 전력 배수
-rules.unitcapvariable = 코어 기체수 제한 추가
-rules.unitpayloadsexplode = Carried Payloads Explode With The Unit
-rules.unitcap = 기본 기체 제한
+rules.unitcapvariable = 코어 유닛 수 제한 추가
+rules.unitpayloadsexplode = 들어올린 화물 유닛과 함께 폭발
+rules.unitcap = 기본 유닛 제한
rules.limitarea = 맵 영역 제한
rules.enemycorebuildradius = 적 코어 건설금지 범위:[lightgray] (타일)
rules.wavespacing = 단계 간격:[lightgray] (초)
@@ -1352,9 +1408,9 @@ rules.buildcostmultiplier = 건설 비용 배수
rules.buildspeedmultiplier = 건설 속도 배수
rules.deconstructrefundmultiplier = 철거 환불 배수
rules.waitForWaveToEnd = 한 단계가 끝날때까지 대기
-rules.wavelimit = Map Ends After Wave
+rules.wavelimit = 특정 단계 이후 맵 종료
rules.dropzoneradius = 스폰 구역 범위: [lightgray] (타일)
-rules.unitammo = 기체 탄약 필요
+rules.unitammo = 유닛 탄약 필요
rules.enemyteam = 적 팀
rules.playerteam = 플레이어 팀
rules.title.waves = 단계
@@ -1367,15 +1423,20 @@ rules.title.teams = 팀
rules.title.planet = 행성
rules.lighting = 조명 표시
rules.fog = 전장의 안개
+rules.invasions = 적 지역 침공
+rules.showspawns = 적 스폰 표시
+rules.randomwaveai = 무작위 단계 AI
rules.fire = 방화 허용
rules.anyenv = <모두>
-rules.explosions = 블록/기체 폭발 피해
+rules.explosions = 블록/유닛 폭발 피해
rules.ambientlight = 주변광
rules.weather = 날씨 추가
rules.weather.frequency = 빈도:
rules.weather.always = 항상
rules.weather.duration = 지속 시간:
-rules.placerangecheck.info = 플레이어가 적 건물 근처에 건설 불가 구역을 생성합니다. 만일, 플레이어가 포탑을 건설하고자 할 경우 반경이 증가되어 적 건물이 포탑의 사정거리에 닿지 않게됩니다.
+
+rules.randomwaveai.info = 단계에 생성된 유닛이 코어 또는 전력 생산기를 공격하는 대신 무작위 구조물을 공격하게 됩니다.
+rules.placerangecheck.info = 플레이어가 적 건물 근처에 건설 불가 구역을 생성합니다. 만일, 플레이어가 포탑을 건설하고자 할 경우 반경이 증가되어 적 건물이 포탑의 사정거리에 닿지 않게 됩니다.
rules.onlydepositcore.info = 코어를 제외한 어떠한 건물에도 자원을 투하할 수 없게 만듭니다.
content.item.name = 자원
@@ -1385,8 +1446,9 @@ content.block.name = 블록
content.status.name = 상태 이상
content.sector.name = 지역
content.team.name = 파벌
-wallore = (벽)
+wallore = (벽)
+#굳이 직역은 안해도 되기에 설금은 해당 명칭을 유지합니다
item.copper.name = 구리
item.lead.name = 납
item.coal.name = 석탄
@@ -1396,7 +1458,7 @@ item.thorium.name = 토륨
item.silicon.name = 실리콘
item.plastanium.name = 플라스터늄
item.phase-fabric.name = 위상 섬유
-item.surge-alloy.name = 서지 합금
+item.surge-alloy.name = 설금
item.spore-pod.name = 포자 꼬투리
item.sand.name = 모래
item.blast-compound.name = 폭발물
@@ -1460,6 +1522,7 @@ unit.scepter.name = 셉터
unit.reign.name = 레인
unit.vela.name = 벨라
unit.corvus.name = 코르버스
+
unit.stell.name = 스텔
unit.locus.name = 로커스
unit.precept.name = 프리셉트
@@ -1517,6 +1580,8 @@ block.graphite-press.name = 흑연 압축기
block.multi-press.name = 다중 압축기
block.constructing = {0} [lightgray](제작중)
block.spawn.name = 적 소환지점
+block.remove-wall.name = 벽 제거
+block.remove-ore.name = 광석 제거
block.core-shard.name = 코어: 조각
block.core-foundation.name = 코어: 기반
block.core-nucleus.name = 코어: 핵심
@@ -1596,12 +1661,12 @@ block.inverted-sorter.name = 반전 필터
block.message.name = 메모 블록
block.reinforced-message.name = 보강된 메모 블록
block.world-message.name = 월드 메모 블록
-block.world-switch.name = World Switch
+block.world-switch.name = 월드 스위치
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 = 융해기
@@ -1611,7 +1676,7 @@ block.separator.name = 광재 분리기
block.coal-centrifuge.name = 석탄 정제기
block.power-node.name = 전력 노드
block.power-node-large.name = 대형 전력 노드
-block.surge-tower.name = 서지 타워
+block.surge-tower.name = 설금 타워
block.diode.name = 다이오드
block.battery.name = 배터리
block.battery-large.name = 대형 배터리
@@ -1630,7 +1695,7 @@ block.item-source.name = 자원 공급기
block.item-void.name = 자원 소멸기
block.liquid-source.name = 액체 공급기
block.liquid-void.name = 액체 소멸기
-block.power-void.name = 방전장치
+block.power-void.name = 전력 소멸기
block.power-source.name = 전력 공급기
block.unloader.name = 언로더
block.vault.name = 창고
@@ -1663,11 +1728,11 @@ block.mass-driver.name = 매스 드라이버
block.blast-drill.name = 압축 공기분사 드릴
block.impulse-pump.name = 충격 펌프
block.thermal-generator.name = 지열 발전기
-block.surge-smelter.name = 서지 제련소
+block.surge-smelter.name = 설금 제련소
block.mender.name = 멘더
block.mend-projector.name = 수리 프로젝터
-block.surge-wall.name = 서지 벽
-block.surge-wall-large.name = 큰 서지 벽
+block.surge-wall.name = 설금 벽
+block.surge-wall-large.name = 대형 설금 벽
block.cyclone.name = 사이클론
block.fuse.name = 퓨즈
block.shock-mine.name = 전격 지뢰
@@ -1684,10 +1749,10 @@ block.segment.name = 세그먼트
block.ground-factory.name = 지상 공장
block.air-factory.name = 항공 공장
block.naval-factory.name = 해양 공장
-block.additive-reconstructor.name = 덧셈식 재구성기
-block.multiplicative-reconstructor.name = 곱셈식 재구성기
-block.exponential-reconstructor.name = 거듭제곱식 재구성기
-block.tetrative-reconstructor.name = 테트레이션식 재구성기
+block.additive-reconstructor.name = 재구성기: Additive
+block.multiplicative-reconstructor.name = 재구성기: Multiplicative
+block.exponential-reconstructor.name = 재구성기: Exponential
+block.tetrative-reconstructor.name = 재구성기: Tetrative
block.payload-conveyor.name = 화물 컨베이어
block.payload-router.name = 화물 분배기
block.duct.name = 도관
@@ -1712,6 +1777,8 @@ block.payload-unloader.name = 화물 언로더
block.payload-unloader.description = 들어간 블록에서 액체와 아이템을 가져옵니다.
block.heat-source.name = 열 공급기
block.heat-source.description = 엄청난 양의 열을 출력합니다. 샌드박스 전용.
+
+#Erekir
block.empty.name = 공백
block.rhyolite-crater.name = 유문암 구덩이
block.rough-rhyolite.name = 거친 유문암
@@ -1774,11 +1841,12 @@ block.electric-heater.name = 전기 가열기
block.slag-heater.name = 광재 가열기
block.phase-heater.name = 위상 가열기
block.heat-redirector.name = 열 전송기
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = 열 분배기
block.slag-incinerator.name = 광재 소각로
block.carbide-crucible.name = 탄화물 도가니
block.slag-centrifuge.name = 광재 원심분리기
-block.surge-crucible.name = 서지 도가니
+block.surge-crucible.name = 설금 도가니
block.cyanogen-synthesizer.name = 시아노겐 합성기
block.phase-synthesizer.name = 위상 합성기
block.heat-reactor.name = 열 반응로
@@ -1789,8 +1857,8 @@ block.tungsten-wall-large.name = 대형 텅스텐 벽
block.blast-door.name = 방폭문
block.carbide-wall.name = 탄화물 벽
block.carbide-wall-large.name = 대형 탄화물 벽
-block.reinforced-surge-wall.name = 보강된 서지 벽
-block.reinforced-surge-wall-large.name = 보강된 대형 서지 벽
+block.reinforced-surge-wall.name = 보강된 설금 벽
+block.reinforced-surge-wall-large.name = 보강된 대형 설금 벽
block.shielded-wall.name = 보호된 벽
block.radar.name = 레이더
block.build-tower.name = 건설 타워
@@ -1802,10 +1870,10 @@ block.armored-duct.name = 장갑 도관
block.overflow-duct.name = 포화 도관
block.underflow-duct.name = 불포화 도관
block.duct-unloader.name = 언로더 도관
-block.surge-conveyor.name = 서지 컨베이어
-block.surge-router.name = 서지 분배기
-block.unit-cargo-loader.name = 기체 화물 적재소
-block.unit-cargo-unload-point.name = 기체 화물 하역지점
+block.surge-conveyor.name = 설금 컨베이어
+block.surge-router.name = 설금 분배기
+block.unit-cargo-loader.name = 유닛 화물 적재소
+block.unit-cargo-unload-point.name = 유닛 화물 하역지점
block.reinforced-pump.name = 보강된 펌프
block.reinforced-conduit.name = 보강된 파이프
block.reinforced-liquid-junction.name = 보강된 액체 교차기
@@ -1821,6 +1889,7 @@ block.chemical-combustion-chamber.name = 화학적 연소실
block.pyrolysis-generator.name = 열분해 발전기
block.vent-condenser.name = 분출구 응결기
block.cliff-crusher.name = 벽 분쇄기
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = 플라즈마 채광기
block.large-plasma-bore.name = 대형 플라즈마 채광기
block.impact-drill.name = 충격 드릴
@@ -1854,7 +1923,7 @@ block.tank-fabricator.name = 전차 조립기
block.mech-fabricator.name = 기계 조립기
block.ship-fabricator.name = 함선 조립기
block.prime-refabricator.name = 상급 조립기
-block.unit-repair-tower.name = 기체 수리 타워
+block.unit-repair-tower.name = 유닛 수리 타워
block.diffuse.name = 디퓨즈
block.basic-assembler-module.name = 기본 조립 모듈
block.smite.name = 스마이트
@@ -1870,6 +1939,7 @@ block.logic-display.name = 로직 디스플레이
block.large-logic-display.name = 대형 로직 디스플레이
block.memory-cell.name = 메모리 셀
block.memory-bank.name = 메모리 보관소
+
team.malis.name = 말리스
team.crux.name = 크럭스
team.sharded.name = 샤디드
@@ -1881,20 +1951,20 @@ hint.skip = 넘기기
hint.desktopMove = [accent][[WASD][] 키를 이용해 움직이십시오.
hint.zoom = [accent]스크롤[]을 통해 화면 확대/축소가 가능합니다.
hint.desktopShoot = [accent][[좌클릭][]으로 발사할 수 있습니다.
-hint.depositItems = 자원을 코어로 옮기려면, 기체의 자원을 코어로 끌어다놓으십시오.
-hint.respawn = 기체를 떠나려면 [accent][[V][]를 누르십시오.
-hint.respawn.mobile = 기체 혹은 포탑을 조종할 수 있습니다. 기체를 떠나려면 [accent]왼쪽 위의 아바타를 누르십시오.[]
+hint.depositItems = 자원을 코어로 옮기려면, 유닛의 자원을 코어로 끌어다놓으십시오.
+hint.respawn = 유닛을 떠나려면 [accent][[V][]를 누르십시오.
+hint.respawn.mobile = 유닛 혹은 포탑을 조종할 수 있습니다. 유닛을 떠나려면 [accent]왼쪽 위의 아바타를 누르십시오.[]
hint.desktopPause = 게임을 일시 정지/재개하기 위해 [accent][[Space][]를 누르십시오.
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 = 새 기술을 연구하려면 \ue88c [accent]메뉴[] 아래의 \ue875 [accent]연구[]버튼을 누르십시오.
-hint.unitControl = 아군 기체와 포탑을 조종하려면 [accent][[왼쪽 ctrl][]을 누른 채로 [accent]클릭[] 하십시오.
-hint.unitControl.mobile = 아군 기체와 포탑을 조종하려면 해당 개체를 [accent]빠르게 두 번 누르십시오[].
-hint.unitSelectControl = 기체를 조종하려면, [accent]왼쪽 shift[]를 눌러 [accent]명령 모드[]를 활성화하시오.\n명령 모드가 활성화되어 있을 때 누르거나 끌어서 기체를 선택합니다. [accent]우클릭[]으로 기체에게 이동과 공격을 명령할 수 있습니다.
-hint.unitSelectControl.mobile = 기체를 조종하려면, 왼쪽 아래에 있는 [accent]명령[]을 눌러 [accent]명령 모드[]를 활성화하시오.\n명령 모드가 활성화되어 있을 때 길게 누르거나 끌어서 기체를 선택합니다. 눌러서 기체에게 이동과 공격을 명령할 수 있습니다.
+hint.unitControl = 아군 유닛과 포탑을 조종하려면 [accent][[왼쪽 ctrl][]을 누른 채로 해당 개체를[accent]클릭[] 하십시오.
+hint.unitControl.mobile = 아군 유닛과 포탑을 조종하려면 해당 개체를 [accent]빠르게 두 번 누르십시오[].
+hint.unitSelectControl = 유닛을 조종하려면, [accent]왼쪽 shift[]를 눌러 [accent]명령 모드[]를 활성화하시오.\n명령 모드가 활성화되어 있을 때 누르거나 끌어서 유닛을 선택합니다. [accent]우클릭[]으로 유닛에게 이동과 공격을 명령할 수 있습니다.
+hint.unitSelectControl.mobile = 유닛을 조종하려면, 왼쪽 아래에 있는 [accent]명령[]을 눌러 [accent]명령 모드[]를 활성화하시오.\n명령 모드가 활성화되어 있을 때 길게 누르거나 끌어서 유닛을 선택합니다. 눌러서 유닛에게 이동과 공격을 명령할 수 있습니다.
hint.launch = 충분한 자원을 모았으면, 오른쪽 아래의 \ue827 [accent]지도[]에서 주변 지역을 선택해서 [accent]출격[]할 수 있습니다.
hint.launch.mobile = 충분한 자원을 모았으면, 오른쪽 아래의 \ue88c [accent]메뉴[]에 있는 \ue827 [accent]지도[]에서 주변 지역을 선택해서 [accent]출격[]할 수 있습니다.
hint.schematicSelect = [accent][[F][]를 누른 채로 끌어서 복사하고 붙여넣을 블록을 선택하십시오. \n\n [accent][[마우스 휠][]을 누르면 한 개의 블록만 복사할 수 있습니다.
@@ -1902,55 +1972,57 @@ hint.rebuildSelect = [accent][[B][]를 누르고 끌어서 파괴된 블록 흔
hint.rebuildSelect.mobile = 복사버튼 \ue874 을 선택하시고, 재건축 버튼 \ue80f 을 탭 하신 뒤, 드래그 하여 블록 흔적을 선택하세요. 선택된 블록은 자동으로 복구됩니다.
hint.conveyorPathfind = [accent][[왼쪽 Ctrl][]을 누른 채로 컨베이어를 대각선으로 끌면 길을 자동으로 만들어줍니다.
hint.conveyorPathfind.mobile = \ue844 [accent]대각 모드[]를 활성화하고 컨베이어를 대각선으로 끌면 길을 자동으로 찾아줍니다.
-hint.boost = [accent][[왼쪽 Shift][]를 눌러 탑승한 기체로 장애물을 넘을 수 있습니다. \n\n 일부 지상 기체만 이륙할 수 있습니다.
-hint.payloadPickup = 작은 블록이나 기체를 집으려면 [accent][[[]를 누르십시오.
-hint.payloadPickup.mobile = 작은 블록이나 기체를 집으려면 [accent]잠깐 누르십시오[].
+hint.boost = [accent][[왼쪽 Shift][]를 눌러 탑승한 기체로 장애물을 넘을 수 있습니다. \n\n 일부 지상 유닛만 이륙할 수 있습니다.
+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]수호자[] 기체는 방어력이 존재합니다. [accent]구리[]와 [accent]납[]처럼 약한 탄약으로는 [scarlet]아무런 효과도 없습니다[].\n\n수호자를 제거하려면 높은 단계의 포탑 또는 \uf835 [accent]흑연[]을 탄약으로 넣은 \uf861듀오/\uf859살보를 사용하십시오.
+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.presetDifficulty = 이 지역은 [scarlet]위험도가 높은[] 지역입니다.\n적절한 기술과 준비 없이 이런 지역들로 출격하는건 [accent]추천하지 않습니다[].
hint.coreIncinerate = 코어가 자원으로 가득 찬 후에 받는 모든 자원들은 [accent]소각[]될 것입니다.
-hint.factoryControl = 기체 공장의 [accent]출력 목적지[]를 설정하려면, 명령 모드에서 공장 블록을 클릭한 다음, 마우스 오른쪽 버튼으로 위치를 지정합니다.\n생산된 유닛은 자동으로 그곳으로 이동합니다.
-hint.factoryControl.mobile = 기체 공장의 [accent]출력 목적지[]를 설정하려면, 명령 모드에서 공장 블록을 클릭한 다음, 눌러서 위치를 지정합니다.\n생산된 유닛은 자동으로 그곳으로 이동합니다.
-gz.mine = 주변 바닥에 있는 \uf8c4 [accent]구리 광석[]으로 이동하고, 광석을 눌러서 채굴을 시작하세요.
-gz.mine.mobile = 주변 바닥에 있는 \uf8c4 [accent]구리 광석[]으로 이동하고, 광석을 눌러서 채굴을 시작하세요.
-gz.research = \ue875 연구 기록을 여세요.\n\uf870 [accent]기계식 드릴[]을 연구하고, 그 후 오른쪽 아래에 있는 메뉴에서 선택하세요.\n구리조각 위를 눌러서 배치합니다.
-gz.research.mobile = \ue875 연구 기록을 여세요.\n\uf870 [accent]기계식 드릴[]을 연구하고, 그 후 오른쪽 아래에 있는 메뉴에서 선택하세요.\n구리조각 위를 눌러서 배치합니다.\n\n오른쪽 아래에서 \ue800 [accent]체크마크[]를 눌러 확정지으세요.
-gz.conveyors = \uf896 [accent]컨베이어[]를 연구하고 배치하여 채굴된 자원을 운반하세요.\n드릴에서 코어로 말이죠.\n\n클릭하고 끌어서 컨베이어를 길게 배치하세요.\n[accent]스크롤[]해서 방향을 회전할 수 있습니다.
-gz.conveyors.mobile = \uf896 [accent]컨베이어[]를 연구하고 배치하여 채굴된 자원을 운반하세요.\n드릴에서 코어로 말이죠.\n\n손가락을 길게 누르고 끌어서 컨베이어를 길게 배치하세요.
-gz.drills = 채굴 작업을 확장하세요.\n기계식 드릴을 더 배치하세요.\n구리 100개 채굴하기.
-gz.lead = \uf837 [accent]납[]은 일반적으로 사용되는 또 다른 자원입니다.\n납을 채굴하기 위한 드릴을 설치하세요.
+hint.factoryControl = 유닛 공장의 [accent]출력 목적지[]를 설정하려면, 명령 모드에서 공장 블록을 클릭한 다음, 마우스 오른쪽 버튼으로 위치를 지정합니다.\n생산된 유닛은 자동으로 그곳으로 이동합니다.
+hint.factoryControl.mobile = 유닛 공장의 [accent]출력 목적지[]를 설정하려면, 명령 모드에서 공장 블록을 클릭한 다음, 눌러서 위치를 지정합니다.\n생산된 유닛은 자동으로 그곳으로 이동합니다.
+
+gz.mine = 주변 땅에 있는 \uf8c4 [accent]구리 광석[]으로 이동하고, 광석을 클릭해서 채굴을 시작하세요.
+gz.mine.mobile = 주변 땅에 있는 \uf8c4 [accent]구리 광석[]으로 이동하고, 광석을 눌러서 채굴을 시작하세요.
+gz.research = 오른쪽 하단에 \ue875 연구 기록을 클릭하거나 [J]키를 눌러 여세요.\n\uf870 [accent]기계식 드릴[]을 연구하고, 그 후 연구 기록을 닫아서 오른쪽 아래에 있는 메뉴에서 해당 드릴을 선택하세요.\n구리 광석 위에 클릭해서 배치합니다.\n(만약 바로 건설되는게 불편하다면, 설정에서 건설 자동 일시정지를 킬 수 있습니다.)[]
+gz.research.mobile = 왼쪽 상단에 \ue875 연구 기록을 눌러 여세요.\n\uf870 [accent]기계식 드릴[]을 연구하고, 그 후 연구 메뉴를 닫아서 오른쪽 아래에 있는 블록 메뉴에서 해당 드릴을 선택하세요.\n구리 광석 위에 눌러서 배치합니다.\n\n오른쪽 아래 \ue800 [accent]체크마크[]를 눌러 확정지으세요.
+gz.conveyors = \uf896 이제 연구 기록을 다시 열어 [accent]컨베이어[]를 연구하고 배치하여 채굴된 자원을 운반하세요.\n드릴에서 코어로 말이죠.\n\n컨베이어를 선택하고, 클릭하고 드래그해서 컨베이어를 길게 배치하세요.\n[accent]스크롤[]로 방향을 회전할 수 있습니다.\n자원이 부족하면 연구나 건설이 불가능해지니 참고해주세요.
+gz.conveyors.mobile = \uf896 이제 연구 기록을 다시 열어 [accent]컨베이어[]를 연구하고 배치하여 채굴된 자원을 운반하세요.\n드릴에서 코어로 말이죠.\n\n손가락을 길게 누르고 끌어서 컨베이어를 길게 배치하세요.\n자원이 부족하면 연구나 건설이 불가능해지니 참고해주세요.
+gz.drills = 채굴 작업을 확장하세요.\n기계식 드릴을 더 배치하세요.\n[accent]새 목표:[] 드릴로 구리를 채굴하고 컨베이어를 이용해 [accent]구리 100개[]를 코어로 운반하기.
+gz.lead = \uf837 [accent]납[]은 일반적으로 사용되는 또 다른 자원입니다.\n납을 채굴하기 위한 드릴을 건설하세요.
gz.moveup = \ue804 추가 목표를 위해 위로 이동하세요.
-gz.turrets = 코어를 보호하기 위해 \uf861 [accent]듀오[] 포탑을 연구하고 2개를 설치하세요.\n듀오 포탑은 컨베이어로부터 \uf838 [accent]탄약[]을 공급받아야 합니다.
+gz.turrets = 이 게임의 핵심인 '코어'를 보호하기 위해 \uf861 [accent]듀오[] 포탑을 연구하고 2개를 설치하세요.\n듀오 포탑은 컨베이어로부터 \uf838 [accent]탄약[]을 공급받아야 합니다.
gz.duoammo = 컨베이어를 활용하여, 듀오 포탑에 [accent]구리[]를 공급하세요.
gz.walls = [accent]벽[]은 건물로 날아오는 공격을 막을 수 있습니다. \n포탑 주변에 \uf8ae [accent]구리 벽[]을 배치하세요.
gz.defend = 적이 다가옵니다, 방어 태세를 갖추세요.
-gz.aa = 비행 기체는 기본 포탑으로는 쉽게 처리할 수 없습니다.\n\uf860 [accent]스캐터[] 포탑은 훌륭한 대공 방어를 자랑하지만, 탄환으로 \uf837 [accent]납[]이 필요합니다.
-gz.scatterammo = 컨베이어를 활용하여,스캐터 포탑에 [accent]납[]을 공급하세요.
+gz.aa = 비행 유닛은 기본 포탑으로는 쉽게 처리할 수 없습니다.\n\uf860 [accent]스캐터[] 포탑은 훌륭한 대공 방어를 자랑하지만, 탄환으로 \uf837 [accent]납[]이 필요합니다.
+gz.scatterammo = 컨베이어를 활용하여, 스캐터 포탑에 [accent]납[]을 공급하세요.
gz.supplyturret = [accent]보급 포탑
gz.zone1 = 이건 적의 착륙 지점입니다.
gz.zone2 = 반경에 세워진 모든 것은 단계가 시작되면 파괴됩니다.
gz.zone3 = 단계가 지금 시작됩니다.\n준비하세요.
-gz.finish = 포탑을 더 건설하고, 자원을 더 채굴하고,\n그리고 모든 단계를 막아내어 [accent]지역을 점령[]하세요.
-onset.mine = 벽에 붙어있는 \uf748 [accent]베릴륨[]을 클릭하여 채굴하세요.\n\n[accent][[WASD]로 움직이세요.
+gz.finish = 포탑을 더 건설하고, 자원을 더 채굴하고,\n그리고 모든 단계를 막아내어 [accent]지역을 점령[]하세요. 이것으로 튜토리얼을 마칩니다. 행운을 빕니다.
+
+onset.mine = 벽에 붙어있는 \uf748 [accent]베릴륨[]을 클릭하여 채굴하세요.\n\n[accent][WASD]로 움직이세요.
onset.mine.mobile = 벽에 붙어있는 \uf748 [accent]베릴륨[]을 눌러서 채굴하세요.
-onset.research = \ue875 연구 기록을 여세요.\n \uf73e [accent]터빈 응결기[]를 연구하고, 구덩이 위에 배치하세요.\n[accent]전력[]을 생산합니다.
-onset.bore = \uf741 [accent]플라즈마 채광기[]를 연구하고 배치하세요.\n벽으로부터 자동으로 자원을 채굴합니다.
+onset.research = \ue875 연구 기록을 여세요.\n \uf73e [accent]터빈 응결기[]를 연구하고, 연구 기록을 다시 닫은 다음, 구덩이 위에 배치하세요.\n[accent]전력[]을 생산합니다.
+onset.bore = 다시 연구 기록을 열어 \uf741 [accent]플라즈마 채광기[]를 연구하고 배치하세요.\n벽으로부터 자동으로 자원을 채굴합니다.
onset.power = [accent]전력[]을 플라즈마 채광기로 전달하기 위해선, \uf73d [accent]빔 노드[]를 연구하고 배치하세요.\n터빈 응결기와 플라즈마 채광기를 연결하세요.
onset.ducts = \uf799 [accent]도관[]을 연구하고 배치하여 플라즈마 채광기에서 채굴한 자원을 코어로 운반하세요.\n클릭하고 끌어서 도관을 길게 연결하세요.\n[accent]스크롤해서[]해서 방향을 회전할 수 있습니다.
onset.ducts.mobile = \uf799 [accent]도관[]을 연구하고 배치하여 플라즈마 채광기에서 채굴한 자원을 코어로 운반하세요.\n손가락을 길게 누르고 끌어서 도관을 길게 연결하세요.
-onset.moremine = 채굴 작업을 확장하세요.\n더 많은 플라즈마 채광기를 배치하고 빔 노드와 덕트를 사용하여 보조하세요.\n베릴륨 200개 채굴하기.
+onset.moremine = 채굴 작업을 확장하세요.\n더 많은 플라즈마 채광기를 배치하고 빔 노드와 도관을 사용하여 보조하세요.\n베릴륨 200개 채굴하기.
onset.graphite = 더 복잡한 건물은 \uf835 [accent]흑연[]이 필요합니다.\n흑연을 채굴하는 플라즈마 채광기를 배치하세요.
onset.research2 = [accent]공장[]을 연구할 시간입니다.\n \uf74d [accent]벽 분쇄기[]와 \uf779 [accent]실리콘 아크 화로[]를 연구하세요.
onset.arcfurnace = 아크 화로는 \uf834 [accent]모래[]와 \uf835 [accent]흑연[]을 가공하여 \uf82f [accent]실리콘[]을 생산합니다.\n[accent]전력[] 또한 필수입니다.
onset.crusher = \uf74d [accent]벽 분쇄기[]를 사용하여 모래를 채굴하세요.
-onset.fabricator = [accent]기체[]는 지도를 정찰하거나, 건물을 보호하거나, 적을 공격할 때 활용할 수 있습니다. \uf6a2 [accent]전차 재조립기[]를 연구하고 배치하세요.
-onset.makeunit = 기체를 생산하세요.\n"?" 버튼을 눌러 선택한 공장의 요구사항을 확인할 수 있습니다.
-onset.turrets = 기체는 유용하지만, [accent]포탑[]은 사용하기에 따라 더 나은 방어 성능을 보여줍니다.\n \uf6eb [accent]브리치[] 포탑을 배치하세요.\n포탑은 \uf748 [accent]탄약[]이 필요합니다.
+onset.fabricator = [accent]유닛[]은 맵을 정찰하거나, 건물을 보호하거나, 적을 공격할 때 활용할 수 있습니다. \uf6a2 [accent]전차 재조립기[]를 연구하고 배치하세요.
+onset.makeunit = 유닛을 생산하세요.\n"?" 버튼을 눌러 선택한 공장의 요구사항을 확인할 수 있습니다.
+onset.turrets = 유닛은 유용하지만, [accent]포탑[]은 사용하기에 따라 더 나은 방어 성능을 보여줍니다.\n \uf6eb [accent]브리치[] 포탑을 배치하세요.\n포탑은 \uf748 [accent]탄약[]이 필요합니다.
onset.turretammo = 포탑에 [accent]베릴륨 탄약[]을 공급하세요.
onset.walls = [accent]벽[]은 건물로 날아오는 공격을 막을 수 있습니다. \n포탑 주변에 \uf6ee [accent]베릴륨 벽[]을 배치하세요.
onset.enemies = 적이 다가옵니다, 방어 태세를 갖추세요.
@@ -1958,14 +2030,15 @@ onset.defenses = [accent]방어 태세 갖추기:[lightgray] {0}
onset.attack = 적은 취약한 상태입니다. 반격하세요.
onset.cores = 새로운 코어는 [accent]코어 타일[]위에 배치할 수 있습니다.\n새로운 코어는 전진기지 역할을 하며 다른 코어와 저장된 자원을 공유합니다.\n \uf725 코어를 배치하세요.
onset.detect = 적은 2분 이내에 당신을 탐지할 것입니다.\n생산, 채굴, 방어시설을 구성하세요.
-onset.commandmode = [accent]shift[]를 눌러 [accent]명령 모드[]를 활성화하세요.\n[accent]좌클릭과 드래그[]로 기체를 선택하세요.\n[accent]우클릭[]으로 선택된 기체들에게 이동 또는 공격 명령을 내리세요.
-onset.commandmode.mobile = [accent]명령 버튼[]을 눌러 [accent]명령 모드[]를 활성화하세요.\n손가락을 꾹 누르고, [accent]드래그[]해서 유닛을 선택하세요.\n[accent]눌러서[] 선택된 기체들에게 이동 또는 공격 명령을 내리세요.
-aegis.tungsten = 텅스텐을 채굴하려면 [accent]충격드릴[]이 필요합니다.\n 충격 드릴은[accent]물[]과 [accent]전력[]을 필요로 합니다.
-split.pickup = 일부 블록은 코어 기체로 집어올릴 수 있습니다.\n이 [accent]컨테이너[]를 집어올리고 [accent]화물 로더[] 속에 내려놓으세요.\n(화물을 집어올리거나 내리는 기본 키는 [ 그리고 ]입니다)
-split.pickup.mobile = 일부 블록은 코어 기체로 집어올릴 수 있습니다.\n이 [accent]컨테이너[]를 집어올리고 [accent]화물 로더[] 속에 내려놓으세요.\n(무언가를 집어올리거나 내려놓으려면, 길게 누르세요.)
-split.acquire = 기체를 제조하려면 텅스텐을 채굴해야 합니다.
-split.build = 기체를 벽의 반대편으로 운반해야 합니다.\n두 개의 [accent]회물 매스 드라이버[]를 각 벽면에 하나씩 배치하세요.\n둘 중 하나를 누른 다음 다른 하나를 선택하여 연결을 설정합니다.
-split.container = 컨테이너와 마찬가지로, 기체도 [accent]화물 매스 드라이버[]를 사용하여 운송할 수 있습니다.\n기체 조립대를 매스 드라이버 근처에 배치하여 기체를 적재한 후, 벽을 가로질러 보내 적 기지를 공격합니다.
+onset.commandmode = [accent]shift[]를 눌러 [accent]명령 모드[]를 활성화하세요.\n[accent]좌클릭과 드래그[]로 유닛을 선택하세요.\n[accent]우클릭[]으로 선택된 유닛들에게 이동 또는 공격 명령을 내리세요.
+onset.commandmode.mobile = [accent]명령 버튼[]을 눌러 [accent]명령 모드[]를 활성화하세요.\n손가락을 꾹 누르고, [accent]드래그[]해서 유닛을 선택하세요.\n[accent]눌러서[] 선택된 유닛들에게 이동 또는 공격 명령을 내리세요. 이것으로 에르키아의 튜토리얼을 마칩니다. 행운을 빕니다.
+aegis.tungsten = 텅스텐을 채굴하려면 [accent]충격 드릴[]이 필요합니다.\n 충격 드릴은[accent]물[]과 [accent]전력[]을 필요로 합니다.
+
+split.pickup = 일부 블록은 코어 유닛으로 집어올릴 수 있습니다.\n이 [accent]컨테이너[]를 집어올리고 [accent]화물 로더[] 속에 내려놓으세요.\n(화물을 집어올리거나 내리는 기본 키는 [ 그리고 ]입니다.)
+split.pickup.mobile = 일부 블록은 코어 유닛으로 집어올릴 수 있습니다.\n이 [accent]컨테이너[]를 집어올리고 [accent]화물 로더[] 속에 내려놓으세요.\n(무언가를 집어올리거나 내려놓으려면, 길게 누르세요.)
+split.acquire = 유닛을 생산하려면 텅스텐을 채굴해야 합니다.
+split.build = 유닛을 벽의 반대편으로 운반해야 합니다.\n두 개의 [accent]화물 매스 드라이버[]를 각 벽면에 하나씩 배치하세요.\n둘 중 하나를 누른 다음 다른 하나를 선택하여 연결을 설정합니다.
+split.container = 컨테이너와 마찬가지로, 유닛도 [accent]화물 매스 드라이버[]를 사용하여 운송할 수 있습니다.\n유닛 조립대를 매스 드라이버 근처에 배치하여 유닛을 적재한 후, 벽을 가로질러 보내 적 기지를 공격하게 만듭니다.
item.copper.description = 모든 종류의 구조물 및 탄약으로 사용하는 기본 자원입니다.
item.copper.details = 평범한 구리. 세르플로에 비정상적으로 많이 분포되어 있습니다. 기본적으로 보강하지 않는 한 구조적으로 약합니다.
@@ -1979,15 +2052,17 @@ item.coal.details = 화석화된 식물 물질. 씨앗이 나오기 훨씬 전
item.titanium.description = 액체 수송 구조물, 드릴 및 공장에서 광범위하게 사용되는 희귀한 초경량 금속입니다.
item.thorium.description = 튼튼한 구조물과 핵 연료로 사용되는 고밀도의 방사성 금속입니다.
item.scrap.description = 융해기와 분쇄기를 통해 다른 물질로 정제할 수 있습니다.
-item.scrap.details = 오래된 구조물과 기체의 잔해. 미량의 다양한 금속들이 포함되어 있습니다.
+item.scrap.details = 오래된 구조물과 유닛의 잔해. 미량의 다양한 금속들이 포함되어 있습니다.
item.silicon.description = 복잡한 전자 장치나 유도탄에 사용되는 유용한 반도체입니다.
-item.plastanium.description = 고급 기체, 절연 및 파편화 탄약에 사용됩니다.
+item.plastanium.description = 고급 유닛, 절연 및 파편화 탄약에 사용됩니다.
item.phase-fabric.description = 최첨단 전자 제품과 자가 수리 기술에 사용되는 거의 무중력에 가까운 물질입니다.
item.surge-alloy.description = 첨단 무기 및 반작용 방어 구조물에 사용되는 고급 합금입니다.
item.spore-pod.description = 석유, 폭발물과 연료로 전환하는 데 사용되는 합성 포자 버섯입니다.
item.spore-pod.details = 포자, 합성 생명체로 판단됩니다. 타 유기체에 치명적인 독가스를 내뿜으며. 매우 빠르게 퍼집니다. 특정한 조건에서 인화성이 매우 높습니다.
item.blast-compound.description = 폭탄과 폭발성 탄약에 사용되는 불안정한 화합물입니다.
item.pyratite.description = 방화 무기와 연료를 연소하는 발전기에 사용되는 가연성이 매우 높은 물질입니다.
+
+#Erekir
item.beryllium.description = 에르키아의 여러 종류의 건축물과 탄약에 사용됩니다.
item.tungsten.description = 드릴, 장갑 및 탄약에 사용됩니다. 보다 발전된 구조물을 건설하는 데 필요합니다.
item.oxide.description = 전원의 열전도체 및 절연체로 사용됩니다.
@@ -1997,6 +2072,8 @@ liquid.water.description = 냉각기 및 폐기물 처리에 사용됩니다.
liquid.slag.description = 분리기를 통해 다른 자원으로 정제하거나 탄환으로 적들에게 살포할 수 있습니다.
liquid.oil.description = 고급 재료 생산, 석탄으로 전환 및 적들에게 살포하여 불을 지를 수 있습니다.
liquid.cryofluid.description = 원자로, 포탑 및 공장에서 냉각수로 사용되는 비부식성 액체입니다.
+
+#Erekir
liquid.arkycite.description = 발전 및 재료 합성을 위한 화학 반응에 사용됩니다.
liquid.ozone.description = 재료 생산에서 산화제로 사용되며 연료로도 사용됩니다. 적당한 폭발성 물질입니다.
liquid.hydrogen.description = 자원 추출, 기체 생산 및 구조물 수리에 사용됩니다. 가연성 물질입니다.
@@ -2005,19 +2082,19 @@ liquid.nitrogen.description = 자원 추출, 가스 생성 및 기체 생산에
liquid.neoplasm.description = 신생물 반응로의 위험한 생물학적 부산물. 접촉하는 즉시 인접한 모든 수분 함유 블록으로 빠르게 확산되며, 진행되는 동안 피해를 입힙니다. 점성을 띄는 물질입니다.
liquid.neoplasm.details = 신생물, 진흙과 비슷한 점성을 가졌으며, 통제 불능의 속도로 빠르게 확산되는 합성세포 덩어리 입니다. 고온에 저항력이 있으며, 일반적인 분석으로는 너무나 복잡하고 불안정하여 아직 정확한 행동 양식이나 생태를 확인하지 못 했습니다. 열 저항. 물과 관련된 구조물에는 매우 위험합니다.\n\n 광재 웅덩이에 소각하는 것이 바람직합니다.
-block.derelict = \ue815 [lightgray]잔해
+block.derelict = \uf77e [lightgray]잔해
block.armored-conveyor.description = 자원을 앞으로 운반합니다. 측면에서 자원을 받아들이지 않습니다.
block.illuminator.description = 발광합니다.
block.message.description = 아군 간의 소통을 위한 메시지를 저장합니다.
block.reinforced-message.description = 동맹 간의 소통을 위한 메시지를 저장합니다.
-block.world-message.description = 지도 작성에 사용되는 메시지 블록. 파괴할 수 없습니다.
+block.world-message.description = 맵 제작에 사용되는 메시지 블록. 파괴할 수 없습니다.
block.graphite-press.description = 석탄을 흑연으로 압축합니다.
block.multi-press.description = 석탄을 흑연으로 압축합니다. 냉각수로 물이 필요합니다.
block.silicon-smelter.description = 석탄과 모래에서 실리콘을 정제합니다.
block.kiln.description = 모래와 납을 강화 유리로 제련합니다.
block.plastanium-compressor.description = 석유와 티타늄으로 플라스터늄을 생산합니다.
-block.phase-weaver.description = 토륨과 모래로 위상 섬유를 합성합니다.
-block.surge-smelter.description = 티타늄, 납, 실리콘 및 구리를 서지 합금으로 혼합합니다.
+block.phase-weaver.description = 토륨과 모래를 위상 섬유로 합성합니다.
+block.surge-smelter.description = 티타늄, 납, 실리콘 및 구리를 설금으로 혼합합니다.
block.cryofluid-mixer.description = 물과 미세 티타늄 분말을 냉각수로 혼합합니다.
block.blast-mixer.description = 파이라타이트와 포자로 폭발물을 생산합니다.
block.pyratite-mixer.description = 석탄, 납, 그리고 모래를 파이라타이트로 혼합합니다.
@@ -2047,13 +2124,17 @@ block.phase-wall.description = 적 발사체로부터 아군 구조물을 보호
block.phase-wall-large.description = 적 발사체로부터 아군 구조물을 보호합니다. 충돌한 탄환 대부분을 반사합니다. \n여러 타일을 차지합니다.
block.surge-wall.description = 적 발사체로부터 아군 구조물을 보호합니다. 접촉 시 무작위로 전격 아크를 방출합니다.
block.surge-wall-large.description = 적 발사체로부터 아군 구조물을 보호합니다. 접촉 시 무작위로 전격 아크를 방출합니다.\n여러 타일을 차지합니다.
+block.scrap-wall.description = 적 발사체로부터 아군 구조물을 보호합니다.
+block.scrap-wall-large.description = 적 발사체로부터 아군 구조물을 보호합니다.
+block.scrap-wall-huge.description = 적 발사체로부터 아군 구조물을 보호합니다.
+block.scrap-wall-gigantic.description = 적 발사체로부터 아군 구조물을 보호합니다.
block.door.description = 탭하여 열거나 닫을 수 있는 벽입니다.
block.door-large.description = 탭하여 열거나 닫을 수 있는 벽입니다.\n여러 타일을 차지합니다.
block.mender.description = 주변 블록을 주기적으로 수리합니다.\n선택적으로 실리콘을 사용하여 범위와 효율성을 향상할 수 있습니다.
block.mend-projector.description = 주변의 블록을 수리합니다.\n선택적으로 위상 섬유를 사용하여 범위와 효율성을 향상할 수 있습니다.
block.overdrive-projector.description = 주변 건물의 속도를 높입니다.\n선택적으로 위상 섬유를 사용하여 범위와 효율성을 향상할 수 있습니다.
-block.force-projector.description = 주위에 육각형 역장을 형성하여 내부의 건물과 기체를 공격으로부터 보호합니다. 지속해서 많은 피해를 받을 경우 과열됩니다.\n선택적으로 냉각수를 사용해서 과열 방지를, 위상 섬유를 사용해서 보호막 크기를 증가시킬 수 있습니다.
-block.shock-mine.description = 접촉한 적 기체에게 전격 아크를 방출합니다.
+block.force-projector.description = 주위에 육각형 역장을 형성하여 내부의 건물과 유닛을 공격으로부터 보호합니다. 지속해서 많은 피해를 받을 경우 과열됩니다.\n선택적으로 냉각수를 사용해서 과열 방지를, 위상 섬유를 사용해서 보호막 크기를 증가시킬 수 있습니다.
+block.shock-mine.description = 접촉한 적 유닛에게 전격 아크를 방출합니다.
block.conveyor.description = 자원을 앞으로 운반합니다. 회전하여 방향을 바꿀 수 있습니다.
block.titanium-conveyor.description = 자원을 앞으로 운반합니다. 컨베이어보다 더 빠릅니다.
block.plastanium-conveyor.description = 자원을 묶어 앞으로 운반합니다. 컨베이에 뒤에서 자원을 받고, 앞에서 세 방향으로 내보냅니다. 최대 처리량을 위해 많은 입출력 지점이 필요합니다.
@@ -2062,7 +2143,7 @@ block.bridge-conveyor.description = 지형이나 건물을 넘어 자원을 운
block.phase-conveyor.description = 지형이나 건물 너머로 자원을 즉시 운반합니다. 속도가 빠르고 다리 컨베이어보다 길지만, 작동하려면 전력이 필요합니다.
block.sorter.description = 입력된 자원이 선택과 일치하면 앞으로 통과하며, 그렇지 않으면 왼쪽과 오른쪽으로 출력합니다.
block.inverted-sorter.description = 필터와 비슷하지만, 대신 선택된 자원을 측면으로 출력합니다.
-block.router.description = 입력된 자원을 최대 3개의 다른 방향으로 동등하게 분배합니다.\n\n[scarlet]공장에서 생산된 자원으로 인해 입력이 막힐 수 있으므로, 절대로 공장 바로 옆에서 사용하지 마세요.
+block.router.description = 입력된 자원을 최대 3개의 다른 방향으로 동등하게 분배합니다.\n\n[scarlet]공장에서 생산된 자원으로 인해 입력이 막힐 수 있으므로, 절대로 공장 바로 옆에서 사용하지 마세요.[]
block.router.details = 필요악. 자원 입력을 위해 공장 옆에 설치하는 것은 그 공장의 출력으로 인해 막힐 수 있으므로 사용하지 않는 것이 좋음.
block.distributor.description = 입력된 자원을 최대 7개의 다른 방향으로 동등하게 분배합니다.
block.overflow-gate.description = 앞쪽 경로가 차단된 경우에만 왼쪽과 오른쪽으로 출력합니다.
@@ -2136,25 +2217,27 @@ block.tsunami.description = 적을 향해 강력한 액체 줄기를 발사합
block.silicon-crucible.description = 파이라타이트를 추가 열원으로 사용하여 모래와 석탄에서 실리콘을 정제합니다. 뜨거운 곳에서 더 효율적입니다.
block.disassembler.description = 광재를 낮은 효율로 미량의 희귀한 광물들로 분리합니다. 토륨을 생산할 수 있습니다.
block.overdrive-dome.description = 주변 건물의 속도를 높입니다. 작동하려면 위상 섬유와 실리콘이 필요합니다.
-block.payload-conveyor.description = 공장에서 생산된 기체같은 큰 화물을 운반합니다.
+block.payload-conveyor.description = 공장에서 생산된 유닛 같은 큰 화물을 운반합니다.
block.payload-router.description = 화물을 3가지 방향으로 번갈아 운반합니다.
-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 = on/off 가능한 스위치입니다. 스위치 상태는 프로세서에 의해 읽히거나 제어될 수 있습니다.
-block.micro-processor.description = 로직 실행문을 순서대로 무한히 실행합니다. 기체 또는 건물을 제어하는 데 쓰일 수 있습니다.
-block.logic-processor.description = 로직 실행문을 순서대로 무한히 실행합니다. 기체 또는 건물을 제어하는 데 쓰일 수 있습니다. 마이크로 프로세서보다 실행 속도가 더 빠릅니다.
-block.hyper-processor.description = 로직 실행문을 순서대로 무한히 실행합니다. 기체 또는 건물을 제어하는 데 쓰일 수 있습니다. 로직 프로세서보다 실행 속도가 더 빠릅니다.
+block.micro-processor.description = 로직 실행문을 순서대로 무한히 실행합니다. 유닛 또는 건물을 제어하는 데 쓰일 수 있습니다.
+block.logic-processor.description = 로직 실행문을 순서대로 무한히 실행합니다. 유닛 또는 건물을 제어하는 데 쓰일 수 있습니다. 마이크로 프로세서보다 실행 속도가 더 빠릅니다.
+block.hyper-processor.description = 로직 실행문을 순서대로 무한히 실행합니다. 유닛 또는 건물을 제어하는 데 쓰일 수 있습니다. 로직 프로세서보다 실행 속도가 더 빠릅니다.
block.memory-cell.description = 프로세서를 위한 데이터를 저장합니다.
block.memory-bank.description = 프로세서를 위한 데이터를 저장합니다. 큰 용량을 지니고 있습니다.
block.logic-display.description = 프로세서를 이용해 임의로 그래픽을 출력할 수 있습니다.
block.large-logic-display.description = 프로세서를 이용해 임의로 그래픽을 출력할 수 있습니다.
block.interplanetary-accelerator.description = 거대한 전자기 레일건 타워. 행성 간 이동을 위한 탈출 속도까지 코어를 가속합니다.
-block.repair-turret.description = 피해를 입은 가장 가까운 기체를 지속적으로 수리합니다. 선택적으로 냉각수를 넣을 수 있습니다.
+block.repair-turret.description = 피해를 입은 가장 가까운 유닛을 지속적으로 수리합니다. 선택적으로 냉각수를 넣을 수 있습니다.
+
+#Erekir
block.core-bastion.description = 기지의 핵심입니다. 튼튼합니다. 한번 파괴되면, 구역을 잃습니다.
block.core-citadel.description = 기지의 핵심입니다. 더 튼튼합니다. 코어: 요새보다 더 많은 양의 자원을 저장합니다.
block.core-acropolis.description = 기지의 핵심입니다. 매우 튼튼합니다. 코어: 성채보다 더 많은 양의 자원을 저장합니다.
@@ -2174,10 +2257,11 @@ block.electric-heater.description = 블록에 열을 가합니다. 많은 양의
block.slag-heater.description = 블록에 열을 가합니다. 광재가 필요합니다.
block.phase-heater.description = 블록에 열을 가합니다. 위상 섬유가 필요합니다.
block.heat-redirector.description = 누적된 열을 다른 블록으로 전달합니다.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = 축적된 열을 세 가지 출력 방향으로 분산시킵니다.
block.electrolyzer.description = 물을 수소와 오존 가스로 변환합니다.
block.atmospheric-concentrator.description = 대기에서 질소를 농축합니다. 열이 필요합니다.
-block.surge-crucible.description = 광재와 실리콘으로 서지 합금을 형성합니다. 열이 필요합니다.
+block.surge-crucible.description = 광재와 실리콘으로 설금을 형성합니다. 열이 필요합니다.
block.phase-synthesizer.description = 토륨, 모래 및 오존으로부터 위상 섬유를 합성합니다. 열이 필요합니다.
block.carbide-crucible.description = 흑연과 텅스텐을 탄화물로 융합합니다. 열이 필요합니다.
block.cyanogen-synthesizer.description = 아르키사이트와 흑연으로부터 시아노겐을 합성합니다. 열이 필요합니다.
@@ -2186,6 +2270,7 @@ block.vent-condenser.description = 분출구에서 나오는 가스를 물로
block.plasma-bore.description = 광석 벽을 향하여 배치하면 자원을 끊임없이 출력합니다. 소량의 전력이 필요합니다.
block.large-plasma-bore.description = 더 큰 플라즈마 채광기. 텅스텐과 토륨을 채굴할 수 있습니다. 수소와 전력이 필요합니다.
block.cliff-crusher.description = 벽을 부수고 모래를 끊임없이 배출합니다. 전력이 필요합니다. 효율은 벽의 유형에 따라 다릅니다.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = 광석에 배치하면 자원을 한번에 몰아서, 끊임없이 출력합니다. 전력과 물이 필요합니다.
block.eruption-drill.description = 개선된 충격 드릴. 토륨을 채굴할 수 있습니다. 수소가 필요합니다.
block.reinforced-conduit.description = 유체를 앞으로 이동합니다. 측면에서 파이프가 아닌 입력을 허용하지 않습니다.
@@ -2213,7 +2298,7 @@ block.duct-unloader.description = 선택한 자원을 뒤의 블록에서 빼냅
block.underflow-duct.description = 포화 도관의 반대입니다. 왼쪽 및 오른쪽 경로가 차단된 경우 앞쪽으로 출력합니다.
block.reinforced-liquid-junction.description = 두 개의 교차 파이프 사이의 다리 역할을 합니다.
block.surge-conveyor.description = 자원을 일괄적으로 이동합니다. 전력을 공급하여 가속할 수 있습니다. 인접한 블록에 전원을 공급합니다.
-block.surge-router.description = 서지 컨베이어에서 항목을 세 방향으로 균등하게 분배합니다. 전력을 공급하여 가속할 수 있습니다. 인접한 블록에 전원을 공급합니다.
+block.surge-router.description = 설금 컨베이어에서 자원을 세 방향으로 균등하게 분배합니다. 전력을 공급하여 가속할 수 있습니다. 인접한 블록에 전원을 공급합니다.
block.unit-cargo-loader.description = 화물용 드론을 제작합니다. 드론은 자동으로 자원과 일치하는 필터로 설정된 기체 화물 하역지점으로 분배합니다.
block.unit-cargo-unload-point.description = 화물 드론의 하역지점 역할을 합니다. 선택한 필터와 일치하는 자원을 받아들입니다.
block.beam-node.description = 전력을 다른 블록에 직선 방향으로 전송합니다. 소량의 전력을 저장합니다.
@@ -2227,24 +2312,24 @@ block.build-tower.description = 범위 내의 구조물을 자동으로 재구
block.regen-projector.description = 정사각형 둘레의 범위 안에 있는 아군 구조물을 천천히 수리합니다. 수소가 필요합니다.
block.reinforced-container.description = 소량의 자원을 저장합니다. 내용물은 언로더를 통해 빼낼 수 있습니다. 코어의 저장 용량은 늘리지 않습니다.
block.reinforced-vault.description = 대량의 자원을 저장합니다. 내용물은 언로더를 통해 빼낼 수 있습니다. 코어의 저장 용량은 늘리지 않습니다.
-block.tank-fabricator.description = 스텔 기체를 구성합니다. 출력된 기체는 직접 사용하거나 강화를 위해 재조립 장치로 이동할 수 있습니다.
-block.ship-fabricator.description = 일루드 기체를 구성합니다. 출력된 기체는 직접 사용하거나 강화를 위해 재조립 장치로 이동할 수 있습니다.
-block.mech-fabricator.description = 메루이 기체를 구성합니다. 출력된 기체는 직접 사용하거나 강화를 위해 재조립 장치로 이동할 수 있습니다.
-block.tank-assembler.description = 입력된 블록과 기체로 대형 전차를 조립합니다. 모듈을 추가하여 출력되는 기체의 등급을 상향할 수 있습니다.
-block.ship-assembler.description = 입력된 블록과 기체로 대형 함선을 조립합니다. 모듈을 추가하여 출력되는 기체의 등급을 상향할 수 있습니다.
-block.mech-assembler.description = 입력된 블록과 기체로 대형 기계를 조립합니다. 모듈을 추가하여 출력되는 기체의 등급을 상향할 수 있습니다.
-block.tank-refabricator.description = 입력된 전차 기체를 두 번째 등급으로 강화합니다.
-block.ship-refabricator.description = 입력된 함선 기체를 두 번째 등급으로 강화합니다.
-block.mech-refabricator.description = 입력된 기계 기체를 두 번째 등급으로 강화합니다.
-block.prime-refabricator.description = 입력된 기체를 세 번째 등급으로 강화합니다.
+block.tank-fabricator.description = 스텔 유닛을 생산합니다. 생산된 유닛은 직접 사용하거나 강화를 위해 재조립 장치로 이동할 수 있습니다.
+block.ship-fabricator.description = 일루드 유닛을 생산합니다. 생산된 유닛은 직접 사용하거나 강화를 위해 재조립 장치로 이동할 수 있습니다.
+block.mech-fabricator.description = 메루이 유닛을 생산합니다. 생산된 유닛은 직접 사용하거나 강화를 위해 재조립 장치로 이동할 수 있습니다.
+block.tank-assembler.description = 입력된 블록과 유닛으로 대형 전차를 조립합니다. 모듈을 추가하여 출력되는 유닛의 등급을 상향할 수 있습니다.
+block.ship-assembler.description = 입력된 블록과 유닛으로 대형 함선을 조립합니다. 모듈을 추가하여 출력되는 유닛의 등급을 상향할 수 있습니다.
+block.mech-assembler.description = 입력된 블록과 유닛으로 대형 기계를 조립합니다. 모듈을 추가하여 출력되는 유닛의 등급을 상향할 수 있습니다.
+block.tank-refabricator.description = 입력된 전차 유닛을 두 번째 등급으로 강화합니다.
+block.ship-refabricator.description = 입력된 함선 유닛을 두 번째 등급으로 강화합니다.
+block.mech-refabricator.description = 입력된 기계 유닛을 두 번째 등급으로 강화합니다.
+block.prime-refabricator.description = 입력된 유닛을 세 번째 등급으로 강화합니다.
block.basic-assembler-module.description = 조립 경계 옆에 배치하면 조립대 등급이 증가합니다. 전력이 필요합니다. 화물 입력으로 사용할 수 있습니다.
-block.small-deconstructor.description = 입력된 구조물 및 기체를 분해합니다. 제작 비용의 100%를 반환합니다.
+block.small-deconstructor.description = 입력된 구조물 및 유닛을 분해합니다. 제작 비용의 100%를 반환합니다.
block.reinforced-payload-conveyor.description = 화물을 앞으로 이동합니다.
block.reinforced-payload-router.description = 화물을 인접 블록으로 분배합니다. 필터가 설정되면 필터로 작동합니다.
block.payload-mass-driver.description = 장거리 화물 운송 구조물. 받은 화물을 연결된 화물 매스 드라이버로 발사합니다.
block.large-payload-mass-driver.description = 장거리 화물 운송 구조물. 받은 화물을 연결된 화물 매스 드라이버로 발사합니다.
-block.unit-repair-tower.description = 주변의 모든 기체를 수리합니다. 오존이 필요합니다.
-block.radar.description = 넓은 반경의 지형과 적 기체를 서서히 파악합니다. 전력이 필요합니다.
+block.unit-repair-tower.description = 주변의 모든 유닛을 수리합니다. 오존이 필요합니다.
+block.radar.description = 넓은 반경의 지형과 적 유닛을 서서히 파악합니다. 전력이 필요합니다.
block.shockwave-tower.description = 반경 내 적의 발사체에 피해를 입히고 파괴합니다. 시아노겐이 필요합니다.
block.canvas.description = 미리 정의된 팔레트를 사용하여 단순 이미지를 표시합니다. 편집 가능.
@@ -2281,11 +2366,13 @@ unit.omura.description = 적을 향해 장거리 관통 레일건을 발사합
unit.alpha.description = 적으로부터 코어: 조각을 방어합니다. 건설할 수 있습니다.
unit.beta.description = 적으로부터 코어: 기반을 방어합니다. 건설할 수 있습니다.
unit.gamma.description = 적으로부터 코어: 핵심을 방어합니다. 건설할 수 있습니다.
-unit.retusa.description = 주변의 적을 향해 유도 어뢰를 발사합니다. 아군 기체를 수리합니다.
+unit.retusa.description = 주변의 적을 향해 유도 어뢰를 발사합니다. 아군 유닛을 수리합니다.
unit.oxynoe.description = 주변의 적을 향해 구조물을 수리하는 화염줄기를 발사합니다. 요격 포탑으로 주변의 적 탄환을 요격합니다.
-unit.cyerce.description = 주변의 적을 향해 유도 집속 미사일을 발사합니다. 아군 기체를 수리합니다.
+unit.cyerce.description = 주변의 적을 향해 유도 집속 미사일을 발사합니다. 아군 유닛을 수리합니다.
unit.aegires.description = 에너지 필드로 들어온 모든 적 기체와 구조물에게 충격을 줍니다. 모든 아군을 수리합니다.
unit.navanax.description = 적 전력망에 상당한 피해를 주고 아군 블록을 수리하는 폭발성 EMP 탄환을 발사합니다. 4개의 자율 레이저 포탑으로 주변 적을 녹입니다.
+
+#Erekir
unit.stell.description = 적 대상에게 일반적인 탄환을 발사합니다.
unit.locus.description = 적 대상에게 번갈아 나오는 탄환을 발사합니다.
unit.precept.description = 적 대상에게 관통하는 집속탄환을 발사합니다.
@@ -2305,103 +2392,112 @@ unit.evoke.description = 코어: 요새를 지켜내기 위해 구조물을 건
unit.incite.description = 코어: 성채를 지켜내기 위해 구조물을 건설합니다. 빔으로 구조물을 수리합니다.
unit.emanate.description = 코어: 도심을 지켜내기 위해 구조물을 건설합니다. 빔으로 구조물을 수리합니다.
-lst.read = 연결된 메모리 셀에서 숫자 읽음
-lst.write = 연결된 메모리 셀에 숫자 작성
-lst.print = 프린트 버퍼에 텍스트 추가\n[accent]Print Flush[]가 사용되기 전까진 아무것도 보여주지 않습니다
-lst.format = Replace next placeholder in text buffer with a value.\nDoes not do anything if placeholder pattern is invalid.\nPlaceholder pattern: "{[accent]number 0-9[]}"\nExample:\n[accent]print "test {0}"\nformat "example"
-lst.draw = 드로잉 버퍼에 실행문 추가\n[accent]Draw Flush[]가 사용되기 전까진 아무것도 보여주지 않습니다
-lst.drawflush = 대기중인 [accent]Draw[]실행문을 디스플레이에 출력
-lst.printflush = 대기중인 [accent]Print[]실행문을 메시지 블록에 출력
-lst.getlink = 순서별로 프로세서의 연결을 가져옴. 0부터 시작
-lst.control = 건물 조종
-lst.radar = 건물 주변의 기체 검색
-lst.sensor = 건물 또는 기체의 정보 수집
-lst.set = 변수 선언/할당
-lst.operation = 1~2개의 변수로 연산
-lst.end = 실행줄의 가장 위로 건너뜀
-lst.wait = 일정 시간(초) 동안 대기
-lst.stop = 이 프로세서의 실행 중지
-lst.lookup = id를 통해 특정 유형의 아이템/액체/기체/블록 조회\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[]\n...로 각 유형의 총 갯수를 알 수 있습니다.
-lst.jump = 조건부로 다른 실행문으로 건너뜀
-lst.unitbind = type 옆에 있는 기체를 지정하고, [accent]@unit[]에 저장
-lst.unitcontrol = 현재 지정된 기체 조종
-lst.unitradar = 현재 지정된 기체 주변의 기체 검색
-lst.unitlocate = 특정 유형의 위치/건물을 지도상에서 조회\n지정된 기체가 필요합니다
-lst.getblock = 특정 위치의 타일 정보를 불러옴
-lst.setblock = 특정 위치의 타일 정보 설정
-lst.spawnunit = 특정 위치에 기체 소환
-lst.applystatus = 기체에게 상태이상을 적용하거나 삭제
-lst.weathersense = Check if a type of weather is active.
-lst.weatherset = Set the current state of a type of weather.
-lst.spawnwave = 특정 위치에 이전 단계를 실행\n실제 단계가 넘어가지 않습니다
-lst.explosion = 특정 위치에 폭발 생성
-lst.setrate = 프로세서 실행 속도를 틱당 연산량으로 설정
-lst.fetch = 기체, 코어, 플레이어 또는 건물을 엔티티 번호로 조회\n번호는 0에서 시작하여 엔티티 번호-1에서 끝납니다
-lst.packcolor = 그리기 혹은 규칙 설정을 위해 [0, 1] RGBA 단일 요소로 묶음
-lst.setrule = 게임 규칙 설정
-lst.flushmessage = 텍스트 버퍼로부터 화면에 메세지를 표시\n이전 메세지가 완료될 때까지 기다립니다
-lst.cutscene = 플레이어 카메라 조작
-lst.setflag = 모든 프로세서가 읽을 수 있는 전역 플래그 설정
-lst.getflag = 전역 플래그가 설정되어 있는지 확인
-lst.setprop = 기체 혹은 건물의 속성을 설정합니다.
-lst.effect = Create a particle effect.
-lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
-lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
-lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
-lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
+lst.read = 연결된 메모리 셀에서 숫자를 읽습니다.
+lst.write = 연결된 메모리 셀에 숫자를 작성합니다.
+lst.print = 프린트 버퍼에 텍스트를 추가합니다.\n[accent]Print Flush[]가 사용되기 전까진 아무것도 보여주지 않습니다.
+lst.format = 텍스트 버퍼의 다음 플레이스홀더를 값으로 바꿉니다.\n자리 표시자 패턴이 유효하지 않은 경우 아무것도 하지 않습니다.\n플레이스홀더 패턴: "{[accent]number 0-9[]}"\n예:\n[accent]print "test {0}"\nformat "example"
+lst.draw = 드로잉 버퍼에 실행문을 추가합니다.\n[accent]Draw Flush[]가 사용되기 전까진 아무것도 보여주지 않습니다.
+lst.drawflush = 대기중인 [accent]Draw[]실행문을 디스플레이에 출력합니다.
+lst.printflush = 대기중인 [accent]Print[]실행문을 메시지 블록에 출력합니다.
+lst.getlink = 순서별로 프로세서의 연결을 가져옵니다. 0부터 시작합니다.
+lst.control = 건물을 조종합니다.
+lst.radar = 건물 주변의 유닛을 검색합니다.
+lst.sensor = 건물 또는 유닛의 정보를 수집합니다.
+lst.set = 변수를 설정합니다.
+lst.operation = 1~2개의 변수로 연산합니다.
+lst.end = 실행줄의 가장 위로 건너뜁니다.
+lst.wait = 일정 시간(초) 동안 대기합니다.
+lst.stop = 이 프로세서의 실행 중지합니다.
+lst.lookup = id를 통해 특정 유형의 자원/액체/유닛/블록을 조회합니다.\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[]\n...로 각 유형의 총 갯수를 알 수 있습니다.
+lst.jump = 조건부로 다른 실행문으로 건너뜁니다.
+lst.unitbind = type 옆에 있는 유닛을 지정하고, [accent]@unit[]에 저장합니다.
+lst.unitcontrol = 현재 지정된 유닛을 조종합니다.
+lst.unitradar = 현재 지정된 유닛 주변의 다른 유닛을 검색합니다.
+lst.unitlocate = 특정 유형의 위치/건물을 맵 상에서 조회.\n지정된 유닛이 필요합니다.
+lst.getblock = 특정 위치의 타일 정보를 불러옵니다.
+lst.setblock = 특정 위치의 타일 정보 설정합니다.
+lst.spawnunit = 특정 위치에 유닛을 소환합니다.
+lst.applystatus = 유닛에게 상태 이상을 적용하거나 삭제합니다.
+lst.weathersense = 어떤 유형의 날씨가 활동하는지 확인합니다.
+lst.weatherset = 날씨 유형의 현재 상태를 설정합니다.
+lst.spawnwave = 특정 위치에 이전 단계를 실행합니다.\n실제로 단계가 넘어가지는 않습니다.
+lst.explosion = 특정 위치에 폭발을 생성합니다.
+lst.setrate = 프로세서 실행 속도를 틱당 연산량으로 설정합니다.
+lst.fetch = 유닛, 코어, 플레이어 또는 건물을 엔티티 번호로 조회합니다.\n번호는 0에서 시작하여 엔티티 번호-1에서 끝납니다.
+lst.packcolor = 그리기 혹은 규칙 설정을 위해 [0, 1] RGBA 단일 요소로 묶습니다.
+lst.setrule = 게임 규칙을 설정합니다.
+lst.flushmessage = 텍스트 버퍼로부터 화면에 메세지를 표시합니다.\n이전 메세지가 완료될 때까지 기다립니다.
+lst.cutscene = 플레이어 카메라를 조작합니다.
+lst.setflag = 모든 프로세서가 읽을 수 있는 전역 플래그 설정합니다.
+lst.getflag = 전역 플래그가 설정되어 있는지 확인합니다.
+lst.setprop = 유닛 혹은 건물의 속성을 설정합니다.
+lst.effect = 파티클 효과를 만듭니다.
+lst.sync = 네트워크 전체에서 변수를 동기화합니다.\n1초에 최대 10번만 호출됩니다.
+lst.playsound = 소리를 재생합니다.\n볼륨과 팬은 전역 값이 될 수도 있고, 위치를 기준으로 계산될 수도 있습니다.
+lst.makemarker = 월드에 새로운 논리 마커를 만듭니다.\n 이 마커를 식별할 ID를 제공해야 합니다.\n 현재 마커는 월드당 20,000개로 제한되어 있습니다.
+lst.setmarker = 마커의 속성을 설정합니다.\n사용된 ID는 마커 만들기 지침에서와 동일해야 합니다.
+lst.localeprint = 텍스트 버퍼에 맵 언어 팩 속성 값을 추가합니다.\n맵 편집기에서 맵 언어 팩을 설정하려면 [accent]맵 정보 > 언어 팩[]을 선택합니다.\n클라이언트가 모바일 기기인 경우 먼저 ".mobile"로 끝나는 속성을 print하려고 시도합니다.
+
lglobal.false = 0
lglobal.true = 1
lglobal.null = null
-lglobal.@pi = The mathematical constant pi (3.141...)
-lglobal.@e = The mathematical constant e (2.718...)
-lglobal.@degToRad = Multiply by this number to convert degrees to radians
-lglobal.@radToDeg = Multiply by this number to convert radians to degrees
-lglobal.@time = Playtime of current save, in milliseconds
-lglobal.@tick = Playtime of current save, in ticks (1 second = 60 ticks)
-lglobal.@second = Playtime of current save, in seconds
-lglobal.@minute = Playtime of current save, in minutes
-lglobal.@waveNumber = Current wave number, if waves are enabled
-lglobal.@waveTime = Countdown timer for waves, in seconds
-lglobal.@mapw = Map width in tiles
-lglobal.@maph = Map height in tiles
-lglobal.sectionMap = Map
-lglobal.sectionGeneral = General
-lglobal.sectionNetwork = Network/Clientside [World Processor Only]
-lglobal.sectionProcessor = Processor
-lglobal.sectionLookup = Lookup
-lglobal.@this = The logic block executing the code
-lglobal.@thisx = X coordinate of block executing the code
-lglobal.@thisy = Y coordinate of block executing the code
-lglobal.@links = Total number of blocks linked to this processors
-lglobal.@ipt = Execution speed of the processor in instructions per tick (60 ticks = 1 second)
-lglobal.@unitCount = Total number of types of unit content in the game; used with the lookup instruction
-lglobal.@blockCount = Total number of types of block content in the game; used with the lookup instruction
-lglobal.@itemCount = Total number of types of item content in the game; used with the lookup instruction
-lglobal.@liquidCount = Total number of types of liquid content in the game; used with the lookup instruction
-lglobal.@server = True if the code is running on a server or in singleplayer, false otherwise
-lglobal.@client = True if the code is running on a client connected to a server
-lglobal.@clientLocale = Locale of the client running the code. For example: en_US
-lglobal.@clientUnit = Unit of client running the code
-lglobal.@clientName = Player name of client running the code
-lglobal.@clientTeam = Team ID of client running the code
-lglobal.@clientMobile = True is the client running the code is on mobile, false otherwise
+lglobal.@pi = 수학적 상수; 파이(pi) (3.141...)
+lglobal.@e = 수학적 상수; 자연상수(e) (2.718...)
+lglobal.@degToRad = 이 숫자를 곱하여 각도를 라디안으로 변환
+lglobal.@radToDeg = 이 숫자를 곱하여 라디안을 각도로 변환
-logic.nounitbuild = [red]기체의 건설 로직은 여기서 허용되지 않습니다.
+lglobal.@time = 현재 저장의 재생 시간(밀리초)
+lglobal.@tick = 현재 저장의 재생 시간(틱 단위, 1초 = 60틱)
+lglobal.@second = 현재 저장의 재생 시간(초)
+lglobal.@minute = 현재 저장 파일의 재생 시간(분)
+lglobal.@waveNumber = 현재 단계 번호(단계가 활성화된 경우)
+lglobal.@waveTime = 단계 카운트다운 타이머(초)
+lglobal.@mapw = 타일 단위의 맵 너비
+lglobal.@maph = 타일 단위의 맵 높이
-lenum.type = 건물/기체의 유형\n예로 분배기는 문자열이 아니라 [accent]@router[]를 반환합니다.
+lglobal.sectionMap = 맵
+lglobal.sectionGeneral = 일반
+lglobal.sectionNetwork = 네트워크/클라이언트 측 [월드 프로세서 전용]
+lglobal.sectionProcessor = 프로세서
+lglobal.sectionLookup = 조회
+
+lglobal.@this = 코드를 실행하는 로직 블록
+lglobal.@thisx = 코드를 실행하는 블록의 X 좌표
+lglobal.@thisy = 코드를 실행하는 블록의 Y 좌표
+lglobal.@links = 이 프로세서에 연결된 총 블록 수
+lglobal.@ipt = 틱당 명령어로 표현된 프로세서의 실행 속도(60틱 = 1초)
+
+lglobal.@unitCount = 게임에서 유닛 콘텐츠 유형의 총 수; 조회 지침과 함께 사용됨
+lglobal.@blockCount = 게임의 블록 콘텐츠 유형의 총 수; 조회 지침과 함께 사용됨
+lglobal.@itemCount = 게임의 아이템 콘텐츠 유형의 총 수; 조회 지침과 함께 사용됨
+lglobal.@liquidCount = 게임의 액체 콘텐츠 유형의 총 수; 조회 지침과 함께 사용됨
+
+lglobal.@server = 코드가 서버 또는 싱글 플레이어에서 실행되는 경우 true, 그렇지 않은 경우 false
+lglobal.@client = 코드가 서버에 연결된 클라이언트에서 실행되는 경우 true
+
+lglobal.@clientLocale = 코드를 실행하는 클라이언트의 언어 팩. 예: en_US (한국어는 ko_KR)
+lglobal.@clientUnit = 코드를 실행하는 클라이언트의 단위
+lglobal.@clientName = 코드를 실행하는 클라이언트의 플레이어 이름
+lglobal.@clientTeam = 코드를 실행하는 클라이언트의 팀 ID
+lglobal.@clientMobile = 코드를 실행하는 클라이언트가 모바일에 있는 경우 true, 그렇지 않으면 false
+
+logic.nounitbuild = [red]유닛의 건설 로직은 여기에서 허용되지 않습니다.
+
+lenum.type = 건물/유닛의 유형\n예로 분배기는 문자열이 아니라 [accent]@router[]를 반환합니다.
lenum.shoot = 특정 위치에 발사
lenum.shootp = 목표물 속도를 예측하여 발사
lenum.config = 필터의 아이템같은 건물의 설정
lenum.enabled = 블록의 활성 여부
-laccess.currentammotype = Current ammo item/liquid of a turret.
-laccess.color = 조명 색상
-laccess.controller = 기체 제어자. 프로세서가 제어하면, 프로세서를 반환합니다.\n다른 기체에 의해 지휘되면(G키), 지휘하는 기체를 반환합니다.\n그 외에는 자신을 반환합니다.
-laccess.dead = 기체 또는 건물 사망/무효 여부
-laccess.controlled = 만약 기체 제어자가 프로세서라면 [accent]@ctrlProcessor[]를 반환합니다.\n만약 기체/건물 제어자가 플레이어라면 [accent]@ctrlPlayer[]를 반환합니다.\n만약 기체가 다른 기체에 의해 지휘되면(G키)[accent]@ctrlFormation[]를 반환합니다.\n그 외에는 0을 반환합니다.
+laccess.currentammotype = 포탑의 현재 탄약/액체.
+laccess.color = 조명 색상.
+laccess.controller = 유닛 제어자. 프로세서가 제어하면, 프로세서를 반환합니다.\n다른 유닛에 의해 지휘되면(G키), 지휘하는 유닛을 반환합니다.\n그 외에는 자신을 반환합니다.
+laccess.dead = 기체 또는 건물 사망/무효 여부.
+laccess.controlled = 만약 유닛 제어자가 프로세서라면 [accent]@ctrlProcessor[]를 반환합니다.\n만약 유닛/건물 제어자가 플레이어라면 [accent]@ctrlPlayer[]를 반환합니다.\n만약 유닛가 다른 유닛에 의해 지휘되면(G키)[accent]@ctrlFormation[]를 반환합니다.\n그 외에는 0을 반환합니다.
laccess.progress = 작업 진행률, 0 에서 1 로 감.\n포탑 재장전이나 구조물 진행률을 반환합니다.
-laccess.speed = 기체의 최대 속도, 타일/초
-laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup operation.
+laccess.speed = 기체의 최대 속도, 타일/초.
+laccess.id = 유닛/블록/아이템/액체의 ID.\n이것은 조회 작업의 역순입니다.
+
lcategory.unknown = 알 수 없음
lcategory.unknown.description = 분류되지 않은 설명
lcategory.io = 입력 & 출력
@@ -2428,7 +2524,7 @@ graphicstype.poly = 정다각형 채우기
graphicstype.linepoly = 정다각형 외곽선 그리기
graphicstype.triangle = 삼각형 채우기
graphicstype.image = 일부 콘텐츠의 이미지 그리기\n예: [accent]@router[] 또는 [accent]@dagger[].
-graphicstype.print = Draws text from the print buffer.\nClears the print buffer.
+graphicstype.print = 프린트 버퍼에서 텍스트를 그립니다.\n프린트 버퍼를 지웁니다.
lenum.always = 항상 참
lenum.idiv = 정수 나누기
@@ -2448,7 +2544,7 @@ lenum.xor = 비트연산자 XOR
lenum.min = 두 수의 최솟값
lenum.max = 두 수의 최댓값
lenum.angle = 벡터의 각(도)
-lenum.anglediff = Absolute distance between two angles in degrees.
+lenum.anglediff = 두 각도 사이의 절대 거리(도).
lenum.len = 벡터의 길이
lenum.sin = 사인(도)
@@ -2467,14 +2563,14 @@ lenum.noise = 2D 심플렉스 노이즈
lenum.abs = 절댓값
lenum.sqrt = 제곱근
-lenum.any = 아무 기체
-lenum.ally = 아군 기체
-lenum.attacker = 무기를 가진 기체
-lenum.enemy = 적 기체
-lenum.boss = 수호자 기체
-lenum.flying = 공중 기체
-lenum.ground = 지상 기체
-lenum.player = 플레이어에 의해 조종된 기체
+lenum.any = 아무 유닛
+lenum.ally = 아군 유닛
+lenum.attacker = 무기를 가진 유닛
+lenum.enemy = 적 유닛
+lenum.boss = 수호자 유닛
+lenum.flying = 공중 유닛
+lenum.ground = 지상 유닛
+lenum.player = 플레이어에 의해 조종된 유닛
lenum.ore = 광석 매장지
lenum.damaged = 손상된 아군 건물
@@ -2494,20 +2590,20 @@ lenum.turret = 포탑
sensor.in = 감지할 건물/기체
radar.from = 감지를 할 건물\n감지 범위는 건물의 감지 범위에 의해 제한됩니다.
-radar.target = 기체 감지 필터
+radar.target = 유닛 감지 필터
radar.and = 추가 필터
radar.order = 정렬 순서. 0은 반전
radar.sort = 결과를 정렬할 기준
-radar.output = 찾은 기체를 대입할 변수
+radar.output = 찾은 유닛을 대입할 변수
-unitradar.target = 기체 감지 필터
+unitradar.target = 유닛 감지 필터
unitradar.and = 추가 필터
unitradar.order = 정렬 순서. 0은 반전
unitradar.sort = 결과를 정렬할 측정 수단
-unitradar.output = 찾은 기체를 대입할 변수
+unitradar.output = 찾은 유닛을 대입할 변수
control.of = 조종할 건물
-control.unit = 조준할 기체/건물
+control.unit = 조준할 유닛/건물
control.shoot = 발사 여부
unitlocate.enemy = 적 건물 포함 여부
@@ -2517,13 +2613,15 @@ unitlocate.outx = X좌표
unitlocate.outy = Y좌표
unitlocate.group = 찾을 건물 집단
+playsound.limit = true인 경우, 같은 프레임에서 이미 재생된 사운드는 재생되지 않습니다.
+
lenum.idle = 이동 정지, 채광/건설 유지\n기본 상태입니다.
lenum.stop = 이동/채광/건설 중단
lenum.unbind = 로직 컨트롤 완전 비활성화\n표준 AI를 다시 따릅니다.
lenum.move = 특정 위치로 이동
lenum.approach = 특정 위치로 반지름만큼 접근
lenum.pathfind = 적 스폰 지점으로 길찾기
-lenum.autopathfind = Automatically pathfinds to the nearest enemy core or drop point.\nThis is the same as standard wave enemy pathfinding.
+lenum.autopathfind = 가장 가까운 적의 코어이나 착륙 지점까지 자동으로 경로를 찾습니다.\n이것은 일반적인 웨이브 적 경로 찾기와 동일합니다.
lenum.target = 특정 위치에 발사
lenum.targetp = 목표물 속도를 예측하여 발사
lenum.itemdrop = 아이템 투하
@@ -2534,13 +2632,14 @@ lenum.payenter = 유닛 아래의 화물 건물에 착륙/진입
lenum.flag = 깃발 수 설정
lenum.mine = 특정 위치에서 채광
lenum.build = 구조물 건설
-lenum.getblock = Fetch building, floor and block type at coordinates.\nUnit must be in range of the position, otherwise null is returned.
+lenum.getblock = 좌표에서 건물, 층, 블록 유형을 가져옵니다.\n단위는 위치 범위 내에 있어야 하며, 그렇지 않으면 null이 반환됩니다.
lenum.within = 좌표 주변 기체 발견 여부
lenum.boost = 이륙 시작/중단
-lenum.flushtext = Flush print buffer's content to marker, if applicable.\nIf fetch is set to true, tries to fetch properties from map locale bundle or game's bundle.
-lenum.texture = Texture name straight from game's texture atlas (using kebab-case naming style).\nIf printFlush is set to true, consumes text buffer content as text argument.
-lenum.texturesize = Size of texture in tiles. Zero value scales marker width to original texture's size.
-lenum.autoscale = Whether to scale marker corresponding to player's zoom level.
-lenum.posi = Indexed position, used for line and quad markers with index zero being the first position.
-lenum.uvi = Texture's position ranging from zero to one, used for quad markers.
-lenum.colori = Indexed position, used for line and quad markers with index zero being the first color.
+
+lenum.flushtext = 해당되는 경우, 프린트 버퍼의 내용을 마커에 플러시.\nFetch가 true로 설정된 경우, 맵 언어 팩 또는 게임 번들에서 속성을 가져오려고 시도합니다.
+lenum.texture = 게임의 texture atlas에서 직접 가져온 텍스처 이름(케밥식 명명 스타일 사용).\n printFlush가 true로 설정된 경우, 텍스트 인수로 텍스트 버퍼 내용을 사용합니다.
+lenum.texturesize = 타일의 텍스처 크기. 0 값은 마커 너비를 원래 텍스처 크기에 맞게 조정합니다.
+lenum.autoscale = 플레이어의 확대/축소 레벨에 맞춰 마커의 크기를 조정할지 여부.
+lenum.posi = 인덱스 위치. 라인 및 쿼드 마커에 사용되며 인덱스 0이 첫 번째 위치입니.
+lenum.uvi = 0에서 1까지의 텍스처 위치, 쿼드 마커에 사용.
+lenum.colori = 인덱스된 위치, 인덱스 0이 첫 번째 색상이며 라인 및 쿼드 마커에 사용.
diff --git a/core/assets/bundles/bundle_lt.properties b/core/assets/bundles/bundle_lt.properties
index d197bd3657..ac9cf13b60 100644
--- a/core/assets/bundles/bundle_lt.properties
+++ b/core/assets/bundles/bundle_lt.properties
@@ -141,6 +141,7 @@ mod.enabled = [lightgray]Įjungta
mod.disabled = [scarlet]Išjungta
mod.multiplayer.compatible = [gray]Multiplayer Compatible
mod.disable = Išjungti
+mod.version = Version:
mod.content = Tūrinys:
mod.delete.error = Negalima ištrinti modifikacijos. Failas gali būti naudojamas.
mod.incompatiblegame = [red]Outdated Game
@@ -190,6 +191,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Išrasta
techtree = Technologijų Medis
techtree.select = Tech Tree Selection
@@ -289,13 +291,14 @@ disconnect.error = Prisijungimo klaida.
disconnect.closed = Prisijungimas uždarytas.
disconnect.timeout = Baigėsi laikas.
disconnect.data = Nepavyko užkrauti pasaulio informacijos!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Negalima prisijungti prie žaidimo ([accent]{0}[]).
connecting = [accent]Prisijungiama...
reconnecting = [accent]Reconnecting...
connecting.data = [accent]Kraunama pasaulio informacija...
server.port = Prievadas:
-server.addressinuse = Adresas jau naudojamas!
server.invalidport = Negaliams prievado numeris!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Įvyko klaida.
save.new = Naujas Išsaugojimas
save.overwrite = Ar esate tikras, jog\n norite perrašyti šį elementą?
@@ -348,6 +351,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -490,6 +494,7 @@ waves.units.show = Show All
wavemode.counts = counts
wavemode.totals = totals
wavemode.health = health
+all = All
editor.default = [lightgray]
details = Detaliau...
@@ -657,7 +662,6 @@ requirement.capture = Capture {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Launch
-research.multiplayer = Only the host can research items.
map.multiplayer = Only the host can view sectors.
uncover = Atidengti
configure = Keisti resursų kiekį
@@ -725,6 +729,7 @@ error.mapnotfound = Žemėlapis nerastas!
error.io = Tinklo I/O klaida.
error.any = Nžinoma tinklo klaida.
error.bloom = Nepavyko inicijuoti spindėjimo.\nJūsų įrenginys gali nepalaikyti šios funkcijos.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Rain
weather.snowing.name = Snow
@@ -774,6 +779,11 @@ threat.medium = Medium
threat.high = High
threat.extreme = Extreme
threat.eradication = Eradication
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planets
planet.serpulo.name = Serpulo
@@ -795,9 +805,19 @@ sector.fungalPass.name = Fungal Pass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on.
sector.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders.
@@ -817,6 +837,18 @@ sector.impact0078.description = Here lie remnants of the interstellar transport
sector.planetaryTerminal.description = The final target.\n\nThis coastal base contains a structure capable of launching Cores to local planets. It is extremely well guarded.\n\nProduce naval units. Eliminate the enemy as quickly as possible. Research the launch structure.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
sector.lake.name = Lake
@@ -1013,6 +1045,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1077,6 +1110,8 @@ bullet.healamount = [stat]{0}[lightgray] direct repair
bullet.multiplier = [stat]{0}[lightgray]x šovinių daugiklis
bullet.reload = [stat]{0}[lightgray]x šaudymo greitis
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blokai
unit.blockssquared = blocks²
@@ -1137,12 +1172,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI mastelio keitimas[lightgray] (reikalingas perkrovimas)[]
setting.uiscale.description = Restart required to apply changes.
setting.swapdiagonal.name = Visada Įstrižinis Padėjimas
-setting.difficulty.training = Mokymai
-setting.difficulty.easy = Lengvas
-setting.difficulty.normal = Normalus
-setting.difficulty.hard = Sunkus
-setting.difficulty.insane = Beprotiškas
-setting.difficulty.name = Sunkumas:
setting.screenshake.name = Ekrano Drebėjimas
setting.bloomintensity.name = Bloom Intensity
setting.bloomblur.name = Bloom Blur
@@ -1232,6 +1261,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Pasirinkite Regioną
keybind.schematic_menu.name = Schemų Meniu
@@ -1309,12 +1339,16 @@ rules.wavetimer = Bangų Laikmatis
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Bangos
rules.airUseSpawns = Air units use spawn points
rules.attack = Puolimo Režimas
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Squad Size
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min Attack Weight
@@ -1357,6 +1391,9 @@ rules.title.teams = Teams
rules.title.planet = Planet
rules.lighting = Apšvietimas
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fire
rules.anyenv =
rules.explosions = Block/Unit Explosion Damage
@@ -1365,6 +1402,7 @@ rules.weather = Weather
rules.weather.frequency = Frequency:
rules.weather.always = Always
rules.weather.duration = Duration:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1505,6 +1543,8 @@ block.graphite-press.name = Grafito Presas
block.multi-press.name = Multi Presas
block.constructing = {0} [lightgray](Konstruojama)
block.spawn.name = Priešų Atsiradimo Zona
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Branduolys: Šerdis
block.core-foundation.name = Branduolys: Pagrindas
block.core-nucleus.name = Branduolys: Centras
@@ -1762,6 +1802,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1809,6 +1850,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2034,6 +2076,10 @@ block.phase-wall.description = Siena padengta specialiu faziniu pagrindu sukurtu
block.phase-wall-large.description = Siena padengta specialiu faziniu pagrindu sukurtu junginiu. Atmuša daugumą šovinių.\nUžima kelias vietas.
block.surge-wall.description = Ypač patvarus gynybinis blokas.\nKaupia krūvį kontakto metu su šoviniu atsitiktinai jį išleisdamas.
block.surge-wall-large.description = Ypač patvarus gynybinis blokas.\nKaupia krūvį kontakto metu su šoviniu atsitiktinai jį išleisdamas.\nUžima kelias vietas.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Mažos durys. Gali būti atidarytos ir uždarytos paspaudus.
block.door-large.description = Didelės durys. Gali būti atidarytos ir uždarytos paspaudus.\nUžima kelias vietas.
block.mender.description = Periodiškai taiso blokus pasiekiamame plote. Palaiko gynybines konstrukcijas pataisytas tarp bangu.\nPapildomai naudoja silicį atstumo ir efektyvumo padidinimui.
@@ -2161,6 +2207,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2173,6 +2220,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2331,6 +2379,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2483,6 +2532,7 @@ unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Don't move, but keep building/mining.\nThe default state.
lenum.stop = Stop moving/mining/building.
lenum.unbind = Completely disable logic control.\nResume standard AI.
diff --git a/core/assets/bundles/bundle_nl.properties b/core/assets/bundles/bundle_nl.properties
index 21df1a3d23..148c8e8bd2 100644
--- a/core/assets/bundles/bundle_nl.properties
+++ b/core/assets/bundles/bundle_nl.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Ingeschakeld
mod.disabled = [scarlet]Uitgeschakeld
mod.multiplayer.compatible = [gray]Geschikt voor meerdere speleres
mod.disable = Deactiveer
+mod.version = Version:
mod.content = Inhoud:
mod.delete.error = Mod verwijderen mislukt. Bestand mogelijk in gebruik.
@@ -197,6 +198,7 @@ campaign.select = Selecteer een veldtocht om mee te starten
campaign.none = [lightgray]Kies een planeet om op te starten.\nJe kan op elk moment omschakelen naar de andere planeet.
campaign.erekir = Nieuwere, meer gepolijste inhoud. Grotendeels lineair veldtochtverloop.\n\nKaarten en algemene ervaring van hogere kwaliteit.
campaign.serpulo = Oudere inhoud; de klassieke ervaring. Meer open veldtochtverloop.\n\nKans op ongebalanceerde kaarten en veldtocht mechanismen. Minder gepolijst.
+campaign.difficulty = Difficulty
completed = [accent]Voltooid
techtree = Techniekboom
techtree.select = Techniekboom selectie
@@ -297,13 +299,14 @@ disconnect.error = Verbindingsfout.
disconnect.closed = Verbinding gestopt.
disconnect.timeout = Verbinding afgekapt.
disconnect.data = Kon de wereld niet laden!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Geen verbinding mogelijk ([accent]{0}[]).
connecting = [accent]Aan het verbinden...
reconnecting = [accent]Aan het herverbinden...
connecting.data = [accent]Wereld aan het laden...
server.port = Poort:
-server.addressinuse = Adres is al in gebruik!
server.invalidport = Poort is geen geldig getal!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Fout met hosten: [accent]{0}
save.new = Nieuwe Save
save.overwrite = Weet je zeker dat je deze\nsave wilt overschrijven?
@@ -356,6 +359,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -498,6 +502,7 @@ waves.units.show = Toon Alle
wavemode.counts = telt
wavemode.totals = totalen
wavemode.health = levenspunten
+all = All
editor.default = [lightgray]
details = Details...
@@ -667,7 +672,6 @@ requirement.capture = Verover {0}
requirement.onplanet = Controlesector Op {0}
requirement.onsector = Land Op Sector: {0}
launch.text = Lanceer
-research.multiplayer = Alleen de host kan dingen onderzoeken.
map.multiplayer = Alleen de host kan sectoren bekijken.
uncover = Ontmasker
configure = Configureer startinventaris
@@ -736,6 +740,7 @@ error.mapnotfound = Kaartbestand niet gevonden!
error.io = Netwerk I/O fout.
error.any = Onbekende netwerk fout.
error.bloom = Bloom aanzetten mislukt.\nJe apparaat ondersteunt het waarschijnlijk niet.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Regen
weather.snowing.name = Sneeuw
@@ -785,6 +790,11 @@ threat.medium = Gemiddeld
threat.high = Hoog
threat.extreme = Extreem
threat.eradication = Uitroeiing
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planeten
planet.serpulo.name = Serpulo
@@ -806,9 +816,19 @@ sector.fungalPass.name = Fungal Pass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetery Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = De optimale locatie om nog een keer te beginnen. Lage vijandelijke dreiging. Enkele grondstoffen.\nVerzamel zoveel mogelijk lood en koper.\nGa door.
sector.frozenForest.description = Zelfs hier, dichter bij de bergen, hebben de schimmels zich verspreid. De koude temperaturen kunnen ze niet eeuwig tegenhouden.\n\nBegin de onderneming in energie. Bouw verbrandingsgeneratoren. Leer herstellers te gebruiken.
@@ -828,6 +848,18 @@ sector.impact0078.description = Hier liggen overblijfselen van het interstellair
sector.planetaryTerminal.description = Het einddoel.\n\nDeze kustbasis bevat een structuur die Cores kan lanceren naar lokale planeten. Het wordt extreem goed bewaakt.\n\nProduceer marine eenheden. Schakel de vijand zo snel mogelijk uit. Onderzoek de lanceerstructuur.
sector.coastline.description = Op deze locatie zijn resten van marinetechnologie gedetecteerd. Sla de vijandelijke aanvallen af, verover deze sector en verkrijg de technologie.
sector.navalFortress.description = De vijand heeft een basis gevestigd op een afgelegen, natuurlijk versterkt eiland. Vernietig deze voorpost. Verkrijg hun geavanceerde marinetechnologie en onderzoek die.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
@@ -1025,6 +1057,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1089,6 +1122,8 @@ bullet.healamount = [stat]{0}[lightgray] directe reparatie
bullet.multiplier = [stat]{0}[lightgray]x ammunitieverdubbelaar
bullet.reload = [stat]{0}[lightgray]x herlaad
bullet.range = [stat]{0}[lightgray] tegels bereik
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blokken
unit.blockssquared = blokken�
@@ -1149,12 +1184,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI Schaal[lightgray] (herstart vereist)[]
setting.uiscale.description = Herstart vereist om veranderingen door te voeren.
setting.swapdiagonal.name = Altijd Diagonaal Plaatsen
-setting.difficulty.training = Oefening
-setting.difficulty.easy = Makkelijk
-setting.difficulty.normal = Normaal
-setting.difficulty.hard = Moeilijk
-setting.difficulty.insane = Krankzinnig
-setting.difficulty.name = Moeilijkheidsgraad:
setting.screenshake.name = Schuddend Scherm
setting.bloomintensity.name = Bloom Intensiteit
setting.bloomblur.name = Bloom Waas
@@ -1244,6 +1273,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Herbouw Regio
keybind.schematic_select.name = Selecteer gebied
keybind.schematic_menu.name = Ontwerpmenu
@@ -1321,12 +1351,16 @@ rules.wavetimer = Vijandelijke Golven Timer
rules.wavesending = Golven Sturen
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Golven
rules.airUseSpawns = Air units use spawn points
rules.attack = Aanvalmodus
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Ploeg Grootte
rules.rtsmaxsquadsize = Max Ploeg Grootte
rules.rtsminattackweight = Min Aanvalsgewicht
@@ -1369,6 +1403,9 @@ rules.title.teams = Teams
rules.title.planet = Planeet
rules.lighting = Belichting
rules.fog = Mist van de Oorlog
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Vuur
rules.anyenv =
rules.explosions = Blok/Eenheid Explosieschade
@@ -1377,6 +1414,7 @@ rules.weather = Weer
rules.weather.frequency = Frequentie:
rules.weather.always = Altijd
rules.weather.duration = Duur:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1517,6 +1555,8 @@ block.graphite-press.name = Grafietpers
block.multi-press.name = Super-Pers
block.constructing = {0} [lightgray](Bouwen)
block.spawn.name = Vijandelijke Spawn
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Core: Scherf
block.core-foundation.name = Core: Fundament
block.core-nucleus.name = Core: Nucleus
@@ -1775,6 +1815,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1822,6 +1863,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2047,6 +2089,10 @@ block.phase-wall.description = Not as strong as a thorium wall but will deflect
block.phase-wall-large.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful.\nSpans multiple tiles.
block.surge-wall.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker.
block.surge-wall-large.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker.\nSpans multiple tiles.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = A small door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through.
block.door-large.description = A large door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through.\nSpans multiple tiles.
block.mender.description = Periodically repairs blocks in its vicinity. Keeps defenses repaired in-between waves.\nOptionally uses silicon to boost range and efficiency.
@@ -2174,6 +2220,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2186,6 +2233,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2344,6 +2392,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2496,6 +2545,7 @@ unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Don't move, but keep building/mining.\nThe default state.
lenum.stop = Stop moving/mining/building.
lenum.unbind = Completely disable logic control.\nResume standard AI.
diff --git a/core/assets/bundles/bundle_nl_BE.properties b/core/assets/bundles/bundle_nl_BE.properties
index bb32cf85be..a9d1b251aa 100644
--- a/core/assets/bundles/bundle_nl_BE.properties
+++ b/core/assets/bundles/bundle_nl_BE.properties
@@ -141,6 +141,7 @@ mod.enabled = [lightgray]Ingeschakeld
mod.disabled = [scarlet]Uitgeschakeld
mod.multiplayer.compatible = [gray]Multiplayer Compatible
mod.disable = Schakel uit
+mod.version = Version:
mod.content = Content:
mod.delete.error = Kan mod niet verwijderen. Bestand is mogelijk in gebruik.
mod.incompatiblegame = [red]Outdated Game
@@ -190,6 +191,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Voltooid
techtree = Technische vooruitgang
techtree.select = Tech Tree Selection
@@ -289,13 +291,14 @@ disconnect.error = Verbindingsfout.
disconnect.closed = Verbinding afgesloten.
disconnect.timeout = Het duurde te lang voordat de server antwoordde.
disconnect.data = Laden van mapdata mislukt!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Kon niet tot het spel toetreden. ([accent]{0}[]).
connecting = [accent]Verbinden...
reconnecting = [accent]Reconnecting...
connecting.data = [accent]Laden map data...
server.port = Poort:
-server.addressinuse = Dit adres wordt al gebruikt!
server.invalidport = Ongeldige poort!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Fout bij het openen van de server: [accent]{0}
save.new = Nieuwe save
save.overwrite = Ben je zeker dat je deze save\nwilt overschrijven?
@@ -348,6 +351,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -490,6 +494,7 @@ waves.units.show = Show All
wavemode.counts = counts
wavemode.totals = totals
wavemode.health = health
+all = All
editor.default = [lightgray]
details = Details...
@@ -657,7 +662,6 @@ requirement.capture = Capture {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Launch
-research.multiplayer = Only the host can research items.
map.multiplayer = Only the host can view sectors.
uncover = Uncover
configure = Configure Loadout
@@ -725,6 +729,7 @@ error.mapnotfound = Map file not found!
error.io = Network I/O error.
error.any = Unknown network error.
error.bloom = Failed to initialize bloom.\nYour device may not support it.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Rain
weather.snowing.name = Snow
@@ -774,6 +779,11 @@ threat.medium = Medium
threat.high = High
threat.extreme = Extreme
threat.eradication = Eradication
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planets
planet.serpulo.name = Serpulo
@@ -795,9 +805,19 @@ sector.fungalPass.name = Fungal Pass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on.
sector.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders.
@@ -817,6 +837,18 @@ sector.impact0078.description = Here lie remnants of the interstellar transport
sector.planetaryTerminal.description = The final target.\n\nThis coastal base contains a structure capable of launching Cores to local planets. It is extremely well guarded.\n\nProduce naval units. Eliminate the enemy as quickly as possible. Research the launch structure.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
sector.lake.name = Lake
@@ -1013,6 +1045,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1077,6 +1110,8 @@ bullet.healamount = [stat]{0}[lightgray] direct repair
bullet.multiplier = [stat]{0}[lightgray]x ammo multiplier
bullet.reload = [stat]{0}[lightgray]x fire rate
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blocks
unit.blockssquared = blocks²
@@ -1137,12 +1172,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI Scaling[lightgray] (requires restart)[]
setting.uiscale.description = Restart required to apply changes.
setting.swapdiagonal.name = Always Diagonal Placement
-setting.difficulty.training = training
-setting.difficulty.easy = easy
-setting.difficulty.normal = normal
-setting.difficulty.hard = hard
-setting.difficulty.insane = insane
-setting.difficulty.name = Difficulty:
setting.screenshake.name = Screen Shake
setting.bloomintensity.name = Bloom Intensity
setting.bloomblur.name = Bloom Blur
@@ -1232,6 +1261,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Select Region
keybind.schematic_menu.name = Schematic Menu
@@ -1309,12 +1339,16 @@ rules.wavetimer = Wave Timer
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Waves
rules.airUseSpawns = Air units use spawn points
rules.attack = Attack Mode
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Squad Size
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min Attack Weight
@@ -1357,6 +1391,9 @@ rules.title.teams = Teams
rules.title.planet = Planet
rules.lighting = Lighting
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fire
rules.anyenv =
rules.explosions = Block/Unit Explosion Damage
@@ -1365,6 +1402,7 @@ rules.weather = Weather
rules.weather.frequency = Frequency:
rules.weather.always = Always
rules.weather.duration = Duration:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1505,6 +1543,8 @@ block.graphite-press.name = Graphite Press
block.multi-press.name = Multi-Press
block.constructing = {0} [lightgray](Constructing)
block.spawn.name = Enemy Spawn
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Core: Shard
block.core-foundation.name = Core: Foundation
block.core-nucleus.name = Core: Nucleus
@@ -1762,6 +1802,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1809,6 +1850,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2034,6 +2076,10 @@ block.phase-wall.description = Not as strong as a thorium wall but will deflect
block.phase-wall-large.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful.\nSpans multiple tiles.
block.surge-wall.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker.
block.surge-wall-large.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker.\nSpans multiple tiles.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = A small door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through.
block.door-large.description = A large door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through.\nSpans multiple tiles.
block.mender.description = Periodically repairs blocks in its vicinity. Keeps defenses repaired in-between waves.\nOptionally uses silicon to boost range and efficiency.
@@ -2161,6 +2207,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2173,6 +2220,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2331,6 +2379,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2483,6 +2532,7 @@ unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Don't move, but keep building/mining.\nThe default state.
lenum.stop = Stop moving/mining/building.
lenum.unbind = Completely disable logic control.\nResume standard AI.
diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties
index 87477c01ab..b868efbc0a 100644
--- a/core/assets/bundles/bundle_pl.properties
+++ b/core/assets/bundles/bundle_pl.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Włączony
mod.disabled = [scarlet]Wyłączony
mod.multiplayer.compatible = [gray]Kompatybilny z trybem wieloosobowym
mod.disable = Wyłącz
+mod.version = Version:
mod.content = Zawartość:
mod.delete.error = Nie udało się usunąć moda. Plik może być w użyciu.
mod.incompatiblegame = [red]Przestarzała Gra
@@ -193,6 +194,7 @@ campaign.select = Wybierz początkową kampanię
campaign.none = [lightgray]Wybierz planetę, na której chcesz zacząć.\nMożesz zmienić planetę w każdej chwili.
campaign.erekir = Nowsza, bardziej dopracowana zawartość. Kampania postępuje bardziej liniowo.\n\nWyższej jakości mapy oraz rozgrywka.
campaign.serpulo = Starsza zawartość; klasyczne doświadczenia. Bardziej otwarta.\n\nPotencjalnie niezbalansowane mapy i mechaniki. Słabiej dopracowana.
+campaign.difficulty = Difficulty
completed = [accent]Ukończony
techtree = Drzewo Techno-\nlogiczne
techtree.select = Wybór Drzewa Technologicznego
@@ -293,13 +295,14 @@ disconnect.error = Błąd połączenia.
disconnect.closed = Połączenie zostało zamknięte.
disconnect.timeout = Przekroczono limit czasu.
disconnect.data = Nie udało się załadować mapy!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Nie można dołączyć do gry ([accent]{0}[]).
connecting = [accent]Łączenie...
reconnecting = [accent]Ponowne łączenie...
connecting.data = [accent]Ładowanie danych świata...
server.port = Port:
-server.addressinuse = Adres jest już w użyciu!
server.invalidport = Nieprawidłowy numer portu.
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Błąd hostowania serwera: [accent]{0}
save.new = Nowy zapis
save.overwrite = Czy na pewno chcesz nadpisać zapis gry?
@@ -352,6 +355,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Załaduj Jednostki
command.loadBlocks = Załaduj Bloki
command.unloadPayload = Rozładuj Ładunek
+command.loopPayload = Loop Unit Transfer
stance.stop = Analuj Rozkazy
stance.shoot = Strzelaj
stance.holdfire = Wstrzymaj Ogień
@@ -495,6 +499,7 @@ waves.units.show = Pokaż Wszystkie
wavemode.counts = liczba
wavemode.totals = sumy
wavemode.health = życie
+all = All
editor.default = [lightgray]
details = Detale...
@@ -662,7 +667,6 @@ requirement.capture = Zdobądź {0}
requirement.onplanet = Kontrolowane Sektory na {0}
requirement.onsector = Wyląduj na Sektorze: {0}
launch.text = Wystrzel
-research.multiplayer = Tylko host może odkrywać przedmioty.
map.multiplayer = Tylko host może widzieć sektory
uncover = Odkryj
configure = Skonfiguruj Ładunek
@@ -731,6 +735,7 @@ error.mapnotfound = Plik mapy nie został znaleziony!
error.io = Błąd sieciowy I/O.
error.any = Nieznany błąd sieci.
error.bloom = Nie udało się załadować funkcji bloom.\nTwoje urządzenie może nie wspierać tej funkcji.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Deszcz
weather.snowing.name = Śnieg
@@ -781,6 +786,11 @@ threat.medium = Średni
threat.high = Wysoki
threat.extreme = Ekstremalny
threat.eradication = Czystka
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planety
@@ -803,9 +813,19 @@ sector.fungalPass.name = Grzybowa Przełęcz
sector.biomassFacility.name = Obiekt Syntezy Biomasy
sector.windsweptIslands.name = Wyspy Wiatru
sector.extractionOutpost.name = Placówka Ekstrakcji
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetarny Terminal Startowy
sector.coastline.name = Linia Brzegowa
sector.navalFortress.name = Morska Forteca
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Optymalna lokalizacja, aby rozpocząć jeszcze raz. Niskie zagrożenie. Niewiele zasobów.\nZbierz możliwie jak najwięcej miedzi i ołowiu.\nPrzejdź do następnej strefy jak najszybciej.
sector.frozenForest.description = Nawet tutaj, bliżej gór, zarodniki się rozprzestrzeniały. Niskie temperatury nie mogą ich zatrzymać na zawsze.\n\nZacznij od produkcji prądu. Buduj generatory spalinowe. Naucz się korzystać z naprawiaczy.
@@ -825,6 +845,18 @@ sector.impact0078.description = Tutaj leżą pozostałości międzygwiezdnego st
sector.planetaryTerminal.description = Ostatni cel.\n\nTa baza przybrzeżna zawiera strukturę zdolną do wystrzeliwania rdzeni na lokalne planety. Jest wyjątkowo dobrze strzeżona.\n\nProdukuj jednostki morskie. Jak najszybciej wyeliminuj wroga. Zbadaj tą strukturę.
sector.coastline.description = W tej lokalizacji zostały znalezione resztki technologii jednostek morskich. Odeprzyj ataki wroga, przejmij ten sektor i zdobądź technologię.
sector.navalFortress.description = Wróg założył bazę na odległej, naturalnie ufortyfikowanej wyspie. Zniszcz tę bazę. Zdobądź zaawansowaną technologię statków morskich i zbadaj ją.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = Początek
sector.aegis.name = Egida
@@ -1022,6 +1054,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1086,6 +1119,8 @@ bullet.healamount = [stat]{0}[lightgray] bezpośrednia naprawa
bullet.multiplier = [stat]{0}[lightgray]x mnożnik amunicji
bullet.reload = [stat]{0}[lightgray]x szybkość ataku
bullet.range = [stat]{0}[lightgray] zasięg ataku
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = bloki
unit.blockssquared = bloki²
@@ -1146,12 +1181,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Skalowanie interfejsu[lightgray] (wymaga restartu)[]
setting.uiscale.description = Aby zastosować zmiany, wymagane jest ponowne uruchomienie.
setting.swapdiagonal.name = Pozwala na ukośną budowę
-setting.difficulty.training = Treningowy
-setting.difficulty.easy = Łatwy
-setting.difficulty.normal = Normalny
-setting.difficulty.hard = Trudny
-setting.difficulty.insane = Szalony
-setting.difficulty.name = Poziom trudności
setting.screenshake.name = Siła wstrząsów ekranu
setting.bloomintensity.name = Intensywaność Rozmycia
setting.bloomblur.name = Niewyraźność Rozmycia
@@ -1241,6 +1270,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Odbuduj Region
keybind.schematic_select.name = Wybierz Region
keybind.schematic_menu.name = Menu Schematów
@@ -1318,12 +1348,16 @@ rules.wavetimer = Zegar Fal
rules.wavesending = Wysyłanie Fal
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Fale
rules.airUseSpawns = Air units use spawn points
rules.attack = Tryb Ataku
rules.buildai = AI Budowania Baz
rules.buildaitier = Poziom Budowania AI
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Minimalny Rozmiar Składu
rules.rtsmaxsquadsize = Maksymalny Rozmiar Składu
rules.rtsminattackweight = Minimalna Waga Ataku
@@ -1366,6 +1400,9 @@ rules.title.teams = Drużyny
rules.title.planet = Planet
rules.lighting = Oświetlenie
rules.fog = Mgła Wojny
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Ogień
rules.anyenv =
rules.explosions = Uszkodzenia Wybuchu Bloku/Jednostki
@@ -1374,6 +1411,7 @@ rules.weather = Pogoda
rules.weather.frequency = Częstotliwość:
rules.weather.always = Zawsze
rules.weather.duration = Czas trwania:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1524,6 +1562,8 @@ block.graphite-press.name = Grafitowa Prasa
block.multi-press.name = Multi-Prasa
block.constructing = {0} [lightgray](Budowa)
block.spawn.name = Spawn wrogów
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Rdzeń: Odłamek
block.core-foundation.name = Rdzeń: Podstawa
block.core-nucleus.name = Rdzeń: Jądro
@@ -1782,6 +1822,7 @@ block.electric-heater.name = Podgrzewacz Elektryczny
block.slag-heater.name = Podgrzewacz Żużlowy
block.phase-heater.name = Podgrzewacz Fazowy
block.heat-redirector.name = Kierownik Ciepła
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Rozdzielacz Ciepła
block.slag-incinerator.name = Spalarnia Żużla
block.carbide-crucible.name = Tygiel Karbidu
@@ -1829,6 +1870,7 @@ block.chemical-combustion-chamber.name = Chemiczna Komora Spalania
block.pyrolysis-generator.name = Generator Pirolizy
block.vent-condenser.name = Skraplacz Pary
block.cliff-crusher.name = Rozdrabniacz Klifów
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plazmowe Wiertło
block.large-plasma-bore.name = Duże Plazmowe Wiertło
block.impact-drill.name = Uderzeniowe Wiertło
@@ -2055,6 +2097,10 @@ block.phase-wall.description = Mur pokryty specjalną mieszanką opartą o Włó
block.phase-wall-large.description = Mur pokryty specjalną mieszanką opartą o Włókna Fazowe, która odbija większość pocisków.\nObejmuje wiele kratek.
block.surge-wall.description = Ekstremalnie wytrzymały blok obronny.\nMa niewielką szansę na wywołanie błyskawicy w kierunku atakującego.
block.surge-wall-large.description = Ekstremalnie wytrzymały blok obronny.\nMa niewielką szansę na wywołanie błyskawicy w kierunku atakującego.\nObejmuje wiele kratek.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Małe drzwi, które można otwierać i zamykać, klikając na nie.\nJeśli są otwarte, wrogowie mogą przez nie strzelać oraz nimi przechodzić.
block.door-large.description = Duże drzwi, które można otwierać i zamykać, klikając na nie.\nJeśli są otwarte, wrogowie mogą przez nie strzelać oraz nimi przechodzić.\nObejmują wiele kratek.
block.mender.description = Co jakiś czas naprawia bloki w zasięgu. Utrzymuje struktury obronne w dobrym stanie.\nOpcjonalnie używa krzemu do zwiększenia zasięgu i szybkości naprawy.
@@ -2182,6 +2228,7 @@ block.electric-heater.description = Ogrzewa bloki naprzeciw, używając do tego
block.slag-heater.description = Ogrzewa bloki naprzeciw, używając do tego żużlu.
block.phase-heater.description = Ogrzewa bloki naprzeciw, używając do tego włókna fazowego.
block.heat-redirector.description = Przekazuje zebrane ciepło do bloku naprzeciw.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Rozprowadza zgromadzone ciepło w trzech różnych kierunkach.
block.electrolyzer.description = Poddaje wodę elektrolizie, uzyskując wodór i ozon w postaci gazowej.
block.atmospheric-concentrator.description = Koncentruje azot z atmosfery, używając do tego ciepła.
@@ -2194,6 +2241,7 @@ block.vent-condenser.description = Skrapla parę wodną z gejzeru.
block.plasma-bore.description = Wydobywa rudę znajdującą się na ścianach. Wymaga minimalnej ilości prądu. Ilość rudy wydobytej co cykl zależy od ilości bloków rudy naprzeciw wiertła.
block.large-plasma-bore.description = Większe wiertło plazmowe. Wydobywa rudę znajdującą się na ścianach. Wymaga większej ilości prądu i dodatkowo wodoru, ale może wydobyć wolfram i tor. Ilość rudy wydobytej co cykl zależy od ilości bloków rudy naprzeciw wiertła.
block.cliff-crusher.description = Kruszy ściany, uzyskując w ten sposób piasek. Wydajność zależy od rodzaju ściany. Wymaga prądu.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = Kiedy stoi na rudzie, wydobywa surowce seriami. Wymaga prądu i wody.
block.eruption-drill.description = Ulepszona wersja wiertła wybuchowego. Zdolne do wydobycia toru. Potrzebuje wodoru do działania.
block.reinforced-conduit.description = Służy do przemieszczania płynów i gazów. Od boku można podłączyć tylko inne rury.
@@ -2365,6 +2413,7 @@ lst.getflag = Sprawdź, czy ustawiona jest flaga globalna.
lst.setprop = Ustaw właściwość jednostki lub budynku.
lst.effect = Stwórz efekt cząsteczki.
lst.sync = Synchronizuje zmienną poprzez sieć.\nWywoływane maksymalnie 10 razy na sekundę.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Stwórz nowy marker logiki.\nMusisz podać ID, aby móc go później zidentyfikować.\nLimit markerów to 20,000.
lst.setmarker = Ustaw właściwości markera.\nID markera musi być takie samo jak podczas jego tworzenia.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2535,6 +2584,7 @@ unitlocate.building = Zmienna wyjściowa dla zlokalizowanego budynku.
unitlocate.outx = Wyjściowa współrzędna X.
unitlocate.outy = Wyjściowa współrzędna Y.
unitlocate.group = Grupa szukanych budynków.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Przestań się poruszać, jednak nadal buduj/wydobywaj.\nDomyślny stan.
lenum.stop = Przestań poruszać się/kopać/budować.
diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties
index 2aadc7d22f..1a9a017efd 100644
--- a/core/assets/bundles/bundle_pt_BR.properties
+++ b/core/assets/bundles/bundle_pt_BR.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Ativado
mod.disabled = [scarlet]Desativado
mod.multiplayer.compatible = [gray]Compatível com Multiplayer
mod.disable = Desati-\nvar
+mod.version = Version:
mod.content = Conteúdo:
mod.delete.error = Incapaz de deletar o mod. O arquivo talvez esteja em uso.
mod.incompatiblegame = [red]Jogo desatualizado
@@ -193,6 +194,7 @@ campaign.select = Selecione a campanha inicial
campaign.none = [lightgray]Selecione um planeta para começar nele.\nVocê pode mudar de planeta a qualquer momento.
campaign.erekir = Novo, conteúdo mais polido. Uma progressão mais linear na campanha.\n\nExperiência geral e mapas de maior qualidade.
campaign.serpulo = Conteúdo antigo; a experiência clássica. Mais aberto.\n\nMapas e mecânicas de campanha potencialmente desbalanceados. Menos polido.
+campaign.difficulty = Difficulty
completed = [accent]Completado
techtree = Árvore Tecnológica
techtree.select = Seleção de Árvore Tecnológica
@@ -293,13 +295,14 @@ disconnect.error = Erro de conexão.
disconnect.closed = Conexão fechada.
disconnect.timeout = Tempo esgotado.
disconnect.data = Falha ao carregar os dados do mundo!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Impossível conectar ([accent]{0}[]).
connecting = [accent]Conectando...
reconnecting = [accent]Reconectando...
connecting.data = [accent]Carregando dados do mundo...
server.port = Porta:
-server.addressinuse = Porta em uso!
server.invalidport = Numero de port inválido!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Erro ao hospedar o servidor: [accent]{0}
save.new = Novo save
save.overwrite = Você tem certeza que quer sobrescrever este save?
@@ -352,6 +355,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -495,6 +499,7 @@ waves.units.show = Mostrar tudo
wavemode.counts = quantidade
wavemode.totals = total
wavemode.health = vida
+all = All
editor.default = [lightgray]
details = Detalhes...
@@ -665,7 +670,6 @@ requirement.capture = Capture {0}
requirement.onplanet = Controle o setor em {0}
requirement.onsector = Lance no setor: {0}
launch.text = Lançar
-research.multiplayer = Apenas o host pode pesquisar itens.
map.multiplayer = Apenas o host consegue ver os setores.
uncover = Descobrir
configure = Configurar carregamento
@@ -739,6 +743,7 @@ error.mapnotfound = Arquivo de mapa não encontrado!
error.io = Erro I/O de internet.
error.any = Erro de rede desconhecido.
error.bloom = Falha ao inicializar bloom.\nSeu dispositivo talvez não o suporte.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Chuva
weather.snowing.name = Neve
@@ -789,6 +794,11 @@ threat.medium = Média
threat.high = Alta
threat.extreme = Extrema
threat.eradication = Erradicação
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planetas
@@ -811,9 +821,19 @@ sector.fungalPass.name = Passagem Fúngica
sector.biomassFacility.name = Instalação de Síntese de Biomassa
sector.windsweptIslands.name = Ilhas Ventadas
sector.extractionOutpost.name = Posto Avançado de Extração
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Terminal de Lançamento Planetário.
sector.coastline.name = Litoral
sector.navalFortress.name = Fortaleza Naval
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Um lugar bom para recomeçar. Baixa ameaça inimiga. Poucos recursos.\nConsiga o máximo possível de chumbo e cobre.\nContinue.
sector.frozenForest.description = Mesmo aqui, perto das montanhas, os esporos se espalharam. As temperaturas baixas não conseguirão contê-los para sempre.\n\nComeçe a aventura com energia. Construa geradores a combustão. Aprenda a usar reparadores.
@@ -833,6 +853,18 @@ sector.impact0078.description = Aqui repousas restos de um reservatório de tran
sector.planetaryTerminal.description = O último alvo.\n\nEssa base costeira contém a estrutura capaz de lançar Núcleos para planetas locais. É extremamente bem guardado.\n\nProduza unidades navais. Elimine o inimigo o mais rápido o possível. pesquise a estrutura de lançamento.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = O Começo
sector.aegis.name = Aegis
@@ -1033,6 +1065,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1096,6 +1129,8 @@ bullet.healamount = [stat]{0}[lightgray] reparo direto
bullet.multiplier = [stat]{0}[lightgray]x multiplicador de munição
bullet.reload = [stat]{0}[lightgray]x cadência de tiro
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = Blocos
unit.blockssquared = Blocos²
@@ -1156,12 +1191,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Escala da\ninterface[lightgray] (reinicialização requerida)[]
setting.uiscale.description = Reinicialização necessária para aplicar as alterações.
setting.swapdiagonal.name = Sempre colocação diagonal
-setting.difficulty.training = Treinamento
-setting.difficulty.easy = Fácil
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Difícil
-setting.difficulty.insane = Insano
-setting.difficulty.name = Dificuldade
setting.screenshake.name = Vibração da Tela
setting.bloomintensity.name = Itensidade do Bloom
setting.bloomblur.name = Desfoque do Bloom
@@ -1251,6 +1280,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Selecionar região
keybind.schematic_menu.name = Menu de Esquemas
@@ -1328,12 +1358,16 @@ rules.wavetimer = Tempo de horda
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Hordas
rules.airUseSpawns = Air units use spawn points
rules.attack = Modo de ataque
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Tamanho mínimo do esquadrão
rules.rtsmaxsquadsize = Tamanho máximo do esquadrão
rules.rtsminattackweight = Peso Mínimo de Ataque
@@ -1376,6 +1410,9 @@ rules.title.teams = Times
rules.title.planet = Planeta
rules.lighting = Iluminação
rules.fog = Névoa de Guerra
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fogo
rules.anyenv =
rules.explosions = Dano de explosão de unidades/blocos
@@ -1384,6 +1421,7 @@ rules.weather = Clima
rules.weather.frequency = Frequência:
rules.weather.always = Sempre
rules.weather.duration = Duração:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1524,6 +1562,8 @@ block.graphite-press.name = Prensa de grafite
block.multi-press.name = Multi-Prensa
block.constructing = {0}\n[lightgray](Construindo)
block.spawn.name = Área Inimiga
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
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
@@ -1781,6 +1821,7 @@ block.electric-heater.name = Aquecedor Elétrico
block.slag-heater.name = Aquecedor de Escória
block.phase-heater.name = Aquecedor de Fase
block.heat-redirector.name = Redirecionador de Calor
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Incinerador de Escória
block.carbide-crucible.name = Crisol de Carboneto
@@ -1828,6 +1869,7 @@ block.chemical-combustion-chamber.name = Câmara de Combustão Química
block.pyrolysis-generator.name = Gerador de Pirólise
block.vent-condenser.name = Condensador de Ventilação
block.cliff-crusher.name = Esmagador de Penhasco
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Mineradora de Plasma
block.large-plasma-bore.name = Mineradora de Plasma Grande
block.impact-drill.name = Broca de Impacto
@@ -2063,6 +2105,10 @@ block.phase-wall.description = Um muro revestido com tecido de fase. Reflete a m
block.phase-wall-large.description = Um muro revestido com tecido de fase. Reflete a maioria das balas ao impacto. Ocupa múltiplos blocos.
block.surge-wall.description = Um bloco defensivo extremamente durável. Se carrega com eletricidade no contato com as balas, soltando-as aleatoriamente.
block.surge-wall-large.description = Um bloco defensivo extremamente durável. Se carrega com eletricidade no contato com as balas, soltando-as aleatoriamente. Ocupa multiplos blocos.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Uma pequeda porta. Pode ser aberta e fechada ao tocar.
block.door-large.description = Uma grande porta. Pode ser aberta e fechada ao tocar. Ocupa múltiplos blocos.
block.mender.description = Periodicamente repara blocos vizinhos.\nOpicionalmente usa silício para aumentar o alcance e a eficácia.
@@ -2192,6 +2238,7 @@ block.electric-heater.description = Aquece blocos a frente. Requer grandes quant
block.slag-heater.description = Aquece blocos a frente. Requer Escória.
block.phase-heater.description = Aquece blocos a frente. Requer Tecido de Fase
block.heat-redirector.description = Redireciona o calor acumulado para outros blocos.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converte Água em Hidrogênio e gás de Ozônio.
block.atmospheric-concentrator.description = Concentra o Nitrogênio da atmosfera. Requer calor.
@@ -2204,6 +2251,7 @@ block.vent-condenser.description = Condensa os gases de ventilação em água. C
block.plasma-bore.description = Quando colocado de frente para uma parede de minério, produz itens por tempo indeterminado. Requer pequenas quantidades de energia.
block.large-plasma-bore.description = Uma Broca de Plasma maior. Capaz de extrair tungstênio e tório. Requer hidrogênio e energia.
block.cliff-crusher.description = Esmaga as paredes, produzindo areia indefinidamente. Requer energia. A eficiência varia de acordo com o tipo de parede.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = Quando colocados sobre minério, os itens saem em rajadas indefinidamente. Requer energia e água.
block.eruption-drill.description = Uma Broca de Impacto melhorada. Capaz de minerar Tório. Requer Hidrogênio.
block.reinforced-conduit.description = Movimenta fluidos para frente. Não aceita entradas de outros blocos, a não ser canos, dos lados.
@@ -2364,6 +2412,7 @@ lst.getflag = Verifique se um sinalizador global está definido.
lst.setprop = Define uma propriedade de uma unidade ou edifício.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2533,6 +2582,7 @@ unitlocate.building = Variável de saída para edifício localizado.
unitlocate.outx = Coordenada X de saída.
unitlocate.outy = Coordenada Y de saída.
unitlocate.group = Grupo de construção para procurar.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Não se mova, mas continue construindo/minerando.\nO estado padrão.
lenum.stop = Pare de mover/mineração/construção.
diff --git a/core/assets/bundles/bundle_pt_PT.properties b/core/assets/bundles/bundle_pt_PT.properties
index 3dbe0a7975..f42d9dfaed 100644
--- a/core/assets/bundles/bundle_pt_PT.properties
+++ b/core/assets/bundles/bundle_pt_PT.properties
@@ -141,6 +141,7 @@ mod.enabled = [lightgray]Ativado
mod.disabled = [scarlet]Desativado
mod.multiplayer.compatible = [gray]Multiplayer Compatible
mod.disable = Desativar
+mod.version = Version:
mod.content = Content:
mod.delete.error = Incapaz de apagar o mod. Ficheiro já em uso.
mod.incompatiblegame = [red]Outdated Game
@@ -190,6 +191,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Completado
techtree = Árvore de tecnologia
techtree.select = Tech Tree Selection
@@ -289,13 +291,14 @@ disconnect.error = Erro de conexão.
disconnect.closed = Conexão fechada.
disconnect.timeout = Tempo esgotado.
disconnect.data = Falha ao abrir os dados do mundo!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Impossível conectar ([accent]{0}[]).
connecting = [accent]Conectando...
reconnecting = [accent]Reconnecting...
connecting.data = [accent]Carregando dados do mundo...
server.port = Porte:
-server.addressinuse = Endereço em uso!
server.invalidport = Numero de porta invalido!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Erro ao hospedar o servidor: [accent]{0}
save.new = Novo gravamento
save.overwrite = Você tem certeza que quer sobrescrever este gravamento?
@@ -348,6 +351,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -490,6 +494,7 @@ waves.units.show = Show All
wavemode.counts = counts
wavemode.totals = totals
wavemode.health = health
+all = All
editor.default = [lightgray]
details = Detalhes...
@@ -657,7 +662,6 @@ requirement.capture = Capture {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Launch
-research.multiplayer = Only the host can research items.
map.multiplayer = Only the host can view sectors.
uncover = Descobrir
configure = Configurar carregamento
@@ -725,6 +729,7 @@ error.mapnotfound = Ficheiro de mapa não encontrado!
error.io = Erro I/O de internet.
error.any = Erro de rede desconhecido.
error.bloom = Falha ao inicializar bloom.\nSeu aparelho talvez não o suporte.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Rain
weather.snowing.name = Snow
@@ -774,6 +779,11 @@ threat.medium = Medium
threat.high = High
threat.extreme = Extreme
threat.eradication = Eradication
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planets
planet.serpulo.name = Serpulo
@@ -795,9 +805,19 @@ sector.fungalPass.name = Fungal Pass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on.
sector.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders.
@@ -817,6 +837,18 @@ sector.impact0078.description = Here lie remnants of the interstellar transport
sector.planetaryTerminal.description = The final target.\n\nThis coastal base contains a structure capable of launching Cores to local planets. It is extremely well guarded.\n\nProduce naval units. Eliminate the enemy as quickly as possible. Research the launch structure.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
sector.lake.name = Lake
@@ -1013,6 +1045,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1077,6 +1110,8 @@ bullet.healamount = [stat]{0}[lightgray] direct repair
bullet.multiplier = [stat]{0}[lightgray]x multiplicador de munição
bullet.reload = [stat]{0}[lightgray]x cadência de tiro
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = Blocos
unit.blockssquared = blocks²
@@ -1137,12 +1172,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Escala da IU[lightgray] (reinicialização requerida)[]
setting.uiscale.description = Restart required to apply changes.
setting.swapdiagonal.name = Sempre colocação diagnoal
-setting.difficulty.training = Treinamento
-setting.difficulty.easy = Fácil
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Difícil
-setting.difficulty.insane = Insano
-setting.difficulty.name = Dificuldade
setting.screenshake.name = Balanço do Ecrã
setting.bloomintensity.name = Bloom Intensity
setting.bloomblur.name = Bloom Blur
@@ -1232,6 +1261,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Selecionar região
keybind.schematic_menu.name = Menu esquemático
@@ -1309,12 +1339,16 @@ rules.wavetimer = Tempo de horda
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Hordas
rules.airUseSpawns = Air units use spawn points
rules.attack = Modo de ataque
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Squad Size
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min Attack Weight
@@ -1357,6 +1391,9 @@ rules.title.teams = Teams
rules.title.planet = Planet
rules.lighting = Lighting
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fire
rules.anyenv =
rules.explosions = Block/Unit Explosion Damage
@@ -1365,6 +1402,7 @@ rules.weather = Weather
rules.weather.frequency = Frequency:
rules.weather.always = Always
rules.weather.duration = Duration:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1505,6 +1543,8 @@ block.graphite-press.name = Prensa de grafite
block.multi-press.name = Multi-Prensa
block.constructing = {0}\n[lightgray](Construindo)
block.spawn.name = Spawn dos inimigos
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
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
@@ -1762,6 +1802,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1809,6 +1850,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2034,6 +2076,10 @@ block.phase-wall.description = Um muro revestido com um composto especial basead
block.phase-wall-large.description = Um muro revestido com um composto especial baseado em tecido de fase. Desvia a maioria das balas no impacto.\nSOcupa múltiplos blocos.
block.surge-wall.description = Um bloco defensivo extremamente durável.\nSe carrega com eletricidade no contato com as balas, soltando-s aleatoriamente.
block.surge-wall-large.description = Um bloco defensivo extremamente durável.\nSe carrega com eletricidade no contato com as balas, soltando-s aleatoriamente.\nOcupa multiplos blocos.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Uma pequeda porta. Pode ser aberta e fechada ao tocar.
block.door-large.description = Uma grande porta. Pode ser aberta e fechada ao tocar.\nOcupa múltiplos blocos.
block.mender.description = Periodicamente repara blocos vizinhos. Mantem as defesas reparadas em e entre ondas.\nPode usar silício para aumentar o alcance e a eficiência.
@@ -2161,6 +2207,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2173,6 +2220,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2331,6 +2379,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2483,6 +2532,7 @@ unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Don't move, but keep building/mining.\nThe default state.
lenum.stop = Stop moving/mining/building.
lenum.unbind = Completely disable logic control.\nResume standard AI.
diff --git a/core/assets/bundles/bundle_ro.properties b/core/assets/bundles/bundle_ro.properties
index cae469702e..50098f2e0b 100644
--- a/core/assets/bundles/bundle_ro.properties
+++ b/core/assets/bundles/bundle_ro.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Activat
mod.disabled = [scarlet]Dezactivat
mod.multiplayer.compatible = [gray]Compatibil cu Multiplayer
mod.disable = Dezactivează
+mod.version = Version:
mod.content = Conținut:
mod.delete.error = Nu s-a putut șterge modul. Fișierul ar putea fi în uz.
mod.incompatiblegame = [red]Outdated Game
@@ -193,6 +194,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Finalizat
techtree = Cercetează
techtree.select = Tech Tree Selection
@@ -293,13 +295,14 @@ disconnect.error = Eroare de conexiune.
disconnect.closed = Conexiune închisă.
disconnect.timeout = Întârzie să răspundă.
disconnect.data = Nu s-au putut încărca datele lumii!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Nu te-ai putut alătura jocului ([accent]{0}[]).
connecting = [accent]Conectare...
reconnecting = [accent]Reconectare...
connecting.data = [accent]Se încarcă datele hărții...
server.port = Port:
-server.addressinuse = Adresa este deja în uz!
server.invalidport = Număr de port invalid!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [scarlet]Eroare la găzduirea serverului.
save.new = Nouă Salvare
save.overwrite = Sigur vrei să scrii peste \nacest slot de salvare?
@@ -352,6 +355,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -495,6 +499,7 @@ waves.units.show = Vezi Tot
wavemode.counts = numere
wavemode.totals = totaluri
wavemode.health = viață
+all = All
editor.default = [lightgray]
details = Detalii...
@@ -664,7 +669,6 @@ requirement.capture = Capturează {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Lansează
-research.multiplayer = Doar gazda poate cerceta noi tehnologii.
map.multiplayer = Doar gazda poate vedea harta sectoarelor.
uncover = Descoperă
configure = Configurează Încărcarea
@@ -733,6 +737,7 @@ error.mapnotfound = Fișierul hărții nu a fost găsit!
error.io = Eroare de rețea I/O.
error.any = Eroare de rețea necunoscută.
error.bloom = Inițializarea strălucirii a eșuat.\nS-ar putea ca dispozitivul tău să nu suporte funcția.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Ploaie
weather.snowing.name = Ninsoare
@@ -783,6 +788,11 @@ threat.medium = Medie
threat.high = Mare
threat.extreme = Extremă
threat.eradication = Eradicare
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planete
@@ -805,9 +815,19 @@ sector.fungalPass.name = Pasul Fungic
sector.biomassFacility.name = Facilitatea de Sinteză a Biomasei
sector.windsweptIslands.name = Insulele Măturate de Vânt
sector.extractionOutpost.name = Avanpostul de Extracție
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Terminalul de Lansare Planetară
sector.coastline.name = Zona de Coastă
sector.navalFortress.name = Fortăreața Navală
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Locația optimă pt a începe încă odată. Risc de inamici scăzut. Puține resurse.\nAdună cât de mult plumb și cupru se poate.\nMergi mai departe.
sector.frozenForest.description = Chiar și aici, aproape de munți, sporii s-au împrăștiat. Temperaturile reci nu-i pot reține la infinit.\n\nÎncepe călătoria către electricitate. Construiește generatoare de combustie. Învață să folosești reparatoare.
@@ -827,6 +847,18 @@ sector.impact0078.description = Aici se află rămășițele primei nave de tran
sector.planetaryTerminal.description = Ținta finală.\n\nAceastă bază de coastă conține o structură capabilă să lanseze nuclee către alte planete locale. Este extrem de bine păzită.\n\nProdu unități navale. Elimină inamicul cât de rapid se poate. Cercetează structura de lansare.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
sector.lake.name = Lake
@@ -1024,6 +1056,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1088,6 +1121,8 @@ bullet.healamount = [stat]{0}[lightgray] direct repair
bullet.multiplier = [stat]{0}[lightgray]x multiplicator muniție
bullet.reload = [stat]{0}[lightgray]x lovituri
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blocuri
unit.blockssquared = blocuri²
@@ -1148,12 +1183,6 @@ setting.fpscap.text = FPS {0}
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
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Greu
-setting.difficulty.insane = Nebunesc
-setting.difficulty.name = Dificultate:
setting.screenshake.name = Agitare Ecran
setting.bloomintensity.name = Bloom Intensity
setting.bloomblur.name = Bloom Blur
@@ -1243,6 +1272,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Selectează Regiunea
keybind.schematic_menu.name = Meniu Scheme
@@ -1320,12 +1350,16 @@ rules.wavetimer = Valuri pe Timp
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Valuri
rules.airUseSpawns = Air units use spawn points
rules.attack = Modul Atac
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Squad Size
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min Attack Weight
@@ -1368,6 +1402,9 @@ rules.title.teams = Echipe
rules.title.planet = Planet
rules.lighting = Luminozitate Ambientală
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Foc
rules.anyenv =
rules.explosions = Explozia Deteriorează Blocul/Unitatea
@@ -1376,6 +1413,7 @@ rules.weather = Vreme
rules.weather.frequency = Frevență:
rules.weather.always = Încontinuu
rules.weather.duration = Durată:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1518,6 +1556,8 @@ block.graphite-press.name = Presă de Grafit
block.multi-press.name = Multi-Presă
block.constructing = {0} [lightgray](În Construcție)
block.spawn.name = Punct Inamic de Lansare
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Nucleu: Shard
block.core-foundation.name = Nucleu: Foundation
block.core-nucleus.name = Nucleu: Core
@@ -1775,6 +1815,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1822,6 +1863,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2049,6 +2091,10 @@ block.phase-wall.description = Protejează clădirile de proiectilele inamice, r
block.phase-wall-large.description = Protejează clădirile de proiectilele inamice, reflectând majoritatea gloanțelor la impact.
block.surge-wall.description = Protejează clădirile de proiectilele inamice, lansând periodic lasere electrice la contactul cu gloanțele.
block.surge-wall-large.description = Protejează clădirile de proiectilele inamice, lansând periodic lasere electrice la contactul cu gloanțele.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Un perete care poate fi deschis sau închis.
block.door-large.description = Un perete care poate fi deschis sau închis.
block.mender.description = Repară periodic blocurile din vecinătate. \nPoate folosi silicon pt a îmbunătăți raza de acțiune și eficiența.
@@ -2176,6 +2222,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2188,6 +2235,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2348,6 +2396,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2518,6 +2567,7 @@ unitlocate.building = Clădirea detectată.
unitlocate.outx = Coordonata X a obiectului detectat.
unitlocate.outy = Coordonata Y a obiectului detectat.
unitlocate.group = Grupul clădirilor de detectat.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Nu mișca, dar continuă să construiești/minezi.\nModul prestabilit.
lenum.stop = Oprește acțiunea curentă. Nu mișca/mina/construi.
diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties
index 23fd6df9b6..1a40bb7986 100644
--- a/core/assets/bundles/bundle_ru.properties
+++ b/core/assets/bundles/bundle_ru.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Включено
mod.disabled = [scarlet]Выключено
mod.multiplayer.compatible = [gray]Доступна в игре по сети
mod.disable = Выкл.
+mod.version = Version:
mod.content = Содержимое:
mod.delete.error = Невозможно удалить модификацию. Возможно, файл используется.
mod.incompatiblegame = [red]Устаревшая игра
@@ -194,6 +195,7 @@ campaign.select = Выберите стартовую кампанию
campaign.none = [lightgray]Выберите планету, с которой хотите начать.\nПереключить планету можно в любое время.
campaign.erekir = Новый, более отточенный контент. В-основном линейное продвижение по кампании.\n\nКарты и игровой процесс более высокого качества.
campaign.serpulo = Старый контент; классический опыт. Более вариативное прохождение.\n\nПотенциально несбалансированные карты и механики кампании. Менее отточено.
+campaign.difficulty = Difficulty
completed = [accent]Завершено
techtree = Дерево\n технологий
techtree.select = Выбор дерева технологий
@@ -293,13 +295,14 @@ disconnect.error = Ошибка соединения.
disconnect.closed = Соединение закрыто.
disconnect.timeout = Время ожидания истекло.
disconnect.data = Ошибка при загрузке данных мира!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Не удаётся присоединиться к игре ([accent]{0}[]).
connecting = [accent]Подключение…
reconnecting = [accent]Переподключение…
connecting.data = [accent]Загрузка данных мира…
server.port = Порт:
-server.addressinuse = Данный адрес уже используется!
server.invalidport = Неверный номер порта!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [scarlet]Ошибка создания сервера.
save.new = Новое сохранение
save.overwrite = Вы уверены, что хотите перезаписать\nэтот слот для сохранения?
@@ -352,6 +355,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -495,6 +499,7 @@ waves.units.show = Показать все
wavemode.counts = количество единиц
wavemode.totals = всего единиц
wavemode.health = всего прочности
+all = All
editor.default = [lightgray]<По умолчанию>
details = Подробности…
@@ -664,7 +669,6 @@ requirement.capture = Захватите {0}
requirement.onplanet = Возьмите сектор под контроль на {0}
requirement.onsector = Высадитесь на сектор: {0}
launch.text = Высадка
-research.multiplayer = Только хост может исследовать предметы.
map.multiplayer = Только хост может просматривать секторы.
uncover = Раскрыть
configure = Конфигурация выгрузки
@@ -733,6 +737,7 @@ error.mapnotfound = Файл карты не найден!
error.io = Сетевая ошибка ввода-вывода.
error.any = Неизвестная сетевая ошибка.
error.bloom = Не удалось инициализировать свечение (Bloom).\nВозможно, ваше устройство не поддерживает его.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Дождь
weather.snowing.name = Снегопад
@@ -784,6 +789,11 @@ threat.medium = Средняя
threat.high = Высокая
threat.extreme = Экстремальная
threat.eradication = Истребляющая
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Планеты
@@ -806,9 +816,19 @@ sector.fungalPass.name = Грибной перевал
sector.biomassFacility.name = Центр исследования биомассы
sector.windsweptIslands.name = Штормовой архипелаг
sector.extractionOutpost.name = Добывающая база
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Планетарный пусковой терминал
sector.coastline.name = Береговая линия
sector.navalFortress.name = Прибрежная крепость
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Оптимальная локация для повторных игр. Низкая вражеская угроза. Немного ресурсов.\nСоберите как можно больше свинца и меди.\nДвигайтесь дальше.
sector.frozenForest.description = Даже здесь, ближе к горам, споры распространились. Холодные температуры не могут сдерживать их вечно.\n\nНачните вкладываться в энергию. Постройте генераторы внутреннего сгорания. Научитесь пользоваться регенератором.
@@ -828,6 +848,18 @@ sector.impact0078.description = Здесь лежат остатки межзв
sector.planetaryTerminal.description = Конечная цель.\n\nЭта береговая база содержит сооружение, способное запускать ядра к окрестным планетам. Оно крайне хорошо охраняется.\n\nПроизведите морские единицы. Уничтожьте врага как можно скорее. Изучите пусковую конструкцию.
sector.coastline.description = В этом месте были обнаружены остатки древней военно-морской технологии. Отбейте атаки противника, захватите этот сектор и изучите эту технологию.
sector.navalFortress.description = Враг возвел базу на удаленном острове с естественными укреплениями. Уничтожьте её. Овладейте их технологией по производству кораблей и изучите ее.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = Начало
sector.aegis.name = Защита
@@ -1025,6 +1057,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1088,6 +1121,8 @@ bullet.healamount = [stat]{0}[lightgray] прямой ремонт
bullet.multiplier = [stat]{0}[lightgray]x множитель боеприпасов
bullet.reload = [stat]{0}%[lightgray] скорость стрельбы
bullet.range = [stat]{0}[lightgray] диапазон
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = блоков
unit.blockssquared = блоков²
@@ -1148,12 +1183,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Масштаб пользовательского интерфейса
setting.uiscale.description = Для вступления изменений в силу может потребоваться перезагрузка игры.
setting.swapdiagonal.name = Всегда диагональное размещение
-setting.difficulty.training = Обучение
-setting.difficulty.easy = Лёгкая
-setting.difficulty.normal = Нормальная
-setting.difficulty.hard = Сложная
-setting.difficulty.insane = Безумная
-setting.difficulty.name = Сложность:
setting.screenshake.name = Тряска экрана
setting.bloomintensity.name = Интенсивность свечения
setting.bloomblur.name = Размытие свечения
@@ -1243,6 +1272,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Перестроить в области
keybind.schematic_select.name = Выбрать область
keybind.schematic_menu.name = Меню схем
@@ -1319,12 +1349,16 @@ rules.wavetimer = Интервал волн
rules.wavesending = Отправка волн
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Волны
rules.airUseSpawns = Air units use spawn points
rules.attack = Режим атаки
rules.buildai = ИИ строит базы
rules.buildaitier = Уровень баз ИИ
rules.rtsai = ИИ в реальном времени
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Минимальный размер отряда
rules.rtsmaxsquadsize = Максимальный размер отряда
rules.rtsminattackweight = Минимальный вес для атаки
@@ -1368,6 +1402,9 @@ rules.title.teams = Команды
rules.title.planet = Планета
rules.lighting = Освещение
rules.fog = Туман войны
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Огонь
rules.anyenv = <Любая>
rules.explosions = Урон от взрывов блоков/единиц
@@ -1376,6 +1413,7 @@ rules.weather = Погода
rules.weather.frequency = Периодичность:
rules.weather.always = Всегда
rules.weather.duration = Длительность:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1518,6 +1556,8 @@ block.graphite-press.name = Графитный пресс
block.multi-press.name = Мульти-пресс
block.constructing = {0} [lightgray](Строится)
block.spawn.name = Точка появления врагов
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Ядро: «Осколок»
block.core-foundation.name = Ядро: «Штаб»
block.core-nucleus.name = Ядро: «Атом»
@@ -1775,6 +1815,7 @@ block.electric-heater.name = Электрический нагреватель
block.slag-heater.name = Шлаковый нагреватель
block.phase-heater.name = Фазовый нагреватель
block.heat-redirector.name = Тепловой перенаправитель
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Тепловой маршрутизатор
block.slag-incinerator.name = Мусоросжигательная печь
block.carbide-crucible.name = Карбидовый тигель
@@ -1822,6 +1863,7 @@ block.chemical-combustion-chamber.name = Химическая камера сг
block.pyrolysis-generator.name = Пиролизный генератор
block.vent-condenser.name = Жерловой конденсатор
block.cliff-crusher.name = Дробитель скал
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Плазменный бур
block.large-plasma-bore.name = Большой плазменный бур
block.impact-drill.name = Ударная дрель
@@ -2051,6 +2093,10 @@ block.phase-wall.description = Защищает постройки от враж
block.phase-wall-large.description = Защищает постройки от вражеских снарядов, отражая большинство пуль при ударе.
block.surge-wall.description = Защищает постройки от вражеских снарядов, периодически выпускает электрический разряд при ударе.
block.surge-wall-large.description = Защищает постройки от вражеских снарядов, периодически выпускает электрический разряд при ударе.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Стена, которую можно открыть или закрыть нажатием.
block.door-large.description = Стена, которую можно открыть или закрыть нажатием.
block.mender.description = Периодически ремонтирует блоки в непосредственной близости.\nОпционально использует кремний для увеличения дальности и эффективности.
@@ -2178,6 +2224,7 @@ block.electric-heater.description = Нагревает блоки напроти
block.slag-heater.description = Нагревает блоки напротив себя. Требует шлак для работы.
block.phase-heater.description = Нагревает блоки напротив себя. Требует фазовую ткань для работы.
block.heat-redirector.description = Перенаправляет накопленное тепло на другие блоки.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Распределяет накопленное тепло в трех направлениях.
block.electrolyzer.description = Преобразует воду в водород и озон.
block.atmospheric-concentrator.description = Концентрирует азот из атмосферы. Требует тепло для работы.
@@ -2190,6 +2237,7 @@ block.vent-condenser.description = Конденсирует воду из газ
block.plasma-bore.description = При размещении напротив стены с рудой, постоянно выводит предметы. Требует небольшое количество энергии для работы.
block.large-plasma-bore.description = Большой плазменный бур. Способен добывать вольфрам и торий. Требует водород и энергию для работы.
block.cliff-crusher.description = Дробит стены, постоянно выводя песок. Требует энергию для работы. Эффективность зависит от типа стены.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = При размещении на соответствующей руде, постоянно выводит предметы очередями. Требует энергию и воду для работы.
block.eruption-drill.description = Усовершенствованная ударная дрель. Способна добывать торий. Требует водород для работы.
block.reinforced-conduit.description = Перемещает жидкости вперед. Не принимает ввод по бокам.
@@ -2350,6 +2398,7 @@ lst.getflag = Проверяет, установлен ли глобальный
lst.setprop = Устанавливает свойство единицы или постройки.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2520,6 +2569,7 @@ unitlocate.building = Переменная для записи обнаруже
unitlocate.outx = Вывод X координаты.
unitlocate.outy = Вывод Y координаты.
unitlocate.group = Группа построек для поиска.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Остановка движения, но продолжение строительства/копания.\nСостояние по умолчанию.
lenum.stop = Остановка движения/копания/строительства.
diff --git a/core/assets/bundles/bundle_sr.properties b/core/assets/bundles/bundle_sr.properties
index 6e6cf07481..6298ae6012 100644
--- a/core/assets/bundles/bundle_sr.properties
+++ b/core/assets/bundles/bundle_sr.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Omogućeno
mod.disabled = [scarlet]Onemogućeno
mod.multiplayer.compatible = [gray]Podesan sa multiplejerom
mod.disable = Onemogući
+mod.version = Version:
mod.content = Sadržaj:
mod.delete.error = Nemoguće izbrisati mod, datoteka je možda u upotrebi.
mod.incompatiblegame = [red]Zastarela Igra
@@ -193,6 +194,7 @@ campaign.select = Izaberite Početnu Kampanju
campaign.none = [lightgray]Izaberite planetu gde bi ste počeli.\nOvo se može promeniti u svakom trenutku.
campaign.erekir = [accent]Preporučeno za novije igrače.[]\n\nNovije, poboljšane funkcije. Uglavnom linearni tok kampanje.\n\nKvalitetniji doživljaji i mape. Veća težina.
campaign.serpulo = [scarlet]Nije preporučeno za novije igrače.[]\n\nStarije funkcije; renesansno iskustvo. Otvoreniji pristup.\n\nMoguće je da mape i tok kampanje nisu glatki i balansirani.
+campaign.difficulty = Difficulty
completed = [accent]Završeno.
techtree = Drvo Tehnologija
techtree.select = Izbor Drveća Tehnologija
@@ -293,13 +295,14 @@ disconnect.error = Greška u povezivanju.
disconnect.closed = Connection closed.
disconnect.timeout = Timed out.
disconnect.data = Neuspešno učitavanje podataka!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Ne može se pridružiti igri ([accent]{0}[]).
connecting = [accent]Povezivanje...
reconnecting = [accent]Ponovno povezivanje...
connecting.data = [accent]Učitavanje podataka...
server.port = Port:
-server.addressinuse = Adresa je već u upotrebi!
server.invalidport = Invalid port number!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [scarlet]Error hosting server.
save.new = Novi Snimak
save.overwrite = Da li ste sigurni da želite da prerežete\novaj snimak?
@@ -352,6 +355,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -495,6 +499,7 @@ waves.units.show = Pokaži Sve
wavemode.counts = količina
wavemode.totals = ukupno
wavemode.health = snaga
+all = All
editor.default = [lightgray]
details = Detalji...
@@ -664,7 +669,6 @@ requirement.capture = Zauzmi {0}
requirement.onplanet = Kontroliši Sektor Na {0}
requirement.onsector = Sleti Na Sektor: {0}
launch.text = Lansiraj
-research.multiplayer = Only the host can research items.
map.multiplayer = Only the host can view sectors.
uncover = Razotkrij
configure = Konfiguriši Zalihe
@@ -734,6 +738,7 @@ error.mapnotfound = Datoteka mape nije pronađena!
error.io = I/O mrežna greška.
error.any = Nepoznata greška u mreži.
error.bloom = Failed to initialize bloom.\nYour device may not support it.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Kiša
weather.snowing.name = Sneg
@@ -784,6 +789,11 @@ threat.medium = Srednje
threat.high = Visoko
threat.extreme = Ekstremno
threat.eradication = Istrebljenje
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planete
@@ -806,9 +816,19 @@ sector.fungalPass.name = Gljivični Prolaz
sector.biomassFacility.name = Biosintetičko Postrojenje
sector.windsweptIslands.name = Vetrovita Ostrva
sector.extractionOutpost.name = Lansirna Utvrda
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetarno Lansirni Terminal
sector.coastline.name = Obala
sector.navalFortress.name = Pomorska Tvrđava
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Savršena lokacija za ponovni početak. Niska neprijateljska pretnja, ali i mala količina resursa.\nSakupite sav bakar i svo olovo koje možete. Nastavite dalje.
sector.frozenForest.description = Čak i ovde, u blizini planina, spore su se proširile… ledene temperature ih neće večno zadržati.\n\nZapočnite upotrebu elektriciteta. Graditei sagorevne generatore. Naučite primenu popravljača.
@@ -828,6 +848,18 @@ sector.impact0078.description = Ovde padoše ostaci međuzvezdane transportne le
sector.planetaryTerminal.description = Krajnji cilj.\n\nOva obalska struktura ima objekat sposoban za lansiranje Jezgara na druge planete. Maksimalno je čuvan.\n\nProizvodite brodove. Elimiši neprijatelja što brže moguće. Sagradi Interplanetarni Akcelerator po osvanjanju sektora.
sector.coastline.description = Ostaci tehnologije pomorskih jedinica su detektovani u ovom sektoru. Odbijte neprijateljske napade, zauzmite ovaj sektor, i preuzmite tehnologiju.
sector.navalFortress.description = Neprijatelj je sagradio bazu na dalekom, prirodno-formiranom ostrvu. Uništite ovu bazu. Preuzmite njihovu naprednu pomorsku tehnologiju, i izuči te je.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = Žačetak
sector.aegis.name = Okrilje
@@ -1026,6 +1058,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1090,6 +1123,8 @@ bullet.healamount = [stat]{0}[lightgray] direktna popravka
bullet.multiplier = [stat]{0}[lightgray]x umnožavanje municije
bullet.reload = [stat]{0}[lightgray]x brzina paljbe
bullet.range = [stat]{0}[lightgray] domet
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blokova
unit.blockssquared = blokova²
@@ -1150,12 +1185,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI Skala
setting.uiscale.description = Restartovanje je zahtevano da bi se učitale promene.
setting.swapdiagonal.name = Uvek Dijagonalno Postavljanje
-setting.difficulty.training = Training
-setting.difficulty.easy = Easy
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Hard
-setting.difficulty.insane = Insane
-setting.difficulty.name = Difficulty:
setting.screenshake.name = Screen Shake
setting.bloomintensity.name = Bloom Intezitet
setting.bloomblur.name = Bloom Magliranje
@@ -1245,6 +1274,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Ponovo Sagradi Region
keybind.schematic_select.name = Izaberi Region
keybind.schematic_menu.name = Menu Šema
@@ -1322,12 +1352,16 @@ rules.wavetimer = Talasna Štoperica
rules.wavesending = Slanje Talasa
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Talasi
rules.airUseSpawns = Air units use spawn points
rules.attack = Mod Napada
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI [red](Nedovršeno)
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Minimalna Veličina Odreda
rules.rtsmaxsquadsize = Maksimalna Veličina Odreda
rules.rtsminattackweight = Minimalna Težina Napada
@@ -1370,6 +1404,9 @@ rules.title.teams = Timovi
rules.title.planet = Planeta
rules.lighting = Osvetljenje
rules.fog = Magla Rata
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Plamen
rules.anyenv =
rules.explosions = Blokovna/Jedinična Šteta Eksplozije
@@ -1378,6 +1415,7 @@ rules.weather = Vreme
rules.weather.frequency = Učestalost:
rules.weather.always = Stalno
rules.weather.duration = Dužina:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1520,6 +1558,8 @@ block.graphite-press.name = Grafitna Presa
block.multi-press.name = Multi-Presa
block.constructing = {0} [lightgray](U izgradnji)
block.spawn.name = Mesto Tvorbe Neprijatelja
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Jezgro: Krhotina
block.core-foundation.name = Jezgro: Temelj
block.core-nucleus.name = Jezgro: Nukleus
@@ -1777,6 +1817,7 @@ block.electric-heater.name = Električna Grejalica
block.slag-heater.name = Šljakna Grejalica
block.phase-heater.name = Fazna Grejalica
block.heat-redirector.name = Preusmerivač Toplote
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Grejni Ruter
block.slag-incinerator.name = Šljakna Spalionica
block.carbide-crucible.name = Karbidna Topionica
@@ -1824,6 +1865,7 @@ block.chemical-combustion-chamber.name = Elektrana Hemijskog Sagorevanja
block.pyrolysis-generator.name = Pirolizna Elektrana
block.vent-condenser.name = Gejzirni Kondezator
block.cliff-crusher.name = Planinolom
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plazma Bušilica
block.large-plasma-bore.name = Velika Plazma Bušilica
block.impact-drill.name = Udarna Drobilica
@@ -2052,6 +2094,10 @@ block.phase-wall.description = Štiti građevine od neprijateljskih projektila,
block.phase-wall-large.description = Štiti građevine od neprijateljskih projektila, odbijajući većinu metaka pri udaru.
block.surge-wall.description = Štiti građevine od neprijateljskih projektila, povremeno uzrokavajući električne udare pri kontaktu.
block.surge-wall-large.description = Štiti građevine od neprijateljskih projektila, povremeno uzrokavajući električne udare pri kontaktu.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Zid koji se može otvarati i zatvarati.
block.door-large.description = Zid koji se može otvarati i zatvarati.
block.mender.description = Povremeno popravlja blokove u okolini.\nMože koristiti silicijum da poveća domet i efikasnost.
@@ -2179,6 +2225,7 @@ block.electric-heater.description = Greje usmerene blokove. Zahteva veliku koli
block.slag-heater.description = Greje usmerene blokove. Zahteva šljaku.
block.phase-heater.description = Greje usmerene blokove. Zahteva faznu tkaninu.
block.heat-redirector.description = Preusmerava sakupljenu toplotu u druge blokove.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Deli vodu na gasove vodonik i ozon.
block.atmospheric-concentrator.description = Koncentriše azot iz atmosfere. Zahteva toplotu.
@@ -2191,6 +2238,7 @@ block.vent-condenser.description = Kondezuje ventilacione gasove u vodu. Zahteva
block.plasma-bore.description = Kada je postavljeno u smeru zidne rude, beskonačno ispušta materijale. Zahteva malo energije.
block.large-plasma-bore.description = Velika plazma bušilica. Može iskopavati volfram i torium. Zahteva vodonik i energiju.
block.cliff-crusher.description = Beskonačno ispušta pesak lomeći stene. Zahteva energiju. Efikasnost zavisi od vrste zida.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = Kada je postavljeno na rudi, beskonačno ispušta materijale u bačvama. Zahteva energiju i vodu.
block.eruption-drill.description = Poboljšana udarna drobilica. Može iskopavati torijum. Zahteva vodonik.
block.reinforced-conduit.description = Usmerava tečnosti napred. Ne prihvata unos sa strane od blokova koje nisu cevi.
@@ -2351,6 +2399,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2521,6 +2570,7 @@ unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Grupa građevina koja se traži.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Zaustavi kretanje, ali nastavi gradnju/iskopavanje.\nThe default state.
lenum.stop = Zaustavi kretanje/gradnju/iskopavanje.
diff --git a/core/assets/bundles/bundle_sv.properties b/core/assets/bundles/bundle_sv.properties
index a9cb83d9fb..f26cd10739 100644
--- a/core/assets/bundles/bundle_sv.properties
+++ b/core/assets/bundles/bundle_sv.properties
@@ -141,6 +141,7 @@ mod.enabled = [lightgray]Aktiverad
mod.disabled = [scarlet]Inaktiverad
mod.multiplayer.compatible = [gray]Flerspelar Kompatibel
mod.disable = Inaktivera
+mod.version = Version:
mod.content = Innehåll:
mod.delete.error = Kunde inte ta bort modden. Filen kanske används.
mod.incompatiblegame = [red]Outdated Game
@@ -190,6 +191,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Avklarad
techtree = Teknologiträd
techtree.select = Teknologiträd Väljare
@@ -289,13 +291,14 @@ disconnect.error = Kopplingsfel.
disconnect.closed = Koppling stängd.
disconnect.timeout = Timed out.
disconnect.data = Failed to load world data!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Unable to join game ([accent]{0}[]).
connecting = [accent]Ansluter...
reconnecting = [accent]Reconnecting...
connecting.data = [accent]Loading world data...
server.port = Port:
-server.addressinuse = Address already in use!
server.invalidport = Ogiltigt portnummer!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Error hosting server: [accent]{0}
save.new = Ny sparfil
save.overwrite = Are you sure you want to overwrite\nthis save slot?
@@ -348,6 +351,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -490,6 +494,7 @@ waves.units.show = Show All
wavemode.counts = counts
wavemode.totals = totals
wavemode.health = health
+all = All
editor.default = [lightgray]
details = Details...
@@ -657,7 +662,6 @@ requirement.capture = Capture {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Launch
-research.multiplayer = Only the host can research items.
map.multiplayer = Only the host can view sectors.
uncover = Uncover
configure = Configure Loadout
@@ -725,6 +729,7 @@ error.mapnotfound = Map file not found!
error.io = Network I/O error.
error.any = Okänt nätverksfel.
error.bloom = Failed to initialize bloom.\nYour device may not support it.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Rain
weather.snowing.name = Snow
@@ -774,6 +779,11 @@ threat.medium = Medium
threat.high = High
threat.extreme = Extreme
threat.eradication = Eradication
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planets
planet.serpulo.name = Serpulo
@@ -795,9 +805,19 @@ sector.fungalPass.name = Svamppass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on.
sector.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders.
@@ -817,6 +837,18 @@ sector.impact0078.description = Here lie remnants of the interstellar transport
sector.planetaryTerminal.description = The final target.\n\nThis coastal base contains a structure capable of launching Cores to local planets. It is extremely well guarded.\n\nProduce naval units. Eliminate the enemy as quickly as possible. Research the launch structure.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
sector.lake.name = Lake
@@ -1013,6 +1045,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1077,6 +1110,8 @@ bullet.healamount = [stat]{0}[lightgray] direct repair
bullet.multiplier = [stat]{0}[lightgray]x ammo multiplier
bullet.reload = [stat]{0}[lightgray]x fire rate
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = block
unit.blockssquared = blocks²
@@ -1137,12 +1172,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI Scaling[lightgray] (requires restart)[]
setting.uiscale.description = Restart required to apply changes.
setting.swapdiagonal.name = Always Diagonal Placement
-setting.difficulty.training = Träning
-setting.difficulty.easy = Lätt
-setting.difficulty.normal = Normalt
-setting.difficulty.hard = Svårt
-setting.difficulty.insane = Galet
-setting.difficulty.name = Svårighetsgrad:
setting.screenshake.name = Skärmskak
setting.bloomintensity.name = Bloom Intensity
setting.bloomblur.name = Bloom Blur
@@ -1232,6 +1261,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Select Region
keybind.schematic_menu.name = Schematic Menu
@@ -1309,12 +1339,16 @@ rules.wavetimer = Vågtimer
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Vågor
rules.airUseSpawns = Air units use spawn points
rules.attack = Attack Mode
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Squad Size
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min Attack Weight
@@ -1357,6 +1391,9 @@ rules.title.teams = Teams
rules.title.planet = Planet
rules.lighting = Lighting
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fire
rules.anyenv =
rules.explosions = Block/Unit Explosion Damage
@@ -1365,6 +1402,7 @@ rules.weather = Weather
rules.weather.frequency = Frequency:
rules.weather.always = Always
rules.weather.duration = Duration:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1505,6 +1543,8 @@ block.graphite-press.name = Grapfitpress
block.multi-press.name = Multi-Press
block.constructing = {0} [lightgray](Constructing)
block.spawn.name = Enemy Spawn
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Core: Shard
block.core-foundation.name = Core: Foundation
block.core-nucleus.name = Core: Nucleus
@@ -1762,6 +1802,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1809,6 +1850,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2034,6 +2076,10 @@ block.phase-wall.description = A wall coated with special phase-based reflective
block.phase-wall-large.description = A wall coated with special phase-based reflective compound. Deflects most bullets upon impact.\nSpans multiple tiles.
block.surge-wall.description = An extremely durable defensive block.\nBuilds up charge on bullet contact, releasing it randomly.
block.surge-wall-large.description = An extremely durable defensive block.\nBuilds up charge on bullet contact, releasing it randomly.\nSpans multiple tiles.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = A small door. Can be opened or closed by tapping.
block.door-large.description = A large door. Can be opened and closed by tapping.\nSpans multiple tiles.
block.mender.description = Periodically repairs blocks in its vicinity. Keeps defenses repaired in-between waves.\nOptionally uses silicon to boost range and efficiency.
@@ -2161,6 +2207,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2173,6 +2220,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2331,6 +2379,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2483,6 +2532,7 @@ unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Don't move, but keep building/mining.\nThe default state.
lenum.stop = Stop moving/mining/building.
lenum.unbind = Completely disable logic control.\nResume standard AI.
diff --git a/core/assets/bundles/bundle_th.properties b/core/assets/bundles/bundle_th.properties
index 1fe1ed195a..6fee96457e 100644
--- a/core/assets/bundles/bundle_th.properties
+++ b/core/assets/bundles/bundle_th.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]เปิดใช้งาน
mod.disabled = [scarlet]ปิดใช้งาน
mod.multiplayer.compatible = [gray]ใช้งานได้กับโหมดผู้เล่นหลายคน
mod.disable = ปิดใช้งาน
+mod.version = Version:
mod.content = เนื้อหา:
mod.delete.error = ไม่สามารถลบม็อดออกได้ ไฟล์อาจอยู่ในระหว่างการใช้งาน
mod.incompatiblegame = [red]เกมล้าสมัย
@@ -193,6 +194,7 @@ campaign.select = เลือกเนื้อเรื่องที่จ
campaign.none = [lightgray]โปรดเลือกดาวที่จะเริ่มต้น\nคุณสามารถสลับกลับไปตอนไหนก็ได้
campaign.erekir = เนื้อหาที่ใหม่กว่าและขัดเกลามามากกว่า เนื้อเรื่องดำเนินเป็นเส้นตรงโดยซะส่วนใหญ่\n\nแมพมีคุณภาพที่ดีกว่า ให้ประสบการณ์โดยรวมที่มีคุณภาพ
campaign.serpulo = ประสบการณ์สุดคลาสสิก เนื้อหาเยอะกว่า เปิดกว้างมากกว่า\n\nแมพและกลไกของแคมเปญอาจไม่สมดุล ขัดเกลามาน้อยกว่า
+campaign.difficulty = Difficulty
completed = [accent]วิจัยแล้ว
techtree = ต้นไม้เทคโนโลยี
techtree.select = เลือกต้นไม้แห่งเทคโนโลยี
@@ -255,7 +257,7 @@ trace = แกะรอยผู้เล่น
trace.playername = ชื่อผู้เล่น: [accent]{0}
trace.ip = IP: [accent]{0}
trace.id = ID: [accent]{0}
-trace.language = Language: [accent]{0}
+trace.language = ภาษา: [accent]{0}
trace.mobile = ไคลเอนต์โทรศัพท์: [accent]{0}
trace.modclient = ไคลเอนต์ปรับแต่ง: [accent]{0}
trace.times.joined = ครั้งที่เข้า: [accent]{0}
@@ -293,13 +295,14 @@ disconnect.error = การเชื่อมต่อมีปัญหา
disconnect.closed = การเชื่อมต่อถูกปิดแล้ว
disconnect.timeout = หมดเวลา
disconnect.data = การโหลดข้อมูลของโลกผิดพลาด!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = ไม่สามารถเข้าร่วมเซิร์ฟเวอร์ ([accent]{0}[])
connecting = [accent]กำลังเชื่อมต่อ...
reconnecting = [accent]กำลังเชื่อมต่อใหม่...
connecting.data = [accent]กำลังโหลดข้อมูลของโลก ...
server.port = พอร์ต:
-server.addressinuse = มีคนใช้ที่อยู่นี้อยู่แล้ว!
server.invalidport = เลขพอร์ตไม่ถูกต้อง!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]การโฮสต์เซิร์ฟเวอร์ผิดพลาด
save.new = เซฟใหม่
save.overwrite = คุณแน่ใจหรือว่าจะเซฟทับ\nเซฟนี้?
@@ -341,23 +344,24 @@ open = เปิด
customize = ตั้งค่ากฎ
cancel = ยกเลิก
command = สั่งการ
-command.queue = [lightgray][Queuing]
+command.queue = คิว
command.mine = ขุด
command.repair = ซ่อมแซม
command.rebuild = สร้างใหม่
command.assist = ช่วยเหลือผู้เล่น
command.move = ขยับ
command.boost = บูสต์
-command.enterPayload = Enter Payload Block
-command.loadUnits = Load Units
-command.loadBlocks = Load Blocks
-command.unloadPayload = Unload Payload
-stance.stop = Cancel Orders
-stance.shoot = Stance: Shoot
-stance.holdfire = Stance: Hold Fire
-stance.pursuetarget = Stance: Pursue Target
-stance.patrol = Stance: Patrol Path
-stance.ram = Stance: Ram\n[lightgray]Straight line movement, no pathfinding
+command.enterPayload = เข้าบล็อกบรรทุก
+command.loadUnits = โหลดยูนิต
+command.loadBlocks = โหลดบล็อก
+command.unloadPayload = วางสิ่งบรรทุก
+command.loopPayload = วนซำ้การขนถ่ายยูนิต
+stance.stop = ยกเลิกคำสั่ง
+stance.shoot = ท่าที: ยิง
+stance.holdfire = ท่าที: หยุดยิง
+stance.pursuetarget = ท่าที: ไล่ตามเป้าหมาย
+stance.patrol = ท่าที: ลาดตระเวน
+stance.ram = ท่าที: พุ่งชน\n[lightgray]ขยับเป็นเส้นตรงโดยที่ไม่มีการตรวจสอบเส้นทาง
openlink = เปิดลิ้งค์
copylink = คัดลอกลิ้งค์
back = กลับ
@@ -438,12 +442,12 @@ editor.waves = คลื่น
editor.rules = กฎ
editor.generation = เจนเนอเรชั่น
editor.objectives = เป้าหมาย
-editor.locales = Locale Bundles
-editor.worldprocessors = World Processors
-editor.worldprocessors.editname = Edit Name
-editor.worldprocessors.none = [lightgray]No world processor blocks found!\nAdd one in the map editor, or use the \ue813 Add button below.
-editor.worldprocessors.nospace = No free space to place a world processor!\nDid you fill the map with structures? Why would you do this?
-editor.worldprocessors.delete.confirm = Are you sure you want to delete this world processor?\n\nIf it is surrounded by walls, it will be replaced by an environmental wall.
+editor.locales = ชุดภาษาท้องถิ่น
+editor.worldprocessors = ตัวประมวลผลโลก
+editor.worldprocessors.editname = แก้ไขชื่อ
+editor.worldprocessors.none = [lightgray]ไม่พบตัวประมวลผลโลกในแมพ!\nสามารถไปเพิ่มในตัวแก้ไขแมพ หรือกดปุ่ม \ue813 เพิ่ม ด้านล่าง
+editor.worldprocessors.nospace = ไม่มีพื้นที่ให้วางตัวประมวลผลโลก!\nนี่คุณวางสิ่งก่อสร้างไว้ทั่วแมพเลยหรอ? ทำไปทำไม?
+editor.worldprocessors.delete.confirm = คุณแน่ใจหรือว่าจะลบตัวประมวลผลโลกนี้?\n\nถ้าหากมันถูกล้อมด้วยกำแพงธรรมชาติ มันจะถูกแทนที่ด้วยกำแพงนั้น
editor.ingame = แก้ไขในเกม
editor.playtest = เล่นทดสอบ
editor.publish.workshop = เผยแพร่บนเวิร์กช็อป
@@ -495,13 +499,14 @@ waves.units.show = แสดงทั้งหมด
wavemode.counts = จำนวน
wavemode.totals = ทั้งหมด
wavemode.health = พลังชีวิต
+all = ทั้งหมด
editor.default = [lightgray]<ค่าเริ่มต้น>
details = รายละเอียด...
edit = แก้ไข...
variables = ตัวแปร
-logic.clear.confirm = Are you sure you want to clear all code from this processor?
-logic.globals = Built-in Variables
+logic.clear.confirm = คุณแน่ใจหรือว่าจะเคลียร์โค้ดทั้งหมดของตัวประมวลผลนี้?
+logic.globals = ตัวแปรค่าเริ่มต้น
editor.name = ชื่อ:
editor.spawn = สร้างยูนิต
editor.removeunit = ลบยูนิต
@@ -510,22 +515,22 @@ editor.errorload = โหลดไฟล์ผิดพลาด
editor.errorsave = เซฟไฟล์ผิดพลาด
editor.errorimage = ไฟล์นั้นคือไฟล์รูป ไม่ใช่แมพ\n\nหากคุณต้องการนำเข้าไฟล์แมพจากเวอร์ชั่น 3.5/build 40 ใช้ปุ่ม 'นำเข้าแมพรูปแบบเก่า' ในตัวแก้ไขแมพ
editor.errorlegacy = แมพนี้เก่าเกินไปและใช้รูปแบบแมพแบบเก่าที่ไม่สนับสนุนแล้ว
-editor.errornot = นี่ไม่ใช้ไฟล์แมพ
+editor.errornot = นี่ไม่ใช่ไฟล์แมพ
editor.errorheader = ไฟล์แมพนี้เสียหรือไม่ถูกต้อง
editor.errorname = แมพไม่มีการกำหนดชื่อ คุณกำลังพยายามโหลดไฟล์เซฟอยู่หรือไม่?
-editor.errorlocales = Error reading invalid locale bundles.
+editor.errorlocales = เกิดข้อผิดพลาดจากการอ่านชุดภาษาที่ไม่ถูกต้อง
editor.update = อัปเดต
editor.randomize = สุ่ม
editor.moveup = ขยับขึ้น
editor.movedown = ขยับลง
editor.copy = คัดลอก
editor.apply = ใช้งาน
-editor.generate = การกำเนิด
+editor.generate = เจนเนอเรท
editor.sectorgenerate = สร้างเซ็กเตอร์
editor.resize = เปลี่ยนขนาด
editor.loadmap = โหลดแมพ
editor.savemap = เซฟแมพ
-editor.savechanges = [scarlet]You have unsaved changes!\n\n[]Do you want to save them?
+editor.savechanges = [scarlet]คุณมีการแก้ไขที่ยังไม่ได้เซฟ!\n\n[]คุณต้องการที่จะเซฟมันหรือไม่?
editor.saved = เซฟเรียบร้อย!
editor.save.noname = แมพของคุณไม่มีชื่อ! สามารถตั้งชื่อได้ในเมนู 'ข้อมูลแมพ'
editor.save.overwrite = แมพของคุณไปทับซ้อนกับแมพค่าเริ่มต้น! เปลี่ยนชื่อได้ในเมนู 'ข้อมูลแมพ'
@@ -589,7 +594,7 @@ filter.clear = เคลียร์
filter.option.ignore = เพิกเฉย
filter.scatter = กระจาย
filter.terrain = พื้นผิว
-filter.logic = Logic
+filter.logic = ลอจิก
filter.option.scale = มาตราส่วน
filter.option.chance = โอกาส
@@ -613,25 +618,26 @@ filter.option.floor2 = พื้นชั้นสอง
filter.option.threshold2 = เกณฑ์ชั้นสอง
filter.option.radius = รัศมี
filter.option.percentile = เปอร์เซ็นต์ไทล์
-filter.option.code = Code
-filter.option.loop = Loop
+filter.option.code = โค้ดคำสั่ง
+filter.option.loop = วนลูป
+#not translating all these yet: still unstable
locales.info = Here, you can add locale bundles for specific languages to your map. In locale bundles, each property has a name and a value. These properties can be used by world processors and objectives using their names. They support text formatting (replacing placeholders with actual values).\n\n[cyan]Example property:\n[]name: [accent]timer[]\nvalue: [accent]Example timer, time left: {0}[]\n\n[cyan]Usage:\n[]Set it as objective's text: [accent]@timer\n\n[]Print it in a world processor:\n[accent]localeprint "timer"\nformat time\n[gray](where time is a separately calculated variable)
-locales.deletelocale = Are you sure you want to delete this locale bundle?
-locales.applytoall = Apply Changes To All Locales
-locales.addtoother = Add To Other Locales
-locales.rollback = Rollback to last applied
-locales.filter = Property filter
-locales.searchname = Search name...
-locales.searchvalue = Search value...
-locales.searchlocale = Search locale...
-locales.byname = By name
-locales.byvalue = By value
+locales.deletelocale = คุณแน่ใจหรือว่าจะลบชุดภาษาท้องถิ่นนี้?
+locales.applytoall = เพิ่มการเปลี่ยนแปลงไปยังทุกค่าภาษา
+locales.addtoother = เพิ่มไปยังภาษาอื่น
+locales.rollback = ย้อนกลับไปเมื่อการใช้งานที่แล้ว
+locales.filter = ตัวกรองค่า
+locales.searchname = ค้นหาชื่อ...
+locales.searchvalue = ค้นหาค่า...
+locales.searchlocale = ค้นหาภาษา...
+locales.byname = ตามชื่อ
+locales.byvalue = ตามค่า
locales.showcorrect = Show properties that are present in all locales and have unique values everywhere
locales.showmissing = Show properties that are missing in some locales
locales.showsame = Show properties that have same values in different locales
-locales.viewproperty = View in all locales
-locales.viewing = Viewing property "{0}"
-locales.addicon = Add Icon
+locales.viewproperty = ดูในทุกค่าภาษา
+locales.viewing = กำลังดูค่า "{0}"
+locales.addicon = เพิ่มไอคอน
width = กว้าง:
height = สูง:
@@ -664,7 +670,6 @@ requirement.capture = ยึดครอง {0}
requirement.onplanet = ควบคุมเซ็กเตอร์บน {0}
requirement.onsector = ลงจอดบนเซ็กเตอร์: {0}
launch.text = ลุย!
-research.multiplayer = โฮสต์เท่านั้นที่วิจัยได้
map.multiplayer = โฮสต์เท่านั้นที่สามารถดูเซ็กเตอร์ได้
uncover = เปิดเผย
configure = ตั้งค่าทรัพยากร
@@ -682,12 +687,12 @@ objective.destroycore.name = ทำลายแกนกลาง
objective.commandmode.name = โหมดสั่งการ
objective.flag.name = ธง
marker.shapetext.name = ข้อความในรูปทรง
-marker.point.name = Point
+marker.point.name = จุด
marker.shape.name = รูปทรง
marker.text.name = ข้อความ
-marker.line.name = Line
-marker.quad.name = Quad
-marker.texture.name = Texture
+marker.line.name = เส้นตรง
+marker.quad.name = สี่เหลี่ยม
+marker.texture.name = เทกเจอร์
marker.background = พื้นหลัง
marker.outline = โครงร่าง
objective.research = [accent]วิจัย:\n[]{0}[lightgray]{1}
@@ -733,9 +738,10 @@ error.mapnotfound = ไม่พบไฟล์แมพ
error.io = ข้อผิดพลาด I/O ของเครือข่าย
error.any = ข้อผิดพลาด: เครือข่ายที่ไม่รู้จัก
error.bloom = ไม่สามารถเริ่มต้นบลูมได้\nอุปกรณ์ของคุณอาจไม่รองรับ
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = ฝน
-weather.snowing.name = หิมะ
+weather.snowing.name = หิมะตก
weather.sandstorm.name = พายุทราย
weather.sporestorm.name = พายุสปอร์
weather.fog.name = หมอก
@@ -772,8 +778,8 @@ sector.curlost = เราเสียเซ็กเตอร์!
sector.missingresources = [scarlet]ขาดทรัพยากรในการลงจอด
sector.attacked = เซ็กเตอร์ [accent]{0}[white] ถูกโจมตี!
sector.lost = เราเสียเซ็กเตอร์ [accent]{0}[white]!
-sector.capture = Sector [accent]{0}[white]Captured!
-sector.capture.current = Sector Captured!
+sector.capture = เรายึดครองเซ็กเตอร์ [accent]{0}[white] ได้แล้ว!
+sector.capture.current = เรายึดครองเซ็กเตอร์นี้ได้แล้ว!
sector.changeicon = เปลี่ยนไอคอน
sector.noswitch.title = ไม่สามารถเปลี่ยนเซ็กเตอร์ได้
sector.noswitch = คุณไม่สามารถเปลี่ยนเซ็กเตอร์ได้ระหว่างที่อีกเซ็กเตอร์กำลังถูกโจมตีอยู่\n\nเซ็กเตอร์: [accent]{0}[] บนดาว [accent]{1}[]
@@ -784,6 +790,11 @@ threat.medium = กลาง
threat.high = สูง
threat.extreme = วิบัติภัย
threat.eradication = ทำลายล้าง
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = ดาว
@@ -797,7 +808,7 @@ sector.craters.name = บ่ออุกกาบาต
sector.frozenForest.name = ป่าหนาวเหน็บ
sector.ruinousShores.name = ชายฝั่งพังทลาย
sector.stainedMountains.name = ภูเขาหลากสี
-sector.desolateRift.name = เดโซเลต ริฟต์
+sector.desolateRift.name = รอยแยกอันรกร้าง
sector.nuclearComplex.name = ฐานผลิตนิวเคลียร์
sector.overgrowth.name = โอเวอร์โกรว์ด
sector.tarFields.name = ราบลุ่มน้ำมัน
@@ -806,44 +817,66 @@ sector.fungalPass.name = ทางผ่านฟังกัล
sector.biomassFacility.name = สถานสังเคราะห์ชีวมวล
sector.windsweptIslands.name = หมู่เกาะพหุวายุ
sector.extractionOutpost.name = ด่านส่งทรัพยากร
+sector.facility32m.name = ฐานผลิต 32 M
+sector.taintedWoods.name = ป่ามลทิน
+sector.infestedCanyons.name = หุบเขาอันมัวหมอง
sector.planetaryTerminal.name = ท่าปล่อยจรวดอวกาศยาน
sector.coastline.name = แนวชายฝั่ง
sector.navalFortress.name = ปราการแห่งวารี
+sector.polarAerodrome.name = ฐานบินขั้วโลก
+sector.atolls.name = อะทอลส์
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
-sector.groundZero.description = จุดที่ดีที่สุดในการเริ่มต้นอีกครั้งนึง ศัตรูน้อย ทรัพยากรน้อย\nเก็บ[accent]ตะกั่ว[]และ[accent]ทองแดง[]ให้ได้มากที่สุด\nแล้วลุยต่อ
-sector.frozenForest.description = แม้แต่ที่นี่ ณ ที่ที่อยู่ใกล้ภูเขา [accent]สปอร์[]ก็ยังแพร่มาถึงที่นี่ อากาศอันแสนเย็นเยือกไม่สามารถหยุดยั้งพวกมันได้ตลอดไป\n\nเริ่มต้นการใช้ไฟฟ้า สร้างเครื่องกำเนิดไฟฟ้าเผาไหม้ เรียนรู้ที่จะใช้เครื่องซ่อมแซม
-sector.saltFlats.description = ณ ขอบของทะเลทราย เป็นที่ตั้งของที่ราบเกลือ สามารถพบทรัพยากรบางอย่างได้ที่นี่\n\nศัตรูได้ตั้งฐานเก็บทรัพยากรไว้ที่นี่ ทำลายแกนกลางของพวกมัน อย่าให้มีอะไรเหลือ
-sector.craters.description = มีน้ำขังอยู่ในหลุมอุกกาบาศแห่งนี้ เป็นอนุสรณ์สถานของสงครามเก่าแก่ ยึดพื้นที่นี่มา เก็บทราย เผา[accent]กระจกเมต้า[] ปั๊มน้ำเพื่อมาหล่อเย็นป้อมปืนและเครื่องขุดเจาะ
-sector.ruinousShores.description = ถัดมาจากทะเลทราย เป็นที่ตั้งของชายฝั่ง ที่ครั้งก่อน เคยเป็นที่ตั้งของฐานป้องกันชายฝั่ง ซึ่งทุกทำลายไปซะส่วนใหญ่แล้ว มีเหลือแค่ระบบการป้องกันพื้นฐาน ทุกอย่างที่เหลือถูกทำลายเหลือเพียงแค่ซากเศษเหล็ก\n\nทำการขยายการสำรวจต่อไป ค้นพบกับเทคโนโลยีอีกครั้ง
+sector.groundZero.description = จุดที่ดีที่สุดในการตั้งต้นใหม่อีกครั้งนึง ศัตรูน้อย ทรัพยากรน้อย\nเก็บ[accent]ตะกั่ว[]และ[accent]ทองแดง[]ให้ได้มากที่สุด\nแล้วลุยต่อ
+sector.frozenForest.description = แม้แต่ที่นี่ ณ ที่ที่อยู่ใกล้กับภูเขา [accent]สปอร์[]ก็ยังแพร่มาถึงที่นี่ได้ อากาศอันแสนเย็นเยือกไม่สามารถหยุดยั้งพวกมันได้ตลอดไป\n\nเริ่มต้นการใช้ไฟฟ้า สร้างเครื่องกำเนิดไฟฟ้าเผาไหม้ เรียนรู้ที่จะใช้เครื่องซ่อมแซม
+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.tarFields.description = แนวชายขอบของแหล่งผลิตน้ำมัน อยู่ระหว่างภูเขาและทะเลทราย เป็นหนึ่งในพื้นที่ที่มีแหล่งน้ำมันดินที่ใช้งานได้\nแม้ว่าจะถูกทิ้งร้าง พื้นที่นี้ยังคงมีฐานทัพของศัตรูอยู่ใกล้ๆ อย่าประมาทกับพวกมัน\n\n[lightgray]วิจัยเทคโนโลยีการแปรรูปน้ำมันหากเป็นไปได้
-sector.desolateRift.description = เป็นพื้นที่ที่อันตรายมาก ทรัพยากรมากมาย แต่พื้นที่คับแคบ ความเสี่ยงในการโดนทำลายล้างสูง รีบออกไปจากที่นี่ให้เร็วที่สุด อย่าให้ถูกหลอกโดยระยะเวลาระหว่างการโจมตีของศัตรูที่เว้นไว้นานกว่าปกติ
+sector.overgrowth.description = พื้นที่แห่งนี้ถูกปกคลุมไปด้วยพืชรกร้าง เริ่มเข้าใกล้กับแหล่งต้นกำเนิดของสปอร์มากขึ้น\nศัตรูได้ตั้งฐานเฝ้าระวังไว้ที่นี่ สร้างยูนิตเมส ทำลายฐานทิ้งซะ\nวิจัย[accent]เครื่องพัฒนารุ่นยกกำลัง[]เพื่อผลิตยูนิตขนาดที่ใหญ่ขึ้น
+sector.tarFields.description = ณ แนวชายขอบของแหล่งผลิตน้ำมัน ระหว่างภูเขากับทะเลทราย เป็นหนึ่งในพื้นที่ที่มีแหล่งน้ำมันดินที่ใช้งานได้\nแม้ว่าจะถูกทิ้งร้าง แต่พื้นที่นี้ยังคงมีฐานทัพของศัตรูอยู่ใกล้ๆ อย่าประมาทกับพวกมัน\n\n[lightgray]วิจัยเทคโนโลยีการแปรรูปน้ำมันหากเป็นไปได้
+sector.desolateRift.description = เป็นพื้นที่ที่อันตรายมาก ทรัพยากรมากมาย แต่พื้นที่คับแคบ ความเสี่ยงในการโดนทำลายล้างสูง รีบสร้างฐานป้องกันให้เร็วที่สุด อย่าหลงกลระยะเวลาระหว่างการโจมตีของศัตรูที่เว้นไว้นานกว่าปกติ
sector.nuclearComplex.description = สถานที่ผลิตและแปรรูป[accent]ทอเรี่ยม[]เก่า ถูกทำลายไม่เหลือสิ้น\nวิจัยทอเรี่ยมและวิธีการใช้มัน\n\nศัตรูในบริเวณนี้มีจำนวนมาก คอยตรวจตราหาผู้บุกรุกอยู่ตลอดเวลา
-sector.fungalPass.description = ทางเปลี่ยนผ่านระหว่างพื้นที่เขาสูงกับที่ราบต่ำที่เต็มไปด้วยสปอร์ มีฐานลาดตระเวนขนาดเล็กของศัตรูตั้งอยู่ที่นี่\nทำลายมันซะ\nผลิตยูนิตแด็กเกอร์และครอว์เลอร์ ทำลายแกนกลางทั้งสองไม่ให้เหลือซาก
-sector.biomassFacility.description = แหล่งต้นกำเนิดของสปอร์ ที่นี่คือฐานวิจัยและผลิตสปอร์เริ่มแรก\nวิจัยเทคโนโลยีที่อยู่ภายในนั้น เพาะชำ[accent]สปอร์[]เพื่อเป็นเชื้อเพลิงและใช้ในการผลิตพลาสติก\n\n[gray]เมื่อสถานแห่งนี้ถึงจุดจบลง สปอร์ก็ถูกปล่อยออกมา ไม่มีสิ่งใดในระบบนิเวศท้องถิ่นที่สามารถแข่งขันกับ\nสิ่งมีชีวิตที่แพร่กระจายในระดับนี้ได้
+sector.fungalPass.description = ทางเปลี่ยนผ่านระหว่างพื้นที่เขาสูงกับที่ราบต่ำที่เต็มไปด้วยสปอร์ มีฐานลาดตระเวนขนาดเล็กของศัตรูตั้งอยู่ที่นี่\nทำลายมันซะ\nผลิตยูนิตแด็กเกอร์และครอว์เลอร์ ทำลายแกนกลางของศัตรูไม่ให้เหลือซาก
+sector.biomassFacility.description = แหล่งต้นกำเนิดของสปอร์ ที่นี่คือฐานวิจัยและผลิตสปอร์เริ่มแรก\nวิจัยเทคโนโลยีที่อยู่ภายในนั้น เพาะชำ[accent]สปอร์[]เพื่อนำเป็นเชื้อเพลิงและใช้ในการผลิตพลาสติก\n\n[gray]เมื่อสถานแห่งนี้ถึงจุดจบลง สปอร์ก็ถูกปล่อยออกมา ไม่มีสิ่งใดในระบบนิเวศท้องถิ่นที่สามารถแข่งขันกับ\nสิ่งมีชีวิตที่แพร่กระจายในระดับนี้ได้
sector.windsweptIslands.description = เลยแนวชายฝั่งไป จะพบกับหมู่เกาะที่ตั้งอยู่ห่างไกลแห่งนี้ เคยมีบันทึกว่าที่นี่มีโรงงานผลิต[accent]พลาสตาเนี่ยม[]อยู่\n\nทำลายเรือศัตรู สร้างฐานทัพบนเกาะ วิจัยโรงงานพวกนี้
-sector.extractionOutpost.description = ด่านที่อยู่ห่างไกล สร้างโดยศัตรูเพื่อใช้ในการส่งทรัพยากรไปยังฐานทัพอื่น\n\nเทคโนโลยีการส่งไอเท็มข้ามเซ็กเตอร์เป็นสิ่งจำเป็นสำหรับการพิชิตถัดๆ ไป ทำลายด่าน วิจัยฐานส่งของ
+sector.extractionOutpost.description = ด่านที่อยู่ห่างไกล สร้างโดยศัตรูเพื่อใช้ในการขนส่งทรัพยากรไปยังฐานทัพอื่น\n\nเทคโนโลยีการส่งไอเท็มข้ามเซ็กเตอร์เป็นสิ่งที่จำเป็นสำหรับการพิชิตครั้งถัดๆ ไป บุกทำลายด่าน วิจัยฐานส่งของ
sector.impact0078.description = ณ ที่แห่งนี้คือเศษซากของยานขนส่งระหว่างดวงดาวที่เคยเข้ามายังระบบนี้\nเศษซากเหล็กและหิมะปกคลุมไปทั่วทั้งพื้นที่\n\nกอบกู้ซากยานให้ได้มากที่สุด วิจัยเทคโนโลยีทั้งหมดที่ยังเหลือรอด\n\n\n[gray]อย่าประมาทกับฐานทัพศัตรูที่อยู่ใกล้ๆ โดยอันขาด\nศัตรูจะส่งกองกำลังมาโจมตีเรื่อยๆ จนกว่าคุณจะพ่ายแพ้
-sector.planetaryTerminal.description = เป้าหมายสุดท้าย\n\nฐานทัพติดชายหาดนี้มีสิ่งประดิษฐ์ที่สามารถส่งแกนกลางไปยังดาวที่อยู่ใกล้ๆ ได้ ฐานทัพมีการป้องกันที่แน่นหนามาก\n\nผลิตยูนิตเรือ กวาดล้างศัตรูให้เร็วที่สุด วิจัยสิ่งประดิษฐ์นั่น
+sector.planetaryTerminal.description = เป้าหมายสุดท้าย\n\nฐานทัพติดชายหาดนี้มีสิ่งปลูกสร้างที่สามารถส่งแกนกลางไปยังดาวที่อยู่ใกล้เคียงได้ ซึ่งมันมีการป้องกันที่แน่นหนามาก\n\nผลิตยูนิตเรือ กวาดล้างศัตรูให้เร็วที่สุด วิจัยสิ่งประดิษฐ์นั่น
sector.coastline.description = ถัดมาจากที่ราบเกลือ เป็นที่ตั้งของแนวชายฝั่ง พบเศษซากของเทคโนโลยียูนิตเรือที่ล้ำหน้าอยู่ในพื้นที่แห่งนี้\nขับไล่ศัตรูออกไป ยึดพื้นที่นี้มา วิจัยเทคโนโลยีนั้น
-sector.navalFortress.description = ศัตรูได้ตั้งฐานทัพอยู๋บนเกาะห่างไกลที่มีกำแพงธรรมชาติปกป้องฐานเอาไว้ ทำลายฐานทัพ ยึดและวิจัยเทคโนโลยีเรือรบที่ล้ำหน้านั้นมา
+sector.navalFortress.description = ศัตรูได้ตั้งฐานทัพอยู่บนเกาะห่างไกลที่มีกำแพงธรรมชาติปกป้องฐานเอาไว้ ทำลายฐานทัพ ยึดและวิจัยเทคโนโลยีเรือรบที่ล้ำหน้านั้นมา
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = การเริ่มต้น
-sector.aegis.name = เกราะกำบัง
+sector.aegis.name = อีจีส
sector.lake.name = ทะเลสาบสีชาด
-sector.intersect.name = ทางเชื่อมผ่าน
+sector.intersect.name = อินเตอร์เซค
sector.atlas.name = แอตลาส
sector.split.name = สองฝั่ง
sector.basin.name = แอ่งยุบ
sector.marsh.name = บึงหนอง
sector.peaks.name = ยอดเขา
sector.ravine.name = หุบเหว
-sector.caldera-erekir.name = หลุมปล่องภูเขาไฟ
+sector.caldera-erekir.name = แอ่งภูเขาไฟ
sector.stronghold.name = ป้อมปราการ
sector.crevice.name = ร่องลึก
sector.siege.name = การรุมล้อม
-sector.crossroads.name = แบ่งแยก
+sector.crossroads.name = ทางเชื่อม
sector.karst.name = คาสต์
sector.origin.name = ต้นกำเนิด
@@ -985,7 +1018,7 @@ stat.abilities = ทักษะ
stat.canboost = บูสต์ได้
stat.flying = บินได้
stat.ammouse = การใช้กระสุน
-stat.ammocapacity = Ammo Capacity
+stat.ammocapacity = ความจุกระสุน
stat.damagemultiplier = พหุคูณดาเมจ
stat.healthmultiplier = พหุคูณพลังชีวิต
stat.speedmultiplier = พหุคูณความเร็ว
@@ -996,46 +1029,48 @@ stat.immunities = ต่อต้านสถานะ
stat.healing = การรักษา
ability.forcefield = โล่พลังงาน
-ability.forcefield.description = Projects a force shield that absorbs bullets
+ability.forcefield.description = ฉายโล่พลังงานที่ดูดซับกระสุนต่างๆ
ability.repairfield = สนามซ่อมแซม
-ability.repairfield.description = Repairs nearby units
+ability.repairfield.description = ซ่อมแซมยูนิตในรอบข้าง
ability.statusfield = สนามเอฟเฟกต์
-ability.statusfield.description = Applies a status effect to nearby units
-ability.unitspawn = โรงงานผลิต
-ability.unitspawn.description = Constructs units
+ability.statusfield.description = เพิ่มเอฟเฟกต์สถานะให้กับยูนิตรอบข้าง
+ability.unitspawn = โรงงานยูนิต
+ability.unitspawn.description = ก่อสร้างยูนิตออกมาได้
ability.shieldregenfield = สนามรักษาโล่
-ability.shieldregenfield.description = Regenerates shields of nearby units
-ability.movelightning = ปล่อยสายฟ้าเมื่อเคลื่อนที่
-ability.movelightning.description = Releases lightning while moving
-ability.armorplate = Armor Plate
-ability.armorplate.description = Reduces damage taken while shooting
+ability.shieldregenfield.description = ฟื้นฟูรักษาโล่ให้กับยูนิตรอบข้าง
+ability.movelightning = สายฟ้าฟาด
+ability.movelightning.description = ปลดปล่อยสายฟ้าในขณะที่เคลื่อนที่
+ability.armorplate = แผ่นเกราะป้องกัน
+ability.armorplate.description = ลดความเสียหายที่ได้รับในขณะที่ยิง
ability.shieldarc = โล่พลังงานโค้ง
-ability.shieldarc.description = Projects a force shield in an arc that absorbs bullets
+ability.shieldarc.description = ฉายโล่พลังงานแบบโค้งงอที่ดูดซับกระสุนต่างๆ
ability.suppressionfield = สนามระงับการฟื้นฟู
-ability.suppressionfield.description = Stops nearby repair buildings
+ability.suppressionfield.description = ระงับยั้บยั้งการทำงานของเครื่องซ่อมแซมของทีมศัตรูที่อยู่ใกล้เคียง
ability.energyfield = สนามพลังงาน
-ability.energyfield.description = Zaps nearby enemies
-ability.energyfield.healdescription = Zaps nearby enemies and heals allies
-ability.regen = Regeneration
-ability.regen.description = Regenerates own health over time
-ability.liquidregen = Liquid Absorption
-ability.liquidregen.description = Absorbs liquid to heal itself
-ability.spawndeath = Death Spawns
-ability.spawndeath.description = Releases units on death
-ability.liquidexplode = Death Spillage
-ability.liquidexplode.description = Spills liquid on death
-ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
-ability.stat.regen = [stat]{0}[lightgray] health/sec
-ability.stat.shield = [stat]{0}[lightgray] shield
-ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
-ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
-ability.stat.cooldown = [stat]{0} sec[lightgray] cooldown
-ability.stat.maxtargets = [stat]{0}[lightgray] max targets
-ability.stat.sametypehealmultiplier = [stat]{0}%[lightgray] same type repair amount
-ability.stat.damagereduction = [stat]{0}%[lightgray] damage reduction
-ability.stat.minspeed = [stat]{0} tiles/sec[lightgray] min speed
-ability.stat.duration = [stat]{0} sec[lightgray] duration
-ability.stat.buildtime = [stat]{0} sec[lightgray] build time
+ability.energyfield.description = ช็อตไฟฟ้าศัตรูที่อยู่รอบข้าง
+ability.energyfield.healdescription = ช็อตไฟฟ้าศัตรูที่อยู่รอบข้างและฟื้นฟูรักษาพันธมิตร
+ability.regen = การฟื้นฟู
+ability.regen.description = ฟื้นฟูสถานะสุขภาพและพลังชีวิตของตัวเองเป็นระยะๆ
+ability.liquidregen = ดูดซับของเหลว
+ability.liquidregen.description = ดูดซับของเหลวเพื่อฟื้นฟูพลังชีวิตตัวเอง
+ability.spawndeath = ตัวตายตัวแทน
+ability.spawndeath.description = ให้กำเนิดยูนิตออกมาหลังความตาย
+ability.liquidexplode = ระเบิดของเหลวแห่งความตาย
+ability.liquidexplode.description = กระจายของเหลวไปทั่วพื้นหลังความตาย
+ability.stat.firingrate = [stat]{0}/วิ[lightgray] อัตราการยิง
+ability.stat.regen = [stat]{0}[lightgray] พลังชีวิต/วิ
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
+ability.stat.shield = [stat]{0}[lightgray] เกราะ
+ability.stat.repairspeed = [stat]{0}/วิ[lightgray] ความเร็วการซ่อมแซม
+ability.stat.slurpheal = [stat]{0}[lightgray] พลังชีวิต/หน่วยของเหลว
+ability.stat.cooldown = [stat]{0} วิ[lightgray] คูลดาวน์
+ability.stat.maxtargets = [lightgray]เป้าหมายสูงสุด: [white]{0}
+ability.stat.sametypehealmultiplier = [lightgray]รักษาชนิดเดียวกัน: [white]{0}%
+ability.stat.damagereduction = [stat]{0}%[lightgray] ความเสียหายลดลง
+ability.stat.minspeed = [stat]{0} ช่อง/วิ[lightgray] ความเร็วต่ำสุด
+ability.stat.duration = [stat]{0} วิ[lightgray] ระยะเวลา
+ability.stat.buildtime = [stat]{0} วิ[lightgray] ความในการสร้าง
+
bar.onlycoredeposit = ขนย้ายทรัพยากรลงแกนกลางได้เท่านั้น
bar.drilltierreq = ต้องมีเครื่องขุดที่ดีกว่านี้
@@ -1075,7 +1110,7 @@ bullet.splashdamage = [stat]{0}[lightgray] ดาเมจกระจาย ~[s
bullet.incendiary = [stat]ติดไฟ
bullet.homing = [stat]ติดตามตัว
bullet.armorpierce = [stat]เจาะเกราะ
-bullet.maxdamagefraction = [stat]{0}%[lightgray] damage limit
+bullet.maxdamagefraction = [stat]{0}%[lightgray] ความเสียหายสูงสุด
bullet.suppression = [stat]{0} วิ[lightgray] ระงับการฟื้นฟู ~ [stat]{1}[lightgray] ช่อง
bullet.interval = [stat]{0}/วิ[lightgray] กระสุนช่วงระยะ:
bullet.frags = [stat]{0}[lightgray]x กระสุนกระจาย:
@@ -1086,9 +1121,11 @@ bullet.pierce = [lightgray]เจาะทะลุ [stat]{0}[lightgray]x
bullet.infinitepierce = [stat]เจาะทะลุ
bullet.healpercent = [stat]{0}[lightgray]% รักษา
bullet.healamount = [lightgray]รักษาโดยตรง [stat]{0}[lightgray] หน่วย
-bullet.multiplier = [lightgray]จำนวนกระสุนต่อไอเท็ม [stat]{0}[lightgray]x
+bullet.multiplier = [stat]{0}[lightgray] กระสุน/ไอเท็ม
bullet.reload = [lightgray]ความเร็วการยิง [stat]{0}[lightgray]%
bullet.range = [lightgray]ระยะยิง [stat]{0}[lightgray] ช่อง
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = บล็อก
unit.blockssquared = บล็อก²
@@ -1111,7 +1148,7 @@ unit.items = ไอเท็ม
unit.thousands = k
unit.millions = mil
unit.billions = b
-unit.shots = shots
+unit.shots = นัด
unit.pershot = /การยิง
category.purpose = วัตถุประสงค์
category.general = ทั่วไป
@@ -1121,8 +1158,8 @@ category.items = ไอเท็ม
category.crafting = การผลิต
category.function = ฟังค์ชั่น
category.optional = ทางเลือกการเพิ่มประสิทธิภาพ
-setting.alwaysmusic.name = Always Play Music
-setting.alwaysmusic.description = When enabled, music will always play on loop in-game.\nWhen disabled, it only plays at random intervals.
+setting.alwaysmusic.name = เล่นเพลงตลอดเวลา
+setting.alwaysmusic.description = เมื่อเปิดใช้งาน เพลงจะเล่นในพื้นหลังวนอยู่ตลอดเวลาในเกม\nเมื่อปิดใช้งาน เพลงจะสุ่มเล่นในช่วงระยะเวลาหนึ่งเท่านั้น
setting.skipcoreanimation.name = ข้ามแอนิเมชั่นการบิน/ลงจอดของแกนกลาง
setting.landscape.name = ล็อกภูมิทัศน์แนวนอน
setting.shadows.name = เงา
@@ -1134,7 +1171,7 @@ setting.backgroundpause.name = หยุดในพื้นหลัง
setting.buildautopause.name = หยุดสร้างชั่วคราวแบบอัตโนมัติ
setting.doubletapmine.name = กดสองครั้งเพื่อขุด
setting.commandmodehold.name = กดค้างเพื่อสั่งการ
-setting.distinctcontrolgroups.name = Limit One Control Group Per Unit
+setting.distinctcontrolgroups.name = จำกัดหนึ่งกลุ่มสั่งการต่อยูนิต
setting.modcrashdisable.name = ปิดม็อดเมื่อเกมขัดข้อง
setting.animatedwater.name = แอนิเมชั่นพื้นและน้ำ
setting.animatedshields.name = แอนิเมชั่นโล่พลังงาน
@@ -1149,12 +1186,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = อัตราขนาด UI
setting.uiscale.description = อาจจะต้องรีสตาร์ทเพื่อใช้งานการเปลี่ยนแปลง
setting.swapdiagonal.name = วางเป็นเส้นทแยงเสมอ
-setting.difficulty.training = ฝึกซ้อม
-setting.difficulty.easy = ง่าย
-setting.difficulty.normal = ปานกลาง
-setting.difficulty.hard = ยาก
-setting.difficulty.insane = โหดเหี้ยม
-setting.difficulty.name = ระดับความยาก:
setting.screenshake.name = การสั่นของจอ
setting.bloomintensity.name = ความรุนแรงของบลูม
setting.bloomblur.name = ความเบลอบลูม
@@ -1181,14 +1212,14 @@ setting.position.name = แสดงตำแหน่งของผู้เ
setting.mouseposition.name = แสดงตำแหน่งเม้าส์
setting.musicvol.name = ระดับเสียงเพลง
setting.atmosphere.name = แสดงชั้นบรรยากาศของดาว
-setting.drawlight.name = Draw Darkness/Lighting
+setting.drawlight.name = วาดแสงสีและความมืด
setting.ambientvol.name = ระดับเสียงแวดล้อม
setting.mutemusic.name = ปิดเสียงเพลง
setting.sfxvol.name = ระดับเสียง SFX
setting.mutesound.name = ปิดเสียง
setting.crashreport.name = ส่งรายงานข้อขัดข้องแบบไม่ระบุตัวตน
setting.savecreate.name = สร้างเซฟโดยอัตโนมัติ
-setting.steampublichost.name = Public Game Visibility
+setting.steampublichost.name = การมองเห็นเกมสาธารณะ
setting.playerlimit.name = จำกัดผู้เล่น
setting.chatopacity.name = ความโปร่งแสงของแชท
setting.lasersopacity.name = ความโปร่งแสงของลำแสงพลังงาน
@@ -1208,7 +1239,7 @@ keybind.title = ตั้งค่าปุ่ม
keybinds.mobile = [scarlet]การตั้งค่าปุ่มส่วนใหญ่ไม่สามารถใช้ในมือถือได้ เฉพาะการเคลื่อนไหวพื้นฐานเท่านั้นที่ใช้ได้
category.general.name = ทั่วไป
category.view.name = การมองเห็น
-category.command.name = Unit Command
+category.command.name = คำสั่งยูนิต
category.multiplayer.name = โหมดผู้เล่นหลายคน
category.blocks.name = เลือกบล็อก
placement.blockselectkeys = \n[lightgray]ปุ่ม: [{0},
@@ -1226,24 +1257,25 @@ keybind.mouse_move.name = ตามเม้าส์
keybind.pan.name = เคลื่อนการมองเห็น
keybind.boost.name = บูสต์
keybind.command_mode.name = โหมดสั่งการ
-keybind.command_queue.name = Unit Command Queue
-keybind.create_control_group.name = Create Control Group
-keybind.cancel_orders.name = Cancel Orders
-keybind.unit_stance_shoot.name = Unit Stance: Shoot
-keybind.unit_stance_hold_fire.name = Unit Stance: Hold Fire
-keybind.unit_stance_pursue_target.name = Unit Stance: Pursue Target
-keybind.unit_stance_patrol.name = Unit Stance: Patrol
-keybind.unit_stance_ram.name = Unit Stance: Ram
-keybind.unit_command_move.name = Unit Command: Move
-keybind.unit_command_repair.name = Unit Command: Repair
-keybind.unit_command_rebuild.name = Unit Command: Rebuild
-keybind.unit_command_assist.name = Unit Command: Assist
-keybind.unit_command_mine.name = Unit Command: Mine
-keybind.unit_command_boost.name = Unit Command: Boost
-keybind.unit_command_load_units.name = Unit Command: Load Units
-keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
-keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
-keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.command_queue.name = คิวคำสั่งยูนิต
+keybind.create_control_group.name = สร้างกลุ่มสั่งการ
+keybind.cancel_orders.name = ยกเลิกคำสั่ง
+keybind.unit_stance_shoot.name = ท่าทียูนิต: ยิง
+keybind.unit_stance_hold_fire.name = ท่าทียูนิต: หยุดยิง
+keybind.unit_stance_pursue_target.name = ท่าทียูนิต: ไล่ตามเป้าหมาย
+keybind.unit_stance_patrol.name = ท่าทียูนิต: ลาดตระเวน
+keybind.unit_stance_ram.name = ท่าทียูนิต: พุ่งชน
+keybind.unit_command_move.name = คำสั่งยูนิต: ขยับ
+keybind.unit_command_repair.name = คำสั่งยูนิต: ซ่อมแซม
+keybind.unit_command_rebuild.name = คำสั่งยูนิต: สร้างใหม่
+keybind.unit_command_assist.name = คำสั่งยูนิต: ช่วยเหลือผู้เล่น
+keybind.unit_command_mine.name = คำสั่งยูนิต: ขุด
+keybind.unit_command_boost.name = คำสั่งยูนิต: บูสต์
+keybind.unit_command_load_units.name = คำสั่งยูนิต: โหลดยูนิต
+keybind.unit_command_load_blocks.name = คำสั่งยูนิต: โหลดบล็อก
+keybind.unit_command_unload_payload.name = คำสั่งยูนิต: วางสิ่งบรรทุก
+keybind.unit_command_enter_payload.name = คำสั่งยูนิต: เข้าบล็อกบรรทุก
+keybind.unit_command_loop_payload.name = คำสั่งยูนิต: วนซำ้การขนถ่ายยูนิต
keybind.rebuild_select.name = เลือกพื้นที่สร้างใหม่
keybind.schematic_select.name = เลือกพื้นที่
keybind.schematic_menu.name = เมนูแผนผัง
@@ -1307,26 +1339,30 @@ mode.pvp.description = สู้กับผู้เล่นอื่น\n[gra
mode.attack.name = โจมตี
mode.attack.description = ทำลายฐานของศัตรู \n[gray]จำเป็นต้องมีแกนกลางสีแดงเพื่อเล่น
mode.custom = กฎแบบกำหนดเอง
-rules.invaliddata = Invalid clipboard data.
+rules.invaliddata = ข้อมูลคลิปบอร์ดไม่ถูกต้อง
rules.hidebannedblocks = ซ่อนบล็อกต้องห้าม
rules.infiniteresources = ทรัพยากรไม่จำกัด
rules.onlydepositcore = ขนย้ายทรัพยากรลงแกนกลางได้เท่านั้น
-rules.derelictrepair = Allow Derelict Block Repair
+rules.derelictrepair = อนุญาตการซ่อมแซมบล็อกทิ้งร้าง
rules.reactorexplosions = เปิดการระเบิดของเตาปฏิกร
rules.coreincinerates = แกนกลางเผาทรัพยากรส่วนเกิน
rules.disableworldprocessors = ปิดการทำงานของตัวประมวลผลโลก
rules.schematic = อนุญาตให้ใช้แผนผัง
rules.wavetimer = นับถอยหลังการปล่อยคลื่น
rules.wavesending = กดเพื่อปล่อยคลื่น
-rules.allowedit = Allow Editing Rules
-rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.allowedit = อนุญาตการแก้ไขกฎ
+rules.allowedit.info = เมื่อเปิดใช้งาน ผู้เล่นจะสามารถแก้ไขกฎของแมพในระหว่างเกมได้ด้วยปุ่มล่างซ้ายในเมนู
+rules.alloweditworldprocessors = อนุญาตการแก้ไขตัวประมวลผลโลก
+rules.alloweditworldprocessors.info = เมื่อเปิดใช้งาน ตัวประมวลผลโลกจะสามารถถูกวางและแก้ไขได้แม้จะอยู่ภายนอกตัวแก้ไข
rules.waves = คลื่น
-rules.airUseSpawns = Air units use spawn points
+rules.airUseSpawns = ยูนิตอากาศใช้จุดเกิด
rules.attack = โหมดการโจมตี
rules.buildai = AI สร้างฐานทัพ
rules.buildaitier = ระดับการสร้างของ AI
rules.rtsai = RTS AI [red](ไม่เสถียร)
+rules.rtsai.campaign = AI โจมตีแบบ RTS
+rules.rtsai.campaign.info = ในแมพโจมตี จะทำให้ยูนิตรวมตัวกันและจู่โจมฐานทัพของผู้เล่นในวิถีการคำนวณที่ฉลาดมากกว่า
rules.rtsminsquadsize = ขนาดกองทัพเล็กที่สุด
rules.rtsmaxsquadsize = ขนาดกองทัพใหญ่ที่สุด
rules.rtsminattackweight = ขนาดน้ำหนักการโจมตีน้อยที่สุด
@@ -1344,7 +1380,7 @@ rules.unitdamagemultiplier = พหุคูณพลังโจมตีขอ
rules.unitcrashdamagemultiplier = พหูคูณดาเมจการตกของยานยูนิต
rules.solarmultiplier = พหูคุณพลังงานแสงอาทิตย์
rules.unitcapvariable = เพิ่มจำนวนยูนิตสูงสุดต่อแกนกลาง
-rules.unitpayloadsexplode = Carried Payloads Explode With The Unit
+rules.unitpayloadsexplode = สิ่งบรรทุกระเบิดไปพร้อมกับยูนิต
rules.unitcap = ขีดกำจัดยูนิตสูงสุดพื้นฐาน
rules.limitarea = จำกัดพื้นที่แมพ
rules.enemycorebuildradius = รัศมีห้ามสร้างบริเวณแกนกลางของศัตรู:[lightgray] (ช่อง)
@@ -1369,6 +1405,9 @@ rules.title.teams = ทีม
rules.title.planet = ดาว
rules.lighting = แสง
rules.fog = หมอกแห่งสงคราม
+rules.invasions = การรุกรานของฐานทัพศัตรู
+rules.showspawns = แสดงจุดเกิดศัตรู
+rules.randomwaveai = AI คลื่นแบบคาดเดาไม่ได้
rules.fire = ไฟ
rules.anyenv = <อะไรก็ได้>
rules.explosions = ดาเมจการระเบิดของบล็อก/ยูนิต
@@ -1377,8 +1416,10 @@ rules.weather = สภาพอากาศ
rules.weather.frequency = ความถี่:
rules.weather.always = ตลอด
rules.weather.duration = ระยะเวลา:
-rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
-rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
+
+rules.randomwaveai.info = ทำให้ยูนิตที่เกิดจากคลิ่นเล็งเป้าหมายสิ่งก่อสร้างอย่างสุ่มแทนที่จะมุ่งโจมตีแต่แกนกลางหรือเครื่องกำเนิดไฟฟ้า
+rules.placerangecheck.info = ป้องกันผู้เล่นไม่ให้วางอะไรใกล้ๆกับสิ่งก่อสร้างศัตรู เมื่อวางป้อมปืน ระยะนั้นจะขยายออกมากขึ้น เพื่อไม่ให้ป้อมปืนนั้นมีระยะยิงถึงศัตรู
+rules.onlydepositcore.info = ป้องกันยูนิตไม่ให้โอนถ่ายไอเท็มลงสิ่งก่อสร้างใดๆ ยกเว้นแกนกลาง
content.item.name = ไอเท็ม
content.liquid.name = ของเหลว
@@ -1424,12 +1465,6 @@ liquid.hydrogen.name = ไฮโดรเจน
liquid.nitrogen.name = ไนโตรเจน
liquid.cyanogen.name = ไซยาโนเจน
-# Three suggestions if you would like to change the transliteration in these names.
-# 1. Using Bali-Sanskrit language sounds weird in futuristic units, please don't.
-# 2. Keep names consistent in each unit tree.
-# 3. Name should resemble the unit, or the original english name.
-# But sometimes transliteration is better, for instance boats, spiders, so please keep it like that - Translator
-
unit.dagger.name = แด็กเกอร์
unit.mace.name = เมส
unit.fortress.name = ฟอร์เทรส
@@ -1483,9 +1518,9 @@ unit.avert.name = อเวิร์ต
unit.obviate.name = อ็อบวีเอท
unit.quell.name = คเวลล์
unit.disrupt.name = ดิสรัปต์
-unit.evoke.name = ปลุกตื่น
-unit.incite.name = ปลุกปั่น
-unit.emanate.name = ปลุกขจร
+unit.evoke.name = อีโวค
+unit.incite.name = อินไซต์
+unit.emanate.name = อิมาเนต
unit.manifold.name = แมนิโฟลด์
unit.assembly-drone.name = โดรนประกอบร่าง
unit.latum.name = ลาทัม
@@ -1525,6 +1560,8 @@ block.graphite-press.name = เครื่องอัดกราไฟต์
block.multi-press.name = เครื่องอัดสารพัดอย่าง
block.constructing = {0} [lightgray](กำลังก่อสร้าง)
block.spawn.name = จุดเกิดศัตรู
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = แกนกลาง: ชาร์ด
block.core-foundation.name = แกนกลาง: ฟาวน์เดชั่น
block.core-nucleus.name = แกนกลาง: นิวเคลียส
@@ -1604,7 +1641,7 @@ block.inverted-sorter.name = เครื่องคัดแยกกลับ
block.message.name = กล่องข้อความ
block.reinforced-message.name = กล่องข้อความเสริมกำลัง
block.world-message.name = กล่องข้อความโลก
-block.world-switch.name = World Switch
+block.world-switch.name = สวิตช์โลก
block.illuminator.name = ตัวเปล่งแสง
block.overflow-gate.name = ประตูระบาย
block.underflow-gate.name = ประตูระบายข้าง
@@ -1782,6 +1819,7 @@ block.electric-heater.name = เครื่องอุ่นไฟฟ้า
block.slag-heater.name = เครื่องอุ่นแร่หลอม
block.phase-heater.name = เครื่องอุ่นใยเฟส
block.heat-redirector.name = เครื่องเปลี่ยนเส้นทางความร้อน
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = เร้าเตอร์ความร้อน
block.slag-incinerator.name = เตาเผาสลายแร่หลอม
block.carbide-crucible.name = เบ้าหลอมคาร์ไบด์
@@ -1829,6 +1867,7 @@ block.chemical-combustion-chamber.name = ห้องเผาไหม้ทา
block.pyrolysis-generator.name = เครื่องกำเนิดไฟฟ้าไพโรไลซิส
block.vent-condenser.name = เครื่องควบแน่นปล่อง
block.cliff-crusher.name = เครื่องบดหน้าผา
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = เครื่องขุดเจาะพลาสม่า
block.large-plasma-bore.name = เครื่องขุดเจาะพลาสม่าขนาดใหญ่
block.impact-drill.name = เครื่องขุดแรงกระแทก
@@ -1904,8 +1943,8 @@ hint.unitControl = กด [accent][[L-Ctrl][] ค้างไว้แล้ว
hint.unitControl.mobile = [accent][[กดสองครั้ง][] เพื่อควบคุมยานพันธมิตรหรือป้อมปืน
hint.unitSelectControl = เพื่อที่จะควบคุมยูนิต ให้เปิด[accent]โหมดสั่งการ[]โดยการกด [accent]L-shift[]\nระหว่างที่อยู่ในโหมดสั่งการ ให้คลิ๊กแล้วลากเพื่อเลือกยูนิต แล้ว[accent]คลิ๊กขวา[]ที่ตำแหน่งหรือเป้าหมายเพื่อสั่งการให้ยูนิตไปที่นั่น
hint.unitSelectControl.mobile = เพื่อที่จะควบคุมยูนิต ให้เปิด[accent]โหมดสั่งการ[]โดยการกดปุ่ม[accent]สั่งการ[]ที่ซ้ายล่างของจอ\nระหว่างที่อยู่ในโหมดสั่งการ ให้กดค้างแล้วลากเพื่อเลือกยูนิต แล้วกดที่ตำแหน่งหรือเป้าหมายเพื่อสั่งการให้ยูนิตไปที่นั่น
-hint.launch = เมื่อเก็บทรัพยากรเยอะพอ คุณสามารถ[accent]ส่งแกนกลาง[]โดยการเลือกเซ็กเตอร์จาก \ue827 [accent]แผนที่[] ตรงขวาล่าง
-hint.launch.mobile = เมื่อเก็บทรัพยากรเยอะพอ คุณสามารถ[accent]ส่งแกนกลาง[]โดยการเลือกเซ็กเตอร์จาก \ue827 [accent]แผนที่[] ใน \ue88c [accent]เมนู[]
+hint.launch = เมื่อเก็บทรัพยากรเยอะพอ คุณสามารถ[accent]ส่งแกนกลาง[]ไปยังเซ็กเตอร์ถัดไปโดยการเลือกเซ็กเตอร์จาก \ue827 [accent]แผนที่[] ตรงขวาล่าง
+hint.launch.mobile = เมื่อเก็บทรัพยากรเยอะพอ คุณสามารถ[accent]ส่งแกนกลาง[]ไปยังเซ็กเตอร์ถัดไปโดยการเลือกเซ็กเตอร์จาก \ue827 [accent]แผนที่[] ใน \ue88c [accent]เมนู[]
hint.schematicSelect = กด [accent][[F][] แล้วลากเพื่อเลือกบล็อกที่จะคัดลอกและวาง\n\n[accent][[คลิ๊กกลาง][] เพื่อคัดลอกบล็อกชนิดเดียว
hint.rebuildSelect = กด [accent][[B][] แล้วลากเพื่อเลือกแผนบล็อกที่ถูกทำลาย\nแผนบล็อกที่เลือกจะถูกสร้างใหม้โดยอัตโนมัติ
hint.rebuildSelect.mobile = กดปุ่ม \ue874 คัดลอก แล้วกดปุ่ม \ue80f สร้างใหม่แล้วลากเพื่อเลือกแผนบล็อกที่ถูกทำลาย\nแผนบล็อกที่เลือกจะถูกสร้างใหม้โดยอัตโนมัติ
@@ -1965,9 +2004,9 @@ onset.turrets = ยูนิตนั้นมีประสิทธิภา
onset.turretammo = เติมกระสุนให้แก่ป้อมปืนด้วย[accent]กระสุนเบริลเลี่ยม[]
onset.walls = [accent]กำแพง[]สามารถป้องกันความเสียหายที่จะมาถึงให้ไม่ไปโดนสิ่งก่อสร้างได้\nวางกำแพง \uf6ee [accent]กำแพงเบริลเลี่ยม[]รอบๆ ป้อมปืน
onset.enemies = ศัตรูกำลังจะเข้ามา เตรียมตัวป้องกันให้ดี
-onset.defenses = [accent]Set up defenses:[lightgray] {0}
+onset.defenses = [accent]ติดตั้งแนวป้องกัน:[lightgray] {0}
onset.attack = ศัตรูอ่อนแอลงแล้ว ตอบโต้กลับ
-onset.cores = แกนกลางใหม่สามารถวางได้บน[accent]โซนแกนกลาง[]\nแกนกลางใหม่จะทำหน้าที่เป็นฐานทัพหน้าด่านและจะแบ่งปันทรัพยากรกับแกนกลางอื่นๆ\nวาง \uf725 แกนกลาง
+onset.cores = แกนกลางใหม่สามารถวางได้บน[accent]โซนแกนกลาง[]\nแกนกลางใหม่จะทำหน้าที่เป็นฐานทัพด่านหน้าและจะแบ่งปันทรัพยากรกับแกนกลางอื่นๆ\nวาง \uf725 แกนกลาง
onset.detect = ศัตรูจะสามารถตรวจจับการมีอยู่ของคุณได้ในอีก 2 นาที\nจัดตั้งกองกำลังป้องกัน ปฏิบัติการขุด และการผลิต
#Don't translate these yet!
@@ -2065,6 +2104,10 @@ block.phase-wall.description = ป้องกันสิ่งก่อสร
block.phase-wall-large.description = ป้องกันสิ่งก่อสร้างจากศัตรู ทนทานและแข็งแรง\nเคลือบด้วยวัสดุพิเศษที่สะท้อนกระสุนส่วนใหญ่ที่รับมา\nครอบคลุมหลายช่อง
block.surge-wall.description = ป้องกันสิ่งก่อสร้างจากศัตรู แข็งแกร่งอย่างมาก\nจะปล่อยพลังงานสายฟ้าออกมาเป็นระยะๆ เมื่อถูกโจมตี
block.surge-wall-large.description = ป้องกันสิ่งก่อสร้างจากศัตรู แข็งแกร่งอย่างมาก\nจะปล่อยพลังงานสายฟ้าออกมาเป็นระยะๆ เมื่อถูกโจมตี\nครอบคลุมหลายช่อง
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = กำแพงที่สามารถเปิดและปิดได้ ไว้ใช้เพื่อให้ยูนิตเดินผ่าน
block.door-large.description = กำแพงที่สามารถเปิดและปิดได้ ไว้ใช้เพื่อให้ยูนิตเดินผ่าน\nครอบคลุมหลายช่อง
block.mender.description = ซ่อมแซมสิ่งก่อสร้างในวงของมันอย่างช้าๆ\nสามารถใช้ซิลิกอนเพื่อเพิ่มระยะและประสิทธิภาพได้
@@ -2129,8 +2172,8 @@ block.core-nucleus.description = ใจกลางของฐานทัพ
block.core-nucleus.details = แกนกลางรุ่นที่สามและเป็นรุ่นสุดท้าย สุดยอดยานบินแกมม่าจะปกป้องแกนกลางนี้ไว้
block.vault.description = เก็บไอเท็มแต่ละชนิดได้จำนวนมาก สามารถใช้ตัวถ่ายไอเท็มในการดึงไอเท็มออกมาได้
block.container.description = เก็บไอเท็มแต่ละชนิดได้นิดหน่อย สามารถใช้ตัวถ่ายไอเท็มในการดึงไอเท็มออกมาได้
-block.unloader.description = ดึงไอเท็มที่เลือกไว้ออกมาจากบล็อกใกล้เคียง
-block.launch-pad.description = ส่งไอเท็มเป็นชุดๆ ไปยังเซ็กเตอร์ที่เลือกไว้
+block.unloader.description = ดึงไอเท็มที่กำหนดไว้ออกมาจากบล็อกใกล้เคียง
+block.launch-pad.description = ส่งไอเท็มเป็นชุดๆ ไปยังเซ็กเตอร์ที่กำหนดไว้
block.launch-pad.details = ระบบขนส่งทรัพยากรวงโคจรย่อยจากจุดหนึ่งไปอีกจุดหนึ่ง แคปซูลบรรทุกทรัพยากรนั้นเปราะบางและไม่สามารถทนความร้อนจากชั้นบรรยากาศได้
block.duo.description = ป้อมปืนขนาดเล็ก ยิงกระสุนที่อยู่ในตัวมันใส่เป้าหมายศัตรู
block.scatter.description = ยิงก้อนตะกั่ว เศษเหล็กหรือกระจกเมต้าใส่ยานบินศัตรูที่อยู่ใกล้เคียง
@@ -2184,9 +2227,9 @@ block.sublimate.description = ยิงลำแสงเปลวไฟเจ
block.titan.description = ยิงกระสุนปืนใหญ่ระเบิดขนาดใหญ่ใส่เป้าหมายศัตรูพื้นดิน ต้องใช้ไฮโดรเจน
block.afflict.description = ยิงลูกแก้วสะเก็ดระเบิดสายฟ้าใส่เป้าหมายศัตรู ต้องใช้ความร้อน
block.disperse.description = ปะทุยิงก้อนสะเก็ดกระสุนใส่ยานบินศัตรู
-block.lustre.description = ยิงลำแสงเลเซอร์เคลื่อนที่ช้าจ่อเป้าหมายศัตรูที่จุดเดียว
-block.scathe.description = ป้อมปืนพิสัยไกล ยิงขีปนาวุธทรงพลังใส่เป้าหมายศัตรูพื้นดินจากระยะไกล ขีปนาวุธอาจถูกยิงสกัดระหว่างทางได้
-block.smite.description = บทลงโทษจากสวรรค์ ปะทุยิงกำแพงกระสุนสายฟ้าเจาะกราะใส่เป้าหมายศัตรู
+block.lustre.description = ยิงลำแสงเลเซอร์เคลื่อนที่ช้าจ่อใส่เป้าหมายศัตรูที่จุดๆเดียว
+block.scathe.description = ป้อมปืนพิสัยไกลอย่างมาก ยิงขีปนาวุธทรงพลังใส่เป้าหมายศัตรูพื้นดินจากระยะไกล ขีปนาวุธอาจถูกยิงสกัดระหว่างทางได้
+block.smite.description = บทลงโทษจากสวรรค์ ปะทุยิงแนวกระสุนสายฟ้าเจาะกราะใส่เป้าหมายศัตรู
block.malign.description = ระดมยิงกระสุนเลเซอร์สายฟ้าติดตามตัวจำนวนมากใส่เป้าหมายศัตรู ต้องใช้ความร้อนจำนวนมากเพื่อที่จะทำงานได้อย่างเต็มประสิทธิภาพ
block.silicon-arc-furnace.description = ผลิตซิลิกอนจากการหลอมทรายและกราไฟต์เข้าด้วยกัน
block.oxidation-chamber.description = แปลงเบริลเลี่ยมและโอโซนให้กลายเป็นอ๊อกไซด์ ปล่อยความร้อนออกมาซึ่งเป็นผลมาจากปฎิบัติการ
@@ -2194,6 +2237,7 @@ block.electric-heater.description = สร้างความร้อนข
block.slag-heater.description = สร้างความร้อนขึ้นมาจากแร่หลอม ใช้โดยการหันหน้าลูกศรไปในทางที่ต้องการจะปล่อยความร้อนออกมา
block.phase-heater.description = สร้างความร้อนขึ้นมาจากการอุ่นใยเฟส ใช้โดยการหันหน้าลูกศรไปในทางที่ต้องการจะปล่อยความร้อนออกมา
block.heat-redirector.description = เปลี่ยนทิศทางของความร้อนที่สะสมมาให้ไปหาบล็อกที่มันหันหน้าเข้าใส่
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = กระจายความร้อนที่สะสมมาออกไปในสามทิศทาง
block.electrolyzer.description = เปลี่ยนน้ำให้กลายเป็นแก็สไฮโดรเจนและโอโซนด้วยขบวนการทางเคมี
block.atmospheric-concentrator.description = หลอมรวมไนโตรเจนจากชั้นบรรยากาศ ใช้ความร้อนในการทำงาน
@@ -2206,6 +2250,7 @@ block.vent-condenser.description = ควบแน่นแก็สในปล
block.plasma-bore.description = เมื่อหันหน้าเข้าหาแร่กำแพง จะขุดแร่นั้นและส่งออกมาอย่างช้าๆ ไปเรื่อยๆ ไม่มีที่สิ้นสุด จำเป็นต้องใช้พลังงานเล็กน้อย สามารถใช้ไฮโดรเจนเพื่อเพิ่มประสิทธิภาพการขุดได้
block.large-plasma-bore.description = เครื่องขุดเจาะพลาสม่าที่ใหญ่กว่า สามารถขุดแร่ทังสเตนและทอเรี่ยมได้ ต้องใช้ไฮโดรเจนและพลังงานในการทำงาน สามารถใช้ไนโตรเจนเพื่อเพิ่มประสิทธิภาพการขุดได้
block.cliff-crusher.description = เมื่อหันหน้าเข้าหากำแพงที่ต้องการ จะบดขยี้กำแพงนั้น และส่งออกผงทรายละเอียดออกมาอย่างไม่มีที่สิ้นสุด จำเป็นต้องใช้พลังงาน ประสิทธิภาพของการบดขึ้นอยู่กับชนิดของกำแพงที่บด
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = เมื่อวางบนพื้นแร่ จะขุดแร่นั้นและส่งออกมาเป็นกลุ่มไปเรื่อยๆ ไม่มีที่สิ้นสุด จำเป็นต้องใช้พลังงานและน้ำ
block.eruption-drill.description = เครื่องขุดแรงกระแทกที่ได้รับการปรับปรุง สามารถขุดทอเรี่ยมได้ จำเป็นต้องใช้ไฮโดรเจน
block.reinforced-conduit.description = เคลื่อนย้ายของเหลวไปข้างหน้า ไม่รับของเหลวจากด้านข้างยกเว้นว่าจะเป็นท่อน้ำด้วยกันเอง
@@ -2262,7 +2307,7 @@ block.small-deconstructor.description = ลบทำลายสิ่งก่
block.reinforced-payload-conveyor.description = เคลื่อนย้ายสิ่งของบรรทุกหนัก อย่างเช่นยูนิต
block.reinforced-payload-router.description = แยกสิ่งของบรรทุกออกเป็นสามทิศทาง จะทำงานเป็นเครื่องคัดแยกหากได้ตั้งตัวกรองเอาไว้
block.payload-mass-driver.description = บล็อกขนส่งสิ่งบรรทุกทางไกล\nยิงสิ่งบรรทุกไปยังเครื่องโอนถ่ายสิ่งบรรทุกอีกเครื่องที่เชื่อมต่อไว้
-block.large-payload-mass-driver.description = บล็อกขนส่งสิ่งบรรทุกทางไกล\nยิงสิ่งบรรทุกไปยังเครื่องโอนถ่ายสิ่งบรรทุกอีกเครื่องที่เชื่อมต่อไว้
+block.large-payload-mass-driver.description = บล็อกขนส่งสิ่งบรรทุกทางไกล\nยิงสิ่งบรรทุกไปยังหอโอนถ่ายสิ่งบรรทุกอีกเครื่องที่เชื่อมต่อไว้
block.unit-repair-tower.description = ซ่อมแซมยูนิตทั้งหมดที่อยู่ในรัศมีของมัน ต้องใช้โอโซนเพื่อทำงาน
block.radar.description = ค่อยๆ เปิดเผยพื้นที่และยูนิตศัตรูในรัศมีขนาดใหญ่ ต้องใช้พลังงาน
block.shockwave-tower.description = สร้างความเสียหายและทำลายกระสุนของศัตรูในรัศมีของมัน ต้องใช้ไซยาโนเจนเพื่อทำงาน
@@ -2330,7 +2375,7 @@ unit.emanate.description = สร้างสิ่งต่างๆ เพื
lst.read = อ่านเลขจากเซลล์ความจำที่เชื่อมต่อไว้
lst.write = เขียนเลขไปยังเซลล์ความจำที่เชื่อมต่อไว้
lst.print = เพิ่มข้อความไปยังคิวข้อความ\nข้อความจะยังไม่แสดงจนกว่าจะใช้คำสั่ง [accent]Print Flush[]
-lst.format = Replace next placeholder in text buffer with a value.\nDoes not do anything if placeholder pattern is invalid.\nPlaceholder pattern: "{[accent]number 0-9[]}"\nExample:\n[accent]print "test {0}"\nformat "example"
+lst.format = แทนที่ข้อความตัวแทนถัดไปในบัฟเฟอร์ข้อความด้วยค่า\nจะไม่ทำอะไรหากรูปแบบข้อความแทนที่นั้นไม่ถูกต้อง\nรูปแบบข้อความแทนที่: "{[accent]ตัวเลข 0-9[]}"\nตัวอย่าง:\n[accent]print "ทดสอบ {0}"\nformat "สวัสดี"
lst.draw = เพิ่มรูปไปยังคิวการวาด\nภาพจะยังไม่แสดงจนกว่าจะใช้คำสั่ง [accent]Draw Flush[]
lst.drawflush = ปล่อยคิว [accent]Draw[] ไปยังหน้าจอลอจิกที่เชื่อมต่อไว้
lst.printflush = ปล่อยคิว [accent]Print[] ไปยังตัวเก็บข้อความที่เชื่อมต่อไว้
@@ -2339,7 +2384,7 @@ lst.control = ควบคุมสิ่งก่อสร้าง
lst.radar = เรดาร์หายูนิตที่อยู่รอบๆ สิ่งก่อสร้าง โดยระยะการตรวจสอบขึ้นอยู่กับระยะของสิ่งก่อสร้าง
lst.sensor = รับข้อมูลจากสิ่งก่อสร้างหรือยูนิต
lst.set = ตั้งตัวแปร
-lst.operation = ทำการดำเนินการกับ 1-2 ตัวแปร
+lst.operation = ทำการคำนวณกับ 1-2 ตัวแปร
lst.end = ย้อนกลับไปยังด้านบนสุดของชุดคำสั่ง
lst.wait = รอเวลาเป็นวินาที
lst.stop = หยุดยั้งการทำงานของตัวประมวลผล
@@ -2351,62 +2396,63 @@ lst.unitradar = ค้นหายูนิตรอบๆ ยูนิตที
lst.unitlocate = ค้นหาตำแหน่ง/สิ่งก่อสร้างเฉพาะอย่างที่ใดก็ได้บนแผนที่\nต้องมียูนิตที่เลือกไว้
lst.getblock = รับข้อมูลของช่องที่ตำแหน่งใดๆ
lst.setblock = ปรับแต่งข้อมูลของช่องที่ตำแหน่งใดๆ
-lst.spawnunit = เสกยูนิตมาที่ตำแหน่งที่กำหนดไว้
+lst.spawnunit = สร้างยูนิตมาที่ตำแหน่งที่กำหนดไว้
lst.applystatus = ใส่หรือล้างเอฟเฟกต์สถานะจากยูนิต
-lst.weathersense = Check if a type of weather is active.
-lst.weatherset = Set the current state of a type of weather.
+lst.weathersense = ตรวจสอบว่าสภาพอากาศใดๆ กำลังทำงานอยู่หรือไม่
+lst.weatherset = ตั้งค่าสถานะในปัจจุบันของสภาพอากาศใดๆ
lst.spawnwave = จำลองคลื่นที่ตำแหน่งใดๆ
-lst.explosion = เสกระเบิดที่ตำแหน่ง
+lst.explosion = สร้างระเบิดที่ตำแหน่งใดๆ
lst.setrate = ตั้งค่าความเร็วการสั่งเป็นคำสั่งใน คำสั่ง/ติก
lst.fetch = ค้นหายูนิต แกนกลาง ผู้เล่น หรือสิ่งก่อสร้างตามดัชนี\nดัชนีเริ่มที่ 0 และจบที่ค่าที่จะส่งกลับ
lst.packcolor = แพ็ค [0, 1] ส่วนประกอบ RGBA มาเป็นเลขบรรทัดเดียวสำหรับการวาดหรือการตั้งค่ากฎ
lst.setrule = ตั้งค่ากฎของเกม
-lst.flushmessage = แสดงข้อความบนหน้าจอจากบัฟเฟอร์ข้อความ\nจะรอจนกว่าข้อความก่อนหน้าจะเสร็จสิ้น
+lst.flushmessage = แสดงข้อความบนหน้าจอจากบัฟเฟอร์ข้อความ\nถ้าตัวแปรผลลัพธ์ออกมาเป็น [accent]@wait[]\nจะรอจนกว่าข้อความก่อนหน้าจะเสร็จสิ้น\nนอกจากนั้น จะส่งออกว่าการแสดงผลข้อความสำเร็จหรือไม่
lst.cutscene = ควบคุมมุมกล้องของผู้เล่น
lst.setflag = เซ็ตธงทั่วโลกที่ตัวประมวลผลทุกตัวสามารถอ่านค่าได้
lst.getflag = เช็กว่าธงทั่วโลกนั้นได้ถูกเซ็ตอยู่รึเปล่า
lst.setprop = ตั้งค่าคุณสมบัติของยูนิตและสิ่งก่อสร้าง
-lst.effect = Create a particle effect.
-lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
-lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
-lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
-lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
+lst.effect = เสกเอฟเฟกต์อนุภาค
+lst.sync = ซิงค์หนึ่งตัวแปรทั่วทั้งเครือข่าย\nสามารถเรียกใช้คำสั่งได้แค่ 10 ครั้งต่อวินาทีอย่างมาก
+lst.playsound = เล่นเสียง\nระดับเสียงและการแพนสามารถใช้เป็นค่าสากลได้ หรือคำนวณเอาจากตำแหน่งก็ได้
+lst.makemarker = สร้างเครื่องหมายลอจิกใหม่ขึ้นมาในแมพ\nจะต้องเพิ่ม ID เข้าไปเพื่อบ่งชี้เครื่องหมายนี้\nเครื่องหมายจำกัดได้แค่ 20,000 ต่อแมพในตอนนี้
+lst.setmarker = ตั้งค่าคุณสมบัติให้กับเครื่องหมาย\nID ของเครื่องหมายที่ใช้จะต้องเป็น ID เดียวกันกับในคำสั่ง Make Marker\nค่า[accent]ว่างเปล่า[]จะถูกข้าม
+lst.localeprint = เพิ่มค่าชุดภาษาท้องถิ่นของแมพลงไปในบัฟเฟอร์ข้อความเพื่อตั้งค่าชุดภาษาของแมพในตัวแก้ไข ให้เปิด [accent]ข้อมูลแมพ > ชุดภาษาท้องถิ่น[].\nถ้าหากผู้เล่นอยู่ในมือถือ ให้ลองปริ้นค่าโดยลงท้ายด้วย ".mobile" ก่อน
lglobal.false = 0
lglobal.true = 1
-lglobal.null = null
-lglobal.@pi = The mathematical constant pi (3.141...)
-lglobal.@e = The mathematical constant e (2.718...)
-lglobal.@degToRad = Multiply by this number to convert degrees to radians
-lglobal.@radToDeg = Multiply by this number to convert radians to degrees
-lglobal.@time = Playtime of current save, in milliseconds
-lglobal.@tick = Playtime of current save, in ticks (1 second = 60 ticks)
-lglobal.@second = Playtime of current save, in seconds
-lglobal.@minute = Playtime of current save, in minutes
-lglobal.@waveNumber = Current wave number, if waves are enabled
-lglobal.@waveTime = Countdown timer for waves, in seconds
-lglobal.@mapw = Map width in tiles
-lglobal.@maph = Map height in tiles
-lglobal.sectionMap = Map
-lglobal.sectionGeneral = General
-lglobal.sectionNetwork = Network/Clientside [World Processor Only]
-lglobal.sectionProcessor = Processor
-lglobal.sectionLookup = Lookup
-lglobal.@this = The logic block executing the code
-lglobal.@thisx = X coordinate of block executing the code
-lglobal.@thisy = Y coordinate of block executing the code
-lglobal.@links = Total number of blocks linked to this processors
-lglobal.@ipt = Execution speed of the processor in instructions per tick (60 ticks = 1 second)
-lglobal.@unitCount = Total number of types of unit content in the game; used with the lookup instruction
-lglobal.@blockCount = Total number of types of block content in the game; used with the lookup instruction
-lglobal.@itemCount = Total number of types of item content in the game; used with the lookup instruction
-lglobal.@liquidCount = Total number of types of liquid content in the game; used with the lookup instruction
-lglobal.@server = True if the code is running on a server or in singleplayer, false otherwise
-lglobal.@client = True if the code is running on a client connected to a server
-lglobal.@clientLocale = Locale of the client running the code. For example: en_US
-lglobal.@clientUnit = Unit of client running the code
-lglobal.@clientName = Player name of client running the code
-lglobal.@clientTeam = Team ID of client running the code
-lglobal.@clientMobile = True is the client running the code is on mobile, false otherwise
+lglobal.null = ค่าว่างเปล่า
+lglobal.@pi = ค่าคงตัวทางคณิตศาสตร์ pi (3.141...)
+lglobal.@e = ค่าคงตัวทางคณิตศาสตร์ e (2.718...)
+lglobal.@degToRad = คูณค่าด้วยเลขตัวนี้เพื่อแปลงองศาเป็นเรเดียน
+lglobal.@radToDeg = คูณค่าด้วยเลขตัวนี้เพื่อแปลงเรเดียนเป็นองศา
+lglobal.@time = ระยะเวลาที่เล่นไปของเซฟนี้ ในหน่วยมิลิวินาที
+lglobal.@tick = ระยะเวลาที่เล่นไปของเซฟนี้ ในหน่วยติก (1 วินาที = 60 ติก)
+lglobal.@second = ระยะเวลาที่เล่นไปของเซฟนี้ ในหน่วยวินาที
+lglobal.@minute = ระยะเวลาที่เล่นไปของเซฟนี้ ในหน่วยนาที
+lglobal.@waveNumber = ลำดับคลื่นในปัจจุบัน หากคลื่นเปิดใช้งาน
+lglobal.@waveTime = เวลานับถอยหลังของคลื่นถัดไป ในหน่วยวินาที
+lglobal.@mapw = ความกว้างของแมพ ในหน่วยช่อง
+lglobal.@maph = ความสูงของแมพ ในหน่วยช่อง
+lglobal.sectionMap = แมพ
+lglobal.sectionGeneral = ทั่วไป
+lglobal.sectionNetwork = เครือข่าย/ฝั่งผู้เล่น [เฉพาะตัวประมวลผลโลก]
+lglobal.sectionProcessor = ตัวประมวลผล
+lglobal.sectionLookup = การค้นหา
+lglobal.@this = บล็อกลอจิกที่กำลังรันโค้ดนี้อยู่
+lglobal.@thisx = พิกัด X ของบล็อกที่กำลังรันโค้ดนี้อยู่
+lglobal.@thisy = พิกัด Y ของบล็อกที่กำลังรันโค้ดนี้อยู่
+lglobal.@links = จำนวนบล็อกทั้งหมดที่เชื่อมต่อกับตัวประมวลผลนี้
+lglobal.@ipt = ความเร็วการสั่งการของตัวประมวลผลนี้ ในหน่วยคำสั่งต่อติก (60 ติก = 1 วินาที)
+lglobal.@unitCount = จำนวนเนื้อหาของชนิดยูนิตทั้งหมดที่อยู่ในเกม ใช้กับคำสั่ง Lookup
+lglobal.@blockCount = จำนวนเนื้อหาของชนิดบล็อกทั้งหมดที่อยู่ในเกม ใช้กับคำสั่ง Lookup
+lglobal.@itemCount = จำนวนเนื้อหาของชนิดไอเท็มทั้งหมดที่อยู่ในเกม ใช้กับคำสั่ง Lookup
+lglobal.@liquidCount = จำนวนเนื้อหาของชนิดของเหลวทั้งหมดที่อยู่ในเกม ใช้กับคำสั่ง Lookup
+lglobal.@server = เป็นจริงหากโค้ดกำลังรันบนเซิร์ฟเวอร์หรือในโหมดผู้เล่นคนเดียว นอกนั้นจะเป็นเท็จ
+lglobal.@client = เป็นจริงหากโค้ดกำลังรันบนฝั่งไคลเอนต์ที่เชื่อมต่อกับเซิร์ฟเวอร์
+lglobal.@clientLocale = ค่าภาษาของฝั่งไคลเอนต์ที่กำลังรันคำสั่ง ยกตัวอย่างเช่น: th_TH
+lglobal.@clientUnit = หน่วยของฝั่งไคลเอนต์ที่กำลังรันคำสั่ง
+lglobal.@clientName = ชื่อผู้เล่นของฝั่งไคลเอนต์ที่กำลังรันคำสั่ง
+lglobal.@clientTeam = ID ของทีมของฝั่งไคลเอนต์ที่กำลังรันคำสั่ง
+lglobal.@clientMobile = เป็นจริงหากฝั่งไคลเอนต์ที่กำลังรันคำสั่งบนอุปกรณ์มือถือ นอกนั้นจะเป็นเท็จ
logic.nounitbuild = [red]ไม่อนุญาตให้ใช้ลอจิกควบคุมให้ยูนิตสร้างที่นี่
@@ -2415,7 +2461,7 @@ lenum.shoot = ยิงไปที่ตำแหน่งเป้าหมา
lenum.shootp = ยิงเป้าหมายโดยมีการคำนวณการยิง
lenum.config = การกำหนดค่าของสิ่งก่อสร้าง เช่น ไอเท็มของเครื่องคัดแยก
lenum.enabled = ว่าบล็อกเปิดใช้งาน/ทำงานอยู่หรือเปล่า
-laccess.currentammotype = Current ammo item/liquid of a turret.
+laccess.currentammotype = ประเภทของกระสุนไอเท็ม/ของเหลวในปัจจุบันของป้อมปืน
laccess.color = สีของตัวเปล่งแสง
laccess.controller = ผู้ควบคุมยูนิต ถ้าผู้ควบคุมคือตัวประมวลผล จะส่งกลับค่า processor\nนอกนั้น จะส่งกลับค่าตัวยูนิตเอง
@@ -2423,7 +2469,7 @@ laccess.dead = ว่าสิ่งก่อสร้าง/ยูนิตน
laccess.controlled = จะส่งกลับ:\n[accent]@ctrlProcessor[] ถ้าผู้ควบคุมคือตัวประมวลผลลอจิก\n[accent]@ctrlPlayer[] ถ้าสิ่งก่อสร้าง/ยูนิตถูกควบคุมโดยผู้เล่น\n[accent]@ctrlCommand[] ถ้ายูนิตถูกสั่งการโดยผู้เล่นอยู่\nนอกนั้นจะเป็น 0
laccess.progress = ความคืบหน้าการดำเนินการจาก 0 ถึง 1\nจะส่งกลับค่าการผลิต การรีโหลดของป้อมปืน หรือความคืบหน้าในการสร้างสิ่งก่อสร้าง
laccess.speed = ความเร็วสูงสุดของยูนิตในหน่วย ช่อง/วินาที
-laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup operation.
+laccess.id = ID ของยูนิต/บล็อก/ไอเท็ม/ของเหลว\nคำสั่งนี้จะตรงกันข้ามกับคำสั่ง lookup
lcategory.unknown = ไม่ทราบ
lcategory.unknown.description = คำสั่งที่ไม่อยู่ในหมวดหมู่ใดๆเลย
@@ -2451,7 +2497,7 @@ graphicstype.poly = เติมรูปหลายเหลี่ยมปก
graphicstype.linepoly = วาดโครงร่างรูปหลายเหลี่ยมปกติ
graphicstype.triangle = เติมสามเหลี่ยม
graphicstype.image = วาดรูปสิ่งต่างๆ \nตัวอย่างเช่น: [accent]@router[] หรือ [accent]@dagger[]
-graphicstype.print = Draws text from the print buffer.\nClears the print buffer.
+graphicstype.print = วาดข้อความจากบัฟเฟอร์ข้อความ\nใช้ตัวอักษร ASCII ได้เท่านั้น\nจะเคลียร์บัฟเฟอร์ข้อความ
lenum.always = เป็นจริงเสมอ
lenum.idiv = หารจำนวนเต็ม
@@ -2539,6 +2585,7 @@ unitlocate.building = ตัวแปรสิ่งก่อสร้างท
unitlocate.outx = ตัวแปรพิกัด X
unitlocate.outy = ตัวแปรพิกัด Y
unitlocate.group = กลุ่มสิ่งก่อสร้างที่มองหา
+playsound.limit = หากจริง จะหยุดยั้งไม่ให้เล่นเสียงนี้\nถ้าหากมันถูกเล่นไปแล้วในเฟรมเดียวกัน
lenum.idle = หยุดขยับ แต่ยังคงขุด/ก่อสร้าง\nสถานะเริ่มต้นของยูนิต
lenum.stop = หยุดขยับ/ขุด/ก่อสร้าง
@@ -2546,7 +2593,7 @@ lenum.unbind = ยกเลิกการควบคุมลอจิกท
lenum.move = ขยับไปที่ตำแหน่งที่กำหนดไว้
lenum.approach = เข้าใกล้ตำแหน่งโดยกำหนดระยะห่าง
lenum.pathfind = ขยับไปที่ตำแหน่งที่กำหนดไว้ โดยมีการคำนวณเพื่อเลี่ยงสิ่งกีดขวาง
-lenum.autopathfind = Automatically pathfinds to the nearest enemy core or drop point.\nThis is the same as standard wave enemy pathfinding.
+lenum.autopathfind = คำนวณเส้นทางที่ใกล้ที่สุดแล้วขยับไปหาแกนกลางหรือจุดเกิดของศัตรูโดยอัตโนมัติ\nเหมือนกันกับการคำนวณเส้นทางของคลื่นศัตรู
lenum.target = ยิงไปที่ตำแหน่งเป้าหมาย
lenum.targetp = ยิงไปที่เป้าหมาย โดยมีการคำนวณความเร็ว
lenum.itemdrop = ปล่อยไอเท็ม
@@ -2557,13 +2604,13 @@ lenum.payenter = เข้าไป/ลงจอดบนบล็อกบร
lenum.flag = ปักธงยูนิตเป็นหมายเลข
lenum.mine = ขุดที่ตำแหน่งเป้าหมาย
lenum.build = สร้างสิ่งก่อสร้าง
-lenum.getblock = Fetch building, floor and block type at coordinates.\nUnit must be in range of the position, otherwise null is returned.
+lenum.getblock = ดึงข้อมูลสิ่งก่อสร้างและประเภทของสิ่งก่อสร้างที่ตำแหน่งเป้าหมาย\nยูนิตต้องอยู่ในระยะของตำแหน่ง\nบล็อกตันที่ไม่ใช่สิ่งก่อสร้างจะมีชนิดเป็น [accent]@solid[]
lenum.within = ตรวจสอบว่ายูนิตนั้นอยู่ในระยะหรือไม่
lenum.boost = เริ่ม/หยุดการบูสต์
-lenum.flushtext = Flush print buffer's content to marker, if applicable.\nIf fetch is set to true, tries to fetch properties from map locale bundle or game's bundle.
-lenum.texture = Texture name straight from game's texture atlas (using kebab-case naming style).\nIf printFlush is set to true, consumes text buffer content as text argument.
-lenum.texturesize = Size of texture in tiles. Zero value scales marker width to original texture's size.
-lenum.autoscale = Whether to scale marker corresponding to player's zoom level.
-lenum.posi = Indexed position, used for line and quad markers with index zero being the first position.
-lenum.uvi = Texture's position ranging from zero to one, used for quad markers.
-lenum.colori = Indexed position, used for line and quad markers with index zero being the first color.
+lenum.flushtext = ระบายเนื้อหาของบัฟเฟอร์ข้อความลงสู่เครื่องหมาย ถ้ามี\nถ้า fetch ถูกตั้งเป็นจริง จะพยายามดึงค่าจากค่าชุดภาษาท้องถิ่นหรือชุดภาษาในเกม
+lenum.texture = ชื่อเทกเจอร์ตรงมาจากแอตลาสเทกเจอร์ของเกม (ใช้การตั้งชื่อแบบ kebab-case)\nถ้า printFlush ถูกตั้งเป็นจริง จะใส่เนื้อหาของบัฟเฟอร์ข้อความไปในช่องข้อความ
+lenum.texturesize = ขนาดของเทกเจอร์ในหน่วยช่อง หากค่าเป็นศูนย์จะปรับขนาดของเครื่องหมายเป็นขนาดปกติ
+lenum.autoscale = ว่าจะให้เครื่องหมายเพิ่มลดขนาดตามระดับการซูมของผู้เล่นหรือไม่
+lenum.posi = ตำแหน่งในดัชนี ใช้สำหรับเครื่องหมายเส้นตรงและสี่เหลี่ยมที่มีดัชนีศูนย์เป็นตำแหน่งเริ่มต้น
+lenum.uvi = ตำแหน่งของเทกเจอร์ในคาบระหว่างศูนย์ถึงหนึ่ง ใช้สำหรับเครื่องหมายสี่เหลี่ยม
+lenum.colori = ค่าสีในดัชนี ใช้สำหรับเครื่องหมายเส้นตรงและสี่เหลี่ยมที่มีดัชนีศูนย์เป็นสีเริ่มต้น
diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties
index e625322820..6b931386ac 100644
--- a/core/assets/bundles/bundle_tk.properties
+++ b/core/assets/bundles/bundle_tk.properties
@@ -141,6 +141,7 @@ mod.enabled = [lightgray]Enabled
mod.disabled = [scarlet]Disabled
mod.multiplayer.compatible = [gray]Multiplayer Compatible
mod.disable = Disable
+mod.version = Version:
mod.content = Content:
mod.delete.error = Unable to delete mod. File may be in use.
mod.incompatiblegame = [red]Outdated Game
@@ -190,6 +191,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]Completed
techtree = Tech Tree
techtree.select = Tech Tree Selection
@@ -289,13 +291,14 @@ disconnect.error = Connection error.
disconnect.closed = Connection closed.
disconnect.timeout = Timed out.
disconnect.data = Oyunun geri yuklenemedi!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Unable to join game ([accent]{0}[]).
connecting = [accent]Baglaniliyor
reconnecting = [accent]Reconnecting...
connecting.data = [accent]Loading world data...
server.port = Link:
-server.addressinuse = Addres zaten kullaniliyor!
server.invalidport = Geçersiz Oyun numarasi!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Oyun acarkes sorun olustu: [accent]{0}
save.new = Yeni Kayit Dosyasi
save.overwrite = Bu oyunun uzerinden\ngecmek istedigine emin\nmisin?
@@ -348,6 +351,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -490,6 +494,7 @@ waves.units.show = Show All
wavemode.counts = counts
wavemode.totals = totals
wavemode.health = health
+all = All
editor.default = [lightgray]
details = Details...
@@ -657,7 +662,6 @@ requirement.capture = Capture {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = Launch
-research.multiplayer = Only the host can research items.
map.multiplayer = Only the host can view sectors.
uncover = Uncover
configure = Configure Loadout
@@ -725,6 +729,7 @@ error.mapnotfound = Map file not found!
error.io = Network I/O error.
error.any = Unkown network error.
error.bloom = Failed to initialize bloom.\nYour device may not support it.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Rain
weather.snowing.name = Snow
@@ -774,6 +779,11 @@ threat.medium = Medium
threat.high = High
threat.extreme = Extreme
threat.eradication = Eradication
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Planets
planet.serpulo.name = Serpulo
@@ -795,9 +805,19 @@ sector.fungalPass.name = Fungal Pass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on.
sector.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders.
@@ -817,6 +837,18 @@ sector.impact0078.description = Here lie remnants of the interstellar transport
sector.planetaryTerminal.description = The final target.\n\nThis coastal base contains a structure capable of launching Cores to local planets. It is extremely well guarded.\n\nProduce naval units. Eliminate the enemy as quickly as possible. Research the launch structure.
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
sector.lake.name = Lake
@@ -1013,6 +1045,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1077,6 +1110,8 @@ bullet.healamount = [stat]{0}[lightgray] direct repair
bullet.multiplier = [stat]{0}[lightgray]x ammo multiplier
bullet.reload = [stat]{0}[lightgray]x reload
bullet.range = [stat]{0}[lightgray] tiles range
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = Yapilar
unit.blockssquared = blocks²
@@ -1137,12 +1172,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI Scaling[lightgray] (requires restart)[]
setting.uiscale.description = Restart required to apply changes.
setting.swapdiagonal.name = Always Diagonal Placement
-setting.difficulty.training = training
-setting.difficulty.easy = kolay
-setting.difficulty.normal = orta
-setting.difficulty.hard = zor
-setting.difficulty.insane = cok zor
-setting.difficulty.name = Zorluk derecesi:
setting.screenshake.name = Ekran sallanmasi
setting.bloomintensity.name = Bloom Intensity
setting.bloomblur.name = Bloom Blur
@@ -1232,6 +1261,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = Select Region
keybind.schematic_menu.name = Schematic Menu
@@ -1309,12 +1339,16 @@ rules.wavetimer = Wave Timer
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Waves
rules.airUseSpawns = Air units use spawn points
rules.attack = Attack Mode
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Min Squad Size
rules.rtsmaxsquadsize = Max Squad Size
rules.rtsminattackweight = Min Attack Weight
@@ -1357,6 +1391,9 @@ rules.title.teams = Teams
rules.title.planet = Planet
rules.lighting = Lighting
rules.fog = Fog of War
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Fire
rules.anyenv =
rules.explosions = Block/Unit Explosion Damage
@@ -1365,6 +1402,7 @@ rules.weather = Weather
rules.weather.frequency = Frequency:
rules.weather.always = Always
rules.weather.duration = Duration:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1505,6 +1543,8 @@ block.graphite-press.name = Graphite Press
block.multi-press.name = Multi-Press
block.constructing = {0}\n[lightgray](Constructing)
block.spawn.name = Enemy Spawn
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Core: Shard
block.core-foundation.name = Core: Foundation
block.core-nucleus.name = Core: Nucleus
@@ -1762,6 +1802,7 @@ block.electric-heater.name = Electric Heater
block.slag-heater.name = Slag Heater
block.phase-heater.name = Phase Heater
block.heat-redirector.name = Heat Redirector
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = Slag Incinerator
block.carbide-crucible.name = Carbide Crucible
@@ -1809,6 +1850,7 @@ block.chemical-combustion-chamber.name = Chemical Combustion Chamber
block.pyrolysis-generator.name = Pyrolysis Generator
block.vent-condenser.name = Vent Condenser
block.cliff-crusher.name = Cliff Crusher
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plasma Bore
block.large-plasma-bore.name = Large Plasma Bore
block.impact-drill.name = Impact Drill
@@ -2034,6 +2076,10 @@ block.phase-wall.description = Not as strong as a thorium wall but will deflect
block.phase-wall-large.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful.\nSpans multiple tiles.
block.surge-wall.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker.
block.surge-wall-large.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker.\nSpans multiple tiles.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = A small door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through.
block.door-large.description = A large door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through.\nSpans multiple tiles.
block.mender.description = Periodically repairs blocks in its vicinity. Keeps defenses repaired in-between waves.\nOptionally uses silicon to boost range and efficiency.
@@ -2161,6 +2207,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2173,6 +2220,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2331,6 +2379,7 @@ lst.getflag = Check if a global flag is set.
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2483,6 +2532,7 @@ unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Don't move, but keep building/mining.\nThe default state.
lenum.stop = Stop moving/mining/building.
lenum.unbind = Completely disable logic control.\nResume standard AI.
diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties
index db687017f7..ed12b152c5 100644
--- a/core/assets/bundles/bundle_tr.properties
+++ b/core/assets/bundles/bundle_tr.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Etkin
mod.disabled = [scarlet]Devre Dışı
mod.multiplayer.compatible = [gray]Çok Oyunculuya Uygun
mod.disable = Devre Dışı Bırak
+mod.version = Version:
mod.content = İçerik:
mod.delete.error = Mod silinemiyor. Dosya kullanımda olabilir.
mod.incompatiblegame = [red]Eski Sürüm
@@ -193,6 +194,7 @@ campaign.select = Başlangıç Mücadelesi Seç
campaign.none = [lightgray]Başlamak için bir gezegen seç.\nBu seçim herhangi bir zamanda değiştirlebilir.
campaign.erekir = Daha yeni ve cilalanmış içerikler. Genellikle kararlı ilerleme.\n\nDaha kaliteli haritalar ve deneyim (herhalde).
campaign.serpulo = Eski içerik; klasik deneyim. Daha serbest.\n\nDaha dengesiz harita ve deneyim. Cilayı unutmuşlar işte...
+campaign.difficulty = Difficulty
completed = [accent]Tamamlandı
techtree = Teknoloji Ağacı
techtree.select = Teknoloji Ağacı Seç
@@ -293,13 +295,14 @@ disconnect.error = Bağlantı hatası.
disconnect.closed = Bağlantı kapatıldı.
disconnect.timeout = Zaman aşımı.
disconnect.data = Dünya verisi yüklenemedi!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Oyuna girilemiyor ([accent]{0}[]).
connecting = [accent]Bağlanılıyor...
reconnecting = [accent]Yeniden Bağlanılıyor...
connecting.data = [accent]Dünya verisi yükleniyor...
server.port = Port:
-server.addressinuse = Adres zaten kullanılıyor!
server.invalidport = Geçersiz port sayısı!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Sunucu kurulamadı: [accent]{0}
save.new = Yeni kayıt
save.overwrite = Bu kaydın üstüne yazmak istediğine\nemin misin?
@@ -352,6 +355,7 @@ command.enterPayload = Kargo Bloğu Seç
command.loadUnits = Birim Yükle
command.loadBlocks = Blok Yükle
command.unloadPayload = Birim Bırak
+command.loopPayload = Loop Unit Transfer
stance.stop = Emri İptal Et
stance.shoot = Duruş: Saldırı
stance.holdfire = Duruş: Hazır Ol
@@ -495,6 +499,7 @@ waves.units.show = Hepsini Göster
wavemode.counts = miktarlar
wavemode.totals = toplamlar
wavemode.health = can
+all = All
editor.default = [lightgray]
details = Detaylar...
@@ -664,7 +669,6 @@ requirement.capture = {0} sektörünü ele geçir
requirement.onplanet = Sektör {0} Kontrol Et
requirement.onsector = Sektör {0}e İniş Yap
launch.text = Kalkış
-research.multiplayer = Sadece sunucu sahibi araştırma yapabilir.
map.multiplayer = Sadece sunucu sahibi sektörleri görebilir.
uncover = Aç
configure = Ekipmanı Yapılandır
@@ -733,6 +737,7 @@ error.mapnotfound = Harita dosyası bulunamadı!
error.io = Ağ I/O hatası.
error.any = Bilinmeyen ağ hatası.
error.bloom = Kamaşma başlatılamadı.\nCihazınız bu özelliği desteklemiyor olabilir.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Yağmur
weather.snowing.name = Kar
@@ -783,6 +788,11 @@ threat.medium = Orta
threat.high = Yüksek
threat.extreme = Aşırı
threat.eradication = İmkansız
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Gezegenler
@@ -805,9 +815,19 @@ sector.fungalPass.name = Mantar Geçidi
sector.biomassFacility.name = Sentetik BioMadde Santrali
sector.windsweptIslands.name = Rüzgarlı Adalar
sector.extractionOutpost.name = Kazı Üssü
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Gezegenler Arası Terminal
sector.coastline.name = Kıyı Şeridi
sector.navalFortress.name = Deniz Kalesi
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Yeniden başlamak için ideal bölge. Düşük düşman tehlikesi ve az miktarda kaynak mevcut. Mümkün olduğunca çok bakır ve kurşun topla.\nİlerle.
sector.frozenForest.description = Burada, dağlara yakın bölgelerde bile sporlar etrafa yayıldı. Dondurucu soğuk onları sonsuza dek durduramaz.\n\nEnerji kullanmaya başla. Termik jeneratörler inşa et. Tamircileri kullanmayı öğren.
@@ -827,6 +847,18 @@ sector.impact0078.description = Burası, eskiden buraya düşmüş bir yıldızl
sector.planetaryTerminal.description = Son aşama.\n\nBu üs, başka gezegenlere gitmeyi sağlayan teknolojiyi barıdırıyor. Aşırı iyi bir şekilde korunuyor.\n\nOlabildiğince hızlı bir şekilde gemi üret ve düşman üssü elegeçir. Gezegenler Arası Hızladırıcıyı aç!
sector.coastline.description = Bu bölgede denizel birim teknoloji kalıntıları tespit edildi. Düşman saldırılarını püskürt, sektörü ele geçir ve teknolojiyi kurtar.
sector.navalFortress.description = Düşman bu uzak adaya doğal olarak korunan bir üs kurmuş. Bu üssü yok et. Onların gelişmiş savaş gemisi teknolojilerini elde et ve araştır.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = Yeni Başlangıç
sector.aegis.name = Siper
sector.lake.name = Göletçik
@@ -1023,6 +1055,7 @@ ability.liquidexplode = Son İsyan
ability.liquidexplode.description = Ölürken sıvı fışkırtır
ability.stat.firingrate = [stat]{0}/sn[lightgray] ateş hızı
ability.stat.regen = [stat]{0}[lightgray] can/sn
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] kalkan
ability.stat.repairspeed = [stat]{0}/sn[lightgray] tamir hızı
ability.stat.slurpheal = [stat]{0}[lightgray] can/sıvı miktarı
@@ -1086,6 +1119,8 @@ bullet.healamount = [stat]{0}[lightgray] direkt tamir
bullet.multiplier = [stat]{0}[lightgray]x mermi çarpanı
bullet.reload = [stat]{0}[lightgray]x atış hızı
bullet.range = [stat]{0}[lightgray] blok menzil
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = blok
unit.blockssquared = blok²
@@ -1146,12 +1181,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Arayüz Ölçeği [lightgray](yeniden başlatma gerekebilir)[]
setting.uiscale.description = Değişikleri uygulamak için yeniden başlatma gerekli.
setting.swapdiagonal.name = Her Zaman Çapraz Yerleştirme
-setting.difficulty.training = Eğitim
-setting.difficulty.easy = Kolay
-setting.difficulty.normal = Normal
-setting.difficulty.hard = Zor
-setting.difficulty.insane = İmkansız
-setting.difficulty.name = Zorluk:
setting.screenshake.name = Ekran Sarsılması
setting.bloomintensity.name = Parlaklık Şiddeti
setting.bloomblur.name = Parlaklık Bulanıklılığı
@@ -1241,6 +1270,7 @@ keybind.unit_command_load_units.name = Birim Komutu: Birim Kargola
keybind.unit_command_load_blocks.name = Birim Komutu: Blok Kargola
keybind.unit_command_unload_payload.name = Birim Komutu: Kargo Boşalt
keybind.unit_command_enter_payload.name = Birim Komutu: Kargoya Gir
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Alanı Geri İşaa Et
keybind.schematic_select.name = Bölge Seç
keybind.schematic_menu.name = Şema Menüsü
@@ -1318,12 +1348,16 @@ rules.wavetimer = Dalga Zamanlayıcısı
rules.wavesending = Dalga Gönderiliyor
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Dalgalar
rules.airUseSpawns = Hava Birimleri doğuş bölgelerini kullanır
rules.attack = Saldırı Modu
rules.buildai = Üs inşa edici YZ
rules.buildaitier = İnşaatçı YZ sınıfı
rules.rtsai = RTS YZ
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Asgari Gurup Boyutu
rules.rtsmaxsquadsize = Azami Gurup Boyutu
rules.rtsminattackweight = Asgari Saldırı Boyutu
@@ -1366,6 +1400,9 @@ rules.title.teams = Takımlar
rules.title.planet = Gezegen
rules.lighting = Işıklandırma
rules.fog = Savaş Sisi
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Ateş
rules.anyenv =
rules.explosions = Blok/Birlik Patlama Hasarı
@@ -1374,6 +1411,7 @@ rules.weather = Hava Durumu
rules.weather.frequency = Sıklık:
rules.weather.always = Her zaman
rules.weather.duration = Süreklilik:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Oyuncuların düşman üssüne yakın inşa etmesini engeller. Bu, silah kurarken daha da fazla.
rules.onlydepositcore.info = Birimlerin Merkez dışında malzeme aktarmasını engeller.
@@ -1516,6 +1554,8 @@ block.graphite-press.name = Grafit Ezici
block.multi-press.name = Çoklu-Ezici
block.constructing = {0} [lightgray](İnşa Ediliyor)
block.spawn.name = Düşman Doğum Noktası
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Merkez: Parçacık
block.core-foundation.name = Merkez: Temel
block.core-nucleus.name = Merkez: Çekirdek
@@ -1774,6 +1814,7 @@ block.electric-heater.name = Elektrikli Isıtıcı
block.slag-heater.name = Cürüflü Isıtıcı
block.phase-heater.name = Faz Isıtıcı
block.heat-redirector.name = Isı Aktarıcı
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Isı Yönlendirici
block.slag-incinerator.name = Cürüf Yakıcı
block.carbide-crucible.name = Karbür Kazanı
@@ -1821,6 +1862,7 @@ block.chemical-combustion-chamber.name = Kimyasal Yanma Odası
block.pyrolysis-generator.name = Piroliz Jeneratörü
block.vent-condenser.name = Baca Sıkıştırıcı
block.cliff-crusher.name = Kayalık Delici
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Plazma Kayalık Kazıcı
block.large-plasma-bore.name = Büyük Plazma Kayalık Kazıcı
block.impact-drill.name = Darbeli Matkap
@@ -2049,6 +2091,10 @@ block.phase-wall.description = Özel faz örgüsü bazlı yansıtıcı materyal
block.phase-wall-large.description = Özel faz bazlı yansıtıcı bileşik ile kaplanmış bir duvar. Çoğu mermi çarpma anında geri sektirir.\nBirçok blok alan kaplar.
block.surge-wall.description = Son derece dayanıklı bir savunma bloğu.\nMermi temasıyla yükü toplar ve bu yükü rastgele serbest bırakır.
block.surge-wall-large.description = Son derece dayanıklı bir savunma bloğu.\nMermi temasıyla yükü toplar ve bu yükü rastgele serbest bırakır.\nBirçok blok alan kaplar.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Küçük bir kapı. Dokunarak açılabilir veya kapatılabilir.
block.door-large.description = Büyük bir kapı. Dokunarak açılabilir veya kapatılabilir.\nBirçok blok alan kaplar.
block.mender.description = Çevresindeki blokları periyodik olarak tamir eder. Savunmaları dalgalar arasında tamir eder.\nİsteğe bağlı olarak menzili ve verimi arttırmak için silikon kullanılabilir.
@@ -2176,6 +2222,7 @@ block.electric-heater.description = Önündeki bloğu ısıtır. Enerji gerektir
block.slag-heater.description = Önündeki bloğu ısıtır. Cürüf gerektirir.
block.phase-heater.description = Önündeki bloğu ısıtır. Faz gerektirir.
block.heat-redirector.description = Isıyı önündeki bloğa aktarır.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Isıyı üç yöne dağtırır.
block.electrolyzer.description = Suyu Oksijen ve Hidrojene ayırır. H₂O
block.atmospheric-concentrator.description = Atmosferden Nitrojen emcikler. Isı gerktirir.
@@ -2188,6 +2235,7 @@ block.vent-condenser.description = Baca gazlarını suya çevirir. Enerji gerekt
block.plasma-bore.description = Bir duvar madeninine bakarken sonsuza dek maden üretir. Az da olsa enerji gerektirir.
block.large-plasma-bore.description = Büyük bir duvar kazıcı. Tungsten ve Toryum kazabilir. Hidrojen ve Enerji gerektirir.
block.cliff-crusher.description = Duvarları parçalar ve Kum üretir. enerji gerektirir. Verimlilik duvar tipine göre değişir.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = Bir madenin üstüne konduğu zaman ara ara maden kazar. Enerji ve su gerektirir.
block.eruption-drill.description = Gelişmiş bir Matkap. Toryum kazabilir. Hidrojen gerektirir.
block.reinforced-conduit.description = Sıvıları iletir. Yandan başka borular dışında sıvı almaz.
@@ -2348,6 +2396,7 @@ lst.getflag = Evrensel İşaretli Numara Oku.
lst.setprop = Bir bina veya birime nitelik atar.
lst.effect = Parçacık efekti oluştur.
lst.sync = Ağ boyunca bir değişkeni senkronize et.\nSaniyede en fazla 10 kere yapılabilir.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Dünyada yeni bir İşlemci İşareti koy.\nBu İşarete bir Kimlik adamalısın.\nDünya başına 20.000 limit bulunmakta.
lst.setmarker = Bir İşlemci İşareti için bir arazi seç.\nKimlik, İşaret Koyucudaki ile aynı olmalı.
lst.localeprint = Harita yerel paket özellik değerini metin arabelleğine ekleyin.\nHarita düzenleyicide harita yerel ayar paketlerini ayarlamak için şunu işaretleyin: [accent]Harita Bilgisi > Yerel Paketler[].\nİstemci bir mobil cihazsa, önce ".mobile" ile biten bir özelliği yazdırmaya çalışır.
@@ -2518,6 +2567,7 @@ unitlocate.building = Bulunan binanın Türü.
unitlocate.outx = X kordinatı.
unitlocate.outy = Y kordinatı.
unitlocate.group = Aranan binanın türü.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Hareket etmez ancak kazmaya ve inşa etmeye devam eder.
lenum.stop = Dur!
diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties
index b50afe1626..3f01330580 100644
--- a/core/assets/bundles/bundle_uk_UA.properties
+++ b/core/assets/bundles/bundle_uk_UA.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Увімкнено
mod.disabled = [scarlet]Вимкнена
mod.multiplayer.compatible = [gray]Доступна у багатоосібній грі
mod.disable = Вимкнути
+mod.version = Version:
mod.content = Зміст:
mod.delete.error = Неможливо видалити модифікацію. Файл, можливо, використовується.
@@ -195,6 +196,7 @@ campaign.select = Виберіть початкову кампанію
campaign.none = [lightgray]Виберіть планету для старту.\nЇї можна змінити в будь-який момент.
campaign.erekir = Новіший, більш відшліфований зміст. Переважно лінійний розвиток кампанії.\n\nВища якість мап та ліпший загальний досвід.
campaign.serpulo = Старий зміст; класичний досвід. Більш відкрита.\n\nПотенційно незбалансовані мапи й механіки кампанії. Менш відшліфована.
+campaign.difficulty = Difficulty
completed = [accent]Завершено
techtree = Дерево технологій
techtree.select = Вибір дерева технологій
@@ -295,13 +297,14 @@ disconnect.error = Помилка з’єднання.
disconnect.closed = З’єднання закрито.
disconnect.timeout = Час вийшов.
disconnect.data = Не вдалося завантажити світові дані!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Не вдалося під’єднатися до гри ([accent]{0}[]).
connecting = [accent]Приєднання…
reconnecting = [accent]Повторне з’єднання…
connecting.data = [accent]Завантаження даних світу…
server.port = Порт:
-server.addressinuse = Ця адреса вже використовується!
server.invalidport = Недійсний номер порту!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]Помилка створення сервера.
save.new = Нове збереження
save.overwrite = Ви дійсно хочете перезаписати це місце збереження?
@@ -354,6 +357,7 @@ command.enterPayload = Увійти до вантажного блока
command.loadUnits = Завантажити одиниці
command.loadBlocks = Завантажити блоки
command.unloadPayload = Вивантажити вантаж
+command.loopPayload = Loop Unit Transfer
stance.stop = Скасувати накази
stance.shoot = Позиція: стріляти
stance.holdfire = Позиція: припинити вогонь
@@ -497,6 +501,7 @@ waves.units.show = Показати все
wavemode.counts = кількість
wavemode.totals = усього
wavemode.health = здоров’я
+all = All
editor.default = [lightgray]<За замовчуванням>
details = Подробиці…
@@ -667,7 +672,6 @@ requirement.capture = Захопіть {0}
requirement.onplanet = Установіть контроль над сектором на {0}
requirement.onsector = Приземліться на такий сектор: {0}
launch.text = Запуск
-research.multiplayer = Лише власник сервера має змогу досліджувати предмети.
map.multiplayer = Лише власник може переглядати сектори.
uncover = Розкрити
configure = Налаштувати вивантаження
@@ -741,6 +745,7 @@ error.mapnotfound = Файл мапи не знайдено!
error.io = Мережева помилка введення-виведення.
error.any = Невідома мережева помилка
error.bloom = Не вдалося ініціалізувати світіння.\nВаш пристрій, мабуть, не підтримує це.
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = Дощ
weather.snowing.name = Сніг
@@ -792,6 +797,11 @@ threat.medium = середня
threat.high = висока
threat.extreme = екстремальна
threat.eradication = викорінювальна
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = Планети
@@ -814,9 +824,19 @@ sector.fungalPass.name = Грибний перевал
sector.biomassFacility.name = Центр дослідження синтезу біомаси
sector.windsweptIslands.name = Вітряні острови
sector.extractionOutpost.name = Видобувна застава
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Термінал планетарного запуску
sector.coastline.name = Узбережжя
sector.navalFortress.name = Морська фортеця
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Оптимальне місце для повторних ігор. Низька ворожа загроза. Мало ресурсів.\nЗберіть якомога більше свинцю та міді.\nНе затримуйтесь і йдіть далі.
sector.frozenForest.description = Навіть тут, ближче до гір, уже поширилися спори. Холодна температура не змогла стримати їх назавжди.\n\nЗважтесь створити енергію. Побудуйте генератори внутрішнього згорання. Навчіться користуватися регенераторами.
@@ -836,6 +856,18 @@ sector.impact0078.description = Тут лежать залишки міжзор
sector.planetaryTerminal.description = Кінцева мета.\n\nЦя прибережна база містить структуру, здатну запускати ядра на навколишні планети. Надзвичайно добре охороняється.\n\nВиробляє військово-морські підрозділи. Усуньте ворога якомога швидше. Дослідіть структуру запуску.
sector.coastline.description = На цьому місці виявлено залишки військово-морських одиниць. Відбийте атаки супротивника, захопіть цей сектор та заволодійте технологією.
sector.navalFortress.description = Ворог створив базу на віддаленому, природно-укріпленому острові. Знищте цей форпост. Заволодійте їхніми передовими технологіями морських кораблів і дослідіть їх.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = Перший наступ
sector.aegis.name = Егіда
@@ -1034,6 +1066,7 @@ ability.liquidexplode = Смертельний розлив
ability.liquidexplode.description = Розливає рідину після смерті
ability.stat.firingrate = [lightgray]Швидкість стрільби[stat]{0} за сек.
ability.stat.regen = Відновлення здоров'я: [stat]{0} за сек.
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [lightgray]Щит: [stat]{0}
ability.stat.repairspeed = [lightgray]Швидкість відновлення: [stat]{0} за сек.
ability.stat.slurpheal = [lightgray]Здоров'я за одиницю рідини: [stat]{0}
@@ -1097,6 +1130,8 @@ bullet.healamount = [stat]{0}[lightgray] безпосереднього ремо
bullet.multiplier = [stat]{0}[lightgray]x патронів
bullet.reload = [stat]{0}%[lightgray] швидкість перезаряджання
bullet.range = [stat]{0}[lightgray] плиток
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = блоки
unit.blockssquared = блоків²
@@ -1157,12 +1192,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Масштабування користувацького інтерфейсу
setting.uiscale.description = Потрібен перезапуск для застосування змін.
setting.swapdiagonal.name = Завжди діагональне розміщення
-setting.difficulty.training = Навчання
-setting.difficulty.easy = Легка
-setting.difficulty.normal = Нормальна
-setting.difficulty.hard = Важка
-setting.difficulty.insane = Неможлива
-setting.difficulty.name = Складність:
setting.screenshake.name = Тряска екрану
setting.bloomintensity.name = Інтенсивність світіння
setting.bloomblur.name = Розмиття світіння
@@ -1252,6 +1281,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Команда одиниці: завантажити вантаж
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Відбудувати регіон
keybind.schematic_select.name = Вибрати ділянку
keybind.schematic_menu.name = Меню схем
@@ -1329,12 +1359,16 @@ rules.wavetimer = Таймер для хвиль
rules.wavesending = Ручне надсилання хвиль
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = Хвилі
rules.airUseSpawns = Air units use spawn points
rules.attack = Режим атаки
rules.buildai = Базовий ШІ-будівельник
rules.buildaitier = Рівень ШІ-будівельника
rules.rtsai = ШІ зі стратегій реального часу
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = Мінімальний розмір загону
rules.rtsmaxsquadsize = Максимальний розмір загону
rules.rtsminattackweight = Мінімальна ударна вага
@@ -1377,6 +1411,9 @@ rules.title.teams = Команди
rules.title.planet = Планета
rules.lighting = Світлотінь
rules.fog = Туман війни
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = Вогонь
rules.anyenv = <Будь-яка>
rules.explosions = Шкода від вибухів блоків і одиниць
@@ -1385,6 +1422,7 @@ rules.weather = Погода
rules.weather.frequency = Повторюваність:
rules.weather.always = Завжди
rules.weather.duration = Тривалість:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1529,6 +1567,8 @@ block.graphite-press.name = Графітний прес
block.multi-press.name = Мультипрес
block.constructing = {0}\n[lightgray](У процесі)
block.spawn.name = Місце появи противника
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = Ядро «Уламок»
block.core-foundation.name = Ядро «Штаб»
block.core-nucleus.name = Ядро «Атом»
@@ -1788,6 +1828,7 @@ block.electric-heater.name = Електричний нагрівач
block.slag-heater.name = Шлаковий нагрівач
block.phase-heater.name = Фазовий нагрівач
block.heat-redirector.name = Перенаправляч тепла
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Тепловий маршрутизатор
block.slag-incinerator.name = Шлаковий сміттєспалювальний завод
block.carbide-crucible.name = Карбідний тигель
@@ -1835,6 +1876,7 @@ block.chemical-combustion-chamber.name = Камера хімічного зго
block.pyrolysis-generator.name = Пиролізовий генератор
block.vent-condenser.name = Джерельний конденсатор
block.cliff-crusher.name = Дробарка скель
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Плазмовий бурильник
block.large-plasma-bore.name = Великий плазмовий бурильник
block.impact-drill.name = Імпульсний бур
@@ -2072,6 +2114,10 @@ block.phase-wall.description = Англійська назва: Phase Wall\nЗа
block.phase-wall-large.description = Англійська назва: Phase Wall Large\nЗахищає споруди від ворожих снарядів, відбиває більшість куль у разі зіткненні.
block.surge-wall.description = Англійська назва: Surge Wall\nЗахищає споруди від ворожих снарядів, періодично випускає електричні дуги в разі зіткненні.
block.surge-wall-large.description = Англійська назва: Surge Wall Large\nЗахищає споруди від ворожих снарядів, періодично випускає електричні дуги в разі зіткненні.
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = Англійська назва: Door\nСтіна, яку можна відчинити й зачинити.
block.door-large.description = Англійська назва: Door Large\nСтіна, яку можна відчинити й зачинити.
block.mender.description = Англійська назва: Mender\nПеріодично ремонтує блоки у своєму радіусі дії.\nЗа бажанням можна використати кремній задля підвищення радіусу дії й ефективності.
@@ -2201,6 +2247,7 @@ block.electric-heater.description = Англійська назва: Electric He
block.slag-heater.description = Англійська назва: Slag Heater\nНагріває лицьові блоки. Потребує шлаку.
block.phase-heater.description = Англійська назва: Phase Heater\nНагріває лицьові блоки. Потрібна фазова тканина.
block.heat-redirector.description = Англійська назва: Heat Redirector\nПеренаправляє отримане тепло на інші блоки.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Англійська назва: Heat Router\nРозподіляє отримане тепло в трьох вихідних напрямках.
block.electrolyzer.description = Англійська назва: Electrolyzer\nПеретворює воду на водень та озоновий газ.
block.atmospheric-concentrator.description = Англійська назва: Atmospheric Concentrator\nВбирає азот з атмосфери. Потребує тепла.
@@ -2213,6 +2260,7 @@ block.vent-condenser.description = Англійська назва: Vent Condens
block.plasma-bore.description = Англійська назва: Plasma Bore\nПри розміщенні лицем до рудної стіни видає предмети нескінченно довго. Потребує невеликої кількості енергії.
block.large-plasma-bore.description = Англійська назва: Large Plasma Bore\nБільший плазмовий бурильник. Здатний видобувати вольфрам і торій. Потребує водню та енергії.
block.cliff-crusher.description = Англійська назва: Cliff Crusher\nДробить стіни, виводячи пісок нескінченно довго. Вимагає енергію. Ефективність залежить від типу стіни.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = Англійська назва: Impact Drill\nПри розміщенні на руді видає предмети серіями до нескінченності. Потребує енергії та води.
block.eruption-drill.description = Англійська назва: Eruption Drill\nПоліпшений імпульсний бур. Здатний видобувати торій. Потребує водню.
block.reinforced-conduit.description = Англійська назва: Reinforced Conduit\nПереміщує рідини вперед. Не приймає нетрубоповідні входи з боків.
@@ -2375,6 +2423,7 @@ lst.getflag = Перевіряє, чи встановлено глобальни
lst.setprop = Установлює властивість одиниці чи будівлі.
lst.effect = Створює ефект частинок.
lst.sync = Синхронізувати змінну по мережі.\nВикликається щонайбільше 10 разів за секунду.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Створює новий логічний маркер у світі.\nПотрібно надати ідентифікатор для ідентифікації цього маркера.\nНаразі кількість маркерів на світ обмежена 20 тисячами.
lst.setmarker = Установлює властивість для маркера.\nВикористаний ідентифікатор має збігатися з інструкцією «Створити маркер».
lst.localeprint = Додає значення властивості мовного пакету мапи до текстового буфера.\nЩоби встановити мовного пакету мапи в редакторі мапи, перейдіть до [accent]Інформація про мапу > Мовні пакети [].\nЯкщо клієнтом є мобільний пристрій, то спочатку намагається надрукувати властивість, що закінчується на ".mobile".
@@ -2546,6 +2595,7 @@ unitlocate.building = Змінна для запису знайденої буд
unitlocate.outx = Виводить координату X.
unitlocate.outy = Виводить координату Y.
unitlocate.group = Група будівель для пошуку.
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = Зупиняти рух, проте продовжути будувати чи видобувати.\nСтан за замовчуванням.
lenum.stop = Зупинити або рух, або видобуток, або будівництво.
diff --git a/core/assets/bundles/bundle_vi.properties b/core/assets/bundles/bundle_vi.properties
index c9622ac982..61d04879e6 100644
--- a/core/assets/bundles/bundle_vi.properties
+++ b/core/assets/bundles/bundle_vi.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]Đã bật
mod.disabled = [red]Đã tắt
mod.multiplayer.compatible = [gray]Tương thích với chế độ nhiều người chơi
mod.disable = Tắt
+mod.version = Version:
mod.content = Nội dung:
mod.delete.error = Không thể xóa mod. Tệp có thể đang được sử dụng.
@@ -197,7 +198,8 @@ campaign.select = Chọn chiến dịch khởi đầu
campaign.none = [lightgray]Chọn một hành tinh để bắt đầu.\nCó thể thay đổi sang hành tinh khác bất cứ lúc nào.
campaign.erekir = Nội dung mới và được trau chuốt. Quá trình chiến dịch liền mạch hơn.\n\nKhó hơn. Bản đồ chất lượng hơn và trải nghiệm tổng thể tốt hơn.
campaign.serpulo = Nội dung cũ; trải nghiệm cơ bản. Tiến trình mở hơn, nhiều nội dung hơn.\n\nRất có thể vẫn còn cơ chế bản đồ và chiến dịch bị mất cân bằng. Ít được trau chuốt.
-completed = [accent]Hoàn tất
+campaign.difficulty = Độ khó
+completed = [accent]Đã nghiên cứu
techtree = Cây công nghệ
techtree.select = Chọn nhánh công nghệ
techtree.serpulo = Serpulo
@@ -230,7 +232,7 @@ server.kicked.customClient = Máy chủ này không hỗ trợ bản dựng tùy
server.kicked.gameover = Trò chơi kết thúc!
server.kicked.serverRestarting = Máy chủ đang khởi động lại.
server.versions = Phiên bản của bạn:[accent] {0}[]\nPhiên bản máy chủ:[accent] {1}[]
-host.info = Nút [accent]Mở máy chủ[] mở máy chủ trên cổng [scarlet]6567[]. \nBất kỳ ai trên cùng [lightgray]wifi hoặc mạng cục bộ[] sẽ có thể thấy máy chủ của bạn trong danh sách máy chủ của họ.\n\nNếu bạn muốn mọi người có thể kết nối từ mọi nơi bằng IP, [accent]điều hướng cổng (port forwarding)[] là bắt buộc.\n\n[lightgray]Lưu ý: Nếu ai đó đang gặp sự cố khi kết nối với máy chủ trong mạng LAN của bạn, đảm bảo rằng bạn đã cho phép Mindustry truy cập vào mạng cục bộ của mình trong cài đặt tường lửa. Lưu ý rằng các mạng công cộng đôi khi không cho phép khám phá máy chủ.
+host.info = Nút [accent]Mở máy chủ[] mở máy chủ trên cổng [scarlet]6567[].\nBất kỳ ai trên cùng [lightgray]wifi hoặc mạng cục bộ[] sẽ có thể thấy máy chủ của bạn trong danh sách máy chủ của họ.\n\nNếu bạn muốn mọi người có thể kết nối từ mọi nơi bằng IP, [accent]chuyển tiếp cổng (port forwarding)[] là bắt buộc.\n\n[lightgray]Lưu ý: Nếu ai đó đang gặp sự cố khi kết nối với máy chủ trong mạng LAN của bạn, đảm bảo rằng bạn đã cho phép Mindustry truy cập vào mạng cục bộ của mình trong cài đặt tường lửa. Lưu ý rằng các mạng công cộng đôi khi không cho phép khám phá máy chủ.
join.info = Tại đây, bạn có thể nhập [accent]IP máy chủ[] kết nối, hoặc khám phá [accent]mạng cục bộ[] hay kết nối đến máy chủ [accent]toàn cầu[].\nCả mạng LAN và WAN đều được hỗ trợ.\n\n[lightgray]Nếu bạn muốn kết nối với ai đó bằng IP, bạn sẽ cần phải hỏi IP của họ, có thể được tìm thấy bằng cách tra google với từ khóa "my ip" trên thiết bị của họ.
hostserver = Mở máy chủ nhiều người chơi
invitefriends = Mời bạn bè
@@ -299,13 +301,14 @@ disconnect.error = Lỗi kết nối.
disconnect.closed = Kết nối đã bị đóng.
disconnect.timeout = Hết thời gian chờ.
disconnect.data = Không tải được dữ liệu thế giới!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = Không thể tham gia trò chơi ([accent]{0}[]).
connecting = [accent]Đang kết nối...
reconnecting = [accent]Đang kết nối lại...
connecting.data = [accent]Đang tải dữ liệu thế giới...
server.port = Cổng:
-server.addressinuse = Địa chỉ đang được sử dụng!
server.invalidport = Số cổng không hợp lệ!
+server.error.addressinuse = [scarlet]Mở máy chủ trên cổng 6567 thất bại.[]\n\nChắc rằng không có máy chủ Mindustry nào đang chạy trên thiết bị hoặc mạng của bạn!
server.error = [scarlet]Lỗi tạo máy chủ.
save.new = Bản lưu mới
save.overwrite = Bạn có chắc muốn ghi đè\nbản lưu này?
@@ -358,6 +361,7 @@ command.enterPayload = Nhập Khối hàng vào Công trình
command.loadUnits = Nhận Đơn vị
command.loadBlocks = Nhận Khối công trình
command.unloadPayload = Dỡ Khối hàng
+command.loopPayload = Lặp vận chuyển đơn vị
stance.stop = Hủy Mệnh lệnh
stance.shoot = Tư thế: Bắn
stance.holdfire = Tư thế: Ngừng bắn
@@ -502,6 +506,7 @@ wavemode.counts = số lượng
wavemode.totals = tổng số
wavemode.health = độ bền
+all = Tất cả
editor.default = [lightgray]
details = Chi tiết...
edit = Chỉnh sửa
@@ -673,7 +678,6 @@ requirement.capture = Chiếm {0}
requirement.onplanet = Kiểm soát khu vực {0}
requirement.onsector = Đáp xuống khu vực: {0}
launch.text = Phóng
-research.multiplayer = Chỉ máy chủ mới có thể nghiên cứu các mục.
map.multiplayer = Chỉ máy chủ mới có thể xem các khu vực.
uncover = Khám phá
configure = Cấu hình vật phẩm khởi đầu
@@ -717,9 +721,9 @@ objective.enemyescelating = [accent]Kẻ địch leo thang sản xuất sau [lig
objective.enemyairunits = [accent]Kẻ địch bắt đầu sản xuất đơn vị bay sau [lightgray]{0}[]
objective.destroycore = [accent]Phá huỷ lõi kẻ địch
objective.command = [accent]Mệnh lệnh đơn vị
-objective.nuclearlaunch = [accent]⚠ Phát hiện việc phóng tên lửa hạt nhân: [lightgray]{0}
+objective.nuclearlaunch = [accent]⚠ Phát hiện việc phóng tên lửa: [lightgray]{0}
-announce.nuclearstrike = [red]⚠ TÊN LỬA HẠT NHÂN SẮP VA CHẠM ⚠\nxây lõi dự phòng ngay
+announce.nuclearstrike = [red]⚠ TÊN LỬA SẮP VA CHẠM ⚠\nxây lõi dự phòng ngay
loadout = Vật phẩm khởi đầu
resources = Tài nguyên
@@ -740,13 +744,14 @@ guardian = Trùm
connectfail = [scarlet]Lỗi kết nối:\n\n[accent]{0}
error.unreachable = Không thể truy cập máy chủ.\nĐịa chỉ liệu có đúng không?
error.invalidaddress = Địa chỉ không hợp lệ.
-error.timedout = Hết thời gian chờ!\nĐảm bảo máy chủ đã thiết lập điều hướng cổng, và địa chỉ đó là chính xác!
+error.timedout = Hết thời gian chờ!\nĐảm bảo máy chủ đã thiết lập chuyển tiếp cổng, và địa chỉ đó là chính xác!
error.mismatch = Lỗi gói tin:\nphiên bản máy khách/máy chủ có thể không khớp.\nĐảm bảo bạn và máy chủ có phiên bản Mindustry mới nhất!
error.alreadyconnected = Đã kết nối rồi.
error.mapnotfound = Không tìm thấy tệp bản đồ!
error.io = Lỗi mạng đầu vào/ra.
error.any = Lỗi mạng không xác định.
error.bloom = Không khởi tạo được hiệu ứng phát sáng.\nThiết bị của bạn có thể không hỗ trợ.
+error.moddex = Mindustry không thể nạp bản mod này.\nThiết bị của bạn đang chặn nhập mod Java do thay đổi gần đây trong Android.\nKhông có giải pháp tạm thời nào cho vấn đề này.
weather.rain.name = Mưa
weather.snowing.name = Tuyết
@@ -799,6 +804,12 @@ threat.high = Cao
threat.extreme = Cực cao
threat.eradication = Hủy diệt
+difficulty.casual = Giải trí
+difficulty.easy = Dễ
+difficulty.normal = Vừa
+difficulty.hard = Khó
+difficulty.eradication = Hủy diệt
+
planets = Hành tinh
planet.serpulo.name = Serpulo
@@ -820,9 +831,19 @@ sector.fungalPass.name = Fungal Pass
sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = Vị trí tối ưu để bắt đầu một lần nữa. Mối đe dọa của kẻ địch thấp. Ít tài nguyên.\nThu thập càng nhiều đồng và chì càng tốt.\nTiến lên.
sector.frozenForest.description = Dù ở đây, gần núi cao, các bào tử vẫn bắt đầu phát tán. Nhiệt độ lạnh giá không thể giữ chúng lại mãi.\n\nBắt đầu tạo năng lượng. Hãy xây dựng máy phát điện đốt. Học cách sử dụng máy sửa chữa.
@@ -842,6 +863,20 @@ sector.impact0078.description = Đây là tàn tích của tàu vận chuyển g
sector.planetaryTerminal.description = Mục tiêu cuối cùng.\n\nCăn cứ ven biển này chứa một cấu trúc có khả năng phóng các lõi tới các hành tinh lân cận. Nó được bảo vệ cực kỳ cẩn thận.\n\nSản xuất đơn vị hải quân. Loại bỏ kẻ địch càng nhanh càng tốt. Nghiên cứu cấu trúc phóng.
sector.coastline.description = Phát hiện tàn dư công nghệ của các đơn vị hải quân tại địa điểm này. Đẩy lùi các cuộc tấn công của kẻ địch, chiếm khu vực này, và lấy công nghệ.
sector.navalFortress.description = Kẻ địch đã thiết lập một căn cứ từ xa, trên đảo tự nhiên. Phá hủy tiền đồn này. Chiếm công nghệ chế tạo đơn vị hải quân tiên tiến của địch và nghiên cứu nó.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+
+#do not translate
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = The Onset
sector.aegis.name = Aegis
@@ -994,7 +1029,7 @@ stat.speed = Vận tốc
stat.buildspeed = Tốc độ xây
stat.minespeed = Tốc độ đào
stat.minetier = Cấp độ đào
-stat.payloadcapacity = Sức chứa khối hàng
+stat.payloadcapacity = Tải trọng
stat.abilities = Khả năng
stat.canboost = Có thể tăng cường
stat.flying = Bay
@@ -1041,7 +1076,8 @@ ability.liquidexplode.description = Tràn chất lỏng khi chết
ability.stat.firingrate = tốc độ bắn [stat]{0}/giây[lightgray]
ability.stat.regen = [stat]{0}[lightgray] độ bền/giây
-ability.stat.shield = [stat]{0}[lightgray] khiên
+ability.stat.pulseregen = [stat]{0}[lightgray] độ bền/xung nhịp
+ability.stat.shield = [stat]{0}[lightgray] khiên tối đa
ability.stat.repairspeed = [stat]{0}/giây[lightgray] tốc độ sửa chữa
ability.stat.slurpheal = [stat]{0}[lightgray] độ bền/đơn vị chất lỏng
ability.stat.cooldown = [stat]{0} giây[lightgray] hồi phục
@@ -1057,7 +1093,7 @@ bar.drilltierreq = Cần máy khoan tốt hơn
bar.noresources = Thiếu tài nguyên
bar.corereq = Yêu cầu lõi cơ bản
bar.corefloor = Yêu cầu ô nền lõi
-bar.cargounitcap = Đã đạt sức chứa khối hàng tối đa
+bar.cargounitcap = Đã đạt tải trọng tối đa
bar.drillspeed = Tốc độ khoan: {0}/giây
bar.pumpspeed = Tốc độ bơm: {0}/giây
bar.efficiency = Hiệu suất: {0}%
@@ -1104,6 +1140,8 @@ bullet.healamount = [stat]{0}[lightgray] sửa chữa trực tiếp
bullet.multiplier = [stat]{0}[lightgray] đạn/vật phẩm
bullet.reload = [stat]{0}%[lightgray] tốc độ bắn
bullet.range = [stat]{0}[lightgray] ô phạm vi
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = khối
unit.blockssquared = khối²
@@ -1164,12 +1202,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = Tỉ lệ giao diện
setting.uiscale.description = Cần khởi động lại để áp dụng các thay đổi.
setting.swapdiagonal.name = Luôn đặt theo đường chéo
-setting.difficulty.training = Luyện tập
-setting.difficulty.easy = Dễ
-setting.difficulty.normal = Vừa
-setting.difficulty.hard = Khó
-setting.difficulty.insane = Điên loạn
-setting.difficulty.name = Độ khó:
setting.screenshake.name = Rung chuyển khung hình
setting.bloomintensity.name = Mức độ phát sáng
setting.bloomblur.name = Xoá mờ phát sáng
@@ -1261,6 +1293,7 @@ keybind.unit_command_load_units.name = Mệnh lệnh đơn vị: Nhập đơn v
keybind.unit_command_load_blocks.name = Mệnh lệnh đơn vị: Nhập khối công trình
keybind.unit_command_unload_payload.name = Mệnh lệnh đơn vị: Dỡ khối hàng
keybind.unit_command_enter_payload.name = Mệnh lệnh đơn vị: Vào khối hàng
+keybind.unit_command_loop_payload.name = Mệnh lệnh đơn vị: Lặp vận chuyển đơn vi
keybind.rebuild_select.name = Xây dựng lại khu vực
keybind.schematic_select.name = Chọn khu vực
@@ -1327,75 +1360,83 @@ mode.attack.description = Phá hủy căn cứ của kẻ địch. \n[gray]Cần
mode.custom = Tùy chỉnh quy tắc
rules.invaliddata = Dữ liệu bộ nhớ tạm không hợp lệ.
-rules.hidebannedblocks = Ẩn các khối bị cấm
-rules.infiniteresources = Tài nguyên vô hạn
-rules.onlydepositcore = Chỉ cho phép đưa tài nguyên vào lõi
-rules.derelictrepair = Cho phép sửa khối bỏ hoang
-rules.reactorexplosions = Nổ lò phản ứng
-rules.coreincinerates = Hủy vật phẩm khi lõi đầy
-rules.disableworldprocessors = Vô hiệu hoá bộ xử lý thế giới
-rules.schematic = Cho phép dùng bản thiết kế
-rules.wavetimer = Đếm ngược đợt
+rules.hidebannedblocks = Ẩn Các Khối Bị Cấm
+rules.infiniteresources = Tài Nguyên Vô Hạn
+rules.onlydepositcore = Chỉ Cho Phép Đưa Tài Nguyên Vào Lõi
+rules.derelictrepair = Cho Phép Sửa Khối Bỏ Hoang
+rules.reactorexplosions = Nổ Nò Phản Ứng
+rules.coreincinerates = Hủy Vật Phẩm Khi Lõi Đầy
+rules.disableworldprocessors = Vô Hiệu Hoá Bộ Xử Lý Thế Giới
+rules.schematic = Cho Phép Dùng Bản Thiết Kế
+rules.wavetimer = Đếm Ngược Đợt
rules.wavesending = Gửi đợt
-rules.allowedit = Cho phép sửa quy tắc
+rules.allowedit = Cho Phép Sửa Quy Tắc
rules.allowedit.info = Khi được bật, người chơi có thể chỉnh sửa các quy tắc trong lúc chơi thông qua nút ở góc dưới bên trái của Trình đơn tạm dừng.
+rules.alloweditworldprocessors = Cho Phép Chỉnh Sửa Bộ Xử Lý Thế Giới
+rules.alloweditworldprocessors.info = Khi bật, Bộ xử lý thế giới có thể được đặt và chỉnh sửa ngay cả bên ngoài trình chỉnh sửa.
rules.waves = Đợt
-rules.airUseSpawns = Các đơn vị không quân dùng điểm xuất hiện
-rules.attack = Chế độ tấn công
-rules.buildai = AI Xây dựng căn cứ
-rules.buildaitier = Cấp độ AI xây dựng
-rules.rtsai = AI Chiến thuật [red](WIP - Đang hoàn thiện)
-rules.rtsminsquadsize = Kích thước đội hình tối thiểu
-rules.rtsmaxsquadsize = Kích thước đội hình tối đa
-rules.rtsminattackweight = Sức tấn công tối thiểu
-rules.cleanupdeadteams = Dọn sạch công trình của đội bị đánh bại (PvP)
-rules.corecapture = Chiếm lõi khi phá hủy
-rules.polygoncoreprotection = Bảo vệ lõi kiểu đa giác
-rules.placerangecheck = Kiểm tra phạm vi xây dựng
-rules.enemyCheat = Tài nguyên kẻ địch vô hạn
-rules.blockhealthmultiplier = Hệ số độ bền khối
-rules.blockdamagemultiplier = Hệ số sát thương của khối
-rules.unitbuildspeedmultiplier = Hệ số tốc độ sản xuất đơn vị
-rules.unitcostmultiplier = Hệ số chi phí sản xuất đơn vị
-rules.unithealthmultiplier = Hệ số độ bền của đơn vị
-rules.unitdamagemultiplier = Hệ số sát thương của đơn vị
-rules.unitcrashdamagemultiplier = Hệ số sát thương của đơn vị khi bị bắn rơi
-rules.solarmultiplier = Hệ số năng lượng mặt trời
-rules.unitcapvariable = Lõi tăng giới hạn đơn vị
-rules.unitpayloadsexplode = Khối hàng mang theo phát nổ cùng đơn vị
-rules.unitcap = Giới hạn đơn vị ban đầu
-rules.limitarea = Giới hạn kích thước bản đồ
-rules.enemycorebuildradius = Bán kính không xây dựng từ lõi của kẻ địch:[lightgray] (ô)
-rules.wavespacing = Giãn cách đợt:[lightgray] (giây)
-rules.initialwavespacing = Giãn cách đợt đầu:[lightgray] (giây)
-rules.buildcostmultiplier = Hệ số chi phí xây dựng
-rules.buildspeedmultiplier = Hệ số tốc độ xây dựng
-rules.deconstructrefundmultiplier = Hệ số số hoàn trả khi phá dỡ
-rules.waitForWaveToEnd = Đợt chờ hết kẻ địch
-rules.wavelimit = Bản đồ kết thúc sau đợt
-rules.dropzoneradius = Bán kính vùng thả:[lightgray] (ô)
-rules.unitammo = Đơn vị cần đạn [red](có thể bị loại bỏ)
-rules.enemyteam = Đội kẻ địch
-rules.playerteam = Đội người chơi
+rules.airUseSpawns = Các Đơn Vị Không Quân Dùng Điểm Xuất Hiện
+rules.attack = Chế Độ Tấn Công
+rules.buildai = AI Xây Dựng Căn Cứ
+rules.buildaitier = Cấp Độ AI Xây Dựng
+rules.rtsai = AI Chiến Thuật [red](WIP - Đang hoàn thiện)
+rules.rtsai.campaign = AI chiến thuật tấn công
+rules.rtsai.campaign.info = Trong bản đồ kiểu tấn công, làm các đơn vị tập hợp nhóm và tấn công căn cứ người chơi theo phương pháp thông minh hơn.
+rules.rtsminsquadsize = Kích Thước Đội Hình Tối Thiểu
+rules.rtsmaxsquadsize = Kích Thước Đội Hình Tối Đa
+rules.rtsminattackweight = Sức Tấn Công Tối Thiểu
+rules.cleanupdeadteams = Dọn Sạch Công Trình Của Đội Bị Đánh Bại (PvP)
+rules.corecapture = Chiếm Lõi Khi Phá Hủy
+rules.polygoncoreprotection = Bảo Vệ Lõi Kiểu Đa Giác
+rules.placerangecheck = Kiểm Tra Phạm Vi Xây Dựng
+rules.enemyCheat = Tài Nguyên Kẻ Địch Vô Hạn
+rules.blockhealthmultiplier = Hệ Số Độ Bền Khối
+rules.blockdamagemultiplier = Hệ Số Sát Thương Của Khối
+rules.unitbuildspeedmultiplier = Hệ Số Tốc Độ Sản Xuất Đơn Vị
+rules.unitcostmultiplier = Hệ Số Chi Phí Sản Xuất Đơn Vị
+rules.unithealthmultiplier = Hệ Số Độ Bền Của Đơn Vị
+rules.unitdamagemultiplier = Hệ Số Sát Thương Của Đơn Vị
+rules.unitcrashdamagemultiplier = Hệ Số Sát Thương Của Đơn Vị Khi Bị Bắn Rơi
+rules.solarmultiplier = Hệ Số Năng Lượng Mặt Trời
+rules.unitcapvariable = Lõi Tăng Giới Hạn Đơn Vị
+rules.unitpayloadsexplode = Khối Hàng Mang Theo Phát Nổ Cùng Đơn Vị
+rules.unitcap = Giới Hạn Đơn Vị Ban Đầu
+rules.limitarea = Giới Hạn Kích Thước Bản Đồ
+rules.enemycorebuildradius = Bán Kính Không Xây Dựng Từ Lõi Của Kẻ Địch:[lightgray] (ô)
+rules.wavespacing = Giãn Cách Đợt:[lightgray] (giây)
+rules.initialwavespacing = Giãn Cách Đợt Đầu:[lightgray] (giây)
+rules.buildcostmultiplier = Hệ Số Chi Phí Xây Dựng
+rules.buildspeedmultiplier = Hệ Số Tốc Độ Xây Dựng
+rules.deconstructrefundmultiplier = Hệ Số Hoàn Trả Khi Phá Dỡ
+rules.waitForWaveToEnd = Đợt Chờ Hết Kẻ Địch
+rules.wavelimit = Bản Đồ Kết Thúc Sau Đợt
+rules.dropzoneradius = Bán Kính Vùng Thả:[lightgray] (ô)
+rules.unitammo = Đơn Vị Cần Có Đạn [red](có thể bị loại bỏ)
+rules.enemyteam = Đội Kẻ Địch
+rules.playerteam = Đội Người Chơi
rules.title.waves = Đợt
-rules.title.resourcesbuilding = Tài nguyên & Xây dựng
-rules.title.enemy = Kẻ địch
-rules.title.unit = Đơn vị
-rules.title.experimental = Thử nghiệm
-rules.title.environment = Môi trường
+rules.title.resourcesbuilding = Tài Nguyên & Xây Dựng
+rules.title.enemy = Kẻ Dịch
+rules.title.unit = Đơn Vị
+rules.title.experimental = Thử Nghiệm
+rules.title.environment = Môi Trường
rules.title.teams = Đội
-rules.title.planet = Hành tinh
-rules.lighting = Ánh sáng
-rules.fog = Sương mù chiến tranb
+rules.title.planet = Hành Tinh
+rules.lighting = Ánh Sáng
+rules.fog = Sương Mù Chiến Tranh
+rules.invasions = Kẻ Địch Xâm Lược Khu Vực
+rules.showspawns = Hiện Khu Kẻ Địch Xuất Hiện
+rules.randomwaveai = Đợt Tấn Công AI Không Đoán Trước
rules.fire = Lửa
rules.anyenv =
-rules.explosions = Sát thương nổ của Khối/Đơn vị
-rules.ambientlight = Ánh sáng môi trường
-rules.weather = Thời tiết
-rules.weather.frequency = Tần suất:
-rules.weather.always = Luôn luôn
-rules.weather.duration = Thời gian:
+rules.explosions = Sát Thương Nổ Của Khối/Đơn Vị
+rules.ambientlight = Ánh Sáng Môi Trường
+rules.weather = Thời Tiết
+rules.weather.frequency = Tần Suất:
+rules.weather.always = Luôn Có
+rules.weather.duration = Thời Lượng:
+rules.randomwaveai.info = Làm các đơn vị xuất hiện trong các lượt nhắm vào công trình ngẫu nhiên thay vì tấn công trực tiếp vào lõi hoặc máy phát năng lượng.
rules.placerangecheck.info = Ngăn chặn người chơi khỏi việc đặt bất kỳ thứ gì gần công trình kẻ địch. Khi cố đặt một bệ súng, phạm vi sẽ bị tăng lên, để bệ súng không thể bắn tới kẻ địch.
rules.onlydepositcore.info = Ngăn chặn các đơn vị khỏi việc thả vật phẩm vào bất kỳ công trình nào ngoài lõi.
@@ -1440,8 +1481,8 @@ liquid.neoplasm.name = Tế bào tân sinh
liquid.arkycite.name = Arkycite
liquid.gallium.name = Gali
liquid.ozone.name = Ôzôn
-liquid.hydrogen.name = Hydro
-liquid.nitrogen.name = Nitro
+liquid.hydrogen.name = Hy-dro lỏng
+liquid.nitrogen.name = Ni-tơ lỏng
liquid.cyanogen.name = Cyano
unit.dagger.name = Dagger
@@ -1540,6 +1581,8 @@ block.graphite-press.name = Máy nén than chì
block.multi-press.name = Máy nén than chì lớn
block.constructing = {0} [lightgray](Đang xây dựng)
block.spawn.name = Điểm tạo ra kẻ địch
+block.remove-wall.name = Loại bỏ tường
+block.remove-ore.name = Loại bỏ khoáng sản
block.core-shard.name = Lõi: Cơ sở
block.core-foundation.name = Lõi: Trụ sở
block.core-nucleus.name = Lõi: Trung tâm
@@ -1799,6 +1842,7 @@ block.electric-heater.name = Máy nhiệt từ điện
block.slag-heater.name = Máy nhiệt từ xỉ
block.phase-heater.name = Máy nhiệt từ lượng tử
block.heat-redirector.name = Khối điều hướng nhiệt
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Khối phân phát nhiệt
block.slag-incinerator.name = Lò xỉ huỷ vật phẩm
block.carbide-crucible.name = Máy nấu Carbide
@@ -1846,6 +1890,7 @@ block.chemical-combustion-chamber.name = Bể điện hoá
block.pyrolysis-generator.name = Máy phát điện nhiệt phân
block.vent-condenser.name = Máy ngưng tụ hơi nước
block.cliff-crusher.name = Máy nghiền vách đá
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = Khoan plasma
block.large-plasma-bore.name = Khoan plasma lớn
block.impact-drill.name = Máy khoan động lực
@@ -1999,7 +2044,7 @@ split.container = Tương tự như thùng chứa, đơn vị cũng có thể đ
item.copper.description = Dùng trong tất cả các loại xây dựng và các loại đạn dược.
item.copper.details = Đồng. Kim loại nhiều bất thường trên Serpulo. Có cấu trúc yếu trừ khi được tôi luyện.
item.lead.description = Được dùng trong vận chuyển chất lỏng và cấu trúc liên quan đến điện.
-item.lead.details = Đặc. Trơ. Dùng cực nhiều trong pin.\nLưu ý: Có thể độc hại đối với các dạng sống sinh học. Không phải vì nó còn nhiều ở xung quanh đây.
+item.lead.details = Đặc. Trơ. Dùng cực nhiều trong pin.\nLưu ý: Có thể độc hại đối với các dạng sống sinh học; không phải vì nó còn nhiều ở xung quanh đây.
item.metaglass.description = Được dùng trong cấu trúc phân phối/lưu trữ chất lỏng.
item.graphite.description = Được dùng trong các bộ phận điện và đạn súng.
item.sand.description = Được dùng để sản xuất các vật liệu tinh chế khác.
@@ -2080,6 +2125,10 @@ block.phase-wall.description = Bảo vệ các công trình khỏi đạn của
block.phase-wall-large.description = Bảo vệ các công trình khỏi đạn của kẻ địch, phản hầu hết đạn khi va chạm.
block.surge-wall.description = Bảo vệ các công trình khỏi đạn của kẻ địch, thường phóng ra các tia điện khi đạn va chạm.
block.surge-wall-large.description = Bảo vệ các công trình khỏi đạn của kẻ địch, thường phóng ra các tia điện khi đạn va chạm.
+block.scrap-wall.description = Bảo vệ các công trình khỏi đạn của kẻ địch.
+block.scrap-wall-large.description = Bảo vệ các công trình khỏi đạn của kẻ địch.
+block.scrap-wall-huge.description = Bảo vệ các công trình khỏi đạn của kẻ địch.
+block.scrap-wall-gigantic.description = Bảo vệ các công trình khỏi đạn của kẻ địch.
block.door.description = Một bức tường có thể mở và đóng.
block.door-large.description = Một bức tường có thể mở và đóng.
block.mender.description = Sửa chữa định kỳ các khối trong vùng lân cận.\nTùy chọn sử dụng silicon để tăng phạm vi và hiệu quả.
@@ -2196,7 +2245,7 @@ block.core-acropolis.description = Trung tâm của căn cứ. Được bọc gi
block.breach.description = Bắn đạn beryl hoặc tungsten xuyên thấu vào kẻ địch.
block.diffuse.description = Bắn một loạt đạn mảnh theo hình nón. Đẩy kẻ địch về phía sau.
block.sublimate.description = Thổi tia lửa mạnh liên tục vào kẻ địch. Xuyên giáp.
-block.titan.description = Bắn đạn pháo nổ khổng lồ vào các mục tiêu trên mặt đất. Yêu cầu hydro.
+block.titan.description = Bắn đạn pháo nổ khổng lồ vào các mục tiêu trên mặt đất. Yêu cầu hy-đrô lỏng.
block.afflict.description = Bắn ra các mảnh vỡ của một quả cầu tích điện khổng lồ. Yêu cầu nhiệt.
block.disperse.description = Bắn các mảnh vỡ vào các mục tiêu trên không.
block.lustre.description = Bắn một tia laser di chuyển chậm một mục tiêu vào các mục tiêu của địch.
@@ -2209,26 +2258,28 @@ block.electric-heater.description = Làm nóng công trình. Yêu cầu một l
block.slag-heater.description = Làm nóng công trinh. Yêu cầu xỉ.
block.phase-heater.description = Làm nóng công trình. Yêu cầu sợi lượng tử.
block.heat-redirector.description = Chuyển lượng nhiệt nhận được sang các khối khác.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Phân phát nhiệt nhận được sang ba hướng đầu ra.
-block.electrolyzer.description = Chuyển đổi nước thành hydro và ôzôn. Các khí xuất hai hướng đối nhau, được đánh dấu bằng các màu tương ứng.
-block.atmospheric-concentrator.description = Cô đặc nitro từ khí quyển. Yêu cầu nhiệt.
+block.electrolyzer.description = Chuyển đổi nước thành hy-đrô lỏng và khí ô-zôn. Các khí xuất hai hướng đối nhau, được đánh dấu bằng các màu tương ứng.
+block.atmospheric-concentrator.description = Cô đặc ni-tơ từ khí quyển. Yêu cầu nhiệt.
block.surge-crucible.description = Tinh chế hợp kim từ xỉ và silicon. Yêu cầu nhiệt.
block.phase-synthesizer.description = Tổng hợp sợi lượng tử từ thori, cát, và ôzôn. Yêu cầu nhiệt.
block.carbide-crucible.description = Kết hợp than chì và tungsten để tạo ra carbide. Yêu cầu nhiệt.
block.cyanogen-synthesizer.description = Tổng hợp cyano từ arkycite và than chì. Yêu cầu nhiệt.
block.slag-incinerator.description = Đốt các vật phẩm hoặc chất lỏng không bay hơi. Yêu cầu xỉ.
block.vent-condenser.description = Ngưng tụ khí từ lỗ hơi nước để tạo ra nước. Tiêu thụ điện.
-block.plasma-bore.description = Khi được đặt đối diện với một bức tường quặng, sản xuất vô hạn vật phẩm. Yêu cầu một lượng điện nhỏ.\nTùy chọn sử dụng hydro để tăng hiệu suất.
-block.large-plasma-bore.description = Một máy khoan plasma lớn hơn. Có thể khoan tungsten và thori. Yêu cầu hydro và điện.\nTùy chọn sử dụng nitro để tăng hiệu suất.
+block.plasma-bore.description = Khi được đặt đối diện với một bức tường quặng, sản xuất vô hạn vật phẩm. Yêu cầu một lượng điện nhỏ.\nTùy chọn sử dụng hy-đrô lỏng để tăng hiệu suất.
+block.large-plasma-bore.description = Một máy khoan plasma lớn hơn. Có thể khoan tungsten và thori. Yêu cầu hy-đrô lỏng và điện.\nTùy chọn sử dụng ni-tơ lỏng để tăng hiệu suất.
block.cliff-crusher.description = Nghiền vách đá, xuất ra cát vô hạn. Yêu cầu năng lượng. Hiệu quả thay đổi dựa theo loại vách đá.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = Khi được đặt lên một loại quặng, sản xuất vô hạn vật phẩm. Yêu cầu điện và nước.
-block.eruption-drill.description = Phiên bản cải tiến của máy khoan động lực. Có thể khoan thori. Yêu cầu hydro.
+block.eruption-drill.description = Phiên bản cải tiến của máy khoan động lực. Có thể khoan thori. Yêu cầu hy-đrô lỏng.
block.reinforced-conduit.description = Di chuyển chất lỏng về phía trước. Không nhận đầu vào nếu không phải ống dẫn từ các bên.
block.reinforced-liquid-router.description = Phân chia chất lỏng đều cho tất cả các bên.
block.reinforced-liquid-tank.description = Lưu trữ một lượng chất lỏng lớn.
block.reinforced-liquid-container.description = Lưu trữ một lượng chất lỏng vừa phải.
block.reinforced-bridge-conduit.description = Vận chuyển chất lỏng qua các công trình và địa hình.
-block.reinforced-pump.description = Bơm chất lỏng lên. Yêu cầu hydro.
+block.reinforced-pump.description = Bơm chất lỏng lên. Yêu cầu hy-đrô lỏng.
block.beryllium-wall.description = Bảo vệ các công trình khỏi đạn của kẻ địch.
block.beryllium-wall-large.description = Bảo vệ các công trình khỏi đạn của kẻ địch.
block.tungsten-wall.description = Bảo vệ các công trình khỏi đạn của kẻ địch.
@@ -2259,7 +2310,7 @@ block.pyrolysis-generator.description = Tạo ra một lượng điện lớn t
block.flux-reactor.description = Tạo ra một lượng điện lớn khi được làm nóng. Yêu cầu sử dụng cyano như một chất làm ổn định. Lượng điện tạo ra và lượng tiêu thụ cyano tỷ lệ thuận với lượng nhiệt nhận được.\nPhát nổ nếu không cung cấp đủ cyano.
block.neoplasia-reactor.description = Sử dụng arkycite, nước và sợi lượng tử để tạo ra lượng điện khổng lồ. Tạo ra nhiệt và lượng tế bào tân sinh nguy hiểm như sản phẩm phụ trong quá trình hoạt động.\nPhát nổ dữ dội nếu tế bào tân sinh không được loại bỏ khỏi lò phản ứng.
block.build-tower.description = Tự động xây dựng lại các công trình trong phạm vi và hỗ trợ các đơn vị khác trong quá trình xây dựng.
-block.regen-projector.description = Sửa chữa các công trình một cách chậm rãi trong phạm vi hình vuông. Yêu cầu hydro.\nTùy chọn sử dụng sợi lượng tử để tăng hiệu suất.
+block.regen-projector.description = Sửa chữa các công trình một cách chậm rãi trong phạm vi hình vuông. Yêu cầu hy-đrô lỏng.\nTùy chọn sử dụng sợi lượng tử để tăng hiệu suất.
block.reinforced-container.description = Lưu trữ một lượng nhỏ vật phẩm. Nội dung có thể được lấy ra thông qua các điểm dỡ hàng. Không làm tăng khả năng lưu trữ của lõi.
block.reinforced-vault.description = Lưu trữ một lượng lớn vật phẩm. Nội dung có thể được lấy ra thông qua các điểm dỡ hàng. Không làm tăng khả năng lưu trữ của lõi.
block.tank-fabricator.description = Chế tạo đơn vị Stell. Các đơn vị được chế tạo có thể được sử dụng trực tiếp hoặc được chuyển vào các máy tái chế tạo khác để được nâng cấp.
@@ -2376,13 +2427,14 @@ lst.setrate = Đặt tốc độ thực thi khối xử lý theo chỉ lệnh/t
lst.fetch = Tra cứu các đơn vị, lõi, người chơi hoặc công trình bằng chỉ số.\nCác chỉ số bắt đầu từ 0 và kết thúc tại số lượng đếm của chúng.
lst.packcolor = Đóng gói màu thành phần RGBA [0, 1] thành một số đơn dùng cho vẽ hoặc thiết lập quy tắc.
lst.setrule = Thiết đặt một quy tắc trò chơi.
-lst.flushmessage = Hiển thị một tin nhắn trên màn hình từ bộ đệm văn bản.\nSẽ đợi cho đến khi tin nhắn trước đó hoàn tất.
+lst.flushmessage = Hiển thị một tin nhắn trên màn hình từ bộ đệm văn bản.\nNếu giá trị [accent]thành công[] (success) trả về là [accent]@wait[],\nsẽ đợi cho đến khi tin nhắn trước đó hoàn tất.\nNgược lại, xuất ra liệu rằng tin nhắn đã hiển thị thành công.
lst.cutscene = Điều khiển máy quay của người chơi.
lst.setflag = Thiết đặt một cờ toàn cục mà có thể đọc được bởi tất cả khối xử lý.
lst.getflag = Kiểm tra nếu cờ toàn cục được đặt.
lst.setprop = Thiết đặt một thuộc tính của đơn vị hoặc công trình.
lst.effect = Tạo một phần hiệu ứng nhỏ.
lst.sync = Đồng bộ biến số qua mạng.\nChỉ gọi tối đa 20 lần mỗi giây cho mỗi biến.
+lst.playsound = Phát một âm thanh.\nÂm lượng và hướng xoay có thể là một giá trị toàn cục, hoặc được tính toán dựa vào vị trí.
lst.makemarker = Tạo mới điểm đánh dấu logic trên thế giới.\nMột định danh cho điểm đánh dấu này phải được cung cấp.\nĐiểm đánh dấu hiện tại bị giới hạn 20,000 trên mỗi thế giới.
lst.setmarker = Thiết đặt một thuộc tính cho một điểm đánh dấu.\nĐịnh danh phải giống như định danh ở chỉ lệnh Tạo Điểm đánh dấu (Make Marker).\nGiá trị [accent]null[] sẽ bị phớt lờ.
lst.localeprint = Thêm một giá trị thuộc tính ngôn ngữ của bản đồ vào bộ đệm văn bản.\nĐể thiết đặt gói ngôn ngữ trong trình chỉnh sửa bản đồ, xem qua [accent]Thông tin bản đồ > Gói ngôn ngữ[].\nNếu máy khách là một thiết bị di động, sẽ cố in thuộc tính kết thúc bằng ".mobile" trước tiên.
@@ -2562,6 +2614,8 @@ unitlocate.outx = Tọa độ X xuất ra.
unitlocate.outy = Tọa độ Y xuất ra.
unitlocate.group = Nhóm công trình để tìm kiếm.
+playsound.limit = Nếu [accent]true[], ngăn âm thanh này phát\nnếu nó đã phát trong chung một khung hình.
+
lenum.idle = Không di chuyển, nhưng vẫn xây dựng/đào.\nTrạng thái mặc định.
lenum.stop = Dừng di chuyển/đào/xây dựng.
lenum.unbind = Vô hiệu hóa hoàn toàn điều khiển logic.\nKhôi phục AI tiêu chuẩn.
diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties
index 60a25dd6d4..87330afaf7 100644
--- a/core/assets/bundles/bundle_zh_CN.properties
+++ b/core/assets/bundles/bundle_zh_CN.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]已启用
mod.disabled = [scarlet]未启用
mod.multiplayer.compatible = [gray]多人游戏兼容性
mod.disable = 禁用
+mod.version = Version:
mod.content = 内容:
mod.delete.error = 无法删除模组。 文件可能正被占用。
@@ -196,6 +197,7 @@ campaign.select = 选择战役出发点
campaign.none = [lightgray]选择初始星球。\n可以在任意时刻切换。
campaign.erekir = 更新,更精致的内容。 战役大部分是线性的。\n\n难度更高,但地图质量与整体体验也更好。
campaign.serpulo = 较旧的内容; 经典的体验。 更加开放,且内容更丰富。\n\n地图与战役机制可能不平衡。 更不完美。
+campaign.difficulty = Difficulty
completed = [accent]己研究
techtree = 科技树
techtree.select = 切换科技树
@@ -296,13 +298,14 @@ disconnect.error = 连接错误。
disconnect.closed = 连接关闭。
disconnect.timeout = 连接超时。
disconnect.data = 地图加载失败!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = 无法加入游戏([accent]{0}[])。
connecting = [accent]连接中…
reconnecting = [accent]重新连接中…
connecting.data = [accent]地图加载中…
server.port = 端口:
-server.addressinuse = 地址已被占用!
server.invalidport = 无效的端口!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [scarlet]创建服务器错误。
save.new = 新存档
save.overwrite = 确定要覆盖这个存档吗?
@@ -355,6 +358,7 @@ command.enterPayload = 进入载荷建筑
command.loadUnits = 拾取单位
command.loadBlocks = 拾取建筑
command.unloadPayload = 卸载载荷
+command.loopPayload = Loop Unit Transfer
stance.stop = 取消指令
stance.shoot = 姿态: 射击
stance.holdfire = 姿态: 停火
@@ -498,6 +502,7 @@ waves.units.show = 全部显示
wavemode.counts = 数目
wavemode.totals = 总数
wavemode.health = 生命值
+all = All
editor.default = [lightgray]<默认>
details = 详情…
@@ -668,7 +673,6 @@ requirement.capture = 占领{0}
requirement.onplanet = 控制区块{0}
requirement.onsector = 着陆区块:{0}
launch.text = 发射
-research.multiplayer = 只有服务器创建者能研究科技。
map.multiplayer = 只有服务器创建者能查看区块。
uncover = 已解锁
configure = 设定装运的物资
@@ -742,6 +746,7 @@ error.mapnotfound = 找不到地图文件!
error.io = 网络I/O错误。
error.any = 未知网络错误。
error.bloom = 未能初始化光效。 \n您的设备可能不支持。
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = 降雨
weather.snowing.name = 降雪
@@ -793,6 +798,11 @@ threat.medium = 中度
threat.high = 高度
threat.extreme = 极高
threat.eradication = 毁灭
+difficulty.casual = Casual
+difficulty.easy = Easy
+difficulty.normal = Normal
+difficulty.hard = Hard
+difficulty.eradication = Eradication
planets = 行星
@@ -815,9 +825,19 @@ sector.fungalPass.name = 真菌通道
sector.biomassFacility.name = 生物质合成区
sector.windsweptIslands.name = 风吹群岛
sector.extractionOutpost.name = 萃取前哨
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = 行星发射终端
sector.coastline.name = 边际海湾
sector.navalFortress.name = 海军要塞
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = 踏上旅程的最佳位置。 这里的敌人威胁很小,但资源也少。\n\n尽你所能收集铅和铜,出发吧!
sector.frozenForest.description = 一个靠近山脉的地方。 哪怕是在这里,也有了孢子扩散的痕迹。\n连极寒也无法长久地约束它们。\n\n开始运用电力,建造火力发电机并学会使用修理器。
@@ -837,6 +857,18 @@ sector.impact0078.description = 最初进入这个星系的星际运输船,残
sector.planetaryTerminal.description = 最终目标。\n这座滨海基地有一个可以将核心发射到其他行星的建筑,防卫森严。\n\n制造海军单位,尽快消灭敌人,研究发射建筑。
sector.coastline.description = 这里探测到了海军单位科技的遗迹。 击退敌人的进攻,占领区块,获取技术。
sector.navalFortress.description = 敌人在一个有天然防御屏障的偏远岛屿上建立了基地。 摧毁它,并研究高级海军科技。
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = 始发地区
sector.aegis.name = 庇护前哨
@@ -1035,6 +1067,7 @@ ability.liquidexplode = 死亡溢液
ability.liquidexplode.description = 死亡时释放液体
ability.stat.firingrate = [stat]{0}/秒[lightgray] 射速
ability.stat.regen = [stat]{0}/秒[lightgray] 生命恢复速度
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] 护盾
ability.stat.repairspeed = [stat]{0}/秒[lightgray] 修复速度
ability.stat.slurpheal = [stat]{0}[lightgray] 生命/液体单位
@@ -1099,6 +1132,8 @@ bullet.healamount = [stat]{0}[lightgray]修复量
bullet.multiplier = [stat]{0}[lightgray]x装填倍数
bullet.reload = [stat]{0}%[lightgray]开火速率
bullet.range = [stat]{0}[lightgray]射程(格)
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = 格
unit.blockssquared = 格²
@@ -1159,12 +1194,6 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI缩放比例
setting.uiscale.description = 需要重新启动
setting.swapdiagonal.name = 总是斜线建造
-setting.difficulty.training = 训练
-setting.difficulty.easy = 简单
-setting.difficulty.normal = 普通
-setting.difficulty.hard = 困难
-setting.difficulty.insane = 疯狂
-setting.difficulty.name = 难度:
setting.screenshake.name = 屏幕抖动
setting.bloomintensity.name = 光效强度
setting.bloomblur.name = 光效模糊
@@ -1254,6 +1283,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = 重建建筑
keybind.schematic_select.name = 框选建筑
keybind.schematic_menu.name = 蓝图目录
@@ -1331,12 +1361,16 @@ rules.wavetimer = 波次计时器
rules.wavesending = 波次可跳波
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = 波次
rules.airUseSpawns = Air units use spawn points
rules.attack = 进攻模式
rules.buildai = 基础建筑者 AI
rules.buildaitier = 建筑者 AI 等级
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = 最小部队规模
rules.rtsmaxsquadsize = 最大部队规模
rules.rtsminattackweight = 最低进攻强度
@@ -1379,6 +1413,9 @@ rules.title.teams = 队伍
rules.title.planet = 星球
rules.lighting = 环境光
rules.fog = 战争迷雾
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = 允许火焰产生并蔓延
rules.anyenv = <任意>
rules.explosions = 建筑/单位爆炸伤害
@@ -1387,6 +1424,7 @@ rules.weather = 天气
rules.weather.frequency = 周期:
rules.weather.always = 永久
rules.weather.duration = 时长:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1531,6 +1569,8 @@ block.graphite-press.name = 石墨压缩机
block.multi-press.name = 多重压缩机
block.constructing = {0}[lightgray](建造中)
block.spawn.name = 敌人出生点
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = 初代核心
block.core-foundation.name = 次代核心
block.core-nucleus.name = 终代核心
@@ -1790,6 +1830,7 @@ block.electric-heater.name = 电制热机
block.slag-heater.name = 矿渣制热机
block.phase-heater.name = 相织制热机
block.heat-redirector.name = 热量传输机
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = 热量路由器
block.slag-incinerator.name = 矿渣焚化炉
block.carbide-crucible.name = 碳化物坩埚
@@ -1837,6 +1878,7 @@ block.chemical-combustion-chamber.name = 化学燃烧室
block.pyrolysis-generator.name = 热解发生器
block.vent-condenser.name = 排气冷凝器
block.cliff-crusher.name = 墙壁粉碎机
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = 等离子钻机
block.large-plasma-bore.name = 大型等离子钻机
block.impact-drill.name = 冲击钻头
@@ -2072,6 +2114,10 @@ block.phase-wall.description = 保护己方建筑,挡下敌方炮弹。 受大
block.phase-wall-large.description = 保护己方建筑,挡下敌方炮弹。 受大多数子弹攻击时有概率将其反弹。
block.surge-wall.description = 保护己方建筑,挡下敌方炮弹。 受攻击时间断释放电弧。
block.surge-wall-large.description = 保护己方建筑,挡下敌方炮弹。 受攻击时间断释放电弧。
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = 可以开关的墙。
block.door-large.description = 可以开关的墙。
block.mender.description = 定期修复附近的建筑。\n可使用硅提高范围和效率。
@@ -2201,6 +2247,7 @@ block.electric-heater.description = 加热朝向的建筑。 需要大量电力
block.slag-heater.description = 加热朝向的建筑。 需要矿渣。
block.phase-heater.description = 加热朝向的建筑。 需要相织布。
block.heat-redirector.description = 将累积的热量传输到其他建筑。
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = 将累积的热量平均分配到其它3个方向。
block.electrolyzer.description = 将水电解为氢和臭氧气体。
block.atmospheric-concentrator.description = 从大气中浓缩氮气。 需要热量。
@@ -2213,6 +2260,7 @@ block.vent-condenser.description = 将排出的水蒸气冷凝成水。 消耗
block.plasma-bore.description = 面向矿壁放置时,以缓慢的速度无限产出物品。 需要少量电力。
block.large-plasma-bore.description = 更大的等离子钻机。 能够开采钨和钍。 需要氢气和电力。
block.cliff-crusher.description = 粉碎墙壁,以缓慢的速度无限产出沙子。 需要电力。 效率因墙的类型而异。
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = 放置在矿物上时,以缓慢的速度无限产出物品。 需要电力和水。
block.eruption-drill.description = 改进过的冲击钻头。 能够开采钍。 需要氢。
block.reinforced-conduit.description = 向前传输流体。 不接受侧面的非导管输入。
@@ -2375,6 +2423,7 @@ lst.getflag = 检查是否设置了全局标志。
lst.setprop = 设置单位或建筑物的属性。
lst.effect = 创建一个粒子效果。
lst.sync = 在网络中同步一个变量。\n最多每秒调用10次。
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = 在世界中创建一个新的逻辑标记。\n必须提供一个用于标识此标记的ID。\n目前每个世界限制最多20000个标记。
lst.setmarker = 为标记设置属性。\n使用的ID必须与制作标记指令中的相同。
lst.localeprint = 将地图本地化文本属性值添加到文本缓冲区中。\n要在地图编辑器中设置地图本地化包,请检查 [accent]地图信息 > 本地化包[]。\n如果客户端是移动设备,则尝试首先打印以 ".mobile" 结尾的属性。
@@ -2547,6 +2596,7 @@ unitlocate.building = 找到的建筑存入此变量
unitlocate.outx = 存入找到的X轴坐标
unitlocate.outy = 存入找到的Y轴坐标
unitlocate.group = 所搜寻的建筑分类
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = 原地不动,但继续进行手上的采矿/建造动作\n单位的默认状态
lenum.stop = 停止移动/采矿/建造动作
diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties
index 7ef0eea54f..9f1ee4db85 100644
--- a/core/assets/bundles/bundle_zh_TW.properties
+++ b/core/assets/bundles/bundle_zh_TW.properties
@@ -144,6 +144,7 @@ mod.enabled = [lightgray]已啟用
mod.disabled = [scarlet]已禁用
mod.multiplayer.compatible = [gray]與多人模式相容
mod.disable = 禁用
+mod.version = Version:
mod.content = 內容:
mod.delete.error = 無法刪除模組,檔案可能在使用中。
mod.incompatiblegame = [red]Outdated Game
@@ -193,6 +194,7 @@ campaign.select = Select Starting Campaign
campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time.
campaign.erekir = Newer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience.
campaign.serpulo = Older content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished.
+campaign.difficulty = Difficulty
completed = [accent]完成
techtree = 科技樹
techtree.select = 選擇科技樹
@@ -293,13 +295,14 @@ disconnect.error = 連線錯誤。
disconnect.closed = 連線關閉。
disconnect.timeout = 連線逾時。
disconnect.data = 無法載入地圖資料!
+disconnect.snapshottimeout = Timed out while receiving UDP snapshots.\nThis may be caused by an unstable network or connection.
cantconnect = 無法加入遊戲 ([accent]{0}[]).
connecting = [accent]連線中……
reconnecting = [accent]重新連接中……
connecting.data = [accent]地圖資料載入中……
server.port = 連接埠:
-server.addressinuse = 該位置已被使用!
server.invalidport = 無效的連接埠!
+server.error.addressinuse = [scarlet]Failed to open server on port 6567.[]\n\nMake sure no other Mindustry servers are running on your device or network!
server.error = [crimson]建立伺服器時發生錯誤。
save.new = 新存檔
save.overwrite = 您確定要覆寫存檔嗎?
@@ -352,6 +355,7 @@ command.enterPayload = Enter Payload Block
command.loadUnits = Load Units
command.loadBlocks = Load Blocks
command.unloadPayload = Unload Payload
+command.loopPayload = Loop Unit Transfer
stance.stop = Cancel Orders
stance.shoot = Stance: Shoot
stance.holdfire = Stance: Hold Fire
@@ -495,6 +499,7 @@ waves.units.show = 全部顯示
wavemode.counts = 數量
wavemode.totals = 總數
wavemode.health = 生命值
+all = All
editor.default = [lightgray](預設)
details = 詳細資訊……
@@ -665,7 +670,6 @@ requirement.capture = 捕獲 {0}
requirement.onplanet = Control Sector On {0}
requirement.onsector = Land On Sector: {0}
launch.text = 發射
-research.multiplayer = 只有管理者可以使用這個物品
map.multiplayer = 只有管理者可以查看地圖
uncover = 探索
configure = 資源配置
@@ -704,9 +708,9 @@ objective.coreitem = [accent]Move into Core:\n[][lightgray]{0}[]/{1}\n{2}[lightg
objective.build = [accent]建造:[][lightgray]{0}[]x\n{1}[lightgray]{2}
objective.buildunit = [accent]產生單位:[][lightgray]{0}[]x\n{1}[lightgray]{2}
objective.destroyunits = [accent]摧毀:[][lightgray]{0}[]x 單位
-objective.enemiesapproaching = [accent]的人在 [lightgray]{0} 到達[]
-objective.enemyescelating = [accent]Enemy production escalating in [lightgray]{0}[]
-objective.enemyairunits = [accent]Enemy air unit production beginning in [lightgray]{0}[]
+objective.enemiesapproaching = [accent]敵人在 [lightgray]{0} 到達[]
+objective.enemyescelating = [accent]敵人正在 [lightgray]{0} 加緊生產[]
+objective.enemyairunits = [accent]敵人在 [lightgray]{0} 開始產生空中單位[]
objective.destroycore = [accent]摧毀敵人核心
objective.command = [accent]Command Units
objective.nuclearlaunch = [accent]⚠ Nuclear launch detected: [lightgray]{0}
@@ -739,6 +743,7 @@ error.mapnotfound = 找不到地圖!
error.io = 網路錯誤。
error.any = 未知網路錯誤。
error.bloom = 初始化特效失敗。\n您的裝置可能不支援
+error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThere is no known workaround to this issue.
weather.rain.name = 雨
weather.snowing.name = 雪
@@ -789,6 +794,11 @@ threat.medium = 中
threat.high = 高
threat.extreme = 極高
threat.eradication = 毀滅性
+difficulty.casual = 休閒模式
+difficulty.easy = 簡單模式
+difficulty.normal = 普通模式
+difficulty.hard = 困難模式
+difficulty.eradication = 滅絕模式
planets = 行星
@@ -811,9 +821,19 @@ sector.fungalPass.name = 真菌走廊
sector.biomassFacility.name = 生物質合成工廠
sector.windsweptIslands.name = 風之島
sector.extractionOutpost.name = 萃取哨站
+sector.facility32m.name = Facility 32 M
+sector.taintedWoods.name = Tainted Woods
+sector.infestedCanyons.name = Infested Canyons
sector.planetaryTerminal.name = 星際發射站
sector.coastline.name = 海岸
sector.navalFortress.name = 海上要塞
+sector.polarAerodrome.name = Polar Aerodrome
+sector.atolls.name = Atolls
+sector.testingGrounds.name = Testing Grounds
+sector.seaPort.name = Sea Port
+sector.weatheredChannels.name = Weathered Channels
+sector.mycelialBastion.name = Mycelial Bastion
+sector.frontier.name = Frontier
sector.groundZero.description = 再次開始的最佳位置。敵人威脅程度低。資源少。\n盡可能地採集鉛與銅。\n繼續前進。
sector.frozenForest.description = 即使是在如此靠近山脈的地方,孢子也已經擴散了。低溫無法永遠遏止它們。\n\n開始探索電力。建造火力發電機。學習如何修理方塊。
@@ -833,6 +853,18 @@ sector.impact0078.description = 沉睡在此的是第一個進入本星系的星
sector.planetaryTerminal.description = 最終目標。\n\n這麼濱海基地具有能夠發射核心到其他行星的建築。 其防禦非常嚴密。\n\n生產海上單位。盡速摧毀敵人。研究該發射建築。
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
+sector.cruxscape.name = Cruxscape
+sector.geothermalStronghold.name = Geothermal Stronghold
+sector.facility32m.description = WIP, map submission by Stormride_R
+sector.taintedWoods.description = WIP, map submission by Stormride_R
+sector.atolls.description = WIP, map submission by Stormride_R
+sector.frontier.description = WIP, map submission by Stormride_R
+sector.infestedCanyons.description = WIP, map submission by Skeledragon
+sector.polarAerodrome.description = WIP, map submission by hhh i 17
+sector.testingGrounds.description = WIP, map submission by dnx2019
+sector.seaPort.description = WIP, map submission by inkognito626
+sector.weatheredChannels.description = WIP, map submission by Skeledragon
+sector.mycelialBastion.description = WIP, map submission by Skeledragon
sector.onset.name = 著陸點
sector.aegis.name = 神盾
@@ -1001,7 +1033,7 @@ stat.immunities = Immunities
stat.healing = 治癒
ability.forcefield = 防護罩
-ability.forcefield.description = Projects a force shield that absorbs bullets
+ability.forcefield.description = 投射一個能吸收子彈的防護罩
ability.repairfield = 維修力場
ability.repairfield.description = Repairs nearby units
ability.statusfield = 狀態力場
@@ -1031,6 +1063,7 @@ ability.liquidexplode = Death Spillage
ability.liquidexplode.description = Spills liquid on death
ability.stat.firingrate = [stat]{0}/sec[lightgray] firing rate
ability.stat.regen = [stat]{0}[lightgray] health/sec
+ability.stat.pulseregen = [stat]{0}[lightgray] health/pulse
ability.stat.shield = [stat]{0}[lightgray] shield
ability.stat.repairspeed = [stat]{0}/sec[lightgray] repair speed
ability.stat.slurpheal = [stat]{0}[lightgray] health/liquid unit
@@ -1094,6 +1127,8 @@ bullet.healamount = [stat]{0}[lightgray] 直接回復
bullet.multiplier = [stat]{0}[lightgray]×彈藥倍數
bullet.reload = [stat]{0}[lightgray]×射擊速率
bullet.range = [stat]{0}[lightgray] 方塊射程
+bullet.notargetsmissiles = [stat] ignores buildings
+bullet.notargetsbuildings = [stat] ignores missiles
unit.blocks = 方塊
unit.blockssquared = 方塊²
@@ -1154,12 +1189,6 @@ setting.fpscap.text = {0}FPS
setting.uiscale.name = 操作介面大小
setting.uiscale.description = 需要重新啟動遊戲以更改大小
setting.swapdiagonal.name = 預設對角線放置
-setting.difficulty.training = 訓練
-setting.difficulty.easy = 簡單
-setting.difficulty.normal = 普通
-setting.difficulty.hard = 困難
-setting.difficulty.insane = 瘋狂
-setting.difficulty.name = 難度:
setting.screenshake.name = 畫面抖動
setting.bloomintensity.name = 火花強度
setting.bloomblur.name = 火花模糊
@@ -1249,6 +1278,7 @@ keybind.unit_command_load_units.name = Unit Command: Load Units
keybind.unit_command_load_blocks.name = Unit Command: Load Blocks
keybind.unit_command_unload_payload.name = Unit Command: Unload Payload
keybind.unit_command_enter_payload.name = Unit Command: Enter Payload
+keybind.unit_command_loop_payload.name = Unit Command: Loop Unit Transfer
keybind.rebuild_select.name = Rebuild Region
keybind.schematic_select.name = 選擇區域
keybind.schematic_menu.name = 藍圖目錄
@@ -1326,12 +1356,16 @@ rules.wavetimer = 波次時間
rules.wavesending = Wave Sending
rules.allowedit = Allow Editing Rules
rules.allowedit.info = When enabled, the player can edit rules in-game via the button in the bottom left corner of the Pause menu.
+rules.alloweditworldprocessors = Allow Editing World Processors
+rules.alloweditworldprocessors.info = When enabled, world logic blocks can be placed and edited even outside the editor.
rules.waves = 波次
rules.airUseSpawns = Air units use spawn points
rules.attack = 攻擊模式
rules.buildai = Base Builder AI
rules.buildaitier = Builder AI Tier
rules.rtsai = RTS AI
+rules.rtsai.campaign = RTS Attack AI
+rules.rtsai.campaign.info = In attack maps, makes units group up and attack player bases in a more intelligent manner.
rules.rtsminsquadsize = 最小隊伍規模
rules.rtsmaxsquadsize = 最大隊伍規模
rules.rtsminattackweight = 最小攻擊力
@@ -1374,6 +1408,9 @@ rules.title.teams = 分隊
rules.title.planet = 星球
rules.lighting = 光照
rules.fog = 戰爭迷霧
+rules.invasions = Enemy Sector Invasions
+rules.showspawns = Show Enemy Spawns
+rules.randomwaveai = Unpredictable Wave AI
rules.fire = 火
rules.anyenv =
rules.explosions = 方塊/單位爆炸傷害
@@ -1382,6 +1419,7 @@ rules.weather = 天氣
rules.weather.frequency = 頻率:
rules.weather.always = 永遠
rules.weather.duration = 持續時間:
+rules.randomwaveai.info = Makes units spawned in waves target random structures instead of directly attacking the core or power generators.
rules.placerangecheck.info = Prevents players from placing anything near enemy buildings. When trying to place a turret, the range is increased, so the turret will not be able to reach the enemy.
rules.onlydepositcore.info = Prevents units from depositing items into any buildings except cores.
@@ -1526,6 +1564,8 @@ block.graphite-press.name = 石墨壓縮機
block.multi-press.name = 多重壓縮機
block.constructing = {0}\n[lightgray](建設中)
block.spawn.name = 敵人生成
+block.remove-wall.name = Remove Wall
+block.remove-ore.name = Remove Ore
block.core-shard.name = 核心:碎片
block.core-foundation.name = 核心:基地
block.core-nucleus.name = 核心:核子
@@ -1785,6 +1825,7 @@ block.electric-heater.name = 電加熱器
block.slag-heater.name = 熔渣加熱器
block.phase-heater.name = 相織布加熱器
block.heat-redirector.name = 熱重定向器
+block.small-heat-redirector.name = Small Heat Redirector
block.heat-router.name = Heat Router
block.slag-incinerator.name = 熔渣焚化爐
block.carbide-crucible.name = 碳化鎢坩堝
@@ -1832,6 +1873,7 @@ block.chemical-combustion-chamber.name = 化學燃燒發電機
block.pyrolysis-generator.name = 熱解發電機
block.vent-condenser.name = 氣體冷凝器
block.cliff-crusher.name = 牆體挖鑿機
+block.large-cliff-crusher.name = Advanced Cliff Crusher
block.plasma-bore.name = 電漿鑽頭
block.large-plasma-bore.name = 大型電漿鑽頭
block.impact-drill.name = 衝擊鑽頭
@@ -2061,6 +2103,10 @@ block.phase-wall.description = 沒有釷牆那麼堅固但特殊的相位化合
block.phase-wall-large.description = 沒有釷牆那麼堅固但特殊的相位化合物塗層會使大多的子彈偏離。\n佔據多個方塊。
block.surge-wall.description = 最強的防禦方塊。\n有低機率對攻擊者觸發閃電。
block.surge-wall-large.description = 最強的防禦方塊。\n有低機率對攻擊者觸發閃電。\n佔據多個方塊。
+block.scrap-wall.description = Protects structures from enemy projectiles.
+block.scrap-wall-large.description = Protects structures from enemy projectiles.
+block.scrap-wall-huge.description = Protects structures from enemy projectiles.
+block.scrap-wall-gigantic.description = Protects structures from enemy projectiles.
block.door.description = 可以通過點擊打開和關閉的一扇小門。\n如果打開,敵人可以穿過它射擊和移動。
block.door-large.description = 可以通過點擊打開和關閉的一扇大門。\n如果打開,敵人可以穿過它射擊和移動。\n佔據多個方塊。
block.mender.description = 定期修復附近的建築物。在每一波之間保持防禦力的修復。\n可選擇使用矽來提高範圍和效率。
@@ -2188,6 +2234,7 @@ block.electric-heater.description = Heats facing blocks. Requires large amounts
block.slag-heater.description = Heats facing blocks. Requires slag.
block.phase-heater.description = Heats facing blocks. Requires phase fabric.
block.heat-redirector.description = Redirects accumulated heat to other blocks.
+block.small-heat-redirector.description = Redirects accumulated heat to other blocks.
block.heat-router.description = Spreads accumulated heat in three output directions.
block.electrolyzer.description = Converts water into hydrogen and ozone gas.
block.atmospheric-concentrator.description = Concentrates nitrogen from the atmosphere. Requires heat.
@@ -2200,6 +2247,7 @@ block.vent-condenser.description = Condenses vent gases into water. Consumes pow
block.plasma-bore.description = When placed facing an ore wall, outputs items indefinitely. Requires small amounts of power.
block.large-plasma-bore.description = A larger plasma bore. Capable of mining tungsten and thorium. Requires hydrogen and power.
block.cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power. Efficiency varies based on type of wall.
+block.large-cliff-crusher.description = Crushes walls, outputting sand indefinitely. Requires power and ozone. Efficiency varies based on type of wall. Optionally consumes tungsten to increase efficiency.
block.impact-drill.description = When placed on ore, outputs items in bursts indefinitely. Requires power and water.
block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen.
block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides.
@@ -2360,6 +2408,7 @@ lst.getflag = 檢查某一全局flag是否存在
lst.setprop = Sets a property of a unit or building.
lst.effect = Create a particle effect.
lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most.
+lst.playsound = Plays a sound.\nVolume and pan can be a global value, or calculated based on position.
lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world.
lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction.
lst.localeprint = Add map locale property value to the text buffer.\nTo set map locale bundles in map editor, check [accent]Map Info > Locale Bundles[].\nIf client is a mobile device, tries to print a property ending in ".mobile" first.
@@ -2531,6 +2580,7 @@ unitlocate.building = 回傳找到的建築為變數
unitlocate.outx = 回傳 X 座標
unitlocate.outy = 回傳 Y 座標
unitlocate.group = 搜索建築種類
+playsound.limit = If true, prevents this sound from playing\nif it has already been played in the same frame.
lenum.idle = 預設AI
lenum.stop = 停止
diff --git a/core/assets/contributors b/core/assets/contributors
index a07a13aadc..8bcc1913ab 100644
--- a/core/assets/contributors
+++ b/core/assets/contributors
@@ -162,9 +162,11 @@ Gabriel "red" Fondato
CoCo Snow
summoner
OpalSoPL
+apollovy
BalaM314
Redstonneur1256
ApsZoldat
+Mythril
hexagon-recursion
JasonP01
BlueTheCube
diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties
index 64963dd203..c2f98f347f 100755
--- a/core/assets/icons/icons.properties
+++ b/core/assets/icons/icons.properties
@@ -588,3 +588,10 @@
63094=cat|cat
63093=world-switch|block-world-switch-ui
63092=dynamic|status-dynamic-ui
+63091=remove-wall|block-remove-wall-ui
+63090=remove-ore|block-remove-ore-ui
+63089=small-heat-redirector|block-small-heat-redirector-ui
+63088=large-cliff-crusher|block-large-cliff-crusher-ui
+63087=scathe-missile-phase|unit-scathe-missile-phase-ui
+63086=scathe-missile-surge|unit-scathe-missile-surge-ui
+63085=scathe-missile-surge-split|unit-scathe-missile-surge-split-ui
diff --git a/core/assets/logicids.dat b/core/assets/logicids.dat
index 26e11eb4c2..2145ea1672 100644
Binary files a/core/assets/logicids.dat and b/core/assets/logicids.dat differ
diff --git a/core/assets/maps/atolls.msav b/core/assets/maps/atolls.msav
new file mode 100644
index 0000000000..42a70ab90c
Binary files /dev/null and b/core/assets/maps/atolls.msav differ
diff --git a/core/assets/maps/biomassFacility.msav b/core/assets/maps/biomassFacility.msav
index 738d890f70..cd355b9c62 100644
Binary files a/core/assets/maps/biomassFacility.msav and b/core/assets/maps/biomassFacility.msav differ
diff --git a/core/assets/maps/coastline.msav b/core/assets/maps/coastline.msav
index 91e8c1db83..63f46969a1 100644
Binary files a/core/assets/maps/coastline.msav and b/core/assets/maps/coastline.msav differ
diff --git a/core/assets/maps/craters.msav b/core/assets/maps/craters.msav
index 9eb3d18444..52aa3f3714 100644
Binary files a/core/assets/maps/craters.msav and b/core/assets/maps/craters.msav differ
diff --git a/core/assets/maps/cruxscape.msav b/core/assets/maps/cruxscape.msav
new file mode 100644
index 0000000000..33489c6854
Binary files /dev/null and b/core/assets/maps/cruxscape.msav differ
diff --git a/core/assets/maps/desolateRift.msav b/core/assets/maps/desolateRift.msav
index d08ee30cfe..11d62928a0 100644
Binary files a/core/assets/maps/desolateRift.msav and b/core/assets/maps/desolateRift.msav differ
diff --git a/core/assets/maps/extractionOutpost.msav b/core/assets/maps/extractionOutpost.msav
index 723cab47a8..6ea0ae63dd 100644
Binary files a/core/assets/maps/extractionOutpost.msav and b/core/assets/maps/extractionOutpost.msav differ
diff --git a/core/assets/maps/facility32m.msav b/core/assets/maps/facility32m.msav
new file mode 100644
index 0000000000..a42a2deb39
Binary files /dev/null and b/core/assets/maps/facility32m.msav differ
diff --git a/core/assets/maps/frontier.msav b/core/assets/maps/frontier.msav
new file mode 100644
index 0000000000..765c4082ce
Binary files /dev/null and b/core/assets/maps/frontier.msav differ
diff --git a/core/assets/maps/fungalPass.msav b/core/assets/maps/fungalPass.msav
index a8ec35c1c4..6ef6328c79 100644
Binary files a/core/assets/maps/fungalPass.msav and b/core/assets/maps/fungalPass.msav differ
diff --git a/core/assets/maps/geothermalStronghold.msav b/core/assets/maps/geothermalStronghold.msav
new file mode 100644
index 0000000000..e76157110d
Binary files /dev/null and b/core/assets/maps/geothermalStronghold.msav differ
diff --git a/core/assets/maps/infestedCanyons.msav b/core/assets/maps/infestedCanyons.msav
new file mode 100644
index 0000000000..02f0c043de
Binary files /dev/null and b/core/assets/maps/infestedCanyons.msav differ
diff --git a/core/assets/maps/mycelialBastion.msav b/core/assets/maps/mycelialBastion.msav
new file mode 100644
index 0000000000..e4d41aab47
Binary files /dev/null and b/core/assets/maps/mycelialBastion.msav differ
diff --git a/core/assets/maps/navalFortress.msav b/core/assets/maps/navalFortress.msav
index b9e583bb1e..2d9dda6171 100644
Binary files a/core/assets/maps/navalFortress.msav and b/core/assets/maps/navalFortress.msav differ
diff --git a/core/assets/maps/overgrowth.msav b/core/assets/maps/overgrowth.msav
index 55a90608fa..e13fd71bf5 100644
Binary files a/core/assets/maps/overgrowth.msav and b/core/assets/maps/overgrowth.msav differ
diff --git a/core/assets/maps/planetaryTerminal.msav b/core/assets/maps/planetaryTerminal.msav
index 2cf2df9dd6..96459e74e0 100644
Binary files a/core/assets/maps/planetaryTerminal.msav and b/core/assets/maps/planetaryTerminal.msav differ
diff --git a/core/assets/maps/polarAerodrome.msav b/core/assets/maps/polarAerodrome.msav
new file mode 100644
index 0000000000..b960bbd922
Binary files /dev/null and b/core/assets/maps/polarAerodrome.msav differ
diff --git a/core/assets/maps/ravine.msav b/core/assets/maps/ravine.msav
index 14daf93199..271afb2bfa 100644
Binary files a/core/assets/maps/ravine.msav and b/core/assets/maps/ravine.msav differ
diff --git a/core/assets/maps/ruinousShores.msav b/core/assets/maps/ruinousShores.msav
index 441fb2044d..22c4fe7908 100644
Binary files a/core/assets/maps/ruinousShores.msav and b/core/assets/maps/ruinousShores.msav differ
diff --git a/core/assets/maps/seaPort.msav b/core/assets/maps/seaPort.msav
new file mode 100644
index 0000000000..47148b8ce9
Binary files /dev/null and b/core/assets/maps/seaPort.msav differ
diff --git a/core/assets/maps/siege.msav b/core/assets/maps/siege.msav
index 0564e38db3..a3be106191 100644
Binary files a/core/assets/maps/siege.msav and b/core/assets/maps/siege.msav differ
diff --git a/core/assets/maps/stainedMountains.msav b/core/assets/maps/stainedMountains.msav
index ee28f1dc23..ca4ad5dc6e 100644
Binary files a/core/assets/maps/stainedMountains.msav and b/core/assets/maps/stainedMountains.msav differ
diff --git a/core/assets/maps/taintedWoods.msav b/core/assets/maps/taintedWoods.msav
new file mode 100644
index 0000000000..237bae65ba
Binary files /dev/null and b/core/assets/maps/taintedWoods.msav differ
diff --git a/core/assets/maps/tarFields.msav b/core/assets/maps/tarFields.msav
index 21f1c29690..36d33eb11c 100644
Binary files a/core/assets/maps/tarFields.msav and b/core/assets/maps/tarFields.msav differ
diff --git a/core/assets/maps/testingGrounds.msav b/core/assets/maps/testingGrounds.msav
new file mode 100644
index 0000000000..b02ba9da54
Binary files /dev/null and b/core/assets/maps/testingGrounds.msav differ
diff --git a/core/assets/maps/weatheredChannels.msav b/core/assets/maps/weatheredChannels.msav
new file mode 100644
index 0000000000..f9ef2030e1
Binary files /dev/null and b/core/assets/maps/weatheredChannels.msav differ
diff --git a/core/assets/maps/windsweptIslands.msav b/core/assets/maps/windsweptIslands.msav
index 690a924716..32daa4dbff 100644
Binary files a/core/assets/maps/windsweptIslands.msav and b/core/assets/maps/windsweptIslands.msav differ
diff --git a/core/assets/scripts/global.js b/core/assets/scripts/global.js
index 662c336cbe..d91fe9950c 100755
--- a/core/assets/scripts/global.js
+++ b/core/assets/scripts/global.js
@@ -41,12 +41,11 @@ function extend(/*Base, ..., def*/){
return instance
}
-
importPackage(Packages.arc)
importPackage(Packages.arc.audio)
importPackage(Packages.arc.files)
-importPackage(Packages.arc.func)
importPackage(Packages.arc.flabel)
+importPackage(Packages.arc.func)
importPackage(Packages.arc.graphics)
importPackage(Packages.arc.graphics.g2d)
importPackage(Packages.arc.graphics.gl)
@@ -62,7 +61,6 @@ importPackage(Packages.arc.scene.ui.layout)
importPackage(Packages.arc.scene.utils)
importPackage(Packages.arc.struct)
importPackage(Packages.arc.util)
-importPackage(Packages.arc.util.async)
importPackage(Packages.arc.util.io)
importPackage(Packages.arc.util.noise)
importPackage(Packages.arc.util.pooling)
@@ -90,11 +88,13 @@ importPackage(Packages.mindustry.graphics)
importPackage(Packages.mindustry.graphics.g3d)
importPackage(Packages.mindustry.input)
importPackage(Packages.mindustry.io)
+importPackage(Packages.mindustry.io.versions)
importPackage(Packages.mindustry.logic)
importPackage(Packages.mindustry.maps)
importPackage(Packages.mindustry.maps.filters)
importPackage(Packages.mindustry.maps.generators)
importPackage(Packages.mindustry.maps.planet)
+importPackage(Packages.mindustry.mod)
importPackage(Packages.mindustry.net)
importPackage(Packages.mindustry.service)
importPackage(Packages.mindustry.type)
@@ -143,9 +143,14 @@ const UnitUnloadEvent = Packages.mindustry.game.EventType.UnitUnloadEvent
const UnitSpawnEvent = Packages.mindustry.game.EventType.UnitSpawnEvent
const UnitCreateEvent = Packages.mindustry.game.EventType.UnitCreateEvent
const UnitDrownEvent = Packages.mindustry.game.EventType.UnitDrownEvent
+const UnitDamageEvent = Packages.mindustry.game.EventType.UnitDamageEvent
+const UnitBulletDestroyEvent = Packages.mindustry.game.EventType.UnitBulletDestroyEvent
const UnitDestroyEvent = Packages.mindustry.game.EventType.UnitDestroyEvent
+const BuildingBulletDestroyEvent = Packages.mindustry.game.EventType.BuildingBulletDestroyEvent
+const GeneratorPressureExplodeEvent = Packages.mindustry.game.EventType.GeneratorPressureExplodeEvent
const BlockDestroyEvent = Packages.mindustry.game.EventType.BlockDestroyEvent
const BuildSelectEvent = Packages.mindustry.game.EventType.BuildSelectEvent
+const BuildRotateEvent = Packages.mindustry.game.EventType.BuildRotateEvent
const BlockBuildEndEvent = Packages.mindustry.game.EventType.BlockBuildEndEvent
const BlockBuildBeginEvent = Packages.mindustry.game.EventType.BlockBuildBeginEvent
const ResearchEvent = Packages.mindustry.game.EventType.ResearchEvent
@@ -157,21 +162,30 @@ const TileChangeEvent = Packages.mindustry.game.EventType.TileChangeEvent
const TilePreChangeEvent = Packages.mindustry.game.EventType.TilePreChangeEvent
const BuildDamageEvent = Packages.mindustry.game.EventType.BuildDamageEvent
const GameOverEvent = Packages.mindustry.game.EventType.GameOverEvent
+const BuildingCommandEvent = Packages.mindustry.game.EventType.BuildingCommandEvent
const UnitControlEvent = Packages.mindustry.game.EventType.UnitControlEvent
+const PayloadDropEvent = Packages.mindustry.game.EventType.PayloadDropEvent
const PickupEvent = Packages.mindustry.game.EventType.PickupEvent
const TapEvent = Packages.mindustry.game.EventType.TapEvent
const ConfigEvent = Packages.mindustry.game.EventType.ConfigEvent
const DepositEvent = Packages.mindustry.game.EventType.DepositEvent
const WithdrawEvent = Packages.mindustry.game.EventType.WithdrawEvent
const SectorCaptureEvent = Packages.mindustry.game.EventType.SectorCaptureEvent
+const ClientChatEvent = Packages.mindustry.game.EventType.ClientChatEvent
const PlayerChatEvent = Packages.mindustry.game.EventType.PlayerChatEvent
+const TextInputEvent = Packages.mindustry.game.EventType.TextInputEvent
const MenuOptionChooseEvent = Packages.mindustry.game.EventType.MenuOptionChooseEvent
+const ClientServerConnectEvent = Packages.mindustry.game.EventType.ClientServerConnectEvent
const ClientPreConnectEvent = Packages.mindustry.game.EventType.ClientPreConnectEvent
const SchematicCreateEvent = Packages.mindustry.game.EventType.SchematicCreateEvent
+const SectorLaunchLoadoutEvent = Packages.mindustry.game.EventType.SectorLaunchLoadoutEvent
const SectorLaunchEvent = Packages.mindustry.game.EventType.SectorLaunchEvent
const LaunchItemEvent = Packages.mindustry.game.EventType.LaunchItemEvent
const SectorInvasionEvent = Packages.mindustry.game.EventType.SectorInvasionEvent
const SectorLoseEvent = Packages.mindustry.game.EventType.SectorLoseEvent
+const SaveLoadEvent = Packages.mindustry.game.EventType.SaveLoadEvent
+const WorldLoadEndEvent = Packages.mindustry.game.EventType.WorldLoadEndEvent
+const WorldLoadBeginEvent = Packages.mindustry.game.EventType.WorldLoadBeginEvent
const WorldLoadEvent = Packages.mindustry.game.EventType.WorldLoadEvent
const FileTreeInitEvent = Packages.mindustry.game.EventType.FileTreeInitEvent
const MusicRegisterEvent = Packages.mindustry.game.EventType.MusicRegisterEvent
@@ -183,12 +197,12 @@ const TurretAmmoDeliverEvent = Packages.mindustry.game.EventType.TurretAmmoDeliv
const LineConfirmEvent = Packages.mindustry.game.EventType.LineConfirmEvent
const TurnEvent = Packages.mindustry.game.EventType.TurnEvent
const WaveEvent = Packages.mindustry.game.EventType.WaveEvent
+const HostEvent = Packages.mindustry.game.EventType.HostEvent
const ResetEvent = Packages.mindustry.game.EventType.ResetEvent
const PlayEvent = Packages.mindustry.game.EventType.PlayEvent
const DisposeEvent = Packages.mindustry.game.EventType.DisposeEvent
const ServerLoadEvent = Packages.mindustry.game.EventType.ServerLoadEvent
const ClientCreateEvent = Packages.mindustry.game.EventType.ClientCreateEvent
-const SaveLoadEvent = Packages.mindustry.game.EventType.SaveLoadEvent
const SaveWriteEvent = Packages.mindustry.game.EventType.SaveWriteEvent
const MapPublishEvent = Packages.mindustry.game.EventType.MapPublishEvent
const MapMakeEvent = Packages.mindustry.game.EventType.MapMakeEvent
diff --git a/core/src/mindustry/ClientLauncher.java b/core/src/mindustry/ClientLauncher.java
index 2e8d7396c1..3e2fbca7df 100644
--- a/core/src/mindustry/ClientLauncher.java
+++ b/core/src/mindustry/ClientLauncher.java
@@ -35,7 +35,7 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
@Override
public void setup(){
- String dataDir = OS.env("MINDUSTRY_DATA_DIR");
+ String dataDir = System.getProperty("mindustry.data.dir", OS.env("MINDUSTRY_DATA_DIR"));
if(dataDir != null){
Core.settings.setDataDirectory(files.absolute(dataDir));
}
@@ -55,6 +55,9 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
Log.info("[GL] Version: @", graphics.getGLVersion());
Log.info("[GL] Max texture size: @", maxTextureSize);
Log.info("[GL] Using @ context.", gl30 != null ? "OpenGL 3" : "OpenGL 2");
+ if(NvGpuInfo.hasMemoryInfo()){
+ Log.info("[GL] Total available VRAM: @mb", NvGpuInfo.getMaxMemoryKB()/1024);
+ }
if(maxTextureSize < 4096) Log.warn("[GL] Your maximum texture size is below the recommended minimum of 4096. This will cause severe performance issues.");
Log.info("[JAVA] Version: @", OS.javaVersion);
if(Core.app.isAndroid()){
@@ -62,7 +65,9 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
}
long ram = Runtime.getRuntime().maxMemory();
boolean gb = ram >= 1024 * 1024 * 1024;
- Log.info("[RAM] Available: @ @", Strings.fixed(gb ? ram / 1024f / 1024 / 1024f : ram / 1024f / 1024f, 1), gb ? "GB" : "MB");
+ if(!OS.isIos){
+ Log.info("[RAM] Available: @ @", Strings.fixed(gb ? ram / 1024f / 1024 / 1024f : ram / 1024f / 1024f, 1), gb ? "GB" : "MB");
+ }
Time.setDeltaProvider(() -> {
float result = Core.graphics.getDeltaTime() * 60f;
diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java
index bc4c6a494a..c17d5a2ec6 100644
--- a/core/src/mindustry/Vars.java
+++ b/core/src/mindustry/Vars.java
@@ -45,10 +45,10 @@ public class Vars implements Loadable{
public static boolean loadLocales = true;
/** Whether the logger is loaded. */
public static boolean loadedLogger = false, loadedFileLogger = false;
- /** Whether to enable various experimental features (e.g. spawn positions for spawn groups) TODO change */
- public static boolean experimental = true;
/** Name of current Steam player. */
public static String steamPlayerName = "";
+ /** If true, the BE server list is always used. */
+ public static boolean forceBeServers = false;
/** Default accessible content types used for player-selectable icons. */
public static final ContentType[] defaultContentIcons = {ContentType.item, ContentType.liquid, ContentType.block, ContentType.unit};
/** Default rule environment. */
@@ -71,11 +71,12 @@ public class Vars implements Loadable{
public static final String discordURL = "https://discord.gg/mindustry";
/** URL the links to the wiki's modding guide.*/
public static final String modGuideURL = "https://mindustrygame.github.io/wiki/modding/1-modding/";
- /** URL to the JSON file containing all the BE servers. Only queried in BE. */
- public static final String serverJsonBeURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers_be.json";
- /** URL to the JSON file containing all the stable servers. */
- //TODO merge with v6 list upon release
- public static final String serverJsonURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers_v7.json";
+ /** URLs to the JSON file containing all the BE servers. Only queried in BE. */
+ public static final String[] serverJsonBeURLs = {"https://raw.githubusercontent.com/Anuken/MindustryServerList/master/servers_be.json", "https://cdn.jsdelivr.net/gh/anuken/mindustryserverlist/servers_be.json"};
+ /** URLs to the JSON file containing all the stable servers. */
+ public static final String[] serverJsonURLs = {"https://raw.githubusercontent.com/Anuken/MindustryServerList/master/servers_v8.json", "https://cdn.jsdelivr.net/gh/anuken/mindustryserverlist/servers_v8.json"};
+ /** URLs to the JSON files containing the list of mods. */
+ public static final String[] modJsonURLs = {"https://raw.githubusercontent.com/Anuken/MindustryMods/master/mods.json", "https://cdn.jsdelivr.net/gh/anuken/mindustrymods/mods.json"};
/** URL of the github issue report template.*/
public static final String reportIssueURL = "https://github.com/Anuken/Mindustry/issues/new?labels=bug&template=bug_report.md";
/** list of built-in servers.*/
@@ -94,6 +95,8 @@ public class Vars implements Loadable{
public static final float finalWorldBounds = 250;
/** default range for building */
public static final float buildingRange = 220f;
+ /** scaling for unit circle collider radius, based on hitbox size */
+ public static final float unitCollisionRadiusScale = 0.6f;
/** range for moving items */
public static final float itemTransferRange = 220f;
/** range for moving items for logic units */
@@ -145,7 +148,7 @@ public class Vars implements Loadable{
"modeSurvival", "commandRally", "commandAttack",
};
/** maximum TCP packet size */
- public static final int maxTcpSize = 900;
+ public static final int maxTcpSize = 1100;
/** default server port */
public static final int port = 6567;
/** multicast discovery port.*/
@@ -170,6 +173,8 @@ public class Vars implements Loadable{
public static boolean confirmExit = true;
/** if true, UI is not drawn */
public static boolean disableUI;
+ /** if true, most autosaving is disabled. internal use only! */
+ public static boolean disableSave;
/** if true, game is set up in mobile mode, even on desktop. used for debugging */
public static boolean testMobile;
/** whether the game is running on a mobile device */
diff --git a/core/src/mindustry/ai/Astar.java b/core/src/mindustry/ai/Astar.java
index 76d73d84b0..23241e65cf 100644
--- a/core/src/mindustry/ai/Astar.java
+++ b/core/src/mindustry/ai/Astar.java
@@ -18,15 +18,15 @@ public class Astar{
private static float[] costs;
private static byte[][] rotations;
- public static Seq pathfind(Tile from, Tile to, TileHueristic th, Boolf passable){
+ public static Seq pathfind(Tile from, Tile to, TileHeuristic th, Boolf passable){
return pathfind(from.x, from.y, to.x, to.y, th, manhattan, passable);
}
- public static Seq pathfind(int startX, int startY, int endX, int endY, TileHueristic th, Boolf passable){
+ public static Seq pathfind(int startX, int startY, int endX, int endY, TileHeuristic th, Boolf passable){
return pathfind(startX, startY, endX, endY, th, manhattan, passable);
}
- public static Seq pathfind(int startX, int startY, int endX, int endY, TileHueristic th, DistanceHeuristic dh, Boolf passable){
+ public static Seq pathfind(int startX, int startY, int endX, int endY, TileHeuristic th, DistanceHeuristic dh, Boolf passable){
Tiles tiles = world.tiles;
Tile start = tiles.getn(startX, startY);
@@ -94,7 +94,7 @@ public class Astar{
float cost(int x1, int y1, int x2, int y2);
}
- public interface TileHueristic{
+ public interface TileHeuristic{
float cost(Tile tile);
default float cost(Tile from, Tile tile){
diff --git a/core/src/mindustry/ai/BaseBuilderAI.java b/core/src/mindustry/ai/BaseBuilderAI.java
index 3df72adb70..e9126f6ca5 100644
--- a/core/src/mindustry/ai/BaseBuilderAI.java
+++ b/core/src/mindustry/ai/BaseBuilderAI.java
@@ -258,7 +258,7 @@ public class BaseBuilderAI{
//queue it
for(Stile tile : result.tiles){
- data.plans.add(new BlockPlan(cx + tile.x, cy + tile.y, tile.rotation, tile.block.id, tile.config));
+ data.plans.add(new BlockPlan(cx + tile.x, cy + tile.y, tile.rotation, tile.block, tile.config));
}
return true;
diff --git a/core/src/mindustry/ai/ControlPathfinder.java b/core/src/mindustry/ai/ControlPathfinder.java
index be200eecda..ba9e3e6c75 100644
--- a/core/src/mindustry/ai/ControlPathfinder.java
+++ b/core/src/mindustry/ai/ControlPathfinder.java
@@ -58,8 +58,8 @@ public class ControlPathfinder implements Runnable{
costNaval = (team, tile) ->
//impassable same-team neutral block, or non-liquid
- (PathTile.solid(tile) && ((PathTile.team(tile) == team && !PathTile.teamPassable(tile)) || PathTile.team(tile) == 0)) || !PathTile.liquid(tile) ? impassable :
- 1 +
+ (PathTile.solid(tile) && ((PathTile.team(tile) == team && !PathTile.teamPassable(tile)) || PathTile.team(tile) == 0)) ? impassable :
+ (!PathTile.liquid(tile) ? 6000 : 1) +
//impassable synthetic enemy block
((PathTile.team(tile) != team && PathTile.team(tile) != 0) && PathTile.solid(tile) ? wallImpassableCap : 0) +
(PathTile.nearGround(tile) || PathTile.nearSolid(tile) ? 6 : 0);
@@ -124,7 +124,7 @@ public class ControlPathfinder implements Runnable{
//TODO: very dangerous usage;
//TODO - it is accessed from the main thread
//TODO - it is written to on the pathfinding thread
- //maps position in world in (x + y * width format) | type (bitpacked to long) to a cache of flow fields
+ //maps position in world in (x + y * width format) | path type | team (bitpacked to long with FieldIndex.get) to a cache of flow fields
LongMap fields = new LongMap<>();
//MAIN THREAD ONLY
Seq fieldList = new Seq<>(false);
@@ -188,6 +188,7 @@ public class ControlPathfinder implements Runnable{
final IntQueue frontier = new IntQueue();
//maps cluster index to field weights; 0 means uninitialized
final IntMap fields = new IntMap<>();
+ //packed (goalPos | costId | team) long key to use in the global fields map
final long mapKey;
//main thread only!
@@ -200,7 +201,7 @@ public class ControlPathfinder implements Runnable{
this.team = team;
this.goalPos = goalPos;
this.costId = costId;
- this.mapKey = Pack.longInt(goalPos, costId);
+ this.mapKey = FieldIndex.get(goalPos, costId, team);
}
}
@@ -232,24 +233,7 @@ public class ControlPathfinder implements Runnable{
Events.on(TileChangeEvent.class, e -> {
- e.tile.getLinkedTiles(t -> {
- int x = t.x, y = t.y, mx = x % clusterSize, my = y % clusterSize, cx = x / clusterSize, cy = y / clusterSize, cluster = cx + cy * cwidth;
-
- //is at the edge of a cluster; this means the portals may have changed.
- if(mx == 0 || my == 0 || mx == clusterSize - 1 || my == clusterSize - 1){
-
- if(mx == 0) queueClusterUpdate(cx - 1, cy); //left
- if(my == 0) queueClusterUpdate(cx, cy - 1); //bottom
- if(mx == clusterSize - 1) queueClusterUpdate(cx + 1, cy); //right
- if(my == clusterSize - 1) queueClusterUpdate(cx, cy + 1); //top
-
- queueClusterUpdate(cx, cy);
- //TODO: recompute edge clusters too.
- }else{
- //there is no need to recompute portals for block updates that are not on the edge.
- queue.post(() -> clustersToInnerUpdate.add(cluster));
- }
- });
+ updateTile(e.tile);
//TODO: recalculate affected flow fields? or just all of them? how to reflow?
});
@@ -258,7 +242,7 @@ public class ControlPathfinder implements Runnable{
Events.run(Trigger.update, () -> {
for(var req : unitRequests.values()){
//skipped N update -> drop it
- if(req.lastUpdateId <= state.updateId - 10){
+ if(req.lastUpdateId <= state.updateId - 10 || !req.unit.isAdded()){
req.invalidated = true;
//concurrent modification!
queue.post(() -> threadPathRequests.remove(req));
@@ -358,6 +342,29 @@ public class ControlPathfinder implements Runnable{
}
}
+ public void updateTile(Tile tile){
+ tile.getLinkedTiles(this::updateSingleTile);
+ }
+
+ public void updateSingleTile(Tile t){
+ int x = t.x, y = t.y, mx = x % clusterSize, my = y % clusterSize, cx = x / clusterSize, cy = y / clusterSize, cluster = cx + cy * cwidth;
+
+ //is at the edge of a cluster; this means the portals may have changed.
+ if(mx == 0 || my == 0 || mx == clusterSize - 1 || my == clusterSize - 1){
+
+ if(mx == 0) queueClusterUpdate(cx - 1, cy); //left
+ if(my == 0) queueClusterUpdate(cx, cy - 1); //bottom
+ if(mx == clusterSize - 1) queueClusterUpdate(cx + 1, cy); //right
+ if(my == clusterSize - 1) queueClusterUpdate(cx, cy + 1); //top
+
+ queueClusterUpdate(cx, cy);
+ //TODO: recompute edge clusters too.
+ }else{
+ //there is no need to recompute portals for block updates that are not on the edge.
+ queue.post(() -> clustersToInnerUpdate.add(cluster));
+ }
+ }
+
void queueClusterUpdate(int cx, int cy){
if(cx >= 0 && cy >= 0 && cx < cwidth && cy < cheight){
queue.post(() -> clustersToUpdate.add(cx + cy * cwidth));
@@ -534,7 +541,7 @@ public class ControlPathfinder implements Runnable{
void updateInnerEdges(int team, PathCost cost, int cx, int cy, Cluster cluster){
int minX = cx * clusterSize, minY = cy * clusterSize, maxX = Math.min(minX + clusterSize - 1, wwidth - 1), maxY = Math.min(minY + clusterSize - 1, wheight - 1);
-
+
usedEdges.clear();
//clear all connections, since portals changed, they need to be recomputed.
@@ -548,7 +555,7 @@ public class ControlPathfinder implements Runnable{
for(int i = 0; i < portals.size; i++){
usedEdges.add(Point2.pack(direction, i));
-
+
int
portal = portals.items[i],
from = Point2.x(portal), to = Point2.y(portal),
@@ -1020,10 +1027,12 @@ public class ControlPathfinder implements Runnable{
//no result found, bail out.
if(nodePath == null){
request.notFound = true;
+ //stop following the old path, it's not relevant now, it's just not possible to reach the destination anymore
+ request.oldCache = null;
return;
}
- FieldCache cache = fields.get(Pack.longInt(goalPos, costId));
+ FieldCache cache = fields.get(FieldIndex.get(goalPos, costId, team));
//if true, extra values are added on the sides of existing field cells that face new cells.
boolean addingFrontier = true;
@@ -1093,6 +1102,10 @@ public class ControlPathfinder implements Runnable{
}
public boolean getPathPosition(Unit unit, Vec2 destination, Vec2 mainDestination, Vec2 out, @Nullable boolean[] noResultFound){
+ if(noResultFound != null){
+ noResultFound[0] = false;
+ }
+
int costId = unit.type.pathCostId;
PathCost cost = idToCost(costId);
@@ -1139,7 +1152,7 @@ public class ControlPathfinder implements Runnable{
boolean any = false;
- long fieldKey = Pack.longInt(destPos, costId);
+ long fieldKey = FieldIndex.get(destPos, costId, team);
//use existing request if it exists.
if(request != null && request.destination == destPos){
@@ -1147,14 +1160,19 @@ public class ControlPathfinder implements Runnable{
Tile tileOn = unit.tileOn(), initialTileOn = tileOn;
//TODO: should fields be accessible from this thread?
- FieldCache fieldCache = fields.get(fieldKey);
+ FieldCache fieldCache = null;
+ try{
+ fieldCache = fields.get(fieldKey);
+ }catch(ArrayIndexOutOfBoundsException ignored){ //TODO fix this, rare crash due to remove() elsewhere
+ }
+ if(fieldCache == null) fieldCache = request.oldCache;
if(fieldCache != null && tileOn != null){
FieldCache old = request.oldCache;
FieldCache targetCache = old != null ? old : fieldCache;
boolean requeue = old == null;
//nullify the old field to be GCed, as it cannot be relevant anymore (this path is complete)
- if(fieldCache.frontier.isEmpty() && old != null){
+ if(fieldCache != request.oldCache && fieldCache.frontier.isEmpty() && old != null){
request.oldCache = null;
}
@@ -1245,7 +1263,11 @@ public class ControlPathfinder implements Runnable{
return true;
}
}
- }else if(request == null){
+ }else{
+ //destroy the old one immediately, it's invalid now
+ if(request != null){
+ request.lastUpdateId = -1000;
+ }
//queue new request.
unitRequests.put(unit, request = new PathRequest(unit, team, costId, destPos));
@@ -1258,9 +1280,7 @@ public class ControlPathfinder implements Runnable{
recalculatePath(f);
});
- out.set(destination);
-
- return true;
+ return false;
}
if(noResultFound != null){
@@ -1445,7 +1465,7 @@ public class ControlPathfinder implements Runnable{
int index = cx + cy * cwidth;
for(var req : threadPathRequests){
- long mapKey = Pack.longInt(req.destination, pathCost);
+ long mapKey = FieldIndex.get(req.destination, pathCost, team);
var field = fields.get(mapKey);
if((field != null && field.fields.containsKey(index)) || req.notFound){
invalidRequests.add(req);
@@ -1531,7 +1551,7 @@ public class ControlPathfinder implements Runnable{
continue;
}
- long mapKey = Pack.longInt(request.destination, request.costId);
+ long mapKey = FieldIndex.get(request.destination, request.costId, request.team);
var field = fields.get(mapKey);
@@ -1539,7 +1559,7 @@ public class ControlPathfinder implements Runnable{
//it's only worth recalculating a path when the current frontier has finished; otherwise the unit will be following something incomplete.
if(field.frontier.isEmpty()){
- //remove the field, to be recalculated next update one recalculatePath is processed
+ //remove the field, to be recalculated next update once recalculatePath is processed
fields.remove(field.mapKey);
Core.app.post(() -> fieldList.remove(field));
@@ -1547,6 +1567,10 @@ public class ControlPathfinder implements Runnable{
for(var otherRequest : threadPathRequests){
if(otherRequest.destination == request.destination){
otherRequest.oldCache = field;
+
+ if(otherRequest != request){
+ queue.post(() -> recalculatePath(otherRequest));
+ }
}
}
@@ -1580,6 +1604,15 @@ public class ControlPathfinder implements Runnable{
}
}
+ @Struct
+ static class FieldIndexStruct{
+ int pos;
+ @StructField(8)
+ int costId;
+ @StructField(8)
+ int team;
+ }
+
@Struct
static class IntraEdgeStruct{
@StructField(8)
diff --git a/core/src/mindustry/ai/Pathfinder.java b/core/src/mindustry/ai/Pathfinder.java
index 19f8a48697..615568aed7 100644
--- a/core/src/mindustry/ai/Pathfinder.java
+++ b/core/src/mindustry/ai/Pathfinder.java
@@ -2,6 +2,7 @@ package mindustry.ai;
import arc.*;
import arc.func.*;
+import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
@@ -16,6 +17,7 @@ import mindustry.world.blocks.storage.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
+import static mindustry.world.meta.BlockFlag.*;
public class Pathfinder implements Runnable{
private static final long maxUpdate = Time.millisToNanos(8);
@@ -37,7 +39,8 @@ public class Pathfinder implements Runnable{
public static final int
costGround = 0,
costLegs = 1,
- costNaval = 2;
+ costNaval = 2,
+ costHover = 3;
public static final Seq costTypes = Seq.with(
//ground
@@ -61,7 +64,13 @@ public class Pathfinder implements Runnable{
PathTile.health(tile) * 5 +
(PathTile.nearGround(tile) || PathTile.nearSolid(tile) ? 14 : 0) +
(PathTile.deep(tile) ? 0 : 1) +
- (PathTile.damages(tile) ? 35 : 0)
+ (PathTile.damages(tile) ? 35 : 0),
+
+ //hover
+ (team, tile) ->
+ (((PathTile.team(tile) == team && !PathTile.teamPassable(tile)) || PathTile.team(tile) == 0) && PathTile.solid(tile)) ? impassable : 1 +
+ PathTile.health(tile) * 5 +
+ (PathTile.nearSolid(tile) ? 2 : 0)
);
/** tile data, see PathTileStruct - kept as a separate array for threading reasons */
@@ -243,6 +252,8 @@ public class Pathfinder implements Runnable{
data.dirty = true;
}
});
+
+ controlPath.updateTile(tile);
}
/** Thread implementation. */
@@ -452,8 +463,34 @@ public class Pathfinder implements Runnable{
}
public static class EnemyCoreField extends Flowfield{
+ private final static BlockFlag[] randomTargets = {storage, generator, launchPad, factory, repair, battery, reactor, drill};
+ private Rand rand = new Rand();
+
@Override
protected void getPositions(IntSeq out){
+ if(state.rules.randomWaveAI && team == state.rules.waveTeam){
+ rand.setSeed(state.rules.waves ? state.wave : (int)(state.tick / (5400)) + hashCode());
+
+ //maximum amount of different target flag types they will attack
+ int max = 1;
+
+ for(int attempt = 0; attempt < 5 && max > 0; attempt++){
+ var targets = indexer.getEnemy(team, randomTargets[rand.random(randomTargets.length - 1)]);
+ if(!targets.isEmpty()){
+ boolean any = false;
+ for(Building other : targets){
+ if((other.items != null && other.items.any()) || other.status() != BlockStatus.noInput){
+ out.add(other.tile.array());
+ any = true;
+ }
+ }
+ if(any){
+ max --;
+ }
+ }
+ }
+ }
+
for(Building other : indexer.getEnemy(team, BlockFlag.core)){
out.add(other.tile.array());
}
diff --git a/core/src/mindustry/ai/RtsAI.java b/core/src/mindustry/ai/RtsAI.java
index 16fcf3ec7a..b97e58e464 100644
--- a/core/src/mindustry/ai/RtsAI.java
+++ b/core/src/mindustry/ai/RtsAI.java
@@ -343,7 +343,7 @@ public class RtsAI{
//other can never be destroyed | other destroys self instantly
if(Float.isInfinite(timeDestroyOther) || Mathf.zero(timeDestroySelf)) return 0f;
//self can never be destroyed | self destroys other instantly
- if(Float.isInfinite(timeDestroySelf) || Mathf.zero(timeDestroyOther)) return 1f;
+ if(Float.isInfinite(timeDestroySelf) || Mathf.zero(timeDestroyOther)) return 100000f;
//examples:
// self 10 sec / other 10 sec -> can destroy target with 100 % losses -> returns 1
diff --git a/core/src/mindustry/ai/UnitCommand.java b/core/src/mindustry/ai/UnitCommand.java
index 51a0edfcf8..85eff6be00 100644
--- a/core/src/mindustry/ai/UnitCommand.java
+++ b/core/src/mindustry/ai/UnitCommand.java
@@ -17,7 +17,7 @@ public class UnitCommand extends MappableContent{
@Deprecated
public static final Seq all = new Seq<>();
- public static UnitCommand moveCommand, repairCommand, rebuildCommand, assistCommand, mineCommand, boostCommand, enterPayloadCommand, loadUnitsCommand, loadBlocksCommand, unloadPayloadCommand;
+ public static UnitCommand moveCommand, repairCommand, rebuildCommand, assistCommand, mineCommand, boostCommand, enterPayloadCommand, loadUnitsCommand, loadBlocksCommand, unloadPayloadCommand, loopPayloadCommand;
/** Name of UI icon (from Icon class). */
public final String icon;
@@ -110,5 +110,10 @@ public class UnitCommand extends MappableContent{
drawTarget = true;
resetTarget = false;
}};
+ loopPayloadCommand = new UnitCommand("loopPayload", "resize", Binding.unit_command_loop_payload, null){{
+ switchToMove = false;
+ drawTarget = true;
+ resetTarget = false;
+ }};
}
}
diff --git a/core/src/mindustry/ai/UnitGroup.java b/core/src/mindustry/ai/UnitGroup.java
index 8973c3e2fb..0c0366cf29 100644
--- a/core/src/mindustry/ai/UnitGroup.java
+++ b/core/src/mindustry/ai/UnitGroup.java
@@ -18,7 +18,7 @@ public class UnitGroup{
public int collisionLayer;
public volatile float[] positions, originalPositions;
public volatile boolean valid;
-
+
public void calculateFormation(Vec2 dest, int collisionLayer){
this.collisionLayer = collisionLayer;
@@ -72,7 +72,7 @@ public class UnitGroup{
positions[a * 2] = v1.x;
positions[a * 2 + 1] = v1.y;
- float rad = units.get(a).hitSize/2f;
+ float rad = units.get(a).hitSize * Vars.unitCollisionRadiusScale;
maxDst = Math.max(maxDst, v1.dst(0f, 0f) + rad);
totalArea += Mathf.PI * rad * rad;
diff --git a/core/src/mindustry/ai/WaveSpawner.java b/core/src/mindustry/ai/WaveSpawner.java
index e23dbbff5e..7935418c5f 100644
--- a/core/src/mindustry/ai/WaveSpawner.java
+++ b/core/src/mindustry/ai/WaveSpawner.java
@@ -66,12 +66,22 @@ public class WaveSpawner{
if(group.type == null) continue;
int spawned = group.getSpawned(state.wave - 1);
+ if(spawned == 0) continue;
+
+ if(state.isCampaign()){
+ //when spawning a boss, round down, so 1.5x (hard) * 1 boss does not result in 2 bosses
+ spawned = Math.max(1, group.effect == StatusEffects.boss ?
+ (int)(spawned * state.getPlanet().campaignRules.difficulty.enemySpawnMultiplier) :
+ Mathf.round(spawned * state.getPlanet().campaignRules.difficulty.enemySpawnMultiplier));
+ }
+
+ int spawnedf = spawned;
if(group.type.flying){
float spread = margin / 1.5f;
eachFlyerSpawn(group.spawn, (spawnX, spawnY) -> {
- for(int i = 0; i < spawned; i++){
+ for(int i = 0; i < spawnedf; i++){
Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1);
unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread));
spawnEffect(unit);
@@ -82,7 +92,7 @@ public class WaveSpawner{
eachGroundSpawn(group.spawn, (spawnX, spawnY, doShockwave) -> {
- for(int i = 0; i < spawned; i++){
+ for(int i = 0; i < spawnedf; i++){
Tmp.v1.rnd(spread);
Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1);
@@ -153,7 +163,7 @@ public class WaveSpawner{
private void eachFlyerSpawn(int filterPos, Floatc2 cons){
boolean airUseSpawns = state.rules.airUseSpawns;
-
+
for(Tile tile : spawns){
if(filterPos != -1 && filterPos != tile.pos()) continue;
diff --git a/core/src/mindustry/ai/types/BuilderAI.java b/core/src/mindustry/ai/types/BuilderAI.java
index ccbe64b7c6..7932ad8d9c 100644
--- a/core/src/mindustry/ai/types/BuilderAI.java
+++ b/core/src/mindustry/ai/types/BuilderAI.java
@@ -179,12 +179,12 @@ public class BuilderAI extends AIController{
BlockPlan block = blocks.first();
//check if it's already been placed
- if(world.tile(block.x, block.y) != null && world.tile(block.x, block.y).block().id == block.block){
+ if(world.tile(block.x, block.y) != null && world.tile(block.x, block.y).block() == block.block){
blocks.removeFirst();
- }else if(Build.validPlace(content.block(block.block), unit.team(), block.x, block.y, block.rotation) && (!alwaysFlee || !nearEnemy(block.x, block.y))){ //it's valid
+ }else if(Build.validPlace(block.block, unit.team(), block.x, block.y, block.rotation) && (!alwaysFlee || !nearEnemy(block.x, block.y))){ //it's valid
lastPlan = block;
//add build plan
- unit.addBuild(new BuildPlan(block.x, block.y, block.rotation, content.block(block.block), block.config));
+ unit.addBuild(new BuildPlan(block.x, block.y, block.rotation, block.block, block.config));
//shift build plan to tail so next unit builds something else
blocks.addLast(blocks.removeFirst());
}else{
@@ -195,7 +195,7 @@ public class BuilderAI extends AIController{
}
if(!unit.type.flying){
- unit.updateBoosting(moving || unit.floorOn().isDuct || unit.floorOn().damageTaken > 0f);
+ unit.updateBoosting(unit.type.boostWhenBuilding || moving || unit.floorOn().isDuct || unit.floorOn().damageTaken > 0f || unit.floorOn().isDeep());
}
}
diff --git a/core/src/mindustry/ai/types/CommandAI.java b/core/src/mindustry/ai/types/CommandAI.java
index 763916539a..9446e72aa3 100644
--- a/core/src/mindustry/ai/types/CommandAI.java
+++ b/core/src/mindustry/ai/types/CommandAI.java
@@ -20,11 +20,12 @@ public class CommandAI extends AIController{
protected static final Vec2 vecOut = new Vec2(), vecMovePos = new Vec2();
protected static final boolean[] noFound = {false};
protected static final UnitPayload tmpPayload = new UnitPayload(null);
+ protected static final int transferStateNone = 0, transferStateLoad = 1, transferStateUnload = 2;
public Seq commandQueue = new Seq<>(5);
public @Nullable Vec2 targetPos;
public @Nullable Teamc attackTarget;
- /** Group of units that were all commanded to reach the same point.. */
+ /** Group of units that were all commanded to reach the same point. */
public @Nullable UnitGroup group;
public int groupIndex = 0;
/** All encountered unreachable buildings of this AI. Why a sequence? Because contains() is very rarely called on it. */
@@ -36,6 +37,8 @@ public class CommandAI extends AIController{
protected Vec2 lastTargetPos;
protected boolean blockingUnit;
protected float timeSpentBlocked;
+ protected float payloadPickupCooldown;
+ protected int transferState = transferStateNone;
/** Stance, usually related to firing mode. */
public UnitStance stance = UnitStance.shoot;
@@ -52,7 +55,7 @@ public class CommandAI extends AIController{
/** Attempts to assign a command to this unit. If not supported by the unit type, does nothing. */
public void command(UnitCommand command){
- if(Structs.contains(unit.type.commands, command)){
+ if(unit.type.commands.contains(command)){
//clear old state.
unit.mineTile = null;
unit.clearBuilding();
@@ -85,8 +88,8 @@ public class CommandAI extends AIController{
}
//assign defaults
- if(command == null && unit.type.commands.length > 0){
- command = unit.type.defaultCommand == null ? unit.type.commands[0] : unit.type.defaultCommand;
+ if(command == null && unit.type.commands.size > 0){
+ command = unit.type.defaultCommand == null ? unit.type.commands.first() : unit.type.defaultCommand;
}
//update command controller based on index.
@@ -113,9 +116,18 @@ public class CommandAI extends AIController{
attackTarget = null;
}
+ void tryPickupUnit(Payloadc pay){
+ Unit target = Units.closest(unit.team, unit.x, unit.y, unit.type.hitSize * 2f, u -> u.isAI() && u != unit && u.isGrounded() && pay.canPickup(u) && u.within(unit, u.hitSize + unit.hitSize));
+ if(target != null){
+ Call.pickedUnitPayload(unit, target);
+ }
+ }
+
public void defaultBehavior(){
if(!net.client() && unit instanceof Payloadc pay){
+ payloadPickupCooldown -= Time.delta;
+
//auto-drop everything
if(command == UnitCommand.unloadPayloadCommand && pay.hasPayload()){
Call.payloadDropped(unit, unit.x, unit.y);
@@ -123,10 +135,7 @@ public class CommandAI extends AIController{
//try to pick up what's under it
if(command == UnitCommand.loadUnitsCommand){
- Unit target = Units.closest(unit.team, unit.x, unit.y, unit.type.hitSize * 2f, u -> u.isAI() && u != unit && u.isGrounded() && pay.canPickup(u) && u.within(unit, u.hitSize + unit.hitSize));
- if(target != null){
- Call.pickedUnitPayload(unit, target);
- }
+ tryPickupUnit(pay);
}
//try to pick up a block
@@ -218,8 +227,14 @@ public class CommandAI extends AIController{
vecMovePos.add(group.positions[groupIndex * 2], group.positions[groupIndex * 2 + 1]);
}
+ Building targetBuild = world.buildWorld(targetPos.x, targetPos.y);
+
//TODO: should the unit stop when it finds a target?
- if(stance == UnitStance.patrol && target != null && unit.within(target, unit.type.range - 2f) && !unit.type.circleTarget){
+ if(
+ (stance == UnitStance.patrol && target != null && unit.within(target, unit.type.range - 2f) && !unit.type.circleTarget) ||
+ (command == UnitCommand.enterPayloadCommand && unit.within(targetPos, 4f) || (targetBuild != null && unit.within(targetBuild, targetBuild.block.size * tilesize/2f * 0.9f))) ||
+ (command == UnitCommand.loopPayloadCommand && unit.within(targetPos, 10f))
+ ){
move = false;
}
@@ -260,6 +275,13 @@ public class CommandAI extends AIController{
vecOut.set(vecMovePos);
}else{
move = controlPath.getPathPosition(unit, vecMovePos, targetPos, vecOut, noFound) && (!blockingUnit || timeSpentBlocked > maxBlockTime);
+
+ //TODO: what to do when there's a target and it can't be reached?
+ /*
+ if(noFound[0] && attackTarget != null && attackTarget.within(unit, unit.type.range * 2f)){
+ move = true;
+ vecOut.set(targetPos);
+ }*/
}
//rare case where unit must be perfectly aligned (happens with 1-tile gaps)
@@ -321,10 +343,54 @@ public class CommandAI extends AIController{
void finishPath(){
//the enter payload command never finishes until they are actually accepted
- if(command == UnitCommand.enterPayloadCommand && commandQueue.size == 0 && targetPos != null && world.buildWorld(targetPos.x, targetPos.y) != null && world.buildWorld(targetPos.x, targetPos.y).block.acceptsPayloads){
+ if(command == UnitCommand.enterPayloadCommand && commandQueue.size == 0 && targetPos != null && world.buildWorld(targetPos.x, targetPos.y) != null && world.buildWorld(targetPos.x, targetPos.y).block.acceptsUnitPayloads){
return;
}
+ if(!net.client() && command == UnitCommand.loopPayloadCommand && unit instanceof Payloadc pay){
+
+ if(transferState == transferStateNone){
+ transferState = pay.hasPayload() ? transferStateUnload : transferStateLoad;
+ }
+
+ if(payloadPickupCooldown > 0f) return;
+
+ if(transferState == transferStateUnload){
+ //drop until there's a failure
+ int prev = -1;
+ while(pay.hasPayload() && prev != pay.payloads().size){
+ prev = pay.payloads().size;
+ Call.payloadDropped(unit, unit.x, unit.y);
+ }
+
+ //wait for everything to unload before running code below
+ if(pay.hasPayload()){
+ return;
+ }
+ payloadPickupCooldown = 60f;
+ }else if(transferState == transferStateLoad){
+ //pick up units until there's a failure
+ int prev = -1;
+ while(prev != pay.payloads().size){
+ prev = pay.payloads().size;
+ tryPickupUnit(pay);
+ }
+
+ //wait to load things before running code below
+ if(!pay.hasPayload()){
+ return;
+ }
+ payloadPickupCooldown = 60f;
+ }
+
+ //it will never finish
+ if(commandQueue.size == 0){
+ return;
+ }
+ }
+
+ transferState = transferStateNone;
+
Vec2 prev = targetPos;
targetPos = null;
@@ -336,7 +402,7 @@ public class CommandAI extends AIController{
commandPosition(position);
}
- if(prev != null && stance == UnitStance.patrol){
+ if(prev != null && (stance == UnitStance.patrol || command == UnitCommand.loopPayloadCommand)){
commandQueue.add(prev.cpy());
}
@@ -351,10 +417,15 @@ public class CommandAI extends AIController{
}
}
+ @Override
+ public void removed(Unit unit){
+ clearCommands();
+ }
+
public void commandQueue(Position location){
if(targetPos == null && attackTarget == null){
- if(location instanceof Teamc target){
- commandTarget(target, this.stopAtTarget);
+ if(location instanceof Teamc t){
+ commandTarget(t, this.stopAtTarget);
}else if(location instanceof Vec2 position){
commandPosition(position);
}
@@ -392,7 +463,7 @@ public class CommandAI extends AIController{
@Override
public Teamc findTarget(float x, float y, float range, boolean air, boolean ground){
- return !nearAttackTarget(x, y, range) ? super.findTarget(x, y, range, air, ground) : attackTarget;
+ return !nearAttackTarget(x, y, range) ? super.findTarget(x, y, range, air, ground) : Units.isHittable(attackTarget, air, ground) ? attackTarget : null;
}
public boolean nearAttackTarget(float x, float y, float range){
@@ -445,52 +516,4 @@ public class CommandAI extends AIController{
this.stopAtTarget = stopAtTarget;
}
- /*
-
- //TODO ひどい
- (does not work)
-
- public static float cohesionScl = 0.3f;
- public static float cohesionRad = 3f, separationRad = 1.1f, separationScl = 1f, flockMult = 0.5f;
-
- Vec2 calculateFlock(){
- if(local.isEmpty()) return flockVec.setZero();
-
- flockVec.setZero();
- separation.setZero();
- cohesion.setZero();
- massCenter.set(unit);
-
- float rad = unit.hitSize;
- float sepDst = rad * separationRad, cohDst = rad * cohesionRad;
-
- //"cohesed" isn't even a word smh
- int separated = 0, cohesed = 1;
-
- for(var other : local){
- float dst = other.dst(unit);
- if(dst < sepDst){
- separation.add(Tmp.v1.set(unit).sub(other).scl(1f / sepDst));
- separated ++;
- }
-
- if(dst < cohDst){
- massCenter.add(other);
- cohesed ++;
- }
- }
-
- if(separated > 0){
- separation.scl(1f / separated);
- flockVec.add(separation.scl(separationScl));
- }
-
- if(cohesed > 1){
- massCenter.scl(1f / cohesed);
- flockVec.add(Tmp.v1.set(massCenter).sub(unit).limit(cohesionScl * unit.type.speed));
- //seek mass center?
- }
-
- return flockVec;
- }*/
}
diff --git a/core/src/mindustry/ai/types/FlyingAI.java b/core/src/mindustry/ai/types/FlyingAI.java
index a938b5d3b6..a412c6f4da 100644
--- a/core/src/mindustry/ai/types/FlyingAI.java
+++ b/core/src/mindustry/ai/types/FlyingAI.java
@@ -2,13 +2,16 @@ package mindustry.ai.types;
import arc.math.*;
import mindustry.entities.units.*;
+import mindustry.game.*;
import mindustry.gen.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
+import static mindustry.world.meta.BlockFlag.*;
-//TODO very strange idle behavior sometimes
public class FlyingAI extends AIController{
+ final static Rand rand = new Rand();
+ final static BlockFlag[] randomTargets = {core, storage, generator, launchPad, factory, repair, battery, reactor, drill};
@Override
public void updateMovement(){
@@ -28,6 +31,30 @@ public class FlyingAI extends AIController{
}
}
+ @Override
+ public Teamc targetFlag(float x, float y, BlockFlag flag, boolean enemy){
+ if(state.rules.randomWaveAI){
+ if(unit.team == Team.derelict) return null;
+ var list = enemy ? indexer.getEnemy(unit.team, flag) : indexer.getFlagged(unit.team, flag);
+ if(list.isEmpty()) return null;
+
+ Building closest = null;
+ float cdist = 0f;
+ for(Building t : list){
+ if((t.items != null && t.items.any()) || t.status() != BlockStatus.noInput){
+ float dst = t.dst2(x, y);
+ if(closest == null || dst < cdist){
+ closest = t;
+ cdist = dst;
+ }
+ }
+ }
+ return closest;
+ }else{
+ return super.targetFlag(x, y, flag, enemy);
+ }
+ }
+
@Override
public Teamc findTarget(float x, float y, float range, boolean air, boolean ground){
var result = findMainTarget(x, y, range, air, ground);
@@ -44,14 +71,27 @@ public class FlyingAI extends AIController{
return core;
}
- for(var flag : unit.type.targetFlags){
- 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(state.rules.randomWaveAI){
+ //when there are no waves, it's just random based on the unit
+ rand.setSeed(unit.type.id + (state.rules.waves ? state.wave : unit.id));
+ //try a few random flags first
+ for(int attempt = 0; attempt < 5; attempt++){
+ Teamc result = targetFlag(x, y, randomTargets[rand.random(randomTargets.length - 1)], true);
if(result != null) return result;
}
+ //try the closest target
+ Teamc result = target(x, y, range, air, ground);
+ if(result != null) return result;
+ }else{
+ for(var flag : unit.type.targetFlags){
+ 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;
diff --git a/core/src/mindustry/ai/types/MissileAI.java b/core/src/mindustry/ai/types/MissileAI.java
index 4dafbd6156..082c445048 100644
--- a/core/src/mindustry/ai/types/MissileAI.java
+++ b/core/src/mindustry/ai/types/MissileAI.java
@@ -10,6 +10,11 @@ import mindustry.gen.*;
public class MissileAI extends AIController{
public @Nullable Unit shooter;
+ @Override
+ protected void resetTimers(){
+ timer.reset(timerTarget, 5f);
+ }
+
@Override
public void updateMovement(){
unloadPayloads();
@@ -33,7 +38,7 @@ public class MissileAI extends AIController{
@Override
public Teamc target(float x, float y, float range, boolean air, boolean ground){
- return Units.closestTarget(unit.team, x, y, range, u -> u.checkTarget(air, ground), t -> ground && (!t.block.underBullets || (shooter != null && t == Vars.world.buildWorld(shooter.aimX, shooter.aimY))));
+ return Units.closestTarget(unit.team, x, y, range, u -> u.checkTarget(air, ground) && !u.isMissile(), t -> ground && (!t.block.underBullets || (shooter != null && t == Vars.world.buildWorld(shooter.aimX, shooter.aimY))));
}
@Override
diff --git a/core/src/mindustry/async/PhysicsProcess.java b/core/src/mindustry/async/PhysicsProcess.java
index 183d126217..a38f28eeb2 100644
--- a/core/src/mindustry/async/PhysicsProcess.java
+++ b/core/src/mindustry/async/PhysicsProcess.java
@@ -45,7 +45,7 @@ public class PhysicsProcess implements AsyncProcess{
body.x = entity.x;
body.y = entity.y;
body.mass = entity.mass();
- body.radius = entity.hitSize / 2f;
+ body.radius = entity.hitSize * Vars.unitCollisionRadiusScale;
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 2c33c82630..db554cc54d 100644
--- a/core/src/mindustry/content/Blocks.java
+++ b/core/src/mindustry/content/Blocks.java
@@ -43,7 +43,7 @@ public class Blocks{
public static Block
//environment
- air, spawn, cliff, deepwater, water, taintedWater, deepTaintedWater, tar, slag, cryofluid, stone, craters, charr, sand, darksand, dirt, mud, ice, snow, darksandTaintedWater, space, empty,
+ air, spawn, removeWall, removeOre, cliff, deepwater, water, taintedWater, deepTaintedWater, tar, slag, cryofluid, stone, craters, charr, sand, darksand, dirt, mud, ice, snow, darksandTaintedWater, space, empty,
dacite, rhyolite, rhyoliteCrater, roughRhyolite, regolith, yellowStone, redIce, redStone, denseRedStone,
arkyciteFloor, arkyicStone,
redmat, bluemat,
@@ -73,7 +73,7 @@ public class Blocks{
melter, separator, disassembler, sporePress, pulverizer, incinerator, coalCentrifuge,
//crafting - erekir
- siliconArcFurnace, electrolyzer, oxidationChamber, atmosphericConcentrator, electricHeater, slagHeater, phaseHeater, heatRedirector, heatRouter, slagIncinerator,
+ siliconArcFurnace, electrolyzer, oxidationChamber, atmosphericConcentrator, electricHeater, slagHeater, phaseHeater, heatRedirector, smallHeatRedirector, heatRouter, slagIncinerator,
carbideCrucible, slagCentrifuge, surgeCrucible, cyanogenSynthesizer, phaseSynthesizer, heatReactor,
//sandbox
@@ -125,7 +125,7 @@ public class Blocks{
//production
mechanicalDrill, pneumaticDrill, laserDrill, blastDrill, waterExtractor, oilExtractor, cultivator,
- cliffCrusher, plasmaBore, largePlasmaBore, impactDrill, eruptionDrill,
+ cliffCrusher, largeCliffCrusher, plasmaBore, largePlasmaBore, impactDrill, eruptionDrill,
//storage
coreShard, coreFoundation, coreNucleus, vault, container, unloader,
@@ -156,7 +156,7 @@ public class Blocks{
//payloads
payloadConveyor, payloadRouter, reinforcedPayloadConveyor, reinforcedPayloadRouter, payloadMassDriver, largePayloadMassDriver, smallDeconstructor, deconstructor, constructor, largeConstructor, payloadLoader, payloadUnloader,
-
+
//logic
message, switchBlock, microProcessor, logicProcessor, hyperProcessor, largeLogicDisplay, logicDisplay, memoryCell, memoryBank,
canvas, reinforcedMessage,
@@ -174,6 +174,10 @@ public class Blocks{
spawn = new SpawnBlock("spawn");
+ removeWall = new RemoveWall("remove-wall");
+
+ removeOre = new RemoveOre("remove-ore");
+
cliff = new Cliff("cliff"){{
inEditor = false;
saveData = true;
@@ -973,7 +977,7 @@ public class Blocks{
consumeItems(with(Items.thorium, 4, Items.sand, 10));
consumePower(5f);
- itemCapacity = 20;
+ itemCapacity = 30;
}};
surgeSmelter = new GenericCrafter("surge-smelter"){{
@@ -1269,7 +1273,7 @@ public class Blocks{
}};
electricHeater = new HeatProducer("electric-heater"){{
- requirements(Category.crafting, with(Items.tungsten, 30, Items.oxide, 30));
+ requirements(Category.crafting, with(Items.tungsten, 30, Items.oxide, 30, Items.beryllium, 30));
researchCostMultiplier = 4f;
@@ -1282,7 +1286,7 @@ public class Blocks{
itemCapacity = 0;
consumePower(100f / 60f);
}};
-
+
slagHeater = new HeatProducer("slag-heater"){{
requirements(Category.crafting, with(Items.tungsten, 50, Items.oxide, 20, Items.beryllium, 20));
@@ -1323,6 +1327,17 @@ public class Blocks{
regionRotated1 = 1;
}};
+ smallHeatRedirector = new HeatConductor("small-heat-redirector"){{
+ requirements(Category.crafting, with(Items.surgeAlloy, 10, Items.graphite, 10));
+
+ researchCostMultiplier = 10f;
+
+ group = BlockGroup.heat;
+ size = 2;
+ drawer = new DrawMulti(new DrawDefault(), new DrawHeatOutput(), new DrawHeatInput("-heat"));
+ regionRotated1 = 1;
+ }};
+
heatRouter = new HeatConductor("heat-router"){{
requirements(Category.crafting, with(Items.tungsten, 15, Items.graphite, 10));
@@ -1338,7 +1353,7 @@ public class Blocks{
slagIncinerator = new ItemIncinerator("slag-incinerator"){{
requirements(Category.crafting, with(Items.tungsten, 15));
size = 1;
- consumeLiquid(Liquids.slag, 2f / 60f);
+ consumeLiquid(Liquids.slag, 0f);
}};
carbideCrucible = new HeatCrafter("carbide-crucible"){{
@@ -1421,7 +1436,6 @@ public class Blocks{
}});
consumeItem(Items.silicon, 3);
- //TODO consume hydrogen/ozone?
consumeLiquid(Liquids.slag, 40f / 60f);
consumePower(2f);
}};
@@ -1451,7 +1465,6 @@ public class Blocks{
liquidCapacity = 80f;
outputLiquid = new LiquidStack(Liquids.cyanogen, 3f / 60f);
- //consumeLiquids(LiquidStack.with(Liquids.hydrogen, 3f / 60f, Liquids.nitrogen, 2f / 60f));
consumeLiquid(Liquids.arkycite, 40f / 60f);
consumeItem(Items.graphite);
consumePower(2f);
@@ -1513,27 +1526,23 @@ public class Blocks{
requirements(Category.defense, with(Items.copper, 6));
health = 80 * wallHealthMultiplier;
researchCostMultiplier = 0.1f;
- envDisabled |= Env.scorching;
}};
copperWallLarge = new Wall("copper-wall-large"){{
requirements(Category.defense, ItemStack.mult(copperWall.requirements, 4));
health = 80 * 4 * wallHealthMultiplier;
size = 2;
- envDisabled |= Env.scorching;
}};
titaniumWall = new Wall("titanium-wall"){{
requirements(Category.defense, with(Items.titanium, 6));
health = 110 * wallHealthMultiplier;
- envDisabled |= Env.scorching;
}};
titaniumWallLarge = new Wall("titanium-wall-large"){{
requirements(Category.defense, ItemStack.mult(titaniumWall.requirements, 4));
health = 110 * wallHealthMultiplier * 4;
size = 2;
- envDisabled |= Env.scorching;
}};
plastaniumWall = new Wall("plastanium-wall"){{
@@ -1542,7 +1551,6 @@ public class Blocks{
insulated = true;
absorbLasers = true;
schematicPriority = 10;
- envDisabled |= Env.scorching;
}};
plastaniumWallLarge = new Wall("plastanium-wall-large"){{
@@ -1552,20 +1560,17 @@ public class Blocks{
insulated = true;
absorbLasers = true;
schematicPriority = 10;
- envDisabled |= Env.scorching;
}};
thoriumWall = new Wall("thorium-wall"){{
requirements(Category.defense, with(Items.thorium, 6));
health = 200 * wallHealthMultiplier;
- envDisabled |= Env.scorching;
}};
thoriumWallLarge = new Wall("thorium-wall-large"){{
requirements(Category.defense, ItemStack.mult(thoriumWall.requirements, 4));
health = 200 * wallHealthMultiplier * 4;
size = 2;
- envDisabled |= Env.scorching;
}};
phaseWall = new Wall("phase-wall"){{
@@ -1573,7 +1578,6 @@ public class Blocks{
health = 150 * wallHealthMultiplier;
chanceDeflect = 10f;
flashHit = true;
- envDisabled |= Env.scorching;
}};
phaseWallLarge = new Wall("phase-wall-large"){{
@@ -1582,14 +1586,12 @@ public class Blocks{
size = 2;
chanceDeflect = 10f;
flashHit = true;
- envDisabled |= Env.scorching;
}};
surgeWall = new Wall("surge-wall"){{
requirements(Category.defense, with(Items.surgeAlloy, 6));
health = 230 * wallHealthMultiplier;
lightningChance = 0.05f;
- envDisabled |= Env.scorching;
}};
surgeWallLarge = new Wall("surge-wall-large"){{
@@ -1597,13 +1599,11 @@ public class Blocks{
health = 230 * 4 * wallHealthMultiplier;
size = 2;
lightningChance = 0.05f;
- envDisabled |= Env.scorching;
}};
door = new Door("door"){{
requirements(Category.defense, with(Items.titanium, 6, Items.silicon, 4));
health = 100 * wallHealthMultiplier;
- envDisabled |= Env.scorching;
}};
doorLarge = new Door("door-large"){{
@@ -1612,44 +1612,42 @@ public class Blocks{
closefx = Fx.doorcloselarge;
health = 100 * 4 * wallHealthMultiplier;
size = 2;
- envDisabled |= Env.scorching;
}};
scrapWall = new Wall("scrap-wall"){{
- requirements(Category.defense, BuildVisibility.sandboxOnly, with(Items.scrap, 6));
+ requirements(Category.defense, with(Items.scrap, 6));
health = 60 * wallHealthMultiplier;
variants = 5;
- envDisabled |= Env.scorching;
+ buildCostMultiplier = 4f;
}};
scrapWallLarge = new Wall("scrap-wall-large"){{
- requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.mult(scrapWall.requirements, 4));
+ requirements(Category.defense, ItemStack.mult(scrapWall.requirements, 4));
health = 60 * 4 * wallHealthMultiplier;
size = 2;
variants = 4;
- envDisabled |= Env.scorching;
+ buildCostMultiplier = 4f;
}};
scrapWallHuge = new Wall("scrap-wall-huge"){{
- requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.mult(scrapWall.requirements, 9));
+ requirements(Category.defense, ItemStack.mult(scrapWall.requirements, 9));
health = 60 * 9 * wallHealthMultiplier;
size = 3;
variants = 3;
- envDisabled |= Env.scorching;
+ buildCostMultiplier = 4f;
}};
scrapWallGigantic = new Wall("scrap-wall-gigantic"){{
- requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.mult(scrapWall.requirements, 16));
+ requirements(Category.defense, ItemStack.mult(scrapWall.requirements, 16));
health = 60 * 16 * wallHealthMultiplier;
size = 4;
- envDisabled |= Env.scorching;
+ buildCostMultiplier = 4f;
}};
thruster = new Thruster("thruster"){{
requirements(Category.defense, BuildVisibility.sandboxOnly, with(Items.scrap, 96));
health = 55 * 16 * wallHealthMultiplier;
size = 4;
- envDisabled |= Env.scorching;
}};
berylliumWall = new Wall("beryllium-wall"){{
@@ -1915,14 +1913,14 @@ public class Blocks{
plastaniumConveyor = new StackConveyor("plastanium-conveyor"){{
requirements(Category.distribution, with(Items.plastanium, 1, Items.silicon, 1, Items.graphite, 1));
- health = 75;
+ health = 90;
speed = 4f / 60f;
itemCapacity = 10;
}};
armoredConveyor = new ArmoredConveyor("armored-conveyor"){{
requirements(Category.distribution, with(Items.plastanium, 1, Items.thorium, 1, Items.metaglass, 1));
- health = 180;
+ health = 280;
speed = 0.08f;
displayedSpeed = 11f;
}};
@@ -2804,6 +2802,28 @@ public class Blocks{
ambientSoundVolume = 0.04f;
}};
+ largeCliffCrusher = new WallCrafter("large-cliff-crusher"){{
+ requirements(Category.production, with(Items.silicon, 80, Items.surgeAlloy, 15, Items.beryllium, 100, Items.tungsten, 50));
+ consumePower(30 / 60f);
+
+ drillTime = 48f;
+ size = 3;
+ attribute = Attribute.sand;
+ output = Items.sand;
+ fogRadius = 3;
+ ambientSound = Sounds.drill;
+ ambientSoundVolume = 0.08f;
+
+ consumeLiquid(Liquids.ozone, 1f / 60f);
+
+ itemConsumer = consumeItem(Items.tungsten).boost();
+ itemCapacity = 20;
+ boostItemUseTime = 60f * 10f;
+
+ //alternatively, boost using nitrogen:
+ //consumeLiquid(Liquids.nitrogen, 3f / 60f).boost();
+ }};
+
plasmaBore = new BeamDrill("plasma-bore"){{
requirements(Category.production, with(Items.beryllium, 40));
consumePower(0.15f);
@@ -2818,7 +2838,6 @@ public class Blocks{
consumeLiquid(Liquids.hydrogen, 0.25f / 60f).boost();
}};
- //TODO awful name
largePlasmaBore = new BeamDrill("large-plasma-bore"){{
requirements(Category.production, with(Items.silicon, 100, Items.oxide, 25, Items.beryllium, 100, Items.tungsten, 70));
consumePower(0.8f);
@@ -2856,8 +2875,8 @@ public class Blocks{
fogRadius = 4;
consumePower(160f / 60f);
- consumeLiquid(Liquids.water, 10f / 60f);
- consumeLiquid(Liquids.ozone, 3f / 60f).boost();
+ consumeLiquid(Liquids.water, 10f/60f);
+ consumeLiquid(Liquids.ozone, 3f / 60f).boost();
}};
eruptionDrill = new BurstDrill("eruption-drill"){{
@@ -2894,7 +2913,7 @@ public class Blocks{
//region storage
coreShard = new CoreBlock("core-shard"){{
- requirements(Category.effect, BuildVisibility.editorOnly, with(Items.copper, 1000, Items.lead, 800));
+ requirements(Category.effect, BuildVisibility.coreZoneOnly, with(Items.copper, 1000, Items.lead, 800));
alwaysUnlocked = true;
isFirstTier = true;
@@ -2902,6 +2921,7 @@ public class Blocks{
health = 1100;
itemCapacity = 4000;
size = 3;
+ buildCostMultiplier = 2f;
unitCapModifier = 8;
}};
@@ -3014,7 +3034,7 @@ public class Blocks{
reinforcedContainer = new StorageBlock("reinforced-container"){{
requirements(Category.effect, with(Items.tungsten, 30, Items.graphite, 40));
size = 2;
- itemCapacity = 80;
+ itemCapacity = 160;
scaledHealth = 120;
coreMerge = false;
}};
@@ -3428,7 +3448,7 @@ public class Blocks{
lightningLength = 10;
}}
);
-
+
shoot = new ShootBarrel(){{
barrels = new float[]{
-4, -1.25f, 0,
@@ -4020,7 +4040,7 @@ public class Blocks{
smokeEffect = Fx.shootBigSmoke;
ammoMultiplier = 1;
reloadMultiplier = 1f;
- pierceCap = 3;
+ pierceCap = 4;
pierce = true;
pierceBuilding = true;
hitColor = backColor = trailColor = Pal.tungstenShot;
@@ -4030,10 +4050,55 @@ public class Blocks{
hitEffect = despawnEffect = Fx.hitBulletColor;
rangeChange = 40f;
buildingDamageMultiplier = 0.3f;
+ }},
+ Items.carbide, new BasicBulletType(12f, 325f/0.75f){{
+ width = 15f;
+ height = 21f;
+ hitSize = 7f;
+ shootEffect = sfe;
+ smokeEffect = Fx.shootBigSmoke;
+ ammoMultiplier = 2;
+ reloadMultiplier = 0.2f;
+ hitColor = backColor = trailColor = Color.valueOf("ab8ec5");
+ frontColor = Color.white;
+ trailWidth = 2.2f;
+ trailLength = 11;
+ trailEffect = Fx.disperseTrail;
+ trailInterval = 2f;
+ hitEffect = despawnEffect = Fx.hitBulletColor;
+ rangeChange = 7f*8f;
+ buildingDamageMultiplier = 0.3f;
+ //targetBlocks = false;
+ //targetMissiles = false;
+ trailRotation = true;
+
+ fragBullets = 3;
+ fragRandomSpread = 0f;
+ fragSpread = 25f;
+ fragVelocityMin = 1f;
+
+ fragBullet = new BasicBulletType(8.1f, 227f){{
+ lifetime = 8f;
+ width = 11f;
+ height = 14f;
+ hitSize = 7f;
+ shootEffect = sfe;
+ ammoMultiplier = 1;
+ reloadMultiplier = 1f;
+ pierceCap = 2;
+ pierce = true;
+ pierceBuilding = true;
+ hitColor = backColor = trailColor = Color.valueOf("ab8ec5");
+ frontColor = Color.white;
+ trailWidth = 1.8f;
+ trailLength = 11;
+ hitEffect = despawnEffect = Fx.hitBulletColor;
+ buildingDamageMultiplier = 0.2f;
+ }};
}}
);
- coolantMultiplier = 6f;
+ coolantMultiplier = 15f;
shootSound = Sounds.shootAlt;
targetUnderBlocks = false;
@@ -4074,12 +4139,43 @@ public class Blocks{
trailLength = 3;
hitEffect = despawnEffect = Fx.hitSquaresColor;
buildingDamageMultiplier = 0.2f;
+ }},
+ Items.oxide, new BasicBulletType(8f, 120){{
+ knockback = 3f;
+ width = 25f;
+ hitSize = 7f;
+ height = 20f;
+ shootEffect = Fx.shootBigColor;
+ smokeEffect = Fx.shootSmokeSquareSparse;
+ ammoMultiplier = 2;
+ hitColor = backColor = trailColor = Color.valueOf("a0b380");
+ frontColor = Color.valueOf("e4ffd6");
+ trailWidth = 6f;
+ trailLength = 3;
+ hitEffect = despawnEffect = Fx.hitSquaresColor;
+ buildingDamageMultiplier = 0.2f;
+ }},
+ Items.silicon, new BasicBulletType(8f, 35){{
+ knockback = 3f;
+ width = 25f;
+ hitSize = 7f;
+ height = 20f;
+ homingPower = 0.045f;
+ shootEffect = Fx.shootBigColor;
+ smokeEffect = Fx.shootSmokeSquareSparse;
+ ammoMultiplier = 1;
+ hitColor = backColor = trailColor = Color.valueOf("858a9b");
+ frontColor = Color.valueOf("dae1ee");
+ trailWidth = 6f;
+ trailLength = 6;
+ hitEffect = despawnEffect = Fx.hitSquaresColor;
+ buildingDamageMultiplier = 0.2f;
}}
);
shoot = new ShootSpread(15, 4f);
- coolantMultiplier = 6f;
+ coolantMultiplier = 15f;
inaccuracy = 0.2f;
velocityRnd = 0.17f;
@@ -4165,7 +4261,6 @@ public class Blocks{
shootSound = Sounds.none;
loopSoundVolume = 1f;
- //TODO balance, set up, where is liquid/sec displayed? status effects maybe?
ammo(
Liquids.ozone, new ContinuousFlameBulletType(){{
damage = 60f;
@@ -4202,7 +4297,7 @@ public class Blocks{
requirements(Category.turret, with(Items.tungsten, 250, Items.silicon, 300, Items.thorium, 400));
ammo(
- //TODO 1 more ammo type, decide on base type
+ //TODO another ammo type
Items.thorium, new ArtilleryBulletType(2.5f, 350, "shell"){{
hitEffect = new MultiEffect(Fx.titanExplosion, Fx.titanSmoke);
despawnEffect = Fx.none;
@@ -4234,6 +4329,93 @@ public class Blocks{
shrinkX = 0.2f;
shrinkY = 0.1f;
buildingDamageMultiplier = 0.3f;
+ }},
+ Items.carbide, new ArtilleryBulletType(2.5f, 500, "shell"){{
+ hitEffect = new MultiEffect(Fx.titanExplosion, Fx.titanSmoke);
+ despawnEffect = Fx.none;
+ knockback = 3f;
+ lifetime = 140f;
+ height = 19f;
+ width = 17f;
+ splashDamageRadius = 55f;
+ splashDamage = 650f;
+ rangeChange = 10f*8f;
+ scaledSplashDamage = true;
+ backColor = hitColor = trailColor = Color.valueOf("ab8ec5");
+ frontColor = Color.white;
+ ammoMultiplier = 1f;
+ hitSound = Sounds.titanExplosion;
+
+ status = StatusEffects.blasted;
+
+ trailLength = 32;
+ trailWidth = 3.35f;
+ trailSinScl = 2.5f;
+ trailSinMag = 0.5f;
+ trailEffect = Fx.disperseTrail;
+ trailInterval = 2f;
+ despawnShake = 7f;
+
+ shootEffect = Fx.shootTitan;
+ smokeEffect = Fx.shootSmokeTitan;
+ trailRotation = true;
+
+ trailInterp = v -> Math.max(Mathf.slope(v), 0.8f);
+ shrinkX = 0.2f;
+ shrinkY = 0.1f;
+ buildingDamageMultiplier = 0.2f;
+ }},
+ Items.oxide, new ArtilleryBulletType(2.5f, 300, "shell"){{
+ hitEffect = new MultiEffect(Fx.titanExplosionLarge, Fx.titanSmokeLarge, Fx.smokeAoeCloud);
+ despawnEffect = Fx.none;
+ knockback = 2f;
+ lifetime = 190f;
+ height = 19f;
+ width = 17f;
+ reloadMultiplier = 0.8f;
+ splashDamageRadius = 110f;
+ rangeChange = 8f;
+ splashDamage = 300f;
+ scaledSplashDamage = true;
+ hitColor = backColor = trailColor = Color.valueOf("a0b380");
+ frontColor = Color.valueOf("e4ffd6");
+ ammoMultiplier = 1f;
+ hitSound = Sounds.titanExplosion;
+
+ status = StatusEffects.blasted;
+
+ trailLength = 32;
+ trailWidth = 3.35f;
+ trailSinScl = 2.5f;
+ trailSinMag = 0.5f;
+ trailEffect = Fx.vapor;
+ trailInterval = 3f;
+ despawnShake = 7f;
+
+ shootEffect = Fx.shootTitan;
+ smokeEffect = Fx.shootSmokeTitan;
+
+ trailInterp = v -> Math.max(Mathf.slope(v), 0.8f);
+ shrinkX = 0.2f;
+ shrinkY = 0.1f;
+ buildingDamageMultiplier = 0.25f;
+
+ fragBullets = 1;
+ fragBullet = new EmptyBulletType(){{
+ lifetime = 60f * 2.5f;
+ bulletInterval = 20f;
+ intervalBullet = new EmptyBulletType(){{
+ splashDamage = 30f;
+ collidesGround = true;
+ collidesAir = false;
+ collides = false;
+ hitEffect = Fx.none;
+ pierce = true;
+ instantDisappear = true;
+ splashDamageRadius = 90f;
+ buildingDamageMultiplier = 0.2f;
+ }};
+ }};
}}
);
@@ -4250,9 +4432,10 @@ public class Blocks{
newTargetInterval = 40f;
shootWarmupSpeed = 0.07f;
+ warmupMaintainTime = 120f;
coolant = consume(new ConsumeLiquid(Liquids.water, 30f / 60f));
- coolantMultiplier = 1.5f;
+ coolantMultiplier = 3.75f;
drawer = new DrawTurret("reinforced-"){{
parts.addAll(
@@ -4288,7 +4471,8 @@ public class Blocks{
disperse = new ItemTurret("disperse"){{
requirements(Category.turret, with(Items.thorium, 50, Items.oxide, 150, Items.silicon, 200, Items.beryllium, 350));
- ammo(Items.tungsten, new BasicBulletType(){{
+ ammo(
+ Items.tungsten, new BasicBulletType(){{
damage = 65;
speed = 8.5f;
width = height = 16;
@@ -4311,7 +4495,107 @@ public class Blocks{
trailEffect = Fx.disperseTrail;
hitEffect = despawnEffect = Fx.hitBulletColor;
- }});
+ }},
+ Items.thorium, new BasicBulletType(){{
+ damage = 90;
+ reloadMultiplier = 0.85f;
+ speed = 9.5f;
+ width = height = 16;
+ pierceCap = 2;
+ shrinkY = 0.3f;
+ backSprite = "large-bomb-back";
+ sprite = "mine-bullet";
+ velocityRnd = 0.5f;
+ collidesGround = false;
+ collidesTiles = false;
+ shootEffect = Fx.shootBig2;
+ smokeEffect = Fx.shootSmokeDisperse;
+ frontColor = Color.white;
+ backColor = trailColor = hitColor = Color.valueOf("e89dbd");
+ trailChance = 0.44f;
+ ammoMultiplier = 2f;
+
+ lifetime = 34f;
+ rotationOffset = 90f;
+ trailRotation = true;
+ trailEffect = Fx.disperseTrail;
+
+ hitEffect = despawnEffect = Fx.hitBulletColor;
+ }},
+ Items.silicon, new BasicBulletType(){{
+ damage = 35;
+ homingPower = 0.045f;
+
+ reloadMultiplier = 0.9f;
+ speed = 9f;
+ width = height = 16;
+ shrinkY = 0.3f;
+ backSprite = "large-bomb-back";
+ sprite = "mine-bullet";
+ velocityRnd = 0.11f;
+ collidesGround = false;
+ collidesTiles = false;
+ shootEffect = Fx.shootBig2;
+ smokeEffect = Fx.shootSmokeDisperse;
+ frontColor = Color.valueOf("dae1ee");
+ backColor = trailColor = hitColor = Color.valueOf("858a9b");
+ ammoMultiplier = 3f;
+
+ lifetime = 34f;
+ rotationOffset = 90f;
+ trailLength = 7;
+ //for chasing targets
+ extraRangeMargin = 32f;
+
+ hitEffect = despawnEffect = Fx.hitBulletColor;
+ }},
+
+ Items.surgeAlloy, new BasicBulletType(){{
+ reloadMultiplier = 0.5f;
+ damage = 65;
+ rangeChange = 8f * 3f;
+ lightning = 3;
+ lightningLength = 4;
+ lightningDamage = 18f;
+ lightningLengthRand = 3;
+ speed = 6f;
+ width = height = 16;
+ shrinkY = 0.3f;
+ backSprite = "large-bomb-back";
+ sprite = "mine-bullet";
+ velocityRnd = 0.11f;
+ collidesGround = false;
+ collidesTiles = false;
+ shootEffect = Fx.shootBig2;
+ smokeEffect = Fx.shootSmokeDisperse;
+ frontColor = Color.white;
+ backColor = trailColor = hitColor = Pal.surge;
+ trailChance = 0.44f;
+ ammoMultiplier = 3f;
+
+ lifetime = 34f;
+ rotationOffset = 90f;
+ trailRotation = true;
+ trailEffect = Fx.disperseTrail;
+
+ hitEffect = despawnEffect = Fx.hitBulletColor;
+
+ bulletInterval = 4f;
+
+ intervalBullet = new BulletType(){{
+ collidesGround = false;
+ collidesTiles = false;
+ lightningLengthRand = 4;
+ lightningLength = 2;
+ lightningCone = 30f;
+ lightningDamage = 20f;
+ lightning = 1;
+ hittable = collides = false;
+ instantDisappear = true;
+ hitEffect = despawnEffect = Fx.none;
+ }};
+ }}
+ );
reload = 9f;
shootY = 15f;
@@ -4363,13 +4647,13 @@ public class Blocks{
size = 4;
coolant = consume(new ConsumeLiquid(Liquids.water, 20f / 60f));
- coolantMultiplier = 2.5f;
+ coolantMultiplier = 6.25f;
- limitRange(5f);
+ limitRange(16f);
}};
afflict = new PowerTurret("afflict"){{
- requirements(Category.turret, with(Items.surgeAlloy, 100, Items.silicon, 200, Items.graphite, 250, Items.oxide, 40));
+ requirements(Category.turret, with(Items.surgeAlloy, 125, Items.silicon, 200, Items.graphite, 250, Items.oxide, 40));
shootType = new BasicBulletType(){{
shootEffect = new MultiEffect(Fx.shootTitan, new WaveEffect(){{
@@ -4494,7 +4778,7 @@ public class Blocks{
requirements(Category.turret, with(Items.silicon, 250, Items.graphite, 200, Items.oxide, 50, Items.carbide, 90));
shootType = new PointLaserBulletType(){{
- damage = 200f;
+ damage = 210f;
buildingDamageMultiplier = 0.3f;
hitColor = Color.valueOf("fda981");
}};
@@ -4531,6 +4815,7 @@ public class Blocks{
}});
}};
+ scaleDamageEfficiency = true;
shootSound = Sounds.none;
loopSoundVolume = 1f;
loopSound = Sounds.laserbeam;
@@ -4548,19 +4833,22 @@ public class Blocks{
range = 250f;
scaledHealth = 210;
- //TODO is this a good idea to begin with?
unitSort = UnitSorts.strongest;
consumeLiquid(Liquids.nitrogen, 6f / 60f);
+ consumePower(200f / 60f);
}};
scathe = new ItemTurret("scathe"){{
requirements(Category.turret, with(Items.silicon, 450, Items.graphite, 400, Items.tungsten, 500, Items.oxide, 100, Items.carbide, 200));
+ predictTarget = false;
+
ammo(
- Items.carbide, new BasicBulletType(0f, 1){{
+ Items.carbide, new BulletType(0f, 0f){{
shootEffect = Fx.shootBig;
- smokeEffect = Fx.shootSmokeMissile;
+ smokeEffect = Fx.shootSmokeMissileColor;
+ hitColor = Pal.redLight;
ammoMultiplier = 1f;
spawnUnit = new MissileUnitType("scathe-missile"){{
@@ -4641,6 +4929,233 @@ public class Blocks{
interval = 7f;
}});
}};
+ }},
+
+ Items.phaseFabric, new BulletType(0f, 0f){{
+ shootEffect = Fx.shootBig;
+ smokeEffect = Fx.shootSmokeMissileColor;
+ hitColor = Color.valueOf("ffd37f");
+ ammoMultiplier = 5f;
+ reloadMultiplier = 0.8f;
+
+ spawnUnit = new MissileUnitType("scathe-missile-phase"){{
+ speed = 4f;
+ maxRange = 6f;
+ lifetime = 60f * 6.1f;
+ outlineColor = Pal.darkOutline;
+ engineColor = trailColor = Color.valueOf("ffd37f");
+ engineLayer = Layer.effect;
+ engineSize = 3.1f;
+ engineOffset = 10f;
+ rotateSpeed = 0.2f;
+ trailLength = 18;
+ missileAccelTime = 50f;
+ lowAltitude = true;
+ loopSound = Sounds.missileTrail;
+ loopSoundVolume = 0.6f;
+ deathSound = Sounds.largeExplosion;
+ targetAir = false;
+ targetUnderBlocks = false;
+
+ parts.add(new ShapePart(){{
+ progress = PartProgress.constant(1f);
+ color = Pal.accent;
+ sides = 6;
+ radius = 3f;
+ rotateSpeed = 3f;
+ hollow = true;
+ layer = Layer.effect;
+ y = 1.8f;
+ }});
+
+ fogRadius = 6f;
+
+ health = 500;
+
+ weapons.add(new Weapon(){{
+ shootCone = 360f;
+ mirror = false;
+ reload = 1f;
+ deathExplosionEffect = Fx.massiveExplosion;
+ shootOnDeath = true;
+ shake = 10f;
+ bullet = new ExplosionBulletType(400f, 120f){{
+ hitColor = engineColor;
+ shootEffect = new MultiEffect(Fx.massiveExplosion, Fx.scatheExplosion, Fx.scatheLight, new WaveEffect(){{
+ lifetime = 10f;
+ strokeFrom = 4f;
+ sizeTo = 130f;
+ }});
+
+ collidesAir = false;
+ buildingDamageMultiplier = 0.1f;
+
+ ammoMultiplier = 1f;
+ fragLifeMin = 0.1f;
+ fragBullets = 7;
+ fragBullet = new ArtilleryBulletType(3.4f, 32){{
+ buildingDamageMultiplier = 0.2f;
+ drag = 0.02f;
+ hitEffect = Fx.massiveExplosion;
+ despawnEffect = Fx.scatheSlash;
+ knockback = 0.8f;
+ lifetime = 23f;
+ width = height = 18f;
+ collidesTiles = false;
+ splashDamageRadius = 56f;
+ splashDamage = 164f;
+ backColor = trailColor = hitColor = engineColor;
+ frontColor = Color.white;
+ smokeEffect = Fx.shootBigSmoke2;
+ despawnShake = 7f;
+ lightRadius = 30f;
+ lightColor = engineColor;
+ lightOpacity = 0.5f;
+
+ trailLength = 20;
+ trailWidth = 3.5f;
+ trailEffect = Fx.none;
+ }};
+ }};
+ }});
+
+ abilities.add(new MoveEffectAbility(){{
+ effect = Fx.missileTrailSmoke;
+ rotation = 180f;
+ y = -9f;
+ color = Color.grays(0.6f).lerp(Pal.redLight, 0.5f).a(0.4f);
+ interval = 7f;
+ }});
+
+ abilities.add(new ForceFieldAbility(90f, 0f, 2000f, 999999999f));
+
+ }};
+ }},
+
+ Items.surgeAlloy, new BulletType(0f, 0f){{
+ shootEffect = Fx.shootBig;
+ smokeEffect = Fx.shootSmokeMissileColor;
+ hitColor = Color.valueOf("f7e97e");
+
+ ammoMultiplier = 1f;
+ rangeChange = -8f*9f;
+ reloadMultiplier = 0.9f;
+
+ spawnUnit = new MissileUnitType("scathe-missile-surge"){{
+ speed = 4.4f;
+ maxRange = 6f;
+ lifetime = 60f * 1.4f;
+ outlineColor = Pal.darkOutline;
+ engineColor = trailColor = Color.valueOf("f7e97e");
+ engineLayer = Layer.effect;
+ engineSize = 3.1f;
+ engineOffset = 10f;
+ rotateSpeed = 0.25f;
+ trailLength = 18;
+ missileAccelTime = 30f;
+ lowAltitude = true;
+ loopSound = Sounds.missileTrail;
+ loopSoundVolume = 0.6f;
+ deathSound = Sounds.largeExplosion;
+ targetAir = false;
+ targetUnderBlocks = false;
+
+ fogRadius = 6f;
+
+ health = 400;
+
+ weapons.add(new Weapon(){{
+ shootCone = 360f;
+ rotate = true;
+ rotationLimit = rotateSpeed = 0f;
+ reload = 1f;
+ deathExplosionEffect = Fx.massiveExplosion;
+ shootOnDeath = true;
+ shake = 10f;
+ bullet = new ExplosionBulletType(300f, 40f){{
+ hitColor = engineColor;
+ shootEffect = new MultiEffect(Fx.massiveExplosion, Fx.scatheExplosionSmall);
+
+ collidesAir = false;
+ buildingDamageMultiplier = 0.1f;
+
+ ammoMultiplier = 1f;
+ fragLifeMin = 0.1f;
+ fragBullets = 5;
+ fragRandomSpread = 0f;
+ fragSpread = 30f;
+ fragBullet = new BulletType(){{
+ shootEffect = Fx.shootBig;
+ smokeEffect = Fx.shootSmokeMissileColor;
+ hitColor = engineColor;
+ ammoMultiplier = 1f;
+
+ spawnUnit = new MissileUnitType("scathe-missile-surge-split"){{
+ speed = 4.8f;
+ maxRange = 6f;
+ lifetime = 60f * 3.5f;
+ outlineColor = Pal.darkOutline;
+ engineColor = trailColor = Color.valueOf("f7e97e");
+ engineLayer = Layer.effect;
+ engineSize = 2.2f;
+ engineOffset = 8f;
+ rotateSpeed = 1.4f;
+ trailLength = 12;
+ lowAltitude = true;
+ loopSound = Sounds.missileTrail;
+ loopSoundVolume = 0.6f;
+ deathSound = Sounds.largeExplosion;
+ targetAir = false;
+ targetUnderBlocks = false;
+
+ fogRadius = 6f;
+
+ health = 100;
+
+ weapons.add(new Weapon(){{
+ shootCone = 360f;
+ mirror = false;
+ reload = 1f;
+ deathExplosionEffect = Fx.massiveExplosion;
+ shootOnDeath = true;
+ shake = 10f;
+ bullet = new ExplosionBulletType(360f, 35f){{
+ lightning = 6;
+ lightningDamage = 35f;
+ lightningLength = 8;
+
+ hitColor = engineColor;
+ shootEffect = new MultiEffect(Fx.massiveExplosion, Fx.scatheExplosionSmall, Fx.scatheLightSmall, new WaveEffect(){{
+ lifetime = 10f;
+ strokeFrom = 4f;
+ sizeTo = 100f;
+ }});
+
+ collidesAir = false;
+ buildingDamageMultiplier = 0.1f;
+ }};
+ }});
+
+ abilities.add(new MoveEffectAbility(){{
+ effect = Fx.missileTrailSmokeSmall;
+ rotation = 180f;
+ y = -9f;
+ color = Color.grays(0.6f).lerp(Color.valueOf("f7e97e"), 0.5f).a(0.4f);
+ interval = 5f;
+ }});
+ }};
+ }};
+ }};
+ }});
+
+ abilities.add(new MoveEffectAbility(){{
+ effect = Fx.missileTrailSmoke;
+ rotation = 180f;
+ y = -9f;
+ color = Color.grays(0.6f).lerp(Color.valueOf("f7e97e"), 0.5f).a(0.4f);
+ interval = 7f;
+ }});
+ }};
}}
);
@@ -4690,7 +5205,7 @@ public class Blocks{
recoil = 0.5f;
fogRadiusMultiplier = 0.4f;
- coolantMultiplier = 6f;
+ coolantMultiplier = 15f;
shootSound = Sounds.missileLaunch;
minWarmup = 0.94f;
@@ -4721,7 +5236,6 @@ public class Blocks{
requirements(Category.turret, with(Items.oxide, 200, Items.surgeAlloy, 400, Items.silicon, 800, Items.carbide, 500, Items.phaseFabric, 300));
ammo(
- //this is really lazy
Items.surgeAlloy, new BasicBulletType(7f, 250){{
sprite = "large-orb";
width = 17f;
@@ -4794,7 +5308,7 @@ public class Blocks{
shootSound = Sounds.shootSmite;
minWarmup = 0.99f;
- coolantMultiplier = 6f;
+ coolantMultiplier = 15f;
var haloProgress = PartProgress.warmup.delay(0.5f);
float haloY = -15f, haloRotSpeed = 1f;
@@ -4973,10 +5487,11 @@ public class Blocks{
outlineColor = Pal.darkOutline;
size = 5;
envEnabled |= Env.space;
- warmupMaintainTime = 30f;
+ warmupMaintainTime = 120f;
reload = 100f;
recoil = 2f;
range = 300;
+ trackingRange = range * 1.4f;
shootCone = 30f;
scaledHealth = 350;
rotateSpeed = 1.5f;
@@ -5299,7 +5814,7 @@ public class Blocks{
velocityRnd = 0.15f;
heatRequirement = 90f;
maxHeatEfficiency = 2f;
- warmupMaintainTime = 30f;
+ warmupMaintainTime = 120f;
consumePower(10f);
shoot = new ShootSummon(0f, 0f, circleRad, 48f);
@@ -5313,6 +5828,7 @@ public class Blocks{
envEnabled |= Env.space;
reload = 9f;
range = 370;
+ trackingRange = range * 1.4f;
shootCone = 100f;
scaledHealth = 370;
rotateSpeed = 2f;
@@ -5349,7 +5865,7 @@ public class Blocks{
requirements(Category.units, with(Items.copper, 150, Items.lead, 130, Items.metaglass, 120));
plans = Seq.with(
new UnitPlan(UnitTypes.risso, 60f * 45f, with(Items.silicon, 20, Items.metaglass, 35)),
- new UnitPlan(UnitTypes.retusa, 60f * 50f, with(Items.silicon, 15, Items.metaglass, 25, Items.titanium, 20))
+ new UnitPlan(UnitTypes.retusa, 60f * 35f, with(Items.silicon, 15, Items.titanium, 20))
);
size = 3;
consumePower(1.2f);
@@ -5809,6 +6325,7 @@ public class Blocks{
itemCapacity = 0;
alwaysUnlocked = true;
ambientSound = Sounds.none;
+ allDatabaseTabs = true;
}};
//TODO move
@@ -5939,7 +6456,7 @@ public class Blocks{
}};
worldProcessor = new LogicBlock("world-processor"){{
- requirements(Category.logic, BuildVisibility.editorOnly, with());
+ requirements(Category.logic, BuildVisibility.worldProcessorOnly, with());
canOverdrive = false;
targetable = false;
@@ -5952,23 +6469,23 @@ public class Blocks{
}};
worldCell = new MemoryBlock("world-cell"){{
- requirements(Category.logic, BuildVisibility.editorOnly, with());
-
+ requirements(Category.logic, BuildVisibility.worldProcessorOnly, with());
+
targetable = false;
privileged = true;
- memoryCapacity = 128;
+ memoryCapacity = 512;
forceDark = true;
}};
worldMessage = new MessageBlock("world-message"){{
- requirements(Category.logic, BuildVisibility.editorOnly, with());
-
+ requirements(Category.logic, BuildVisibility.worldProcessorOnly, with());
+
targetable = false;
privileged = true;
}};
worldSwitch = new SwitchBlock("world-switch"){{
- requirements(Category.logic, BuildVisibility.editorOnly, with());
+ requirements(Category.logic, BuildVisibility.worldProcessorOnly, with());
targetable = false;
privileged = true;
diff --git a/core/src/mindustry/content/Bullets.java b/core/src/mindustry/content/Bullets.java
index ea10110ae8..4536a3b826 100644
--- a/core/src/mindustry/content/Bullets.java
+++ b/core/src/mindustry/content/Bullets.java
@@ -10,7 +10,7 @@ import mindustry.entities.bullet.*;
public class Bullets{
public static BulletType
- placeholder, spaceLiquid, damageLightning, damageLightningGround, fireball;
+ placeholder, spaceLiquid, damageLightning, damageLightningGround, damageLightningAir, fireball;
public static void load(){
@@ -37,6 +37,10 @@ public class Bullets{
damageLightningGround = damageLightning.copy();
damageLightningGround.collidesAir = false;
+ damageLightningAir = damageLightning.copy();
+ damageLightningAir.collidesGround = false;
+ damageLightningAir.collidesTiles = false;
+
fireball = new FireBulletType(1f, 4){{
hittable = false;
}};
diff --git a/core/src/mindustry/content/ErekirTechTree.java b/core/src/mindustry/content/ErekirTechTree.java
index 6c4571a43a..680c0194dd 100644
--- a/core/src/mindustry/content/ErekirTechTree.java
+++ b/core/src/mindustry/content/ErekirTechTree.java
@@ -137,6 +137,10 @@ public class ErekirTechTree{
node(eruptionDrill, Seq.with(new OnSector(stronghold)), () -> {
});
+
+ node(largeCliffCrusher, Seq.with(new OnSector(stronghold)), () -> {
+
+ });
});
});
});
@@ -220,7 +224,9 @@ public class ErekirTechTree{
});
node(heatRouter, () -> {
+ node(smallHeatRedirector, () -> {
+ });
});
});
});
diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java
index 1e8579f4b7..16e42a0fbf 100644
--- a/core/src/mindustry/content/Fx.java
+++ b/core/src/mindustry/content/Fx.java
@@ -28,7 +28,7 @@ public class Fx{
public static final Effect
none = new Effect(0, 0f, e -> {}),
-
+
blockCrash = new Effect(90f, e -> {
if(!(e.data instanceof Block block)) return;
@@ -445,6 +445,20 @@ public class Fx{
}
}),
+ titanExplosionLarge = new Effect(45f, 220f, e -> {
+ color(e.color);
+ stroke(e.fout() * 3f);
+ float circleRad = 6f + e.finpow() * 110f;
+ Lines.circle(e.x, e.y, circleRad);
+
+ rand.setSeed(e.id);
+ for(int i = 0; i < 21; i++){
+ float angle = rand.random(360f);
+ float lenRand = rand.random(0.5f, 1f);
+ Lines.lineAngle(e.x, e.y, angle, e.foutpow() * 50f * rand.random(1f, 0.6f) + 2f, e.finpow() * 100f * lenRand + 6f);
+ }
+ }),
+
titanSmoke = new Effect(300f, 300f, b -> {
float intensity = 3f;
@@ -465,6 +479,34 @@ public class Fx{
}
}),
+ titanSmokeLarge = new Effect(400f, 400f, b -> {
+ float intensity = 4f;
+
+ color(b.color, 0.65f);
+ for(int i = 0; i < 4; i++){
+ rand.setSeed(b.id*2 + i);
+ float lenScl = rand.random(0.5f, 1f);
+ int fi = i;
+ b.scaled(b.lifetime * lenScl, e -> {
+ randLenVectors(e.id + fi - 1, e.fin(Interp.pow10Out), (int)(2.9f * intensity), 26f * intensity, (x, y, in, out) -> {
+ float fout = e.fout(Interp.pow5Out) * rand.random(0.5f, 1f);
+ float rad = fout * ((2f + intensity) * 2.35f);
+
+ Fill.circle(e.x + x, e.y + y, rad);
+ Drawf.light(e.x + x, e.y + y, rad * 2.5f, b.color, 0.5f);
+ });
+ });
+ }
+ }),
+
+ smokeAoeCloud = new Effect(60f * 3f, 250f, e -> {
+ color(e.color, 0.65f);
+
+ randLenVectors(e.id, 80, 90f, (x, y) -> {
+ Fill.circle(e.x + x, e.y + y, 6f * Mathf.clamp(e.fin() / 0.1f) * Mathf.clamp(e.fout() / 0.1f));
+ });
+ }),
+
missileTrailSmoke = new Effect(180f, 300f, b -> {
float intensity = 2f;
@@ -485,6 +527,26 @@ public class Fx{
}
}).layer(Layer.bullet - 1f),
+ missileTrailSmokeSmall = new Effect(120f, 200f, b -> {
+ float intensity = 1.3f;
+
+ color(b.color, 0.7f);
+ for(int i = 0; i < 3; i++){
+ rand.setSeed(b.id*2 + i);
+ float lenScl = rand.random(0.5f, 1f);
+ int fi = i;
+ b.scaled(b.lifetime * lenScl, e -> {
+ randLenVectors(e.id + fi - 1, e.fin(Interp.pow10Out), (int)(2.9f * intensity), 13f * intensity, (x, y, in, out) -> {
+ float fout = e.fout(Interp.pow5Out) * rand.random(0.5f, 1f);
+ float rad = fout * ((2f + intensity) * 2.35f);
+
+ Fill.circle(e.x + x, e.y + y, rad);
+ Drawf.light(e.x + x, e.y + y, rad * 2.5f, b.color, 0.5f);
+ });
+ });
+ }
+ }).layer(Layer.bullet - 1f),
+
neoplasmSplat = new Effect(400f, 300f, b -> {
float intensity = 3f;
@@ -523,6 +585,24 @@ public class Fx{
}
}),
+ scatheExplosionSmall = new Effect(40f, 160f, e -> {
+ color(e.color);
+ stroke(e.fout() * 4f);
+ float circleRad = 6f + e.finpow() * 40f;
+ Lines.circle(e.x, e.y, circleRad);
+
+ rand.setSeed(e.id);
+ for(int i = 0; i < 16; i++){
+ float angle = rand.random(360f);
+ float lenRand = rand.random(0.5f, 1f);
+ Tmp.v1.trns(angle, circleRad);
+
+ for(int s : Mathf.signs){
+ Drawf.tri(e.x + Tmp.v1.x, e.y + Tmp.v1.y, e.foutpow() * 30f, e.fout() * 25f * lenRand + 6f, angle + 90f + s * 90f);
+ }
+ }
+ }),
+
scatheLight = new Effect(60f, 160f, e -> {
float circleRad = 6f + e.finpow() * 60f;
@@ -530,6 +610,13 @@ public class Fx{
Fill.circle(e.x, e.y, circleRad);
}).layer(Layer.bullet + 2f),
+ scatheLightSmall = new Effect(60f, 160f, e -> {
+ float circleRad = 6f + e.finpow() * 40f;
+
+ color(e.color, e.foutpow());
+ Fill.circle(e.x, e.y, circleRad);
+ }).layer(Layer.bullet + 2f),
+
scatheSlash = new Effect(40f, 160f, e -> {
Draw.color(e.color);
for(int s : Mathf.signs){
@@ -761,7 +848,7 @@ public class Fx{
Fill.circle(e.x + x, e.y + y, e.fout() * 2f);
});
}),
-
+
hitLaserBlast = new Effect(12, e -> {
color(e.color);
stroke(e.fout() * 1.5f);
@@ -1114,7 +1201,7 @@ public class Fx{
stroke(2f * e.fout());
Lines.circle(e.x, e.y, 5f * e.fout());
}),
-
+
forceShrink = new Effect(20, e -> {
color(e.color, e.fout());
if(renderer.animateShields){
@@ -1703,6 +1790,18 @@ public class Fx{
}
}),
+ shootSmokeMissileColor = new Effect(130f, 300f, e -> {
+ color(e.color);
+ alpha(0.5f);
+ rand.setSeed(e.id);
+ for(int i = 0; i < 35; i++){
+ v.trns(e.rotation + 180f + rand.range(21f), rand.random(e.finpow() * 90f)).add(rand.range(3f), rand.range(3f));
+ e.scaled(e.lifetime * rand.random(0.2f, 1f), b -> {
+ Fill.circle(e.x + v.x, e.y + v.y, b.fout() * 9f + 0.3f);
+ });
+ }
+ }),
+
regenParticle = new Effect(100f, e -> {
color(Pal.regen);
diff --git a/core/src/mindustry/content/Items.java b/core/src/mindustry/content/Items.java
index cfb8bb14d6..00cc3cc5d5 100644
--- a/core/src/mindustry/content/Items.java
+++ b/core/src/mindustry/content/Items.java
@@ -60,7 +60,7 @@ public class Items{
}};
scrap = new Item("scrap", Color.valueOf("777777")){{
-
+ cost = 0.5f;
}};
silicon = new Item("silicon", Color.valueOf("53565c")){{
diff --git a/core/src/mindustry/content/Planets.java b/core/src/mindustry/content/Planets.java
index c5e4531e55..338e25cadc 100644
--- a/core/src/mindustry/content/Planets.java
+++ b/core/src/mindustry/content/Planets.java
@@ -65,7 +65,6 @@ public class Planets{
clearSectorOnLose = true;
defaultCore = Blocks.coreBastion;
iconColor = Color.valueOf("ff9266");
- hiddenItems.addAll(Items.serpuloItems).removeAll(Items.erekirItems);
enemyBuildSpeedMultiplier = 0.4f;
//TODO disallowed for now
@@ -86,6 +85,8 @@ public class Planets{
r.coreDestroyClear = true;
r.onlyDepositCore = true;
};
+ campaignRuleDefaults.fog = true;
+ campaignRuleDefaults.showSpawns = true;
unlockedOnLand.add(Blocks.coreBastion);
}};
@@ -144,6 +145,7 @@ public class Planets{
r.waveTeam = Team.crux;
r.placeRangeCheck = false;
r.showSpawns = false;
+ r.coreDestroyClear = true;
};
iconColor = Color.valueOf("7d4dff");
atmosphereColor = Color.valueOf("3c1b8f");
@@ -152,7 +154,6 @@ public class Planets{
startSector = 15;
alwaysUnlocked = true;
landCloudColor = Pal.spore.cpy().a(0.5f);
- hiddenItems.addAll(Items.erekirItems).removeAll(Items.serpuloItems);
}};
verilus = makeAsteroid("verlius", sun, Blocks.stoneWall, Blocks.iceWall, 0.5f, 12, 2f, gen -> {
diff --git a/core/src/mindustry/content/SectorPresets.java b/core/src/mindustry/content/SectorPresets.java
index eb537f1164..af9a2bc53e 100644
--- a/core/src/mindustry/content/SectorPresets.java
+++ b/core/src/mindustry/content/SectorPresets.java
@@ -7,10 +7,12 @@ import static mindustry.content.Planets.*;
public class SectorPresets{
public static SectorPreset
groundZero,
- craters, biomassFacility, frozenForest, ruinousShores, windsweptIslands, stainedMountains, tarFields,
- fungalPass, extractionOutpost, saltFlats, overgrowth,
+ craters, biomassFacility, taintedWoods, frozenForest, ruinousShores, facility32m, windsweptIslands, stainedMountains, tarFields,
+ frontier, fungalPass, infestedCanyons, atolls, mycelialBastion, extractionOutpost, saltFlats, testingGrounds, overgrowth, //polarAerodrome,
impact0078, desolateRift, nuclearComplex, planetaryTerminal,
- coastline, navalFortress,
+ coastline, navalFortress, weatheredChannels, seaPort,
+
+ geothermalStronghold, cruxscape,
onset, aegis, lake, intersect, basin, atlas, split, marsh, peaks, ravine, caldera,
stronghold, crevice, siege, crossroads, karst, origin;
@@ -32,6 +34,11 @@ public class SectorPresets{
difficulty = 5;
}};
+ testingGrounds = new SectorPreset("testingGrounds", serpulo, 3){{
+ difficulty = 7;
+ captureWave = 33;
+ }};
+
frozenForest = new SectorPreset("frozenForest", serpulo, 86){{
captureWave = 15;
difficulty = 2;
@@ -42,6 +49,11 @@ public class SectorPresets{
difficulty = 3;
}};
+ taintedWoods = new SectorPreset("taintedWoods", serpulo, 221){{
+ captureWave = 33;
+ difficulty = 5;
+ }};
+
craters = new SectorPreset("craters", serpulo, 18){{
captureWave = 20;
difficulty = 2;
@@ -52,6 +64,15 @@ public class SectorPresets{
difficulty = 3;
}};
+ seaPort = new SectorPreset("seaPort", serpulo, 47){{
+ difficulty = 4;
+ }};
+
+ facility32m = new SectorPreset("facility32m", serpulo, 64){{
+ captureWave = 25;
+ difficulty = 4;
+ }};
+
windsweptIslands = new SectorPreset("windsweptIslands", serpulo, 246){{
captureWave = 30;
difficulty = 4;
@@ -66,19 +87,45 @@ public class SectorPresets{
difficulty = 5;
}};
+ //TODO: removed for now
+ //polarAerodrome = new SectorPreset("polarAerodrome", serpulo, 68){{
+ // difficulty = 7;
+ //}};
+
coastline = new SectorPreset("coastline", serpulo, 108){{
captureWave = 30;
difficulty = 5;
}};
- navalFortress = new SectorPreset("navalFortress", serpulo, 216){{
+ weatheredChannels = new SectorPreset("weatheredChannels", serpulo, 39){{
+ captureWave = 40;
difficulty = 9;
}};
+ navalFortress = new SectorPreset("navalFortress", serpulo, 216){{
+ difficulty = 8;
+ }};
+
+ frontier = new SectorPreset("frontier", serpulo, 203){{
+ difficulty = 4;
+ }};
+
fungalPass = new SectorPreset("fungalPass", serpulo, 21){{
difficulty = 4;
}};
+ infestedCanyons = new SectorPreset("infestedCanyons", serpulo, 210){{
+ difficulty = 4;
+ }};
+
+ atolls = new SectorPreset("atolls", serpulo, 1){{
+ difficulty = 7;
+ }};
+
+ mycelialBastion = new SectorPreset("mycelialBastion", serpulo, 260){{
+ difficulty = 8;
+ }};
+
overgrowth = new SectorPreset("overgrowth", serpulo, 134){{
difficulty = 5;
}};
@@ -108,6 +155,14 @@ public class SectorPresets{
isLastSector = true;
}};
+ geothermalStronghold = new SectorPreset("geothermalStronghold", serpulo, 264){{
+ difficulty = 10;
+ }};
+
+ cruxscape = new SectorPreset("cruxscape", serpulo, 54){{
+ difficulty = 10;
+ }};
+
//endregion
//region erekir
diff --git a/core/src/mindustry/content/SerpuloTechTree.java b/core/src/mindustry/content/SerpuloTechTree.java
index 6b7ab42668..6da887240c 100644
--- a/core/src/mindustry/content/SerpuloTechTree.java
+++ b/core/src/mindustry/content/SerpuloTechTree.java
@@ -2,6 +2,7 @@ package mindustry.content;
import arc.struct.*;
import mindustry.game.Objectives.*;
+import mindustry.type.*;
import static mindustry.content.Blocks.*;
import static mindustry.content.SectorPresets.craters;
@@ -122,7 +123,7 @@ public class SerpuloTechTree{
});
node(pyratiteMixer, () -> {
- node(blastMixer, () -> {
+ node(blastMixer, Seq.with(new SectorComplete(facility32m)), () -> {
});
});
@@ -138,7 +139,7 @@ public class SerpuloTechTree{
});
});
- node(plastaniumCompressor, Seq.with(new SectorComplete(windsweptIslands)), () -> {
+ node(plastaniumCompressor, Seq.with(new SectorComplete(windsweptIslands), new OnSector(tarFields)), () -> {
node(phaseWeaver, Seq.with(new SectorComplete(tarFields)), () -> {
});
@@ -261,12 +262,21 @@ public class SerpuloTechTree{
node(duo, () -> {
node(copperWall, () -> {
node(copperWallLarge, () -> {
+ node(scrapWall, () -> {
+ node(scrapWallLarge, () -> {
+ node(scrapWallHuge, () -> {
+ node(scrapWallGigantic);
+ });
+ });
+ });
+
node(titaniumWall, () -> {
node(titaniumWallLarge);
node(door, () -> {
node(doorLarge);
});
+
node(plastaniumWall, () -> {
node(plastaniumWallLarge, () -> {
@@ -359,11 +369,12 @@ public class SerpuloTechTree{
});
});
- node(crawler, () -> {
+ //override research requirements to have graphite, not coal
+ node(crawler, ItemStack.with(Items.silicon, 400, Items.graphite, 400), () -> {
node(atrax, () -> {
node(spiroct, () -> {
node(arkyid, () -> {
- node(toxopid, () -> {
+ node(toxopid, Seq.with(new SectorComplete(mycelialBastion)), () -> {
});
});
@@ -397,7 +408,7 @@ public class SerpuloTechTree{
});
});
- node(navalFactory, Seq.with(new SectorComplete(ruinousShores)), () -> {
+ node(navalFactory, Seq.with(new OnSector(windsweptIslands)), () -> {
node(risso, () -> {
node(minke, () -> {
node(bryde, () -> {
@@ -425,8 +436,8 @@ public class SerpuloTechTree{
});
node(additiveReconstructor, Seq.with(new SectorComplete(biomassFacility)), () -> {
- node(multiplicativeReconstructor, () -> {
- node(exponentialReconstructor, Seq.with(new SectorComplete(overgrowth)), () -> {
+ node(multiplicativeReconstructor, Seq.with(new SectorComplete(overgrowth)), () -> {
+ node(exponentialReconstructor, () -> {
node(tetrativeReconstructor, () -> {
});
@@ -446,6 +457,16 @@ public class SerpuloTechTree{
new Research(mender),
new Research(combustionGenerator)
), () -> {
+ node(frontier, Seq.with(
+ new Research(groundFactory),
+ new Research(airFactory),
+ new Research(thermalGenerator),
+ new Research(dagger),
+ new Research(mono)
+ ), () -> {
+
+ });
+
node(ruinousShores, Seq.with(
new SectorComplete(craters),
new Research(graphitePress),
@@ -459,6 +480,18 @@ public class SerpuloTechTree{
new Research(siliconSmelter),
new Research(steamGenerator)
), () -> {
+ node(seaPort, Seq.with(
+ new SectorComplete(biomassFacility),
+ new Research(navalFactory),
+ new Research(risso),
+ new Research(retusa),
+ new Research(steamGenerator),
+ new Research(cultivator),
+ new Research(coalCentrifuge)
+ ), () -> {
+
+ });
+
node(tarFields, Seq.with(
new SectorComplete(windsweptIslands),
new Research(coalCentrifuge),
@@ -487,28 +520,73 @@ public class SerpuloTechTree{
new Research(risso),
new Research(minke),
new Research(bryde),
+ new Research(sei),
+ new Research(omura),
new Research(spectre),
new Research(launchPad),
new Research(massDriver),
new Research(impactReactor),
new Research(additiveReconstructor),
- new Research(exponentialReconstructor)
+ new Research(exponentialReconstructor),
+ new Research(tetrativeReconstructor)
), () -> {
+ node(geothermalStronghold, Seq.with(
+ new Research(omura),
+ new Research(navanax),
+ new Research(eclipse),
+ new Research(oct),
+ new Research(reign),
+ new Research(corvus),
+ new Research(toxopid)
+ ), () -> {
+ });
+
+ node(cruxscape, Seq.with(
+ new Research(omura),
+ new Research(navanax),
+ new Research(eclipse),
+ new Research(oct),
+ new Research(reign),
+ new Research(corvus),
+ new Research(toxopid)
+ ), () -> {
+
+ });
});
});
});
});
- node(extractionOutpost, Seq.with(
- new SectorComplete(stainedMountains),
- new SectorComplete(windsweptIslands),
- new Research(groundFactory),
- new Research(nova),
- new Research(airFactory),
- new Research(mono)
+ node(facility32m, Seq.with(
+ new Research(pneumaticDrill),
+ new SectorComplete(stainedMountains)
), () -> {
+ node(extractionOutpost, Seq.with(
+ new SectorComplete(windsweptIslands),
+ new SectorComplete(facility32m),
+ new Research(groundFactory),
+ new Research(nova),
+ new Research(airFactory),
+ new Research(mono)
+ ), () -> {
+ //TODO: removed for now
+ /*node(polarAerodrome, Seq.with(
+ new SectorComplete(fungalPass),
+ new SectorComplete(desolateRift),
+ new SectorComplete(overgrowth),
+ new Research(multiplicativeReconstructor),
+ new Research(zenith),
+ new Research(swarmer),
+ new Research(cyclone),
+ new Research(blastDrill),
+ new Research(blastDrill),
+ new Research(massDriver)
+ ), () -> {
+ });
+ */
+ });
});
node(saltFlats, Seq.with(
@@ -518,21 +596,41 @@ public class SerpuloTechTree{
new Research(airFactory),
new Research(door)
), () -> {
+ node(testingGrounds, Seq.with(
+ new Research(cryofluidMixer),
+ new Research(Liquids.cryofluid),
+ new Research(waterExtractor),
+ new Research(ripple)
+ ), () -> {
+
+ });
+
node(coastline, Seq.with(
new SectorComplete(windsweptIslands),
new SectorComplete(saltFlats),
new Research(navalFactory),
new Research(payloadConveyor)
), () -> {
+
node(navalFortress, Seq.with(
new SectorComplete(coastline),
new SectorComplete(extractionOutpost),
+ new Research(coreNucleus),
+ new Research(massDriver),
new Research(oxynoe),
new Research(minke),
+ new Research(bryde),
new Research(cyclone),
new Research(ripple)
), () -> {
+ node(weatheredChannels, Seq.with(
+ new SectorComplete(impact0078),
+ new Research(bryde),
+ new Research(surgeSmelter),
+ new Research(overdriveProjector)
+ ), () -> {
+ });
});
});
});
@@ -548,7 +646,22 @@ public class SerpuloTechTree{
new Research(UnitTypes.mace),
new Research(UnitTypes.flare)
), () -> {
+ node(mycelialBastion, Seq.with(
+ new Research(atrax),
+ new Research(spiroct),
+ new Research(multiplicativeReconstructor),
+ new Research(exponentialReconstructor)
+ ), () -> {
+ });
+
+ node(atolls, Seq.with(
+ new SectorComplete(windsweptIslands),
+ new Research(multiplicativeReconstructor),
+ new Research(mega)
+ ), () -> {
+
+ });
});
});
@@ -559,6 +672,14 @@ public class SerpuloTechTree{
new Research(scatter),
new Research(graphitePress)
), () -> {
+ node(taintedWoods, Seq.with(
+ new SectorComplete(biomassFacility),
+ new Research(Items.sporePod),
+ new Research(wave)
+ ), () -> {
+
+ });
+
node(stainedMountains, Seq.with(
new SectorComplete(biomassFacility),
new Research(pneumaticDrill),
@@ -569,6 +690,16 @@ public class SerpuloTechTree{
new Research(groundFactory),
new Research(door)
), () -> {
+ node(infestedCanyons, Seq.with(
+ new SectorComplete(fungalPass),
+ new Research(navalFactory),
+ new Research(risso),
+ new Research(minke),
+ new Research(additiveReconstructor)
+ ), () -> {
+
+ });
+
node(nuclearComplex, Seq.with(
new SectorComplete(fungalPass),
new Research(thermalGenerator),
diff --git a/core/src/mindustry/content/StatusEffects.java b/core/src/mindustry/content/StatusEffects.java
index ff3dcf43df..1ccaabc80f 100644
--- a/core/src/mindustry/content/StatusEffects.java
+++ b/core/src/mindustry/content/StatusEffects.java
@@ -61,12 +61,12 @@ public class StatusEffects{
color = Pal.lightishGray;
speedMultiplier = 0.4f;
- init(() -> opposite(fast));
+ init(() -> opposite(fast));
}};
fast = new StatusEffect("fast"){{
- color = Pal.boostTo;
- speedMultiplier = 1.6f;
+ color = Pal.boostTo;
+ speedMultiplier = 1.6f;
init(() -> opposite(slow));
}};
@@ -89,7 +89,7 @@ public class StatusEffects{
opposite(burning, melting);
});
}};
-
+
muddy = new StatusEffect("muddy"){{
color = Color.valueOf("46382a");
speedMultiplier = 0.94f;
diff --git a/core/src/mindustry/content/TechTree.java b/core/src/mindustry/content/TechTree.java
index b782b8204d..c4e05638b0 100644
--- a/core/src/mindustry/content/TechTree.java
+++ b/core/src/mindustry/content/TechTree.java
@@ -139,6 +139,16 @@ public class TechTree{
}
}
+ /** Adds the specified database tab to all the content in this tree. */
+ public void addDatabaseTab(UnlockableContent tab){
+ each(node -> node.content.databaseTabs.add(tab));
+ }
+
+ /** Adds the specified planet to the shownPlanets of all the content in this tree. */
+ public void addPlanet(Planet planet){
+ each(node -> node.content.shownPlanets.add(planet));
+ }
+
public Drawable icon(){
return icon == null ? new TextureRegionDrawable(content.uiIcon) : icon;
}
diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java
index ab6b1942f2..61e0e64c84 100644
--- a/core/src/mindustry/content/UnitTypes.java
+++ b/core/src/mindustry/content/UnitTypes.java
@@ -255,7 +255,7 @@ public class UnitTypes{
reign = new UnitType("reign"){{
speed = 0.4f;
- hitSize = 26f;
+ hitSize = 30f;
rotateSpeed = 1.65f;
health = 24000;
armor = 18f;
@@ -322,7 +322,7 @@ public class UnitTypes{
speed = 0.55f;
hitSize = 8f;
health = 120f;
- buildSpeed = 0.35f;
+ buildSpeed = 0.3f;
armor = 1f;
abilities.add(new RepairFieldAbility(10f, 60f * 4, 60f));
@@ -617,6 +617,7 @@ public class UnitTypes{
weapons.add(new Weapon(){{
shootOnDeath = true;
+ targetUnderBlocks = false;
reload = 24f;
shootCone = 180f;
ejectEffect = Fx.none;
@@ -1011,7 +1012,7 @@ public class UnitTypes{
accel = 0.08f;
drag = 0.016f;
flying = true;
- hitSize = 10f;
+ hitSize = 11f;
targetAir = false;
engineOffset = 7.8f;
range = 140f;
@@ -1041,6 +1042,7 @@ public class UnitTypes{
status = StatusEffects.blasted;
statusDuration = 60f;
+ damage = splashDamage * 0.5f;
}};
}});
}};
@@ -1254,6 +1256,7 @@ public class UnitTypes{
controller = u -> new MinerAI();
defaultCommand = UnitCommand.mineCommand;
+ allowChangeCommands = false;
flying = true;
drag = 0.06f;
@@ -1445,6 +1448,7 @@ public class UnitTypes{
healPercent = 15f;
splashDamage = 220f;
splashDamageRadius = 80f;
+ damage = splashDamage * 0.7f;
}};
}});
}};
@@ -1831,7 +1835,6 @@ public class UnitTypes{
//region naval support
retusa = new UnitType("retusa"){{
speed = 0.9f;
- targetAir = false;
drag = 0.14f;
hitSize = 11f;
health = 270;
@@ -1861,6 +1864,23 @@ public class UnitTypes{
}};
}});
+ weapons.add(new Weapon("retusa-weapon"){{
+ shootSound = Sounds.lasershoot;
+ reload = 22f;
+ x = 4.5f;
+ y = -3.5f;
+ rotateSpeed = 5f;
+ mirror = true;
+ rotate = true;
+ bullet = new LaserBoltBulletType(5.2f, 12){{
+ lifetime = 30f;
+ healPercent = 5.5f;
+ collidesTeam = true;
+ backColor = Pal.heal;
+ frontColor = Color.white;
+ }};
+ }});
+
weapons.add(new Weapon(){{
mirror = false;
rotate = true;
@@ -1912,7 +1932,7 @@ public class UnitTypes{
trailWidth = 3f;
trailLength = 8;
- splashDamage = 33f;
+ splashDamage = 40f;
splashDamageRadius = 32f;
}};
}});
@@ -2346,7 +2366,8 @@ public class UnitTypes{
//region core
alpha = new UnitType("alpha"){{
- aiController = BuilderAI::new;
+ aiController = () -> new BuilderAI(true, 400f);
+ controller = u -> u.team.isAI() ? aiController.get() : new CommandAI();
isEnemy = false;
lowAltitude = true;
@@ -2384,7 +2405,8 @@ public class UnitTypes{
}};
beta = new UnitType("beta"){{
- aiController = BuilderAI::new;
+ aiController = () -> new BuilderAI(true, 400f);
+ controller = u -> u.team.isAI() ? aiController.get() : new CommandAI();
isEnemy = false;
flying = true;
@@ -2425,7 +2447,8 @@ public class UnitTypes{
}};
gamma = new UnitType("gamma"){{
- aiController = BuilderAI::new;
+ aiController = () -> new BuilderAI(true, 400f);
+ controller = u -> u.team.isAI() ? aiController.get() : new CommandAI();
isEnemy = false;
lowAltitude = true;
@@ -2646,7 +2669,7 @@ public class UnitTypes{
width = 5f;
height = 7f;
lifetime = 15f;
- hitSize = 4f;
+ hitSize = 4f;
pierceCap = 3;
pierce = true;
pierceBuilding = true;
@@ -3524,7 +3547,7 @@ public class UnitTypes{
trailWidth = 2.2f;
trailLength = 7;
trailChance = -1f;
-
+
collidesAir = false;
despawnEffect = Fx.none;
diff --git a/core/src/mindustry/core/ContentLoader.java b/core/src/mindustry/core/ContentLoader.java
index 7abaf35f29..4e2f86410a 100644
--- a/core/src/mindustry/core/ContentLoader.java
+++ b/core/src/mindustry/core/ContentLoader.java
@@ -27,6 +27,7 @@ import static mindustry.Vars.*;
public class ContentLoader{
private ObjectMap[] contentNameMap = new ObjectMap[ContentType.all.length];
private Seq[] contentMap = new Seq[ContentType.all.length];
+ private ObjectMap nameMap = new ObjectMap<>();
private MappableContent[][] temporaryMapper;
private @Nullable LoadedMod currentMod;
private @Nullable Content lastAdded;
@@ -81,13 +82,14 @@ public class ContentLoader{
for(int k = 0; k < contentMap.length; k++){
Log.debug("[@]: loaded @", ContentType.all[k].name(), contentMap[k].size);
}
- Log.debug("Total content loaded: @", Seq.with(ContentType.all).mapInt(c -> contentMap[c.ordinal()].size).sum());
+ Log.debug("Total content loaded: @", Seq.with(ContentType.all).sum(c -> contentMap[c.ordinal()].size));
Log.debug("-------------------");
}
/** Calls Content#init() on everything. Use only after all modules have been created. */
public void init(){
initialize(Content::init);
+ initialize(Content::postInit);
if(logicVars != null) logicVars.init();
Events.fire(new ContentInitEvent());
}
@@ -171,6 +173,13 @@ public class ContentLoader{
public void handleMappableContent(MappableContent content){
if(contentNameMap[content.getContentType().ordinal()].containsKey(content.name)){
+ var list = contentMap[content.getContentType().ordinal()];
+
+ //this method is only called when registering content, and after handleContent.
+ //If this is the last registered content, and it is invalid, make sure to remove it from the list to prevent invalid stuff from being registered
+ if(list.size > 0 && list.peek() == content){
+ list.pop();
+ }
throw new IllegalArgumentException("Two content objects cannot have the same name! (issue: '" + content.name + "')");
}
if(currentMod != null){
@@ -180,12 +189,18 @@ public class ContentLoader{
}
}
contentNameMap[content.getContentType().ordinal()].put(content.name, content);
+ nameMap.put(content.name, content);
}
public void setTemporaryMapper(MappableContent[][] temporaryMapper){
this.temporaryMapper = temporaryMapper;
}
+ /** @return the last registered content with the specified name. Note that the content loader makes no attempt to resolve name conflicts. This method can be unreliable. */
+ public @Nullable MappableContent byName(String name){
+ return nameMap.get(name);
+ }
+
public Seq[] getContentMap(){
return contentMap;
}
diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java
index bc730c44c4..da36e8009a 100644
--- a/core/src/mindustry/core/Control.java
+++ b/core/src/mindustry/core/Control.java
@@ -16,9 +16,9 @@ import mindustry.content.*;
import mindustry.content.TechTree.*;
import mindustry.core.GameState.*;
import mindustry.entities.*;
+import mindustry.game.*;
import mindustry.game.EventType.*;
import mindustry.game.Objectives.*;
-import mindustry.game.*;
import mindustry.game.Saves.*;
import mindustry.gen.*;
import mindustry.input.*;
@@ -30,7 +30,6 @@ import mindustry.net.*;
import mindustry.type.*;
import mindustry.ui.dialogs.*;
import mindustry.world.*;
-import mindustry.world.blocks.storage.*;
import mindustry.world.blocks.storage.CoreBlock.*;
import java.io.*;
@@ -75,6 +74,7 @@ public class Control implements ApplicationListener, Loadable{
ui.showInfo("@mods.initfailed");
});
}
+ checkAutoUnlocks();
});
Events.on(StateChangeEvent.class, event -> {
@@ -404,7 +404,7 @@ public class Control implements ApplicationListener, Loadable{
ui.planet.hide();
SaveSlot slot = sector.save;
sector.planet.setLastSector(sector);
- if(slot != null && !clearSectors && (!sector.planet.clearSectorOnLose || sector.info.hasCore)){
+ if(slot != null && !clearSectors && (!(sector.planet.clearSectorOnLose || sector.info.hasWorldProcessor) || sector.info.hasCore)){
try{
boolean hadNoCore = !sector.info.hasCore;
@@ -417,7 +417,7 @@ public class Control implements ApplicationListener, Loadable{
//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){
- if(sector.planet.clearSectorOnLose){
+ if(sector.planet.clearSectorOnLose || sector.info.hasWorldProcessor){
playNewSector(origin, sector, reloader);
}else{
//no spawn set -> delete the sector save
@@ -441,6 +441,7 @@ public class Control implements ApplicationListener, Loadable{
state.wave = 1;
//set up default wave time
state.wavetime = state.rules.initialWaveSpacing <= 0f ? (state.rules.waveSpacing * (sector.preset == null ? 2f : sector.preset.startWaveTimeMultiplier)) : state.rules.initialWaveSpacing;
+ state.wavetime *= sector.planet.campaignRules.difficulty.waveTimeMultiplier;
//reset captured state
sector.info.wasCaptured = false;
@@ -457,7 +458,7 @@ public class Control implements ApplicationListener, Loadable{
for(var plan : state.rules.waveTeam.data().plans){
Tile tile = world.tile(plan.x, plan.y);
if(tile != null){
- tile.setBlock(content.block(plan.block), state.rules.waveTeam, plan.rotation);
+ tile.setBlock(plan.block, state.rules.waveTeam, plan.rotation);
if(plan.config != null && tile.build != null){
tile.build.configureAny(plan.config);
}
diff --git a/core/src/mindustry/core/GameState.java b/core/src/mindustry/core/GameState.java
index 17d3b3bfe9..1066e6d2a6 100644
--- a/core/src/mindustry/core/GameState.java
+++ b/core/src/mindustry/core/GameState.java
@@ -78,7 +78,7 @@ public class GameState{
}
public @Nullable Planet getPlanet(){
- return rules.sector != null ? rules.sector.planet : null;
+ return rules.sector != null ? rules.sector.planet : rules.planet;
}
public boolean isEditor(){
diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java
index 59f9b3cdcd..4b4f0be7d3 100644
--- a/core/src/mindustry/core/Logic.java
+++ b/core/src/mindustry/core/Logic.java
@@ -92,7 +92,7 @@ public class Logic implements ApplicationListener{
if(wavesPassed > 0){
//simulate wave counter moving forward
state.wave += wavesPassed;
- state.wavetime = state.rules.waveSpacing;
+ state.wavetime = state.rules.waveSpacing * state.getPlanet().campaignRules.difficulty.waveTimeMultiplier;
SectorDamage.applyCalculatedDamage();
}
@@ -131,6 +131,7 @@ public class Logic implements ApplicationListener{
//enable building AI on campaign unless the preset disables it
state.rules.coreIncinerates = true;
+ state.rules.allowEditWorldProcessors = false;
state.rules.waveTeam.rules().infiniteResources = true;
state.rules.waveTeam.rules().buildSpeedMultiplier *= state.getPlanet().enemyBuildSpeedMultiplier;
@@ -140,10 +141,6 @@ public class Logic implements ApplicationListener{
core.items.set(item, core.block.itemCapacity);
}
}
-
- //set up hidden items
- state.rules.hiddenBuildItems.clear();
- state.rules.hiddenBuildItems.addAll(state.rules.sector.planet.hiddenItems);
}
//save settings
@@ -213,8 +210,7 @@ public class Logic implements ApplicationListener{
var bounds = tile.block().bounds(tile.x, tile.y, Tmp.r1);
while(it.hasNext()){
BlockPlan b = it.next();
- Block block = content.block(b.block);
- if(bounds.overlaps(block.bounds(b.x, b.y, Tmp.r2))){
+ if(bounds.overlaps(b.block.bounds(b.x, b.y, Tmp.r2))){
b.removed = true;
it.remove();
}
@@ -225,7 +221,7 @@ public class Logic implements ApplicationListener{
public void play(){
state.set(State.playing);
//grace period of 2x wave time before game starts
- state.wavetime = state.rules.initialWaveSpacing <= 0 ? state.rules.waveSpacing * 2 : state.rules.initialWaveSpacing;
+ state.wavetime = (state.rules.initialWaveSpacing <= 0 ? state.rules.waveSpacing * 2 : state.rules.initialWaveSpacing) * (state.isCampaign() ? state.getPlanet().campaignRules.difficulty.waveTimeMultiplier : 1f);;
Events.fire(new PlayEvent());
//add starting items
@@ -274,7 +270,7 @@ public class Logic implements ApplicationListener{
public void runWave(){
spawner.spawnEnemies();
state.wave++;
- state.wavetime = state.rules.waveSpacing;
+ state.wavetime = state.rules.waveSpacing * (state.isCampaign() ? state.getPlanet().campaignRules.difficulty.waveTimeMultiplier : 1f);
Events.fire(new WaveEvent());
}
@@ -398,8 +394,8 @@ public class Logic implements ApplicationListener{
public static void researched(Content content){
if(!(content instanceof UnlockableContent u)) return;
- boolean was = u.unlockedNow();
- state.rules.researched.add(u.name);
+ boolean was = u.unlockedNowHost();
+ state.rules.researched.add(u);
if(!was){
Events.fire(new UnlockEvent(u));
diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java
index 8d3ac0bd19..97f2d96160 100644
--- a/core/src/mindustry/core/NetClient.java
+++ b/core/src/mindustry/core/NetClient.java
@@ -10,6 +10,7 @@ import arc.util.*;
import arc.util.CommandHandler.*;
import arc.util.io.*;
import arc.util.serialization.*;
+import arc.util.serialization.JsonValue.*;
import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.core.GameState.*;
@@ -18,6 +19,7 @@ import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.game.Teams.*;
import mindustry.gen.*;
+import mindustry.io.*;
import mindustry.logic.*;
import mindustry.net.Administration.*;
import mindustry.net.*;
@@ -32,10 +34,12 @@ import java.util.zip.*;
import static mindustry.Vars.*;
public class NetClient implements ApplicationListener{
+ private static final long entitySnapshotTimeout = 1000 * 20;
private static final float dataTimeout = 60 * 30;
/** ticks between syncs, e.g. 5 means 60/5 = 12 syncs/sec*/
private static final float playerSyncTime = 4;
private static final Reads dataReads = new Reads(null);
+ private static final JsonValue tmpJsonMap = new JsonValue(ValueType.object);
private long ping;
private Interval timer = new Interval(5);
@@ -47,6 +51,8 @@ public class NetClient implements ApplicationListener{
private boolean quietReset = false;
/** Counter for data timeout. */
private float timeoutTime = 0f;
+ /** Timestamp for last UDP state snapshot received. */
+ private long lastSnapshotTimestamp;
/** Last sent client snapshot ID. */
private int lastSent;
@@ -57,6 +63,8 @@ public class NetClient implements ApplicationListener{
private DataInputStream dataStream = new DataInputStream(byteStream);
/** Packet handlers for custom types of messages. */
private ObjectMap>> customPacketHandlers = new ObjectMap<>();
+ /** Packet handlers for custom types of messages, in binary. */
+ private ObjectMap>> customBinaryPacketHandlers = new ObjectMap<>();
public NetClient(){
@@ -147,10 +155,34 @@ public class NetClient implements ApplicationListener{
return customPacketHandlers.get(type, Seq::new);
}
+ public void addBinaryPacketHandler(String type, Cons handler){
+ customBinaryPacketHandlers.get(type, Seq::new).add(handler);
+ }
+
+ public Seq> getBinaryPacketHandlers(String type){
+ return customBinaryPacketHandlers.get(type, Seq::new);
+ }
+
+ @Remote(targets = Loc.server, variants = Variant.both)
+ public static void clientBinaryPacketReliable(String type, byte[] contents){
+ var arr = netClient.customBinaryPacketHandlers.get(type);
+ if(arr != null){
+ for(var c : arr){
+ c.get(contents);
+ }
+ }
+ }
+
+ @Remote(targets = Loc.server, variants = Variant.both, unreliable = true)
+ public static void clientBinaryPacketUnreliable(String type, byte[] contents){
+ clientBinaryPacketReliable(type, contents);
+ }
+
@Remote(targets = Loc.server, variants = Variant.both)
public static void clientPacketReliable(String type, String contents){
- if(netClient.customPacketHandlers.containsKey(type)){
- for(Cons c : netClient.customPacketHandlers.get(type)){
+ var arr = netClient.customPacketHandlers.get(type);
+ if(arr != null){
+ for(Cons c : arr){
c.get(contents);
}
}
@@ -340,6 +372,18 @@ public class NetClient implements ApplicationListener{
state.rules = rules;
}
+ @Remote(variants = Variant.both)
+ public static void setRule(String rule, String jsonData){
+ try{
+ //readField searches for the specified value, so create a fake parent for it.
+ tmpJsonMap.child = null;
+ tmpJsonMap.addChild(rule, new JsonReader().parse(jsonData));
+ JsonIO.json.readField(state.rules, rule, tmpJsonMap);
+ }catch(Throwable error){
+ Log.err("Failed to read rule", error);
+ }
+ }
+
//NOTE: avoid using this, runs into packet/buffer size limitations
@Remote(variants = Variant.both)
public static void setObjectives(MapObjectives executor){
@@ -437,6 +481,7 @@ public class NetClient implements ApplicationListener{
@Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true)
public static void entitySnapshot(short amount, byte[] data){
try{
+ netClient.lastSnapshotTimestamp = Time.millis();
netClient.byteStream.setBytes(data);
DataInputStream input = netClient.dataStream;
@@ -534,7 +579,18 @@ public class NetClient implements ApplicationListener{
if(!net.client()) return;
if(state.isGame()){
- if(!connecting) sync();
+ if(!connecting){
+ sync();
+
+ //timeout if UDP snapshot packets are not received for a while
+ if(lastSnapshotTimestamp > 0 && Time.timeSinceMillis(lastSnapshotTimestamp) > entitySnapshotTimeout){
+ Log.err("Timed out after not received UDP snapshots.");
+ quiet = true;
+ ui.showErrorMessage("@disconnect.snapshottimeout");
+ net.disconnect();
+ lastSnapshotTimestamp = 0;
+ }
+ }
}else if(!connecting){
net.disconnect();
}else{ //...must be connecting
@@ -571,6 +627,7 @@ public class NetClient implements ApplicationListener{
Core.app.post(Call::connectConfirm);
Time.runTask(40f, platform::updateRPC);
Core.app.post(ui.loadfrag::hide);
+ lastSnapshotTimestamp = Time.millis();
}
private void reset(){
@@ -581,6 +638,7 @@ public class NetClient implements ApplicationListener{
quietReset = false;
quiet = false;
lastSent = 0;
+ lastSnapshotTimestamp = 0;
Groups.clear();
ui.chatfrag.clearMessages();
diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java
index 3558877cbb..61e088aea8 100644
--- a/core/src/mindustry/core/NetServer.java
+++ b/core/src/mindustry/core/NetServer.java
@@ -117,6 +117,8 @@ public class NetServer implements ApplicationListener{
private DataOutputStream dataStream = new DataOutputStream(syncStream);
/** Packet handlers for custom types of messages. */
private ObjectMap>> customPacketHandlers = new ObjectMap<>();
+ /** Packet handlers for custom types of messages - binary version. */
+ private ObjectMap>> customBinaryPacketHandlers = new ObjectMap<>();
/** Packet handlers for logic client data */
private ObjectMap>> logicClientDataHandlers = new ObjectMap<>();
@@ -423,7 +425,7 @@ public class NetServer implements ApplicationListener{
}
});
- clientCommands.register("vote", "", "Vote to kick the current player. Admin can cancel the voting with 'c'.", (arg, player) -> {
+ clientCommands.register("vote", "", "Vote to kick the current player. Admins can cancel the voting with 'c'.", (arg, player) -> {
if(currentlyKicking == null){
player.sendMessage("[scarlet]Nobody is being voted on.");
}else{
@@ -517,6 +519,14 @@ public class NetServer implements ApplicationListener{
return customPacketHandlers.get(type, Seq::new);
}
+ public void addBinaryPacketHandler(String type, Cons2 handler){
+ customBinaryPacketHandlers.get(type, Seq::new).add(handler);
+ }
+
+ public Seq> getBinaryPacketHandlers(String type){
+ return customBinaryPacketHandlers.get(type, Seq::new);
+ }
+
public void addLogicDataHandler(String type, Cons2 handler){
logicClientDataHandlers.get(type, Seq::new).add(handler);
}
@@ -589,6 +599,20 @@ public class NetServer implements ApplicationListener{
serverPacketReliable(player, type, contents);
}
+ @Remote(targets = Loc.client)
+ public static void serverBinaryPacketReliable(Player player, String type, byte[] contents){
+ if(netServer.customPacketHandlers.containsKey(type)){
+ for(var c : netServer.customBinaryPacketHandlers.get(type)){
+ c.get(player, contents);
+ }
+ }
+ }
+
+ @Remote(targets = Loc.client, unreliable = true)
+ public static void serverBinaryPacketUnreliable(Player player, String type, byte[] contents){
+ serverBinaryPacketReliable(player, type, contents);
+ }
+
@Remote(targets = Loc.client)
public static void clientLogicDataReliable(Player player, String channel, Object value){
Seq> handlers = netServer.logicClientDataHandlers.get(channel);
@@ -674,7 +698,7 @@ public class NetServer implements ApplicationListener{
//auto-skip done requests
if(req.breaking && tile.block() == Blocks.air){
continue;
- }else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || (tile.build != null && tile.build.rotation == req.rotation))){
+ }else if(!req.breaking && tile.block() == req.block && tile.team() != Team.derelict && (!req.block.rotate || (tile.build != null && tile.build.rotation == req.rotation))){
continue;
}else if(con.rejectedRequests.contains(r -> r.breaking == req.breaking && r.x == req.x && r.y == req.y)){ //check if request was recently rejected, and skip it if so
continue;
@@ -1058,7 +1082,7 @@ public class NetServer implements ApplicationListener{
try{
writeEntitySnapshot(player);
}catch(IOException e){
- e.printStackTrace();
+ Log.err(e);
}
});
diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java
index ae3ae07e38..c544e8bba2 100644
--- a/core/src/mindustry/core/Renderer.java
+++ b/core/src/mindustry/core/Renderer.java
@@ -339,6 +339,8 @@ public class Renderer implements ApplicationListener{
Draw.draw(Layer.effect + 0.02f, bloom::render);
}
+ control.input.drawCommanded();
+
Draw.draw(Layer.plans, overlays::drawBottom);
if(animateShields && Shaders.shield != null){
@@ -548,6 +550,7 @@ public class Renderer implements ApplicationListener{
public void showLaunch(CoreBuild landCore, CoreBlock coreType){
control.input.config.hideConfig();
+ control.input.planConfig.hide();
control.input.inv.hide();
this.landCore = landCore;
diff --git a/core/src/mindustry/core/UI.java b/core/src/mindustry/core/UI.java
index d634e122b5..1eb38240d1 100644
--- a/core/src/mindustry/core/UI.java
+++ b/core/src/mindustry/core/UI.java
@@ -158,7 +158,7 @@ public class UI implements ApplicationListener, Loadable{
Core.scene.draw();
if(Core.input.keyTap(KeyCode.mouseLeft) && Core.scene.hasField()){
- Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true);
+ Element e = Core.scene.getHoverElement();
if(!(e instanceof TextField)){
Core.scene.setKeyboardFocus(null);
}
@@ -628,6 +628,7 @@ public class UI implements ApplicationListener, Loadable{
int option = 0;
for(var optionsRow : options){
+ if(optionsRow.length == 0) continue;
Table buttonRow = table.row().table().get().row();
int fullWidth = 400 - (optionsRow.length - 1) * 8; // adjust to count padding as well
int width = fullWidth / optionsRow.length;
diff --git a/core/src/mindustry/core/Version.java b/core/src/mindustry/core/Version.java
index 73bbd59416..c79594eebd 100644
--- a/core/src/mindustry/core/Version.java
+++ b/core/src/mindustry/core/Version.java
@@ -12,6 +12,8 @@ public class Version{
public static String type = "unknown";
/** Build modifier, e.g. 'alpha' or 'release' */
public static String modifier = "unknown";
+ /** Git commit hash (short) */
+ public static String commitHash = "unknown";
/** Number specifying the major version, e.g. '4' */
public static int number;
/** Build number, e.g. '43'. set to '-1' for custom builds. */
@@ -32,6 +34,7 @@ public class Version{
type = map.get("type");
number = Integer.parseInt(map.get("number", "4"));
modifier = map.get("modifier");
+ commitHash = map.get("commitHash");
if(map.get("build").contains(".")){
String[] split = map.get("build").split("\\.");
try{
@@ -73,6 +76,6 @@ public class Version{
if(build == -1){
return "custom build";
}
- return (type.equals("official") ? modifier : type) + " build " + build + (revision == 0 ? "" : "." + revision);
+ return (type.equals("official") ? modifier : type) + " build " + build + (revision == 0 ? "" : "." + revision) + (commitHash.equals("unknown") ? "" : " (" + commitHash + ")");
}
}
diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java
index 92e3e46a8c..a9e858a0c7 100644
--- a/core/src/mindustry/core/World.java
+++ b/core/src/mindustry/core/World.java
@@ -321,8 +321,6 @@ public class World{
state.rules.cloudColor = sector.planet.landCloudColor;
state.rules.env = sector.planet.defaultEnv;
state.rules.planet = sector.planet;
- state.rules.hiddenBuildItems.clear();
- state.rules.hiddenBuildItems.addAll(sector.planet.hiddenItems);
sector.planet.applyRules(state.rules);
sector.info.resources = content.toSeq();
sector.info.resources.sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id)));
diff --git a/core/src/mindustry/ctype/Content.java b/core/src/mindustry/ctype/Content.java
index 58a75b4dc8..97816377e2 100644
--- a/core/src/mindustry/ctype/Content.java
+++ b/core/src/mindustry/ctype/Content.java
@@ -25,6 +25,9 @@ public abstract class Content implements Comparable{
/** Called after all content and modules are created. Do not use to load regions or texture data! */
public void init(){}
+ /** Called after init(). */
+ public void postInit(){}
+
/**
* Called after all content is created, only on non-headless versions.
* Use for loading regions or other image data.
diff --git a/core/src/mindustry/ctype/UnlockableContent.java b/core/src/mindustry/ctype/UnlockableContent.java
index 2692c28a94..c4ed0bf708 100644
--- a/core/src/mindustry/ctype/UnlockableContent.java
+++ b/core/src/mindustry/ctype/UnlockableContent.java
@@ -9,6 +9,7 @@ import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
+import mindustry.content.*;
import mindustry.content.TechTree.*;
import mindustry.game.EventType.*;
import mindustry.graphics.*;
@@ -35,8 +36,6 @@ public abstract class UnlockableContent extends MappableContent{
public boolean hideDetails = true;
/** If false, all icon generation is disabled for this content; createIcons is not called. */
public boolean generateIcons = true;
- /** Special logic icon ID. */
- public int iconId = 0;
/** How big the content appears in certain selection menus */
public float selectionSize = 24f;
/** Icon of the content to use in UI. */
@@ -45,11 +44,24 @@ public abstract class UnlockableContent extends MappableContent{
public TextureRegion fullIcon;
/** Override for the full icon. Useful for mod content with duplicate icons. Overrides any other full icon.*/
public String fullOverride = "";
+ /** If true, this content will appear in all database tabs. */
+ public boolean allDatabaseTabs = false;
+ /**
+ * Planets that this content is made for. If empty, a planet is decided based on item requirements.
+ * Currently, this is only meaningful for blocks.
+ * */
+ public ObjectSet shownPlanets = new ObjectSet<>();
+ /**
+ * Content - usually a planet - that dictates which database tab(s) this content will appear in.
+ * If nothing is defined, it will use the values in shownPlanets.
+ * If shownPlanets is also empty, it will use Serpulo as the "default" tab.
+ * */
+ public ObjectSet databaseTabs = new ObjectSet<>();
/** The tech tree node for this content, if applicable. Null if not part of a tech tree. */
public @Nullable TechNode techNode;
/** Tech nodes for all trees that this content is part of. */
public Seq techNodes = new Seq<>();
- /** Unlock state. Loaded from settings. Do not modify outside of the constructor. */
+ /** Unlock state. Loaded from settings. Do not modify outside the constructor. */
protected boolean unlocked;
public UnlockableContent(String name){
@@ -61,10 +73,17 @@ public abstract class UnlockableContent extends MappableContent{
this.unlocked = Core.settings != null && Core.settings.getBool(this.name + "-unlocked", false);
}
+ @Override
+ public void postInit(){
+ super.postInit();
+
+ databaseTabs.addAll(shownPlanets);
+ }
+
@Override
public void loadIcon(){
fullIcon =
- Core.atlas.find(fullOverride,
+ Core.atlas.find(fullOverride == null ? "" : fullOverride,
Core.atlas.find(getContentType().name() + "-" + name + "-full",
Core.atlas.find(name + "-full",
Core.atlas.find(name,
@@ -74,6 +93,10 @@ public abstract class UnlockableContent extends MappableContent{
uiIcon = Core.atlas.find(getContentType().name() + "-" + name + "-ui", fullIcon);
}
+ public boolean isOnPlanet(@Nullable Planet planet){
+ return planet == null || planet == Planets.sun || shownPlanets.isEmpty() || shownPlanets.contains(planet);
+ }
+
public int getLogicId(){
return logicVars.lookupLogicId(this);
}
@@ -200,15 +223,24 @@ public abstract class UnlockableContent extends MappableContent{
}
public boolean unlockedNowHost(){
- if(!state.isCampaign()) return true;
+ return !state.isCampaign() || unlockedHost();
+ }
+
+ /** @return in multiplayer, whether this is unlocked for the host player, otherwise, whether it is unlocked for the local player (same as unlocked()) */
+ public boolean unlockedHost(){
return net != null && net.client() ?
- alwaysUnlocked || state.rules.researched.contains(name) :
+ alwaysUnlocked || state.rules.researched.contains(this) :
unlocked || alwaysUnlocked;
}
+ /** @return whether this content is unlocked, or the player is in a custom (non-campaign) game. */
+ public boolean unlockedNow(){
+ return unlocked() || !state.isCampaign();
+ }
+
public boolean unlocked(){
return net != null && net.client() ?
- alwaysUnlocked || unlocked || state.rules.researched.contains(name) :
+ alwaysUnlocked || unlocked || state.rules.researched.contains(this) :
unlocked || alwaysUnlocked;
}
@@ -220,11 +252,6 @@ public abstract class UnlockableContent extends MappableContent{
}
}
- /** @return whether this content is unlocked, or the player is in a custom (non-campaign) game. */
- public boolean unlockedNow(){
- return unlocked() || !state.isCampaign();
- }
-
public boolean locked(){
return !unlocked();
}
diff --git a/core/src/mindustry/editor/MapEditorDialog.java b/core/src/mindustry/editor/MapEditorDialog.java
index a4c2de9dc3..ad35a4a45f 100644
--- a/core/src/mindustry/editor/MapEditorDialog.java
+++ b/core/src/mindustry/editor/MapEditorDialog.java
@@ -172,21 +172,18 @@ public class MapEditorDialog extends Dialog implements Disposable{
menu.cont.row();
}
- //wip feature
- if(experimental){
- menu.cont.button("@editor.sectorgenerate", Icon.terrain, () -> {
- menu.hide();
- sectorGenDialog.show();
- }).padTop(!steam ? -3 : 1).size(swidth * 2f + 10, 60f);
- menu.cont.row();
- }
+ menu.cont.button("@editor.sectorgenerate", Icon.terrain, () -> {
+ menu.hide();
+ sectorGenDialog.show();
+ }).padTop(!steam ? -3 : 1).size(swidth * 2f + 10, 60f);
+ menu.cont.row();
menu.cont.row();
menu.cont.button("@quit", Icon.exit, () -> {
tryExit();
menu.hide();
- }).padTop(!steam && !experimental ? -3 : 1).size(swidth * 2f + 10, 60f);
+ }).padTop(1).size(swidth * 2f + 10, 60f);
resizeDialog = new MapResizeDialog((width, height, shiftX, shiftY) -> {
if(!(editor.width() == width && editor.height() == height && shiftX == 0 && shiftY == 0)){
@@ -271,6 +268,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
));
world.endMapLoad();
player.set(world.width() * tilesize/2f, world.height() * tilesize/2f);
+ Core.camera.position.set(player);
player.clearUnit();
for(var unit : Groups.unit){
@@ -695,28 +693,6 @@ public class MapEditorDialog extends Dialog implements Disposable{
editor.undo();
}
- //more undocumented features, fantastic
- if(Core.input.keyTap(KeyCode.t)){
-
- //clears all 'decoration' from the map
- for(int x = 0; x < editor.width(); x++){
- for(int y = 0; y < editor.height(); y++){
- Tile tile = editor.tile(x, y);
- if(tile.block().breakable && tile.block() instanceof Prop){
- tile.setBlock(Blocks.air);
- editor.renderer.updatePoint(x, y);
- }
-
- if(tile.overlay() != Blocks.air && tile.overlay() != Blocks.spawn){
- tile.setOverlay(Blocks.air);
- editor.renderer.updatePoint(x, y);
- }
- }
- }
-
- editor.flushOp();
- }
-
if(Core.input.keyTap(KeyCode.y)){
editor.redo();
}
@@ -737,7 +713,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
private void addBlockSelection(Table cont){
blockSelection = new Table();
- pane = new ScrollPane(blockSelection);
+ pane = new ScrollPane(blockSelection, Styles.smallPane);
pane.setFadeScrollBars(false);
pane.setOverscroll(true, false);
pane.exited(() -> {
@@ -754,7 +730,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
cont.row();
cont.table(Tex.underline, extra -> extra.labelWrap(() -> editor.drawBlock.localizedName).width(200f).center()).growX();
cont.row();
- cont.add(pane).expandY().top().left();
+ cont.add(pane).expandY().growX().top().left();
rebuildBlockSelection("");
}
@@ -784,7 +760,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|| (!searchText.isEmpty() && !block.localizedName.toLowerCase().contains(searchText.toLowerCase()))
) continue;
- ImageButton button = new ImageButton(Tex.whiteui, Styles.squareTogglei);
+ ImageButton button = new ImageButton(Tex.whiteui, Styles.clearNoneTogglei);
button.getStyle().imageUp = new TextureRegionDrawable(region);
button.clicked(() -> editor.drawBlock = block);
button.resizeImage(8 * 4f);
@@ -793,7 +769,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
if(i == 0) editor.drawBlock = block;
- if(++i % 4 == 0){
+ if(++i % 6 == 0){
blockSelection.row();
}
}
diff --git a/core/src/mindustry/editor/MapObjectivesCanvas.java b/core/src/mindustry/editor/MapObjectivesCanvas.java
index bd84a22ff7..0cde471b89 100644
--- a/core/src/mindustry/editor/MapObjectivesCanvas.java
+++ b/core/src/mindustry/editor/MapObjectivesCanvas.java
@@ -368,7 +368,7 @@ public class MapObjectivesCanvas extends WidgetGroup{
() -> obj,
res -> {}
);
- }).width(400f).fillY()).grow();
+ }).width(Math.min(Core.graphics.getWidth() * 0.95f / Scl.scl(1f) - Scl.scl(20f), 700f)).fillY()).grow();
dialog.addCloseButton();
dialog.show();
diff --git a/core/src/mindustry/editor/MapObjectivesDialog.java b/core/src/mindustry/editor/MapObjectivesDialog.java
index ecdc53e01e..c8f021f214 100644
--- a/core/src/mindustry/editor/MapObjectivesDialog.java
+++ b/core/src/mindustry/editor/MapObjectivesDialog.java
@@ -1,5 +1,6 @@
package mindustry.editor;
+import arc.*;
import arc.func.*;
import arc.graphics.*;
import arc.math.geom.*;
@@ -44,7 +45,7 @@ public class MapObjectivesDialog extends BaseDialog{
name(cont, name, remover, indexer);
if(field != null && field.isAnnotationPresent(Multiline.class)){
- cont.area(get.get(), set).height(85f).growX();
+ cont.area(get.get(), set).height(100f).growX();
}else{
cont.field(get.get(), set).growX();
}
@@ -465,10 +466,42 @@ public class MapObjectivesDialog extends BaseDialog{
buttons.defaults().size(160f, 64f).pad(2f);
buttons.button("@back", Icon.left, MapObjectivesDialog.this::hide);
buttons.button("@add", Icon.add, () -> getProvider(MapObjective.class).get(new TypeInfo(MapObjective.class), canvas::query));
+ buttons.button("@waves.edit", Icon.edit, () -> {
+ BaseDialog dialog = new BaseDialog("@waves.edit");
+ dialog.addCloseButton();
+ dialog.setFillParent(false);
+ dialog.cont.table(Tex.button, t -> {
+ var style = Styles.cleart;
+ t.defaults().size(280f, 64f).pad(2f);
+
+ t.button("@waves.copy", Icon.copy, style, () -> {
+ ui.showInfoFade("@copied");
+ Core.app.setClipboardText(JsonIO.write(new MapObjectives(canvas.objectives)));
+ dialog.hide();
+ }).disabled(b -> canvas.objectives.isEmpty()).marginLeft(12f).row();
+
+ t.button("@waves.load", Icon.download, style, () -> {
+ try{
+ rebuildObjectives(new Seq<>(JsonIO.read(MapObjectives.class, Core.app.getClipboardText()).all));
+ }catch(Exception e){
+ Log.err(e);
+ ui.showErrorMessage("@waves.invalid");
+ }
+ dialog.hide();
+ }).disabled(Core.app.getClipboardText() == null || !Core.app.getClipboardText().startsWith("[")).marginLeft(12f).row();
+
+ t.button("@clear", Icon.none, style, () -> ui.showConfirm("@confirm", "@settings.clear.confirm", () -> {
+ rebuildObjectives(new Seq<>());
+ dialog.hide();
+ })).marginLeft(12f).row();
+ });
+
+ dialog.show();
+ });
if(mobile){
- buttons.button("@cancel", Icon.cancel, canvas::stopQuery).disabled(b -> !canvas.isQuerying());
- buttons.button("@ok", Icon.ok, canvas::placeQuery).disabled(b -> !canvas.isQuerying());
+ buttons.button("@cancel", Icon.cancel, canvas::stopQuery).visible(() -> canvas.isQuerying());
+ buttons.button("@ok", Icon.ok, canvas::placeQuery).visible(() -> canvas.isQuerying());
}
setFillParent(true);
@@ -490,22 +523,27 @@ public class MapObjectivesDialog extends BaseDialog{
public void show(Seq objectives, Cons> out){
this.out = out;
+ rebuildObjectives(objectives);
+ show();
+ }
+
+ public void rebuildObjectives(Seq objectives){
canvas.clearObjectives();
if(
- objectives.any() && (
- // If the objectives were previously programmatically made...
- objectives.contains(obj -> obj.editorX == -1 || obj.editorY == -1) ||
- // ... or some idiot somehow made it not work...
- objectives.contains(obj -> !canvas.tilemap.createTile(obj))
+ objectives.any() && (
+ // If the objectives were previously programmatically made...
+ objectives.contains(obj -> obj.editorX == -1 || obj.editorY == -1) ||
+ // ... or some idiot somehow made it not work...
+ objectives.contains(obj -> !canvas.tilemap.createTile(obj))
)){
// ... then rebuild the structure.
canvas.clearObjectives();
// This is definitely NOT a good way to do it, but only insane people or people from the distant past would actually encounter this anyway.
int w = objWidth + 2,
- len = objectives.size * w,
- columns = objectives.size,
- rows = 1;
+ len = objectives.size * w,
+ columns = objectives.size,
+ rows = 1;
if(len > bounds){
rows = len / bounds;
@@ -525,7 +563,6 @@ public class MapObjectivesDialog extends BaseDialog{
}
canvas.objectives.set(objectives);
- show();
}
public static void showContentSelect(@Nullable ContentType type, Cons cons, Boolf check){
diff --git a/core/src/mindustry/editor/MapProcessorsDialog.java b/core/src/mindustry/editor/MapProcessorsDialog.java
index dd0f73d3f7..8867c2df13 100644
--- a/core/src/mindustry/editor/MapProcessorsDialog.java
+++ b/core/src/mindustry/editor/MapProcessorsDialog.java
@@ -19,7 +19,7 @@ import mindustry.world.blocks.logic.LogicBlock.*;
import static mindustry.Vars.*;
public class MapProcessorsDialog extends BaseDialog{
- private IconSelectDialog iconSelect = new IconSelectDialog();
+ private IconSelectDialog iconSelect = new IconSelectDialog(true);
private TextField search;
private Seq processors = new Seq<>();
private Table list;
diff --git a/core/src/mindustry/editor/MapView.java b/core/src/mindustry/editor/MapView.java
index dd1c447f61..4131bc2bcd 100644
--- a/core/src/mindustry/editor/MapView.java
+++ b/core/src/mindustry/editor/MapView.java
@@ -329,7 +329,7 @@ public class MapView extends Element implements GestureListener{
return Core.scene != null && Core.scene.getKeyboardFocus() != null
&& Core.scene.getKeyboardFocus().isDescendantOf(ui.editor)
&& ui.editor.isShown() && tool == EditorTool.zoom &&
- Core.scene.hit(Core.input.mouse().x, Core.input.mouse().y, true) == this;
+ Core.scene.getHoverElement() == this;
}
@Override
diff --git a/core/src/mindustry/editor/SectorGenerateDialog.java b/core/src/mindustry/editor/SectorGenerateDialog.java
index f51b55f443..4d0b8bcb37 100644
--- a/core/src/mindustry/editor/SectorGenerateDialog.java
+++ b/core/src/mindustry/editor/SectorGenerateDialog.java
@@ -93,6 +93,7 @@ public class SectorGenerateDialog extends BaseDialog{
var preset = sectorobj.preset;
sectorobj.preset = null;
+ logic.reset(); //TODO: is this a good idea? all rules and map state are cleared, but it fixes inconsistent gen
world.loadSector(sectorobj, seed, false);
sectorobj.preset = preset;
diff --git a/core/src/mindustry/editor/WaveGraph.java b/core/src/mindustry/editor/WaveGraph.java
index 398443c177..11e6e6cfe8 100644
--- a/core/src/mindustry/editor/WaveGraph.java
+++ b/core/src/mindustry/editor/WaveGraph.java
@@ -1,8 +1,13 @@
package mindustry.editor;
+import arc.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
+import arc.input.*;
import arc.math.*;
+import arc.math.geom.*;
+import arc.scene.*;
+import arc.scene.event.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
@@ -17,7 +22,6 @@ import mindustry.ui.*;
public class WaveGraph extends Table{
public Seq groups = new Seq<>();
- public int from = 0, to = 20;
private Mode mode = Mode.counts;
private int[][] values;
@@ -26,47 +30,114 @@ public class WaveGraph extends Table{
private float maxHealth;
private Table colors;
private ObjectSet hidden = new ObjectSet<>();
+ private StringBuilder countStr = new StringBuilder();
+
+ private float pan;
+ private float zoom = 1f;
+ private int from = 0, to = 20;
+ private int lastFrom = -1, lastTo = -1;
+ private float lastZoom = -1f;
+
+ private float defaultSpace = Scl.scl(40f);
+ private FloatSeq points = new FloatSeq(40);
public WaveGraph(){
background(Tex.pane);
+ scrolled((scroll) -> {
+ zoom -= scroll * 2f / 10f * zoom;
+ clampZoom();
+ });
+
+ touchable = Touchable.enabled;
+ addListener(new InputListener(){
+
+ @Override
+ public void enter(InputEvent event, float x, float y, int pointer, Element fromActor){
+ requestScroll();
+ }
+ });
+
+ addListener(new ElementGestureListener(){
+ @Override
+ public void pan(InputEvent event, float x, float y, float deltaX, float deltaY){
+ pan -= deltaX/zoom;
+ }
+
+ @Override
+ public void zoom(InputEvent event, float initialDistance, float distance){
+ if(lastZoom < 0) lastZoom = zoom;
+
+ zoom = distance / initialDistance * lastZoom;
+ clampZoom();
+ }
+
+ @Override
+ public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){
+ lastZoom = zoom;
+ }
+ });
+
rect((x, y, width, height) -> {
Lines.stroke(Scl.scl(3f));
+ countStr.setLength(0);
+
+ Vec2 mouse = stageToLocalCoordinates(Core.input.mouse());
GlyphLayout lay = Pools.obtain(GlyphLayout.class, GlyphLayout::new);
Font font = Fonts.outline;
- lay.setText(font, "1");
-
int maxY = switch(mode){
case counts -> nextStep(max);
case health -> nextStep((int)maxHealth);
case totals -> nextStep(maxTotal);
};
- float fh = lay.height;
- float offsetX = Scl.scl(lay.width * (maxY + "").length() * 2), offsetY = Scl.scl(22f) + fh + Scl.scl(5f);
+ lay.setText(font, "1");
- float graphX = x + offsetX, graphY = y + offsetY, graphW = width - offsetX, graphH = height - offsetY;
- float spacing = graphW / (values.length - 1);
+ float spacing = zoom * defaultSpace;
+ pan = Math.max(pan, (width/2f)/zoom-defaultSpace);
+
+ float fh = lay.height;
+ float offsetX = 0f, offsetY = Scl.scl(22f) + fh + Scl.scl(5f);
+ float graphX = x + offsetX - pan * zoom + width/2f, graphY = y + offsetY, graphW = width - offsetX, graphH = height - offsetY;
+
+ float left = (x-graphX)/spacing, right = (x + width - graphX)/spacing;
+
+ //int radius = Mathf.ceil(graphW / spacing / 2f);
+
+ from = (int)left - 1;
+ to = (int)right + 1;
+
+ if(lastFrom != from || lastTo != to){
+ rebuild();
+ }
+
+ lastFrom = from;
+ lastTo = to;
+
+ if(!clipBegin(x + offsetX, y + offsetY, graphW, graphH)) return;
+
+ int selcol = Rect.contains(x, y, width, height, mouse.x, mouse.y) ? Mathf.round((mouse.x - graphX - (from * spacing)) / spacing) : -1;
+ if(selcol + from <= -1) selcol = -1;
if(mode == Mode.counts){
for(UnitType type : used.orderedItems()){
Draw.color(color(type));
Draw.alpha(parentAlpha);
- Lines.beginLine();
+ beginLine();
for(int i = 0; i < values.length; i++){
int val = values[i][type.id];
- float cx = graphX + i * spacing, cy = graphY + val * graphH / maxY;
- Lines.linePoint(cx, cy);
+ float cx = graphX + (i+from) * spacing, cy = graphY + val * graphH / maxY;
+ linePoint(cx, cy);
}
- Lines.endLine();
+ endLine();
}
}else if(mode == Mode.totals){
- Lines.beginLine();
+ beginLine();
Draw.color(Pal.accent);
for(int i = 0; i < values.length; i++){
@@ -75,13 +146,13 @@ public class WaveGraph extends Table{
sum += values[i][type.id];
}
- float cx = graphX + i * spacing, cy = graphY + sum * graphH / maxY;
- Lines.linePoint(cx, cy);
+ float cx = graphX + (i+from) * spacing, cy = graphY + sum * graphH / maxY;
+ linePoint(cx, cy);
}
- Lines.endLine();
+ endLine();
}else if(mode == Mode.health){
- Lines.beginLine();
+ beginLine();
Draw.color(Pal.health);
for(int i = 0; i < values.length; i++){
@@ -90,13 +161,32 @@ public class WaveGraph extends Table{
sum += (type.health) * values[i][type.id];
}
- float cx = graphX + i * spacing, cy = graphY + sum * graphH / maxY;
- Lines.linePoint(cx, cy);
+ float cx = graphX + (i+from) * spacing, cy = graphY + sum * graphH / maxY;
+ linePoint(cx, cy);
}
- Lines.endLine();
+ endLine();
}
+
+ if(selcol >= 0 && selcol < values.length){
+ Draw.color(1f, 0f, 0f, 0.2f);
+ Fill.crect((selcol+from) * spacing + graphX - spacing/2f, graphY, spacing, graphH);
+ Draw.color();
+ font.getData().setScale(1.5f);
+ for(UnitType type : used.orderedItems()){
+ int amount = values[Mathf.clamp(selcol, 0, values.length - 1)][type.id];
+ if(amount > 0){
+ countStr.append(type.emoji()).append(" ").append(amount).append("\n");
+ }
+ }
+ float pad = Scl.scl(5f);
+ font.draw(countStr, (selcol+from) * spacing + graphX - spacing/2f + pad, graphY + graphH - pad);
+ font.getData().setScale(1f);
+ }
+
+ clipEnd();
+
//how many numbers can fit here
float totalMarks = Mathf.clamp(maxY, 1, 10);
@@ -106,13 +196,13 @@ public class WaveGraph extends Table{
Draw.alpha(0.1f);
for(int i = 0; i < maxY; i += markSpace){
- float cy = graphY + i * graphH / maxY, cx = graphX;
+ float cy = graphY + i * graphH / maxY, cx = x;
Lines.line(cx, cy, cx + graphW, cy);
lay.setText(font, "" + i);
- font.draw("" + i, cx, cy + lay.height / 2f, Align.right);
+ font.draw("" + i, cx, cy + lay.height / 2f, Align.left);
}
Draw.alpha(1f);
@@ -120,10 +210,12 @@ public class WaveGraph extends Table{
font.setColor(Color.lightGray);
for(int i = 0; i < values.length; i++){
- float cy = y + fh, cx = graphX + graphW / (values.length - 1) * i;
+ float cy = y + fh, cx = graphX + spacing * (i + from);
- Lines.line(cx, cy, cx, cy + len);
- if(i == values.length / 2){
+ if(cx >= x + offsetX && cx <= x + offsetX + graphW){
+ Lines.line(cx, cy, cx, cy + len);
+ }
+ if(i == selcol){
font.draw("" + (i + from + 1), cx, cy - Scl.scl(2f), Align.center);
}
}
@@ -152,6 +244,28 @@ public class WaveGraph extends Table{
}).growX();
}
+ private void clampZoom(){
+ zoom = Mathf.clamp(zoom, 0.5f / Scl.scl(1f), 40f / Scl.scl(1f));
+ }
+
+ private void linePoint(float x, float y){
+ points.add(x, y);
+ }
+
+ private void beginLine(){
+ points.clear();
+ }
+
+ private void endLine(){
+ var items = points.items;
+ for(int i = 0; i < points.size - 2; i += 2){
+ Lines.line(items[i], items[i + 1], items[i + 2], items[i + 3], false);
+ Fill.circle(items[i], items[i + 1], Lines.getStroke()/2f);
+ }
+ Fill.circle(items[points.size - 2], items[points.size - 1], Lines.getStroke());
+ points.clear();
+ }
+
public void rebuild(){
values = new int[to - from + 1][Vars.content.units().size];
used.clear();
@@ -177,6 +291,8 @@ public class WaveGraph extends Table{
maxHealth = Math.max(maxHealth, healthsum);
}
+ used.orderedItems().sort();
+
ObjectSet usedCopy = new ObjectSet<>(used);
colors.clear();
@@ -198,7 +314,7 @@ public class WaveGraph extends Table{
t.button(b -> {
Color tcolor = color(type).cpy();
b.image().size(32f).update(i -> i.setColor(b.isChecked() ? Tmp.c1.set(tcolor).mul(0.5f) : tcolor)).get().act(1);
- b.image(type.uiIcon).size(32f).padRight(20).update(i -> i.setColor(b.isChecked() ? Color.gray : Color.white)).get().act(1);
+ b.image(type.uiIcon).size(32f).scaling(Scaling.fit).padRight(20).update(i -> i.setColor(b.isChecked() ? Color.gray : Color.white)).get().act(1);
b.margin(0f);
}, Styles.fullTogglet, () -> {
if(!hidden.add(type)){
@@ -212,6 +328,8 @@ public class WaveGraph extends Table{
}
}).scrollY(false);
+ colors.act(0.000001f);
+
for(UnitType type : hidden){
used.remove(type);
}
diff --git a/core/src/mindustry/editor/WaveInfoDialog.java b/core/src/mindustry/editor/WaveInfoDialog.java
index d3f2e7ca6e..b4bc26acc2 100644
--- a/core/src/mindustry/editor/WaveInfoDialog.java
+++ b/core/src/mindustry/editor/WaveInfoDialog.java
@@ -27,7 +27,6 @@ import static mindustry.Vars.*;
import static mindustry.game.SpawnGroup.*;
public class WaveInfoDialog extends BaseDialog{
- private int start = 0, displayed = 20;
Seq groups = new Seq<>();
private @Nullable SpawnGroup expandedGroup;
@@ -36,7 +35,6 @@ public class WaveInfoDialog extends BaseDialog{
private @Nullable UnitType filterType;
private Sort sort = Sort.begin;
private boolean reverseSort = false;
- private float updateTimer, updatePeriod = 1f;
private boolean checkedSpawns;
private WaveGraph graph = new WaveGraph();
@@ -49,7 +47,6 @@ public class WaveInfoDialog extends BaseDialog{
});
hidden(() -> state.rules.spawns = groups);
- onResize(this::setup);
addCloseButton();
buttons.button("@waves.edit", Icon.edit, () -> {
@@ -71,7 +68,7 @@ public class WaveInfoDialog extends BaseDialog{
groups = maps.readWaves(Core.app.getClipboardText());
buildGroups();
}catch(Exception e){
- e.printStackTrace();
+ Log.err(e);
ui.showErrorMessage("@waves.invalid");
}
dialog.hide();
@@ -93,57 +90,11 @@ public class WaveInfoDialog extends BaseDialog{
dialog.show();
}).size(250f, 64f);
- buttons.defaults().width(60f);
-
- buttons.button("<", () -> {}).update(t -> {
- if(t.getClickListener().isPressed()){
- shift(-1);
- }
- });
- buttons.button(">", () -> {}).update(t -> {
- if(t.getClickListener().isPressed()){
- shift(1);
- }
- });
-
- buttons.button("-", () -> {}).update(t -> {
- if(t.getClickListener().isPressed()){
- view(-1);
- }
- });
- buttons.button("+", () -> {}).update(t -> {
- if(t.getClickListener().isPressed()){
- view(1);
- }
- });
-
- if(experimental){
- buttons.button(Core.bundle.get("waves.random"), Icon.refresh, () -> {
- groups.clear();
- groups = Waves.generate(1f / 10f);
- buildGroups();
- }).width(200f);
- }
- }
-
- void view(int amount){
- updateTimer += Time.delta;
- if(updateTimer >= updatePeriod){
- displayed += amount;
- if(displayed < 5) displayed = 5;
- updateTimer = 0f;
- updateWaves();
- }
- }
-
- void shift(int amount){
- updateTimer += Time.delta;
- if(updateTimer >= updatePeriod){
- start += amount;
- if(start < 0) start = 0;
- updateTimer = 0f;
- updateWaves();
- }
+ buttons.button(Core.bundle.get("waves.random"), Icon.refresh, () -> {
+ groups.clear();
+ groups = Waves.generate(1f / 10f);
+ buildGroups();
+ }).width(200f);
}
void setup(){
@@ -156,7 +107,6 @@ public class WaveInfoDialog extends BaseDialog{
s.image(Icon.zoom).padRight(8);
s.field(search < 0 ? "" : (search + 1) + "", TextFieldFilter.digitsOnly, text -> {
search = groups.any() ? Strings.parseInt(text, 0) - 1 : -1;
- start = Math.max(search - (displayed / 2) - (displayed % 2), 0);
buildGroups();
}).growX().maxTextLength(8).get().setMessageText("@waves.search");
s.button(Icon.units, Styles.emptyi, () -> showUnits(type -> filterType = type, true)).size(46f).tooltip("@waves.filter")
@@ -222,7 +172,7 @@ public class WaveInfoDialog extends BaseDialog{
t.button(b -> {
b.left();
b.image(group.type.uiIcon).size(32f).padRight(3).scaling(Scaling.fit);
- b.add(group.type.localizedName).color(Pal.accent);
+ b.add(group.type.localizedName).ellipsis(true).width(110f).left().color(Pal.accent);
b.add().growX();
@@ -493,8 +443,6 @@ public class WaveInfoDialog extends BaseDialog{
void updateWaves(){
graph.groups = groups;
- graph.from = start;
- graph.to = start + displayed;
graph.rebuild();
}
}
\ No newline at end of file
diff --git a/core/src/mindustry/entities/Damage.java b/core/src/mindustry/entities/Damage.java
index 988b92660e..7f13c16546 100644
--- a/core/src/mindustry/entities/Damage.java
+++ b/core/src/mindustry/entities/Damage.java
@@ -16,6 +16,8 @@ import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.*;
+import mindustry.world.blocks.*;
+import mindustry.world.meta.*;
import static mindustry.Vars.*;
@@ -101,9 +103,13 @@ public class Damage{
float damagePerWave = explosiveness / 2f;
for(int i = 0; i < waves; i++){
+ var shields = ignoreTeam == null ? null : indexer.getEnemy(ignoreTeam, BlockFlag.shield);
int f = i;
Time.run(i * 2f, () -> {
- damage(ignoreTeam, x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), damagePerWave, false);
+ if(shields == null || shields.isEmpty() || !shields.contains(b -> b instanceof ExplosionShield s && s.absorbExplosion(x, y, damagePerWave))){
+ damage(ignoreTeam, x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), damagePerWave, false);
+ }
+
Fx.blockExplosionSmoke.at(x + Mathf.range(radius), y + Mathf.range(radius));
});
}
@@ -166,7 +172,7 @@ public class Damage{
public static float findPierceLength(Bullet b, int pierceCap, float length){
return findPierceLength(b, pierceCap, b.type.laserAbsorb, length);
}
-
+
public static float findPierceLength(Bullet b, int pierceCap, boolean laser, float length){
vec.trnsExact(b.rotation(), length);
rect.setPosition(b.x, b.y).setSize(vec.x, vec.y).normalize().grow(3f);
@@ -358,7 +364,7 @@ public class Damage{
*/
public static Healthc linecast(Bullet hitter, float x, float y, float angle, float length){
vec.trns(angle, length);
-
+
tmpBuilding = null;
if(hitter.type.collidesGround){
@@ -644,7 +650,7 @@ public class Damage{
this.target = target;
return this;
}
-
+
@Override
public void reset(){
target = null;
diff --git a/core/src/mindustry/entities/Units.java b/core/src/mindustry/entities/Units.java
index 659112d57a..d334651092 100644
--- a/core/src/mindustry/entities/Units.java
+++ b/core/src/mindustry/entities/Units.java
@@ -83,6 +83,7 @@ public class Units{
@Remote(called = Loc.server)
public static void unitDespawn(Unit unit){
+ if(unit == null) return;
Fx.unitDespawn.at(unit.x, unit.y, 0, unit);
unit.remove();
}
@@ -94,7 +95,7 @@ public class Units{
public static int getCap(Team team){
//wave team has no cap
- if((team == state.rules.waveTeam && !state.rules.pvp) || (state.isCampaign() && team == state.rules.waveTeam)){
+ if((team == state.rules.waveTeam && !state.rules.pvp) || (state.isCampaign() && team == state.rules.waveTeam) || state.rules.disableUnitCap){
return Integer.MAX_VALUE;
}
return Math.max(0, state.rules.unitCapVariable ? state.rules.unitCap + team.data().unitCap : state.rules.unitCap);
@@ -111,6 +112,10 @@ public class Units{
return player == null || tile == null || tile.interactable(player.team()) || state.rules.editor;
}
+ public static boolean isHittable(@Nullable Posc target, boolean air, boolean ground){
+ return target != null && (target instanceof Buildingc ? ground : (target instanceof Unit u && u.checkTarget(air, ground)));
+ }
+
/**
* Validates a target.
* @param target The target to validate
@@ -474,7 +479,7 @@ public class Units{
Seq data = state.teams.present;
for(int i = 0; i < data.size; i++){
var other = data.items[i];
- if(other.team != team){
+ if(other.team != team && other.team != Team.derelict){
if(other.tree().any(x, y, width, height)){
return true;
}
diff --git a/core/src/mindustry/entities/abilities/Ability.java b/core/src/mindustry/entities/abilities/Ability.java
index 42a31d6312..d64a77ffea 100644
--- a/core/src/mindustry/entities/abilities/Ability.java
+++ b/core/src/mindustry/entities/abilities/Ability.java
@@ -15,6 +15,7 @@ public abstract class Ability implements Cloneable{
public void update(Unit unit){}
public void draw(Unit unit){}
public void death(Unit unit){}
+ public void created(Unit unit){}
public void init(UnitType type){}
public void displayBars(Unit unit, Table bars){}
public void addStats(Table t){
diff --git a/core/src/mindustry/entities/abilities/EnergyFieldAbility.java b/core/src/mindustry/entities/abilities/EnergyFieldAbility.java
index 8c041087c0..430ccd9d3c 100644
--- a/core/src/mindustry/entities/abilities/EnergyFieldAbility.java
+++ b/core/src/mindustry/entities/abilities/EnergyFieldAbility.java
@@ -14,6 +14,7 @@ import mindustry.game.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
+import mindustry.world.meta.*;
import static mindustry.Vars.*;
@@ -68,7 +69,7 @@ public class EnergyFieldAbility extends Ability{
t.add(Core.bundle.format("bullet.damage", damage));
if(status != StatusEffects.none){
t.row();
- t.add((status.hasEmoji() ? status.emoji() : "") + "[stat]" + status.localizedName);
+ t.add((status.hasEmoji() ? status.emoji() : "") + "[stat]" + status.localizedName).with(l -> StatValues.withTooltip(l, status));
}
if(displayHeal){
t.row();
@@ -135,7 +136,7 @@ public class EnergyFieldAbility extends Ability{
if(hitBuildings && targetGround){
Units.nearbyBuildings(rx, ry, range, b -> {
- if((b.team != Team.derelict || state.rules.coreCapture) && (b.team != unit.team || b.damaged())){
+ if((b.team != Team.derelict || state.rules.coreCapture) && ((b.team != unit.team && b.block.targetable) || b.damaged()) && !b.block.privileged){
all.add(b);
}
});
diff --git a/core/src/mindustry/entities/abilities/ForceFieldAbility.java b/core/src/mindustry/entities/abilities/ForceFieldAbility.java
index 504bf20681..d4cdac20d4 100644
--- a/core/src/mindustry/entities/abilities/ForceFieldAbility.java
+++ b/core/src/mindustry/entities/abilities/ForceFieldAbility.java
@@ -105,6 +105,15 @@ public class ForceFieldAbility extends Ability{
}
}
+ @Override
+ public void death(Unit unit){
+
+ //self-destructing units can have a shield on death
+ if(unit.shield > 0f && !wasBroken){
+ Fx.shieldBreak.at(unit.x, unit.y, radius, unit.type.shieldColor(unit), this);
+ }
+ }
+
@Override
public void draw(Unit unit){
checkRadius(unit);
@@ -131,6 +140,11 @@ public class ForceFieldAbility extends Ability{
bars.add(new Bar("stat.shieldhealth", Pal.accent, () -> unit.shield / max)).row();
}
+ @Override
+ public void created(Unit unit){
+ unit.shield = max;
+ }
+
public void checkRadius(Unit unit){
//timer2 is used to store radius scale as an effect
realRad = radiusScale * radius;
diff --git a/core/src/mindustry/entities/abilities/ShieldArcAbility.java b/core/src/mindustry/entities/abilities/ShieldArcAbility.java
index 820255f602..a4d60c3eec 100644
--- a/core/src/mindustry/entities/abilities/ShieldArcAbility.java
+++ b/core/src/mindustry/entities/abilities/ShieldArcAbility.java
@@ -11,7 +11,6 @@ import mindustry.*;
import mindustry.content.*;
import mindustry.gen.*;
import mindustry.graphics.*;
-import mindustry.type.*;
import mindustry.ui.*;
public class ShieldArcAbility extends Ability{
@@ -20,9 +19,9 @@ public class ShieldArcAbility extends Ability{
private static Vec2 paramPos = new Vec2();
private static final Cons shieldConsumer = b -> {
if(b.team != paramUnit.team && b.type.absorbable && paramField.data > 0 &&
- !b.within(paramPos, paramField.radius - paramField.width/2f) &&
- Tmp.v1.set(b).add(b.vel).within(paramPos, paramField.radius + paramField.width/2f) &&
- Angles.within(paramPos.angleTo(b), paramUnit.rotation + paramField.angleOffset, paramField.angle / 2f)){
+ !(b.within(paramPos, paramField.radius - paramField.width/2f) && paramPos.within(b.x - b.deltaX, b.y - b.deltaY, paramField.radius - paramField.width/2f)) &&
+ (Tmp.v1.set(b).add(b.deltaX, b.deltaY).within(paramPos, paramField.radius + paramField.width/2f) || b.within(paramPos, paramField.radius + paramField.width/2f)) &&
+ (Angles.within(paramPos.angleTo(b), paramUnit.rotation + paramField.angleOffset, paramField.angle / 2f) || Angles.within(paramPos.angleTo(b.x + b.deltaX, b.y + b.deltaY), paramUnit.rotation + paramField.angleOffset, paramField.angle / 2f))){
b.absorb();
Fx.absorb.at(b);
@@ -60,7 +59,7 @@ public class ShieldArcAbility extends Ability{
public boolean drawArc = true;
/** If not null, will be drawn on top. */
public @Nullable String region;
- /** Color override of the shield. Uses unit shield colour by default. */
+ /** Color override of the shield. Uses unit shield colour by default. */
public @Nullable Color color;
/** If true, sprite position will be influenced by x/y. */
public boolean offsetRegion = false;
@@ -80,7 +79,7 @@ public class ShieldArcAbility extends Ability{
@Override
public void update(Unit unit){
-
+
if(data < max){
data += Time.delta * regen;
}
@@ -102,7 +101,7 @@ public class ShieldArcAbility extends Ability{
}
@Override
- public void init(UnitType type){
+ public void created(Unit unit){
data = max;
}
diff --git a/core/src/mindustry/entities/abilities/ShieldRegenFieldAbility.java b/core/src/mindustry/entities/abilities/ShieldRegenFieldAbility.java
index 092222ec0d..fe7a3e68bb 100644
--- a/core/src/mindustry/entities/abilities/ShieldRegenFieldAbility.java
+++ b/core/src/mindustry/entities/abilities/ShieldRegenFieldAbility.java
@@ -34,6 +34,8 @@ public class ShieldRegenFieldAbility extends Ability{
t.row();
t.add(abilityStat("firingrate", Strings.autoFixed(60f / reload, 2)));
t.row();
+ t.add(abilityStat("pulseregen", Strings.autoFixed(amount, 2)));
+ t.row();
t.add(abilityStat("shield", Strings.autoFixed(max, 2)));
}
diff --git a/core/src/mindustry/entities/abilities/StatusFieldAbility.java b/core/src/mindustry/entities/abilities/StatusFieldAbility.java
index c0ca12d381..a70a382bf0 100644
--- a/core/src/mindustry/entities/abilities/StatusFieldAbility.java
+++ b/core/src/mindustry/entities/abilities/StatusFieldAbility.java
@@ -1,12 +1,14 @@
package mindustry.entities.abilities;
import arc.*;
+import arc.graphics.*;
import arc.math.*;
import arc.scene.ui.layout.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
+import mindustry.graphics.*;
import mindustry.type.*;
import static mindustry.Vars.*;
@@ -19,6 +21,7 @@ public class StatusFieldAbility extends Ability{
public Effect activeEffect = Fx.overdriveWave;
public float effectX, effectY;
public boolean parentizeEffects, effectSizeParam = true;
+ public Color color = Pal.accent;
protected float timer;
@@ -52,7 +55,7 @@ public class StatusFieldAbility extends Ability{
});
float x = unit.x + Angles.trnsx(unit.rotation, effectY, effectX), y = unit.y + Angles.trnsy(unit.rotation, effectY, effectX);
- activeEffect.at(x, y, effectSizeParam ? range : unit.rotation, parentizeEffects ? unit : null);
+ activeEffect.at(x, y, effectSizeParam ? range : unit.rotation, color, parentizeEffects ? unit : null);
timer = 0f;
}
diff --git a/core/src/mindustry/entities/bullet/ArtilleryBulletType.java b/core/src/mindustry/entities/bullet/ArtilleryBulletType.java
index 43a1b49466..69e6afbd97 100644
--- a/core/src/mindustry/entities/bullet/ArtilleryBulletType.java
+++ b/core/src/mindustry/entities/bullet/ArtilleryBulletType.java
@@ -52,7 +52,7 @@ public class ArtilleryBulletType extends BasicBulletType{
super.update(b);
if(b.timer(0, (3 + b.fslope() * 2f) * trailMult)){
- trailEffect.at(b.x, b.y, b.fslope() * trailSize, backColor);
+ trailEffect.at(b.x, b.y, trailRotation ? b.rotation() : b.fslope() * trailSize, backColor);
}
}
}
diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java
index 74fb8a7365..cb177512f0 100644
--- a/core/src/mindustry/entities/bullet/BulletType.java
+++ b/core/src/mindustry/entities/bullet/BulletType.java
@@ -102,6 +102,10 @@ public class BulletType extends Content implements Cloneable{
public StatusEffect status = StatusEffects.none;
/** Intensity of applied status effect in terms of duration. */
public float statusDuration = 60 * 8f;
+ /** Turret only. If false, blocks will not be targeted. */
+ public boolean targetBlocks = true;
+ /** Turret only. If false, missiles will not be targeted. */
+ public boolean targetMissiles = true;
/** Whether this bullet type collides with tiles. */
public boolean collidesTiles = true;
/** Whether this bullet type collides with tiles that are of the same team. */
@@ -137,6 +141,8 @@ public class BulletType extends Content implements Cloneable{
public float rangeOverride = -1f;
/** When used in a turret with multiple ammo types, this can be set to a non-zero value to influence range. */
public float rangeChange = 0f;
+ /** When used in turrets with limitRange() applied, this adds extra range to the bullets that extends past targeting range. Only particularly relevant in vanilla. */
+ public float extraRangeMargin = 0f;
/** Range initialized in init(). */
public float range = 0f;
/** % of block health healed **/
@@ -346,7 +352,7 @@ public class BulletType extends Content implements Cloneable{
return spawnUnit.estimateDps();
}
- float sum = damage * (pierce ? pierceCap == -1 ? 2 : Mathf.clamp(pierceCap, 1, 2) : 1f) * splashDamage*0.75f;
+ float sum = (damage + splashDamage*0.75f) * (pierce ? pierceCap == -1 ? 2 : Mathf.clamp(pierceCap, 1, 2) : 1f);
if(fragBullet != null && fragBullet != this){
sum += fragBullet.estimateDPS() * fragBullets / 2f;
}
@@ -521,7 +527,7 @@ public class BulletType extends Content implements Cloneable{
if(fragBullet != null && (fragOnAbsorb || !b.absorbed) && !(b.frags >= pierceFragCap && pierceFragCap > 0)){
for(int i = 0; i < fragBullets; i++){
float len = Mathf.random(fragOffsetMin, fragOffsetMax);
- float a = b.rotation() + Mathf.range(fragRandomSpread / 2) + fragAngle + ((i - fragBullets/2) * fragSpread);
+ float a = b.rotation() + Mathf.range(fragRandomSpread / 2) + fragAngle + fragSpread * i - (fragBullets - 1) * fragSpread / 2f;
fragBullet.create(b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax), Mathf.random(fragLifeMin, fragLifeMax));
}
b.frags++;
@@ -549,7 +555,7 @@ public class BulletType extends Content implements Cloneable{
if(!fragOnHit){
createFrags(b, b.x, b.y);
}
-
+
despawnEffect.at(b.x, b.y, b.rotation(), hitColor);
despawnSound.at(b);
@@ -675,7 +681,7 @@ public class BulletType extends Content implements Cloneable{
}
}
}
-
+
public void updateTrail(Bullet b){
if(!headless && trailLength > 0){
if(b.trail == null){
@@ -710,13 +716,16 @@ public class BulletType extends Content implements Cloneable{
}
if(lightningType == null){
- lightningType = !collidesAir ? Bullets.damageLightningGround : Bullets.damageLightning;
+ lightningType =
+ !collidesAir ? Bullets.damageLightningGround :
+ !collidesGround ? Bullets.damageLightningAir :
+ Bullets.damageLightning;
}
if(lightRadius <= -1){
lightRadius = Math.max(18, hitSize * 5f);
}
-
+
drawSize = Math.max(drawSize, trailLength * speed * 2f);
range = calculateRange();
}
@@ -748,15 +757,15 @@ public class BulletType extends Content implements Cloneable{
}
public @Nullable Bullet create(Bullet parent, float x, float y, float angle){
- return create(parent.owner, parent.team, x, y, angle);
+ return create(parent.owner, parent.shooter, parent.team, x, y, angle, -1, 1f, 1f, null, null, -1f, -1f);
}
public @Nullable Bullet create(Bullet parent, float x, float y, float angle, float velocityScl, float lifeScale){
- return create(parent.owner, parent.team, x, y, angle, velocityScl, lifeScale);
+ return create(parent.owner, parent.shooter, parent.team, x, y, angle, -1, velocityScl, lifeScale, null, null, -1f, -1f);
}
public @Nullable Bullet create(Bullet parent, float x, float y, float angle, float velocityScl){
- return create(parent.owner(), parent.team, x, y, angle, velocityScl);
+ return create(parent.owner, parent.shooter, parent.team, x, y, angle, -1, velocityScl, 1f, null, null, -1f, -1f);
}
public @Nullable Bullet create(@Nullable Entityc owner, Team team, float x, float y, float angle, float damage, float velocityScl, float lifetimeScl, Object data){
@@ -772,6 +781,13 @@ public class BulletType extends Content implements Cloneable{
}
public @Nullable Bullet create(@Nullable Entityc owner, @Nullable Entityc shooter, Team team, float x, float y, float angle, float damage, float velocityScl, float lifetimeScl, Object data, @Nullable Mover mover, float aimX, float aimY){
+ return create(owner, shooter, team, x, y, angle, damage, velocityScl, lifetimeScl, data, mover, aimX, aimY, null);
+ }
+
+ public @Nullable Bullet create(
+ @Nullable Entityc owner, @Nullable Entityc shooter, Team team, float x, float y, float angle, float damage, float velocityScl,
+ float lifetimeScl, Object data, @Nullable Mover mover, float aimX, float aimY, @Nullable Teamc target
+ ){
if(!Mathf.chance(createChance)) return null;
if(ignoreSpawnAngle) angle = 0;
if(spawnUnit != null){
@@ -807,12 +823,13 @@ public class BulletType extends Content implements Cloneable{
Bullet bullet = Bullet.create();
bullet.type = this;
bullet.owner = owner;
+ bullet.shooter = (shooter == null ? owner : shooter);
bullet.team = team;
bullet.time = 0f;
bullet.originX = x;
bullet.originY = y;
if(!(aimX == -1f && aimY == -1f)){
- bullet.aimTile = world.tileWorld(aimX, aimY);
+ bullet.aimTile = target instanceof Building b ? b.tile : world.tileWorld(aimX, aimY);
}
bullet.aimX = aimX;
bullet.aimY = aimY;
diff --git a/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java b/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java
index b8d6d029be..df7cebd304 100644
--- a/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java
+++ b/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java
@@ -37,6 +37,7 @@ public class ContinuousLaserBulletType extends ContinuousBulletType{
incendSpread = 5;
incendChance = 0.4f;
lightColor = Color.orange;
+ lightOpacity = 0.7f;
}
@Override
@@ -66,7 +67,7 @@ public class ContinuousLaserBulletType extends ContinuousBulletType{
Tmp.v1.trns(b.rotation(), realLength * 1.1f);
- Drawf.light(b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, lightStroke, lightColor, 0.7f);
+ Drawf.light(b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, lightStroke, lightColor, lightOpacity);
Draw.reset();
}
diff --git a/core/src/mindustry/entities/bullet/EmptyBulletType.java b/core/src/mindustry/entities/bullet/EmptyBulletType.java
new file mode 100644
index 0000000000..13dfd83ccc
--- /dev/null
+++ b/core/src/mindustry/entities/bullet/EmptyBulletType.java
@@ -0,0 +1,10 @@
+package mindustry.entities.bullet;
+
+public class EmptyBulletType extends BulletType{
+
+ public EmptyBulletType(){
+ hittable = collidesGround = collidesAir = collidesTiles = false;
+ speed = 0f;
+ keepVelocity = false;
+ }
+}
diff --git a/core/src/mindustry/entities/bullet/LightningBulletType.java b/core/src/mindustry/entities/bullet/LightningBulletType.java
index add245a16e..226d188f91 100644
--- a/core/src/mindustry/entities/bullet/LightningBulletType.java
+++ b/core/src/mindustry/entities/bullet/LightningBulletType.java
@@ -1,6 +1,5 @@
package mindustry.entities.bullet;
-import arc.graphics.*;
import arc.math.*;
import mindustry.content.*;
import mindustry.entities.*;
@@ -8,8 +7,6 @@ import mindustry.gen.*;
import mindustry.graphics.*;
public class LightningBulletType extends BulletType{
- public Color lightningColor = Pal.lancerLaser;
- public int lightningLength = 25, lightningLengthRand = 0;
public LightningBulletType(){
damage = 1f;
@@ -21,6 +18,9 @@ public class LightningBulletType extends BulletType{
hittable = false;
//for stats
status = StatusEffects.shocked;
+ lightningLength = 25;
+ lightningLengthRand = 0;
+ lightningColor = Pal.lancerLaser;
}
@Override
@@ -33,10 +33,6 @@ public class LightningBulletType extends BulletType{
return super.estimateDPS() * Math.max(lightningLength / 10f, 1);
}
- @Override
- public void draw(Bullet b){
- }
-
@Override
public void init(Bullet b){
super.init(b);
diff --git a/core/src/mindustry/entities/comp/BuilderComp.java b/core/src/mindustry/entities/comp/BuilderComp.java
index 794edf5d04..575d5ffc0b 100644
--- a/core/src/mindustry/entities/comp/BuilderComp.java
+++ b/core/src/mindustry/entities/comp/BuilderComp.java
@@ -1,7 +1,6 @@
package mindustry.entities.comp;
import arc.*;
-import arc.func.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
@@ -63,7 +62,7 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{
Tile tile = world.tile(plan.x, plan.y);
boolean isSameDerelict = (tile != null && tile.build != null && tile.block() == plan.block && tile.build.tileX() == plan.x && tile.build.tileY() == plan.y && tile.team() == Team.derelict);
if(tile == null || (plan.breaking && tile.block() == Blocks.air) || (!plan.breaking && ((tile.build != null && tile.build.rotation == plan.rotation && !isSameDerelict) || !plan.block.rotate) &&
- //th block must be the same, but not derelict and the same
+ //the block must be the same, but not derelict and the same
((tile.block() == plan.block && !isSameDerelict) ||
//same floor or overlay
(plan.block != null && (plan.block.isOverlay() && plan.block == tile.overlay() || (plan.block.isFloor() && plan.block == tile.floor())))))){
@@ -137,17 +136,31 @@ 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) ||
+ if(!current.initialized && !current.breaking && Build.validPlaceIgnoreUnits(current.block, team, current.x, current.y, current.rotation, true)){
+ if(Build.checkNoUnitOverlap(current.block, current.x, current.y)){
+ boolean hasAll = infinite || current.isRotation(team) ||
//derelict repair
(tile.team() == Team.derelict && tile.block() == current.block && tile.build != null && tile.block().allowDerelictRepair && state.rules.derelictRepair) ||
//make sure there's at least 1 item of each type first
- !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item, Math.min(Mathf.round(i.amount * state.rules.buildCostMultiplier), 1)));
+ !Structs.contains(current.block.requirements, i -> !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);
+ if(hasAll){
+ Call.beginPlace(self(), current.block, team, current.x, current.y, current.rotation);
+
+ if(current.block.instantBuild){
+ if(plans.size > 0){
+ plans.removeFirst();
+ }
+ continue;
+ }
+ }else{
+ current.stuck = true;
+ }
}else{
- current.stuck = true;
+ //there's a unit blocking the plan, skip it
+ plans.removeFirst();
+ plans.addLast(current);
+ continue;
}
}else if(!current.initialized && current.breaking && Build.validBreak(team, current.x, current.y)){
Call.beginBreak(self(), team, current.x, current.y);
@@ -186,11 +199,10 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{
/** Draw all current build plans. Does not draw the beam effect, only the positions. */
void drawBuildPlans(){
- Boolf skip = plan -> plan.progress > 0.01f || (buildPlan() == plan && plan.initialized && (within(plan.x * tilesize, plan.y * tilesize, type.buildRange) || state.isEditor()));
for(int i = 0; i < 2; i++){
for(BuildPlan plan : plans){
- if(skip.get(plan)) continue;
+ if(plan.progress > 0.01f || (buildPlan() == plan && plan.initialized && (within(plan.x * tilesize, plan.y * tilesize, type.buildRange) || state.isEditor()))) continue;
if(i == 0){
drawPlan(plan, 1f);
}else{
diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java
index 067ebd0afd..b5611ca178 100644
--- a/core/src/mindustry/entities/comp/BuildingComp.java
+++ b/core/src/mindustry/entities/comp/BuildingComp.java
@@ -338,7 +338,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
}
- data.plans.addFirst(new BlockPlan(tile.x, tile.y, (short)rotation, toAdd.id, overrideConfig == null ? config() : overrideConfig));
+ data.plans.addFirst(new BlockPlan(tile.x, tile.y, (short)rotation, toAdd, overrideConfig == null ? config() : overrideConfig));
}
public @Nullable Tile findClosestEdge(Position to, Boolf solid){
@@ -1217,6 +1217,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
public void payloadDraw(){
+ if(block.isAir()) return;
draw();
}
@@ -1370,6 +1371,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Called when the block is destroyed. The tile is still intact at this stage. */
public void onDestroyed(){
+ if(sound != null){
+ sound.stop();
+ }
+
float explosiveness = block.baseExplosiveness;
float flammability = 0f;
float power = 0f;
diff --git a/core/src/mindustry/entities/comp/BulletComp.java b/core/src/mindustry/entities/comp/BulletComp.java
index d9c3aef000..35916e43f9 100644
--- a/core/src/mindustry/entities/comp/BulletComp.java
+++ b/core/src/mindustry/entities/comp/BulletComp.java
@@ -39,6 +39,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
//setting this variable to true prevents lifetime from decreasing for a frame.
transient boolean keepAlive;
+ transient Entityc shooter;
transient @Nullable Tile aimTile;
transient float aimX, aimY;
transient float originX, originY;
@@ -248,7 +249,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
type.draw(self());
type.drawLight(self());
-
+
Draw.reset();
}
diff --git a/core/src/mindustry/entities/comp/HealthComp.java b/core/src/mindustry/entities/comp/HealthComp.java
index c06e6909e3..f315b3fb75 100644
--- a/core/src/mindustry/entities/comp/HealthComp.java
+++ b/core/src/mindustry/entities/comp/HealthComp.java
@@ -59,6 +59,8 @@ abstract class HealthComp implements Entityc, Posc{
}
void damage(float amount){
+ if(Float.isNaN(health)) health = 0f;
+
health -= amount;
hitTime = 1f;
if(health <= 0 && !dead){
@@ -86,6 +88,7 @@ abstract class HealthComp implements Entityc, Posc{
void clampHealth(){
health = Math.min(health, maxHealth);
+ if(Float.isNaN(health)) health = 0f;
}
/** Heals by a flat amount. */
diff --git a/core/src/mindustry/entities/comp/PayloadComp.java b/core/src/mindustry/entities/comp/PayloadComp.java
index 9b9d6e6405..223716d9bd 100644
--- a/core/src/mindustry/entities/comp/PayloadComp.java
+++ b/core/src/mindustry/entities/comp/PayloadComp.java
@@ -90,6 +90,8 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
}
void pickup(Unit unit){
+ if(unit.isAdded()) unit.team.data().updateCount(unit.type, 1);
+
unit.remove();
addPayload(new UnitPayload(unit));
Fx.unitPickup.at(unit);
@@ -129,7 +131,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
}
//drop off payload on an acceptor if possible
- if(on != null && on.build != null && on.build.acceptPayload(on.build, payload)){
+ if(on != null && on.build != null && on.build.team == team && on.build.acceptPayload(on.build, payload)){
Fx.unitDrop.at(on.build);
on.build.handlePayload(on.build, payload);
return true;
@@ -146,8 +148,12 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
boolean dropUnit(UnitPayload payload){
Unit u = payload.unit;
+ //add random offset to prevent unit stacking
+ Tmp.v1.rnd(Mathf.random(2f));
+
//can't drop ground units
- if(!u.canPass(tileX(), tileY()) || Units.count(x, y, u.physicSize(), o -> o.isGrounded()) > 1){
+ //allow stacking for small units for now - otherwise, unit transfer would get annoying
+ if(!u.canPass(World.toTile(x + Tmp.v1.x), World.toTile(y + Tmp.v1.y)) || Units.count(x, y, u.physicSize(), o -> o.isGrounded() && o.hitSize > 14f) > 1){
return false;
}
@@ -156,8 +162,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
//clients do not drop payloads
if(Vars.net.client()) return true;
- u.set(this);
- u.trns(Tmp.v1.rnd(Mathf.random(2f)));
+ u.set(x + Tmp.v1.x, y + Tmp.v1.y);
u.rotation(rotation);
//reset the ID to a new value to make sure it's synced
u.id = EntityGroup.nextId();
diff --git a/core/src/mindustry/entities/comp/ShieldComp.java b/core/src/mindustry/entities/comp/ShieldComp.java
index c290fa6251..f2f6e4c808 100644
--- a/core/src/mindustry/entities/comp/ShieldComp.java
+++ b/core/src/mindustry/entities/comp/ShieldComp.java
@@ -45,6 +45,8 @@ abstract class ShieldComp implements Healthc, Posc{
protected void rawDamage(float amount){
boolean hadShields = shield > 0.0001f;
+ if(Float.isNaN(health)) health = 0f;
+
if(hadShields){
shieldAlpha = 1f;
}
diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java
index ffa2bc3592..ef479e2956 100644
--- a/core/src/mindustry/entities/comp/UnitComp.java
+++ b/core/src/mindustry/entities/comp/UnitComp.java
@@ -25,8 +25,10 @@ import mindustry.logic.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
+import mindustry.world.blocks.*;
import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.payloads.*;
+import mindustry.world.meta.*;
import static mindustry.Vars.*;
import static mindustry.logic.GlobalVars.*;
@@ -443,6 +445,10 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
}
}
+ public boolean isMissile(){
+ return this instanceof TimedKillc;
+ }
+
public int count(){
return team.data().countType(type);
}
@@ -713,7 +719,11 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
//if this unit crash landed (was flying), damage stuff in a radius
if(type.flying && !spawnedByCore && type.createWreck && state.rules.unitCrashDamage(team) > 0){
- Damage.damage(team, x, y, Mathf.pow(hitSize, 0.94f) * 1.25f, Mathf.pow(hitSize, 0.75f) * type.crashDamageMultiplier * 5f * state.rules.unitCrashDamage(team), true, false, true);
+ var shields = indexer.getEnemy(team, BlockFlag.shield);
+ float crashDamage = Mathf.pow(hitSize, 0.75f) * type.crashDamageMultiplier * 5f * state.rules.unitCrashDamage(team);
+ if(shields.isEmpty() || !shields.contains(b -> b instanceof ExplosionShield s && s.absorbExplosion(x, y, crashDamage))){
+ Damage.damage(team, x, y, Mathf.pow(hitSize, 0.94f) * 1.25f, crashDamage, true, false, true);
+ }
}
if(!headless && type.createScorch){
diff --git a/core/src/mindustry/entities/part/DrawPart.java b/core/src/mindustry/entities/part/DrawPart.java
index a8642fe6d4..6e14ccb247 100644
--- a/core/src/mindustry/entities/part/DrawPart.java
+++ b/core/src/mindustry/entities/part/DrawPart.java
@@ -96,9 +96,13 @@ public abstract class DrawPart{
}
default float getClamp(PartParams p){
- return Mathf.clamp(get(p));
+ return getClamp(p, true);
}
-
+
+ default float getClamp(PartParams p, boolean clamp){
+ return clamp ? Mathf.clamp(get(p)) : get(p);
+ }
+
default PartProgress inv(){
return p -> 1f - get(p);
}
diff --git a/core/src/mindustry/entities/part/FlarePart.java b/core/src/mindustry/entities/part/FlarePart.java
index d07987d37e..ccf274a5b9 100644
--- a/core/src/mindustry/entities/part/FlarePart.java
+++ b/core/src/mindustry/entities/part/FlarePart.java
@@ -12,6 +12,7 @@ public class FlarePart extends DrawPart{
public float x, y, rotation, rotMove, spinSpeed;
public boolean followRotation;
public Color color1 = Pal.techBlue, color2 = Color.white;
+ public boolean clampProgress = true;
public PartProgress progress = PartProgress.warmup;
public float layer = Layer.effect;
@@ -20,7 +21,7 @@ public class FlarePart extends DrawPart{
float z = Draw.z();
if(layer > 0) Draw.z(layer);
- float prog = progress.getClamp(params);
+ float prog = progress.getClamp(params, clampProgress);
int i = params.sideOverride == -1 ? 0 : params.sideOverride;
float sign = (i == 0 ? 1 : -1) * params.sideMultiplier;
diff --git a/core/src/mindustry/entities/part/HaloPart.java b/core/src/mindustry/entities/part/HaloPart.java
index 0f5f4cafd0..7dc1dfcace 100644
--- a/core/src/mindustry/entities/part/HaloPart.java
+++ b/core/src/mindustry/entities/part/HaloPart.java
@@ -20,6 +20,7 @@ public class HaloPart extends DrawPart{
public Color color = Color.white;
public @Nullable Color colorTo;
public boolean mirror = false;
+ public boolean clampProgress = true;
public PartProgress progress = PartProgress.warmup;
public float layer = -1f, layerOffset = 0f;
@@ -32,7 +33,7 @@ public class HaloPart extends DrawPart{
Draw.z(Draw.z() + layerOffset);
float
- prog = progress.getClamp(params),
+ prog = progress.getClamp(params, clampProgress),
baseRot = Time.time * rotateSpeed,
rad = radiusTo < 0 ? radius : Mathf.lerp(radius, radiusTo, prog),
triLen = triLengthTo < 0 ? triLength : Mathf.lerp(triLength, triLengthTo, prog),
diff --git a/core/src/mindustry/entities/part/RegionPart.java b/core/src/mindustry/entities/part/RegionPart.java
index 0088e46f34..527ccae184 100644
--- a/core/src/mindustry/entities/part/RegionPart.java
+++ b/core/src/mindustry/entities/part/RegionPart.java
@@ -15,7 +15,7 @@ public class RegionPart extends DrawPart{
public String suffix = "";
/** Overrides suffix if set. */
public @Nullable String name;
- public TextureRegion heat;
+ public TextureRegion heat, light;
public TextureRegion[] regions = {};
public TextureRegion[] outlines = {};
@@ -27,6 +27,8 @@ public class RegionPart extends DrawPart{
public boolean drawRegion = true;
/** If true, the heat region produces light. */
public boolean heatLight = false;
+ /** Whether to clamp progress to (0-1). If false, allows usage of interps that go past the range, but may have unwanted visual bugs depending on values. */
+ public boolean clampProgress = true;
/** Progress function for determining position/rotation. */
public PartProgress progress = PartProgress.warmup;
/** Progress function for scaling. */
@@ -67,14 +69,14 @@ public class RegionPart extends DrawPart{
Draw.z(Draw.z() + layerOffset);
float prevZ = Draw.z();
- float prog = progress.getClamp(params), sclProg = growProgress.getClamp(params);
+ float prog = progress.getClamp(params, clampProgress), sclProg = growProgress.getClamp(params, clampProgress);
float mx = moveX * prog, my = moveY * prog, mr = moveRot * prog + rotation,
gx = growX * sclProg, gy = growY * sclProg;
if(moves.size > 0){
for(int i = 0; i < moves.size; i++){
var move = moves.get(i);
- float p = move.progress.getClamp(params);
+ float p = move.progress.getClamp(params, clampProgress);
mx += move.x * p;
my += move.y * p;
mr += move.rot * p;
@@ -130,10 +132,10 @@ public class RegionPart extends DrawPart{
}
if(heat.found()){
- float hprog = heatProgress.getClamp(params);
+ float hprog = heatProgress.getClamp(params, clampProgress);
heatColor.write(Tmp.c1).a(hprog * heatColor.a);
Drawf.additive(heat, Tmp.c1, rx, ry, rot, turretShading ? turretHeatLayer : Draw.z() + heatLayerOffset);
- if(heatLight) Drawf.light(rx, ry, heat, rot, Tmp.c1, heatLightOpacity * hprog);
+ if(heatLight) Drawf.light(rx, ry, light.found() ? light : heat, rot, Tmp.c1, heatLightOpacity * hprog);
}
Draw.xscl *= sign;
@@ -187,6 +189,7 @@ public class RegionPart extends DrawPart{
}
heat = Core.atlas.find(realName + "-heat");
+ light = Core.atlas.find(realName + "-light");
for(var child : children){
child.turretShading = turretShading;
child.load(name);
diff --git a/core/src/mindustry/entities/part/ShapePart.java b/core/src/mindustry/entities/part/ShapePart.java
index 7093c46b6b..dc8211fb26 100644
--- a/core/src/mindustry/entities/part/ShapePart.java
+++ b/core/src/mindustry/entities/part/ShapePart.java
@@ -15,6 +15,7 @@ public class ShapePart extends DrawPart{
public Color color = Color.white;
public @Nullable Color colorTo;
public boolean mirror = false;
+ public boolean clampProgress = true;
public PartProgress progress = PartProgress.warmup;
public float layer = -1f, layerOffset = 0f;
@@ -26,7 +27,7 @@ public class ShapePart extends DrawPart{
Draw.z(Draw.z() + layerOffset);
- float prog = progress.getClamp(params),
+ float prog = progress.getClamp(params, clampProgress),
baseRot = Time.time * rotateSpeed,
rad = radiusTo < 0 ? radius : Mathf.lerp(radius, radiusTo, prog),
str = strokeTo < 0 ? stroke : Mathf.lerp(stroke, strokeTo, prog);
diff --git a/core/src/mindustry/entities/units/AIController.java b/core/src/mindustry/entities/units/AIController.java
index 8adea77edb..f91b707699 100644
--- a/core/src/mindustry/entities/units/AIController.java
+++ b/core/src/mindustry/entities/units/AIController.java
@@ -4,7 +4,6 @@ import arc.math.*;
import arc.math.geom.*;
import arc.util.*;
import mindustry.*;
-import mindustry.ai.*;
import mindustry.entities.*;
import mindustry.game.*;
import mindustry.gen.*;
@@ -29,8 +28,12 @@ public class AIController implements UnitController{
protected Teamc target;
{
- timer.reset(0, Mathf.random(40f));
- timer.reset(1, Mathf.random(60f));
+ resetTimers();
+ }
+
+ protected void resetTimers(){
+ timer.reset(timerTarget, Mathf.random(40f));
+ timer.reset(timerTarget2, Mathf.random(60f));
}
@Override
@@ -127,7 +130,7 @@ public class AIController implements UnitController{
if(tile == null) return;
Tile targetTile = pathfinder.getTargetTile(tile, pathfinder.getField(unit.team, costType, pathTarget));
- if(tile == targetTile || (costType == Pathfinder.costNaval && !targetTile.floor().isLiquid)) return;
+ if(tile == targetTile || !unit.canPass(targetTile.x, targetTile.y)) return;
unit.movePref(vec.trns(unit.angleTo(targetTile.worldx(), targetTile.worldy()), prefSpeed()));
}
diff --git a/core/src/mindustry/entities/units/BuildPlan.java b/core/src/mindustry/entities/units/BuildPlan.java
index 5390f3451f..f9930f707f 100644
--- a/core/src/mindustry/entities/units/BuildPlan.java
+++ b/core/src/mindustry/entities/units/BuildPlan.java
@@ -4,6 +4,7 @@ import arc.func.*;
import arc.math.geom.*;
import arc.math.geom.QuadTree.*;
import arc.util.*;
+import mindustry.content.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.world.*;
@@ -64,7 +65,6 @@ public class BuildPlan implements Position, QuadTreeObject{
public BuildPlan(){
}
-
public boolean placeable(Team team){
return Build.validPlace(block, team, x, y, rotation);
}
@@ -152,6 +152,17 @@ public class BuildPlan implements Position, QuadTreeObject{
return y*tilesize + (block == null ? 0 : block.offset);
}
+ public boolean isDone(){
+ Tile tile = world.tile(x, y);
+ if(tile == null) return true;
+ Block tblock = tile.block();
+ if(breaking){
+ return tblock == Blocks.air || tblock == tile.floor();
+ }else{
+ return tblock == block && (tile.build == null || tile.build.rotation == rotation);
+ }
+ }
+
public @Nullable Tile tile(){
return world.tile(x, y);
}
diff --git a/core/src/mindustry/entities/units/UnitController.java b/core/src/mindustry/entities/units/UnitController.java
index b77a857a2f..240728b2cc 100644
--- a/core/src/mindustry/entities/units/UnitController.java
+++ b/core/src/mindustry/entities/units/UnitController.java
@@ -1,10 +1,11 @@
package mindustry.entities.units;
+import arc.util.*;
import mindustry.gen.*;
public interface UnitController{
void unit(Unit unit);
- Unit unit();
+ @Nullable Unit unit();
default void hit(Bullet bullet){
diff --git a/core/src/mindustry/game/CampaignRules.java b/core/src/mindustry/game/CampaignRules.java
new file mode 100644
index 0000000000..7ed813cab7
--- /dev/null
+++ b/core/src/mindustry/game/CampaignRules.java
@@ -0,0 +1,22 @@
+package mindustry.game;
+
+import mindustry.type.*;
+
+public class CampaignRules{
+ public Difficulty difficulty = Difficulty.normal;
+ public boolean fog;
+ public boolean showSpawns;
+ public boolean sectorInvasion;
+ public boolean randomWaveAI;
+
+ public void apply(Planet planet, Rules rules){
+ rules.staticFog = rules.fog = fog;
+ rules.showSpawns = showSpawns;
+ rules.randomWaveAI = randomWaveAI;
+ rules.objectiveTimerMultiplier = difficulty.waveTimeMultiplier;
+ rules.teams.get(rules.waveTeam).blockHealthMultiplier = difficulty.enemyHealthMultiplier;
+ rules.teams.get(rules.waveTeam).unitHealthMultiplier = difficulty.enemyHealthMultiplier;
+ rules.teams.get(rules.waveTeam).unitCostMultiplier = 1f / difficulty.enemySpawnMultiplier;
+ rules.teams.get(rules.waveTeam).unitBuildSpeedMultiplier = difficulty.enemySpawnMultiplier;
+ }
+}
diff --git a/core/src/mindustry/game/Difficulty.java b/core/src/mindustry/game/Difficulty.java
new file mode 100644
index 0000000000..fe657294ed
--- /dev/null
+++ b/core/src/mindustry/game/Difficulty.java
@@ -0,0 +1,27 @@
+package mindustry.game;
+
+import arc.*;
+
+public enum Difficulty{
+ //TODO these need tweaks
+ casual(0.75f, 0.5f, 2f),
+ easy(1f, 0.75f, 1.5f),
+ normal(1f, 1f, 1f),
+ hard(1.25f, 1.5f, 0.8f),
+ eradication(1.5f, 2f, 0.6f);
+
+ public static final Difficulty[] all = values();
+
+ //TODO add more fields
+ public float enemyHealthMultiplier, enemySpawnMultiplier, waveTimeMultiplier;
+
+ Difficulty(float enemyHealthMultiplier, float enemySpawnMultiplier, float waveTimeMultiplier){
+ this.enemySpawnMultiplier = enemySpawnMultiplier;
+ this.waveTimeMultiplier = waveTimeMultiplier;
+ this.enemyHealthMultiplier = enemyHealthMultiplier;
+ }
+
+ public String localized(){
+ return Core.bundle.get("difficulty." + name());
+ }
+}
diff --git a/core/src/mindustry/game/MapObjectives.java b/core/src/mindustry/game/MapObjectives.java
index d1ba8ffbc6..3a6f77e5ae 100644
--- a/core/src/mindustry/game/MapObjectives.java
+++ b/core/src/mindustry/game/MapObjectives.java
@@ -106,6 +106,13 @@ public class MapObjectives implements Iterable, Eachable all){
+ this.all.addAll(all);
+ }
+
+ public MapObjectives(){
+ }
+
/** Adds all given objectives to the executor as root objectives. */
public void add(MapObjective... objectives){
for(var objective : objectives) flatten(objective);
@@ -164,6 +171,7 @@ public class MapObjectives implements Iterable, Eachable, Eachable= duration;
+ return (countup += Time.delta) >= duration * state.rules.objectiveTimerMultiplier;
}
@Override
@@ -453,7 +461,7 @@ public class MapObjectives implements Iterable, Eachable, Eachable revealedBlocks = new ObjectSet<>();
/** Unlocked content names. Only used in multiplayer when the campaign is enabled. */
- public ObjectSet researched = new ObjectSet<>();
- /** Block containing these items as requirements are hidden. */
- public ObjectSet- hiddenBuildItems = Items.erekirOnlyItems.asSet();
+ public ObjectSet researched = new ObjectSet<>();
/** In-map objective executor. */
public MapObjectives objectives = new MapObjectives();
/** Flags set by objectives. Used in world processors. */
diff --git a/core/src/mindustry/game/Saves.java b/core/src/mindustry/game/Saves.java
index 6927813008..575c8bb697 100644
--- a/core/src/mindustry/game/Saves.java
+++ b/core/src/mindustry/game/Saves.java
@@ -111,7 +111,7 @@ public class Saves{
if(state.isGame() && !state.gameOver && current != null && current.isAutosave()){
time += Time.delta;
- if(time > Core.settings.getInt("saveinterval") * 60){
+ if(time > Core.settings.getInt("saveinterval") * 60 && !Vars.disableSave){
saving = true;
try{
diff --git a/core/src/mindustry/game/Schematics.java b/core/src/mindustry/game/Schematics.java
index 32b304f3e9..a54ddca43e 100644
--- a/core/src/mindustry/game/Schematics.java
+++ b/core/src/mindustry/game/Schematics.java
@@ -200,8 +200,7 @@ public class Schematics implements Loadable{
Seq keys = previews.orderedKeys().copy();
for(int i = 0; i < previews.size - maxPreviewsMobile; i++){
//dispose and remove unneeded previews
- previews.get(keys.get(i)).dispose();
- previews.remove(keys.get(i));
+ previews.remove(keys.get(i)).dispose();
}
//update last clear time
lastClearTime = Time.millis();
@@ -654,7 +653,7 @@ public class Schematics implements Loadable{
private static Schematic rotated(Schematic input, boolean counter){
int direction = Mathf.sign(counter);
- Schematic schem = input == tmpSchem ? tmpSchem2 : tmpSchem2;
+ Schematic schem = input == tmpSchem ? tmpSchem2 : tmpSchem;
schem.width = input.width;
schem.height = input.height;
Pools.freeAll(schem.tiles);
diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java
index c4ee046c6c..00ff253867 100644
--- a/core/src/mindustry/game/SectorInfo.java
+++ b/core/src/mindustry/game/SectorInfo.java
@@ -38,6 +38,8 @@ public class SectorInfo{
public int storageCapacity = 0;
/** Whether a core is available here. */
public boolean hasCore = true;
+ /** Whether a world processor is on this map - implies that the map will get cleared. */
+ public boolean hasWorldProcessor;
/** Whether this sector was ever fully captured. */
public boolean wasCaptured = false;
/** Sector that was launched from. */
@@ -82,7 +84,7 @@ public class SectorInfo{
public transient ItemSeq lastImported = new ItemSeq();
/** Special variables for simulation. */
- public float sumHealth, sumRps, sumDps, waveHealthBase, waveHealthSlope, waveDpsBase, waveDpsSlope, bossHealth, bossDps, curEnemyHealth, curEnemyDps;
+ public float sumHealth, sumRps, sumDps, bossHealth, bossDps, curEnemyHealth, curEnemyDps;
/** Wave where first boss shows up. */
public int bossWave = -1;
@@ -175,6 +177,7 @@ public class SectorInfo{
spawnPosition = entity.pos();
}
+ hasWorldProcessor = state.teams.present.contains(t -> t.getBuildings(Blocks.worldProcessor).any());
waveSpacing = state.rules.waveSpacing;
wave = state.wave;
winWave = state.rules.winWave;
diff --git a/core/src/mindustry/game/Teams.java b/core/src/mindustry/game/Teams.java
index 9fb472bf50..4597e5874e 100644
--- a/core/src/mindustry/game/Teams.java
+++ b/core/src/mindustry/game/Teams.java
@@ -8,6 +8,7 @@ import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.ai.*;
+import mindustry.annotations.Annotations.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.*;
@@ -239,6 +240,8 @@ public class Teams{
}
public static class TeamData{
+ private static final IntSeq derelictBuffer = new IntSeq();
+
public final Team team;
/** Handles building ""bases"". */
@@ -316,6 +319,8 @@ public class Teams{
}
}
+ finishScheduleDerelict();
+
//kill all units randomly
units.each(u -> Time.run(Mathf.random(0f, 60f * 5f), () -> {
//ensure unit hasn't switched teams for whatever reason
@@ -325,21 +330,7 @@ public class Teams{
}));
}
- /** Make all buildings within this range derelict / explode. */
- public void makeDerelict(float x, float y, float range){
- var builds = new Seq();
- if(buildingTree != null){
- buildingTree.intersect(x - range, y - range, range * 2f, range * 2f, builds);
- }
-
- for(var build : builds){
- if(build.within(x, y, range) && !build.block.privileged){
- scheduleDerelict(build);
- }
- }
- }
-
- /** Make all buildings within this range explode. */
+ /** Make all buildings within this range derelict/explode. */
public void timeDestroy(float x, float y, float range){
var builds = new Seq();
if(buildingTree != null){
@@ -347,23 +338,31 @@ public class Teams{
}
for(var build : builds){
- if(build.within(x, y, range) && !cores.contains(c -> c.within(build, range))){
- //TODO GPU driver bugs?
- build.kill();
- //Time.run(Mathf.random(0f, 60f * 6f), build::kill);
+ if(!build.block.privileged && build.within(x, y, range) && !cores.contains(c -> c.within(build, range))){
+ scheduleDerelict(build);
}
}
+ finishScheduleDerelict();
}
private void scheduleDerelict(Building build){
- //TODO this may cause a lot of packet spam, optimize?
- Call.setTeam(build, Team.derelict);
+ //queue block to be handled later, avoid packet spam
+ derelictBuffer.add(build.pos());
- if(Mathf.chance(0.25)){
+ if(build.getPayload() instanceof UnitPayload){
+ Call.destroyPayload(build);
+ }
+
+ if(Mathf.chance(0.2)){
Time.run(Mathf.random(0f, 60f * 6f), build::kill);
}
}
+ private void finishScheduleDerelict(){
+ derelictBuffer.chunked(1000, values -> Call.setTeams(values, Team.derelict));
+ derelictBuffer.clear();
+ }
+
//this is just an alias for consistency
@Nullable
public Seq getUnits(UnitType type){
@@ -425,14 +424,23 @@ public class Teams{
}
}
+ @Remote(called = Loc.server, unreliable = true)
+ public static void destroyPayload(Building build){
+ if(build != null && build.getPayload() instanceof UnitPayload && build.takePayload() instanceof UnitPayload unit){
+ unit.dump();
+ unit.unit.killed();
+ }
+ }
+
/** Represents a block made by this team that was destroyed somewhere on the map.
* This does not include deconstructed blocks.*/
public static class BlockPlan{
- public final short x, y, rotation, block;
+ public final short x, y, rotation;
+ public final Block block;
public final Object config;
public boolean removed;
- public BlockPlan(int x, int y, short rotation, short block, Object config){
+ public BlockPlan(int x, int y, short rotation, Block block, Object config){
this.x = (short)x;
this.y = (short)y;
this.rotation = rotation;
diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java
index 4aa77d8be7..a22d073f9d 100644
--- a/core/src/mindustry/game/Universe.java
+++ b/core/src/mindustry/game/Universe.java
@@ -252,7 +252,7 @@ public class Universe{
}
//queue random invasions
- if(!sector.isAttacked() && sector.planet.allowSectorInvasion && sector.info.minutesCaptured > invasionGracePeriod && sector.info.hasSpawns){
+ if(!sector.isAttacked() && sector.planet.campaignRules.sectorInvasion && sector.info.minutesCaptured > invasionGracePeriod && sector.info.hasSpawns){
int count = sector.near().count(s -> s.hasEnemyBase() && !s.hasBase());
//invasion chance depends on # of nearby bases
diff --git a/core/src/mindustry/graphics/BlockRenderer.java b/core/src/mindustry/graphics/BlockRenderer.java
index aec39b6661..10e29ef135 100644
--- a/core/src/mindustry/graphics/BlockRenderer.java
+++ b/core/src/mindustry/graphics/BlockRenderer.java
@@ -274,7 +274,7 @@ public class BlockRenderer{
if(brokenFade > 0.001f){
for(BlockPlan block : player.team().data().plans){
- Block b = content.block(block.block);
+ Block b = block.block;
if(!camera.bounds(Tmp.r1).grow(tilesize * 2f).overlaps(Tmp.r2.setSize(b.size * tilesize).setCenter(block.x * tilesize + b.offset, block.y * tilesize + b.offset))) continue;
Draw.alpha(0.33f * brokenFade);
diff --git a/core/src/mindustry/graphics/Drawf.java b/core/src/mindustry/graphics/Drawf.java
index db7db61dd5..497736e6c9 100644
--- a/core/src/mindustry/graphics/Drawf.java
+++ b/core/src/mindustry/graphics/Drawf.java
@@ -141,11 +141,18 @@ public class Drawf{
Draw.z(pz);
}
- public static void limitLine(Position start, Position dest, float len1, float len2){
+ public static void limitLine(Position start, Position dest, float len1, float len2, Color color){
+ if(start.within(dest, len1 + len2)){
+ return;
+ }
Tmp.v1.set(dest).sub(start).setLength(len1);
Tmp.v2.set(Tmp.v1).scl(-1f).setLength(len2);
- Drawf.line(Pal.accent, start.getX() + Tmp.v1.x, start.getY() + Tmp.v1.y, dest.getX() + Tmp.v2.x, dest.getY() + Tmp.v2.y);
+ Drawf.line(color, start.getX() + Tmp.v1.x, start.getY() + Tmp.v1.y, dest.getX() + Tmp.v2.x, dest.getY() + Tmp.v2.y);
+ }
+
+ public static void limitLine(Position start, Position dest, float len1, float len2){
+ limitLine(start, dest, len1, len2, Pal.accent);
}
public static void dashLineDst(Color color, float x, float y, float x2, float y2){
@@ -306,7 +313,7 @@ public class Drawf{
Draw.rect(region, x, y);
Draw.color();
}
-
+
public static void shadow(TextureRegion region, float x, float y, float width, float height, float rotation){
Draw.color(Pal.shadow);
Draw.rect(region, x, y, width, height, rotation);
@@ -354,13 +361,21 @@ public class Drawf{
}
public static void square(float x, float y, float radius, float rotation, Color color){
- Lines.stroke(3f, Pal.gray);
+ Lines.stroke(3f, Pal.gray.write(Tmp.c3).a(color.a));
Lines.square(x, y, radius + 1f, rotation);
Lines.stroke(1f, color);
Lines.square(x, y, radius + 1f, rotation);
Draw.reset();
}
+ public static void poly(float x, float y, int sides, float radius, float rotation, Color color){
+ Lines.stroke(3f, Pal.gray);
+ Lines.poly(x, y, sides, radius + 1f, rotation);
+ Lines.stroke(1f, color);
+ Lines.poly(x, y, sides, radius + 1f, rotation);
+ Draw.reset();
+ }
+
public static void square(float x, float y, float radius, float rotation){
square(x, y, radius, rotation, Pal.accent);
}
@@ -436,7 +451,7 @@ public class Drawf{
public static void construct(float x, float y, TextureRegion region, float rotation, float progress, float alpha, float time){
construct(x, y, region, Pal.accent, rotation, progress, alpha, time);
}
-
+
public static void construct(float x, float y, TextureRegion region, Color color, float rotation, float progress, float alpha, float time){
Shaders.build.region = region;
Shaders.build.progress = progress;
@@ -458,7 +473,7 @@ public class Drawf{
public static void construct(Building t, TextureRegion region, Color color, float rotation, float progress, float alpha, float time){
construct(t, region, color, rotation, progress, alpha, time, t.block.size * tilesize - 4f);
}
-
+
public static void construct(Building t, TextureRegion region, Color color, float rotation, float progress, float alpha, float time, float size){
Shaders.build.region = region;
Shaders.build.progress = progress;
@@ -477,7 +492,7 @@ public class Drawf{
Draw.reset();
}
-
+
/** Draws a sprite that should be light-wise correct, when rotated. Provided sprite must be symmetrical in shape. */
public static void spinSprite(TextureRegion region, float x, float y, float r){
float a = Draw.getColorAlpha();
diff --git a/core/src/mindustry/graphics/FogRenderer.java b/core/src/mindustry/graphics/FogRenderer.java
index da0212bd86..60807ed8cf 100644
--- a/core/src/mindustry/graphics/FogRenderer.java
+++ b/core/src/mindustry/graphics/FogRenderer.java
@@ -16,7 +16,6 @@ import mindustry.world.meta.*;
import static mindustry.Vars.*;
-/** Highly experimental fog-of-war renderer. */
public final class FogRenderer{
private FrameBuffer staticFog = new FrameBuffer(), dynamicFog = new FrameBuffer();
private LongSeq events = new LongSeq();
diff --git a/core/src/mindustry/graphics/MultiPacker.java b/core/src/mindustry/graphics/MultiPacker.java
index e5f473a765..42bc8d00d7 100644
--- a/core/src/mindustry/graphics/MultiPacker.java
+++ b/core/src/mindustry/graphics/MultiPacker.java
@@ -116,8 +116,7 @@ public class MultiPacker implements Disposable{
//main page can be massive, but 8192 throws GL_OUT_OF_MEMORY on some GPUs and I can't deal with it yet.
main(4096),
- //TODO stuff like this throws OOM on some devices
- environment(4096, 2048),
+ environment(4096),
ui(4096),
rubble(4096, 2048),
editor(4096, 2048);
diff --git a/core/src/mindustry/graphics/NvGpuInfo.java b/core/src/mindustry/graphics/NvGpuInfo.java
new file mode 100644
index 0000000000..f620680b03
--- /dev/null
+++ b/core/src/mindustry/graphics/NvGpuInfo.java
@@ -0,0 +1,28 @@
+package mindustry.graphics;
+
+import arc.*;
+import arc.graphics.*;
+
+/** Nvidia-specific utility class for querying GPU VRAM information. */
+public class NvGpuInfo{
+ private static final int GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX = 0x9048;
+ private static final int GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX = 0x9049;
+
+ private static boolean supported, initialized;
+
+ public static int getMaxMemoryKB(){
+ return hasMemoryInfo() ? Gl.getInt(GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX) : 0;
+ }
+
+ public static int getAvailableMemoryKB(){
+ return hasMemoryInfo() ? Gl.getInt(GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX) : 0;
+ }
+
+ public static boolean hasMemoryInfo(){
+ if(!initialized){
+ supported = Core.graphics.supportsExtension("GL_NVX_gpu_memory_info");
+ initialized = true;
+ }
+ return supported;
+ }
+}
\ No newline at end of file
diff --git a/core/src/mindustry/graphics/OverlayRenderer.java b/core/src/mindustry/graphics/OverlayRenderer.java
index 8346eb94d6..3aa4be1bf8 100644
--- a/core/src/mindustry/graphics/OverlayRenderer.java
+++ b/core/src/mindustry/graphics/OverlayRenderer.java
@@ -151,6 +151,7 @@ public class OverlayRenderer{
}
input.drawTop();
+ input.drawUnitSelection();
buildFade = Mathf.lerpDelta(buildFade, input.isPlacing() || input.isUsingSchematic() ? 1f : 0f, 0.06f);
diff --git a/core/src/mindustry/input/Binding.java b/core/src/mindustry/input/Binding.java
index 039829ebd4..d5c52930d3 100644
--- a/core/src/mindustry/input/Binding.java
+++ b/core/src/mindustry/input/Binding.java
@@ -60,6 +60,7 @@ public enum Binding implements KeyBind{
unit_command_load_units(KeyCode.unset),
unit_command_load_blocks(KeyCode.unset),
unit_command_unload_payload(KeyCode.unset),
+ unit_command_loop_payload(KeyCode.unset),
category_prev(KeyCode.comma, "blocks"),
category_next(KeyCode.period),
@@ -80,6 +81,7 @@ public enum Binding implements KeyBind{
block_select_10(KeyCode.num0),
zoom(new Axis(KeyCode.scroll), "view"),
+ detach_camera(KeyCode.unset),
menu(Vars.android ? KeyCode.back : KeyCode.escape),
fullscreen(KeyCode.f11),
pause(KeyCode.space),
diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java
index 1fc15522d1..78ac0604a7 100644
--- a/core/src/mindustry/input/DesktopInput.java
+++ b/core/src/mindustry/input/DesktopInput.java
@@ -56,6 +56,8 @@ public class DesktopInput extends InputHandler{
/** Time of most recent control group selection */
public long lastCtrlGroupSelectMillis;
+ private float buildPlanMouseOffsetX, buildPlanMouseOffsetY;
+
boolean showHint(){
return ui.hudfrag.shown && Core.settings.getBool("hints") && selectPlans.isEmpty() && !player.dead() &&
(!isBuilding && !Core.settings.getBool("buildautopause") || player.unit().isBuilding() || !player.dead() && !player.unit().spawnedByCore());
@@ -108,6 +110,10 @@ public class DesktopInput extends InputHandler{
@Override
public void drawTop(){
+ if(cursorType != SystemCursor.arrow && scene.hasMouse()){
+ graphics.cursor(cursorType = SystemCursor.arrow);
+ }
+
Lines.stroke(1f);
int cursorX = tileX(Core.input.mouseX());
int cursorY = tileY(Core.input.mouseY());
@@ -126,9 +132,6 @@ public class DesktopInput extends InputHandler{
}
}
-
- drawCommanded();
-
Draw.reset();
}
@@ -222,28 +225,46 @@ public class DesktopInput extends InputHandler{
boolean locked = locked();
boolean panCam = false;
float camSpeed = (!Core.input.keyDown(Binding.boost) ? panSpeed : panBoostSpeed) * Time.delta;
+ boolean detached = settings.getBool("detach-camera", false);
- if(input.keyDown(Binding.pan) && !scene.hasField() && !scene.hasDialog()){
- panCam = true;
- panning = true;
+ if(!scene.hasField() && !scene.hasDialog()){
+ if(input.keyTap(Binding.detach_camera)){
+ settings.put("detach-camera", detached = !detached);
+ if(!detached){
+ panning = false;
+ }
+ spectating = null;
+ }
+
+ if(input.keyDown(Binding.pan)){
+ panCam = true;
+ panning = true;
+ spectating = null;
+ }
+
+ if((Math.abs(Core.input.axis(Binding.move_x)) > 0 || Math.abs(Core.input.axis(Binding.move_y)) > 0 || input.keyDown(Binding.mouse_move))){
+ panning = false;
+ spectating = null;
+ }
}
- if((Math.abs(Core.input.axis(Binding.move_x)) > 0 || Math.abs(Core.input.axis(Binding.move_y)) > 0 || input.keyDown(Binding.mouse_move)) && (!scene.hasField())){
- panning = false;
- }
+ panning |= detached;
+
if(!locked){
- if(((player.dead() || state.isPaused()) && !ui.chatfrag.shown()) && !scene.hasField() && !scene.hasDialog()){
+ if(((player.dead() || state.isPaused() || detached) && !ui.chatfrag.shown()) && !scene.hasField() && !scene.hasDialog()){
if(input.keyDown(Binding.mouse_move)){
panCam = true;
}
Core.camera.position.add(Tmp.v1.setZero().add(Core.input.axis(Binding.move_x), Core.input.axis(Binding.move_y)).nor().scl(camSpeed));
- }else if(!player.dead() && !panning){
+ }else if((!player.dead() || spectating != null) && !panning){
//TODO do not pan
Team corePanTeam = state.won ? state.rules.waveTeam : player.team();
Position coreTarget = state.gameOver && !state.rules.pvp && corePanTeam.data().lastCore != null ? corePanTeam.data().lastCore : null;
- Core.camera.position.lerpDelta(coreTarget != null ? coreTarget : player, Core.settings.getBool("smoothcamera") ? 0.08f : 1f);
+ Position panTarget = coreTarget != null ? coreTarget : spectating != null ? spectating : player;
+
+ Core.camera.position.lerpDelta(panTarget, Core.settings.getBool("smoothcamera") ? 0.08f : 1f);
}
if(panCam){
@@ -446,12 +467,14 @@ public class DesktopInput extends InputHandler{
Tile cursor = tileAt(Core.input.mouseX(), Core.input.mouseY());
+ cursorType = SystemCursor.arrow;
+
if(cursor != null){
if(cursor.build != null && cursor.build.interactable(player.team())){
cursorType = cursor.build.getCursor();
}
- if(cursor.build != null && player.team() != Team.derelict && cursor.build.team == Team.derelict && Build.validPlace(cursor.block(), player.team(), cursor.build.tileX(), cursor.build.tileY(), cursor.build.rotation)){
+ if(canRepairDerelict(cursor)){
cursorType = ui.repairCursor;
}
@@ -498,9 +521,9 @@ public class DesktopInput extends InputHandler{
if(!Core.scene.hasMouse()){
Core.graphics.cursor(cursorType);
+ }else{
+ cursorType = SystemCursor.arrow;
}
-
- cursorType = SystemCursor.arrow;
}
@Override
@@ -521,8 +544,6 @@ public class DesktopInput extends InputHandler{
@Override
public void buildPlacementUI(Table table){
- table.image().color(Pal.gray).height(4f).colspan(4).growX();
- table.row();
table.left().margin(0f).defaults().size(48f).left();
table.button(Icon.paste, Styles.clearNonei, () -> {
@@ -622,11 +643,10 @@ public class DesktopInput extends InputHandler{
}
if(splan != null){
- float offset = ((splan.block.size + 2) % 2) * tilesize / 2f;
- float x = Core.input.mouseWorld().x + offset;
- float y = Core.input.mouseWorld().y + offset;
- splan.x = (int)(x / tilesize);
- splan.y = (int)(y / tilesize);
+ float x = Core.input.mouseWorld().x + buildPlanMouseOffsetX;
+ float y = Core.input.mouseWorld().y + buildPlanMouseOffsetY;
+ splan.x = Math.round(x / tilesize);
+ splan.y = Math.round(y / tilesize);
}
if(block == null || mode != placing){
@@ -657,6 +677,15 @@ public class DesktopInput extends InputHandler{
tappedOne = false;
BuildPlan plan = getPlan(cursorX, cursorY);
+ if(plan != null){
+ //move selected to front
+ int index = player.unit().plans.indexOf(plan, true);
+ if(index != -1){
+ player.unit().plans.removeIndex(index);
+ player.unit().plans.addFirst(plan);
+ }
+ }
+
if(Core.input.keyDown(Binding.break_block)){
mode = none;
}else if(!selectPlans.isEmpty()){
@@ -668,8 +697,10 @@ public class DesktopInput extends InputHandler{
lastLineY = cursorY;
mode = placing;
updateLine(selectX, selectY);
- }else if(plan != null && !plan.breaking && mode == none && !plan.initialized){
+ }else if(plan != null && !plan.breaking && mode == none && !plan.initialized && plan.progress <= 0f){
splan = plan;
+ buildPlanMouseOffsetX = splan.x * tilesize - Core.input.mouseWorld().x;
+ buildPlanMouseOffsetY = splan.y * tilesize - Core.input.mouseWorld().y;
}else if(plan != null && plan.breaking){
deleting = true;
}else if(commandMode){
@@ -754,6 +785,15 @@ public class DesktopInput extends InputHandler{
if(getPlan(splan.x, splan.y, splan.block.size, splan) != null){
player.unit().plans().remove(splan, true);
}
+
+ if(input.ctrl()){
+ inv.hide();
+ config.hideConfig();
+ planConfig.showConfig(splan);
+ }else{
+ planConfig.hide();
+ }
+
splan = null;
}
@@ -853,9 +893,20 @@ public class DesktopInput extends InputHandler{
float ya = Core.input.axis(Binding.move_y);
boolean boosted = (unit instanceof Mechc && unit.isFlying());
- movement.set(xa, ya).nor().scl(speed);
- if(Core.input.keyDown(Binding.mouse_move)){
- movement.add(input.mouseWorld().sub(player).scl(1f / 25f * speed)).limit(speed);
+ if(settings.getBool("detach-camera")){
+ Vec2 targetPos = camera.position;
+
+ movement.set(targetPos).sub(player).limit(speed);
+
+ if(player.within(targetPos, 15f)){
+ movement.setZero();
+ unit.vel.approachDelta(Vec2.ZERO, unit.speed() * unit.type().accel / 2f);
+ }
+ }else{
+ movement.set(xa, ya).nor().scl(speed);
+ if(Core.input.keyDown(Binding.mouse_move)){
+ movement.add(input.mouseWorld().sub(player).scl(1f / 25f * speed)).limit(speed);
+ }
}
float mouseAngle = Angles.mouseAngle(unit.x, unit.y);
diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java
index 49146f701c..0ec6712921 100644
--- a/core/src/mindustry/input/InputHandler.java
+++ b/core/src/mindustry/input/InputHandler.java
@@ -12,6 +12,7 @@ import arc.scene.*;
import arc.scene.event.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
+import arc.struct.Queue;
import arc.util.*;
import mindustry.*;
import mindustry.ai.*;
@@ -52,7 +53,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
/** Used for dropping items. */
final static float playerSelectRange = mobile ? 17f : 11f;
+ final static float unitSelectRadScl = 1f;
final static IntSeq removed = new IntSeq();
+ final static IntSet intSet = new IntSet();
/** Maximum line length. */
final static int maxLength = 100;
final static Rect r1 = new Rect(), r2 = new Rect();
@@ -96,6 +99,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public BuildPlan bplan = new BuildPlan();
public Seq linePlans = new Seq<>();
public Seq selectPlans = new Seq<>(BuildPlan.class);
+ public Queue lastPlans = new Queue<>();
+ public @Nullable Unit lastUnit;
+ public @Nullable Unit spectating;
//for RTS controls
public Seq selectedUnits = new Seq<>();
@@ -112,6 +118,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public final BlockInventoryFragment inv;
public final BlockConfigFragment config;
+ public final PlanConfigFragment planConfig;
private WidgetGroup group = new WidgetGroup();
@@ -132,6 +139,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
group.touchable = Touchable.childrenOnly;
inv = new BlockInventoryFragment();
config = new BlockConfigFragment();
+ planConfig = new PlanConfigFragment();
Events.on(UnitDestroyEvent.class, e -> {
if(e.unit != null && e.unit.isPlayer() && e.unit.getPlayer().isLocal() && e.unit.type.weapons.contains(w -> w.bullet.killShooter)){
@@ -147,6 +155,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
logicCutscene = false;
itemDepositCooldown = 0f;
Arrays.fill(controlGroups, null);
+ lastUnit = null;
+ lastPlans.clear();
});
}
@@ -793,7 +803,16 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
return !selectPlans.isEmpty();
}
+ public void spectate(Unit unit){
+ spectating = unit;
+ camera.position.set(unit);
+ }
+
public void update(){
+ if(spectating != null && (!spectating.isValid() || spectating.team != player.team())){
+ spectating = null;
+ }
+
if(logicCutscene && !renderer.isCutscene()){
Core.camera.position.lerpDelta(logicCamPan, logicCamSpeed);
}else{
@@ -808,6 +827,24 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
commandRect = false;
}
+ if(player.isBuilder()){
+ var playerPlans = player.unit().plans;
+ if(player.unit() != lastUnit && playerPlans.size <= 1){
+ playerPlans.ensureCapacity(lastPlans.size);
+ for(var plan : lastPlans){
+ playerPlans.addLast(plan);
+ }
+ }
+ if(lastPlans.size != playerPlans.size || (lastPlans.size > 0 && playerPlans.size > 0 && lastPlans.first() != playerPlans.first())){
+ lastPlans.clear();
+ for(var plan : playerPlans){
+ lastPlans.addLast(plan);
+ }
+ }
+ }
+
+ lastUnit = player.unit();
+
playerPlanTree.clear();
if(!player.dead()){
player.unit().plans.each(playerPlanTree::insert);
@@ -830,7 +867,6 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
//you don't want selected blocks while locked, looks weird
if(locked()){
block = null;
-
}
wasShooting = player.shooting;
@@ -1035,30 +1071,69 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
public void drawCommand(Unit sel){
- Drawf.square(sel.x, sel.y, sel.hitSize / 1.4f + Mathf.absin(4f, 1f), selectedUnits.contains(sel) ? Pal.remove : Pal.accent);
+ Drawf.poly(sel.x, sel.y, 6, sel.hitSize / unitSelectRadScl + Mathf.absin(4f, 1f), 0f, selectedUnits.contains(sel) ? Pal.remove : Pal.accent);
}
public void drawCommanded(){
+ Draw.draw(Layer.plans, () -> {
+ drawCommanded(true);
+ });
+
+ Draw.draw(Layer.groundUnit - 1, () -> {
+ drawCommanded(false);
+ });
+ }
+
+ public void drawCommanded(boolean flying){
+ float lineLimit = 6.5f;
+ Color color = Pal.accent;
+ int sides = 6;
+ float alpha = 0.5f;
+
if(commandMode){
//happens sometimes
selectedUnits.removeAll(u -> !u.isCommandable());
//draw command overlay UI
for(Unit unit : selectedUnits){
+ if(unit.isFlying() != flying) continue;
CommandAI ai = unit.command();
Position lastPos = ai.attackTarget != null ? ai.attackTarget : ai.targetPos;
//draw target line
if(ai.targetPos != null && ai.currentCommand().drawTarget){
Position lineDest = ai.attackTarget != null ? ai.attackTarget : ai.targetPos;
- Drawf.limitLine(unit, lineDest, unit.hitSize / 2f, 3.5f);
+ Drawf.limitLine(unit, lineDest, unit.hitSize / unitSelectRadScl + 1f, lineLimit, color.write(Tmp.c1).a(alpha));
if(ai.attackTarget == null){
- Drawf.square(lineDest.getX(), lineDest.getY(), 3.5f);
+ Drawf.square(lineDest.getX(), lineDest.getY(), 3.5f, color.write(Tmp.c1).a(alpha));
+
+ if(ai.currentCommand() == UnitCommand.enterPayloadCommand){
+ var build = world.buildWorld(lineDest.getX(), lineDest.getY());
+ if(build != null && build.block.acceptsUnitPayloads && build.team == unit.team){
+ Drawf.selected(build, color);
+ }
+ }
}
}
- Drawf.square(unit.x, unit.y, unit.hitSize / 1.4f + 1f);
+ float rad = unit.hitSize / unitSelectRadScl + 1f;
+
+ Fill.lightInner(unit.x, unit.y, sides,
+ Math.max(0f, rad * 0.8f),
+ rad,
+ 0f,
+ Tmp.c3.set(color).a(0f),
+ Tmp.c2.set(color).a(0.7f)
+ );
+
+ Lines.stroke(1f);
+ Draw.color(color);
+ Lines.poly(unit.x, unit.y, sides, rad + 0.5f);
+ //uncomment for a dark border
+ //Draw.color(Pal.gray);
+ //Lines.poly(unit.x, unit.y, sides, rad + 1.5f);
+ Draw.reset();
if(ai.attackTarget != null && ai.currentCommand().drawTarget){
Drawf.target(ai.attackTarget.getX(), ai.attackTarget.getY(), 6f, Pal.remove);
@@ -1071,54 +1146,72 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
//draw command queue
if(ai.currentCommand().drawTarget && ai.commandQueue.size > 0){
for(var next : ai.commandQueue){
- Drawf.limitLine(lastPos, next, 3.5f, 3.5f);
+ Drawf.limitLine(lastPos, next, lineLimit, lineLimit, color.write(Tmp.c1).a(alpha));
lastPos = next;
if(next instanceof Vec2 vec){
- Drawf.square(vec.x, vec.y, 3.5f);
+ Drawf.square(vec.x, vec.y, 3.5f, color.write(Tmp.c1).a(alpha));
}else{
Drawf.target(next.getX(), next.getY(), 6f, Pal.remove);
}
}
}
+
+ if(ai.targetPos != null && ai.currentCommand() == UnitCommand.loopPayloadCommand && unit instanceof Payloadc pay){
+ Draw.color(color, 0.4f + Mathf.absin(5f, 0.5f));
+ TextureRegion region = pay.hasPayload() ? Icon.download.getRegion() : Icon.upload.getRegion();
+ float offset = 11f;
+ float size = 8f;
+ Draw.rect(region, ai.targetPos.x, ai.targetPos.y + offset, size, size / region.ratio());
+
+ if(ai.commandQueue.size > 0){
+ region = !pay.hasPayload() ? Icon.download.getRegion() : Icon.upload.getRegion();
+ Draw.rect(region, ai.commandQueue.first().getX(), ai.commandQueue.first().getY() + offset, size, size / region.ratio());
+ }
+ Draw.color();
+ }
}
- for(var commandBuild : commandBuildings){
- if(commandBuild != null){
- Drawf.square(commandBuild.x, commandBuild.y, commandBuild.hitSize() / 1.4f + 1f);
- var cpos = commandBuild.getCommandPosition();
+ if(flying){
+ for(var commandBuild : commandBuildings){
+ if(commandBuild != null){
+ Drawf.square(commandBuild.x, commandBuild.y, commandBuild.hitSize() / 1.4f + 1f);
+ var cpos = commandBuild.getCommandPosition();
- if(cpos != null){
- Drawf.limitLine(commandBuild, cpos, commandBuild.hitSize() / 2f, 3.5f);
- Drawf.square(cpos.x, cpos.y, 3.5f);
+ if(cpos != null){
+ Drawf.limitLine(commandBuild, cpos, commandBuild.hitSize() / 2f, lineLimit, color.write(Tmp.c1).a(alpha));
+ Drawf.square(cpos.x, cpos.y, 3.5f, color.write(Tmp.c1).a(alpha));
+ }
}
}
}
-
- if(commandMode && !commandRect){
- Unit sel = selectedCommandUnit(input.mouseWorldX(), input.mouseWorldY());
-
- if(sel != null && !(!multiUnitSelect() && selectedUnits.size == 1 && selectedUnits.contains(sel))){
- drawCommand(sel);
- }
- }
-
- if(commandRect){
- float x2 = input.mouseWorldX(), y2 = input.mouseWorldY();
- var units = selectedCommandUnits(commandRectX, commandRectY, x2 - commandRectX, y2 - commandRectY);
- for(var unit : units){
- drawCommand(unit);
- }
-
- Draw.color(Pal.accent, 0.3f);
- Fill.crect(commandRectX, commandRectY, x2 - commandRectX, y2 - commandRectY);
- }
}
Draw.reset();
}
+ public void drawUnitSelection(){
+ if(commandRect && commandMode){
+ float x2 = input.mouseWorldX(), y2 = input.mouseWorldY();
+ var units = selectedCommandUnits(commandRectX, commandRectY, x2 - commandRectX, y2 - commandRectY);
+ for(var unit : units){
+ drawCommand(unit);
+ }
+
+ Draw.color(Pal.accent, 0.3f);
+ Fill.crect(commandRectX, commandRectY, x2 - commandRectX, y2 - commandRectY);
+ }
+
+ if(commandMode && !commandRect){
+ Unit sel = selectedCommandUnit(input.mouseWorldX(), input.mouseWorldY());
+
+ if(sel != null && !(!multiUnitSelect() && selectedUnits.size == 1 && selectedUnits.contains(sel))){
+ drawCommand(sel);
+ }
+ }
+ }
+
public void drawBottom(){
}
@@ -1348,9 +1441,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
for(BlockPlan plan : player.team().data().plans){
- Block block = content.block(plan.block);
+ Block block = plan.block;
if(block.bounds(plan.x, plan.y, Tmp.r2).overlaps(Tmp.r1)){
- drawSelected(plan.x, plan.y, content.block(plan.block), Pal.remove);
+ drawSelected(plan.x, plan.y, plan.block, Pal.remove);
}
}
@@ -1362,17 +1455,31 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
Lines.rect(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
}
- protected void drawRebuildSelection(int x, int y, int x2, int y2){
- drawSelection(x, y, x2, y2, 0, Pal.sapBulletBack, Pal.sapBullet);
+ protected void drawRebuildSelection(int x1, int y1, int x2, int y2){
+ drawSelection(x1, y1, x2, y2, 0, Pal.sapBulletBack, Pal.sapBullet);
- NormalizeDrawResult result = Placement.normalizeDrawArea(Blocks.air, x, y, x2, y2, false, 0, 1f);
+ NormalizeDrawResult result = Placement.normalizeDrawArea(Blocks.air, x1, y1, x2, y2, false, 0, 1f);
Tmp.r1.set(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
for(BlockPlan plan : player.team().data().plans){
- Block block = content.block(plan.block);
+ Block block = plan.block;
if(block.bounds(plan.x, plan.y, Tmp.r2).overlaps(Tmp.r1)){
- drawSelected(plan.x, plan.y, content.block(plan.block), Pal.sapBullet);
+ drawSelected(plan.x, plan.y, plan.block, Pal.sapBullet);
+ }
+ }
+
+ NormalizeResult dresult = Placement.normalizeArea(x1, y1, x2, y2, rotation, false, 999999999);
+
+ intSet.clear();
+ for(int x = dresult.x; x <= dresult.x2; x++){
+ for(int y = dresult.y; y <= dresult.y2; y++){
+
+ Tile tile = world.tileBuilding(x, y);
+
+ if(tile != null && intSet.add(tile.pos()) && canRepairDerelict(tile)){
+ drawSelected(tile.x, tile.y, tile.block(), Pal.sapBullet);
+ }
}
}
}
@@ -1398,7 +1505,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
protected void flushSelectPlans(Seq plans){
for(BuildPlan plan : plans){
- if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation)){
+ if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation, null, true)){
BuildPlan other = getPlan(plan.x, plan.y, plan.block.size, null);
if(other == null){
selectPlans.add(plan.copy());
@@ -1414,7 +1521,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
//reversed iteration.
for(int i = plans.size - 1; i >= 0; i--){
var plan = plans.get(i);
- if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation)){
+ if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation, null, true)){
BuildPlan copy = plan.copy();
plan.block.onNewPlan(copy);
player.unit().addBuild(copy, false);
@@ -1424,7 +1531,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
protected void flushPlans(Seq plans){
for(var plan : plans){
- if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation)){
+ if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation, null, true)){
BuildPlan copy = plan.copy();
plan.block.onNewPlan(copy);
player.unit().addBuild(copy);
@@ -1522,7 +1629,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
Iterator broken = player.team().data().plans.iterator();
while(broken.hasNext()){
BlockPlan plan = broken.next();
- Block block = content.block(plan.block);
+ Block block = plan.block;
if(block.bounds(plan.x, plan.y, Tmp.r2).overlaps(Tmp.r1)){
removed.add(Point2.pack(plan.x, plan.y));
plan.removed = true;
@@ -1567,6 +1674,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
/** Handles tile tap events that are not platform specific. */
boolean tileTapped(@Nullable Building build){
+ planConfig.hide();
if(build == null){
inv.hide();
config.hideConfig();
@@ -1638,7 +1746,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
/** Tries to begin mining a tile, returns true if successful. */
boolean tryBeginMine(Tile tile){
- if(canMine(tile)){
+ if(!player.dead() && canMine(tile)){
player.unit().mineTile = tile;
return true;
}
@@ -1647,7 +1755,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
/** Tries to stop mining, returns true if mining was stopped. */
boolean tryStopMine(){
- if(player.unit().mining()){
+ if(!player.dead() && player.unit().mining()){
player.unit().mineTile = null;
return true;
}
@@ -1655,7 +1763,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
boolean tryStopMine(Tile tile){
- if(player.unit().mineTile == tile){
+ if(!player.dead() && player.unit().mineTile == tile){
player.unit().mineTile = null;
return true;
}
@@ -1663,13 +1771,20 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
boolean tryRepairDerelict(Tile selected){
- if(selected != null && player.team() != Team.derelict && selected.build != null && selected.build.block.unlockedNow() && selected.build.team == Team.derelict && Build.validPlace(selected.block(), player.team(), selected.build.tileX(), selected.build.tileY(), selected.build.rotation)){
+ if(selected != null && !state.rules.editor && player.team() != Team.derelict && selected.build != null && selected.build.block.unlockedNow() && selected.build.team == Team.derelict &&
+ Build.validPlace(selected.block(), player.team(), selected.build.tileX(), selected.build.tileY(), selected.build.rotation)){
+
player.unit().addBuild(new BuildPlan(selected.build.tileX(), selected.build.tileY(), selected.build.rotation, selected.block(), selected.build.config()));
return true;
}
return false;
}
+ boolean canRepairDerelict(Tile tile){
+ return tile != null && tile.build != null && !state.rules.editor && player.team() != Team.derelict && tile.build.team == Team.derelict && tile.build.block.unlockedNowHost() &&
+ Build.validPlace(tile.block(), player.team(), tile.build.tileX(), tile.build.tileY(), tile.build.rotation);
+ }
+
boolean canMine(Tile tile){
return !Core.scene.hasMouse()
&& player.unit().validMine(tile)
@@ -1835,6 +1950,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
inv.build(group);
config.build(group);
+ planConfig.build(group);
}
}
@@ -1877,16 +1993,28 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
}
- public void rebuildArea(int x, int y, int x2, int y2){
- NormalizeResult result = Placement.normalizeArea(x, y, x2, y2, rotation, false, 999999999);
+ public void rebuildArea(int x1, int y1, int x2, int y2){
+ NormalizeResult result = Placement.normalizeArea(x1, y1, x2, y2, rotation, false, 999999999);
Tmp.r1.set(result.x * tilesize, result.y * tilesize, (result.x2 - result.x) * tilesize, (result.y2 - result.y) * tilesize);
Iterator broken = player.team().data().plans.iterator();
while(broken.hasNext()){
BlockPlan plan = broken.next();
- Block block = content.block(plan.block);
+ Block block = plan.block;
if(block.bounds(plan.x, plan.y, Tmp.r2).overlaps(Tmp.r1)){
- player.unit().addBuild(new BuildPlan(plan.x, plan.y, plan.rotation, content.block(plan.block), plan.config));
+ player.unit().addBuild(new BuildPlan(plan.x, plan.y, plan.rotation, plan.block, plan.config));
+ }
+ }
+
+ intSet.clear();
+ for(int x = result.x; x <= result.x2; x++){
+ for(int y = result.y; y <= result.y2; y++){
+
+ Tile tile = world.tileBuilding(x, y);
+
+ if(tile != null && tile.build != null && intSet.add(tile.pos())){
+ tryRepairDerelict(tile);
+ }
}
}
}
@@ -1900,9 +2028,12 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public boolean validPlace(int x, int y, Block type, int rotation){
return validPlace(x, y, type, rotation, null);
}
+ public boolean validPlace(int x, int y, Block type, int rotation, @Nullable BuildPlan ignore){
+ return validPlace(x, y, type, rotation, ignore, false);
+ }
- public boolean validPlace(int x, int y, Block type, int rotation, BuildPlan ignore){
- if(player.unit().plans.size > 0){
+ public boolean validPlace(int x, int y, Block type, int rotation, @Nullable BuildPlan ignore, boolean ignoreUnits){
+ if(player.isBuilder() && player.unit().plans.size > 0){
Tmp.r1.setCentered(x * tilesize + type.offset, y * tilesize + type.offset, type.size * tilesize);
plansOut.clear();
playerPlanTree.intersect(Tmp.r1, plansOut);
@@ -1918,7 +2049,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
}
- return Build.validPlace(type, player.team(), x, y, rotation);
+ return ignoreUnits ? Build.validPlaceIgnoreUnits(type, player.team(), x, y, rotation, true) : Build.validPlace(type, player.team(), x, y, rotation);
}
public boolean validBreak(int x, int y){
@@ -1926,6 +2057,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
public void breakBlock(int x, int y){
+ if(!player.isBuilder()) return;
+
Tile tile = world.tile(x, y);
if(tile != null && tile.build != null) tile = tile.build.tile;
player.unit().addBuild(new BuildPlan(tile.x, tile.y));
diff --git a/core/src/mindustry/input/MobileInput.java b/core/src/mindustry/input/MobileInput.java
index ce16f8d915..20490ccd5c 100644
--- a/core/src/mindustry/input/MobileInput.java
+++ b/core/src/mindustry/input/MobileInput.java
@@ -88,9 +88,11 @@ public class MobileInput extends InputHandler implements GestureListener{
/** Check and assign targets for a specific position. */
void checkTargets(float x, float y){
+ if(player.dead()) return;
+
Unit unit = Units.closestEnemy(player.team(), x, y, 20f, u -> !u.dead);
- if(unit != null && !player.dead() && player.unit().type.canAttack){
+ if(unit != null && player.unit().type.canAttack){
player.unit().mineTile = null;
target = unit;
}else{
@@ -188,8 +190,6 @@ public class MobileInput extends InputHandler implements GestureListener{
@Override
public void buildPlacementUI(Table table){
- table.image().color(Pal.gray).height(4f).colspan(4).growX();
- table.row();
table.left().margin(0f).defaults().size(48f);
table.button(Icon.hammer, Styles.clearNoneTogglei, () -> {
@@ -234,7 +234,7 @@ public class MobileInput extends InputHandler implements GestureListener{
//actually place/break all selected blocks
if(tile != null){
if(!plan.breaking){
- if(validPlace(plan.x, plan.y, plan.block, plan.rotation)){
+ if(validPlace(plan.x, plan.y, plan.block, plan.rotation, null, true)){
BuildPlan other = getPlan(plan.x, plan.y, plan.block.size, null);
BuildPlan copy = plan.copy();
@@ -265,11 +265,11 @@ public class MobileInput extends InputHandler implements GestureListener{
}).name("confirmplace");
}
- boolean showCancel(){
- return !player.dead() && (player.unit().isBuilding() || block != null || mode == breaking || !selectPlans.isEmpty()) && !hasSchem();
+ public boolean showCancel(){
+ return !player.dead() && (player.unit().isBuilding() || block != null || mode == breaking || !selectPlans.isEmpty()) && !hasSchematic();
}
- boolean hasSchem(){
+ public boolean hasSchematic(){
return lastSchematic != null && !selectPlans.isEmpty();
}
@@ -290,7 +290,7 @@ public class MobileInput extends InputHandler implements GestureListener{
});
group.fill(t -> {
- t.visible(() -> !showCancel() && block == null && !hasSchem());
+ t.visible(() -> !showCancel() && block == null && !hasSchematic() && !state.rules.editor);
t.bottom().left();
t.button("@command.queue", Icon.rightOpen, Styles.clearTogglet, () -> {
@@ -310,7 +310,7 @@ public class MobileInput extends InputHandler implements GestureListener{
});
group.fill(t -> {
- t.visible(this::hasSchem);
+ t.visible(this::hasSchematic);
t.bottom().left();
t.table(Tex.pane, b -> {
b.defaults().size(50f);
@@ -391,8 +391,6 @@ public class MobileInput extends InputHandler implements GestureListener{
}else if(mode == rebuildSelect){
drawRebuildSelection(lineStartX, lineStartY, lastLineX, lastLineY);
}
-
- drawCommanded();
}
@Override
@@ -759,7 +757,7 @@ public class MobileInput extends InputHandler implements GestureListener{
payloadTarget = null;
}
- if(locked || block != null || scene.hasField() || hasSchem() || selectPlans.size > 0){
+ if(locked || block != null || scene.hasField() || hasSchematic() || selectPlans.size > 0){
commandMode = false;
}
@@ -772,14 +770,18 @@ public class MobileInput extends InputHandler implements GestureListener{
}
//zoom camera
- if(!locked && Math.abs(Core.input.axisTap(Binding.zoom)) > 0 && !Core.input.keyDown(Binding.rotateplaced) && (Core.input.keyDown(Binding.diagonal_placement) || ((!player.isBuilder() || !isPlacing() || !block.rotate) && selectPlans.isEmpty()))){
+ if(!locked && !scene.hasKeyboard() && !scene.hasScroll() && Math.abs(Core.input.axisTap(Binding.zoom)) > 0 && !Core.input.keyDown(Binding.rotateplaced) && (Core.input.keyDown(Binding.diagonal_placement) || ((!player.isBuilder() || !isPlacing() || !block.rotate) && selectPlans.isEmpty()))){
renderer.scaleCamera(Core.input.axisTap(Binding.zoom));
}
if(!Core.settings.getBool("keyboard") && !locked && !scene.hasKeyboard()){
//move camera around
float camSpeed = 6f;
- Core.camera.position.add(Tmp.v1.setZero().add(Core.input.axis(Binding.move_x), Core.input.axis(Binding.move_y)).nor().scl(Time.delta * camSpeed));
+ Vec2 delta = Tmp.v1.setZero().add(Core.input.axis(Binding.move_x), Core.input.axis(Binding.move_y)).nor().scl(Time.delta * camSpeed);
+ Core.camera.position.add(delta);
+ if(!delta.isZero()){
+ spectating = null;
+ }
}
if(Core.settings.getBool("keyboard")){
@@ -940,6 +942,7 @@ public class MobileInput extends InputHandler implements GestureListener{
//pan player
Core.camera.position.x -= deltaX;
Core.camera.position.y -= deltaY;
+ spectating = null;
}
camera.position.clamp(-camera.width/4f, -camera.height/4f, world.unitWidth() + camera.width/4f, world.unitHeight() + camera.height/4f);
diff --git a/core/src/mindustry/input/Placement.java b/core/src/mindustry/input/Placement.java
index abec7d9f65..5274692aaa 100644
--- a/core/src/mindustry/input/Placement.java
+++ b/core/src/mindustry/input/Placement.java
@@ -142,7 +142,7 @@ public class Placement{
Boolf placeable = plan ->
(plan.placeable(player.team()) || (plan.tile() != null && plan.tile().block() == plan.block)) && //don't count the same block as inaccessible
- !(plan.build() != null && plan.build().rotation != plan.rotation && avoid.get(plan.tile().block()));
+ !(plan != plans.first() && plan.build() != null && plan.build().rotation != plan.rotation && avoid.get(plan.tile().block()));
var result = plans1.clear();
var rotated = plans.first().tile() != null && plans.first().tile().absoluteRelativeTo(plans.peek().x, plans.peek().y) == Mathf.mod(plans.first().rotation + 2, 4);
@@ -217,7 +217,7 @@ public class Placement{
Boolf placeable = plan ->
(plan.placeable(player.team()) || (plan.tile() != null && plan.tile().block() == plan.block)) && //don't count the same block as inaccessible
- !(plan.build() != null && plan.build().rotation != plan.rotation && avoid.get(plan.tile().block()));
+ !(plan != plans.first() && plan.build() != null && plan.build().rotation != plan.rotation && avoid.get(plan.tile().block()));
var result = plans1.clear();
diff --git a/core/src/mindustry/io/JsonIO.java b/core/src/mindustry/io/JsonIO.java
index e301f5b499..34957d1443 100644
--- a/core/src/mindustry/io/JsonIO.java
+++ b/core/src/mindustry/io/JsonIO.java
@@ -261,15 +261,8 @@ public class JsonIO{
public UnlockableContent read(Json json, JsonValue jsonData, Class type){
if(jsonData.isNull()) return null;
String str = jsonData.asString();
- Item item = Vars.content.item(str);
- Liquid liquid = Vars.content.liquid(str);
- Block block = Vars.content.block(str);
- UnitType unit = Vars.content.unit(str);
- return
- item != null ? item :
- liquid != null ? liquid :
- block != null ? block :
- unit;
+ var map = Vars.content.byName(str);
+ return map instanceof UnlockableContent u ? u : null;
}
});
diff --git a/core/src/mindustry/io/SaveVersion.java b/core/src/mindustry/io/SaveVersion.java
index ca7a5f4c9e..1dff34d35f 100644
--- a/core/src/mindustry/io/SaveVersion.java
+++ b/core/src/mindustry/io/SaveVersion.java
@@ -232,7 +232,8 @@ public abstract class SaveVersion extends SaveFileReader{
Tile tile = world.rawTile(i % world.width(), i / world.width());
stream.writeShort(tile.blockID());
- boolean savedata = tile.block().saveData;
+ boolean savedata = tile.floor().saveData || tile.overlay().saveData || tile.block().saveData;
+
byte packed = (byte)((tile.build != null ? 1 : 0) | (savedata ? 2 : 0));
//make note of whether there was an entity/rotation here
@@ -367,7 +368,7 @@ public abstract class SaveVersion extends SaveFileReader{
stream.writeShort(block.x);
stream.writeShort(block.y);
stream.writeShort(block.rotation);
- stream.writeShort(block.block);
+ stream.writeShort(block.block.id);
TypeIO.writeObject(Writes.get(stream), block.config);
}
}
@@ -425,7 +426,7 @@ public abstract class SaveVersion extends SaveFileReader{
var obj = TypeIO.readObject(reads);
//cannot have two in the same position
if(set.add(Point2.pack(x, y))){
- data.plans.addLast(new BlockPlan(x, y, rot, content.block(bid).id, obj));
+ data.plans.addLast(new BlockPlan(x, y, rot, content.block(bid), obj));
}
}
}
diff --git a/core/src/mindustry/io/TypeIO.java b/core/src/mindustry/io/TypeIO.java
index c02ceb4ae6..5be1d54403 100644
--- a/core/src/mindustry/io/TypeIO.java
+++ b/core/src/mindustry/io/TypeIO.java
@@ -246,7 +246,7 @@ public class TypeIO{
//this is irrelevant.
static final WeaponMount[] noMounts = {};
-
+
public static WeaponMount[] readMounts(Reads read){
read.skip(read.b() * (1 + 4 + 4));
@@ -581,7 +581,7 @@ public class TypeIO{
if(ai.command == null) ai.command = UnitCommand.moveCommand;
}
- //command queue only in type 7
+ //command queue only in type 7/8
if(type == 7 || type == 8){
ai.commandQueue.clear();
int length = read.ub();
diff --git a/core/src/mindustry/io/versions/Save3.java b/core/src/mindustry/io/versions/Save3.java
index 51cd8bf4aa..6eff300d88 100644
--- a/core/src/mindustry/io/versions/Save3.java
+++ b/core/src/mindustry/io/versions/Save3.java
@@ -21,7 +21,7 @@ public class Save3 extends LegacySaveVersion{
TeamData data = team.data();
int blocks = stream.readInt();
for(int j = 0; j < blocks; j++){
- data.plans.addLast(new BlockPlan(stream.readShort(), stream.readShort(), stream.readShort(), content.block(stream.readShort()).id, stream.readInt()));
+ data.plans.addLast(new BlockPlan(stream.readShort(), stream.readShort(), stream.readShort(), content.block(stream.readShort()), stream.readInt()));
}
}
diff --git a/core/src/mindustry/logic/GlobalVars.java b/core/src/mindustry/logic/GlobalVars.java
index 0164b18b25..e1a57959cd 100644
--- a/core/src/mindustry/logic/GlobalVars.java
+++ b/core/src/mindustry/logic/GlobalVars.java
@@ -1,6 +1,7 @@
package mindustry.logic;
import arc.*;
+import arc.audio.*;
import arc.files.*;
import arc.graphics.*;
import arc.math.*;
@@ -8,6 +9,7 @@ import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.ctype.*;
+import mindustry.gen.*;
import mindustry.game.*;
import mindustry.type.*;
import mindustry.world.*;
@@ -25,7 +27,7 @@ public class GlobalVars{
public static final Rand rand = new Rand();
//non-constants that depend on state
- private static LVar varTime, varTick, varSecond, varMinute, varWave, varWaveTime, varMapW, varMapH, varServer, varClient, varClientLocale, varClientUnit, varClientName, varClientTeam, varClientMobile;
+ private static LVar varTime, varTick, varSecond, varMinute, varWave, varWaveTime, varMapW, varMapH, varWait, varServer, varClient, varClientLocale, varClientUnit, varClientName, varClientTeam, varClientMobile;
private ObjectMap vars = new ObjectMap<>();
private Seq varEntries = new Seq<>();
@@ -33,6 +35,8 @@ public class GlobalVars{
private UnlockableContent[][] logicIdToContent;
private int[][] contentIdToLogicId;
+ public static final Seq soundNames = new Seq<>();
+
public void init(){
putEntryOnly("sectionProcessor");
@@ -69,6 +73,7 @@ public class GlobalVars{
varMapW = putEntry("@mapw", 0);
varMapH = putEntry("@maph", 0);
+ varWait = putEntry("@wait", null);
putEntryOnly("sectionNetwork");
@@ -87,6 +92,17 @@ public class GlobalVars{
put("@ctrlPlayer", ctrlPlayer);
put("@ctrlCommand", ctrlCommand);
+ //sounds
+ if(Core.assets != null){
+ for(Sound sound : Core.assets.getAll(Sound.class, new Seq<>(Sound.class))){
+ if(sound != Sounds.none && sound != Sounds.swish && sound.file != null){
+ String name = sound.file.nameWithoutExtension();
+ soundNames.add(name);
+ put("@sfx-" + name, Sounds.getSoundId(sound));
+ }
+ }
+ }
+
//store base content
for(Team team : Team.baseTeams){
@@ -116,7 +132,9 @@ public class GlobalVars{
}
for(UnitType type : Vars.content.units()){
- put("@" + type.name, type);
+ if(!type.internal){
+ put("@" + type.name, type);
+ }
}
for(Weather weather : Vars.content.weathers()){
@@ -185,7 +203,7 @@ public class GlobalVars{
varClient.numval = net.client() ? 1 : 0;
//client
- if(!net.server() && player != null){
+ if(player != null){
varClientLocale.objval = player.locale();
varClientUnit.objval = player.unit();
varClientName.objval = player.name();
@@ -194,6 +212,10 @@ public class GlobalVars{
}
}
+ public LVar waitVar(){
+ return varWait;
+ }
+
public Seq getEntries(){
return varEntries;
}
diff --git a/core/src/mindustry/logic/LAssembler.java b/core/src/mindustry/logic/LAssembler.java
index 29cb396a35..847e409100 100644
--- a/core/src/mindustry/logic/LAssembler.java
+++ b/core/src/mindustry/logic/LAssembler.java
@@ -10,7 +10,6 @@ import mindustry.logic.LExecutor.*;
/** "Compiles" a sequence of statements into instructions. */
public class LAssembler{
public static ObjectMap> customParsers = new ObjectMap<>();
- public static final int maxTokenLength = 36;
private static final int invalidNum = Integer.MIN_VALUE;
@@ -22,7 +21,7 @@ public class LAssembler{
public LAssembler(){
//instruction counter
- putVar("@counter");
+ putVar("@counter").isobj = false;
//currently controlled unit
putConst("@unit", null);
//reference to self
@@ -34,8 +33,9 @@ public class LAssembler{
Seq st = read(data, privileged);
- asm.instructions = st.map(l -> l.build(asm)).retainAll(l -> l != null).toArray(LInstruction.class);
asm.privileged = privileged;
+
+ asm.instructions = st.map(l -> l.build(asm)).retainAll(l -> l != null).toArray(LInstruction.class);
return asm;
}
@@ -59,7 +59,7 @@ public class LAssembler{
/** @return a variable by name.
* This may be a constant variable referring to a number or object. */
public LVar var(String symbol){
- LVar constVar = Vars.logicVars.get(symbol);
+ LVar constVar = Vars.logicVars.get(symbol, privileged);
if(constVar != null) return constVar;
symbol = symbol.trim();
@@ -121,7 +121,9 @@ public class LAssembler{
if(vars.containsKey(name)){
return vars.get(name);
}else{
+ //variables are null objects by default
LVar var = new LVar(name);
+ var.isobj = true;
vars.put(name, var);
return var;
}
diff --git a/core/src/mindustry/logic/LCanvas.java b/core/src/mindustry/logic/LCanvas.java
index 04871c02fb..b78908ef6f 100644
--- a/core/src/mindustry/logic/LCanvas.java
+++ b/core/src/mindustry/logic/LCanvas.java
@@ -116,14 +116,7 @@ public class LCanvas extends Table{
jumps.cullable = false;
}).grow().get();
pane.setFlickScroll(false);
-
pane.setScrollYForce(s);
- pane.updateVisualScroll();
- //load old scroll percent
- Core.app.post(() -> {
- pane.setScrollYForce(s);
- pane.updateVisualScroll();
- });
if(toLoad != null){
load(toLoad);
@@ -171,7 +164,7 @@ public class LCanvas extends Table{
}
StatementElem checkHovered(){
- Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true);
+ Element e = Core.scene.getHoverElement();
if(e != null){
while(e != null && !(e instanceof StatementElem)){
e = e.parent;
@@ -257,7 +250,7 @@ public class LCanvas extends Table{
}
}
- invalidateHierarchy();
+ if(parent != null) parent.invalidateHierarchy();
if(parent != null && parent instanceof Table){
setCullingArea(parent.getCullingArea());
diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java
index 481895ea4c..2333fdc344 100644
--- a/core/src/mindustry/logic/LExecutor.java
+++ b/core/src/mindustry/logic/LExecutor.java
@@ -1,6 +1,7 @@
package mindustry.logic;
import arc.*;
+import arc.audio.*;
import arc.graphics.*;
import arc.math.*;
import arc.math.geom.*;
@@ -41,7 +42,6 @@ public class LExecutor{
maxDisplayBuffer = 1024,
maxTextBuffer = 400;
-
public LInstruction[] instructions = {};
/** Non-constant variables used for network sync */
public LVar[] vars = {};
@@ -555,7 +555,7 @@ public class LExecutor{
int address = position.numi();
Building from = target.building();
- if(from instanceof MemoryBuild mem && (exec.privileged || from.team == exec.team)){
+ if(from instanceof MemoryBuild mem && (exec.privileged || (from.team == exec.team && !mem.block.privileged))){
output.setnum(address < 0 || address >= mem.memory.length ? 0 : mem.memory[address]);
}
}
@@ -662,7 +662,7 @@ public class LExecutor{
LogicAI ai = null;
if(base instanceof Ranged r && (exec.privileged || r.team() == exec.team) &&
- (base instanceof Building || (ai = UnitControlI.checkLogicAI(exec, base)) != null)){ //must be a building or a controllable unit
+ ((base instanceof Building b && (!b.block.privileged || exec.privileged)) || (ai = UnitControlI.checkLogicAI(exec, base)) != null)){ //must be a building or a controllable unit
float range = r.range();
Healthc targeted;
@@ -966,8 +966,8 @@ public class LExecutor{
exec.textBuffer.append(strValue);
}else{
//display integer version when possible
- if(Math.abs(value.numval - (long)value.numval) < 0.00001){
- exec.textBuffer.append((long)value.numval);
+ if(Math.abs(value.numval - Math.round(value.numval)) < 0.00001){
+ exec.textBuffer.append(Math.round(value.numval));
}else{
exec.textBuffer.append(value.numval);
}
@@ -978,7 +978,6 @@ public class LExecutor{
return
obj == null ? "null" :
obj instanceof String s ? s :
- obj == Blocks.stoneWall ? "solid" : //special alias
obj instanceof MappableContent content ? content.name :
obj instanceof Content ? "[content]" :
obj instanceof Building build ? build.block.name :
@@ -1028,8 +1027,8 @@ public class LExecutor{
exec.textBuffer.replace(placeholderIndex, placeholderIndex + 3, strValue);
}else{
//display integer version when possible
- if(Math.abs(value.numval - (long)value.numval) < 0.00001){
- exec.textBuffer.replace(placeholderIndex, placeholderIndex + 3, (long)value.numval + "");
+ if(Math.abs(value.numval - Math.round(value.numval)) < 0.00001){
+ exec.textBuffer.replace(placeholderIndex, placeholderIndex + 3, Math.round(value.numval) + "");
}else{
exec.textBuffer.replace(placeholderIndex, placeholderIndex + 3, value.numval + "");
}
@@ -1050,7 +1049,7 @@ public class LExecutor{
@Override
public void run(LExecutor exec){
- if(target.building() instanceof MessageBuild d && (d.team == exec.team || exec.privileged)){
+ if(target.building() instanceof MessageBuild d && (exec.privileged || (d.team == exec.team && !d.block.privileged))){
d.message.setLength(0);
d.message.append(exec.textBuffer, 0, Math.min(exec.textBuffer.length(), maxTextBuffer));
@@ -1242,7 +1241,8 @@ public class LExecutor{
result.setobj(units == null || i < 0 || i >= units.size ? null : units.get(i));
}
}
- case player -> result.setobj(i < 0 || i >= data.players.size ? null : data.players.get(i).unit());
+ case player -> result.setobj(i < 0 || i >= data.players.size ? null :
+ data.players.get(i).unit() instanceof BlockUnitc block ? block.tile() : data.players.get(i).unit());
case core -> result.setobj(i < 0 || i >= data.cores.size ? null : data.cores.get(i));
case build -> {
Block block = extra.obj() instanceof Block b ? b : null;
@@ -1295,7 +1295,7 @@ public class LExecutor{
@Override
public void run(LExecutor exec){
- Tile tile = world.tile(x.numi(), y.numi());
+ Tile tile = world.tile(Mathf.round(x.numf()), Mathf.round(y.numf()));
if(tile == null){
dest.setobj(null);
}else{
@@ -1349,7 +1349,7 @@ public class LExecutor{
if(t == null) t = Team.derelict;
if(tile.block() != b || tile.team() != t){
- tile.setBlock(b, t, Mathf.clamp(rotation.numi(), 0, 3));
+ tile.setNet(b, t, Mathf.clamp(rotation.numi(), 0, 3));
}
}
}
@@ -1380,7 +1380,7 @@ public class LExecutor{
Team t = team.team();
- if(type.obj() instanceof UnitType type && !type.hidden && t != null && Units.canCreate(t, type)){
+ if(type.obj() instanceof UnitType type && !type.internal && !type.hidden && t != null && Units.canCreate(t, type)){
//random offset to prevent stacking
var unit = type.spawn(t, World.unconv(x.numf()) + Mathf.range(0.01f), World.unconv(y.numf()) + Mathf.range(0.01f));
spawner.spawnEffect(unit, rotation.numf());
@@ -1600,7 +1600,7 @@ public class LExecutor{
public void run(LExecutor exec){
//set default to success
outSuccess.setnum(1);
- if(headless && type != MessageType.mission) {
+ if(headless && type != MessageType.mission){
exec.textBuffer.setLength(0);
return;
}
@@ -1610,8 +1610,14 @@ public class LExecutor{
type == MessageType.notify && ui.hudfrag.hasToast() ||
type == MessageType.toast && ui.hasAnnouncement()
){
- //set outSuccess=false to let user retry.
- outSuccess.setnum(0);
+ //backwards compatibility; if it is @wait, block execution
+ if(outSuccess == logicVars.waitVar()){
+ exec.counter.numval--;
+ exec.yield = true;
+ }else{
+ //set outSuccess=false to let user retry.
+ outSuccess.setnum(0);
+ }
return;
}
@@ -1696,7 +1702,7 @@ public class LExecutor{
public static void logicExplosion(Team team, float x, float y, float radius, float damage, boolean air, boolean ground, boolean pierce, boolean effect){
if(damage < 0f) return;
- Damage.damage(team, x, y, radius, damage, pierce, air, ground);
+ Damage.damage(team, x, y, radius, damage, pierce, air, ground, true, null);
if(effect){
if(pierce){
Fx.spawnShockwave.at(x, y, World.conv(radius));
@@ -1911,6 +1917,37 @@ public class LExecutor{
}
}
+ public static class PlaySoundI implements LInstruction{
+ public boolean positional;
+ public LVar id, volume, pitch, pan, x, y, limit;
+
+ public PlaySoundI(){
+ }
+
+ public PlaySoundI(boolean positional, LVar id, LVar volume, LVar pitch, LVar pan, LVar x, LVar y, LVar limit){
+ this.positional = positional;
+ this.id = id;
+ this.volume = volume;
+ this.pitch = pitch;
+ this.pan = pan;
+ this.x = x;
+ this.y = y;
+ this.limit = limit;
+ }
+
+ @Override
+ public void run(LExecutor exec){
+ Sound sound = Sounds.getSound(id.numi());
+ if(sound == null || sound == Sounds.swish) sound = Sounds.none; //no.
+
+ if(positional){
+ sound.at(World.unconv(x.numf()), World.unconv(y.numf()), pitch.numf(), Math.min(volume.numf(), 2f), limit.bool());
+ }else{
+ sound.play(Math.min(volume.numf() * (Core.settings.getInt("sfxvol") / 100f), 2f), pitch.numf(), pan.numf(), false, limit.bool());
+ }
+ }
+ }
+
public static class SetMarkerI implements LInstruction{
public LMarkerControl type = LMarkerControl.pos;
public LVar id, p1, p2, p3;
diff --git a/core/src/mindustry/logic/LStatement.java b/core/src/mindustry/logic/LStatement.java
index 42e0c2ee67..76bcd781b3 100644
--- a/core/src/mindustry/logic/LStatement.java
+++ b/core/src/mindustry/logic/LStatement.java
@@ -103,7 +103,7 @@ public abstract class LStatement{
protected Cell field(Table table, String value, Cons setter){
return table.field(value, Styles.nodeField, s -> setter.get(sanitize(s)))
- .size(144f, 40f).pad(2f).color(table.color).maxTextLength(LAssembler.maxTokenLength);
+ .size(144f, 40f).pad(2f).color(table.color);
}
protected Cell fields(Table table, String desc, String value, Cons setter){
diff --git a/core/src/mindustry/logic/LStatements.java b/core/src/mindustry/logic/LStatements.java
index 3ca506e0e0..11477feb1f 100644
--- a/core/src/mindustry/logic/LStatements.java
+++ b/core/src/mindustry/logic/LStatements.java
@@ -1324,15 +1324,11 @@ public class LStatements{
@Override
public void build(Table table){
- rebuild(table);
- }
-
- void rebuild(Table table){
table.clearChildren();
table.button(clear ? "clear" : "apply", Styles.logict, () -> {
clear = !clear;
- rebuild(table);
+ build(table);
}).size(80f, 40f).pad(4f).color(table.color);
if(statusNames == null){
@@ -1343,11 +1339,10 @@ public class LStatements{
b.label(() -> effect).grow().wrap().labelAlign(Align.center).center();
b.clicked(() -> showSelect(b, statusNames, effect, o -> {
effect = o;
+ build(table);
}, 2, c -> c.size(120f, 38f)));
}, Styles.logict, () -> {}).size(120f, 40f).pad(4f).color(table.color);
- //TODO effect select
-
table.add(clear ? " from " : " to ");
row(table);
@@ -1594,7 +1589,7 @@ public class LStatements{
@RegisterStatement("message")
public static class FlushMessageStatement extends LStatement{
public MessageType type = MessageType.announce;
- public String duration = "3", outSuccess = "success";
+ public String duration = "3", outSuccess = "@wait";
@Override
public void build(Table table){
@@ -1616,9 +1611,11 @@ public class LStatements{
case announce, toast -> {
table.add(" for ");
fields(table, duration, str -> duration = str);
- table.add(" secs ");
+ table.add(" sec ");
}
}
+ row(table);
+
table.add(" success ");
fields(table, outSuccess, str -> outSuccess = str);
}
@@ -2122,6 +2119,74 @@ public class LStatements{
}
}
+ @RegisterStatement("playsound")
+ public static class PlaySoundStatement extends LStatement{
+ public boolean positional;
+ public String id = "@sfx-pew", volume = "1", pitch = "1", pan = "0", x = "@thisx", y = "@thisy", limit = "true";
+
+ @Override
+ public void build(Table table){
+ rebuild(table);
+ }
+
+ void rebuild(Table table){
+ table.clearChildren();
+
+ table.button(positional ? "positional" : "global", Styles.logict, () -> {
+ positional = !positional;
+ rebuild(table);
+ }).size(160f, 40f).pad(4f).color(table.color);
+
+ row(table);
+
+ field(table, id, str -> id = str).padRight(0f).get();
+
+ table.button(b -> {
+ b.image(Icon.pencilSmall);
+
+ String soundName = id.startsWith("@sfx-") ? id.substring(5) : id;
+ b.clicked(() -> showSelect(b, GlobalVars.soundNames.toArray(String.class), soundName, t -> {
+ id = "@sfx-" + t;
+ rebuild(table);
+ }, 2, cell -> cell.size(160, 50)));
+ }, Styles.logict, () -> {}).size(40).color(table.color).left().padLeft(-1);
+
+ row(table);
+
+ fieldst(table, "volume", volume, str -> volume = str);
+ fieldst(table, "pitch", pitch, str -> pitch = str);
+
+ table.row();
+
+ if(positional){
+ fieldst(table, "x", x, str -> x = str);
+
+ fieldst(table, "y", y, str -> y = str);
+ }else{
+ fieldst(table, "pan", pan, str -> pan = str);
+ }
+
+ table.row();
+
+ fieldst(table, "limit", limit, str -> limit = str);
+ }
+
+ @Override
+ public boolean privileged(){
+ return true;
+ }
+
+ @Override
+ public LInstruction build(LAssembler builder){
+ return new PlaySoundI(positional, builder.var(id), builder.var(volume), builder.var(pitch), builder.var(pan), builder.var(x), builder.var(y), builder.var(limit));
+ }
+
+ @Override
+ public LCategory category(){
+ return LCategory.world;
+ }
+ }
+
@RegisterStatement("setmarker")
public static class SetMarkerStatement extends LStatement{
public LMarkerControl type = LMarkerControl.pos;
diff --git a/core/src/mindustry/logic/LogicDialog.java b/core/src/mindustry/logic/LogicDialog.java
index d36a66ee6b..ef3dfb4a53 100644
--- a/core/src/mindustry/logic/LogicDialog.java
+++ b/core/src/mindustry/logic/LogicDialog.java
@@ -3,6 +3,7 @@ package mindustry.logic;
import arc.*;
import arc.func.*;
import arc.graphics.*;
+import arc.input.*;
import arc.scene.actions.*;
import arc.scene.ui.*;
import arc.scene.ui.TextButton.*;
@@ -19,6 +20,8 @@ import mindustry.ui.*;
import mindustry.ui.dialogs.*;
import mindustry.world.blocks.logic.*;
+import java.util.*;
+
import static mindustry.Vars.*;
import static mindustry.logic.LCanvas.*;
@@ -28,6 +31,7 @@ public class LogicDialog extends BaseDialog{
boolean privileged;
@Nullable LExecutor executor;
GlobalVarsDialog globalsDialog = new GlobalVarsDialog();
+ boolean wasRows, wasPortrait;
public LogicDialog(){
super("logic");
@@ -40,10 +44,25 @@ public class LogicDialog extends BaseDialog{
addCloseListener();
shown(this::setup);
+ shown(() -> {
+ wasRows = LCanvas.useRows();
+ wasPortrait = Core.graphics.isPortrait();
+ });
hidden(() -> consumer.get(canvas.save()));
onResize(() -> {
- setup();
- canvas.rebuild();
+ if(wasRows != LCanvas.useRows() || wasPortrait != Core.graphics.isPortrait()){
+ setup();
+ canvas.rebuild();
+ wasPortrait = Core.graphics.isPortrait();
+ wasRows = LCanvas.useRows();
+ }
+ });
+
+ //show add instruction on shift+enter
+ keyDown(KeyCode.enter, () -> {
+ if(Core.input.shift()){
+ showAddDialog();
+ }
});
add(canvas).grow().name("canvas");
@@ -136,13 +155,13 @@ public class LogicDialog extends BaseDialog{
buttons.button("@variables", Icon.menu, () -> {
BaseDialog dialog = new BaseDialog("@variables");
dialog.hidden(() -> {
- if(!wasPaused && !net.active()){
+ if(!wasPaused && !net.active() && !state.isMenu()){
state.set(State.paused);
}
});
dialog.shown(() -> {
- if(!wasPaused && !net.active()){
+ if(!wasPaused && !net.active() && !state.isMenu()){
state.set(State.playing);
}
});
@@ -169,7 +188,7 @@ public class LogicDialog extends BaseDialog{
Label label = out.add("").style(Styles.outlineLabel).padLeft(4).padRight(4).width(140f).wrap().get();
label.update(() -> {
if(counter[0] < 0 || (counter[0] += Time.delta) >= period){
- String text = s.isobj ? PrintI.toString(s.objval) : Math.abs(s.numval - (long)s.numval) < 0.00001 ? (long)s.numval + "" : s.numval + "";
+ String text = s.isobj ? PrintI.toString(s.objval) : Math.abs(s.numval - Math.round(s.numval)) < 0.00001 ? Math.round(s.numval) + "" : s.numval + "";
if(!label.textEquals(text)){
label.setText(text);
if(counter[0] >= 0f){
@@ -201,16 +220,60 @@ public class LogicDialog extends BaseDialog{
dialog.buttons.button("@logic.globals", Icon.list, () -> globalsDialog.show()).size(210f, 64f);
dialog.show();
- }).name("variables").disabled(b -> executor == null || executor.vars.length == 0);
+ }).name("variables").disabled(b -> executor == null || executor.vars.length == 0 || state.isMenu());
buttons.button("@add", Icon.add, () -> {
- BaseDialog dialog = new BaseDialog("@add");
- dialog.cont.table(table -> {
- table.background(Tex.button);
- table.pane(t -> {
+ showAddDialog();
+ }).disabled(t -> canvas.statements.getChildren().size >= LExecutor.maxInstructions);
+ }
+
+ public void showAddDialog(){
+ BaseDialog dialog = new BaseDialog("@add");
+ dialog.cont.table(table -> {
+ String[] searchText = {""};
+ Prov[] matched = {null};
+ Runnable[] rebuild = {() -> {}};
+
+ table.background(Tex.button);
+
+ table.table(s -> {
+ s.image(Icon.zoom).padRight(8);
+ var search = s.field(null, text -> {
+ searchText[0] = text;
+ rebuild[0].run();
+ }).growX().get();
+ search.setMessageText("@players.search");
+
+ //auto add first match on enter key
+ if(!mobile){
+
+ //don't focus on mobile (it may cause issues with a popup keyboard)
+ Core.app.post(search::requestKeyboard);
+
+ search.keyDown(KeyCode.enter, () -> {
+ if(!searchText[0].isEmpty() && matched[0] != null){
+ canvas.add((LStatement)matched[0].get());
+ dialog.hide();
+ }
+ });
+ }
+ }).growX().padBottom(4).row();
+
+ table.pane(t -> {
+ rebuild[0] = () -> {
+ t.clear();
+
+ var text = searchText[0].toLowerCase();
+
+ matched[0] = null;
+
for(Prov prov : LogicIO.allStatements){
LStatement example = prov.get();
- if(example instanceof InvalidStatement || example.hidden() || (example.privileged() && !privileged) || (example.nonPrivileged() && privileged)) continue;
+ if(example instanceof InvalidStatement || example.hidden() || (example.privileged() && !privileged) || (example.nonPrivileged() && privileged) || (!text.isEmpty() && !example.name().toLowerCase(Locale.ROOT).contains(text))) continue;
+
+ if(matched[0] == null){
+ matched[0] = prov;
+ }
LCategory category = example.category();
Table cat = t.find(category.name);
@@ -242,11 +305,13 @@ public class LogicDialog extends BaseDialog{
if(cat.getChildren().size % 3 == 0) cat.row();
}
- }).grow();
- }).fill().maxHeight(Core.graphics.getHeight() * 0.8f);
- dialog.addCloseButton();
- dialog.show();
- }).disabled(t -> canvas.statements.getChildren().size >= LExecutor.maxInstructions);
+ };
+
+ rebuild[0].run();
+ }).grow();
+ }).fill().maxHeight(Core.graphics.getHeight() * 0.8f);
+ dialog.addCloseButton();
+ dialog.show();
}
public void show(String code, LExecutor executor, boolean privileged, Cons modified){
diff --git a/core/src/mindustry/maps/SectorDamage.java b/core/src/mindustry/maps/SectorDamage.java
index de34be2753..0050ecf667 100644
--- a/core/src/mindustry/maps/SectorDamage.java
+++ b/core/src/mindustry/maps/SectorDamage.java
@@ -3,12 +3,11 @@ package mindustry.maps;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
-import arc.util.*;
import mindustry.ai.*;
+import mindustry.ai.types.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.entities.*;
-import mindustry.entities.abilities.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.logic.*;
@@ -22,7 +21,7 @@ import mindustry.world.blocks.storage.*;
import static mindustry.Vars.*;
public class SectorDamage{
- public static final int maxRetWave = 40, maxWavesSimulated = 50;
+ public static final int maxRetWave = 110, maxWavesSimulated = 111;
//direct damage is for testing only
private static final boolean rubble = true;
@@ -42,7 +41,7 @@ public class SectorDamage{
return (int)getDamage(info, maxRetWave, true);
}
- /** @return calculated capture progress of the enemy if retWave if false, otherwise return the maximum waves survived as int.
+ /** @return calculated capture progress of the enemy if retWave is false, otherwise return the maximum waves survived as int.
* if it survives all the waves, returns maxRetWave. */
public static float getDamage(SectorInfo info, int wavesPassed, boolean retWave){
float health = info.sumHealth;
@@ -60,15 +59,29 @@ public class SectorDamage{
waveBegin = waveEnd - maxWavesSimulated;
}
+ int groundSpawns = Math.max(spawner.countFlyerSpawns(), 1), airSpawns = Math.max(spawner.countGroundSpawns(), 1);
+
for(int i = waveBegin; i <= waveEnd; i++){
+ float enemyDps = 0f, enemyHealth = 0f;
+
+ for(SpawnGroup group : state.rules.spawns){
+ //calculate the amount of spawn points used
+ //if there's a spawn position override, there is only one potential place they spawn
+ //assume that all overridden positions are valid, should always be true in properly designed campaign maps
+ int spawnCount = group.spawn != -1 ? 1 : group.type.flying ? airSpawns : groundSpawns;
+
+ float healthMult = 1f + Mathf.clamp(group.type.armor / 20f);
+ StatusEffect effect = (group.effect == null ? StatusEffects.none : group.effect);
+ int spawned = group.getSpawned(i) * spawnCount;
+ if(spawned <= 0) continue;
+ enemyHealth += spawned * (group.getShield(i) + group.type.health * effect.healthMultiplier * healthMult);
+ enemyDps += spawned * group.type.dpsEstimate * effect.damageMultiplier;
+ }
float efficiency = health / info.sumHealth;
float dps = info.sumDps * efficiency;
float rps = info.sumRps * efficiency;
- float enemyDps = info.waveDpsBase + info.waveDpsSlope * (i);
- float enemyHealth = info.waveHealthBase + info.waveHealthSlope * (i);
-
if(info.bossWave == i){
enemyDps += info.bossDps;
enemyHealth += info.bossHealth;
@@ -320,13 +333,9 @@ public class SectorDamage{
if(unit.team == state.rules.defaultTeam){
sumHealth += unit.health*healthMult + unit.shield;
sumDps += unit.type.dpsEstimate;
- if(Structs.find(unit.abilities, a -> a instanceof RepairFieldAbility) instanceof RepairFieldAbility h){
- sumRps += h.amount / h.reload * 60f;
- }
- sumRps += unit.type.weapons.sumf(w -> w.shotsPerSec() * (w.bullet.healPercent * 60f + w.bullet.healAmount));
- if(unit.canBuild()){
- //assume it rebuilds 1 block with 'standard' build cost (20) and health (50) every 2 seconds
- sumRps += unit.type.buildSpeed * (60f / 20f) * (1f / 2f) * 50f;
+ sumRps += unit.type.weapons.sumf(w -> w.shotsPerSec() * (w.bullet.healPercent/100f * 20f + w.bullet.healAmount));
+ if(unit.controller() instanceof CommandAI ai && ai.command == UnitCommand.rebuildCommand){
+ sumRps += unit.type.buildSpeed * 20f;
}
}else{
float bossMult = unit.isBoss() ? 3f : 1f;
@@ -335,41 +344,11 @@ public class SectorDamage{
}
}
- //calculate DPS and health for the next few waves and store in list
- var reg = new LinearRegression();
- SpawnGroup bossGroup = null;
- Seq waveDps = new Seq<>(), waveHealth = new Seq<>();
- int groundSpawns = Math.max(spawner.countFlyerSpawns(), 1), airSpawns = Math.max(spawner.countGroundSpawns(), 1);
-
- //TODO storing all this is dumb when you can just calculate it exactly from the rules...
- for(int wave = state.wave; wave < state.wave + 10; wave ++){
- float sumWaveDps = 0f, sumWaveHealth = 0f;
-
- for(SpawnGroup group : state.rules.spawns){
- //calculate the amount of spawn points used
- //if there's a spawn position override, there is only one potential place they spawn
- //assume that all overridden positions are valid, should always be true in properly designed campaign maps
- int spawnCount = group.spawn != -1 ? 1 : group.type.flying ? airSpawns : groundSpawns;
-
- float healthMult = 1f + Mathf.clamp(group.type.armor / 20f);
- StatusEffect effect = (group.effect == null ? StatusEffects.none : group.effect);
- int spawned = group.getSpawned(wave) * spawnCount;
- //save the boss group
- if(group.effect == StatusEffects.boss){
- bossGroup = group;
- continue;
- }
- if(spawned <= 0) continue;
- sumWaveHealth += spawned * (group.getShield(wave) + group.type.health * effect.healthMultiplier * healthMult);
- sumWaveDps += spawned * group.type.dpsEstimate * effect.damageMultiplier;
- }
- waveDps.add(new Vec2(wave, sumWaveDps));
- waveHealth.add(new Vec2(wave, sumWaveHealth));
- }
+ SpawnGroup bossGroup = state.rules.spawns.find(s -> s.effect == StatusEffects.boss);
if(bossGroup != null){
float bossMult = 1.2f;
- //calculate first boss appearaance
+ //calculate first boss appearance
for(int wave = state.wave; wave < state.wave + 60; wave++){
int spawned = bossGroup.getSpawned(wave - 1);
if(spawned > 0){
@@ -382,15 +361,6 @@ public class SectorDamage{
}
}
- //calculate linear regression of the wave data and store it
- reg.calculate(waveHealth);
- info.waveHealthBase = reg.intercept;
- info.waveHealthSlope = reg.slope;
-
- reg.calculate(waveDps);
- info.waveDpsBase = reg.intercept;
- info.waveDpsSlope = reg.slope;
-
info.sumHealth = sumHealth * 0.9f;
info.sumDps = sumDps;
info.sumRps = sumRps;
diff --git a/core/src/mindustry/maps/filters/GenerateFilter.java b/core/src/mindustry/maps/filters/GenerateFilter.java
index a412a51978..9ce29045f6 100644
--- a/core/src/mindustry/maps/filters/GenerateFilter.java
+++ b/core/src/mindustry/maps/filters/GenerateFilter.java
@@ -35,10 +35,12 @@ public abstract class GenerateFilter implements Cloneable{
Tile tile = tiles.geti(i);
long b = buffer[i];
- Block block = Vars.content.block(PackTile.block(b)), floor = Vars.content.block(PackTile.floor(b)), overlay = Vars.content.block(PackTile.overlay(b));
+ Block block = Vars.content.block(PackTile.block(b)), floorb = Vars.content.block(PackTile.floor(b)), overlay = Vars.content.block(PackTile.overlay(b));
- tile.setFloor(floor.asFloor());
- tile.setOverlay(!floor.asFloor().hasSurface() && overlay.asFloor().needsSurface && overlay instanceof OreBlock ? Blocks.air : overlay);
+ if(floorb instanceof Floor floor){
+ tile.setFloor(floor);
+ tile.setOverlay(!floor.hasSurface() && overlay.asFloor().needsSurface && overlay instanceof OreBlock ? Blocks.air : overlay);
+ }
if(!tile.block().synthetic() && !block.synthetic()){
tile.setBlock(block);
@@ -49,8 +51,10 @@ public abstract class GenerateFilter implements Cloneable{
in.set(tile.x, tile.y, tile.block(), tile.floor(), tile.overlay());
apply(in);
- tile.setFloor(in.floor.asFloor());
- tile.setOverlay(!in.floor.asFloor().hasSurface() && in.overlay.asFloor().needsSurface && in.overlay instanceof OreBlock ? Blocks.air : in.overlay);
+ if(in.floor instanceof Floor floor){
+ tile.setFloor(floor);
+ tile.setOverlay(!floor.hasSurface() && in.overlay.asFloor().needsSurface && in.overlay instanceof OreBlock ? Blocks.air : in.overlay);
+ }
if(!tile.block().synthetic() && !in.block.synthetic()){
tile.setBlock(in.block);
diff --git a/core/src/mindustry/maps/generators/BaseGenerator.java b/core/src/mindustry/maps/generators/BaseGenerator.java
index 9671a83a42..27623957be 100644
--- a/core/src/mindustry/maps/generators/BaseGenerator.java
+++ b/core/src/mindustry/maps/generators/BaseGenerator.java
@@ -34,7 +34,7 @@ public class BaseGenerator{
Seq wallsSmall = content.blocks().select(b -> b instanceof Wall && b.isVanilla() && b.size == size
&& !b.insulated && b.buildVisibility == BuildVisibility.shown
&& !(b instanceof Door)
- && !(Structs.contains(b.requirements, i -> state.rules.hiddenBuildItems.contains(i.item))));
+ && b.isOnPlanet(state.getPlanet()));
wallsSmall.sort(b -> b.buildCost);
return wallsSmall.getFrac(difficulty * 0.91f);
}
@@ -74,14 +74,14 @@ public class BaseGenerator{
pass(tile -> {
if(!tile.block().alwaysReplace) return;
- if(((tile.overlay().asFloor().itemDrop != null || (tile.drop() != null && Mathf.chance(nonResourceChance)))
- || (tile.floor().liquidDrop != null && Mathf.chance(nonResourceChance * 2))) && Mathf.chance(resourceChance)){
+ if(((tile.overlay().asFloor().itemDrop != null || (tile.drop() != null && Mathf.rand.chance(nonResourceChance)))
+ || (tile.floor().liquidDrop != null && Mathf.rand.chance(nonResourceChance * 2))) && Mathf.rand.chance(resourceChance)){
Seq parts = bases.forResource(tile.drop() != null ? tile.drop() : tile.floor().liquidDrop);
if(!parts.isEmpty()){
- tryPlace(parts.getFrac(difficulty + Mathf.range(bracketRange)), tile.x, tile.y, team);
+ tryPlace(parts.getFrac(difficulty + Mathf.rand.range(bracketRange)), tile.x, tile.y, team, Mathf.rand);
}
- }else if(Mathf.chance(nonResourceChance)){
- tryPlace(bases.parts.getFrac(Mathf.rand.random(1f)), tile.x, tile.y, team);
+ }else if(Mathf.rand.chance(nonResourceChance)){
+ tryPlace(bases.parts.getFrac(Mathf.rand.random(1f)), tile.x, tile.y, team, Mathf.rand);
}
});
}
@@ -191,31 +191,36 @@ public class BaseGenerator{
* Tries to place a base part at a certain location with a certain team.
* @return success state
* */
- public static boolean tryPlace(BasePart part, int x, int y, Team team){
- return tryPlace(part, x, y, team, null);
+ public static boolean tryPlace(BasePart part, int x, int y, Team team, Rand rand){
+ return tryPlace(part, x, y, team, rand, null);
}
/**
* Tries to place a base part at a certain location with a certain team.
* @return success state
* */
- public static boolean tryPlace(BasePart part, int x, int y, Team team, @Nullable Intc2 posc){
- int rotation = Mathf.range(2);
+ public static boolean tryPlace(BasePart part, int x, int y, Team team, Rand random, @Nullable Intc2 posc){
+ int rotation = random.range(2);
axis.set((int)(part.schematic.width / 2f), (int)(part.schematic.height / 2f));
Schematic result = Schematics.rotate(part.schematic, rotation);
- int rotdeg = rotation*90;
- rotator.set(part.centerX, part.centerY).rotateAround(axis, rotdeg);
+ rotator.set(part.centerX, part.centerY).rotateAround(axis, rotation * 90);
//bottom left schematic corner
int cx = x - (int)rotator.x;
int cy = y - (int)rotator.y;
+ if(!insanity){
+ for(Stile tile : result.tiles){
+ int realX = tile.x + cx, realY = tile.y + cy;
+ if(isTaken(tile.block, realX, realY)){
+ return false;
+ }
+ }
+ }
+
+ //only do callback after validation
for(Stile tile : result.tiles){
int realX = tile.x + cx, realY = tile.y + cy;
- if(!insanity && isTaken(tile.block, realX, realY)){
- return false;
- }
-
if(posc != null){
posc.get(realX, realY);
}
@@ -223,7 +228,6 @@ public class BaseGenerator{
if(part.required instanceof Item item){
for(Stile tile : result.tiles){
- //uncomment for extra checks if changed above
if(tile.block instanceof Drill && (!insanity || !isTaken(tile.block, tile.x + cx, tile.y + cy))){
tile.block.iterateTaken(tile.x + cx, tile.y + cy, (ex, ey) -> {
@@ -235,7 +239,7 @@ public class BaseGenerator{
set(placed, item);
}
- Tile rand = world.tiles.getc(ex + Mathf.rand.range(1), ey + Mathf.rand.range(1));
+ Tile rand = world.tiles.getc(ex + random.range(1), ey + random.range(1));
if(rand.floor().hasSurface()){
//random ores nearby to make it look more natural
set(rand, item);
@@ -273,6 +277,8 @@ public class BaseGenerator{
}
static boolean isTaken(Block block, int x, int y){
+ if(state.teams.anyEnemyCoresWithin(state.rules.waveTeam, x * tilesize + block.offset, y * tilesize + block.offset, state.rules.enemyCoreBuildRadius + tilesize)) return true;
+
int offsetx = -(block.size - 1) / 2;
int offsety = -(block.size - 1) / 2;
int pad = 1;
diff --git a/core/src/mindustry/maps/generators/BasicGenerator.java b/core/src/mindustry/maps/generators/BasicGenerator.java
index 0305b1d3b0..3daa39c68f 100644
--- a/core/src/mindustry/maps/generators/BasicGenerator.java
+++ b/core/src/mindustry/maps/generators/BasicGenerator.java
@@ -158,7 +158,7 @@ public abstract class BasicGenerator implements WorldGenerator{
int rotation = 0;
for(int i = 0; i < 8; i++){
- Tile other = world.tiles.get(tile.x + Geometry.d8[i].x, tile.y + Geometry.d8[i].y);
+ Tile other = tiles.get(tile.x + Geometry.d8[i].x, tile.y + Geometry.d8[i].y);
if(other != null && !other.block().isStatic()){
rotation |= (1 << i);
}
@@ -209,7 +209,7 @@ public abstract class BasicGenerator implements WorldGenerator{
public void overlay(Block floor, Block block, float chance, int octaves, float falloff, float scl, float threshold){
pass((x, y) -> {
- if(noise(x, y, octaves, falloff, scl) > threshold && Mathf.chance(chance) && tiles.getn(x, y).floor() == floor){
+ if(noise(x, y, octaves, falloff, scl) > threshold && rand.chance(chance) && tiles.getn(x, y).floor() == floor){
ore = block;
}
});
@@ -227,14 +227,14 @@ public abstract class BasicGenerator implements WorldGenerator{
int mx = x % secSize, my = y % secSize;
int sclx = x / secSize, scly = y / secSize;
if(noise(sclx, scly, 0.2f, 1f) > 0.63f && noise(sclx, scly + 999, 200f, 1f) > 0.6f && (mx == 0 || my == 0 || mx == secSize - 1 || my == secSize - 1)){
- if(Mathf.chance(noise(x + 0x231523, y, 40f, 1f))){
+ if(rand.chance(noise(x + 0x231523, y, 40f, 1f))){
floor = floor1;
if(Mathf.dst(mx, my, secSize/2, secSize/2) > secSize/2f + 2){
floor = floor2;
}
}
- if(block.solid && Mathf.chance(0.7)){
+ if(block.solid && rand.chance(0.7)){
block = wall;
}
}
@@ -262,7 +262,7 @@ public abstract class BasicGenerator implements WorldGenerator{
public void scatter(Block target, Block dst, float chance){
pass((x, y) -> {
- if(!Mathf.chance(chance)) return;
+ if(!rand.chance(chance)) return;
if(floor == target){
floor = dst;
}else if(block == target){
@@ -444,7 +444,7 @@ public abstract class BasicGenerator implements WorldGenerator{
}
}
- public Seq pathfind(int startX, int startY, int endX, int endY, TileHueristic th, DistanceHeuristic dh){
+ public Seq pathfind(int startX, int startY, int endX, int endY, TileHeuristic th, DistanceHeuristic dh){
return Astar.pathfind(startX, startY, endX, endY, th, dh, tile -> world.getDarkness(tile.x, tile.y) <= 1f);
}
diff --git a/core/src/mindustry/maps/generators/PlanetGenerator.java b/core/src/mindustry/maps/generators/PlanetGenerator.java
index 710e63b0dd..69524884d7 100644
--- a/core/src/mindustry/maps/generators/PlanetGenerator.java
+++ b/core/src/mindustry/maps/generators/PlanetGenerator.java
@@ -20,7 +20,6 @@ public abstract class PlanetGenerator extends BasicGenerator implements HexMeshe
public int baseSeed = 0;
public int seed = 0;
- protected IntSeq ints = new IntSeq();
protected @Nullable Sector sector;
/** Should generate sector bases for a planet. */
diff --git a/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java b/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java
index 60feb2a2ab..bcc797b6d0 100644
--- a/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java
+++ b/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java
@@ -529,7 +529,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
//random stuff
dec: {
for(int i = 0; i < 4; i++){
- Tile near = world.tile(x + Geometry.d4[i].x, y + Geometry.d4[i].y);
+ Tile near = tiles.get(x + Geometry.d4[i].x, y + Geometry.d4[i].y);
if(near != null && near.block() != Blocks.air){
break dec;
}
@@ -542,11 +542,11 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
});
float difficulty = sector.threat;
- ints.clear();
- ints.ensureCapacity(width * height / 4);
-
int ruinCount = rand.random(-2, 4);
+
if(ruinCount > 0){
+ IntSeq ints = new IntSeq(width * height / 4);
+
int padding = 25;
//create list of potential positions
@@ -586,7 +586,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
}
//actually place the part
- if(part != null && BaseGenerator.tryPlace(part, x, y, Team.derelict, (cx, cy) -> {
+ if(part != null && BaseGenerator.tryPlace(part, x, y, Team.derelict, rand, (cx, cy) -> {
Tile other = tiles.getn(cx, cy);
if(other.floor().hasSurface()){
other.setOverlay(Blocks.oreScrap);
diff --git a/core/src/mindustry/mod/ClassLoaderCloser.java b/core/src/mindustry/mod/ClassLoaderCloser.java
new file mode 100644
index 0000000000..22710cc0a1
--- /dev/null
+++ b/core/src/mindustry/mod/ClassLoaderCloser.java
@@ -0,0 +1,13 @@
+package mindustry.mod;
+
+import java.net.*;
+
+public class ClassLoaderCloser{
+
+ /** Workaround for the close() method not being available on Android. */
+ public static void close(ClassLoader loader) throws Exception{
+ if(loader instanceof URLClassLoader u){
+ u.close();
+ }
+ }
+}
diff --git a/core/src/mindustry/mod/ClassMap.java b/core/src/mindustry/mod/ClassMap.java
index db15ff5e89..df08419251 100644
--- a/core/src/mindustry/mod/ClassMap.java
+++ b/core/src/mindustry/mod/ClassMap.java
@@ -5,7 +5,7 @@ import arc.struct.*;
@SuppressWarnings("deprecation")
public class ClassMap{
public static final ObjectMap> classes = new ObjectMap<>();
-
+
static{
classes.put("AssemblerAI", mindustry.ai.types.AssemblerAI.class);
classes.put("BoostAI", mindustry.ai.types.BoostAI.class);
@@ -104,6 +104,7 @@ public class ClassMap{
classes.put("ItemStack", mindustry.type.ItemStack.class);
classes.put("Liquid", mindustry.type.Liquid.class);
classes.put("LiquidStack", mindustry.type.LiquidStack.class);
+ classes.put("MapLocales", mindustry.type.MapLocales.class);
classes.put("PayloadSeq", mindustry.type.PayloadSeq.class);
classes.put("PayloadStack", mindustry.type.PayloadStack.class);
classes.put("Planet", mindustry.type.Planet.class);
@@ -140,7 +141,9 @@ public class ClassMap{
classes.put("ConstructBlock", mindustry.world.blocks.ConstructBlock.class);
classes.put("ConstructBuild", mindustry.world.blocks.ConstructBlock.ConstructBuild.class);
classes.put("ControlBlock", mindustry.world.blocks.ControlBlock.class);
+ classes.put("ExplosionShield", mindustry.world.blocks.ExplosionShield.class);
classes.put("ItemSelection", mindustry.world.blocks.ItemSelection.class);
+ classes.put("RotBlock", mindustry.world.blocks.RotBlock.class);
classes.put("UnitTetherBlock", mindustry.world.blocks.UnitTetherBlock.class);
classes.put("Accelerator", mindustry.world.blocks.campaign.Accelerator.class);
classes.put("AcceleratorBuild", mindustry.world.blocks.campaign.Accelerator.AcceleratorBuild.class);
@@ -250,6 +253,8 @@ public class ClassMap{
classes.put("OreBlock", mindustry.world.blocks.environment.OreBlock.class);
classes.put("OverlayFloor", mindustry.world.blocks.environment.OverlayFloor.class);
classes.put("Prop", mindustry.world.blocks.environment.Prop.class);
+ classes.put("RemoveOre", mindustry.world.blocks.environment.RemoveOre.class);
+ classes.put("RemoveWall", mindustry.world.blocks.environment.RemoveWall.class);
classes.put("SeaBush", mindustry.world.blocks.environment.SeaBush.class);
classes.put("Seaweed", mindustry.world.blocks.environment.Seaweed.class);
classes.put("ShallowLiquid", mindustry.world.blocks.environment.ShallowLiquid.class);
@@ -435,6 +440,7 @@ public class ClassMap{
classes.put("ConsumeItemExplosive", mindustry.world.consumers.ConsumeItemExplosive.class);
classes.put("ConsumeItemFilter", mindustry.world.consumers.ConsumeItemFilter.class);
classes.put("ConsumeItemFlammable", mindustry.world.consumers.ConsumeItemFlammable.class);
+ classes.put("ConsumeItemList", mindustry.world.consumers.ConsumeItemList.class);
classes.put("ConsumeItemRadioactive", mindustry.world.consumers.ConsumeItemRadioactive.class);
classes.put("ConsumeItems", mindustry.world.consumers.ConsumeItems.class);
classes.put("ConsumeLiquid", mindustry.world.consumers.ConsumeLiquid.class);
diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java
index 05198c401e..0395da4e09 100644
--- a/core/src/mindustry/mod/ContentParser.java
+++ b/core/src/mindustry/mod/ContentParser.java
@@ -327,6 +327,20 @@ public class ContentParser{
readFields(consume, data);
return consume;
});
+ put(Team.class, (type, data) -> {
+ if(data.isString()){
+ Team out = Structs.find(Team.baseTeams, t -> t.name.equals(data.asString()));
+ if(out == null) throw new IllegalArgumentException("Unknown team: " + data.asString());
+ return out;
+ }else if(data.isNumber()){
+ if(data.asInt() >= Team.all.length || data.asInt() < 0){
+ throw new IllegalArgumentException("Unknown team: " + data.asString());
+ }
+ return Team.get(data.asInt());
+ }else{
+ throw new IllegalArgumentException("Unknown team: " + data.asString() + ". Team must either be a string or a number.");
+ }
+ });
}};
/** Stores things that need to be parsed fully, e.g. reading fields of content.
* This is done to accommodate binding of content names first.*/
@@ -674,6 +688,27 @@ public class ContentParser{
currentContent = planet;
read(() -> readFields(planet, value));
return planet;
+ },
+ ContentType.team, (TypeParser)(mod, name, value) -> {
+ TeamEntry entry;
+ Team team;
+ if(value.has("team")){
+ team = (Team)classParsers.get(Team.class).parse(Team.class, value.get("team"));
+ }else{
+ throw new RuntimeException("Team field missing.");
+ }
+ value.remove("team");
+
+ if(locate(ContentType.team, name) != null){
+ entry = locate(ContentType.team, name);
+ readBundle(ContentType.team, name, value);
+ }else{
+ readBundle(ContentType.team, name, value);
+ entry = new TeamEntry(mod + "-" + name, team);
+ }
+ currentContent = entry;
+ read(() -> readFields(entry, value));
+ return entry;
}
);
@@ -1062,29 +1097,41 @@ public class ContentParser{
}
Field field = metadata.field;
try{
- boolean isMap = ObjectMap.class.isAssignableFrom(field.getType()) || ObjectIntMap.class.isAssignableFrom(field.getType()) || ObjectFloatMap.class.isAssignableFrom(field.getType());
- boolean mergeMap = isMap && child.has("add") && child.get("add").isBoolean() && child.getBoolean("add", false);
+ if(child.isObject() && child.has("add") && (Seq.class.isAssignableFrom(field.getType()) || ObjectSet.class.isAssignableFrom(field.getType()))){
+ Object readField = parser.readValue(field.getType(), metadata.elementType, child.get("add"), metadata.keyType);
+ Object fieldObj = field.get(object);
- if(mergeMap){
- child.remove("add");
- }
-
- Object readField = parser.readValue(field.getType(), metadata.elementType, child, metadata.keyType);
- Object fieldObj = field.get(object);
-
- //if a map has add: true, add its contents to the map instead
- if(mergeMap && (fieldObj instanceof ObjectMap,?> || fieldObj instanceof ObjectIntMap> || fieldObj instanceof ObjectFloatMap>)){
- if(field.get(object) instanceof ObjectMap,?> baseMap){
- baseMap.putAll((ObjectMap)readField);
- }else if(field.get(object) instanceof ObjectIntMap> baseMap){
- baseMap.putAll((ObjectIntMap)readField);
- }else if(field.get(object) instanceof ObjectFloatMap> baseMap){
- baseMap.putAll((ObjectFloatMap)readField);
+ if(fieldObj instanceof ObjectSet set){
+ set.addAll((ObjectSet)readField);
+ }else if(fieldObj instanceof Seq seq){
+ seq.addAll((Seq)readField);
+ }else{
+ throw new SerializationException("This should be impossible");
}
}else{
- field.set(object, readField);
- }
+ boolean isMap = ObjectMap.class.isAssignableFrom(field.getType()) || ObjectIntMap.class.isAssignableFrom(field.getType()) || ObjectFloatMap.class.isAssignableFrom(field.getType());
+ boolean mergeMap = isMap && child.has("add") && child.get("add").isBoolean() && child.getBoolean("add", false);
+ if(mergeMap){
+ child.remove("add");
+ }
+
+ Object readField = parser.readValue(field.getType(), metadata.elementType, child, metadata.keyType);
+ Object fieldObj = field.get(object);
+
+ //if a map has add: true, add its contents to the map instead
+ if(mergeMap && (fieldObj instanceof ObjectMap,?> || fieldObj instanceof ObjectIntMap> || fieldObj instanceof ObjectFloatMap>)){
+ if(field.get(object) instanceof ObjectMap,?> baseMap){
+ baseMap.putAll((ObjectMap)readField);
+ }else if(field.get(object) instanceof ObjectIntMap> baseMap){
+ baseMap.putAll((ObjectIntMap)readField);
+ }else if(field.get(object) instanceof ObjectFloatMap> baseMap){
+ baseMap.putAll((ObjectFloatMap)readField);
+ }
+ }else{
+ field.set(object, readField);
+ }
+ }
}catch(IllegalAccessException ex){
throw new SerializationException("Error accessing field: " + field.getName() + " (" + type.getName() + ")", ex);
}catch(SerializationException ex){
diff --git a/core/src/mindustry/mod/Mods.java b/core/src/mindustry/mod/Mods.java
index 3ece15b1d9..470811fc9e 100644
--- a/core/src/mindustry/mod/Mods.java
+++ b/core/src/mindustry/mod/Mods.java
@@ -62,12 +62,13 @@ public class Mods implements Loadable{
return mainLoader;
}
- /** @return the folder where configuration files for this mod should go. The folder may not exist yet; call mkdirs() before writing to it.
- * Call this in init(). */
+ /** @return the folder where configuration files for this mod should go. Call this in init(). */
public Fi getConfigFolder(Mod mod){
ModMeta load = metas.get(mod.getClass());
if(load == null) throw new IllegalArgumentException("Mod is not loaded yet (or missing)!");
- return modDirectory.child(load.name);
+ Fi result = modDirectory.child(load.name);
+ result.mkdirs();
+ return result;
}
/** @return a file named 'config.json' in the config folder for the specified mod.
@@ -411,6 +412,14 @@ public class Mods implements Loadable{
/** Removes a mod file and marks it for requiring a restart. */
public void removeMod(LoadedMod mod){
+ if(!android && mod.loader != null){
+ try{
+ ClassLoaderCloser.close(mod.loader);
+ }catch(Exception e){
+ Log.err(e);
+ }
+ }
+
if(mod.root instanceof ZipFi){
mod.root.delete();
}
@@ -957,6 +966,12 @@ public class Mods implements Loadable{
if(other != null){
//steam mods can't really be deleted, they need to be unsubscribed
if(overwrite && !other.hasSteamID()){
+
+ //close the classloader for jar mods
+ if(!android){
+ ClassLoaderCloser.close(other.loader);
+ }
+
//close zip file
if(other.root instanceof ZipFi){
other.root.delete();
@@ -1251,6 +1266,7 @@ public class Mods implements Loadable{
if(name != null) name = Strings.stripColors(name);
if(displayName != null) displayName = Strings.stripColors(displayName);
if(displayName == null) displayName = name;
+ if(version == null) version = "0";
if(author != null) author = Strings.stripColors(author);
if(description != null) description = Strings.stripColors(description);
if(subtitle != null) subtitle = Strings.stripColors(subtitle).replace("\n", "");
diff --git a/core/src/mindustry/mod/Scripts.java b/core/src/mindustry/mod/Scripts.java
index 6334d2491f..fdbc717c6d 100644
--- a/core/src/mindustry/mod/Scripts.java
+++ b/core/src/mindustry/mod/Scripts.java
@@ -10,8 +10,8 @@ import rhino.*;
import rhino.module.*;
import rhino.module.provider.*;
-import java.io.*;
import java.net.*;
+import java.util.*;
import java.util.regex.*;
public class Scripts implements Disposable{
@@ -46,7 +46,18 @@ public class Scripts implements Disposable{
Object o = context.evaluateString(scope, text, "console.js", 1);
if(o instanceof NativeJavaObject n) o = n.unwrap();
if(o == null) o = "null";
+
else if(o instanceof Undefined) o = "undefined";
+
+ else if(o instanceof Object[] arr) o = Arrays.toString(arr);
+ else if(o instanceof int[] arr) o = Arrays.toString(arr);
+ else if(o instanceof float[] arr) o = Arrays.toString(arr);
+ else if(o instanceof byte[] arr) o = Arrays.toString(arr);
+ else if(o instanceof double[] arr) o = Arrays.toString(arr);
+ else if(o instanceof long[] arr) o = Arrays.toString(arr);
+ else if(o instanceof char[] arr) o = Arrays.toString(arr);
+ else if(o instanceof boolean[] arr) o = Arrays.toString(arr);
+
var out = o.toString();
return out == null ? "null" : out;
}catch(Throwable t){
@@ -73,7 +84,7 @@ public class Scripts implements Disposable{
public void run(LoadedMod mod, Fi file){
currentMod = mod;
- run(file.readString(), file.name(), true);
+ run(file.readString(), mod.name + "/" + file.name(), true);
currentMod = null;
}
@@ -83,15 +94,10 @@ public class Scripts implements Disposable{
//inject script info into file
context.evaluateString(scope, "modName = \"" + currentMod.name + "\"\nscriptName = \"" + file + "\"", "initscript.js", 1);
}
- context.evaluateString(scope,
- wrap ? "(function(){'use strict';\n" + script + "\n})();" : script,
- file, 0);
+ context.evaluateString(scope, wrap ? "(function(){'use strict';\n" + script + "\n})();" : script, file, 0);
return true;
}catch(Throwable t){
- if(currentMod != null){
- file = currentMod.name + "/" + file;
- }
- log(LogLevel.err, file, "" + getError(t, true));
+ log(LogLevel.err, file, getError(t, true));
return false;
}
}
@@ -111,10 +117,10 @@ public class Scripts implements Disposable{
@Override
public ModuleSource loadSource(String moduleId, Scriptable paths, Object validator) throws URISyntaxException{
if(currentMod == null) return null;
- return loadSource(moduleId, currentMod.root.child("scripts"), validator);
+ return loadSource(currentMod, moduleId, currentMod.root.child("scripts"), validator);
}
- private ModuleSource loadSource(String moduleId, Fi root, Object validator) throws URISyntaxException{
+ private ModuleSource loadSource(LoadedMod sourceMod, String moduleId, Fi root, Object validator) throws URISyntaxException{
Matcher matched = directory.matcher(moduleId);
if(matched.find()){
LoadedMod required = Vars.mods.locateMod(matched.group(1));
@@ -122,18 +128,16 @@ public class Scripts implements Disposable{
if(required == null){ // Mod not found, treat it as a folder
Fi dir = root.child(matched.group(1));
if(!dir.exists()) return null; // Mod and folder not found
- return loadSource(script, dir, validator);
+ return loadSource(sourceMod, script, dir, validator);
}
currentMod = required;
- return loadSource(script, required.root.child("scripts"), validator);
+ return loadSource(sourceMod, script, required.root.child("scripts"), validator);
}
Fi module = root.child(moduleId + ".js");
if(!module.exists() || module.isDirectory()) return null;
- return new ModuleSource(
- new InputStreamReader(new ByteArrayInputStream((module.readString()).getBytes())),
- new URI(moduleId), root.file().toURI(), validator);
+ return new ModuleSource(module.reader(Vars.bufferSize), new URI(sourceMod.name + "/" + moduleId + ".js"), root.file().toURI(), validator);
}
}
}
diff --git a/core/src/mindustry/net/ArcNetProvider.java b/core/src/mindustry/net/ArcNetProvider.java
index e7a1a33dd6..66d2d5278c 100644
--- a/core/src/mindustry/net/ArcNetProvider.java
+++ b/core/src/mindustry/net/ArcNetProvider.java
@@ -42,7 +42,12 @@ public class ArcNetProvider implements NetProvider{
public ArcNetProvider(){
ArcNet.errorHandler = e -> {
if(Log.level == LogLevel.debug){
- Log.debug(Strings.getStackTrace(e));
+ var finalCause = Strings.getFinalCause(e);
+
+ //"connection is closed" is a pointless annoying error that should not be logged
+ if(!"Connection is closed.".equals(finalCause.getMessage())){
+ Log.debug(Strings.getStackTrace(e));
+ }
}
};
@@ -139,7 +144,7 @@ public class ArcNetProvider implements NetProvider{
@Override
public void received(Connection connection, Object object){
- if(!(connection.getArbitraryData() instanceof ArcConnection k) || !(object instanceof Packet pack)) return;
+ if(!(connection.getArbitraryData() instanceof ArcConnection k)) return;
if(packetSpamLimit > 0 && !k.packetRate.allow(3000, packetSpamLimit)){
Log.warn("Blacklisting IP '@' as potential DOS attack - packet spam.", k.address);
@@ -148,6 +153,8 @@ public class ArcNetProvider implements NetProvider{
return;
}
+ if(!(object instanceof Packet pack)) return;
+
Core.app.post(() -> {
try{
net.handleServerReceived(k, pack);
@@ -361,10 +368,12 @@ public class ArcNetProvider implements NetProvider{
@Override
public void send(Object object, boolean reliable){
try{
- if(reliable){
- connection.sendTCP(object);
- }else{
- connection.sendUDP(object);
+ if(connection.isConnected()){
+ if(reliable){
+ connection.sendTCP(object);
+ }else{
+ connection.sendUDP(object);
+ }
}
}catch(Exception e){
Log.err(e);
diff --git a/core/src/mindustry/net/BeControl.java b/core/src/mindustry/net/BeControl.java
index 668e687d7c..2b96a3f231 100644
--- a/core/src/mindustry/net/BeControl.java
+++ b/core/src/mindustry/net/BeControl.java
@@ -31,7 +31,7 @@ public class BeControl{
/** @return whether this is a bleeding edge build. */
public boolean active(){
- return Version.type.equals("bleeding-edge");
+ return Version.type.equals("bleeding-edge") && !steam;
}
public BeControl(){
diff --git a/core/src/mindustry/net/CrashSender.java b/core/src/mindustry/net/CrashHandler.java
similarity index 63%
rename from core/src/mindustry/net/CrashSender.java
rename to core/src/mindustry/net/CrashHandler.java
index 26f90007a8..2ac952c3e6 100644
--- a/core/src/mindustry/net/CrashSender.java
+++ b/core/src/mindustry/net/CrashHandler.java
@@ -17,20 +17,25 @@ import java.util.*;
import static arc.Core.*;
import static mindustry.Vars.*;
-public class CrashSender{
+public class CrashHandler{
- public static String createReport(String error){
- String report = "Mindustry has crashed. How unfortunate.\n";
+ public static String createReport(Throwable exception){
+ String error = writeException(exception);
+ LoadedMod cause = getModCause(exception);
+
+ String report = cause == null ? "Mindustry has crashed. How unfortunate.\n" : "The mod '" + cause.meta.displayName + "' (" + cause.name + ")" + " has caused Mindustry to crash.\n";
if(mods != null && mods.list().size == 0 && Version.build != -1){
report += "Report this at " + Vars.reportIssueURL + "\n\n";
}
+
return report
+ "Version: " + Version.combined() + (Vars.headless ? " (Server)" : "") + "\n"
+ "OS: " + OS.osName + " x" + (OS.osArchBits) + " (" + OS.osArch + ")\n"
+ ((OS.isAndroid || OS.isIos) && app != null ? "Android API level: " + Core.app.getVersion() + "\n" : "")
+ "Java Version: " + OS.javaVersion + "\n"
+ "Runtime Available Memory: " + (Runtime.getRuntime().maxMemory() / 1024 / 1024) + "mb\n"
- + "Cores: " + Runtime.getRuntime().availableProcessors() + "\n"
+ + "Cores: " + OS.cores + "\n"
+ + (cause == null ? "" : "Likely Cause: " + cause.meta.displayName + " (" + cause.name + " v" + cause.meta.version + ")\n")
+ (mods == null ? "" : "Mods: " + (!mods.list().contains(LoadedMod::shouldBeEnabled) ? "none (vanilla)" : mods.list().select(LoadedMod::shouldBeEnabled).toString(", ", mod -> mod.name + ":" + mod.meta.version)))
+ "\n\n" + error;
}
@@ -38,12 +43,12 @@ public class CrashSender{
public static void log(Throwable exception){
try{
Core.settings.getDataDirectory().child("crashes").child("crash_" + System.currentTimeMillis() + ".txt")
- .writeString(createReport(Strings.neatError(exception)));
+ .writeString(createReport(exception));
}catch(Throwable ignored){
}
}
- public static void send(Throwable exception, Cons writeListener){
+ public static void handle(Throwable exception, Cons writeListener){
try{
try{
//log to file
@@ -59,14 +64,14 @@ public class CrashSender{
//don't create crash logs for custom builds, as it's expected
if(OS.username.equals("anuke") && !"steam".equals(Version.modifier)){
- ret();
+ System.exit(1);
}
//attempt to load version regardless
if(Version.number == 0){
try{
ObjectMap map = new ObjectMap<>();
- PropertiesUtils.load(map, new InputStreamReader(CrashSender.class.getResourceAsStream("/version.properties")));
+ PropertiesUtils.load(map, new InputStreamReader(CrashHandler.class.getResourceAsStream("/version.properties")));
Version.type = map.get("type");
Version.number = Integer.parseInt(map.get("number"));
@@ -87,7 +92,7 @@ public class CrashSender{
try{
File file = new File(OS.getAppDataDirectoryString(Vars.appName), "crashes/crash-report-" + new SimpleDateFormat("MM_dd_yyyy_HH_mm_ss").format(new Date()) + ".txt");
new Fi(OS.getAppDataDirectoryString(Vars.appName)).child("crashes").mkdirs();
- new Fi(file).writeString(createReport(writeException(exception)));
+ new Fi(file).writeString(createReport(exception));
writeListener.get(file);
}catch(Throwable e){
Log.err("Failed to save local crash report.", e);
@@ -103,11 +108,41 @@ public class CrashSender{
death.printStackTrace();
}
- ret();
+ System.exit(1);
}
- private static void ret(){
- System.exit(1);
+ /** @return the mod that is likely to have caused the supplied crash */
+ public static @Nullable LoadedMod getModCause(Throwable e){
+ if(Vars.mods == null) return null;
+ try{
+ for(var element : e.getStackTrace()){
+ String name = element.getClassName();
+ if(!name.matches("(mindustry|arc|java|javax|sun|jdk)\\..*")){
+ for(var mod : mods.list()){
+ if(mod.meta.main != null && getMatches(mod.meta.main, name) > 0){
+ return mod;
+ }else if(element.getFileName() != null && element.getFileName().endsWith(".js") && element.getFileName().startsWith(mod.name + "/")){
+ return mod;
+ }
+ }
+ }
+ }
+ }catch(Throwable ignored){}
+ return null;
+ }
+
+ private static int getMatches(String name1, String name2){
+ String[] arr1 = name1.split("\\."), arr2 = name2.split("\\.");
+ int matches = 0;
+ for(int i = 0; i < Math.min(arr1.length, arr2.length); i++){
+
+ if(!arr1[i].equals(arr2[i])){
+ return i;
+ }else if(!arr1[i].matches("net|org|com|io")){ //ignore common domain prefixes, as that's usually not enough to call something a "match"
+ matches ++;
+ }
+ }
+ return matches;
}
private static String writeException(Throwable e){
diff --git a/core/src/mindustry/net/Net.java b/core/src/mindustry/net/Net.java
index 145238bf88..a5c319220e 100644
--- a/core/src/mindustry/net/Net.java
+++ b/core/src/mindustry/net/Net.java
@@ -35,7 +35,10 @@ public class Net{
private final ObjectMap, Cons> clientListeners = new ObjectMap<>();
private final ObjectMap, Cons2> serverListeners = new ObjectMap<>();
private final IntMap streams = new IntMap<>();
- private final ExecutorService pingExecutor = OS.isWindows && !OS.is64Bit ? Threads.boundedExecutor("Ping Servers", 5) : Threads.unboundedExecutor();
+ private final ExecutorService pingExecutor =
+ OS.isWindows && !OS.is64Bit ? Threads.boundedExecutor("Ping Servers", 5) : //on 32-bit windows, thread spam crashes
+ OS.isIos ? Threads.boundedExecutor("Ping Servers", 32) : //on IOS, 256 threads can crash, so limit the amount
+ Threads.unboundedExecutor();
private final NetProvider provider;
diff --git a/core/src/mindustry/net/NetworkIO.java b/core/src/mindustry/net/NetworkIO.java
index 48599c6b96..3dac108090 100644
--- a/core/src/mindustry/net/NetworkIO.java
+++ b/core/src/mindustry/net/NetworkIO.java
@@ -30,7 +30,7 @@ public class NetworkIO{
for(ContentType type : ContentType.all){
for(Content c : content.getBy(type)){
if(c instanceof UnlockableContent u && u.unlocked() && u.techNode != null){
- state.rules.researched.add(u.name);
+ state.rules.researched.add(u);
}
}
}
diff --git a/core/src/mindustry/service/GameService.java b/core/src/mindustry/service/GameService.java
index ce008a3c88..4cad46716b 100644
--- a/core/src/mindustry/service/GameService.java
+++ b/core/src/mindustry/service/GameService.java
@@ -81,12 +81,12 @@ public class GameService{
}
private void registerEvents(){
- allTransportSerpulo = content.blocks().select(b -> b.category == Category.distribution && b.isVisibleOn(Planets.serpulo) && b.isVanilla() && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
- allTransportErekir = content.blocks().select(b -> b.category == Category.distribution && b.isVisibleOn(Planets.erekir) && b.isVanilla() && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
+ allTransportSerpulo = content.blocks().select(b -> b.category == Category.distribution && b.isOnPlanet(Planets.serpulo) && b.isVanilla() && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
+ allTransportErekir = content.blocks().select(b -> b.category == Category.distribution && b.isOnPlanet(Planets.erekir) && b.isVanilla() && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
//cores are ignored since they're upgrades and can be skipped
- allSerpuloBlocks = content.blocks().select(b -> b.synthetic() && b.isVisibleOn(Planets.serpulo) && b.isVanilla() && !(b instanceof CoreBlock) && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
- allErekirBlocks = content.blocks().select(b -> b.synthetic() && b.isVisibleOn(Planets.erekir) && b.isVanilla() && !(b instanceof CoreBlock) && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
+ allSerpuloBlocks = content.blocks().select(b -> b.synthetic() && b.isOnPlanet(Planets.serpulo) && b.isVanilla() && !(b instanceof CoreBlock) && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
+ allErekirBlocks = content.blocks().select(b -> b.synthetic() && b.isOnPlanet(Planets.erekir) && b.isVanilla() && !(b instanceof CoreBlock) && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
unitsBuilt = Core.settings.getJson("units-built" , ObjectSet.class, String.class, ObjectSet::new);
blocksBuilt = Core.settings.getJson("blocks-built" , ObjectSet.class, String.class, ObjectSet::new);
@@ -171,7 +171,7 @@ public class GameService{
}
}
- if(campaign() && player.unit().type.canBoost && player.unit().elevation >= 0.25f){
+ if(campaign() && !player.dead() && player.unit().type.canBoost && player.unit().elevation >= 0.25f){
boostUnit.complete();
}
});
@@ -526,7 +526,7 @@ public class GameService{
}
for(Building entity : player.team().cores()){
- if(!content.items().contains(i -> !state.rules.hiddenBuildItems.contains(i) && entity.items.get(i) < entity.block.itemCapacity)){
+ if(!content.items().contains(i -> i.isOnPlanet(state.getPlanet()) && entity.items.get(i) < entity.block.itemCapacity)){
fillCoreAllCampaign.complete();
break;
}
diff --git a/core/src/mindustry/type/Item.java b/core/src/mindustry/type/Item.java
index 1c59b0d07a..5d81790919 100644
--- a/core/src/mindustry/type/Item.java
+++ b/core/src/mindustry/type/Item.java
@@ -47,7 +47,9 @@ public class Item extends UnlockableContent implements Senseable{
/** If true, this material is used by buildings. If false, this material will be incinerated in certain cores. */
public boolean buildable = true;
public boolean hidden = false;
- /** For mods. Adds this item to the listed planets' hidden items Seq. */
+
+ /** @deprecated no-op, do not use. */
+ @Deprecated
public @Nullable Planet[] hiddenOnPlanets;
public Item(String name, Color color){
@@ -60,14 +62,9 @@ public class Item extends UnlockableContent implements Senseable{
}
@Override
- public void init(){
- super.init();
-
- if(hiddenOnPlanets != null){
- for(Planet planet : hiddenOnPlanets){
- planet.hiddenItems.add(this);
- }
- }
+ public boolean isOnPlanet(Planet planet){
+ //hidden items should not appear on any planet's resource selection screen
+ return super.isOnPlanet(planet) && !hidden;
}
@Override
diff --git a/core/src/mindustry/type/ItemStack.java b/core/src/mindustry/type/ItemStack.java
index 1da2c72231..a0e0f4c587 100644
--- a/core/src/mindustry/type/ItemStack.java
+++ b/core/src/mindustry/type/ItemStack.java
@@ -80,9 +80,6 @@ public class ItemStack implements Comparable{
@Override
public String toString(){
- return "ItemStack{" +
- "item=" + item +
- ", amount=" + amount +
- '}';
+ return item + ": " + amount;
}
}
diff --git a/core/src/mindustry/type/MapLocales.java b/core/src/mindustry/type/MapLocales.java
index 88dc81237a..a49869d177 100644
--- a/core/src/mindustry/type/MapLocales.java
+++ b/core/src/mindustry/type/MapLocales.java
@@ -21,7 +21,13 @@ public class MapLocales extends ObjectMap implements JsonSeri
@Override
public void read(Json json, JsonValue jsonData){
for(JsonValue value : jsonData){
- put(value.name, json.readValue(StringMap.class, value));
+ StringMap map = new StringMap();
+
+ for(JsonValue child = value.child; child != null; child = child.next){
+ map.put(child.name, json.readValue(String.class, null, child));
+ }
+
+ put(value.name, map);
}
}
diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java
index c25852881f..f99fba5fe6 100644
--- a/core/src/mindustry/type/Planet.java
+++ b/core/src/mindustry/type/Planet.java
@@ -15,11 +15,11 @@ import mindustry.content.*;
import mindustry.content.TechTree.*;
import mindustry.ctype.*;
import mindustry.game.*;
-import mindustry.game.EventType.ContentInitEvent;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.graphics.g3d.*;
import mindustry.graphics.g3d.PlanetGrid.*;
+import mindustry.io.*;
import mindustry.maps.generators.*;
import mindustry.world.*;
import mindustry.world.blocks.*;
@@ -128,15 +128,15 @@ public class Planet extends UnlockableContent{
public boolean allowWaves = false;
/** If false, players are unable to land on this planet's numbered sectors. */
public boolean allowLaunchToNumbered = true;
+ /** If true, the player is allowed to change the difficulty/rules in the planet UI. */
+ public boolean allowCampaignRules = false;
/** Icon as displayed in the planet selection dialog. This is a string, as drawables are null at load time. */
public String icon = "planet";
/** Plays in the planet dialog when this planet is selected. */
public Music launchMusic = Musics.launch;
/** Default core block for launching. */
public Block defaultCore = Blocks.coreShard;
- /** Sets up rules on game load for any sector on this planet. */
- public Cons ruleSetter = r -> {};
- /** Parent body that this planet orbits around. If null, this planet is considered to be in the middle of the solar system.*/
+ /** Parent body that this planet orbits around. If null, this planet is considered to be in the middle of the solar system. */
public @Nullable Planet parent;
/** The root parent of the whole solar system this planet is in. */
public Planet solarSystem;
@@ -146,10 +146,8 @@ public class Planet extends UnlockableContent{
public @Nullable TechNode techTree;
/** TODO remove? Planets that can be launched to from this one. Made mutual in init(). */
public Seq launchCandidates = new Seq<>();
- /** Items not available on this planet. Left out for backwards compatibility. */
- public Seq
- hiddenItems = new Seq<>();
- /** The only items available on this planet, if defined. */
- public Seq
- itemWhitelist = new Seq<>();
+ /** If true, all content in this planet's tech tree will be assigned this planet in their shownPlanets. */
+ public boolean autoAssignPlanet = true;
/** Content (usually planet-specific) that is unlocked upon landing here. */
public Seq unlockedOnLand = new Seq<>();
/** Loads the mesh. Clientside only. Defaults to a boring sphere mesh. */
@@ -157,6 +155,18 @@ public class Planet extends UnlockableContent{
/** Loads the planet grid outline mesh. Clientside only. */
public Prov gridMeshLoader = () -> MeshBuilder.buildPlanetGrid(grid, outlineColor, outlineRad * radius);
+ /** Global difficulty/modifier settings for this planet's campaign. */
+ public CampaignRules campaignRules = new CampaignRules();
+ /** Defaults applied to the rules. */
+ public CampaignRules campaignRuleDefaults = new CampaignRules();
+ /** Sets up rules on game load for any sector on this planet. */
+ public Cons ruleSetter = r -> {};
+
+ /** @deprecated no-op, do not use. */
+ @Deprecated
+ public Seq
- itemWhitelist = new Seq<>(), hiddenItems = new Seq<>();
+
+
public Planet(String name, Planet parent, float radius){
super(name);
@@ -179,15 +189,9 @@ public class Planet extends UnlockableContent{
parent.updateTotalRadius();
}
- //if an item whitelist exists, add everything else not in that whitelist to hidden items
- Events.on(ContentInitEvent.class, e -> {
- if(itemWhitelist.size > 0){
- hiddenItems.addAll(content.items().select(i -> !itemWhitelist.contains(i)));
- }
- });
-
//calculate solar system
for(solarSystem = this; solarSystem.parent != null; solarSystem = solarSystem.parent);
+ allowCampaignRules = isVanilla();
}
public Planet(String name, Planet parent, float radius, int sectorSize){
@@ -205,19 +209,38 @@ public class Planet extends UnlockableContent{
}
}
+ public void saveRules(){
+ Core.settings.putJson(name + "-campaign-rules", campaignRules);
+ }
+
+ public void loadRules(){
+ campaignRules = Core.settings.getJson(name + "-campaign-rules", CampaignRules.class, () -> campaignRules);
+ }
+
public @Nullable Sector getStartSector(){
return sectors.size == 0 ? null : sectors.get(startSector);
}
public void applyRules(Rules rules){
+ applyRules(rules, false);
+ }
+
+ public void applyRules(Rules rules, boolean customGame){
ruleSetter.get(rules);
rules.attributes.clear();
rules.attributes.add(defaultAttributes);
rules.env = defaultEnv;
rules.planet = this;
- rules.hiddenBuildItems.clear();
- rules.hiddenBuildItems.addAll(hiddenItems);
+
+ if(!customGame){
+ campaignRules.apply(this, rules);
+ }
+ }
+
+ public void applyDefaultRules(CampaignRules rules){
+ JsonIO.copy(campaignRuleDefaults, rules);
+ rules.sectorInvasion = allowSectorInvasion;
}
public @Nullable Sector getLastSector(){
@@ -334,10 +357,18 @@ public class Planet extends UnlockableContent{
@Override
public void init(){
+ applyDefaultRules(campaignRules);
+ loadRules();
+
if(techTree == null){
techTree = TechTree.roots.find(n -> n.planet == this);
}
+ if(techTree != null && autoAssignPlanet){
+ techTree.addDatabaseTab(this);
+ techTree.addPlanet(this);
+ }
+
for(Sector sector : sectors){
sector.loadInfo();
}
@@ -382,7 +413,7 @@ public class Planet extends UnlockableContent{
Vec3 vec = intersect(ray, radius);
if(vec == null) return null;
vec.sub(position).rotate(Vec3.Y, getRotation());
- return sectors.min(t -> t.tile.v.dst2(vec));
+ return sectors.min(t -> Tmp.v31.set(t.tile.v).setLength(radius).dst2(vec));
}
/** @return the sector that is hit by this ray, or null if nothing intersects it. */
diff --git a/core/src/mindustry/type/Sector.java b/core/src/mindustry/type/Sector.java
index 304a73452a..c7573b3c3a 100644
--- a/core/src/mindustry/type/Sector.java
+++ b/core/src/mindustry/type/Sector.java
@@ -163,7 +163,7 @@ public class Sector{
}
public boolean isCaptured(){
- if(isBeingPlayed()) return !info.waves && !info.attack;
+ if(isBeingPlayed()) return !state.rules.waves && !state.rules.attackMode;
return save != null && !info.waves && !info.attack;
}
diff --git a/core/src/mindustry/type/StatusEffect.java b/core/src/mindustry/type/StatusEffect.java
index 79d0177b41..e344f652f0 100644
--- a/core/src/mindustry/type/StatusEffect.java
+++ b/core/src/mindustry/type/StatusEffect.java
@@ -68,10 +68,12 @@ public class StatusEffect extends UnlockableContent{
public StatusEffect(String name){
super(name);
+ allDatabaseTabs = true;
}
@Override
public void init(){
+ super.init();
if(initblock != null){
initblock.run();
}
@@ -113,7 +115,7 @@ public class StatusEffect extends UnlockableContent{
//don't list affinities *and* reactions, as that would be redundant
if(!reacts){
for(var e : affinities.toSeq().sort()){
- stats.add(Stat.affinities, e.emoji() + "" + e);
+ stats.add(Stat.affinities, e.emoji() + e);
}
if(affinities.size > 0 && transitionDamage != 0){
diff --git a/core/src/mindustry/type/TeamEntry.java b/core/src/mindustry/type/TeamEntry.java
index e3f1d42868..3d4f9880c3 100644
--- a/core/src/mindustry/type/TeamEntry.java
+++ b/core/src/mindustry/type/TeamEntry.java
@@ -9,11 +9,15 @@ import mindustry.game.*;
public class TeamEntry extends UnlockableContent{
public final Team team;
- public TeamEntry(Team team){
- super(team.name);
+ public TeamEntry(String name, Team team){
+ super(name);
this.team = team;
}
+ public TeamEntry(Team team){
+ this(team.name, team);
+ }
+
@Override
public void displayExtra(Table table){
table.add("@team." + name + ".log").pad(6).padTop(20).width(400f).wrap().fillX();
diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java
index 3408948807..5ddbbe7763 100644
--- a/core/src/mindustry/type/UnitType.java
+++ b/core/src/mindustry/type/UnitType.java
@@ -155,6 +155,8 @@ public class UnitType extends UnlockableContent implements Senseable{
circleTarget = false,
/** if true, this unit can boost into the air if a player/processors controls it*/
canBoost = false,
+ /** if true, this unit will always boost when using builder AI */
+ boostWhenBuilding = true,
/** if false, logic processors cannot control this unit */
logicControllable = true,
/** if false, players cannot control this unit */
@@ -300,12 +302,14 @@ public class UnitType extends UnlockableContent implements Senseable{
/** 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};
+ /** A value of false is used to hide command changing UI in unit factories. */
+ public boolean allowChangeCommands = true;
/** Commands available to this unit through RTS controls. An empty array means commands will be assigned based on unit capabilities in init(). */
- public UnitCommand[] commands = {};
+ public Seq commands = new Seq<>();
/** Command to assign to this unit upon creation. Null indicates the first command in the array. */
public @Nullable UnitCommand defaultCommand;
/** Stances this unit can have. An empty array means stances will be assigned based on unit capabilities in init(). */
- public UnitStance[] stances = {};
+ public Seq stances = new Seq<>();
/** color for outline generated around sprites */
public Color outlineColor = Pal.darkerMetal;
@@ -458,6 +462,12 @@ public class UnitType extends UnlockableContent implements Senseable{
Unit unit = constructor.get();
unit.team = team;
unit.setType(this);
+ if(unit.controller() instanceof CommandAI command && defaultCommand != null){
+ command.command = defaultCommand;
+ }
+ for(var ability : unit.abilities){
+ ability.created(unit);
+ }
unit.ammo = ammoCapacity; //fill up on ammo upon creation
unit.elevation = flying ? 1f : 0;
unit.heal();
@@ -675,6 +685,8 @@ public class UnitType extends UnlockableContent implements Senseable{
@CallSuper
@Override
public void init(){
+ super.init();
+
if(constructor == null) throw new IllegalArgumentException("no constructor set up for unit '" + name + "'");
Unit example = constructor.get();
@@ -821,49 +833,49 @@ public class UnitType extends UnlockableContent implements Senseable{
canAttack = weapons.contains(w -> !w.noAttack);
//assign default commands.
- if(commands.length == 0){
- Seq cmds = new Seq<>(UnitCommand.class);
+ if(commands.size == 0){
- cmds.add(UnitCommand.moveCommand, UnitCommand.enterPayloadCommand);
+ commands.add(UnitCommand.moveCommand, UnitCommand.enterPayloadCommand);
if(canBoost){
- cmds.add(UnitCommand.boostCommand);
+ commands.add(UnitCommand.boostCommand);
if(buildSpeed > 0f){
- cmds.add(UnitCommand.rebuildCommand, UnitCommand.assistCommand);
+ commands.add(UnitCommand.rebuildCommand, UnitCommand.assistCommand);
}
}
//healing, mining and building is only supported for flying units; pathfinding to ambiguously reachable locations is hard.
if(flying){
if(canHeal){
- cmds.add(UnitCommand.repairCommand);
+ commands.add(UnitCommand.repairCommand);
}
if(buildSpeed > 0){
- cmds.add(UnitCommand.rebuildCommand, UnitCommand.assistCommand);
+ commands.add(UnitCommand.rebuildCommand, UnitCommand.assistCommand);
}
if(mineTier > 0){
- cmds.add(UnitCommand.mineCommand);
+ commands.add(UnitCommand.mineCommand);
}
if(example instanceof Payloadc){
- cmds.addAll(UnitCommand.loadUnitsCommand, UnitCommand.loadBlocksCommand, UnitCommand.unloadPayloadCommand);
+ commands.addAll(UnitCommand.loadUnitsCommand, UnitCommand.loadBlocksCommand, UnitCommand.unloadPayloadCommand, UnitCommand.loopPayloadCommand);
}
}
-
- commands = cmds.toArray();
}
- if(stances.length == 0){
+ if(defaultCommand == null && commands.size > 0){
+ defaultCommand = commands.first();
+ }
+
+ if(stances.size == 0){
if(canAttack){
- Seq seq = Seq.with(UnitStance.stop, UnitStance.shoot, UnitStance.holdFire, UnitStance.pursueTarget, UnitStance.patrol);
+ stances.addAll(UnitStance.stop, UnitStance.shoot, UnitStance.holdFire, UnitStance.pursueTarget, UnitStance.patrol);
if(!flying){
- seq.add(UnitStance.ram);
+ stances.add(UnitStance.ram);
}
- stances = seq.toArray(UnitStance.class);
}else{
- stances = new UnitStance[]{UnitStance.stop, UnitStance.patrol};
+ stances.addAll(UnitStance.stop, UnitStance.patrol);
}
}
@@ -890,7 +902,7 @@ public class UnitType extends UnlockableContent implements Senseable{
//suicide enemy
if(weapons.contains(w -> w.bullet.killShooter)){
//scale down DPS to be insignificant
- dpsEstimate /= 25f;
+ dpsEstimate /= 15f;
}
}
@@ -1271,7 +1283,9 @@ public class UnitType extends UnlockableContent implements Senseable{
if(drawCell) drawCell(unit);
drawWeapons(unit);
if(drawItems) drawItems(unit);
- drawLight(unit);
+ if(!isPayload){
+ drawLight(unit);
+ }
if(unit.shieldAlpha > 0 && drawShields){
drawShield(unit);
@@ -1311,12 +1325,12 @@ public class UnitType extends UnlockableContent implements Senseable{
Draw.reset();
}
-
+
//...where do I put this
public Color shieldColor(Unit unit){
return shieldColor == null ? unit.team.color : shieldColor;
}
-
+
public void drawMining(Unit unit){
if(!unit.mining()) return;
diff --git a/core/src/mindustry/type/Weapon.java b/core/src/mindustry/type/Weapon.java
index d67a1ca032..d097677d3c 100644
--- a/core/src/mindustry/type/Weapon.java
+++ b/core/src/mindustry/type/Weapon.java
@@ -168,7 +168,7 @@ public class Weapon implements Cloneable{
t.row();
t.add("[lightgray]" + Stat.inaccuracy.localized() + ": [white]" + (int)inaccuracy + " " + StatUnit.degrees.localized());
}
- if(!alwaysContinuous && reload > 0){
+ if(!alwaysContinuous && reload > 0 && !bullet.killShooter){
t.row();
t.add("[lightgray]" + Stat.reload.localized() + ": " + (mirror ? "2x " : "") + "[white]" + Strings.autoFixed(60f / reload * shoot.shots, 2) + " " + StatUnit.perSecond.localized());
}
@@ -489,7 +489,7 @@ public class Weapon implements Cloneable{
angle = shootAngle + Mathf.range(inaccuracy + bullet.inaccuracy);
Entityc shooter = unit.controller() instanceof MissileAI ai ? ai.shooter : unit; //Pass the missile's shooter down to its bullets
- mount.bullet = bullet.create(unit, shooter, unit.team, bulletX, bulletY, angle, -1f, (1f - velocityRnd) + Mathf.random(velocityRnd), lifeScl, null, mover, mount.aimX, mount.aimY);
+ mount.bullet = bullet.create(unit, shooter, unit.team, bulletX, bulletY, angle, -1f, (1f - velocityRnd) + Mathf.random(velocityRnd), lifeScl, null, mover, mount.aimX, mount.aimY, mount.target);
handleBullet(unit, mount, mount.bullet);
if(!continuous){
diff --git a/core/src/mindustry/type/weapons/BuildWeapon.java b/core/src/mindustry/type/weapons/BuildWeapon.java
index ab51b976f5..98d732ee8d 100644
--- a/core/src/mindustry/type/weapons/BuildWeapon.java
+++ b/core/src/mindustry/type/weapons/BuildWeapon.java
@@ -38,7 +38,7 @@ public class BuildWeapon extends Weapon{
mount.aimY = unit.buildPlan().drawy();
}else{
//aim for front
- float weaponRotation = unit.rotation - 90;
+ float weaponRotation = unit.rotation - 90 + baseRotation;
mount.aimX = unit.x + Angles.trnsx(unit.rotation - 90, x, y) + Angles.trnsx(weaponRotation, this.shootX, this.shootY);
mount.aimY = unit.y + Angles.trnsy(unit.rotation - 90, x, y) + Angles.trnsy(weaponRotation, this.shootX, this.shootY);
}
diff --git a/core/src/mindustry/ui/ItemDisplay.java b/core/src/mindustry/ui/ItemDisplay.java
deleted file mode 100644
index 4967c1e09d..0000000000
--- a/core/src/mindustry/ui/ItemDisplay.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package mindustry.ui;
-
-import arc.scene.ui.layout.*;
-import arc.util.*;
-import mindustry.type.*;
-import mindustry.world.meta.*;
-
-//TODO replace with static methods?
-/** An item image with text. */
-public class ItemDisplay extends Table{
- public final Item item;
- public final int amount;
-
- public ItemDisplay(Item item){
- this(item, 0);
- }
-
- public ItemDisplay(Item item, int amount, boolean showName){
- add(new ItemImage(new ItemStack(item, amount)));
- if(showName) add(item.localizedName).padLeft(4 + amount > 99 ? 4 : 0);
-
- this.item = item;
- this.amount = amount;
- }
-
- public ItemDisplay(Item item, int amount){
- this(item, amount, true);
- }
-
- /** Displays the item with a "/sec" qualifier based on the time period, in ticks. */
- public ItemDisplay(Item item, int amount, float timePeriod, boolean showName){
- add(new ItemImage(item.uiIcon, amount));
- add((showName ? item.localizedName + "\n" : "") + "[lightgray]" + Strings.autoFixed(amount / (timePeriod / 60f), 2) + StatUnit.perSecond.localized()).padLeft(2).padRight(5).style(Styles.outlineLabel);
-
- this.item = item;
- this.amount = amount;
- }
-}
diff --git a/core/src/mindustry/ui/ItemImage.java b/core/src/mindustry/ui/ItemImage.java
deleted file mode 100644
index 874fa6ceff..0000000000
--- a/core/src/mindustry/ui/ItemImage.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package mindustry.ui;
-
-import arc.graphics.g2d.*;
-import arc.scene.ui.*;
-import arc.scene.ui.layout.*;
-import arc.util.*;
-import mindustry.core.*;
-import mindustry.type.*;
-
-public class ItemImage extends Stack{
-
- public ItemImage(TextureRegion region, int amount){
-
- add(new Table(o -> {
- o.left();
- o.add(new Image(region)).size(32f).scaling(Scaling.fit);
- }));
-
- if(amount != 0){
- add(new Table(t -> {
- t.left().bottom();
- t.add(amount >= 1000 ? UI.formatAmount(amount) : amount + "").style(Styles.outlineLabel);
- t.pack();
- }));
- }
- }
-
- public ItemImage(ItemStack stack){
- this(stack.item.uiIcon, stack.amount);
- }
-
- public ItemImage(PayloadStack stack){
- this(stack.item.uiIcon, stack.amount);
- }
-}
diff --git a/core/src/mindustry/ui/ItemsDisplay.java b/core/src/mindustry/ui/ItemsDisplay.java
index f7e62ded29..dc83f5e54d 100644
--- a/core/src/mindustry/ui/ItemsDisplay.java
+++ b/core/src/mindustry/ui/ItemsDisplay.java
@@ -30,6 +30,8 @@ public class ItemsDisplay extends Table{
top().left();
margin(0);
+ if(items == null) return;
+
table(Tex.button, c -> {
c.margin(10).marginLeft(12).marginTop(15f);
c.marginRight(12f);
diff --git a/core/src/mindustry/ui/LiquidDisplay.java b/core/src/mindustry/ui/LiquidDisplay.java
deleted file mode 100644
index d0982374ab..0000000000
--- a/core/src/mindustry/ui/LiquidDisplay.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package mindustry.ui;
-
-import arc.graphics.*;
-import arc.scene.ui.*;
-import arc.scene.ui.layout.*;
-import arc.util.*;
-import mindustry.type.*;
-import mindustry.world.meta.*;
-
-import static mindustry.Vars.*;
-
-/** An ItemDisplay, but for liquids. */
-public class LiquidDisplay extends Table{
- public final Liquid liquid;
- public final float amount;
- public final boolean perSecond;
-
- public LiquidDisplay(Liquid liquid, float amount, boolean perSecond){
- this.liquid = liquid;
- this.amount = amount;
- this.perSecond = perSecond;
-
- add(new Stack(){{
- add(new Image(liquid.uiIcon).setScaling(Scaling.fit));
-
- if(amount != 0){
- Table t = new Table().left().bottom();
- t.add(Strings.autoFixed(amount, 2)).style(Styles.outlineLabel);
- add(t);
- }
- }}).size(iconMed).padRight(3 + (amount != 0 && Strings.autoFixed(amount, 2).length() > 2 ? 8 : 0));
-
- if(perSecond){
- add(StatUnit.perSecond.localized()).padLeft(2).padRight(5).color(Color.lightGray).style(Styles.outlineLabel);
- }
-
- add(liquid.localizedName);
- }
-}
diff --git a/core/src/mindustry/ui/Minimap.java b/core/src/mindustry/ui/Minimap.java
index 99c7a32303..ee03fc2435 100644
--- a/core/src/mindustry/ui/Minimap.java
+++ b/core/src/mindustry/ui/Minimap.java
@@ -111,7 +111,7 @@ public class Minimap extends Table{
update(() -> {
- Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true);
+ Element e = Core.scene.getHoverElement();
if(e != null && e.isDescendantOf(this)){
requestScroll();
}else if(hasScroll()){
diff --git a/core/src/mindustry/ui/dialogs/AboutDialog.java b/core/src/mindustry/ui/dialogs/AboutDialog.java
index fe755d8879..24a49ced6c 100644
--- a/core/src/mindustry/ui/dialogs/AboutDialog.java
+++ b/core/src/mindustry/ui/dialogs/AboutDialog.java
@@ -41,7 +41,7 @@ public class AboutDialog extends BaseDialog{
ScrollPane pane = new ScrollPane(in);
for(LinkEntry link : Links.getLinks()){
- if((ios || OS.isMac || steam) && bannedItems.contains(link.name)){
+ if((ios || steam) && bannedItems.contains(link.name)){
continue;
}
@@ -50,7 +50,7 @@ public class AboutDialog extends BaseDialog{
table.table(img -> {
img.image().height(h - 5).width(40f).color(link.color);
img.row();
- img.image().height(5).width(40f).color(link.color.cpy().mul(0.8f, 0.8f, 0.8f, 1f));
+ img.image().height(5).width(40f).color(link.color.cpy().mul(0.6f, 0.6f, 0.8f, 1f));
}).expandY();
table.table(i -> {
@@ -64,7 +64,7 @@ public class AboutDialog extends BaseDialog{
inset.labelWrap(link.description).width(w - 100f - h).color(Color.lightGray).growX();
}).padLeft(8);
- table.button(Icon.link, Styles.clearNoneTogglei, () -> {
+ table.button(Icon.link, Styles.clearNonei, () -> {
if(link.name.equals("wiki")) Events.fire(Trigger.openWiki);
if(!Core.app.openURI(link.link)){
diff --git a/core/src/mindustry/ui/dialogs/CampaignRulesDialog.java b/core/src/mindustry/ui/dialogs/CampaignRulesDialog.java
new file mode 100644
index 0000000000..55e6fda0e7
--- /dev/null
+++ b/core/src/mindustry/ui/dialogs/CampaignRulesDialog.java
@@ -0,0 +1,95 @@
+package mindustry.ui.dialogs;
+
+import arc.*;
+import arc.func.*;
+import arc.scene.ui.*;
+import arc.scene.ui.layout.*;
+import mindustry.*;
+import mindustry.game.*;
+import mindustry.gen.*;
+import mindustry.type.*;
+import mindustry.ui.*;
+
+public class CampaignRulesDialog extends BaseDialog{
+ Planet planet;
+ Table current;
+
+ public CampaignRulesDialog(){
+ super("@campaign.difficulty");
+
+ addCloseButton();
+
+ hidden(() -> {
+ if(planet != null){
+ planet.saveRules();
+
+ if(Vars.state.isGame() && Vars.state.isCampaign() && Vars.state.getPlanet() == planet){
+ planet.campaignRules.apply(planet, Vars.state.rules);
+ Call.setRules(Vars.state.rules);
+ }
+ }
+ });
+
+ onResize(() -> {
+ rebuild();
+ });
+ }
+
+ void rebuild(){
+ CampaignRules rules = planet.campaignRules;
+ cont.clear();
+
+ cont.top().pane(inner -> {
+ inner.top().left().defaults().fillX().left().pad(5);
+ current = inner;
+
+ current.table(Tex.button, t -> {
+ t.margin(10f);
+ var group = new ButtonGroup<>();
+ var style = Styles.flatTogglet;
+
+ t.defaults().size(140f, 50f);
+
+ for(Difficulty diff : Difficulty.all){
+ t.button(diff.localized(), style, () -> {
+ rules.difficulty = diff;
+ }).group(group).checked(b -> rules.difficulty == diff);
+
+ if(Core.graphics.isPortrait() && diff.ordinal() % 2 == 1){
+ t.row();
+ }
+ }
+ }).left().fill(false).expand(false, false).row();
+
+ if(planet.allowSectorInvasion){
+ check("@rules.invasions", b -> rules.sectorInvasion = b, () -> rules.sectorInvasion);
+ }
+
+ check("@rules.fog", b -> rules.fog = b, () -> rules.fog);
+ check("@rules.showspawns", b -> rules.showSpawns = b, () -> rules.showSpawns);
+ check("@rules.randomwaveai", b -> rules.randomWaveAI = b, () -> rules.randomWaveAI);
+ }).growY();
+ }
+
+ public void show(Planet planet){
+ this.planet = planet;
+
+ rebuild();
+ show();
+ }
+
+ void check(String text, Boolc cons, Boolp prov){
+ check(text, cons, prov, () -> true);
+ }
+
+ void check(String text, Boolc cons, Boolp prov, Boolp condition){
+ String infoText = text.substring(1) + ".info";
+ var cell = current.check(text, cons).checked(prov.get()).update(a -> a.setDisabled(!condition.get()));
+ if(Core.bundle.has(infoText)){
+ cell.tooltip(text + ".info");
+ }
+ cell.get().left();
+ current.row();
+ }
+
+}
diff --git a/core/src/mindustry/ui/dialogs/ContentInfoDialog.java b/core/src/mindustry/ui/dialogs/ContentInfoDialog.java
index 8defe26a24..b0e2bfb3ea 100644
--- a/core/src/mindustry/ui/dialogs/ContentInfoDialog.java
+++ b/core/src/mindustry/ui/dialogs/ContentInfoDialog.java
@@ -1,6 +1,7 @@
package mindustry.ui.dialogs;
import arc.*;
+import arc.scene.actions.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
@@ -96,9 +97,16 @@ public class ContentInfoDialog extends BaseDialog{
content.displayExtra(table);
ScrollPane pane = new ScrollPane(table);
+ table.marginRight(30f);
+ //TODO: some things (e.g. reconstructor requirements) are too long and screw up the layout
+ //pane.setScrollingDisabled(true, false);
cont.add(pane);
- show();
+ if(isShown()){
+ show(scene, Actions.fadeIn(0f));
+ }else{
+ show();
+ }
}
}
diff --git a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java
index a277593dd3..9c2dd94759 100644
--- a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java
+++ b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java
@@ -220,28 +220,16 @@ public class CustomRulesDialog extends BaseDialog{
check("@rules.wavesending", b -> rules.waveSending = b, () -> rules.waveSending, () -> rules.waves);
check("@rules.wavetimer", b -> rules.waveTimer = b, () -> rules.waveTimer, () -> rules.waves);
check("@rules.waitForWaveToEnd", b -> rules.waitEnemies = b, () -> rules.waitEnemies, () -> rules.waves && rules.waveTimer);
+ check("@rules.randomwaveai", b -> rules.randomWaveAI = b, () -> rules.randomWaveAI, () -> rules.waves);
check("@rules.airUseSpawns", b -> rules.airUseSpawns = b, () -> rules.airUseSpawns, () -> rules.waves);
numberi("@rules.wavelimit", f -> rules.winWave = f, () -> rules.winWave, () -> rules.waves, 0, Integer.MAX_VALUE);
number("@rules.wavespacing", false, f -> rules.waveSpacing = f * 60f, () -> rules.waveSpacing / 60f, () -> rules.waves && rules.waveTimer, 1, Float.MAX_VALUE);
- //this is experimental, because it's not clear that 0 makes it default.
- if(experimental){
- number("@rules.initialwavespacing", false, f -> rules.initialWaveSpacing = f * 60f, () -> rules.initialWaveSpacing / 60f, () -> rules.waves && rules.waveTimer, 0, Float.MAX_VALUE);
- }
+ number("@rules.initialwavespacing", false, f -> rules.initialWaveSpacing = f * 60f, () -> rules.initialWaveSpacing / 60f, () -> rules.waves && rules.waveTimer, 0, Float.MAX_VALUE);
number("@rules.dropzoneradius", false, f -> rules.dropZoneRadius = f * tilesize, () -> rules.dropZoneRadius / tilesize, () -> rules.waves);
-
category("resourcesbuilding");
- check("@rules.infiniteresources", b -> {
- rules.infiniteResources = b;
-
- //reset to serpulo if any env was enabled
- if(!b && rules.hiddenBuildItems.isEmpty()){
- rules.env = Planets.serpulo.defaultEnv;
- rules.hiddenBuildItems.clear();
- rules.hiddenBuildItems.addAll(Planets.serpulo.hiddenItems);
- setup();
- }
- }, () -> rules.infiniteResources);
+ check("@rules.alloweditworldprocessors", b -> rules.allowEditWorldProcessors = b, () -> rules.allowEditWorldProcessors);
+ check("@rules.infiniteresources", b -> rules.infiniteResources = b, () -> rules.infiniteResources);
check("@rules.onlydepositcore", b -> rules.onlyDepositCore = b, () -> rules.onlyDepositCore);
check("@rules.derelictrepair", b -> rules.derelictRepair = b, () -> rules.derelictRepair);
check("@rules.reactorexplosions", b -> rules.reactorExplosions = b, () -> rules.reactorExplosions);
@@ -301,13 +289,11 @@ public class CustomRulesDialog extends BaseDialog{
check("@rules.fog", b -> rules.fog = b, () -> rules.fog);
check("@rules.lighting", b -> rules.lighting = b, () -> rules.lighting);
- if(experimental){
- check("@rules.limitarea", b -> rules.limitMapArea = b, () -> rules.limitMapArea);
- numberi("x", x -> rules.limitX = x, () -> rules.limitX, () -> rules.limitMapArea, 0, 10000);
- numberi("y", y -> rules.limitY = y, () -> rules.limitY, () -> rules.limitMapArea, 0, 10000);
- numberi("w", w -> rules.limitWidth = w, () -> rules.limitWidth, () -> rules.limitMapArea, 0, 10000);
- numberi("h", h -> rules.limitHeight = h, () -> rules.limitHeight, () -> rules.limitMapArea, 0, 10000);
- }
+ check("@rules.limitarea", b -> rules.limitMapArea = b, () -> rules.limitMapArea);
+ numberi("x", x -> rules.limitX = x, () -> rules.limitX, () -> rules.limitMapArea, 0, 10000);
+ numberi("y", y -> rules.limitY = y, () -> rules.limitY, () -> rules.limitMapArea, 0, 10000);
+ numberi("w", w -> rules.limitWidth = w, () -> rules.limitWidth, () -> rules.limitMapArea, 0, 10000);
+ numberi("h", h -> rules.limitHeight = h, () -> rules.limitHeight, () -> rules.limitMapArea, 0, 10000);
number("@rules.solarmultiplier", f -> rules.solarMultiplier = f, () -> rules.solarMultiplier);
@@ -339,7 +325,7 @@ public class CustomRulesDialog extends BaseDialog{
for(Planet planet : content.planets().select(p -> p.accessible && p.visible && p.isLandable())){
t.button(planet.localizedName, style, () -> {
- planet.applyRules(rules);
+ planet.applyRules(rules, true);
}).group(group).checked(b -> rules.planet == planet);
if(t.getChildren().size % 3 == 0){
@@ -349,7 +335,6 @@ public class CustomRulesDialog extends BaseDialog{
t.button("@rules.anyenv", style, () -> {
rules.env = Vars.defaultEnv;
- rules.hiddenBuildItems.clear();
rules.planet = Planets.sun;
}).group(group).checked(b -> rules.planet == Planets.sun);
}).left().fill(false).expand(false, false).row();
diff --git a/core/src/mindustry/ui/dialogs/DatabaseDialog.java b/core/src/mindustry/ui/dialogs/DatabaseDialog.java
index 9fdefa9e1c..10e2ab9ddb 100644
--- a/core/src/mindustry/ui/dialogs/DatabaseDialog.java
+++ b/core/src/mindustry/ui/dialogs/DatabaseDialog.java
@@ -5,11 +5,13 @@ import arc.graphics.*;
import arc.input.*;
import arc.math.*;
import arc.scene.event.*;
+import arc.scene.style.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
+import mindustry.content.*;
import mindustry.ctype.*;
import mindustry.gen.*;
import mindustry.graphics.*;
@@ -24,16 +26,30 @@ public class DatabaseDialog extends BaseDialog{
private TextField search;
private Table all = new Table();
+ private @Nullable Seq allTabs;
+ //sun means "all content"
+ private UnlockableContent tab = Planets.sun;
+
public DatabaseDialog(){
super("@database");
shouldPause = true;
addCloseButton();
- shown(this::rebuild);
+ shown(() -> {
+ checkTabList();
+ if(state.isCampaign() && allTabs.contains(state.getPlanet())){
+ tab = state.getPlanet();
+ }else if(state.isGame() && state.rules.planet != null && allTabs.contains(state.rules.planet)){
+ tab = state.rules.planet;
+ }
+
+ rebuild();
+ });
onResize(this::rebuild);
- all.margin(20).marginTop(0f);
+ all.margin(20).marginTop(0f).marginRight(30f);
+ cont.top();
cont.table(s -> {
s.image(Icon.zoom).padRight(8);
search = s.field(null, text -> rebuild()).growX().get();
@@ -43,18 +59,51 @@ public class DatabaseDialog extends BaseDialog{
cont.pane(all).scrollX(false);
}
+ void checkTabList(){
+ if(allTabs == null){
+ Seq[] allContent = Vars.content.getContentMap();
+ ObjectSet all = new ObjectSet<>();
+ for(var contents : allContent){
+ for(var content : contents){
+ if(content instanceof UnlockableContent u){
+ all.addAll(u.databaseTabs);
+ }
+ }
+ }
+ allTabs = all.toSeq().sort();
+ allTabs.insert(0, Planets.sun);
+ }
+ }
+
void rebuild(){
+ checkTabList();
+
all.clear();
var text = search.getText().toLowerCase();
Seq[] allContent = Vars.content.getContentMap();
+ all.table(t -> {
+ int i = 0;
+ for(var content : allTabs){
+ t.button(content == Planets.sun ? Icon.eyeSmall : content instanceof Planet ? Icon.planet : new TextureRegionDrawable(content.uiIcon), Styles.clearNoneTogglei, iconMed, () -> {
+ tab = content;
+ rebuild();
+ }).size(50f).checked(b -> tab == content).tooltip(content == Planets.sun ? "@all" : content.localizedName).with(but -> {
+ but.getStyle().imageUpColor = content instanceof Planet p ? p.iconColor : Color.white.cpy();
+ });
+
+ if(++i % 10 == 0) t.row();
+ }
+ }).row();;
+
for(int j = 0; j < allContent.length; j++){
ContentType type = ContentType.all[j];
Seq array = allContent[j]
- .select(c -> c instanceof UnlockableContent u && !u.isHidden() &&
+ .select(c -> c instanceof UnlockableContent u && !u.isHidden() && (tab == Planets.sun || u.allDatabaseTabs || u.databaseTabs.contains(tab)) &&
(text.isEmpty() || u.localizedName.toLowerCase().contains(text))).as();
+
if(array.size == 0) continue;
all.add("@content." + type.name() + ".name").growX().left().color(Pal.accent);
diff --git a/core/src/mindustry/ui/dialogs/HostDialog.java b/core/src/mindustry/ui/dialogs/HostDialog.java
index 6abba5784e..5f8f143498 100644
--- a/core/src/mindustry/ui/dialogs/HostDialog.java
+++ b/core/src/mindustry/ui/dialogs/HostDialog.java
@@ -9,7 +9,7 @@ import mindustry.game.EventType.*;
import mindustry.gen.*;
import mindustry.ui.*;
-import java.io.*;
+import java.util.*;
import static mindustry.Vars.*;
@@ -90,8 +90,8 @@ public class HostDialog extends BaseDialog{
}
- }catch(IOException e){
- ui.showException("@server.error", e);
+ }catch(Exception e){
+ ui.showException(e.getMessage() != null && e.getMessage().toLowerCase(Locale.ROOT).contains("address already in use") ? "@server.error.addressinuse" : "@server.error", e);
}
ui.loadfrag.hide();
hide();
diff --git a/core/src/mindustry/ui/dialogs/IconSelectDialog.java b/core/src/mindustry/ui/dialogs/IconSelectDialog.java
index 153d25761d..33766e6bfb 100644
--- a/core/src/mindustry/ui/dialogs/IconSelectDialog.java
+++ b/core/src/mindustry/ui/dialogs/IconSelectDialog.java
@@ -15,8 +15,13 @@ import static mindustry.Vars.*;
public class IconSelectDialog extends Dialog{
private Intc consumer = i -> Log.info("you have mere seconds");
+ private boolean allowLocked;
public IconSelectDialog(){
+ this(true);
+ }
+
+ public IconSelectDialog(boolean allowLocked){
closeOnBack();
setFillParent(true);
@@ -52,7 +57,7 @@ public class IconSelectDialog extends Dialog{
i = 0;
for(UnlockableContent u : content.getBy(ctype).as()){
- if(!u.isHidden() && u.unlocked()){
+ if(!u.isHidden() && (allowLocked || u.unlocked())){
t.button(new TextureRegionDrawable(u.uiIcon), Styles.flati, iconMed, () -> {
hide();
consumer.get(u.emojiChar());
diff --git a/core/src/mindustry/ui/dialogs/JoinDialog.java b/core/src/mindustry/ui/dialogs/JoinDialog.java
index 3c3fd58ba4..f6e4191c7b 100644
--- a/core/src/mindustry/ui/dialogs/JoinDialog.java
+++ b/core/src/mindustry/ui/dialogs/JoinDialog.java
@@ -599,7 +599,7 @@ public class JoinDialog extends BaseDialog{
connect(lastIp, lastPort);
}, exception -> {});
}, 1, 1);
-
+
ui.loadfrag.setButton(() -> {
ui.loadfrag.hide();
if(ping == null) return;
@@ -631,12 +631,24 @@ public class JoinDialog extends BaseDialog{
Core.settings.remove("server-list");
}
- var url = becontrol.active() ? serverJsonBeURL : serverJsonURL;
- Log.info("Fetching community servers at @", url);
+ var urls = Version.type.equals("bleeding-edge") || Vars.forceBeServers ? serverJsonBeURLs : serverJsonURLs;
+
+ fetchServers(urls, 0);
+ }
+
+ private void fetchServers(String[] urls, int index){
+ if(index >= urls.length) return;
//get servers
- Http.get(url)
- .error(t -> Log.err("Failed to fetch community servers", t))
+ Http.get(urls[index])
+ .error(t -> {
+ if(index < urls.length - 1){
+ //attempt fetching from the next URL upon failure
+ fetchServers(urls, index + 1);
+ }else{
+ Log.err("Failed to fetch community servers", t);
+ }
+ })
.submit(result -> {
Jval val = Jval.read(result.getResultAsString());
Seq servers = new Seq<>();
diff --git a/core/src/mindustry/ui/dialogs/LaunchLoadoutDialog.java b/core/src/mindustry/ui/dialogs/LaunchLoadoutDialog.java
index 61d3358233..082b8c134e 100644
--- a/core/src/mindustry/ui/dialogs/LaunchLoadoutDialog.java
+++ b/core/src/mindustry/ui/dialogs/LaunchLoadoutDialog.java
@@ -48,7 +48,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
ItemSeq launch = universe.getLaunchResources();
if(sector.planet.allowLaunchLoadout){
for(var item : content.items()){
- if(sector.planet.hiddenItems.contains(item)){
+ if(!item.isOnPlanet(sector.planet)){
launch.set(item, 0);
}
}
@@ -72,7 +72,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
if(destination.preset != null){
var rules = destination.preset.generator.map.rules();
for(var stack : rules.loadout){
- if(!sector.planet.hiddenItems.contains(stack.item)){
+ if(stack.item.isOnPlanet(sector.planet)){
resources.add(stack.item, stack.amount);
}
}
@@ -89,7 +89,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
total.clear();
selected.requirements().each(total::add);
universe.getLaunchResources().each(total::add);
- valid = sitems.has(total);
+ valid = sitems.has(total) || PlanetDialog.debugSelect;
};
Cons
rebuild = table -> {
@@ -136,7 +136,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
ItemSeq realItems = sitems.copy();
selected.requirements().each(realItems::remove);
- loadout.show(lastCapacity, realItems, out, i -> i.unlocked() && !sector.planet.hiddenItems.contains(i), out::clear, () -> {}, () -> {
+ loadout.show(lastCapacity, realItems, out, i -> i.unlocked() && i.isOnPlanet(sector.planet), out::clear, () -> {}, () -> {
universe.updateLaunchResources(new ItemSeq(out));
update.run();
rebuildItems.run();
@@ -172,7 +172,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
Cons handler = s -> {
if(s.tiles.contains(tile -> !tile.block.supportsEnv(sector.planet.defaultEnv) ||
//make sure block can be built here.
- (!sector.planet.hiddenItems.isEmpty() && Structs.contains(tile.block.requirements, stack -> sector.planet.hiddenItems.contains(stack.item))))){
+ !tile.block.isOnPlanet(sector.planet))){
return;
}
diff --git a/core/src/mindustry/ui/dialogs/ModsDialog.java b/core/src/mindustry/ui/dialogs/ModsDialog.java
index cfc64166ab..aa9593beaa 100644
--- a/core/src/mindustry/ui/dialogs/ModsDialog.java
+++ b/core/src/mindustry/ui/dialogs/ModsDialog.java
@@ -72,6 +72,7 @@ public class ModsDialog extends BaseDialog{
browserTable = tablebrow;
}).scrollX(false);
browser.addCloseButton();
+ browser.makeButtonOverlay();
browser.onResize(this::rebuildBrowser);
@@ -106,40 +107,56 @@ public class ModsDialog extends BaseDialog{
ui.showErrorMessage("@feature.unsupported");
}else if(error instanceof HttpStatusException st){
ui.showErrorMessage(Core.bundle.format("connectfail", Strings.capitalize(st.status.toString().toLowerCase())));
+ }else if(error.getMessage() != null && error.getMessage().toLowerCase(Locale.ROOT).contains("writable dex")){
+ ui.showException("@error.moddex", error);
}else{
ui.showException(error);
}
}
- void getModList(Cons> listener){
- if(modList == null){
- Http.get("https://raw.githubusercontent.com/Anuken/MindustryMods/master/mods.json", response -> {
- String strResult = response.getResultAsString();
+ void getModList(int index, Cons> listener){
+ if(index >= modJsonURLs.length) return;
+ if(modList != null){
+ listener.get(modList);
+ return;
+ }
+
+ Http.get(modJsonURLs[index], response -> {
+ String strResult = response.getResultAsString();
+
+ Core.app.post(() -> {
+ try{
+ modList = JsonIO.json.fromJson(Seq.class, ModListing.class, strResult);
+
+ var d = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+ Func parser = text -> {
+ try{
+ return d.parse(text);
+ }catch(Exception e){
+ return new Date();
+ }
+ };
+
+ modList.sortComparing(m -> parser.get(m.lastUpdated)).reverse();
+ listener.get(modList);
+ }catch(Exception e){
+ Log.err(e);
+ ui.showException(e);
+ }
+ });
+ }, error -> {
+ if(index < modJsonURLs.length - 1){
+ getModList(index + 1, listener);
+ }else{
Core.app.post(() -> {
- try{
- modList = JsonIO.json.fromJson(Seq.class, ModListing.class, strResult);
-
- var d = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
- Func parser = text -> {
- try{
- return d.parse(text);
- }catch(Exception e){
- return new Date();
- }
- };
-
- modList.sortComparing(m -> parser.get(m.lastUpdated)).reverse();
- listener.get(modList);
- }catch(Exception e){
- e.printStackTrace();
- ui.showException(e);
+ modError(error);
+ if(browser != null){
+ browser.hide();
}
});
- }, error -> Core.app.post(() -> modError(error)));
- }else{
- listener.get(modList);
- }
+ }
+ });
}
void setup(){
@@ -174,7 +191,7 @@ public class ModsDialog extends BaseDialog{
mods.importMod(file);
setup();
}catch(Exception e){
- ui.showException(e);
+ ui.showException(e.getMessage() != null && e.getMessage().toLowerCase(Locale.ROOT).contains("writable dex") ? "@error.moddex" : "", e);
Log.err(e);
}
}, "zip", "jar");
@@ -398,6 +415,12 @@ public class ModsDialog extends BaseDialog{
desc.add(mod.meta.author).growX().wrap().padTop(2);
desc.row();
}
+ if(mod.meta.version != null){
+ desc.add("@mod.version").padRight(10).color(Color.gray).top();
+ desc.row();
+ desc.add(mod.meta.version).growX().wrap().padTop(2);
+ desc.row();
+ }
if(mod.meta.description != null){
desc.add("@editor.description").padRight(10).color(Color.gray).top();
desc.row();
@@ -455,7 +478,7 @@ public class ModsDialog extends BaseDialog{
int cols = (int)Math.max(Core.graphics.getWidth() / Scl.scl(480), 1);
- getModList(rlistings -> {
+ getModList(0, rlistings -> {
browserTable.clear();
int i = 0;
diff --git a/core/src/mindustry/ui/dialogs/PausedDialog.java b/core/src/mindustry/ui/dialogs/PausedDialog.java
index 677b3d53ed..2ff15e272b 100644
--- a/core/src/mindustry/ui/dialogs/PausedDialog.java
+++ b/core/src/mindustry/ui/dialogs/PausedDialog.java
@@ -159,7 +159,7 @@ public class PausedDialog extends BaseDialog{
return;
}
- if(control.saves.getCurrent() == null || !control.saves.getCurrent().isAutosave() || wasClient || state.gameOver){
+ if(control.saves.getCurrent() == null || !control.saves.getCurrent().isAutosave() || wasClient || state.gameOver || disableSave){
logic.reset();
return;
}
diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java
index c8f4fb44c2..1a040bc00a 100644
--- a/core/src/mindustry/ui/dialogs/PlanetDialog.java
+++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java
@@ -67,10 +67,11 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
public Label hoverLabel = new Label("");
private Texture[] planetTextures;
+ private CampaignRulesDialog campaignRules = new CampaignRulesDialog();
public PlanetDialog(){
super("", Styles.fullDialog);
-
+
state.renderer = this;
state.drawUi = true;
@@ -387,7 +388,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
//preset sectors can only be selected once unlocked
if(sector.preset != null){
TechNode node = sector.preset.techNode;
- return node == null || node.parent == null || (node.parent.content.unlocked() && (!(node.parent.content instanceof SectorPreset preset) || preset.sector.hasBase()));
+ return sector.preset.unlocked() || node == null || node.parent == null || (node.parent.content.unlocked() && (!(node.parent.content instanceof SectorPreset preset) || preset.sector.hasBase()));
}
return sector.planet.generator != null ?
@@ -474,7 +475,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
if(state.uiAlpha > 0.001f){
for(Sector sec : planet.sectors){
if(sec.hasBase()){
- if(planet.allowSectorInvasion){
+ if(planet.campaignRules.sectorInvasion){
for(Sector enemy : sec.near()){
if(enemy.hasEnemyBase()){
planets.drawArc(planet, enemy.tile.v, sec.tile.v, Team.crux.color.write(Tmp.c2).a(state.uiAlpha), Color.clear, 0.24f, 110f, 25);
@@ -587,7 +588,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
@Override
public void act(float delta){
- if(scene.getDialog() == PlanetDialog.this && !scene.hit(input.mouseX(), input.mouseY(), true).isDescendantOf(e -> e instanceof ScrollPane)){
+ if(scene.getDialog() == PlanetDialog.this && (scene.getHoverElement() == null || !scene.getHoverElement().isDescendantOf(e -> e instanceof ScrollPane))){
scene.setScrollFocus(PlanetDialog.this);
}
@@ -612,6 +613,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
t.top().left();
ScrollPane pane = new ScrollPane(null, Styles.smallPane);
t.add(pane).colspan(2).row();
+ t.button("@campaign.difficulty", Icon.bookSmall, () -> {
+ campaignRules.show(state.planet);
+ }).margin(12f).size(208f, 40f).padTop(12f).visible(() -> state.planet.allowCampaignRules).row();
+ t.add().height(64f); //padding for close button
Table starsTable = new Table(Styles.black);
pane.setWidget(starsTable);
pane.setScrollingDisabled(true, false);
@@ -1133,7 +1138,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
if(sector.isAttacked()){
addSurvivedInfo(sector, stable, false);
- }else if(sector.hasBase() && sector.planet.allowSectorInvasion && sector.near().contains(Sector::hasEnemyBase)){
+ }else if(sector.hasBase() && sector.planet.campaignRules.sectorInvasion && sector.near().contains(Sector::hasEnemyBase)){
stable.add("@sectors.vulnerable");
stable.row();
}else if(!sector.hasBase() && sector.hasEnemyBase()){
diff --git a/core/src/mindustry/ui/dialogs/ResearchDialog.java b/core/src/mindustry/ui/dialogs/ResearchDialog.java
index a251419f31..abc8f66aa0 100644
--- a/core/src/mindustry/ui/dialogs/ResearchDialog.java
+++ b/core/src/mindustry/ui/dialogs/ResearchDialog.java
@@ -47,10 +47,30 @@ public class ResearchDialog extends BaseDialog{
public ItemSeq items;
private boolean showTechSelect;
+ private boolean needsRebuild;
public ResearchDialog(){
super("");
+ Events.on(ResetEvent.class, e -> {
+ hide();
+ });
+
+ Events.on(UnlockEvent.class, e -> {
+ if(net.client() && !needsRebuild){
+ needsRebuild = true;
+ Core.app.post(() -> {
+ needsRebuild = false;
+
+ checkNodes(root);
+ view.hoverNode = null;
+ treeLayout();
+ view.rebuild();
+ Core.scene.act();
+ });
+ }
+ });
+
titleTable.remove();
titleTable.clear();
titleTable.top();
@@ -67,7 +87,7 @@ public class ResearchDialog extends BaseDialog{
t.table(Tex.button, in -> {
in.defaults().width(300f).height(60f);
for(TechNode node : TechTree.roots){
- if(node.requiresUnlock && !node.content.unlocked() && node != getPrefRoot()) continue;
+ if(node.requiresUnlock && !node.content.unlockedHost() && node != getPrefRoot()) continue;
//TODO toggle
in.button(node.localizedName(), node.icon(), Styles.flatTogglet, iconMed, () -> {
@@ -84,10 +104,11 @@ public class ResearchDialog extends BaseDialog{
addCloseButton();
}}.show();
- }).visible(() -> showTechSelect = TechTree.roots.count(node -> !(node.requiresUnlock && !node.content.unlocked())) > 1).minWidth(300f);
+ }).visible(() -> showTechSelect = TechTree.roots.count(node -> !(node.requiresUnlock && !node.content.unlockedHost())) > 1).minWidth(300f);
margin(0f).marginBottom(8);
cont.stack(titleTable, view = new View(), itemDisplay = new ItemsDisplay()).grow();
+ itemDisplay.visible(() -> !net.client());
titleTable.toFront();
@@ -177,15 +198,6 @@ public class ResearchDialog extends BaseDialog{
});
}
- @Override
- public Dialog show(){
- if(net.client()){
- ui.showInfo("@research.multiplayer");
- return this;
- }
- return show(Core.scene);
- }
-
void checkMargin(){
if(Core.graphics.isPortrait() && showTechSelect){
itemDisplay.marginTop(60f);
@@ -361,11 +373,12 @@ public class ResearchDialog extends BaseDialog{
}
boolean selectable(TechNode node){
- return node.content.unlocked() || !node.objectives.contains(i -> !i.complete());
+ //there's a desync here as far as sectors go, since the client doesn't know about that, but I'm not too concerned
+ return node.content.unlockedHost() || !node.objectives.contains(i -> !i.complete());
}
boolean locked(TechNode node){
- return node.content.locked();
+ return !node.content.unlockedHost();
}
class LayoutNode extends TreeNode{
@@ -418,31 +431,34 @@ public class ResearchDialog extends BaseDialog{
button.resizeImage(32f);
button.getImage().setScaling(Scaling.fit);
button.visible(() -> node.visible);
- button.clicked(() -> {
- if(moved) return;
+ if(!net.client()){
+ button.clicked(() -> {
+ if(moved) return;
- if(mobile){
- hoverNode = button;
- rebuild();
- float right = infoTable.getRight();
- if(right > Core.graphics.getWidth()){
- float moveBy = right - Core.graphics.getWidth();
- addAction(new RelativeTemporalAction(){
- {
- setDuration(0.1f);
- setInterpolation(Interp.fade);
- }
+ if(mobile){
+ hoverNode = button;
+ rebuild();
+ float right = infoTable.getRight();
+ if(right > Core.graphics.getWidth()){
+ float moveBy = right - Core.graphics.getWidth();
+ addAction(new RelativeTemporalAction(){
+ {
+ setDuration(0.1f);
+ setInterpolation(Interp.fade);
+ }
- @Override
- protected void updateRelative(float percentDelta){
- panX -= moveBy * percentDelta;
- }
- });
+ @Override
+ protected void updateRelative(float percentDelta){
+ panX -= moveBy * percentDelta;
+ }
+ });
+ }
+ }else if(canSpend(node.node) && locked(node.node)){
+ spend(node.node);
}
- }else if(canSpend(node.node) && locked(node.node)){
- spend(node.node);
- }
- });
+ });
+ }
+
button.hovered(() -> {
if(!mobile && hoverNode != button && node.visible){
hoverNode = button;
@@ -459,9 +475,10 @@ public class ResearchDialog extends BaseDialog{
button.userObject = node.node;
button.setSize(nodeSize);
button.update(() -> {
+ button.setDisabled(net.client() && !mobile);
float offset = (Core.graphics.getHeight() % 2) / 2f;
button.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f + offset, Align.center);
- button.getStyle().up = !locked(node.node) ? Tex.buttonOver : !selectable(node.node) || !canSpend(node.node) ? Tex.buttonRed : Tex.button;
+ button.getStyle().up = !locked(node.node) ? Tex.buttonOver : !selectable(node.node) || (!canSpend(node.node) && !net.client()) ? Tex.buttonRed : Tex.button;
((TextureRegionDrawable)button.getStyle().imageUp).setRegion(node.selectable ? node.node.content.uiIcon : Icon.lock.getRegion());
button.getImage().setColor(!locked(node.node) ? Color.white : node.selectable ? Color.gray : Pal.gray);
@@ -472,7 +489,7 @@ public class ResearchDialog extends BaseDialog{
if(mobile){
tapped(() -> {
- Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true);
+ Element e = Core.scene.getHoverElement();
if(e == this){
hoverNode = null;
rebuild();
@@ -498,7 +515,7 @@ public class ResearchDialog extends BaseDialog{
}
boolean canSpend(TechNode node){
- if(!selectable(node)) return false;
+ if(!selectable(node) || net.client()) return false;
if(node.requirements.length == 0) return true;
@@ -514,6 +531,8 @@ public class ResearchDialog extends BaseDialog{
}
void spend(TechNode node){
+ if(net.client()) return;
+
boolean complete = true;
boolean[] shine = new boolean[node.requirements.length];
@@ -549,6 +568,7 @@ public class ResearchDialog extends BaseDialog{
Core.scene.act();
rebuild(shine);
itemDisplay.rebuild(items, usedShine);
+ checkMargin();
}
void unlock(TechNode node){
@@ -611,86 +631,90 @@ public class ResearchDialog extends BaseDialog{
desc.left().defaults().left();
desc.add(selectable ? node.content.localizedName : "[accent]???");
desc.row();
- if(locked(node) || debugShowRequirements){
+ if(locked(node) || (debugShowRequirements && !net.client())){
- desc.table(t -> {
- t.left();
- if(selectable){
+ if(net.client()){
+ desc.add("@locked").color(Pal.remove);
+ }else{
+ desc.table(t -> {
+ t.left();
+ if(selectable){
- //check if there is any progress, add research progress text
- if(Structs.contains(node.finishedRequirements, s -> s.amount > 0)){
- float sum = 0f, used = 0f;
- boolean shiny = false;
+ //check if there is any progress, add research progress text
+ if(Structs.contains(node.finishedRequirements, s -> s.amount > 0)){
+ float sum = 0f, used = 0f;
+ boolean shiny = false;
- for(int i = 0; i < node.requirements.length; i++){
- sum += node.requirements[i].item.cost * node.requirements[i].amount;
- used += node.finishedRequirements[i].item.cost * node.finishedRequirements[i].amount;
- if(shine != null) shiny |= shine[i];
- }
+ for(int i = 0; i < node.requirements.length; i++){
+ sum += node.requirements[i].item.cost * node.requirements[i].amount;
+ used += node.finishedRequirements[i].item.cost * node.finishedRequirements[i].amount;
+ if(shine != null) shiny |= shine[i];
+ }
- Label label = t.add(Core.bundle.format("research.progress", Math.min((int)(used / sum * 100), 99))).left().get();
-
- if(shiny){
- label.setColor(Pal.accent);
- label.actions(Actions.color(Color.lightGray, 0.75f, Interp.fade));
- }else{
- label.setColor(Color.lightGray);
- }
-
- t.row();
- }
-
- for(int i = 0; i < node.requirements.length; i++){
- ItemStack req = node.requirements[i];
- ItemStack completed = node.finishedRequirements[i];
-
- //skip finished stacks
- if(req.amount <= completed.amount && !debugShowRequirements) continue;
- boolean shiny = shine != null && shine[i];
-
- t.table(list -> {
- int reqAmount = debugShowRequirements ? req.amount : req.amount - completed.amount;
-
- list.left();
- list.image(req.item.uiIcon).size(8 * 3).padRight(3);
- list.add(req.item.localizedName).color(Color.lightGray);
- Label label = list.label(() -> " " +
- UI.formatAmount(Math.min(items.get(req.item), reqAmount)) + " / "
- + UI.formatAmount(reqAmount)).get();
-
- Color targetColor = items.has(req.item) ? Color.lightGray : Color.scarlet;
+ Label label = t.add(Core.bundle.format("research.progress", Math.min((int)(used / sum * 100), 99))).left().get();
if(shiny){
label.setColor(Pal.accent);
- label.actions(Actions.color(targetColor, 0.75f, Interp.fade));
+ label.actions(Actions.color(Color.lightGray, 0.75f, Interp.fade));
}else{
- label.setColor(targetColor);
+ label.setColor(Color.lightGray);
}
- }).fillX().left();
+ t.row();
+ }
+
+ for(int i = 0; i < node.requirements.length; i++){
+ ItemStack req = node.requirements[i];
+ ItemStack completed = node.finishedRequirements[i];
+
+ //skip finished stacks
+ if(req.amount <= completed.amount && !debugShowRequirements) continue;
+ boolean shiny = shine != null && shine[i];
+
+ t.table(list -> {
+ int reqAmount = debugShowRequirements ? req.amount : req.amount - completed.amount;
+
+ list.left();
+ list.image(req.item.uiIcon).size(8 * 3).padRight(3);
+ list.add(req.item.localizedName).color(Color.lightGray);
+ Label label = list.label(() -> " " +
+ UI.formatAmount(Math.min(items.get(req.item), reqAmount)) + " / "
+ + UI.formatAmount(reqAmount)).get();
+
+ Color targetColor = items.has(req.item) ? Color.lightGray : Color.scarlet;
+
+ if(shiny){
+ label.setColor(Pal.accent);
+ label.actions(Actions.color(targetColor, 0.75f, Interp.fade));
+ }else{
+ label.setColor(targetColor);
+ }
+
+ }).fillX().left();
+ t.row();
+ }
+ }else if(node.objectives.size > 0){
+ t.table(r -> {
+ r.add("@complete").colspan(2).left();
+ r.row();
+ for(Objective o : node.objectives){
+ if(o.complete()) continue;
+
+ r.add("> " + o.display()).color(Color.lightGray).left();
+ r.image(o.complete() ? Icon.ok : Icon.cancel, o.complete() ? Color.lightGray : Color.scarlet).padLeft(3);
+ r.row();
+ }
+ });
t.row();
}
- }else if(node.objectives.size > 0){
- t.table(r -> {
- r.add("@complete").colspan(2).left();
- r.row();
- for(Objective o : node.objectives){
- if(o.complete()) continue;
-
- r.add("> " + o.display()).color(Color.lightGray).left();
- r.image(o.complete() ? Icon.ok : Icon.cancel, o.complete() ? Color.lightGray : Color.scarlet).padLeft(3);
- r.row();
- }
- });
- t.row();
- }
- });
+ });
+ }
}else{
desc.add("@completed");
}
}).pad(9);
- if(mobile && locked(node)){
+ if(mobile && locked(node) && !net.client()){
b.row();
b.button("@research", Icon.ok, new TextButtonStyle(){{
disabled = Tex.button;
diff --git a/core/src/mindustry/ui/dialogs/SchematicsDialog.java b/core/src/mindustry/ui/dialogs/SchematicsDialog.java
index 3907f10dbe..f64cf14ca2 100644
--- a/core/src/mindustry/ui/dialogs/SchematicsDialog.java
+++ b/core/src/mindustry/ui/dialogs/SchematicsDialog.java
@@ -71,6 +71,13 @@ public class SchematicsDialog extends BaseDialog{
rebuildPane.run();
}).growX().get();
searchField.setMessageText("@schematic.search");
+ searchField.clicked(KeyCode.mouseRight, () -> {
+ if(!search.isEmpty()){
+ search = "";
+ searchField.clearText();
+ rebuildPane.run();
+ }
+ });
}).fillX().padBottom(4);
cont.row();
diff --git a/core/src/mindustry/ui/fragments/BlockConfigFragment.java b/core/src/mindustry/ui/fragments/BlockConfigFragment.java
index 356c63fca4..79ad799a3a 100644
--- a/core/src/mindustry/ui/fragments/BlockConfigFragment.java
+++ b/core/src/mindustry/ui/fragments/BlockConfigFragment.java
@@ -67,7 +67,7 @@ public class BlockConfigFragment{
}
public boolean hasConfigMouse(){
- Element e = Core.scene.hit(Core.input.mouseX(), Core.graphics.getHeight() - Core.input.mouseY(), true);
+ Element e = Core.scene.getHoverElement();
return e != null && (e == table || e.isDescendantOf(table));
}
diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java
index 70a1d15279..23c6d1a742 100644
--- a/core/src/mindustry/ui/fragments/HudFragment.java
+++ b/core/src/mindustry/ui/fragments/HudFragment.java
@@ -14,6 +14,7 @@ import arc.scene.ui.ImageButton.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
+import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.core.GameState.*;
@@ -27,8 +28,11 @@ import mindustry.input.*;
import mindustry.net.Packets.*;
import mindustry.type.*;
import mindustry.ui.*;
+import mindustry.world.*;
+import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.storage.*;
import mindustry.world.blocks.storage.CoreBlock.*;
+import mindustry.world.meta.*;
import static mindustry.Vars.*;
import static mindustry.gen.Tex.*;
@@ -36,11 +40,11 @@ import static mindustry.gen.Tex.*;
public class HudFragment{
private static final float dsize = 65f, pauseHeight = 36f;
- public final PlacementFragment blockfrag = new PlacementFragment();
+ public PlacementFragment blockfrag = new PlacementFragment();
+ public CoreItemsDisplay coreItems = new CoreItemsDisplay();
public boolean shown = true;
private ImageButton flip;
- private CoreItemsDisplay coreItems = new CoreItemsDisplay();
private String hudText = "";
private boolean showHudText;
@@ -49,6 +53,80 @@ public class HudFragment{
private Table lastUnlockLayout;
private long lastToast;
+ private Seq blocksOut = new Seq<>();
+
+ private void addBlockSelection(Table cont){
+ Table blockSelection = new Table();
+ var pane = new ScrollPane(blockSelection, Styles.smallPane);
+ pane.setFadeScrollBars(false);
+ Planet[] last = {state.rules.planet};
+ pane.update(() -> {
+ if(pane.hasScroll()){
+ Element result = Core.scene.getHoverElement();
+ if(result == null || !result.isDescendantOf(pane)){
+ Core.scene.setScrollFocus(null);
+ }
+ }
+
+ if(state.rules.planet != last[0]){
+ last[0] = state.rules.planet;
+ rebuildBlockSelection(blockSelection, "");
+ }
+ });
+
+ cont.table(search -> {
+ search.image(Icon.zoom).padRight(8);
+ search.field("", text -> rebuildBlockSelection(blockSelection, text)).growX()
+ .name("editor/search").maxTextLength(maxNameLength).get().setMessageText("@players.search");
+ }).growX().pad(-2).padLeft(6f);
+ cont.row();
+ cont.add(pane).expandY().top().left();
+
+ rebuildBlockSelection(blockSelection, "");
+ }
+
+ private void rebuildBlockSelection(Table blockSelection, String searchText){
+ blockSelection.clear();
+
+ blocksOut.clear();
+ blocksOut.addAll(Vars.content.blocks());
+ blocksOut.sort((b1, b2) -> {
+ int synth = Boolean.compare(b1.synthetic(), b2.synthetic());
+ if(synth != 0) return synth;
+ int ore = Boolean.compare(b1 instanceof OverlayFloor && b1 != Blocks.removeOre, b2 instanceof OverlayFloor && b2 != Blocks.removeOre);
+ if(ore != 0) return ore;
+ return Integer.compare(b1.id, b2.id);
+ });
+
+ int i = 0;
+
+ for(Block block : blocksOut){
+ TextureRegion region = block.uiIcon;
+
+ if(!Core.atlas.isFound(region)
+ || (!block.inEditor && !(block instanceof RemoveWall) && !(block instanceof RemoveOre))
+ || !block.isOnPlanet(state.rules.planet)
+ || block.buildVisibility == BuildVisibility.debugOnly
+ || (!searchText.isEmpty() && !block.localizedName.toLowerCase().contains(searchText.toLowerCase()))
+ ) continue;
+
+ ImageButton button = new ImageButton(Tex.whiteui, Styles.clearNoneTogglei);
+ button.getStyle().imageUp = new TextureRegionDrawable(region);
+ button.clicked(() -> control.input.block = block);
+ button.resizeImage(8 * 4f);
+ button.update(() -> button.setChecked(control.input.block == block));
+ blockSelection.add(button).size(48f).tooltip(block.localizedName);
+
+ if(++i % 6 == 0){
+ blockSelection.row();
+ }
+ }
+
+ if(i == 0){
+ blockSelection.add("@none.found").padLeft(54f).padTop(10f);
+ }
+ }
+
public void build(Group parent){
//warn about guardian/boss waves
@@ -247,26 +325,79 @@ public class HudFragment{
editorMain.name = "editor";
editorMain.table(Tex.buttonEdge4, t -> {
- //t.margin(0f);
t.name = "teams";
- t.add("@editor.teams").growX().left();
- t.row();
- t.table(teams -> {
+ t.top().table(teams -> {
teams.left();
int i = 0;
for(Team team : Team.baseTeams){
- ImageButton button = teams.button(Tex.whiteui, Styles.clearNoneTogglei, 40f, () -> Call.setPlayerTeamEditor(player, team))
+ ImageButton button = teams.button(Tex.whiteui, Styles.clearNoneTogglei, 38f, () -> Call.setPlayerTeamEditor(player, team))
.size(50f).margin(6f).get();
button.getImageCell().grow();
button.getStyle().imageUpColor = team.color;
button.update(() -> button.setChecked(player.team() == team));
- if(++i % 3 == 0){
+ if(++i % 6 == 0){
teams.row();
}
}
- }).left();
+ }).top().left();
+
+ t.row();
+
+ t.table(control.input::buildPlacementUI).growX().left().with(in -> in.left()).row();
+
+ //hovering item display
+ t.table(h -> {
+ Runnable rebuild = () -> {
+ h.clear();
+ h.left();
+
+ Displayable hover = blockfrag.hovered();
+ UnlockableContent toDisplay = control.input.block;
+
+ if(toDisplay == null && hover != null){
+ if(hover instanceof Building b){
+ toDisplay = b.block;
+ }else if(hover instanceof Tile tile){
+ toDisplay =
+ tile.block().itemDrop != null ? tile.block() :
+ tile.overlay().itemDrop != null || tile.wallDrop() != null ? tile.overlay() :
+ tile.floor();
+ }else if(hover instanceof Unit u){
+ toDisplay = u.type;
+ }
+ }
+
+ if(toDisplay != null){
+ h.image(toDisplay.uiIcon).scaling(Scaling.fit).size(8 * 4);
+ h.add(toDisplay.localizedName).ellipsis(true).left().growX().padLeft(5);
+ }
+ };
+
+ Object[] hovering = {null};
+ h.update(() -> {
+ Object nextHover = control.input.block != null ? control.input.block : blockfrag.hovered();
+ if(nextHover != hovering[0]){
+ hovering[0] = nextHover;
+ rebuild.run();
+ }
+ });
+ }).growX().left().minHeight(36f).row();
+
+ t.table(blocks -> {
+ addBlockSelection(blocks);
+ }).fillX().left();
}).width(dsize * 5 + 4f);
+ if(mobile){
+ editorMain.row().spacerY(() -> {
+ if(control.input instanceof MobileInput mob){
+ if(Core.graphics.isPortrait()) return Core.graphics.getHeight() / 2f / Scl.scl(1f);
+ if(mob.hasSchematic()) return 156f;
+ if(mob.showCancel()) return 50f;
+ }
+ return 0f;
+ });
+ }
editorMain.visible(() -> shown && state.isEditor());
//fps display
@@ -806,7 +937,7 @@ public class HudFragment{
if(state.rules.objectives.any()){
boolean first = true;
for(var obj : state.rules.objectives){
- if(!obj.qualified()) continue;
+ if(!obj.qualified() || obj.hidden) continue;
String text = obj.text();
if(text != null && !text.isEmpty()){
diff --git a/core/src/mindustry/ui/fragments/PlacementFragment.java b/core/src/mindustry/ui/fragments/PlacementFragment.java
index 2c3e6ad524..6b42c3c3fc 100644
--- a/core/src/mindustry/ui/fragments/PlacementFragment.java
+++ b/core/src/mindustry/ui/fragments/PlacementFragment.java
@@ -8,6 +8,7 @@ import arc.scene.*;
import arc.scene.event.*;
import arc.scene.style.*;
import arc.scene.ui.*;
+import arc.scene.ui.Tooltip.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
@@ -25,6 +26,7 @@ import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.blocks.ConstructBlock.*;
+import mindustry.world.meta.*;
import static mindustry.Vars.*;
@@ -122,9 +124,7 @@ public class PlacementFragment{
toggler.setZIndex(index);
}
- boolean gridUpdate(InputHandler input){
- scrollPositions.put(currentCategory, blockPane.getScrollY());
-
+ boolean updatePick(InputHandler input){
if(Core.input.keyTap(Binding.pick) && player.isBuilder() && !Core.scene.hasDialog()){ //mouse eyedropper select
var build = world.buildWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y);
@@ -144,13 +144,34 @@ public class PlacementFragment{
}
}
- if(tryRecipe != null && tryRecipe.isVisible() && unlocked(tryRecipe)){
+ if(tryRecipe == null && state.rules.editor){
+ var tile = world.tileWorld(Core.input.mouseWorldX(), Core.input.mouseWorldY());
+ if(tile != null){
+ tryRecipe =
+ tile.block() != Blocks.air ? tile.block() :
+ tile.overlay() != Blocks.air ? tile.overlay() :
+ tile.floor() != Blocks.air ? tile.floor() : null;
+ }
+ }
+
+ if(tryRecipe != null && ((tryRecipe.isVisible() && unlocked(tryRecipe)) || state.rules.editor)){
input.block = tryRecipe;
tryRecipe.lastConfig = tryConfig;
- currentCategory = input.block.category;
+ if(tryRecipe.isVisible()){
+ currentCategory = input.block.category;
+ }
return true;
}
}
+ return false;
+ }
+
+ boolean gridUpdate(InputHandler input){
+ scrollPositions.put(currentCategory, blockPane.getScrollY());
+
+ if(updatePick(input)){
+ return true;
+ }
if(ui.chatfrag.shown() || ui.consolefrag.shown() || Core.scene.hasKeyboard()) return false;
@@ -244,7 +265,14 @@ public class PlacementFragment{
public void build(Group parent){
parent.fill(full -> {
toggler = full;
- full.bottom().right().visible(() -> ui.hudfrag.shown);
+ full.bottom().right().visible(() -> {
+ if(state.rules.editor){
+ //force update the mouse picking, since it otherwise would not happen
+ updatePick(control.input);
+ }
+
+ return ui.hudfrag.shown && !state.rules.editor;
+ });
full.table(frame -> {
@@ -386,7 +414,7 @@ public class PlacementFragment{
}
}).growX().left().margin(3);
- if(!displayBlock.isPlaceable() || !player.isBuilder()){
+ if((!displayBlock.isPlaceable() || !player.isBuilder()) && !state.rules.editor){
topTable.row();
topTable.table(b -> {
b.image(Icon.cancel).padRight(2).color(Color.scarlet);
@@ -465,7 +493,10 @@ public class PlacementFragment{
for(int i = 0; i < counts.length; i++){
if(counts[i] > 0){
var type = content.unit(i);
- unitlist.add(new ItemImage(type.uiIcon, counts[i])).tooltip(type.localizedName).pad(4).with(b -> {
+ unitlist.add(StatValues.stack(type, counts[i])).pad(4).with(b -> {
+ b.clearListeners();
+ b.addListener(Tooltips.getInstance().create(type.localizedName, false));
+
var listener = new ClickListener();
//left click -> select
@@ -494,7 +525,7 @@ public class PlacementFragment{
firstCommand = true;
}else{
//remove commands that this next unit type doesn't have
- commands.removeAll(com -> !Structs.contains(type.commands, com));
+ commands.removeAll(com -> !type.commands.contains(com));
}
if(!firstStance){
@@ -502,7 +533,7 @@ public class PlacementFragment{
firstStance = true;
}else{
//remove commands that this next unit type doesn't have
- stances.removeAll(st -> !Structs.contains(type.stances, st));
+ stances.removeAll(st -> !type.stances.contains(st));
}
}
}
@@ -529,6 +560,10 @@ public class PlacementFragment{
if(stances.size > 1){
u.row();
+ if(commands.size > 1){
+ u.add(new Image(Tex.whiteui)).height(3f).color(Pal.gray).pad(7f).growX().row();
+ }
+
u.table(coms -> {
coms.left();
int scol = 0;
@@ -615,7 +650,7 @@ public class PlacementFragment{
blocksSelect.margin(4).marginTop(0);
blockPane = blocksSelect.pane(blocks -> blockTable = blocks).height(194f).update(pane -> {
if(pane.hasScroll()){
- Element result = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true);
+ Element result = Core.scene.getHoverElement();
if(result == null || !result.isDescendantOf(pane)){
Core.scene.setScrollFocus(null);
}
@@ -623,7 +658,11 @@ public class PlacementFragment{
}).grow().get();
blockPane.setStyle(Styles.smallPane);
blocksSelect.row();
- blocksSelect.table(control.input::buildPlacementUI).name("inputTable").growX();
+ blocksSelect.table(t -> {
+ t.image().color(Pal.gray).height(4f).colspan(4).growX();
+ t.row();
+ control.input.buildPlacementUI(t);
+ }).name("inputTable").growX();
}).fillY().bottom().touchable(Touchable.enabled);
blockCatTable.table(categories -> {
categories.bottom();
@@ -700,8 +739,8 @@ public class PlacementFragment{
}
boolean unlocked(Block block){
- return block.unlockedNow() && block.placeablePlayer && block.environmentBuildable() &&
- block.supportsEnv(state.rules.env); //TODO this hides env unsupported blocks, not always a good thing
+ return block.unlockedNowHost() && block.placeablePlayer && block.environmentBuildable() &&
+ block.supportsEnv(state.rules.env);
}
boolean hasInfoBox(){
@@ -709,13 +748,14 @@ public class PlacementFragment{
return control.input.block != null || menuHoverBlock != null || hover != null;
}
- /** Returns the thing being hovered over. */
- @Nullable
- Displayable hovered(){
- Vec2 v = topTable.stageToLocalCoordinates(Core.input.mouse());
+ /** @return the thing being hovered over. */
+ public @Nullable Displayable hovered(){
+ if(!state.rules.editor){
+ Vec2 v = topTable.stageToLocalCoordinates(Core.input.mouse());
- //if the mouse intersects the table or the UI has the mouse, no hovering can occur
- if(Core.scene.hasMouse() || topTable.hit(v.x, v.y, false) != null) return null;
+ //if the mouse intersects the table or the UI has the mouse, no hovering can occur
+ if(Core.scene.hasMouse() || topTable.hit(v.x, v.y, false) != null) return null;
+ }
//check for a unit
Unit unit = Units.closestOverlap(player.team(), Core.input.mouseWorldX(), Core.input.mouseWorldY(), 5f, u -> !u.isLocal() && u.displayable());
diff --git a/core/src/mindustry/ui/fragments/PlanConfigFragment.java b/core/src/mindustry/ui/fragments/PlanConfigFragment.java
new file mode 100644
index 0000000000..2303bbf6a6
--- /dev/null
+++ b/core/src/mindustry/ui/fragments/PlanConfigFragment.java
@@ -0,0 +1,83 @@
+package mindustry.ui.fragments;
+
+import arc.*;
+import arc.math.*;
+import arc.math.geom.*;
+import arc.scene.*;
+import arc.scene.actions.*;
+import arc.scene.ui.layout.*;
+import arc.struct.*;
+import arc.util.*;
+import mindustry.ctype.*;
+import mindustry.entities.units.*;
+import mindustry.game.*;
+import mindustry.world.*;
+import mindustry.world.blocks.*;
+
+import static mindustry.Vars.*;
+
+/**
+ * Displays the configuration UI for build plans before they have been placed.
+ * Shamelessly stolen from Foo's Client.
+ */
+public class PlanConfigFragment{
+ Table table = new Table();
+ BuildPlan selected;
+
+ public void build(Group parent){
+ table.visible = false;
+ parent.addChild(table);
+
+ Events.on(EventType.ResetEvent.class, e -> forceHide());
+ }
+
+ public void showConfig(BuildPlan plan){
+ if(this.selected == plan || plan.block == null){
+ hide();
+ return;
+ }
+ Block block = plan.block;
+ if(!block.configurable) return;
+ selected = plan;
+ table.clear();
+
+ var options = new Seq();
+ block.getPlanConfigs(options);
+
+ if(options.isEmpty()) return;
+
+ ItemSelection.buildTable(
+ table, options,
+ () -> selected != null ? (selected.config instanceof UnlockableContent c ? c : null) : null,
+ content -> {
+ selected.config = content;
+ hide();
+ },
+ block.selectionRows, block.selectionColumns
+ );
+ table.pack();
+ table.setTransform(true);
+ table.visible = true;
+ table.actions(Actions.scaleTo(0f, 1f), Actions.visible(true),
+ Actions.scaleTo(1f, 1f, 0.07f, Interp.pow3Out));
+ table.update(() -> {
+ table.setOrigin(Align.center);
+ if(plan.isDone() || !(control.input.selectPlans.contains(plan) || player.dead() || player.unit().plans.contains(plan))){
+ this.hide();
+ return;
+ }
+ Vec2 pos = Core.input.mouseScreen(plan.drawx(), plan.drawy() - block.size * tilesize / 2.0F - 1);
+ table.setPosition(pos.x, pos.y, Align.top);
+ });
+ }
+
+ public void forceHide(){
+ table.visible = false;
+ selected = null;
+ }
+
+ public void hide(){
+ selected = null;
+ table.actions(Actions.scaleTo(0f, 1f, 0.06f, Interp.pow3Out), Actions.visible(false));
+ }
+}
\ No newline at end of file
diff --git a/core/src/mindustry/ui/fragments/PlayerListFragment.java b/core/src/mindustry/ui/fragments/PlayerListFragment.java
index 9286aab195..58d82ae32d 100644
--- a/core/src/mindustry/ui/fragments/PlayerListFragment.java
+++ b/core/src/mindustry/ui/fragments/PlayerListFragment.java
@@ -13,7 +13,6 @@ import arc.util.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.graphics.*;
-import mindustry.input.*;
import mindustry.net.*;
import mindustry.net.Packets.*;
import mindustry.ui.*;
@@ -127,11 +126,8 @@ public class PlayerListFragment{
iconTable.tapped(() -> {
if(!user.dead() && clickable){
- Core.camera.position.set(user.unit());
+ control.input.spectate(user.unit());
ui.showInfoFade(Core.bundle.format("viewplayer", user.name), 1f);
- if(control.input instanceof DesktopInput input){
- input.panning = true;
- }
}
});
diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java
index d2b2cbf2fa..9daa65d5aa 100644
--- a/core/src/mindustry/world/Block.java
+++ b/core/src/mindustry/world/Block.java
@@ -58,7 +58,7 @@ public class Block extends UnlockableContent implements Senseable{
/** If true, this block can output payloads; affects blending. */
public boolean outputsPayload = false;
/** If true, this block can input payloads; affects unit payload enter behavior. */
- public boolean acceptsPayloads = false;
+ public boolean acceptsUnitPayloads = false;
/** If true, payloads will attempt to move into this block. */
public boolean acceptsPayload = false;
/** Visual flag use for blending of certain transportation blocks. */
@@ -328,6 +328,8 @@ public class Block extends UnlockableContent implements Senseable{
public boolean instantDeconstruct = false;
/** If true, this block constructs immediately. This implies no resource requirement, and ignores configs - do not use, this is for performance only! */
public boolean instantBuild = false;
+ /** If true, this block can be placed even in "dark" areas. Only used for editor static walls. */
+ public boolean ignoreBuildDarkness = false;
/** Effect for placing the block. Passes size as rotation. */
public Effect placeEffect = Fx.placeBlock;
/** Effect for breaking the block. Passes size as rotation. */
@@ -441,6 +443,14 @@ public class Block extends UnlockableContent implements Senseable{
Drawf.square(other.x, other.y, other.block.size * tilesize / 2f + 2f, Pal.place);
});
+
+ BeamNode.getNodeLinks(tile, this, player.team(), other -> {
+ BeamNode node = (BeamNode)other.block;
+ Draw.color(node.laserColor1, Renderer.laserOpacity * 0.5f);
+ node.drawLaser(other.x, other.y, x * tilesize + offset, y * tilesize + offset, size, other.block.size);
+
+ Drawf.square(other.x, other.y, other.block.size * tilesize / 2f + 2f, Pal.place);
+ });
}
}
}
@@ -891,10 +901,6 @@ public class Block extends UnlockableContent implements Senseable{
return !isHidden() && (state.rules.editor || (!state.rules.hideBannedBlocks || !state.rules.isBanned(this)));
}
- public boolean isVisibleOn(Planet planet){
- return !Structs.contains(requirements, i -> planet.hiddenItems.contains(i.item));
- }
-
public boolean isPlaceable(){
return isVisible() && (!state.rules.isBanned(this) || state.rules.editor) && supportsEnv(state.rules.env);
}
@@ -914,6 +920,11 @@ public class Block extends UnlockableContent implements Senseable{
placeBegan(tile, previous);
}
+ /** Called when building of this block ends. */
+ public void placeEnded(Tile tile, @Nullable Unit builder){
+
+ }
+
/** Called right before building of this block begins. */
public void beforePlaceBegan(Tile tile, Block previous){
@@ -940,7 +951,7 @@ public class Block extends UnlockableContent implements Senseable{
}
public boolean environmentBuildable(){
- return (state.rules.hiddenBuildItems.isEmpty() || !Structs.contains(requirements, i -> state.rules.hiddenBuildItems.contains(i.item)));
+ return isOnPlanet(state.getPlanet());
}
public boolean isStatic(){
@@ -1156,10 +1167,28 @@ public class Block extends UnlockableContent implements Senseable{
return buildVisibility != BuildVisibility.hidden;
}
+ @Override
+ public void postInit(){
+ //usually, an empty set of planets is a configuration error. auto-assign based on requirements
+ if(requirements.length > 0 && shownPlanets.isEmpty()){
+ for(Planet planet : content.planets()){
+ if(planet.isLandable()){
+ if(!Structs.contains(requirements, s -> !s.item.isOnPlanet(planet))){
+ shownPlanets.add(planet);
+ }
+ }
+ }
+ }
+
+ super.postInit();
+ }
+
/** Called after all blocks are created. */
@Override
@CallSuper
public void init(){
+ super.init();
+
//disable standard shadow
if(customShadow){
hasShadow = false;
@@ -1402,6 +1431,16 @@ public class Block extends UnlockableContent implements Senseable{
}
}
+ /** Fills the specified array with the list of configuration options this block has. Only used for plans. */
+ public void getPlanConfigs(Seq options){
+ if(configurations.containsKey(Item.class)){
+ options.add(content.items());
+ }
+ if(configurations.containsKey(Liquid.class)){
+ options.add(content.liquids());
+ }
+ }
+
@Override
public double sense(LAccess sensor){
return switch(sensor){
diff --git a/core/src/mindustry/world/Build.java b/core/src/mindustry/world/Build.java
index a47363df2f..d0129890fc 100644
--- a/core/src/mindustry/world/Build.java
+++ b/core/src/mindustry/world/Build.java
@@ -157,19 +157,25 @@ public class Build{
result.placeBegan(tile, previous, unit);
}
- /** Returns whether a tile can be placed at this location by this team. */
+ /** @return whether a tile can be placed at this location by this team. */
public static boolean validPlace(Block type, Team team, int x, int y, int rotation){
return validPlace(type, team, x, y, rotation, true);
}
- /** Returns whether a tile can be placed at this location by this team. */
+ /** @return whether a tile can be placed at this location by this team. */
public static boolean validPlace(Block type, Team team, int x, int y, int rotation, boolean checkVisible){
- //the wave team can build whatever they want as long as it's visible - banned blocks are not applicable
- if(type == null || (checkVisible && (!type.environmentBuildable() || (!type.isPlaceable() && !(state.rules.waves && team == state.rules.waveTeam && type.isVisible()))))){
- return false;
- }
+ return validPlaceIgnoreUnits(type, team, x, y, rotation, checkVisible) && checkNoUnitOverlap(type, x, y);
+ }
- if((type.solid || type.solidifes) && Units.anyEntities(x * tilesize + type.offset - type.size*tilesize/2f, y * tilesize + type.offset - type.size*tilesize/2f, type.size * tilesize, type.size*tilesize)){
+ /** @return whether a tile can be placed at this location by this team. */
+ public static boolean checkNoUnitOverlap(Block type, int x, int y){
+ return (!type.solid && !type.solidifes) || !Units.anyEntities(x * tilesize + type.offset - type.size * tilesize / 2f, y * tilesize + type.offset - type.size * tilesize / 2f, type.size * tilesize, type.size * tilesize);
+ }
+
+ /** Returns whether a tile can be placed at this location by this team. Ignores units at this location. */
+ public static boolean validPlaceIgnoreUnits(Block type, Team team, int x, int y, int rotation, boolean checkVisible){
+ //the wave team can build whatever they want as long as it's visible - banned blocks are not applicable
+ if(type == null || (!state.rules.editor && (checkVisible && (!type.environmentBuildable() || (!type.isPlaceable() && !(state.rules.waves && team == state.rules.waveTeam && type.isVisible())))))){
return false;
}
@@ -199,13 +205,17 @@ public class Build{
if(tile == null) return false;
+ if(!type.canPlaceOn(tile, team, rotation)){
+ return false;
+ }
+
//floors have different checks
if(type.isFloor()){
return type.isOverlay() ? tile.overlay() != type : tile.floor() != type;
}
//campaign darkness check
- if(world.getDarkness(x, y) >= 3){
+ if(!type.ignoreBuildDarkness && world.getDarkness(x, y) >= 3){
return false;
}
@@ -213,10 +223,6 @@ public class Build{
return false;
}
- if(!type.canPlaceOn(tile, team, rotation)){
- return false;
- }
-
int offsetx = -(type.size - 1) / 2;
int offsety = -(type.size - 1) / 2;
@@ -233,7 +239,7 @@ public class Build{
(check.floor().isDeep() && !type.floating && !type.requiresWater && !type.placeableLiquid) || //deep water
(type == check.block() && check.build != null && rotation == check.build.rotation && type.rotate && !((type == check.block && team != Team.derelict && check.team() == Team.derelict))) || //same block, same rotation
!check.interactable(team) || //cannot interact
- !check.floor().placeableOn || //solid floor
+ !check.floor().placeableOn && !type.ignoreBuildDarkness || //solid floor
(!checkVisible && !check.block().alwaysReplace) || //replacing a block that should be replaced (e.g. payload placement)
!(((type.canReplace(check.block()) || (type == check.block && team != Team.derelict && state.rules.derelictRepair && check.team() == Team.derelict)) || //can replace type OR can replace derelict block of same type
(check.build instanceof ConstructBuild build && build.current == type && check.centerX() == tile.x && check.centerY() == tile.y)) && //same type in construction
diff --git a/core/src/mindustry/world/DirectionalItemBuffer.java b/core/src/mindustry/world/DirectionalItemBuffer.java
index 48cbdc84c0..f71aa74671 100644
--- a/core/src/mindustry/world/DirectionalItemBuffer.java
+++ b/core/src/mindustry/world/DirectionalItemBuffer.java
@@ -23,7 +23,7 @@ public class DirectionalItemBuffer{
public void accept(int buffer, Item item){
if(!accepts(buffer)) return;
- buffers[buffer][indexes[buffer]++] = BufferItem.get((byte)item.id, Time.time);
+ buffers[buffer][indexes[buffer]++] = BufferItem.get(item.id, Time.time);
}
public Item poll(int buffer, float speed){
@@ -54,11 +54,21 @@ public class DirectionalItemBuffer{
}
public void read(Reads read){
+ read(read, false);
+ }
+
+ public void read(Reads read, boolean legacy){
for(int i = 0; i < 4; i++){
indexes[i] = read.b();
byte length = read.b();
for(int j = 0; j < length; j++){
long value = read.l();
+
+ if(legacy){
+ //read value as the old format with 1-byte items, and create a new one with the new 2-byte format
+ value = BufferItem.get(BufferItemLegacy.item(value), BufferItemLegacy.time(value));
+ }
+
if(j < buffers[i].length){
buffers[i][j] = value;
}
@@ -68,6 +78,12 @@ public class DirectionalItemBuffer{
@Struct
class BufferItemStruct{
+ short item;
+ float time;
+ }
+
+ @Struct
+ class BufferItemLegacyStruct{
byte item;
float time;
}
diff --git a/core/src/mindustry/world/Tile.java b/core/src/mindustry/world/Tile.java
index 9fedd0aa27..45fad8a3e0 100644
--- a/core/src/mindustry/world/Tile.java
+++ b/core/src/mindustry/world/Tile.java
@@ -293,6 +293,9 @@ public class Tile implements Position, QuadTreeObject, Displayable{
if(build != null){
build.onProximityUpdate();
}
+ if(!world.isGenerating() && pathfinder != null){
+ pathfinder.updateTile(this);
+ }
}
public boolean isEditorTile(){
@@ -690,6 +693,42 @@ public class Tile implements Position, QuadTreeObject, Displayable{
//remote utility methods
+ /** Positions are in 'packed position' format - left bits x, right bits y. */
+ @Remote(called = Loc.server)
+ public static void setTileBlocks(Block block, Team team, int[] positions){
+ if(block == null || positions == null) return;
+ for(int pos : positions){
+ Tile tile = world.tile(pos);
+ if(tile != null){
+ tile.setBlock(block, team, 0);
+ }
+ }
+ }
+
+ /** Positions are in 'packed position' format - left bits x, right bits y. */
+ @Remote(called = Loc.server)
+ public static void setTileFloors(Block block, int[] positions){
+ if(positions == null || !(block instanceof Floor floor)) return;
+ for(int pos : positions){
+ Tile tile = world.tile(pos);
+ if(tile != null){
+ tile.setFloor(floor);
+ }
+ }
+ }
+
+ /** Positions are in 'packed position' format - left bits x, right bits y. */
+ @Remote(called = Loc.server)
+ public static void setTileOverlays(Block block, int[] positions){
+ if(positions == null || !(block instanceof OverlayFloor floor)) return;
+ for(int pos : positions){
+ Tile tile = world.tile(pos);
+ if(tile != null){
+ tile.setOverlay(floor);
+ }
+ }
+ }
+
@Remote(called = Loc.server)
public static void setFloor(Tile tile, Block floor, Block overlay){
tile.setFloor(floor.asFloor());
@@ -719,6 +758,17 @@ public class Tile implements Position, QuadTreeObject, Displayable{
}
}
+ @Remote(called = Loc.server)
+ public static void setTeams(int[] positions, Team team){
+ if(positions == null) return;
+ for(int pos : positions){
+ Tile tile = world.tile(pos);
+ if(tile != null && tile.build != null){
+ tile.build.changeTeam(team);
+ }
+ }
+ }
+
@Remote(called = Loc.server)
public static void buildDestroyed(Building build){
if(build == null) return;
diff --git a/core/src/mindustry/world/blocks/Autotiler.java b/core/src/mindustry/world/blocks/Autotiler.java
index fa62143fd5..4cefac1434 100644
--- a/core/src/mindustry/world/blocks/Autotiler.java
+++ b/core/src/mindustry/world/blocks/Autotiler.java
@@ -189,14 +189,14 @@ public interface Autotiler{
default boolean blendsArmored(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
return Point2.equals(tile.x + Geometry.d4(rotation).x, tile.y + Geometry.d4(rotation).y, otherx, othery)
- || ((!otherblock.rotatedOutput(otherx, othery) && Edges.getFacingEdge(otherblock, otherx, othery, tile) != null &&
+ || ((!otherblock.rotatedOutput(otherx, othery, tile) && Edges.getFacingEdge(otherblock, otherx, othery, tile) != null &&
Edges.getFacingEdge(otherblock, otherx, othery, tile).relativeTo(tile) == rotation) ||
- (otherblock.rotatedOutput(otherx, othery) && Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y)));
+ (otherblock.rotatedOutput(otherx, othery, tile) && Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y)));
}
/** @return whether this other block is *not* looking at this one. */
default boolean notLookingAt(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
- return !(otherblock.rotatedOutput(otherx, othery) && Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y));
+ return !(otherblock.rotatedOutput(otherx, othery, tile) && Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y));
}
/** @return whether this tile is looking at the other tile, or the other tile is looking at this one.
diff --git a/core/src/mindustry/world/blocks/ConstructBlock.java b/core/src/mindustry/world/blocks/ConstructBlock.java
index f45822964a..0a49f8212f 100644
--- a/core/src/mindustry/world/blocks/ConstructBlock.java
+++ b/core/src/mindustry/world/blocks/ConstructBlock.java
@@ -110,6 +110,8 @@ public class ConstructBlock extends Block{
if(shouldPlay()) block.placeSound.at(tile, block.placePitchChange ? calcPitch(true) : 1f);
}
+ block.placeEnded(tile, builder);
+
Events.fire(new BlockBuildEndEvent(tile, builder, team, false, config));
}
@@ -358,7 +360,9 @@ public class ConstructBlock extends Block{
int target = Mathf.round(requirements[i].amount * state.rules.buildCostMultiplier * state.rules.deconstructRefundMultiplier);
int remaining = target - itemsLeft[i];
- core.items.add(current.requirements[i].item, Mathf.clamp(remaining, 0, core.storageCapacity - core.items.get(current.requirements[i].item)));
+ if(requirements[i].item.unlockedNowHost()){
+ core.items.add(requirements[i].item, Mathf.clamp(remaining, 0, core.storageCapacity - core.items.get(requirements[i].item)));
+ }
itemsLeft[i] = target;
}
}
diff --git a/core/src/mindustry/world/blocks/ExplosionShield.java b/core/src/mindustry/world/blocks/ExplosionShield.java
new file mode 100644
index 0000000000..892795632c
--- /dev/null
+++ b/core/src/mindustry/world/blocks/ExplosionShield.java
@@ -0,0 +1,7 @@
+package mindustry.world.blocks;
+
+//TODO: horrible API design, but I'm not sure of a better way to do this right now. please don't use this class
+public interface ExplosionShield{
+ /** @return whether the shield was able to absorb the explosion; this should apply damage to the shield if true is returned. */
+ boolean absorbExplosion(float x, float y, float damage);
+}
diff --git a/core/src/mindustry/world/blocks/ItemSelection.java b/core/src/mindustry/world/blocks/ItemSelection.java
index 483ba28134..6bbe2ba127 100644
--- a/core/src/mindustry/world/blocks/ItemSelection.java
+++ b/core/src/mindustry/world/blocks/ItemSelection.java
@@ -1,5 +1,6 @@
package mindustry.world.blocks;
+import arc.*;
import arc.func.*;
import arc.math.*;
import arc.scene.style.*;
@@ -9,7 +10,6 @@ import arc.struct.*;
import arc.util.*;
import mindustry.ctype.*;
import mindustry.gen.*;
-import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
@@ -65,7 +65,7 @@ public class ItemSelection{
Seq list = items.select(u -> (text.isEmpty() || u.localizedName.toLowerCase().contains(text.toLowerCase())));
for(T item : list){
- if(!item.unlockedNow() || (item instanceof Item checkVisible && state.rules.hiddenBuildItems.contains(checkVisible)) || item.isHidden()) continue;
+ if(!item.unlockedNow() || !item.isOnPlanet(state.getPlanet()) || item.isHidden()) continue;
ImageButton button = cont.button(Tex.whiteui, Styles.clearNoneTogglei, Mathf.clamp(item.selectionSize, 0f, 40f), () -> {
if(closeSelect) control.input.config.hideConfig();
@@ -94,6 +94,11 @@ public class ItemSelection{
ScrollPane pane = new ScrollPane(cont, Styles.smallPane);
pane.setScrollingDisabled(true, false);
+ pane.exited(() -> {
+ if(pane.hasScroll()){
+ Core.scene.setScrollFocus(null);
+ }
+ });
if(block != null){
pane.setScrollYForce(block.selectScroll);
diff --git a/core/src/mindustry/world/blocks/campaign/LaunchPad.java b/core/src/mindustry/world/blocks/campaign/LaunchPad.java
index a41ca50edc..440029ebf4 100644
--- a/core/src/mindustry/world/blocks/campaign/LaunchPad.java
+++ b/core/src/mindustry/world/blocks/campaign/LaunchPad.java
@@ -56,8 +56,6 @@ public class LaunchPad extends Block{
super.setBars();
addBar("items", entity -> new Bar(() -> Core.bundle.format("bar.items", entity.items.total()), () -> Pal.items, () -> (float)entity.items.total() / itemCapacity));
-
- //TODO is "bar.launchcooldown" the right terminology?
addBar("progress", (LaunchPadBuild build) -> new Bar(() -> Core.bundle.get("bar.launchcooldown"), () -> Pal.ammo, () -> Mathf.clamp(build.launchCounter / launchTime)));
}
diff --git a/core/src/mindustry/world/blocks/defense/BaseShield.java b/core/src/mindustry/world/blocks/defense/BaseShield.java
index 32bc077e8f..bb1f0dd6fe 100644
--- a/core/src/mindustry/world/blocks/defense/BaseShield.java
+++ b/core/src/mindustry/world/blocks/defense/BaseShield.java
@@ -19,6 +19,8 @@ public class BaseShield extends Block{
//TODO game rule? or field? should vary by base.
public float radius = 200f;
public int sides = 24;
+
+ public @Nullable Color shieldColor;
protected static BaseShieldBuild paramBuild;
//protected static Effect paramEffect;
@@ -125,7 +127,7 @@ public class BaseShield extends Block{
Draw.z(Layer.shields);
- Draw.color(team.color, Color.white, Mathf.clamp(hit));
+ Draw.color(shieldColor == null ? team.color : shieldColor, Color.white, Mathf.clamp(hit));
if(renderer.animateShields){
Fill.poly(x, y, sides, radius);
diff --git a/core/src/mindustry/world/blocks/defense/BuildTurret.java b/core/src/mindustry/world/blocks/defense/BuildTurret.java
index 10330650ac..a6468c5433 100644
--- a/core/src/mindustry/world/blocks/defense/BuildTurret.java
+++ b/core/src/mindustry/world/blocks/defense/BuildTurret.java
@@ -146,10 +146,10 @@ public class BuildTurret extends BaseTurret{
for(int i = 0; i < blocks.size; i++){
var block = blocks.get(i);
if(within(block.x * tilesize, block.y * tilesize, range)){
- var btype = content.block(block.block);
+ var btype = block.block;
if(Build.validPlace(btype, unit.team(), block.x, block.y, block.rotation) && (state.rules.infiniteResources || team.rules().infiniteResources || team.items().has(btype.requirements, state.rules.buildCostMultiplier))){
- unit.addBuild(new BuildPlan(block.x, block.y, block.rotation, content.block(block.block), block.config));
+ unit.addBuild(new BuildPlan(block.x, block.y, block.rotation, block.block, block.config));
//shift build plan to tail so next unit builds something else
blocks.addLast(blocks.removeIndex(i));
lastPlan = block;
diff --git a/core/src/mindustry/world/blocks/defense/ForceProjector.java b/core/src/mindustry/world/blocks/defense/ForceProjector.java
index 74f0fd4860..0013d4c2ff 100644
--- a/core/src/mindustry/world/blocks/defense/ForceProjector.java
+++ b/core/src/mindustry/world/blocks/defense/ForceProjector.java
@@ -6,6 +6,7 @@ import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
+import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.annotations.Annotations.*;
@@ -18,6 +19,7 @@ import mindustry.graphics.*;
import mindustry.logic.*;
import mindustry.ui.*;
import mindustry.world.*;
+import mindustry.world.blocks.*;
import mindustry.world.consumers.*;
import mindustry.world.meta.*;
@@ -38,6 +40,7 @@ public class ForceProjector extends Block{
public float cooldownBrokenBase = 0.35f;
public float coolantConsumption = 0.1f;
public boolean consumeCoolant = true;
+ public float crashDamageMultiplier = 2f;
public Effect absorbEffect = Fx.absorb;
public Effect shieldBreakEffect = Fx.shieldBreak;
public @Load("@-top") TextureRegion topRegion;
@@ -48,7 +51,7 @@ public class ForceProjector extends Block{
protected static ForceBuild paramEntity;
protected static Effect paramEffect;
protected static final Cons shieldConsumer = bullet -> {
- if(bullet.team != paramEntity.team && bullet.type.absorbable && Intersector.isInRegularPolygon(((ForceProjector)(paramEntity.block)).sides, paramEntity.x, paramEntity.y, paramEntity.realRadius(), ((ForceProjector)(paramEntity.block)).shieldRotation, bullet.x, bullet.y)){
+ if(bullet.team != paramEntity.team && bullet.type.absorbable && !bullet.absorbed && Intersector.isInRegularPolygon(((ForceProjector)(paramEntity.block)).sides, paramEntity.x, paramEntity.y, paramEntity.realRadius(), ((ForceProjector)(paramEntity.block)).shieldRotation, bullet.x, bullet.y)){
bullet.absorb();
paramEffect.at(bullet);
paramEntity.hit = 1f;
@@ -67,6 +70,7 @@ public class ForceProjector extends Block{
envEnabled |= Env.space;
ambientSound = Sounds.shield;
ambientSoundVolume = 0.08f;
+ flags = EnumSet.of(BlockFlag.shield);
if(consumeCoolant){
consume(coolantConsumer = new ConsumeCoolant(coolantConsumption)).boost().update(false);
@@ -119,7 +123,7 @@ public class ForceProjector extends Block{
Draw.color();
}
- public class ForceBuild extends Building implements Ranged{
+ public class ForceBuild extends Building implements Ranged, ExplosionShield{
public boolean broken = true;
public float buildup, radscl, hit, warmup, phaseHeat;
@@ -213,6 +217,17 @@ public class ForceProjector extends Block{
}
}
+ @Override
+ public boolean absorbExplosion(float ex, float ey, float damage){
+ boolean absorb = !broken && Intersector.isInRegularPolygon(sides, x, y, realRadius(), shieldRotation, ex, ey);
+ if(absorb){
+ absorbEffect.at(ex, ey);
+ hit = 1f;
+ buildup += damage * crashDamageMultiplier;
+ }
+ return absorb;
+ }
+
public float realRadius(){
return (radius + phaseHeat * phaseRadiusBoost) * radscl;
}
@@ -237,7 +252,7 @@ public class ForceProjector extends Block{
Draw.z(Layer.block);
Draw.reset();
}
-
+
drawShield();
}
@@ -266,6 +281,14 @@ public class ForceProjector extends Block{
Draw.reset();
}
+ @Override
+ public void overwrote(Seq previous){
+ if(previous.size > 0 && previous.first().block == block && previous.first() instanceof ForceBuild b){
+ broken = b.broken;
+ buildup = b.buildup;
+ }
+ }
+
@Override
public void write(Writes write){
super.write(write);
diff --git a/core/src/mindustry/world/blocks/defense/turrets/ContinuousLiquidTurret.java b/core/src/mindustry/world/blocks/defense/turrets/ContinuousLiquidTurret.java
index ffd50d5b3d..b785e3ec4f 100644
--- a/core/src/mindustry/world/blocks/defense/turrets/ContinuousLiquidTurret.java
+++ b/core/src/mindustry/world/blocks/defense/turrets/ContinuousLiquidTurret.java
@@ -50,13 +50,6 @@ public class ContinuousLiquidTurret extends ContinuousTurret{
public void display(Stats stats){
}
-
- //TODO
- //@Override
- //protected float use(Building entity){
- // BulletType type = ammoTypes.get(entity.liquids.current());
- // return Math.min(amount * entity.edelta(), entity.block.liquidCapacity) / (type == null ? 1f : type.ammoMultiplier);
- //}
});
ammoTypes.each((item, type) -> placeOverlapRange = Math.max(placeOverlapRange, range + type.rangeChange + placeOverlapMargin));
@@ -73,9 +66,9 @@ public class ContinuousLiquidTurret extends ContinuousTurret{
@Override
public void updateTile(){
- unit.ammo(unit.type().ammoCapacity * liquids.currentAmount() / liquidCapacity);
-
super.updateTile();
+
+ unit.ammo(unit.type().ammoCapacity * liquids.currentAmount() / liquidCapacity);
}
@Override
diff --git a/core/src/mindustry/world/blocks/defense/turrets/ContinuousTurret.java b/core/src/mindustry/world/blocks/defense/turrets/ContinuousTurret.java
index cfd5171b41..36e1b46266 100644
--- a/core/src/mindustry/world/blocks/defense/turrets/ContinuousTurret.java
+++ b/core/src/mindustry/world/blocks/defense/turrets/ContinuousTurret.java
@@ -15,6 +15,7 @@ public class ContinuousTurret extends Turret{
public BulletType shootType = Bullets.placeholder;
/** Speed at which the turret can change its bullet "aim" distance. This is only used for point laser bullets. */
public float aimChangeSpeed = Float.POSITIVE_INFINITY;
+ public boolean scaleDamageEfficiency = false;
public ContinuousTurret(String name){
super(name);
@@ -115,6 +116,9 @@ public class ContinuousTurret extends Turret{
entry.bullet.aimX = Tmp.v1.x;
entry.bullet.aimY = Tmp.v1.y;
+ if(scaleDamageEfficiency){
+ entry.bullet.damage = entry.bullet.type.damage * Math.min(efficiency, 1f) * entry.bullet.damageMultiplier();
+ }
if(isShooting() && hasAmmo()){
entry.bullet.time = entry.bullet.lifetime * entry.bullet.type.optimalLifeFract * Math.min(shootWarmup, efficiency);
diff --git a/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java b/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java
index 6d3683958f..d1d79ae868 100644
--- a/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java
+++ b/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java
@@ -85,7 +85,6 @@ public class LaserTurret extends PowerTurret{
heat = 1f;
curRecoil = 1f;
}else if(reloadCounter > 0){
- wasShooting = true;
if(coolant != null){
//TODO does not handle multi liquid req?
diff --git a/core/src/mindustry/world/blocks/defense/turrets/ReloadTurret.java b/core/src/mindustry/world/blocks/defense/turrets/ReloadTurret.java
index 9203869459..8748b91ed8 100644
--- a/core/src/mindustry/world/blocks/defense/turrets/ReloadTurret.java
+++ b/core/src/mindustry/world/blocks/defense/turrets/ReloadTurret.java
@@ -1,9 +1,6 @@
package mindustry.world.blocks.defense.turrets;
import arc.math.*;
-import arc.struct.*;
-import arc.util.*;
-import mindustry.type.*;
import mindustry.world.consumers.*;
import mindustry.world.meta.*;
@@ -21,23 +18,7 @@ public class ReloadTurret extends BaseTurret{
super.setStats();
if(coolant != null){
- stats.remove(Stat.booster);
-
- //TODO this is very hacky, there is no current way to check if a ConsumeLiquidBase accepts something individually. fix later
- ObjectSet notBooster = content.liquids().select(l -> {
- for(Consume c : consumers){
- if(!c.booster && c != coolant &&
- ((c instanceof ConsumeLiquid cl && cl.liquid == l) ||
- (c instanceof ConsumeLiquids cl2 && Structs.contains(cl2.liquids, s -> s.liquid == l)) ||
- (c instanceof ConsumeLiquidFilter clf && clf.filter.get(l)))){
-
- return true;
- }
- }
- return false;
- }).asSet();
-
- stats.add(Stat.booster, StatValues.boosters(reload, coolant.amount, coolantMultiplier, true, l -> l.coolant && consumesLiquid(l) && !notBooster.contains(l)));
+ stats.replace(Stat.booster, StatValues.boosters(reload, coolant.amount, coolantMultiplier, true, coolant::consumes));
}
}
@@ -46,10 +27,10 @@ public class ReloadTurret extends BaseTurret{
protected void updateCooling(){
if(reloadCounter < reload && coolant != null && coolant.efficiency(this) > 0 && efficiency > 0){
- float capacity = coolant instanceof ConsumeLiquidFilter filter ? filter.getConsumed(this).heatCapacity : 1f;
+ float capacity = coolant instanceof ConsumeLiquidFilter filter ? filter.getConsumed(this).heatCapacity : (coolant.consumes(liquids.current()) ? liquids.current().heatCapacity : 0.4f);
float amount = coolant.amount * coolant.efficiency(this);
coolant.update(this);
- reloadCounter += amount * edelta() * capacity * coolantMultiplier;
+ reloadCounter += amount * edelta() * capacity * coolantMultiplier * ammoReloadMultiplier();
if(Mathf.chance(0.06 * amount)){
coolEffect.at(x + Mathf.range(size * tilesize / 2f), y + Mathf.range(size * tilesize / 2f));
@@ -57,6 +38,10 @@ public class ReloadTurret extends BaseTurret{
}
}
+ protected float ammoReloadMultiplier(){
+ return 1f;
+ }
+
protected float baseReloadSpeed(){
return efficiency;
}
diff --git a/core/src/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/mindustry/world/blocks/defense/turrets/Turret.java
index e9f5331bbe..e56be0378a 100644
--- a/core/src/mindustry/world/blocks/defense/turrets/Turret.java
+++ b/core/src/mindustry/world/blocks/defense/turrets/Turret.java
@@ -60,6 +60,8 @@ public class Turret extends ReloadTurret{
public float shootX = 0f, shootY = Float.NEGATIVE_INFINITY;
/** Random spread on the X axis. */
public float xRand = 0f;
+ /** Range at which it finds and locks on to the target, but does not shoot. */
+ public float trackingRange = 0f;
/** Minimum bullet range. Used for artillery only. */
public float minRange = 0f;
/** Minimum warmup needed to fire. */
@@ -77,6 +79,8 @@ public class Turret extends ReloadTurret{
public boolean targetAir = true;
/** If true, this block targets ground units and structures. */
public boolean targetGround = true;
+ /** If true, this block targets blocks. */
+ public boolean targetBlocks = true;
/** If true, this block targets friend blocks, to heal them. */
public boolean targetHealing = false;
/** If true, this turret can be controlled by players. */
@@ -182,6 +186,7 @@ public class Turret extends ReloadTurret{
if(newTargetInterval <= 0f) newTargetInterval = targetInterval;
super.init();
+ trackingRange = Math.max(range, trackingRange);
}
@Override
@@ -204,7 +209,7 @@ public class Turret extends ReloadTurret{
public void limitRange(BulletType bullet, float margin){
float realRange = bullet.rangeChange + range;
//doesn't handle drag
- bullet.lifetime = (realRange + margin) / bullet.speed;
+ bullet.lifetime = (realRange + margin + bullet.extraRangeMargin) / bullet.speed;
}
public static abstract class AmmoEntry{
@@ -234,6 +239,8 @@ public class Turret extends ReloadTurret{
public float heatReq;
public float[] sideHeat = new float[4];
+ float lastRangeChange;
+
@Override
public float estimateDps(){
if(!hasAmmo()) return 0f;
@@ -248,6 +255,10 @@ public class Turret extends ReloadTurret{
return range;
}
+ public float trackingRange(){
+ return range() + trackingRange - range;
+ }
+
@Override
public float warmup(){
return shootWarmup;
@@ -307,6 +318,11 @@ public class Turret extends ReloadTurret{
};
}
+ @Override
+ public float fogRadius(){
+ return (range + (hasAmmo() ? peekAmmo().rangeChange : 0f)) / tilesize * fogRadiusMultiplier;
+ }
+
@Override
public float progress(){
return Mathf.clamp(reloadCounter / reload);
@@ -343,8 +359,8 @@ public class Turret extends ReloadTurret{
offset.set(h.deltaX(), h.deltaY()).scl(shoot.firstShotDelay / Time.delta);
}
- if(predictTarget){
- targetPos.set(Predict.intercept(this, pos, offset.x, offset.y, bullet.speed <= 0.01f ? 99999999f : bullet.speed));
+ if(predictTarget && bullet.speed >= 0.01f){
+ targetPos.set(Predict.intercept(this, pos, offset.x, offset.y, bullet.speed));
}else{
targetPos.set(pos);
}
@@ -364,7 +380,7 @@ public class Turret extends ReloadTurret{
if(!validateTarget()) target = null;
float warmupTarget = (isShooting() && canConsume()) || charging() ? 1f : 0f;
- if(warmupTarget > 0 && shootWarmup >= minWarmup && !isControlled()){
+ if(warmupTarget > 0 && !isControlled()){
warmupHold = 1f;
}
if(warmupHold > 0f){
@@ -406,6 +422,14 @@ public class Turret extends ReloadTurret{
//turret always reloads regardless of whether it's targeting something
updateReload();
+ if(state.rules.fog){
+ float newRange = hasAmmo() ? peekAmmo().rangeChange : 0f;
+ if(newRange != lastRangeChange){
+ lastRangeChange = newRange;
+ fogControl.forceUpdate(team, this);
+ }
+ }
+
if(hasAmmo()){
if(Float.isNaN(reloadCounter)) reloadCounter = 0;
@@ -425,6 +449,7 @@ public class Turret extends ReloadTurret{
targetPosition(target);
if(Float.isNaN(rotation)) rotation = 0;
+ canShoot = within(target, range() + (target instanceof Sized hb ? hb.hitSize()/1.9f : 0f));
}
if(!isControlled()){
@@ -474,13 +499,25 @@ public class Turret extends ReloadTurret{
return targetHealing && hasAmmo() && peekAmmo().collidesTeam && peekAmmo().heals();
}
- protected void findTarget(){
- float range = range();
-
+ protected Posc findEnemy(float range){
if(targetAir && !targetGround){
- target = Units.bestEnemy(team, x, y, range, e -> !e.dead() && !e.isGrounded() && unitFilter.get(e), unitSort);
+ return Units.bestEnemy(team, x, y, range, e -> !e.dead() && !e.isGrounded() && unitFilter.get(e), unitSort);
}else{
- target = Units.bestTarget(team, x, y, range, e -> !e.dead() && unitFilter.get(e) && (e.isGrounded() || targetAir) && (!e.isGrounded() || targetGround), b -> targetGround && buildingFilter.get(b), unitSort);
+ var ammo = peekAmmo();
+ boolean buildings = targetGround && targetBlocks && (ammo == null || ammo.targetBlocks), missiles = ammo == null || ammo.targetMissiles;
+ return Units.bestTarget(team, x, y, range,
+ e -> !e.dead() && unitFilter.get(e) && (e.isGrounded() || targetAir) && (!e.isGrounded() || targetGround) && (missiles || !(e instanceof TimedKillc)),
+ b -> buildings && buildingFilter.get(b), unitSort);
+ }
+ }
+
+ protected void findTarget(){
+ float trackRange = trackingRange(), range = range();
+
+ target = findEnemy(range);
+ //find another target within the tracking range, but only if there's nothing else (always prioritize standard target)
+ if(!Mathf.equal(trackRange, range) && target == null){
+ target = findEnemy(trackRange);
}
if(target == null && canHeal()){
@@ -538,13 +575,17 @@ public class Turret extends ReloadTurret{
}
protected void updateReload(){
- float multiplier = hasAmmo() ? peekAmmo().reloadMultiplier : 1f;
- reloadCounter += delta() * multiplier * baseReloadSpeed();
+ reloadCounter += delta() * ammoReloadMultiplier() * baseReloadSpeed();
//cap reload for visual reasons
reloadCounter = Math.min(reloadCounter, reload);
}
+ @Override
+ protected float ammoReloadMultiplier(){
+ return hasAmmo() ? peekAmmo().reloadMultiplier : 1f;
+ }
+
protected void updateShooting(){
if(reloadCounter >= reload && !charging() && shootWarmup >= minWarmup){
diff --git a/core/src/mindustry/world/blocks/distribution/ArmoredConveyor.java b/core/src/mindustry/world/blocks/distribution/ArmoredConveyor.java
index 4788b6662e..8c5d2f6e23 100644
--- a/core/src/mindustry/world/blocks/distribution/ArmoredConveyor.java
+++ b/core/src/mindustry/world/blocks/distribution/ArmoredConveyor.java
@@ -21,9 +21,9 @@ public class ArmoredConveyor extends Conveyor{
@Override
public boolean blendsArmored(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
return Point2.equals(tile.x + Geometry.d4(rotation).x, tile.y + Geometry.d4(rotation).y, otherx, othery)
- || ((!otherblock.rotatedOutput(otherx, othery) && Edges.getFacingEdge(otherblock, otherx, othery, tile) != null &&
+ || ((!otherblock.rotatedOutput(otherx, othery, tile) && Edges.getFacingEdge(otherblock, otherx, othery, tile) != null &&
Edges.getFacingEdge(otherblock, otherx, othery, tile).relativeTo(tile) == rotation) ||
- (otherblock instanceof Conveyor && otherblock.rotatedOutput(otherx, othery) && Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y)));
+ (otherblock instanceof Conveyor && otherblock.rotatedOutput(otherx, othery, tile) && Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y)));
}
public class ArmoredConveyorBuild extends ConveyorBuild{
diff --git a/core/src/mindustry/world/blocks/distribution/Conveyor.java b/core/src/mindustry/world/blocks/distribution/Conveyor.java
index 1d9b895049..cf1ab20889 100644
--- a/core/src/mindustry/world/blocks/distribution/Conveyor.java
+++ b/core/src/mindustry/world/blocks/distribution/Conveyor.java
@@ -30,6 +30,7 @@ public class Conveyor extends Block implements Autotiler{
public float speed = 0f;
public float displayedSpeed = 0f;
+ public boolean pushUnits = true;
public @Nullable Block junctionReplacement, bridgeReplacement;
@@ -223,7 +224,7 @@ public class Conveyor extends Block implements Autotiler{
@Override
public void unitOn(Unit unit){
- if(clogHeat > 0.5f || !enabled) return;
+ if(!pushUnits || clogHeat > 0.5f || !enabled) return;
noSleep();
@@ -380,13 +381,20 @@ public class Conveyor extends Block implements Autotiler{
}
}
+ @Override
+ public byte version(){
+ return 1;
+ }
+
@Override
public void write(Writes write){
super.write(write);
write.i(len);
for(int i = 0; i < len; i++){
- write.i(Pack.intBytes((byte)ids[i].id, (byte)(xs[i] * 127), (byte)(ys[i] * 255 - 128), (byte)0));
+ write.s(ids[i].id);
+ write.b((byte)(xs[i] * 127));
+ write.b((byte)(ys[i] * 255 - 128));
}
}
@@ -397,10 +405,20 @@ public class Conveyor extends Block implements Autotiler{
len = Math.min(amount, capacity);
for(int i = 0; i < amount; i++){
- int val = read.i();
- short id = (short)(((byte)(val >> 24)) & 0xff);
- float x = (float)((byte)(val >> 16)) / 127f;
- float y = ((float)((byte)(val >> 8)) + 128f) / 255f;
+ short id;
+ float x, y;
+
+ if(revision == 0){
+ int val = read.i();
+ id = (short)(((byte)(val >> 24)) & 0xff);
+ x = (float)((byte)(val >> 16)) / 127f;
+ y = ((float)((byte)(val >> 8)) + 128f) / 255f;
+ }else{
+ id = read.s();
+ x = (float)read.b() / 127f;
+ y = ((float)read.b() + 128f) / 255f;
+ }
+
if(i < capacity){
ids[i] = content.item(id);
xs[i] = x;
diff --git a/core/src/mindustry/world/blocks/distribution/Duct.java b/core/src/mindustry/world/blocks/distribution/Duct.java
index 0505ec7aad..dacd3a8b8e 100644
--- a/core/src/mindustry/world/blocks/distribution/Duct.java
+++ b/core/src/mindustry/world/blocks/distribution/Duct.java
@@ -82,10 +82,10 @@ public class Duct extends Block implements Autotiler{
@Override
public boolean blendsArmored(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
return Point2.equals(tile.x + Geometry.d4(rotation).x, tile.y + Geometry.d4(rotation).y, otherx, othery)
- || ((!otherblock.rotatedOutput(otherx, othery) && Edges.getFacingEdge(otherblock, otherx, othery, tile) != null &&
+ || ((!otherblock.rotatedOutput(otherx, othery, tile) && Edges.getFacingEdge(otherblock, otherx, othery, tile) != null &&
Edges.getFacingEdge(otherblock, otherx, othery, tile).relativeTo(tile) == rotation) ||
- ((otherblock.rotatedOutput(otherx, othery)) && (otherblock.isDuct) && Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y)));
+ ((otherblock.rotatedOutput(otherx, othery, tile)) && (otherblock.isDuct) && Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y)));
}
@Override
diff --git a/core/src/mindustry/world/blocks/distribution/Junction.java b/core/src/mindustry/world/blocks/distribution/Junction.java
index d02fb84404..ec21de0b16 100644
--- a/core/src/mindustry/world/blocks/distribution/Junction.java
+++ b/core/src/mindustry/world/blocks/distribution/Junction.java
@@ -79,6 +79,11 @@ public class Junction extends Block{
return to != null && to.team == team;
}
+ @Override
+ public byte version(){
+ return 1;
+ }
+
@Override
public void write(Writes write){
super.write(write);
@@ -88,7 +93,7 @@ public class Junction extends Block{
@Override
public void read(Reads read, byte revision){
super.read(read, revision);
- buffer.read(read);
+ buffer.read(read, revision == 0);
}
}
}
diff --git a/core/src/mindustry/world/blocks/environment/Floor.java b/core/src/mindustry/world/blocks/environment/Floor.java
index dfd29de65b..2ea499d015 100644
--- a/core/src/mindustry/world/blocks/environment/Floor.java
+++ b/core/src/mindustry/world/blocks/environment/Floor.java
@@ -92,6 +92,7 @@ public class Floor extends Block{
placeableLiquid = true;
allowRectanglePlacement = true;
instantBuild = true;
+ ignoreBuildDarkness = true;
placeEffect = Fx.rotateBlock;
}
diff --git a/core/src/mindustry/world/blocks/environment/OverlayFloor.java b/core/src/mindustry/world/blocks/environment/OverlayFloor.java
index c20eccceaf..c7d5a10f28 100644
--- a/core/src/mindustry/world/blocks/environment/OverlayFloor.java
+++ b/core/src/mindustry/world/blocks/environment/OverlayFloor.java
@@ -2,6 +2,7 @@ package mindustry.world.blocks.environment;
import arc.graphics.g2d.*;
import arc.math.*;
+import mindustry.game.*;
import mindustry.world.*;
/**A type of floor that is overlaid on top of other floors.*/
@@ -12,6 +13,11 @@ public class OverlayFloor extends Floor{
useColor = false;
}
+ @Override
+ public boolean canPlaceOn(Tile tile, Team team, int rotation){
+ return !wallOre || tile.block().solid;
+ }
+
@Override
public void drawBase(Tile tile){
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
diff --git a/core/src/mindustry/world/blocks/environment/RemoveOre.java b/core/src/mindustry/world/blocks/environment/RemoveOre.java
new file mode 100644
index 0000000000..b50d019c4f
--- /dev/null
+++ b/core/src/mindustry/world/blocks/environment/RemoveOre.java
@@ -0,0 +1,51 @@
+package mindustry.world.blocks.environment;
+
+import arc.graphics.g2d.*;
+import arc.util.*;
+import mindustry.content.*;
+import mindustry.entities.units.*;
+import mindustry.game.*;
+import mindustry.gen.*;
+import mindustry.world.*;
+
+public class RemoveOre extends OverlayFloor{
+
+ public RemoveOre(String name){
+ super(name);
+
+ allowRectanglePlacement = true;
+ placeEffect = Fx.rotateBlock;
+ instantBuild = true;
+ ignoreBuildDarkness = true;
+ placeableLiquid = true;
+ inEditor = false;
+ variants = 0;
+ }
+
+ @Override
+ public void drawPlan(BuildPlan plan, Eachable list, boolean valid, float alpha){
+ Draw.reset();
+ Draw.alpha(alpha * (valid ? 1f : 0.2f));
+ float prevScale = Draw.scl;
+ Draw.scl *= plan.animScale;
+ drawPlanRegion(plan, list);
+ Draw.scl = prevScale;
+ Draw.reset();
+ }
+
+ @Override
+ public boolean canPlaceOn(Tile tile, Team team, int rotation){
+ return tile.overlay() != Blocks.air;
+ }
+
+ @Override
+ public boolean canReplace(Block other){
+ return true;
+ }
+
+ @Override
+ public void placeEnded(Tile tile, @Nullable Unit builder){
+ tile.setOverlay(Blocks.air);
+ }
+
+}
diff --git a/core/src/mindustry/world/blocks/environment/RemoveWall.java b/core/src/mindustry/world/blocks/environment/RemoveWall.java
new file mode 100644
index 0000000000..0359ee7052
--- /dev/null
+++ b/core/src/mindustry/world/blocks/environment/RemoveWall.java
@@ -0,0 +1,53 @@
+package mindustry.world.blocks.environment;
+
+import arc.graphics.g2d.*;
+import arc.util.*;
+import mindustry.content.*;
+import mindustry.entities.units.*;
+import mindustry.game.*;
+import mindustry.gen.*;
+import mindustry.world.*;
+
+public class RemoveWall extends Block{
+
+ public RemoveWall(String name){
+ super(name);
+
+ allowRectanglePlacement = true;
+ placeEffect = Fx.rotateBlock;
+ instantBuild = true;
+ ignoreBuildDarkness = true;
+ placeableLiquid = true;
+ inEditor = false;
+ }
+
+ @Override
+ public void drawPlan(BuildPlan plan, Eachable list, boolean valid, float alpha){
+ Draw.reset();
+ Draw.alpha(alpha * (valid ? 1f : 0.2f));
+ float prevScale = Draw.scl;
+ Draw.scl *= plan.animScale;
+ drawPlanRegion(plan, list);
+ Draw.scl = prevScale;
+ Draw.reset();
+ }
+
+ @Override
+ public boolean canPlaceOn(Tile tile, Team team, int rotation){
+ return tile.block() != Blocks.air;
+ }
+
+ @Override
+ public boolean canReplace(Block other){
+ return other != Blocks.air && !other.synthetic();
+ }
+
+ @Override
+ public void placeEnded(Tile tile, @Nullable Unit builder){
+ tile.setBlock(Blocks.air);
+ if(tile.overlay().wallOre){
+ tile.setOverlay(Blocks.air);
+ }
+ }
+
+}
diff --git a/core/src/mindustry/world/blocks/environment/StaticWall.java b/core/src/mindustry/world/blocks/environment/StaticWall.java
index 56fc569b24..b59b25f30b 100644
--- a/core/src/mindustry/world/blocks/environment/StaticWall.java
+++ b/core/src/mindustry/world/blocks/environment/StaticWall.java
@@ -5,6 +5,7 @@ import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
import mindustry.annotations.Annotations.*;
+import mindustry.content.*;
import mindustry.graphics.*;
import mindustry.world.*;
@@ -21,7 +22,10 @@ public class StaticWall extends Prop{
variants = 2;
cacheLayer = CacheLayer.walls;
allowRectanglePlacement = true;
+ placeEffect = Fx.rotateBlock;
instantBuild = true;
+ ignoreBuildDarkness = true;
+ placeableLiquid = true;
}
@Override
@@ -29,7 +33,7 @@ public class StaticWall extends Prop{
int rx = tile.x / 2 * 2;
int ry = tile.y / 2 * 2;
- if(Core.atlas.isFound(large) && eq(rx, ry) && Mathf.randomSeed(Point2.pack(rx, ry)) < 0.5){
+ if(Core.atlas.isFound(large) && eq(rx, ry) && Mathf.randomSeed(Point2.pack(rx, ry)) < 0.5 && split.length >= 2 && split[0].length >= 2){
Draw.rect(split[tile.x % 2][1 - tile.y % 2], tile.worldx(), tile.worldy());
}else if(variants > 0){
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
@@ -46,7 +50,20 @@ public class StaticWall extends Prop{
@Override
public void load(){
super.load();
- split = large.split(32, 32);
+ int size = large.width / 2;
+ split = large.split(size, size);
+ if(split != null){
+ for(var arr : split){
+ for(var reg : arr){
+ reg.scale = region.scale;
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean canReplace(Block other){
+ return other instanceof StaticWall || super.canReplace(other);
}
boolean eq(int rx, int ry){
diff --git a/core/src/mindustry/world/blocks/environment/SteamVent.java b/core/src/mindustry/world/blocks/environment/SteamVent.java
index 6ab3eccc75..ef2414e1cf 100644
--- a/core/src/mindustry/world/blocks/environment/SteamVent.java
+++ b/core/src/mindustry/world/blocks/environment/SteamVent.java
@@ -60,7 +60,7 @@ public class SteamVent extends Floor{
@Override
public void renderUpdate(UpdateRenderState state){
- if(state.tile.block() == Blocks.air && (state.data += Time.delta) >= effectSpacing){
+ if(state.tile.nearby(-1, -1) != null && state.tile.nearby(-1, -1).block() == Blocks.air && (state.data += Time.delta) >= effectSpacing){
effect.at(state.tile.x * tilesize - tilesize, state.tile.y * tilesize - tilesize, effectColor);
state.data = 0f;
}
diff --git a/core/src/mindustry/world/blocks/logic/CanvasBlock.java b/core/src/mindustry/world/blocks/logic/CanvasBlock.java
index af6ebc9db8..809c765ba5 100644
--- a/core/src/mindustry/world/blocks/logic/CanvasBlock.java
+++ b/core/src/mindustry/world/blocks/logic/CanvasBlock.java
@@ -16,6 +16,7 @@ import arc.util.io.*;
import mindustry.annotations.Annotations.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
+import mindustry.graphics.*;
import mindustry.ui.*;
import mindustry.world.*;
@@ -253,34 +254,59 @@ public class CanvasBlock extends Block{
Texture texture = new Texture(pix);
int[] curColor = {palette[0]};
boolean[] modified = {false};
+ boolean[] fill = {false};
dialog.resized(dialog::hide);
dialog.cont.table(Tex.pane, body -> {
- body.stack(new Element(){
+ body.add(new Element(){
int lastX, lastY;
+ IntSeq stack = new IntSeq();
+
+ int convertX(float ex){
+ return (int)((ex) / (width / canvasSize));
+ }
+
+ int convertY(float ey){
+ return pix.height - 1 - (int)((ey) / (height / canvasSize));
+ }
{
addListener(new InputListener(){
- int convertX(float ex){
- return (int)((ex - x) / width * canvasSize);
- }
-
- int convertY(float ey){
- return pix.height - 1 - (int)((ey - y) / height * canvasSize);
- }
@Override
public boolean touchDown(InputEvent event, float ex, float ey, int pointer, KeyCode button){
int cx = convertX(ex), cy = convertY(ey);
- draw(cx, cy);
- lastX = cx;
- lastY = cy;
+ if(fill[0]){
+ stack.clear();
+ int src = curColor[0];
+ int dst = pix.get(cx, cy);
+ if(src != dst){
+ stack.add(Point2.pack(cx, cy));
+ while(!stack.isEmpty()){
+ int current = stack.pop();
+ int x = Point2.x(current), y = Point2.y(current);
+ draw(x, y);
+ for(int i = 0; i < 4; i++){
+ int nx = x + Geometry.d4x(i), ny = y + Geometry.d4y(i);
+ if(nx >= 0 && ny >= 0 && nx < pix.width && ny < pix.height && pix.getRaw(nx, ny) == dst){
+ stack.add(Point2.pack(nx, ny));
+ }
+ }
+ }
+ }
+
+ }else{
+ draw(cx, cy);
+ lastX = cx;
+ lastY = cy;
+ }
return true;
}
@Override
public void touchDragged(InputEvent event, float ex, float ey, int pointer){
+ if(fill[0]) return;
int cx = convertX(ex), cy = convertY(ey);
Bresenham2.line(lastX, lastY, cx, cy, (x, y) -> draw(x, y));
lastX = cx;
@@ -302,14 +328,47 @@ public class CanvasBlock extends Block{
Tmp.tr1.set(texture);
Draw.alpha(parentAlpha);
Draw.rect(Tmp.tr1, x + width/2f, y + height/2f, width, height);
+
+ //draw grid
+ {
+ float xspace = (getWidth() / canvasSize);
+ float yspace = (getHeight() / canvasSize);
+ float s = 1f;
+
+ int minspace = 10;
+
+ int jumpx = (int)(Math.max(minspace, xspace) / xspace);
+ int jumpy = (int)(Math.max(minspace, yspace) / yspace);
+
+ for(int x = 0; x <= canvasSize; x += jumpx){
+ Fill.crect((int)(this.x + xspace * x - s), y - s, 2, getHeight() + (x == canvasSize ? 1 : 0));
+ }
+
+ for(int y = 0; y <= canvasSize; y += jumpy){
+ Fill.crect(x - s, (int)(this.y + y * yspace - s), getWidth(), 2);
+ }
+ }
+
+ if(!mobile){
+ Vec2 s = screenToLocalCoordinates(Core.input.mouse());
+ if(s.x >= 0 && s.y >= 0 && s.x < width && s.y < height){
+ float sx = Mathf.round(s.x, width / canvasSize), sy = Mathf.round(s.y, height / canvasSize);
+
+ Lines.stroke(Scl.scl(6f));
+ Draw.color(Pal.accent);
+ Lines.rect(sx + x, sy + y, width / canvasSize, height / canvasSize, Lines.getStroke() - 1f);
+
+ Draw.reset();
+ }
+ }
}
- }, new GridImage(canvasSize, canvasSize){{
- touchable = Touchable.disabled;
- }}).size(mobile && !Core.graphics.isPortrait() ? Math.min(290f, Core.graphics.getHeight() / Scl.scl(1f) - 75f / Scl.scl(1f)) : 480f);
- });
+ }).size(mobile && !Core.graphics.isPortrait() ? Math.min(290f, Core.graphics.getHeight() / Scl.scl(1f) - 75f / Scl.scl(1f)) : 480f);
+ }).colspan(3);
dialog.cont.row();
+ dialog.cont.add().size(60f);
+
dialog.cont.table(Tex.button, p -> {
for(int i = 0; i < palette.length; i++){
int fi = i;
@@ -321,6 +380,12 @@ public class CanvasBlock extends Block{
}
});
+ dialog.cont.table(Tex.button, t -> {
+ t.button(Icon.fill, Styles.clearNoneTogglei, () -> {
+ fill[0] = !fill[0];
+ }).size(44f);
+ });
+
dialog.closeOnBack();
dialog.buttons.defaults().size(150f, 64f);
diff --git a/core/src/mindustry/world/blocks/logic/LogicBlock.java b/core/src/mindustry/world/blocks/logic/LogicBlock.java
index 655cf48e4f..b978be9993 100644
--- a/core/src/mindustry/world/blocks/logic/LogicBlock.java
+++ b/core/src/mindustry/world/blocks/logic/LogicBlock.java
@@ -109,7 +109,7 @@ public class LogicBlock extends Block{
}
public boolean accessible(){
- return !privileged || state.rules.editor || state.playtestingMap != null;
+ return !privileged || state.rules.editor || state.playtestingMap != null || state.rules.allowEditWorldProcessors;
}
@Override
@@ -377,13 +377,15 @@ public class LogicBlock extends Block{
asm.putConst("@links", executor.links.length);
asm.putConst("@ipt", instructionsPerTick);
+ Object oldUnit = null;
+
if(keep){
+ oldUnit = executor.unit.objval;
//store any older variables
for(LVar var : executor.vars){
- boolean unit = var.name.equals("@unit");
- if(!var.constant || unit){
+ if(!var.constant){
LVar dest = asm.getVar(var.name);
- if(dest != null && (!dest.constant || unit)){
+ if(dest != null && !dest.constant){
dest.isobj = var.isobj;
dest.objval = var.objval;
dest.numval = var.numval;
@@ -395,6 +397,10 @@ public class LogicBlock extends Block{
//inject any extra variables
if(assemble != null){
assemble.get(asm);
+
+ if(oldUnit == null && asm.getVar("@unit") != null && asm.getVar("@unit").objval instanceof Unit u){
+ oldUnit = u;
+ }
}
asm.getVar("@this").setconst(this);
@@ -402,6 +408,8 @@ public class LogicBlock extends Block{
asm.putConst("@thisy", World.conv(y));
executor.load(asm);
+ executor.unit.objval = oldUnit;
+ executor.unit.isobj = true;
}catch(Exception e){
//handle malformed code and replace it with nothing
executor.load(LAssembler.assemble(code = "", privileged));
@@ -752,8 +760,17 @@ public class LogicBlock extends Block{
//load up the variables that were stored
for(int i = 0; i < varcount; i++){
LVar var = asm.getVar(names[i]);
- if(var.objval instanceof Boxed> boxed){
- var.objval = boxed.unbox();
+ if(var != null && (!var.constant || var.name.equals("@unit"))){
+ var value = values[i];
+ if(value instanceof Boxed> boxed) value = boxed.unbox();
+
+ if(value instanceof Number num){
+ var.numval = num.doubleValue();
+ var.isobj = false;
+ }else{
+ var.objval = value;
+ var.isobj = true;
+ }
}
}
});
diff --git a/core/src/mindustry/world/blocks/logic/MemoryBlock.java b/core/src/mindustry/world/blocks/logic/MemoryBlock.java
index 37a6c2af61..44af66623a 100644
--- a/core/src/mindustry/world/blocks/logic/MemoryBlock.java
+++ b/core/src/mindustry/world/blocks/logic/MemoryBlock.java
@@ -28,7 +28,7 @@ public class MemoryBlock extends Block{
}
public boolean accessible(){
- return !privileged || state.rules.editor;
+ return !privileged || state.rules.editor || state.rules.allowEditWorldProcessors;
}
@Override
diff --git a/core/src/mindustry/world/blocks/logic/MessageBlock.java b/core/src/mindustry/world/blocks/logic/MessageBlock.java
index f81e7d4672..eb644b57de 100644
--- a/core/src/mindustry/world/blocks/logic/MessageBlock.java
+++ b/core/src/mindustry/world/blocks/logic/MessageBlock.java
@@ -58,7 +58,7 @@ public class MessageBlock extends Block{
}
public boolean accessible(){
- return !privileged || state.rules.editor;
+ return !privileged || state.rules.editor || state.rules.allowEditWorldProcessors;
}
@Override
diff --git a/core/src/mindustry/world/blocks/logic/SwitchBlock.java b/core/src/mindustry/world/blocks/logic/SwitchBlock.java
index 6c166fd331..db49b70f6c 100644
--- a/core/src/mindustry/world/blocks/logic/SwitchBlock.java
+++ b/core/src/mindustry/world/blocks/logic/SwitchBlock.java
@@ -28,7 +28,7 @@ public class SwitchBlock extends Block{
}
public boolean accessible(){
- return !privileged || state.rules.editor;
+ return !privileged || state.rules.editor || state.rules.allowEditWorldProcessors;
}
@Override
diff --git a/core/src/mindustry/world/blocks/payloads/BlockProducer.java b/core/src/mindustry/world/blocks/payloads/BlockProducer.java
index e5eccb570f..2bc66e0e1f 100644
--- a/core/src/mindustry/world/blocks/payloads/BlockProducer.java
+++ b/core/src/mindustry/world/blocks/payloads/BlockProducer.java
@@ -30,7 +30,7 @@ public abstract class BlockProducer extends PayloadBlock{
hasItems = true;
solid = true;
hasPower = true;
- acceptsPayloads = false;
+ acceptsUnitPayloads = false;
rotate = true;
regionRotated1 = 1;
@@ -69,7 +69,7 @@ public abstract class BlockProducer extends PayloadBlock{
addBar("progress", (BlockProducerBuild entity) -> new Bar("bar.progress", Pal.ammo, () -> entity.recipe() == null ? 0f : (entity.progress / entity.recipe().buildCost)));
}
-
+
public abstract class BlockProducerBuild extends PayloadBlockBuild{
public float progress, time, heat;
diff --git a/core/src/mindustry/world/blocks/payloads/BuildPayload.java b/core/src/mindustry/world/blocks/payloads/BuildPayload.java
index 90e37e9e16..57d0812e8c 100644
--- a/core/src/mindustry/world/blocks/payloads/BuildPayload.java
+++ b/core/src/mindustry/world/blocks/payloads/BuildPayload.java
@@ -53,6 +53,7 @@ public class BuildPayload implements Payload{
@Override
public void destroyed(){
+ build.dead = true;
build.onDestroyed();
}
diff --git a/core/src/mindustry/world/blocks/payloads/Constructor.java b/core/src/mindustry/world/blocks/payloads/Constructor.java
index 695600afdd..2983023068 100644
--- a/core/src/mindustry/world/blocks/payloads/Constructor.java
+++ b/core/src/mindustry/world/blocks/payloads/Constructor.java
@@ -7,6 +7,7 @@ import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.*;
+import mindustry.ctype.*;
import mindustry.world.*;
import mindustry.world.blocks.*;
import mindustry.world.blocks.storage.*;
@@ -44,10 +45,15 @@ public class Constructor extends BlockProducer{
stats.add(Stat.output, "@x@ ~ @x@", minBlockSize, minBlockSize, maxBlockSize, maxBlockSize);
}
+ @Override
+ public void getPlanConfigs(Seq options){
+ options.add(content.blocks().select(this::canProduce));
+ }
+
public boolean canProduce(Block b){
return b.isVisible() && b.size >= minBlockSize && b.size <= maxBlockSize && !(b instanceof CoreBlock) && !state.rules.isBanned(b) && b.environmentBuildable() && (filter.isEmpty() || filter.contains(b));
}
-
+
public class ConstructorBuild extends BlockProducerBuild{
public @Nullable Block recipe;
@@ -65,7 +71,7 @@ public class Constructor extends BlockProducer{
public Object config(){
return recipe;
}
-
+
@Override
public void drawSelect(){
if(recipe != null){
diff --git a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java
index ab7dc95320..e6a913390b 100644
--- a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java
+++ b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java
@@ -25,7 +25,7 @@ public class PayloadBlock extends Block{
update = true;
sync = true;
group = BlockGroup.payloads;
- acceptsPayloads = true;
+ acceptsUnitPayloads = true;
envEnabled |= Env.space | Env.underwater;
}
diff --git a/core/src/mindustry/world/blocks/payloads/PayloadConveyor.java b/core/src/mindustry/world/blocks/payloads/PayloadConveyor.java
index e6c368d97e..650846987b 100644
--- a/core/src/mindustry/world/blocks/payloads/PayloadConveyor.java
+++ b/core/src/mindustry/world/blocks/payloads/PayloadConveyor.java
@@ -21,6 +21,7 @@ public class PayloadConveyor extends Block{
public @Load("@-edge") TextureRegion edgeRegion;
public Interp interp = Interp.pow5;
public float payloadLimit = 3f;
+ public boolean pushUnits = true;
public PayloadConveyor(String name){
super(name);
@@ -30,7 +31,7 @@ public class PayloadConveyor extends Block{
update = true;
outputsPayload = true;
noUpdateDisabled = true;
- acceptsPayloads = true;
+ acceptsUnitPayloads = true;
priority = TargetPriority.transport;
envEnabled |= Env.space | Env.underwater;
sync = true;
@@ -257,7 +258,7 @@ public class PayloadConveyor extends Block{
@Override
public void unitOn(Unit unit){
- if(!enabled) return;
+ if(!pushUnits || !enabled) return;
//calculate derivative of units moved last frame
float delta = (curInterp - lastInterp) * size * tilesize;
diff --git a/core/src/mindustry/world/blocks/payloads/PayloadRouter.java b/core/src/mindustry/world/blocks/payloads/PayloadRouter.java
index 20fbde8091..e2219de3cf 100644
--- a/core/src/mindustry/world/blocks/payloads/PayloadRouter.java
+++ b/core/src/mindustry/world/blocks/payloads/PayloadRouter.java
@@ -4,6 +4,7 @@ import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.scene.ui.layout.*;
+import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.*;
@@ -22,7 +23,7 @@ import static mindustry.Vars.*;
public class PayloadRouter extends PayloadConveyor{
public boolean invert = false;
-
+
public @Load("@-over") TextureRegion overRegion;
public PayloadRouter(String name){
@@ -45,6 +46,12 @@ public class PayloadRouter extends PayloadConveyor{
Draw.rect(overRegion, plan.drawx(), plan.drawy());
}
+ @Override
+ public void getPlanConfigs(Seq options){
+ options.add(content.blocks().select(this::canSort));
+ options.add(content.units().select(this::canSort));
+ }
+
public boolean canSort(Block b){
return b.isVisible() && b.size <= size && !(b instanceof CoreBlock) && !state.rules.isBanned(b) && b.environmentBuildable();
}
diff --git a/core/src/mindustry/world/blocks/payloads/PayloadSource.java b/core/src/mindustry/world/blocks/payloads/PayloadSource.java
index 1354b9edc1..618f258feb 100644
--- a/core/src/mindustry/world/blocks/payloads/PayloadSource.java
+++ b/core/src/mindustry/world/blocks/payloads/PayloadSource.java
@@ -5,6 +5,7 @@ import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
import arc.scene.ui.layout.*;
+import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.*;
@@ -37,7 +38,7 @@ public class PayloadSource extends PayloadBlock{
noUpdateDisabled = true;
clearOnDoubleTap = true;
regionRotated1 = 1;
- acceptsPayloads = false;
+ acceptsUnitPayloads = false;
commandable = true;
config(Block.class, (PayloadSourceBuild build, Block block) -> {
@@ -66,6 +67,12 @@ public class PayloadSource extends PayloadBlock{
});
}
+ @Override
+ public void getPlanConfigs(Seq options){
+ options.add(content.blocks().select(this::canProduce));
+ options.add(content.units().select(this::canProduce));
+ }
+
@Override
public TextureRegion[] icons(){
return new TextureRegion[]{region, outRegion, topRegion};
diff --git a/core/src/mindustry/world/blocks/power/BeamNode.java b/core/src/mindustry/world/blocks/power/BeamNode.java
index b99590d2be..a32f2e2178 100644
--- a/core/src/mindustry/world/blocks/power/BeamNode.java
+++ b/core/src/mindustry/world/blocks/power/BeamNode.java
@@ -1,14 +1,17 @@
package mindustry.world.blocks.power;
+import arc.func.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
+import arc.util.*;
import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.core.*;
import mindustry.entities.*;
+import mindustry.game.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.input.*;
@@ -20,6 +23,9 @@ import java.util.*;
import static mindustry.Vars.*;
public class BeamNode extends PowerBlock{
+ //maximum expected range of any beam node; used for previews
+ private static final int maxRange = 30;
+
public int range = 5;
public @Load(value = "@-beam", fallback = "power-beam") TextureRegion laser;
@@ -101,7 +107,48 @@ public class BeamNode extends PowerBlock{
@Override
public void changePlacementPath(Seq points, int rotation, boolean diagonal){
if(!diagonal){
- Placement.calculateNodes(points, this, rotation, (point, other) -> Math.max(Math.abs(point.x - other.x), Math.abs(point.y - other.y)) <= range);
+ Placement.calculateNodes(points, this, rotation, (point, other) -> Math.max(Math.abs(point.x - other.x), Math.abs(point.y - other.y)) <= range + size - 1);
+ }
+ }
+
+ /** Iterates through linked nodes of a block at a tile. All returned buildings are beam nodes. */
+ public static void getNodeLinks(Tile tile, Block block, Team team, Cons others){
+ var tree = team.data().buildingTree;
+
+ if(tree == null) return;
+
+ float cx = tile.worldx() + block.offset, cy = tile.worldy() + block.offset, s = block.size * tilesize/2f, r = maxRange * tilesize;
+
+ for(int i = 0; i < 4; i++){
+ switch(i){
+ case 0 -> Tmp.r1.set(cx - s, cy - s, r, s * 2f);
+ case 1 -> Tmp.r1.set(cx - s, cy - s, s * 2f, r);
+ case 2 -> Tmp.r1.set(cx + s, cy - s, -r, s * 2f).normalize();
+ case 3 -> Tmp.r1.set(cx - s, cy + s, s * 2f, -r).normalize();
+ }
+
+ tempBuilds.clear();
+ tree.intersect(Tmp.r1, tempBuilds);
+ int fi = i;
+ Building closest = tempBuilds.min(b -> b instanceof BeamNodeBuild node && node.couldConnect((fi + 2) % 4, block, tile.x, tile.y), b -> b.dst2(cx, cy));
+ tempBuilds.clear();
+ if(closest != null){
+ others.get(closest);
+ }
+ }
+ }
+
+ /** Note that x1 and y1 are expected to be coordinates of the node to draw the beam from. */
+ public void drawLaser(float x1, float y1, float x2, float y2, int size1, int size2){
+ float w = laserWidth;
+ float dst = Math.max(Math.abs(x1 - x2), Math.abs(y2 - y1)) / tilesize;
+ float sizeOff = dst * tilesize - (size1 + size2) * tilesize/2f;
+
+ //don't draw lasers for adjacent blocks
+ if(dst > 1 + size/2){
+ var point = Geometry.d4(Tile.relativeTo(x1, y1, x2, y2));
+ float poff = tilesize/2f;
+ Drawf.laser(laser, laserEnd, x1 + poff*size*point.x, y1 + poff*size*point.y, x1 + (poff*size + sizeOff) * point.x, y1 + (poff*size + sizeOff) * point.y, w);
}
}
@@ -111,6 +158,34 @@ public class BeamNode extends PowerBlock{
public Tile[] dests = new Tile[4];
public int lastChange = -2;
+ /** @return whether a beam could theoretically connect with the specified block at a position */
+ public boolean couldConnect(int direction, Block target, int targetX, int targetY){
+ int offset = -(target.size - 1) / 2;
+ int minX = targetX + offset, minY = targetY + offset, maxX = targetX + offset + target.size - 1, maxY = targetY + offset + target.size - 1;
+ var dir = Geometry.d4[direction];
+
+ int rangeOffset = size/2;
+
+ //find first block with power in range
+ for(int j = 1 + rangeOffset; j <= range + rangeOffset; j++){
+ var other = world.tile(tile.x + j * dir.x, tile.y + j * dir.y);
+
+ if(other == null) return false;
+
+ //hit insulated wall
+ if((other.build != null && other.build.isInsulated()) || (other.block().hasPower && other.block().connectedPower && other.team() == team)){
+ return false;
+ }
+
+ //within target rectangle
+ if(other.x >= minX && other.y >= minY && other.x <= maxX && other.y <= maxY){
+ return true;
+ }
+ }
+
+ return false;
+ }
+
@Override
public void updateTile(){
//TODO this block technically does not need to update every frame, perhaps put it in a special list.
@@ -132,7 +207,7 @@ public class BeamNode extends PowerBlock{
public void draw(){
super.draw();
- if(Mathf.zero(Renderer.laserOpacity)) return;
+ if(Mathf.zero(Renderer.laserOpacity) || team == Team.derelict) return;
Draw.z(Layer.power);
Draw.color(laserColor1, laserColor2, (1f - power.graph.getSatisfaction()) * 0.86f + Mathf.absin(3f, 0.1f));
diff --git a/core/src/mindustry/world/blocks/power/PowerNode.java b/core/src/mindustry/world/blocks/power/PowerNode.java
index 421684f43b..89ddae8cbc 100644
--- a/core/src/mindustry/world/blocks/power/PowerNode.java
+++ b/core/src/mindustry/world/blocks/power/PowerNode.java
@@ -472,7 +472,7 @@ public class PowerNode extends PowerBlock{
public void draw(){
super.draw();
- if(Mathf.zero(Renderer.laserOpacity) || isPayload()) return;
+ if(Mathf.zero(Renderer.laserOpacity) || isPayload() || team == Team.derelict) return;
Draw.z(Layer.power);
setupColor(power.graph.getSatisfaction());
diff --git a/core/src/mindustry/world/blocks/power/ThermalGenerator.java b/core/src/mindustry/world/blocks/power/ThermalGenerator.java
index 9c71e77ca8..1af92ce5da 100644
--- a/core/src/mindustry/world/blocks/power/ThermalGenerator.java
+++ b/core/src/mindustry/world/blocks/power/ThermalGenerator.java
@@ -88,9 +88,15 @@ public class ThermalGenerator extends PowerGenerator{
}
}
+ @Override
+ public void afterPickedUp(){
+ super.afterPickedUp();
+ sum = 0f;
+ }
+
@Override
public float totalProgress(){
- return enabled ? super.totalProgress() : 0f;
+ return enabled && sum > 0 ? super.totalProgress() : 0f;
}
@Override
diff --git a/core/src/mindustry/world/blocks/production/Separator.java b/core/src/mindustry/world/blocks/production/Separator.java
index fd387d6960..1bd5351b5e 100644
--- a/core/src/mindustry/world/blocks/production/Separator.java
+++ b/core/src/mindustry/world/blocks/production/Separator.java
@@ -38,7 +38,14 @@ public class Separator extends Block{
stats.timePeriod = craftTime;
super.setStats();
- stats.add(Stat.output, StatValues.items(item -> Structs.contains(results, i -> i.item == item)));
+ int[] sum = {0};
+ for(var r : results) sum[0] += r.amount;
+
+ stats.add(Stat.output, table -> {
+ for(ItemStack stack : results){
+ table.add(StatValues.displayItemPercent(stack.item, (int)((float)stack.amount / sum[0] * 100), true)).padRight(5);
+ }
+ });
stats.add(Stat.productionTime, craftTime / 60f, StatUnit.seconds);
}
diff --git a/core/src/mindustry/world/blocks/production/WallCrafter.java b/core/src/mindustry/world/blocks/production/WallCrafter.java
index d499f2cfe3..22f621c613 100644
--- a/core/src/mindustry/world/blocks/production/WallCrafter.java
+++ b/core/src/mindustry/world/blocks/production/WallCrafter.java
@@ -17,6 +17,7 @@ import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
+import mindustry.world.consumers.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
@@ -30,6 +31,8 @@ public class WallCrafter extends Block{
/** Time to produce one item at 100% efficiency. */
public float drillTime = 150f;
+ /** How many times faster the drill will progress when boosted by liquid. */
+ public float liquidBoostIntensity = 1.6f;
/** Effect randomly played while drilling. */
public Effect updateEffect = Fx.mineWallSmall;
public float updateEffectChance = 0.02f;
@@ -39,6 +42,14 @@ public class WallCrafter extends Block{
public Item output = Items.sand;
+ public float boostItemUseTime = 120f;
+ /** How many times faster the drill will progress when boosted by items. Note: Using item and liquid boosters at once is not supported. */
+ public float itemBoostIntensity = 1.6f;
+ public @Nullable Consume itemConsumer;
+ public boolean hasLiquidBooster;
+
+ public final int timerUse = timers ++;
+
public WallCrafter(String name){
super(name);
@@ -67,6 +78,31 @@ public class WallCrafter extends Block{
stats.add(Stat.output, output);
stats.add(Stat.tiles, StatValues.blocks(attribute, floating, 1f, true, false));
stats.add(Stat.drillSpeed, 60f / drillTime * size, StatUnit.itemsSecond);
+
+ boolean consItems = itemConsumer != null;
+
+ if(consItems) stats.timePeriod = boostItemUseTime;
+
+ if(consItems && itemConsumer instanceof ConsumeItems coni){
+ stats.remove(Stat.booster);
+ stats.add(Stat.booster, StatValues.itemBoosters("{0}" + StatUnit.timesSpeed.localized(), stats.timePeriod, itemBoostIntensity, 0f, coni.items, i -> Structs.contains(coni.items, s -> s.item == i)));
+ }
+
+ if(liquidBoostIntensity != 1 && findConsumer(f -> f instanceof ConsumeLiquidBase && f.booster) instanceof ConsumeLiquidBase consBase){
+ stats.remove(Stat.booster);
+ stats.add(Stat.booster,
+ StatValues.speedBoosters("{0}" + StatUnit.timesSpeed.localized(),
+ consBase.amount,
+ liquidBoostIntensity, false, consBase::consumes)
+ );
+ }
+ }
+
+ @Override
+ public void init(){
+ super.init();
+
+ hasLiquidBooster = findConsumer(f -> f instanceof ConsumeLiquidBase && f.booster) != null;
}
@Override
@@ -151,6 +187,7 @@ public class WallCrafter extends Block{
super.updateTile();
boolean cons = shouldConsume();
+ boolean itemValid = itemConsumer != null && itemConsumer.efficiency(this) > 0;
warmup = Mathf.approachDelta(warmup, Mathf.num(efficiency > 0), 1f / 40f);
float dx = Geometry.d4x(rotation) * 0.5f, dy = Geometry.d4y(rotation) * 0.5f;
@@ -164,7 +201,11 @@ public class WallCrafter extends Block{
dest.block().mapColor
);
}
- }, null);
+ }, null) * Mathf.lerp(1f, liquidBoostIntensity, hasLiquidBooster ? optionalEfficiency : 0f) * (itemValid ? itemBoostIntensity : 1f);
+
+ if(itemValid && eff * efficiency > 0 && timer(timerUse, boostItemUseTime)){
+ consume();
+ }
lastEfficiency = eff * timeScale * efficiency;
@@ -173,16 +214,16 @@ public class WallCrafter extends Block{
time %= drillTime;
}
- totalTime += edelta() * warmup;
+ totalTime += edelta() * warmup * (eff <= 0f ? 0f : 1f);
if(timer(timerDump, dumpTime)){
- dump();
+ dump(output);
}
}
@Override
public boolean shouldConsume(){
- return items.total() < itemCapacity;
+ return items.get(output) < itemCapacity;
}
@Override
diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java
index 15a80f0c6e..11f7b8c893 100644
--- a/core/src/mindustry/world/blocks/storage/CoreBlock.java
+++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java
@@ -733,15 +733,14 @@ public class CoreBlock extends StorageBlock{
@Override
public void onRemoved(){
- int total = proximity.count(e -> e.items != null && e.items == items);
- float fract = 1f / total / state.teams.cores(team).size;
+ int totalCapacity = proximity.sum(e -> e.items != null && e.items == items ? e.block.itemCapacity : 0);
proximity.each(e -> owns(e) && e.items == items && owns(e), t -> {
StorageBuild ent = (StorageBuild)t;
ent.linkedCore = null;
ent.items = new ItemModule();
for(Item item : content.items()){
- ent.items.set(item, (int)(fract * items.get(item)));
+ ent.items.set(item, (int)Math.min(ent.block.itemCapacity, items.get(item) * (float)ent.block.itemCapacity / totalCapacity));
}
});
diff --git a/core/src/mindustry/world/blocks/storage/Unloader.java b/core/src/mindustry/world/blocks/storage/Unloader.java
index db0fdbfe1e..08a9880162 100644
--- a/core/src/mindustry/world/blocks/storage/Unloader.java
+++ b/core/src/mindustry/world/blocks/storage/Unloader.java
@@ -7,6 +7,7 @@ import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import arc.util.pooling.*;
+import arc.util.pooling.Pool.*;
import mindustry.annotations.Annotations.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
@@ -68,7 +69,7 @@ public class Unloader extends Block{
removeBar("items");
}
- public static class ContainerStat{
+ public static class ContainerStat implements Poolable{
Building building;
float loadFactor;
boolean canLoad;
@@ -76,6 +77,11 @@ public class Unloader extends Block{
/** Cached !(building instanceof StorageBuild) */
boolean notStorage;
int lastUsed;
+
+ @Override
+ public void reset(){
+ building = null;
+ }
}
public class UnloaderBuild extends Building{
@@ -255,4 +261,4 @@ public class Unloader extends Block{
sortItem = id == -1 ? null : content.item(id);
}
}
-}
\ No newline at end of file
+}
diff --git a/core/src/mindustry/world/blocks/units/Reconstructor.java b/core/src/mindustry/world/blocks/units/Reconstructor.java
index 25b6e72226..8c243d878c 100644
--- a/core/src/mindustry/world/blocks/units/Reconstructor.java
+++ b/core/src/mindustry/world/blocks/units/Reconstructor.java
@@ -89,7 +89,7 @@ public class Reconstructor extends UnitBlock{
table.table(Styles.grayPanel, t -> {
t.left();
- t.image(upgrade[0].uiIcon).size(40).pad(10f).left().scaling(Scaling.fit);
+ t.image(upgrade[0].uiIcon).size(40).pad(10f).left().scaling(Scaling.fit).with(i -> StatValues.withTooltip(i, upgrade[0]));
t.table(info -> {
info.add(upgrade[0].localizedName).left();
info.row();
@@ -104,7 +104,7 @@ public class Reconstructor extends UnitBlock{
table.table(Styles.grayPanel, t -> {
t.left();
- t.image(upgrade[1].uiIcon).size(40).pad(10f).right().scaling(Scaling.fit);
+ t.image(upgrade[1].uiIcon).size(40).pad(10f).right().scaling(Scaling.fit).with(i -> StatValues.withTooltip(i, upgrade[1]));
t.table(info -> {
info.add(upgrade[1].localizedName).right();
info.row();
@@ -168,7 +168,7 @@ public class Reconstructor extends UnitBlock{
public boolean canSetCommand(){
var output = unit();
- return output != null && output.commands.length > 1;
+ return output != null && output.commands.size > 1 && output.allowChangeCommands;
}
@Override
@@ -311,10 +311,8 @@ public class Reconstructor extends UnitBlock{
if(commandPos != null){
payload.unit.command().commandPosition(commandPos);
}
- if(command != null){
- //this already checks if it is a valid command for the unit type
- payload.unit.command().command(command);
- }
+ //this already checks if it is a valid command for the unit type
+ payload.unit.command().command(command == null && payload.unit.type.defaultCommand != null ? payload.unit.type.defaultCommand : command);
}
progress %= 1f;
diff --git a/core/src/mindustry/world/blocks/units/UnitAssembler.java b/core/src/mindustry/world/blocks/units/UnitAssembler.java
index 2d2a40115e..2311d4100a 100644
--- a/core/src/mindustry/world/blocks/units/UnitAssembler.java
+++ b/core/src/mindustry/world/blocks/units/UnitAssembler.java
@@ -150,7 +150,7 @@ public class UnitAssembler extends PayloadBlock{
}
if(plan.unit.unlockedNow()){
- t.image(plan.unit.uiIcon).scaling(Scaling.fit).size(40).pad(10f).left();
+ t.image(plan.unit.uiIcon).scaling(Scaling.fit).size(40).pad(10f).left().with(i -> StatValues.withTooltip(i, plan.unit));
t.table(info -> {
info.defaults().left();
info.add(plan.unit.localizedName);
@@ -170,7 +170,7 @@ public class UnitAssembler extends PayloadBlock{
}
PayloadStack stack = plan.requirements.get(i);
- req.add(new ItemImage(stack)).pad(5);
+ req.add(StatValues.stack(stack)).pad(5);
}
}).right().grow().pad(10f);
}else{
@@ -452,7 +452,7 @@ public class UnitAssembler extends PayloadBlock{
unit.command().commandPosition(commandPos);
}
unit.set(spawn.x + Mathf.range(0.001f), spawn.y + Mathf.range(0.001f));
- unit.rotation = 90f;
+ unit.rotation = rotdeg();
unit.add();
}
@@ -507,7 +507,7 @@ public class UnitAssembler extends PayloadBlock{
//margin due to units not taking up whole region
Shaders.blockbuild.progress = Mathf.clamp(progress + 0.05f);
- Draw.rect(plan.unit.fullIcon, sx, sy);
+ Draw.rect(plan.unit.fullIcon, sx, sy, rotdeg() - 90f);
Draw.flush();
Draw.color();
});
@@ -519,7 +519,7 @@ public class UnitAssembler extends PayloadBlock{
//draw unit silhouette
Draw.mixcol(Tmp.c1.set(Pal.accent).lerp(Pal.remove, invalidWarmup), 1f);
Draw.alpha(Math.min(powerWarmup, sameTypeWarmup));
- Draw.rect(plan.unit.fullIcon, spawn.x, spawn.y);
+ Draw.rect(plan.unit.fullIcon, spawn.x, spawn.y, rotdeg() - 90f);
//build beams do not draw when invalid
Draw.alpha(Math.min(1f - invalidWarmup, warmup));
diff --git a/core/src/mindustry/world/blocks/units/UnitFactory.java b/core/src/mindustry/world/blocks/units/UnitFactory.java
index b89d945c65..10ee5a3a13 100644
--- a/core/src/mindustry/world/blocks/units/UnitFactory.java
+++ b/core/src/mindustry/world/blocks/units/UnitFactory.java
@@ -6,11 +6,14 @@ import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
import arc.scene.style.*;
+import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.*;
+import mindustry.ai.*;
+import mindustry.ctype.*;
import mindustry.entities.*;
import mindustry.entities.units.*;
import mindustry.game.EventType.*;
@@ -46,23 +49,32 @@ public class UnitFactory extends UnitBlock{
commandable = true;
ambientSound = Sounds.respawning;
- config(Integer.class, (UnitFactoryBuild tile, Integer i) -> {
+ config(Integer.class, (UnitFactoryBuild build, Integer i) -> {
if(!configurable) return;
- if(tile.currentPlan == i) return;
- tile.currentPlan = i < 0 || i >= plans.size ? -1 : i;
- tile.progress = 0;
+ if(build.currentPlan == i) return;
+ build.currentPlan = i < 0 || i >= plans.size ? -1 : i;
+ build.progress = 0;
+ if(build.command != null && !build.unit().commands.contains(build.command)){
+ build.command = null;
+ }
});
- config(UnitType.class, (UnitFactoryBuild tile, UnitType val) -> {
+ config(UnitType.class, (UnitFactoryBuild build, UnitType val) -> {
if(!configurable) return;
int next = plans.indexOf(p -> p.unit == val);
- if(tile.currentPlan == next) return;
- tile.currentPlan = next;
- tile.progress = 0;
+ if(build.currentPlan == next) return;
+ build.currentPlan = next;
+ build.progress = 0;
+ if(build.command != null && !val.commands.contains(build.command)){
+ build.command = null;
+ }
});
+ config(UnitCommand.class, (UnitFactoryBuild build, UnitCommand command) -> build.command = command);
+ configClear((UnitFactoryBuild build) -> build.command = null);
+
consume(new ConsumeItemDynamic((UnitFactoryBuild e) -> e.currentPlan != -1 ? plans.get(Math.min(e.currentPlan, plans.size - 1)).requirements : ItemStack.empty));
}
@@ -122,7 +134,7 @@ public class UnitFactory extends UnitBlock{
}
if(plan.unit.unlockedNow()){
- t.image(plan.unit.uiIcon).size(40).pad(10f).left().scaling(Scaling.fit);
+ t.image(plan.unit.uiIcon).size(40).pad(10f).left().scaling(Scaling.fit).with(i -> StatValues.withTooltip(i, plan.unit));
t.table(info -> {
info.add(plan.unit.localizedName).left();
info.row();
@@ -137,7 +149,7 @@ public class UnitFactory extends UnitBlock{
}
ItemStack stack = plan.requirements[i];
- req.add(new ItemDisplay(stack.item, stack.amount, plan.time, true)).pad(5);
+ req.add(StatValues.displayItem(stack.item, stack.amount, plan.time, true)).pad(5);
}
}).right().grow().pad(10f);
}else{
@@ -161,6 +173,15 @@ public class UnitFactory extends UnitBlock{
Draw.rect(topRegion, plan.drawx(), plan.drawy());
}
+ @Override
+ public void getPlanConfigs(Seq options){
+ for(var plan : plans){
+ if(!plan.unit.isBanned()){
+ options.add(plan.unit);
+ }
+ }
+ }
+
public static class UnitPlan{
public UnitType unit;
public ItemStack[] requirements;
@@ -177,12 +198,28 @@ public class UnitFactory extends UnitBlock{
public class UnitFactoryBuild extends UnitBuild{
public @Nullable Vec2 commandPos;
+ public @Nullable UnitCommand command;
public int currentPlan = -1;
public float fraction(){
return currentPlan == -1 ? 0 : progress / plans.get(currentPlan).time;
}
+ public boolean canSetCommand(){
+ var output = unit();
+ return output != null && output.commands.size > 1 && output.allowChangeCommands &&
+ //to avoid cluttering UI, don't show command selection for "standard" units that only have two commands.
+ !(output.commands.size == 2 && output.commands.get(1) == UnitCommand.enterPayloadCommand);
+ }
+
+ @Override
+ public void created(){
+ //auto-set to the first plan, it's better than nothing.
+ if(currentPlan == -1){
+ currentPlan = plans.indexOf(u -> u.unit.unlockedNow());
+ }
+ }
+
@Override
public Vec2 getCommandPosition(){
return commandPos;
@@ -217,6 +254,62 @@ public class UnitFactory extends UnitBlock{
if(units.any()){
ItemSelection.buildTable(UnitFactory.this, table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit)), selectionRows, selectionColumns);
+
+ table.row();
+
+ Table commands = new Table();
+ commands.top().left();
+
+ Runnable rebuildCommands = () -> {
+ commands.clear();
+ commands.background(null);
+ var unit = unit();
+ if(unit != null && canSetCommand()){
+ commands.background(Styles.black6);
+ var group = new ButtonGroup();
+ group.setMinCheckCount(0);
+ int i = 0, columns = Mathf.clamp(units.size, 2, selectionColumns);
+ var list = unit.commands;
+
+ commands.image(Tex.whiteui, Pal.gray).height(4f).growX().colspan(columns).row();
+
+ for(var item : list){
+ ImageButton button = commands.button(item.getIcon(), Styles.clearNoneTogglei, 40f, () -> {
+ configure(item);
+ }).tooltip(item.localized()).group(group).get();
+
+ button.update(() -> button.setChecked(command == item || (command == null && unit.defaultCommand == item)));
+
+ if(++i % columns == 0){
+ commands.row();
+ }
+ }
+
+ if(list.size < columns){
+ for(int j = 0; j < (columns - list.size); j++){
+ commands.add().size(40f);
+ }
+ }
+ }
+ };
+
+ rebuildCommands.run();
+
+ //Since the menu gets hidden when a new unit is selected, this is unnecessary.
+ /*
+ UnitType[] lastUnit = {unit()};
+
+ commands.update(() -> {
+ if(lastUnit[0] != unit()){
+ lastUnit[0] = unit();
+ rebuildCommands.run();
+ }
+ });*/
+
+ table.row();
+
+ table.add(commands).fillX().left();
+
}else{
table.table(Styles.black3, t -> t.add("@none").color(Color.lightGray));
}
@@ -303,9 +396,14 @@ public class UnitFactory extends UnitBlock{
progress %= 1f;
Unit unit = plan.unit.create(team);
- if(commandPos != null && unit.isCommandable()){
- unit.command().commandPosition(commandPos);
+ if(unit.isCommandable()){
+ if(commandPos != null){
+ unit.command().commandPosition(commandPos);
+ }
+
+ unit.command().command(command == null && unit.type.defaultCommand != null ? unit.type.defaultCommand : command);
}
+
payload = new UnitPayload(unit);
payVector.setZero();
consume();
@@ -341,7 +439,7 @@ public class UnitFactory extends UnitBlock{
@Override
public byte version(){
- return 2;
+ return 3;
}
@Override
@@ -350,6 +448,7 @@ public class UnitFactory extends UnitBlock{
write.f(progress);
write.s(currentPlan);
TypeIO.writeVecNullable(write, commandPos);
+ TypeIO.writeCommand(write, command);
}
@Override
@@ -360,6 +459,10 @@ public class UnitFactory extends UnitBlock{
if(revision >= 2){
commandPos = TypeIO.readVecNullable(read);
}
+
+ if(revision >= 3){
+ command = TypeIO.readCommand(read);
+ }
}
}
}
diff --git a/core/src/mindustry/world/consumers/ConsumeItemDynamic.java b/core/src/mindustry/world/consumers/ConsumeItemDynamic.java
index 45325369cd..b026ce3df9 100644
--- a/core/src/mindustry/world/consumers/ConsumeItemDynamic.java
+++ b/core/src/mindustry/world/consumers/ConsumeItemDynamic.java
@@ -6,6 +6,7 @@ import mindustry.gen.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
+import mindustry.world.meta.*;
public class ConsumeItemDynamic extends Consume{
public final Func items;
@@ -42,7 +43,7 @@ public class ConsumeItemDynamic extends Consume{
int i = 0;
for(ItemStack stack : items.get(build)){
- table.add(new ReqImage(new ItemImage(stack.item.uiIcon, Math.round(stack.amount * multiplier.get(build))),
+ table.add(new ReqImage(StatValues.stack(stack.item, Math.round(stack.amount * multiplier.get(build))),
() -> build.items != null && build.items.has(stack.item, Math.round(stack.amount * multiplier.get(build))))).padRight(8).left();
if(++i % 4 == 0) table.row();
}
diff --git a/core/src/mindustry/world/consumers/ConsumeItemFilter.java b/core/src/mindustry/world/consumers/ConsumeItemFilter.java
index 8993bd59e1..a2ed17f52d 100644
--- a/core/src/mindustry/world/consumers/ConsumeItemFilter.java
+++ b/core/src/mindustry/world/consumers/ConsumeItemFilter.java
@@ -31,7 +31,7 @@ public class ConsumeItemFilter extends Consume{
@Override
public void build(Building build, Table table){
MultiReqImage image = new MultiReqImage();
- content.items().each(i -> filter.get(i) && i.unlockedNow(), item -> image.add(new ReqImage(new ItemImage(item.uiIcon, 1),
+ content.items().each(i -> filter.get(i) && i.unlockedNow(), item -> image.add(new ReqImage(StatValues.stack(item, 1),
() -> build.items.has(item))));
table.add(image).size(8 * 4);
diff --git a/core/src/mindustry/world/consumers/ConsumeItems.java b/core/src/mindustry/world/consumers/ConsumeItems.java
index 791db5a71d..c43fa42a32 100644
--- a/core/src/mindustry/world/consumers/ConsumeItems.java
+++ b/core/src/mindustry/world/consumers/ConsumeItems.java
@@ -33,7 +33,7 @@ public class ConsumeItems extends Consume{
table.table(c -> {
int i = 0;
for(var stack : items){
- c.add(new ReqImage(new ItemImage(stack.item.uiIcon, Math.round(stack.amount * multiplier.get(build))),
+ c.add(new ReqImage(StatValues.stack(stack.item, Math.round(stack.amount * multiplier.get(build))),
() -> build.items.has(stack.item, Math.round(stack.amount * multiplier.get(build))))).padRight(8);
if(++i % 4 == 0) c.row();
}
diff --git a/core/src/mindustry/world/consumers/ConsumeLiquid.java b/core/src/mindustry/world/consumers/ConsumeLiquid.java
index 3581a4f3fa..a4a3ebc460 100644
--- a/core/src/mindustry/world/consumers/ConsumeLiquid.java
+++ b/core/src/mindustry/world/consumers/ConsumeLiquid.java
@@ -50,4 +50,9 @@ public class ConsumeLiquid extends ConsumeLiquidBase{
public void display(Stats stats){
stats.add(booster ? Stat.booster : Stat.input, liquid, amount * 60f, true);
}
+
+ @Override
+ public boolean consumes(Liquid liquid){
+ return liquid == this.liquid;
+ }
}
diff --git a/core/src/mindustry/world/consumers/ConsumeLiquidBase.java b/core/src/mindustry/world/consumers/ConsumeLiquidBase.java
index 1a55711416..9a74338434 100644
--- a/core/src/mindustry/world/consumers/ConsumeLiquidBase.java
+++ b/core/src/mindustry/world/consumers/ConsumeLiquidBase.java
@@ -1,5 +1,6 @@
package mindustry.world.consumers;
+import mindustry.type.*;
import mindustry.world.*;
public abstract class ConsumeLiquidBase extends Consume{
@@ -16,4 +17,6 @@ public abstract class ConsumeLiquidBase extends Consume{
public void apply(Block block){
block.hasLiquids = true;
}
+
+ public abstract boolean consumes(Liquid liquid);
}
diff --git a/core/src/mindustry/world/consumers/ConsumeLiquidFilter.java b/core/src/mindustry/world/consumers/ConsumeLiquidFilter.java
index 7dbaab7043..94e049c260 100644
--- a/core/src/mindustry/world/consumers/ConsumeLiquidFilter.java
+++ b/core/src/mindustry/world/consumers/ConsumeLiquidFilter.java
@@ -53,7 +53,7 @@ public class ConsumeLiquidFilter extends ConsumeLiquidBase{
if(ed <= 0.00000001f) return 0f;
return liq != null ? Math.min(build.liquids.get(liq) / (amount * ed * multiplier.get(build)), 1f) : 0f;
}
-
+
public @Nullable Liquid getConsumed(Building build){
if(filter.get(build.liquids.current()) && build.liquids.currentAmount() > 0){
return build.liquids.current();
@@ -74,4 +74,9 @@ public class ConsumeLiquidFilter extends ConsumeLiquidBase{
public void display(Stats stats){
stats.add(booster ? Stat.booster : Stat.input, StatValues.liquids(filter, amount * 60f, true));
}
+
+ @Override
+ public boolean consumes(Liquid liquid){
+ return filter.get(liquid);
+ }
}
diff --git a/core/src/mindustry/world/consumers/ConsumePayloadDynamic.java b/core/src/mindustry/world/consumers/ConsumePayloadDynamic.java
index d12abb009d..ebb6f32430 100644
--- a/core/src/mindustry/world/consumers/ConsumePayloadDynamic.java
+++ b/core/src/mindustry/world/consumers/ConsumePayloadDynamic.java
@@ -63,7 +63,7 @@ public class ConsumePayloadDynamic extends Consume{
table.table(c -> {
int i = 0;
for(var stack : pay){
- c.add(new ReqImage(new ItemImage(stack.item.uiIcon, Math.round(stack.amount * multiplier.get(build))),
+ c.add(new ReqImage(StatValues.stack(stack.item, Math.round(stack.amount * multiplier.get(build))),
() -> inv.contains(stack.item, Math.round(stack.amount * multiplier.get(build))))).padRight(8);
if(++i % 4 == 0) c.row();
}
diff --git a/core/src/mindustry/world/consumers/ConsumePayloadFilter.java b/core/src/mindustry/world/consumers/ConsumePayloadFilter.java
index e43fc41a1c..ffcf0dc2a6 100644
--- a/core/src/mindustry/world/consumers/ConsumePayloadFilter.java
+++ b/core/src/mindustry/world/consumers/ConsumePayloadFilter.java
@@ -57,7 +57,7 @@ public class ConsumePayloadFilter extends Consume{
MultiReqImage image = new MultiReqImage();
content.blocks().each(i -> filter.get(i) && i.unlockedNow(),
- block -> image.add(new ReqImage(new ItemImage(block.uiIcon, 1),
+ block -> image.add(new ReqImage(StatValues.stack(block, 1),
() -> inv.contains(block, 1)))
);
diff --git a/core/src/mindustry/world/consumers/ConsumePayloads.java b/core/src/mindustry/world/consumers/ConsumePayloads.java
index ae905a4e8b..cbbc4145e6 100644
--- a/core/src/mindustry/world/consumers/ConsumePayloads.java
+++ b/core/src/mindustry/world/consumers/ConsumePayloads.java
@@ -38,7 +38,7 @@ public class ConsumePayloads extends Consume{
for(var stack : payloads){
stats.add(Stat.input, t -> {
- t.add(new ItemImage(stack));
+ t.add(StatValues.stack(stack));
t.add(stack.item.localizedName).padLeft(4).padRight(4);
});
}
@@ -51,7 +51,7 @@ public class ConsumePayloads extends Consume{
table.table(c -> {
int i = 0;
for(var stack : payloads){
- c.add(new ReqImage(new ItemImage(stack.item.uiIcon, Math.round(stack.amount * multiplier.get(build))),
+ c.add(new ReqImage(StatValues.stack(stack.item, Math.round(stack.amount * multiplier.get(build))),
() -> inv.contains(stack.item, Math.round(stack.amount * multiplier.get(build))))).padRight(8);
if(++i % 4 == 0) c.row();
}
diff --git a/core/src/mindustry/world/meta/BlockFlag.java b/core/src/mindustry/world/meta/BlockFlag.java
index 314c0424b6..82d073a780 100644
--- a/core/src/mindustry/world/meta/BlockFlag.java
+++ b/core/src/mindustry/world/meta/BlockFlag.java
@@ -22,6 +22,8 @@ public enum BlockFlag{
extinguisher,
/** Is a drill. */
drill,
+ /** Force projector block. */
+ shield,
//special, internal identifiers
launchPad,
@@ -32,5 +34,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, battery, reactor};
+ public final static BlockFlag[] allLogic = {core, storage, generator, turret, factory, repair, battery, reactor, drill, shield};
}
diff --git a/core/src/mindustry/world/meta/BuildVisibility.java b/core/src/mindustry/world/meta/BuildVisibility.java
index ee84452779..5572b3cdf2 100644
--- a/core/src/mindustry/world/meta/BuildVisibility.java
+++ b/core/src/mindustry/world/meta/BuildVisibility.java
@@ -2,6 +2,7 @@ package mindustry.world.meta;
import arc.func.*;
import mindustry.*;
+import mindustry.content.*;
public class BuildVisibility{
public static final BuildVisibility
@@ -10,6 +11,8 @@ public class BuildVisibility{
shown = new BuildVisibility(() -> true),
debugOnly = new BuildVisibility(() -> false),
editorOnly = new BuildVisibility(() -> Vars.state.rules.editor),
+ coreZoneOnly = new BuildVisibility(() -> Vars.indexer.isBlockPresent(Blocks.coreZone)),
+ worldProcessorOnly = new BuildVisibility(() -> Vars.state.rules.editor || Vars.state.rules.allowEditWorldProcessors),
sandboxOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.rules.infiniteResources),
campaignOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.isCampaign()),
lightingOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.rules.lighting || Vars.state.isCampaign()),
diff --git a/core/src/mindustry/world/meta/StatValues.java b/core/src/mindustry/world/meta/StatValues.java
index 9c548f2836..d0be047ebc 100644
--- a/core/src/mindustry/world/meta/StatValues.java
+++ b/core/src/mindustry/world/meta/StatValues.java
@@ -5,12 +5,16 @@ import arc.func.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
+import arc.scene.*;
+import arc.scene.event.*;
import arc.scene.ui.*;
+import arc.scene.ui.Tooltip.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.entities.abilities.*;
import mindustry.entities.bullet.*;
@@ -66,7 +70,7 @@ public class StatValues{
}
public static StatValue liquid(Liquid liquid, float amount, boolean perSecond){
- return table -> table.add(new LiquidDisplay(liquid, amount, perSecond));
+ return table -> table.add(displayLiquid(liquid, amount, perSecond));
}
public static StatValue liquids(Boolf filter, float amount, boolean perSecond){
@@ -74,7 +78,7 @@ public class StatValues{
Seq list = content.liquids().select(i -> filter.get(i) && i.unlockedNow() && !i.isHidden());
for(int i = 0; i < list.size; i++){
- table.add(new LiquidDisplay(list.get(i), amount, perSecond)).padRight(5);
+ table.add(displayLiquid(list.get(i), amount, perSecond)).padRight(5);
if(i != list.size - 1){
table.add("/");
@@ -90,7 +94,7 @@ public class StatValues{
public static StatValue liquids(float timePeriod, boolean perSecond, LiquidStack... stacks){
return table -> {
for(var stack : stacks){
- table.add(new LiquidDisplay(stack.liquid, stack.amount * (60f / timePeriod), perSecond)).padRight(5);
+ table.add(displayLiquid(stack.liquid, stack.amount * (60f / timePeriod), perSecond)).padRight(5);
}
};
}
@@ -102,7 +106,7 @@ public class StatValues{
public static StatValue items(boolean displayName, ItemStack... stacks){
return table -> {
for(ItemStack stack : stacks){
- table.add(new ItemDisplay(stack.item, stack.amount, displayName)).padRight(5);
+ table.add(displayItem(stack.item, stack.amount, displayName)).padRight(5);
}
};
}
@@ -110,7 +114,7 @@ public class StatValues{
public static StatValue items(float timePeriod, ItemStack... stacks){
return table -> {
for(ItemStack stack : stacks){
- table.add(new ItemDisplay(stack.item, stack.amount, timePeriod, true)).padRight(5);
+ table.add(displayItem(stack.item, stack.amount, timePeriod, true)).padRight(5);
}
};
}
@@ -126,7 +130,7 @@ public class StatValues{
for(int i = 0; i < list.size; i++){
Item item = list.get(i);
- table.add(timePeriod <= 0 ? new ItemDisplay(item) : new ItemDisplay(item, 1, timePeriod, true)).padRight(5);
+ table.add(timePeriod <= 0 ? displayItem(item) : displayItem(item, 1, timePeriod, true)).padRight(5);
if(i != list.size - 1){
table.add("/");
@@ -135,6 +139,127 @@ public class StatValues{
};
}
+ public static Table displayLiquid(Liquid liquid, float amount, boolean perSecond){
+ Table t = new Table();
+
+ t.add(new Stack(){{
+ add(new Image(liquid.uiIcon).setScaling(Scaling.fit));
+
+ if(amount != 0){
+ Table t = new Table().left().bottom();
+ t.add(Strings.autoFixed(amount, 2)).style(Styles.outlineLabel);
+ add(t);
+ }
+ }}).size(iconMed).padRight(3 + (amount != 0 && Strings.autoFixed(amount, 2).length() > 2 ? 8 : 0)).with(s -> withTooltip(s, liquid, false));
+
+ if(perSecond && amount != 0){
+ t.add(StatUnit.perSecond.localized()).padLeft(2).padRight(5).color(Color.lightGray).style(Styles.outlineLabel);
+ }
+
+ t.add(liquid.localizedName);
+
+ return t;
+ }
+
+ public static T withTooltip(T element, UnlockableContent content, boolean tooltip){
+ if(content != null){
+ if(!mobile){
+ if(tooltip){
+ element.addListener(Tooltips.getInstance().create(content.localizedName, mobile));
+ }
+ element.addListener(new HandCursorListener(() -> !content.isHidden(), true));
+ }
+ element.clicked(() -> {
+ if(!content.isHidden()){
+ Vars.ui.content.show(content);
+ }
+ });
+ }
+ return element;
+ }
+
+ public static T withTooltip(T element, UnlockableContent content){
+ return withTooltip(element, content, false);
+ }
+
+ /** Displays an item with a specified amount. */
+ private static Stack stack(TextureRegion region, int amount, @Nullable UnlockableContent content, boolean tooltip){
+ Stack stack = new Stack();
+
+ stack.add(new Table(o -> {
+ o.left();
+ o.add(new Image(region)).size(32f).scaling(Scaling.fit);
+ }));
+
+ if(amount != 0){
+ stack.add(new Table(t -> {
+ t.left().bottom();
+ t.add(amount >= 1000 ? UI.formatAmount(amount) : amount + "").style(Styles.outlineLabel);
+ t.pack();
+ }));
+ }
+
+ withTooltip(stack, content, tooltip);
+
+ return stack;
+ }
+
+ /** Displays an item with a specified amount. */
+ private static Stack stack(TextureRegion region, int amount, @Nullable UnlockableContent content){
+ return stack(region, amount, content, true);
+ }
+
+ public static Stack stack(ItemStack stack){
+ return stack(stack.item.uiIcon, stack.amount, stack.item);
+ }
+
+ public static Stack stack(UnlockableContent item, int amount){
+ return stack(item.uiIcon, amount, item);
+ }
+
+ public static Stack stack(UnlockableContent item, int amount, boolean tooltip){
+ return stack(item.uiIcon, amount, item, tooltip);
+ }
+
+ public static Stack stack(Item item){
+ return stack(item.uiIcon, 0, item);
+ }
+
+ public static Stack stack(PayloadStack stack){
+ return stack(stack.item.uiIcon, stack.amount, stack.item);
+ }
+
+ public static Table displayItem(Item item){
+ return displayItem(item, 0);
+ }
+
+ public static Table displayItem(Item item, int amount, boolean showName){
+ Table t = new Table();
+ t.add(stack(item, amount, !showName));
+ if(showName) t.add(item.localizedName).padLeft(4 + amount > 99 ? 4 : 0);
+ return t;
+ }
+
+ public static Table displayItem(Item item, int amount){
+ return displayItem(item, amount, true);
+ }
+
+ /** Displays the item with a "/sec" qualifier based on the time period, in ticks. */
+ public static Table displayItem(Item item, int amount, float timePeriod, boolean showName){
+ Table t = new Table();
+ t.add(stack(item, amount, !showName));
+ t.add((showName ? item.localizedName + "\n" : "") + "[lightgray]" + Strings.autoFixed(amount / (timePeriod / 60f), 2) + StatUnit.perSecond.localized()).padLeft(2).padRight(5).style(Styles.outlineLabel);
+ return t;
+ }
+
+ /** Displays the item with a "/sec" qualifier based on the time period, in ticks. */
+ public static Table displayItemPercent(Item item, int percent, boolean showName){
+ Table t = new Table();
+ t.add(stack(item, 0, !showName));
+ t.add((showName ? item.localizedName + "\n" : "") + "[lightgray]" + percent + "%").padLeft(2).padRight(5).style(Styles.outlineLabel);
+ return t;
+ }
+
public static StatValue content(UnlockableContent content){
return table -> {
table.add(new Image(content.uiIcon)).size(iconSmall).padRight(3);
@@ -212,7 +337,7 @@ public class StatValues{
if(!check.get(item)) continue;
any = true;
- if(item.uiIcon.found()) l.image(item.uiIcon).size(iconSmall).padRight(2).padLeft(2).padTop(3).padBottom(3);
+ if(item.uiIcon.found()) l.image(item.uiIcon).size(iconSmall).scaling(Scaling.fit).padRight(2).padLeft(2).padTop(3).padBottom(3).with(img -> withTooltip(img, item, false));
l.add(item.localizedName).left().padLeft(1).padRight(4).colspan(item.uiIcon.found() ? 1 : 2);
if(i % 5 == 4){
l.row();
@@ -250,7 +375,7 @@ public class StatValues{
b.table(info -> {
info.left();
info.add(block.localizedName).left().row();
- info.add(block.itemDrop.emoji()).left();
+ info.add(block.itemDrop.emoji()).with(l -> withTooltip(l, block.itemDrop)).left();
}).grow();
if(multipliers != null){
b.add(Strings.autoFixed(60f / (Math.max(drillTime + drillMultiplier * block.itemDrop.hardness, drillTime) / multipliers.get(block.itemDrop, 1f)) * size, 2) + StatUnit.perSecond.localized())
@@ -271,7 +396,7 @@ public class StatValues{
if(!filter.get(liquid)) continue;
c.table(Styles.grayPanel, b -> {
- b.image(liquid.uiIcon).size(40).pad(10f).left().scaling(Scaling.fit);
+ b.image(liquid.uiIcon).size(40).pad(10f).left().scaling(Scaling.fit).with(i -> withTooltip(i, liquid, false));;
b.table(info -> {
info.add(liquid.localizedName).left().row();
info.add(Strings.autoFixed(maxUsed * 60f, 2) + StatUnit.perSecond.localized()).left().color(Color.lightGray);
@@ -300,7 +425,7 @@ public class StatValues{
if(!filter.get(liquid)) continue;
c.table(Styles.grayPanel, b -> {
- b.image(liquid.uiIcon).size(40).pad(10f).left().scaling(Scaling.fit);
+ b.image(liquid.uiIcon).size(40).pad(10f).left().scaling(Scaling.fit).with(i -> withTooltip(i, liquid, false));;
b.table(info -> {
info.add(liquid.localizedName).left().row();
info.add(Strings.autoFixed(amount * 60f, 2) + StatUnit.perSecond.localized()).left().color(Color.lightGray);
@@ -327,9 +452,9 @@ public class StatValues{
c.table(Styles.grayPanel, b -> {
for(ItemStack stack : items){
if(timePeriod < 0){
- b.add(new ItemDisplay(stack.item, stack.amount, true)).pad(20f).left();
+ b.add(displayItem(stack.item, stack.amount, true)).pad(20f).left();
}else{
- b.add(new ItemDisplay(stack.item, stack.amount, timePeriod, true)).pad(20f).left();
+ b.add(displayItem(stack.item, stack.amount, timePeriod, true)).pad(20f).left();
}
if(items.length > 1) b.row();
}
@@ -425,7 +550,7 @@ public class StatValues{
//no point in displaying unit icon twice
if(!compact && !(t instanceof Turret)){
bt.table(title -> {
- title.image(icon(t)).size(3 * 8).padRight(4).right().scaling(Scaling.fit).top();
+ title.image(icon(t)).size(3 * 8).padRight(4).right().scaling(Scaling.fit).top().with(i -> withTooltip(i, t, false));
title.add(t.localizedName).padRight(10).left().top();
});
bt.row();
@@ -494,7 +619,7 @@ public class StatValues{
}
if(type.maxDamageFraction > 0){
- sep(bt, Core.bundle.format("bullet.maxdamagefraction", (int)(type.maxDamageFraction * 100)));
+ sep(bt, Core.bundle.format("bullet.maxdamagefraction", (int)(type.maxDamageFraction * 100)));
}
if(type.suppressionRange > 0){
@@ -502,7 +627,16 @@ public class StatValues{
}
if(type.status != StatusEffects.none){
- sep(bt, (type.status.hasEmoji() ? type.status.emoji() : "") + "[stat]" + type.status.localizedName + (type.status.reactive ? "" : "[lightgray] ~ [stat]" + ((int)(type.statusDuration / 60f)) + "[lightgray] " + Core.bundle.get("unit.seconds")));
+ sep(bt, (type.status.hasEmoji() ? type.status.emoji() : "") + "[stat]" + type.status.localizedName + (type.status.reactive ? "" : "[lightgray] ~ [stat]" +
+ ((int)(type.statusDuration / 60f)) + "[lightgray] " + Core.bundle.get("unit.seconds"))).with(c -> withTooltip(c, type.status));
+ }
+
+ if(!type.targetMissiles){
+ sep(bt, "@bullet.notargetsmissiles");
+ }
+
+ if(!type.targetBlocks){
+ sep(bt, "@bullet.notargetsbuildings");
}
if(type.intervalBullet != null){
@@ -547,9 +681,9 @@ public class StatValues{
}
//for AmmoListValue
- private static void sep(Table table, String text){
+ private static Cell> sep(Table table, String text){
table.row();
- table.add(text);
+ return table.add(text);
}
//for AmmoListValue
diff --git a/core/src/mindustry/world/meta/Stats.java b/core/src/mindustry/world/meta/Stats.java
index 7056c6fa2c..b776994228 100644
--- a/core/src/mindustry/world/meta/Stats.java
+++ b/core/src/mindustry/world/meta/Stats.java
@@ -73,6 +73,12 @@ public class Stats{
add(stat, StatValues.string(format, args));
}
+ /** Replaces a stat, removing the old value if it exists. */
+ public void replace(Stat stat, StatValue value){
+ remove(stat);
+ add(stat, value);
+ }
+
/** Adds a stat value. */
public void add(Stat stat, StatValue value){
if(map == null) map = new OrderedMap<>();
diff --git a/core/src/mindustry/world/modules/ItemModule.java b/core/src/mindustry/world/modules/ItemModule.java
index 04c9a878c2..5f01d335e3 100644
--- a/core/src/mindustry/world/modules/ItemModule.java
+++ b/core/src/mindustry/world/modules/ItemModule.java
@@ -179,8 +179,7 @@ public class ItemModule extends BlockModule{
return total > 0;
}
- @Nullable
- public Item first(){
+ public @Nullable Item first(){
for(int i = 0; i < items.length; i++){
if(items[i] > 0){
return content.item(i);
@@ -189,8 +188,7 @@ public class ItemModule extends BlockModule{
return null;
}
- @Nullable
- public Item take(){
+ public @Nullable Item take(){
for(int i = 0; i < items.length; i++){
int index = (i + takeRotation);
if(index >= items.length) index -= items.length;
@@ -204,30 +202,6 @@ public class ItemModule extends BlockModule{
return null;
}
- /** Begins a speculative take operation. This returns the item that would be returned by #take(), but does not change state. */
- @Nullable
- public Item takeIndex(int takeRotation){
- for(int i = 0; i < items.length; i++){
- int index = (i + takeRotation);
- if(index >= items.length) index -= items.length;
- if(items[index] > 0){
- return content.item(index);
- }
- }
- return null;
- }
-
- public int nextIndex(int takeRotation){
- for(int i = 1; i < items.length; i++){
- int index = (i + takeRotation);
- if(index >= items.length) index -= items.length;
- if(items[index] > 0){
- return (takeRotation + i) % items.length;
- }
- }
- return takeRotation;
- }
-
public int get(int id){
return items[id];
}
diff --git a/desktop/build.gradle b/desktop/build.gradle
index 7f4ecdcf0a..b4d9955e70 100644
--- a/desktop/build.gradle
+++ b/desktop/build.gradle
@@ -118,20 +118,20 @@ platforms.each{ platform ->
}
}else{
def jarPath = JDK_DIR + "packr.jar"
- def args = ["java", "-jar", jarPath] as String[]
+ def args = new String[]{"java", "-jar", jarPath}
- args += [
- "--platform", platform == "MacOS" ? "Mac" : platform.toString(),
- "--jdk", JDK_DIR + "jre-${platform.toString().toLowerCase()}",
- "--executable", appName,
- "--classpath", "$rootDir/desktop/build/packr/desktop.jar".toString(),
- "--mainclass", project.ext.mainClassName,
- "--verbose",
- "--bundle", getPackage() + ".mac",
- "--icon", ICON_DIR,
- "--output", "$rootDir/desktop/build/packr/output".toString(),
- "--removelibs", "$rootDir/desktop/build/packr/desktop.jar".toString()
- ]
+ args += new String[]{
+ "--platform", platform == "MacOS" ? "Mac" : platform.toString(),
+ "--jdk", JDK_DIR + "jre-${platform.toString().toLowerCase()}",
+ "--executable", appName,
+ "--classpath", "$rootDir/desktop/build/packr/desktop.jar".toString(),
+ "--mainclass", project.ext.mainClassName,
+ "--verbose",
+ "--bundle", getPackage() + ".mac",
+ "--icon", ICON_DIR,
+ "--output", "$rootDir/desktop/build/packr/output".toString(),
+ "--removelibs", "$rootDir/desktop/build/packr/desktop.jar".toString()
+ }
args += "--vmargs"
diff --git a/desktop/src/mindustry/desktop/DesktopLauncher.java b/desktop/src/mindustry/desktop/DesktopLauncher.java
index 44f3b5b03f..2500d18e59 100644
--- a/desktop/src/mindustry/desktop/DesktopLauncher.java
+++ b/desktop/src/mindustry/desktop/DesktopLauncher.java
@@ -7,7 +7,6 @@ import arc.backend.sdl.jni.*;
import arc.discord.*;
import arc.discord.DiscordRPC.*;
import arc.files.*;
-import arc.func.*;
import arc.math.*;
import arc.struct.*;
import arc.util.*;
@@ -19,6 +18,7 @@ import mindustry.core.*;
import mindustry.desktop.steam.*;
import mindustry.game.EventType.*;
import mindustry.gen.*;
+import mindustry.mod.Mods.*;
import mindustry.net.*;
import mindustry.net.Net.*;
import mindustry.service.*;
@@ -223,27 +223,30 @@ public class DesktopLauncher extends ClientLauncher{
}
static void handleCrash(Throwable e){
- Cons dialog = Runnable::run;
boolean badGPU = false;
String finalMessage = Strings.getFinalMessage(e);
String total = Strings.getCauses(e).toString();
if(total.contains("Couldn't create window") || total.contains("OpenGL 2.0 or higher") || total.toLowerCase().contains("pixel format") || total.contains("GLEW")|| total.contains("unsupported combination of formats")){
- dialog.get(() -> message(
+ message(
total.contains("Couldn't create window") ? "A graphics initialization error has occured! Try to update your graphics drivers:\n" + finalMessage :
"Your graphics card does not support the right OpenGL features.\n" +
"Try to update your graphics drivers. If this doesn't work, your computer may not support Mindustry.\n\n" +
- "Full message: " + finalMessage));
+ "Full message: " + finalMessage);
badGPU = true;
}
boolean fbgp = badGPU;
- CrashSender.send(e, file -> {
+ LoadedMod cause = CrashHandler.getModCause(e);
+ String causeString = cause == null ? (Structs.contains(e.getStackTrace(), st -> st.getClassName().contains("rhino.gen.")) ? "A mod or script has caused Mindustry to crash.\nConsider disabling your mods if the issue persists.\n" : "Mindustry has crashed.") :
+ "'" + cause.meta.displayName + "' (" + cause.name + ") has caused Mindustry to crash.\nConsider disabling this mod if issues persist.\n";
+
+ CrashHandler.handle(e, file -> {
Throwable fc = Strings.getFinalCause(e);
if(!fbgp){
- dialog.get(() -> message("A crash has occured. It has been saved in:\n" + file.getAbsolutePath() + "\n" + fc.getClass().getSimpleName().replace("Exception", "") + (fc.getMessage() == null ? "" : ":\n" + fc.getMessage())));
+ message(causeString + "\nThe logs have been saved in:\n" + file.getAbsolutePath() + "\n" + fc.getClass().getSimpleName().replace("Exception", "") + (fc.getMessage() == null ? "" : ":\n" + fc.getMessage()));
}
});
}
diff --git a/fastlane/metadata/steam/hungarian/achievements.vdf b/fastlane/metadata/steam/hungarian/achievements.vdf
index afdc6b8013..5a98182a26 100644
--- a/fastlane/metadata/steam/hungarian/achievements.vdf
+++ b/fastlane/metadata/steam/hungarian/achievements.vdf
@@ -4,51 +4,51 @@
"Tokens"
{
"NEW_ACHIEVEMENT_20_1_NAME" "Selejtező"
- "NEW_ACHIEVEMENT_20_1_DESC" "Pusztíts el 1,000 ellenséges egységet."
+ "NEW_ACHIEVEMENT_20_1_DESC" "Pusztíts el 1 000 ellenséges egységet."
"NEW_ACHIEVEMENT_20_2_NAME" "Megtisztulás"
- "NEW_ACHIEVEMENT_20_2_DESC" "Pusztíts el 100,000 ellenséges egységet."
- "NEW_ACHIEVEMENT_20_5_NAME" "Végtelen Szállítmányok"
- "NEW_ACHIEVEMENT_20_5_DESC" "Összesen 100,000 tétel elindítása a szektorok között."
+ "NEW_ACHIEVEMENT_20_2_DESC" "Pusztíts el 100 000 ellenséges egységet."
+ "NEW_ACHIEVEMENT_20_5_NAME" "Végtelen szállítmányok"
+ "NEW_ACHIEVEMENT_20_5_DESC" "Összesen 100 000 nyersanyag elindítása a szektorok között."
"NEW_ACHIEVEMENT_20_6_NAME" "Hódító"
"NEW_ACHIEVEMENT_20_6_DESC" "Nyerj meg 10 támadó módú mérkőzést."
"NEW_ACHIEVEMENT_20_7_NAME" "Bajnok"
"NEW_ACHIEVEMENT_20_7_DESC" "Nyerj meg 10 többjátékos PvP mérkőzést."
"NEW_ACHIEVEMENT_20_8_NAME" "Villám"
- "NEW_ACHIEVEMENT_20_8_DESC" "Semmisítsd meg az ellenséges magot egy támadási zónában 5, vagy annál kevesebb hullámban."
- "NEW_ACHIEVEMENT_20_9_NAME" "Mag Eső"
- "NEW_ACHIEVEMENT_20_9_DESC" "Indítsd el a magot 30-szor."
+ "NEW_ACHIEVEMENT_20_8_DESC" "Semmisítsd meg egy ellenséges támaszpontot egy támadási zónában 5, vagy annál kevesebb hullámban."
+ "NEW_ACHIEVEMENT_20_9_NAME" "Támaszpont eső"
+ "NEW_ACHIEVEMENT_20_9_DESC" "Indítsd el a támaszpontot 30-szor."
"NEW_ACHIEVEMENT_20_10_NAME" "Kitartó"
"NEW_ACHIEVEMENT_20_10_DESC" "Élj túl 100 hullámot."
- "NEW_ACHIEVEMENT_20_12_NAME" "Kutató"
- "NEW_ACHIEVEMENT_20_12_DESC" "Kutass fel mindent."
+ "NEW_ACHIEVEMENT_20_12_NAME" "Fejlesztő"
+ "NEW_ACHIEVEMENT_20_12_DESC" "Fejlessz ki mindent."
"NEW_ACHIEVEMENT_20_14_NAME" "Túlterhelés"
"NEW_ACHIEVEMENT_20_14_DESC" "Üss meg egy vízzel borított ellenséget árammal."
"NEW_ACHIEVEMENT_20_15_NAME" "Eltérítés"
"NEW_ACHIEVEMENT_20_15_DESC" "Pusztíts el egy egységet a saját visszavert lövedékével."
- "NEW_ACHIEVEMENT_20_17_NAME" "Egy Végzetes Hiba"
+ "NEW_ACHIEVEMENT_20_17_NAME" "Egy végzetes hiba"
"NEW_ACHIEVEMENT_20_17_DESC" "Az elosztó kifejlesztése."
"NEW_ACHIEVEMENT_20_18_NAME" "Készítő"
- "NEW_ACHIEVEMENT_20_18_DESC" "Helyezz el 10,000 blokkot."
+ "NEW_ACHIEVEMENT_20_18_DESC" "Helyezz el 10 000 blokkot."
"NEW_ACHIEVEMENT_20_19_NAME" "Zúzás"
- "NEW_ACHIEVEMENT_20_19_DESC" "Pusztíts el 1,000 ellenséges blokkot."
- "NEW_ACHIEVEMENT_20_20_NAME" "Egy Látványos Katasztrófa"
+ "NEW_ACHIEVEMENT_20_19_DESC" "Pusztíts el 1 000 ellenséges blokkot."
+ "NEW_ACHIEVEMENT_20_20_NAME" "Egy látványos katasztrófa"
"NEW_ACHIEVEMENT_20_20_DESC" "Egy tóriumreaktor túlmelegedése és felrobbanása."
"NEW_ACHIEVEMENT_20_21_NAME" "Térképész"
"NEW_ACHIEVEMENT_20_21_DESC" "Készíts 10 új pályát."
"NEW_ACHIEVEMENT_20_22_NAME" "Böngésző"
- "NEW_ACHIEVEMENT_20_22_DESC" "Töltse le egy pályát a Workshop-ból."
+ "NEW_ACHIEVEMENT_20_22_DESC" "Töltse le egy pályát a Steam Műhelyből."
"NEW_ACHIEVEMENT_20_23_NAME" "Alkotó"
- "NEW_ACHIEVEMENT_20_23_DESC" "Tegyél közzé egy pályát a Workshop-ban."
+ "NEW_ACHIEVEMENT_20_23_DESC" "Tegyél közzé egy pályát a Steam Műhelyben."
"NEW_ACHIEVEMENT_20_24_NAME" "Gyilkoló"
- "NEW_ACHIEVEMENT_20_24_DESC" "Győzz le egy Őrzőt."
- "NEW_ACHIEVEMENT_20_29_NAME" "Anyag II"
- "NEW_ACHIEVEMENT_20_29_DESC" "Oldd fel a Tóriumot."
- "NEW_ACHIEVEMENT_20_31_NAME" "Anyag I"
- "NEW_ACHIEVEMENT_20_31_DESC" "Oldd fel a Titániumot."
+ "NEW_ACHIEVEMENT_20_24_DESC" "Győzz le egy őrzőt."
+ "NEW_ACHIEVEMENT_20_29_NAME" "Nyersanyag II"
+ "NEW_ACHIEVEMENT_20_29_DESC" "Oldd fel a tóriumot."
+ "NEW_ACHIEVEMENT_20_31_NAME" "Nyersanyag I"
+ "NEW_ACHIEVEMENT_20_31_DESC" "Oldd fel a titániumot."
"NEW_ACHIEVEMENT_21_0_NAME" "Kamikaze"
- "NEW_ACHIEVEMENT_21_0_DESC" "Töltsd fel bármely nem-mag egységet robbanóanyaggal és halj meg."
- "NEW_ACHIEVEMENT_21_1_NAME" "Ez Kezdődik"
- "NEW_ACHIEVEMENT_21_1_DESC" "Építs egy földi-egység gyárat."
+ "NEW_ACHIEVEMENT_21_0_DESC" "Tölts fel egy bármely nem-támaszpont egységet robbanóanyaggal és halj meg."
+ "NEW_ACHIEVEMENT_21_1_NAME" "Elkezdődik"
+ "NEW_ACHIEVEMENT_21_1_DESC" "Építs egy földiegységgyárat."
"NEW_ACHIEVEMENT_21_2_NAME" "Közvetlen támadás"
"NEW_ACHIEVEMENT_21_2_DESC" "Parancsold meg bármelyik egységnek, hogy támadjon meg egy célpontot."
"NEW_ACHIEVEMENT_21_3_NAME" "Raj"
@@ -58,123 +58,123 @@
"NEW_ACHIEVEMENT_21_5_NAME" "Robottechnikus"
"NEW_ACHIEVEMENT_21_5_DESC" "Állítsd elő az egységek minden típusát."
"NEW_ACHIEVEMENT_21_6_NAME" "Légiók"
- "NEW_ACHIEVEMENT_21_6_DESC" "Állíts elő 1,000 egységet."
- "NEW_ACHIEVEMENT_21_9_NAME" "Figyelned Kellett Volna"
+ "NEW_ACHIEVEMENT_21_6_DESC" "Állíts elő 1 000 egységet."
+ "NEW_ACHIEVEMENT_21_9_NAME" "Figyelned kellett volna"
"NEW_ACHIEVEMENT_21_9_DESC" "Halj meg a ledobási pont kizárási zónájában."
- "NEW_ACHIEVEMENT_21_10_NAME" "Ezért Vannak a Haditengerészeti Egységek"
+ "NEW_ACHIEVEMENT_21_10_NAME" "Ezért vannak a haditengerészeti egységek"
"NEW_ACHIEVEMENT_21_10_DESC" "Megfulladt."
"NEW_ACHIEVEMENT_21_11_NAME" "Gyűjtő"
- "NEW_ACHIEVEMENT_21_11_DESC" "Töltsd meg a magot a maximális kapacitásig mindenféle nyersanyaggal."
+ "NEW_ACHIEVEMENT_21_11_DESC" "Töltsd meg a támaszpontot a maximális kapacitásig mindenféle nyersanyaggal."
"NEW_ACHIEVEMENT_21_12_NAME" "Tömeg"
- "NEW_ACHIEVEMENT_21_12_DESC" "Hosztolj egy szervert 10 játékossal."
+ "NEW_ACHIEVEMENT_21_12_DESC" "Indíts egy kiszolgálót 10 játékossal."
"NEW_ACHIEVEMENT_21_13_NAME" "Sebezhetetlen"
"NEW_ACHIEVEMENT_21_13_DESC" "Építs Meltdown, Spectre és Foreshadow lövegtornyokat."
"NEW_ACHIEVEMENT_21_14_NAME" "Felszállás"
- "NEW_ACHIEVEMENT_21_14_DESC" "Használd a Kilövő Állást."
+ "NEW_ACHIEVEMENT_21_14_DESC" "Használd a kilövőállást."
"NEW_ACHIEVEMENT_21_16_NAME" "Eretnekség"
- "NEW_ACHIEVEMENT_21_16_DESC" "Építs két Elosztót egymás mellé."
- "NEW_ACHIEVEMENT_21_17_NAME" "Magányos Védelmező"
- "NEW_ACHIEVEMENT_21_17_DESC" "Élj túl 10 hullámot bármelyik zónában blokkok elhelyezése nélkül."
+ "NEW_ACHIEVEMENT_21_16_DESC" "Építs két elosztót egymás mellé."
+ "NEW_ACHIEVEMENT_21_17_NAME" "Magányos védelmező"
+ "NEW_ACHIEVEMENT_21_17_DESC" "Élj túl 10 hullámot bármelyik zónában, blokkok elhelyezése nélkül."
"NEW_ACHIEVEMENT_21_18_NAME" "Hamvasztás"
- "NEW_ACHIEVEMENT_21_18_DESC" "Használd a Piratitot bármelyik lövegtoronyban."
+ "NEW_ACHIEVEMENT_21_18_DESC" "Használd a piratitot bármelyik lövegtoronyban."
"NEW_ACHIEVEMENT_21_19_NAME" "Hatásfok"
"NEW_ACHIEVEMENT_21_19_DESC" "Hűts le egy lövegtornyot vízzel, vagy hűtőfolyadékkal."
- "NEW_ACHIEVEMENT_21_20_NAME" "Klasszikus Mód"
+ "NEW_ACHIEVEMENT_21_20_NAME" "Klasszikus mód"
"NEW_ACHIEVEMENT_21_20_DESC" "Kapcsold be a pixeles módot."
"NEW_ACHIEVEMENT_21_21_NAME" "Tudós"
"NEW_ACHIEVEMENT_21_21_DESC" "Nyisd meg a Wiki-t a játékból."
- "NEW_ACHIEVEMENT_21_22_NAME" "Erős Kezdés"
- "NEW_ACHIEVEMENT_21_22_DESC" "Indítsd el a magot bármely zónába 10,000, vagy több nyersanyaggal konfigurálva."
+ "NEW_ACHIEVEMENT_21_22_NAME" "Erős kezdés"
+ "NEW_ACHIEVEMENT_21_22_DESC" "Indítsd el a támaszpontot bármely zónába 10 000, vagy több nyersanyaggal konfigurálva."
"NEW_ACHIEVEMENT_21_23_NAME" "Begyújtás"
- "NEW_ACHIEVEMENT_21_23_DESC" "Indíts be egy Ütközéses Reaktort."
+ "NEW_ACHIEVEMENT_21_23_DESC" "Indíts be egy ütközéses erőművet."
"NEW_ACHIEVEMENT_21_25_NAME" "A spirál"
- "NEW_ACHIEVEMENT_21_25_DESC" "Járkálj körbe-körbe..."
+ "NEW_ACHIEVEMENT_21_25_DESC" "Csak körbe-körbe szállít..."
"NEW_ACHIEVEMENT_21_26_NAME" "Fokozás"
"NEW_ACHIEVEMENT_21_26_DESC" "Építs egy 5-ös szintű egységet."
"NEW_ACHIEVEMENT_21_27_NAME" "Építész"
"NEW_ACHIEVEMENT_21_27_DESC" "Készíts 20 vázlatot."
- "NEW_ACHIEVEMENT_21_28_NAME" "Globális Dominancia"
+ "NEW_ACHIEVEMENT_21_28_NAME" "Globális dominancia"
"NEW_ACHIEVEMENT_21_28_DESC" "Foglald el a Serpulo minden szektorát."
"NEW_ACHIEVEMENT_21_29_NAME" "Légiszállítás"
"NEW_ACHIEVEMENT_21_29_DESC" "Vegyél fel egy 5-ös szintű egységet egy Oct egységszállítóba."
- "NEW_ACHIEVEMENT_21_30_NAME" "A Tökéletes Forma"
+ "NEW_ACHIEVEMENT_21_30_NAME" "A tökéletes forma"
"NEW_ACHIEVEMENT_21_30_DESC" "Csatlakozz hozzájuk."
"NEW_ACHIEVEMENT_21_31_NAME" "Termelés I"
- "NEW_ACHIEVEMENT_21_31_DESC" "Érj el 5,000 nyersanyag/perc össztermelést a kampányban."
+ "NEW_ACHIEVEMENT_21_31_DESC" "Érj el 5 000 nyersanyag/perc össztermelést a hadjáratban."
"NEW_ACHIEVEMENT_26_0_NAME" "Termelés II"
- "NEW_ACHIEVEMENT_26_0_DESC" "Érj el 50,000 nyersanyag/perc össztermelést a kampányban."
- "NEW_ACHIEVEMENT_26_1_NAME" "Biztos Győzelem"
+ "NEW_ACHIEVEMENT_26_0_DESC" "Érj el 50 000 nyersanyag/perc össztermelést a hadjáratban."
+ "NEW_ACHIEVEMENT_26_1_NAME" "Biztos győzelem"
"NEW_ACHIEVEMENT_26_1_DESC" "Foglalj el egy szektort, miközben egy másik szektorban játszol."
- "NEW_ACHIEVEMENT_26_2_NAME" "Kis Birodalom"
+ "NEW_ACHIEVEMENT_26_2_NAME" "Kis birodalom"
"NEW_ACHIEVEMENT_26_2_DESC" "Legyen az ellenőrzésed alatt egyszerre 10 szektor."
"NEW_ACHIEVEMENT_26_3_NAME" "Tervező"
"NEW_ACHIEVEMENT_26_3_DESC" "Készíts 500 vázlatot."
- "NEW_ACHIEVEMENT_26_4_NAME" "Mester a Terjesztésben"
+ "NEW_ACHIEVEMENT_26_4_NAME" "Terjesztőmester"
"NEW_ACHIEVEMENT_26_4_DESC" "Használj minden nyersanyagszállító blokkot (egy bolygón) egyetlen pályán."
"NEW_ACHIEVEMENT_26_5_NAME" "Túlhajtás"
- "NEW_ACHIEVEMENT_26_5_DESC" "Építs egy Túlhajtó Projektort."
+ "NEW_ACHIEVEMENT_26_5_DESC" "Építs egy túlhajtó kivetítőt."
"NEW_ACHIEVEMENT_26_6_NAME" "Foltozás"
- "NEW_ACHIEVEMENT_26_6_DESC" "Építs egy Foltozó Projektort."
+ "NEW_ACHIEVEMENT_26_6_DESC" "Építs egy foltozó kivetítőt."
"NEW_ACHIEVEMENT_26_7_NAME" "Hatástalanság"
- "NEW_ACHIEVEMENT_26_7_DESC" "Építs Vízkiválasztót a vízre, ahelyett, hogy szivattyút használnál."
+ "NEW_ACHIEVEMENT_26_7_DESC" "Építs kútfúró tornyot a vízre, ahelyett, hogy szivattyút használnál."
"NEW_ACHIEVEMENT_26_8_NAME" "Raktárkészlet"
- "NEW_ACHIEVEMENT_26_8_DESC" "Gyűjts össze összesen 10 millió nyersanyagot a kampányban."
- "NEW_ACHIEVEMENT_26_9_NAME" "Minden Esély Ellenére"
+ "NEW_ACHIEVEMENT_26_8_DESC" "Gyűjts össze összesen 10 millió nyersanyagot a hadjáratban."
+ "NEW_ACHIEVEMENT_26_9_NAME" "Minden esély ellenére"
"NEW_ACHIEVEMENT_26_9_DESC" "Mérj gyilkos csapást egy Eclipse egységre egy Duo toronnyal."
- "NEW_ACHIEVEMENT_26_10_NAME" "Erekir Befejezése"
+ "NEW_ACHIEVEMENT_26_10_NAME" "Erekir befejezése"
"NEW_ACHIEVEMENT_26_10_DESC" "Foglald el az Erekir utolsó szektorát."
"NEW_ACHIEVEMENT_26_11_NAME" "Serpulo Befejezése"
"NEW_ACHIEVEMENT_26_11_DESC" "Foglald el a Serpulo utolsó szektorát."
"NEW_ACHIEVEMENT_26_12_NAME" "Rakomány"
- "NEW_ACHIEVEMENT_26_12_DESC" "Indítsd el a magot a Serpulo egyik szektorába egy saját egyéni mag-vázlatot használva."
- "NEW_ACHIEVEMENT_26_13_NAME" "Túlságosan Felkészült"
- "NEW_ACHIEVEMENT_26_13_DESC" "Fejleszd a Becsapódási Pont szektorban lévő magot Magnum-ra."
+ "NEW_ACHIEVEMENT_26_12_DESC" "Indítsd el a támaszpontot a Serpulo egyik szektorába egy saját egyéni támaszpontvázlatot használva."
+ "NEW_ACHIEVEMENT_26_13_NAME" "Túlságosan felkészült"
+ "NEW_ACHIEVEMENT_26_13_DESC" "Fejleszd a Becsapódási Pont szektorban lévő támaszpontot Magnumra."
"NEW_ACHIEVEMENT_26_14_NAME" "Kitörés"
- "NEW_ACHIEVEMENT_26_14_DESC" "A Neoplazma terjedjen át bármely víztartalmú blokkra."
+ "NEW_ACHIEVEMENT_26_14_DESC" "A neoplazma terjedjen át bármely víztartalmú blokkra."
"NEW_ACHIEVEMENT_26_15_NAME" "Törékeny"
- "NEW_ACHIEVEMENT_26_15_DESC" "Adj extra robbanás-sebzést a Fagyasztó állapothatással rendelkező egységnek."
- "NEW_ACHIEVEMENT_26_16_NAME" "Serpulo Struktúra Mester"
+ "NEW_ACHIEVEMENT_26_15_DESC" "Adj extra robbanássebzést egy fagyasztó állapothatással rendelkező egységnek."
+ "NEW_ACHIEVEMENT_26_16_NAME" "Serpulo struktúramester"
"NEW_ACHIEVEMENT_26_16_DESC" "Építsd meg a Serpulo összes elérhető blokkját."
- "NEW_ACHIEVEMENT_26_17_NAME" "Erekir Struktúra Mester"
+ "NEW_ACHIEVEMENT_26_17_NAME" "Erekir struktúramester"
"NEW_ACHIEVEMENT_26_17_DESC" "Építsd meg az Erekir összes elérhető blokkját."
- "NEW_ACHIEVEMENT_26_18_NAME" "Pajzsok Le"
- "NEW_ACHIEVEMENT_26_18_DESC" "Törd össze egy ellenséges Erő Projektor pajzsát."
- "NEW_ACHIEVEMENT_26_19_NAME" "Hol Van A Kézikönyv?"
- "NEW_ACHIEVEMENT_26_19_DESC" "Fejleszd ki a Mikroprocesszort."
+ "NEW_ACHIEVEMENT_26_18_NAME" "Pajzsok le"
+ "NEW_ACHIEVEMENT_26_18_DESC" "Törd össze egy ellenséges erőpajzs-kivetítő pajzsát."
+ "NEW_ACHIEVEMENT_26_19_NAME" "Hol van a kézikönyv?"
+ "NEW_ACHIEVEMENT_26_19_DESC" "Fejleszd ki a mikroprocesszort."
"NEW_ACHIEVEMENT_26_20_NAME" "Árnyékolás"
- "NEW_ACHIEVEMENT_26_20_DESC" "Negatív 10k/sec teljesítmény elérése egy hálózatban."
- "NEW_ACHIEVEMENT_26_21_NAME" "Teljesítmény Túltengés"
- "NEW_ACHIEVEMENT_26_21_DESC" "Pozitív 100k/sec teljesítmény elérése egy hálózatban."
- "NEW_ACHIEVEMENT_26_22_NAME" "Magas Kapacitás"
+ "NEW_ACHIEVEMENT_26_20_DESC" "Negatív 10k/mp teljesítmény elérése egy hálózatban."
+ "NEW_ACHIEVEMENT_26_21_NAME" "Teljesítmény túltengés"
+ "NEW_ACHIEVEMENT_26_21_DESC" "Pozitív 100k/mp teljesítmény elérése egy hálózatban."
+ "NEW_ACHIEVEMENT_26_22_NAME" "Magas kapacitás"
"NEW_ACHIEVEMENT_26_22_DESC" "Legyen 1 millió tárolt energia az akkumulátorokban egy hálózatban."
- "NEW_ACHIEVEMENT_26_23_NAME" "Rossz Ötlet"
- "NEW_ACHIEVEMENT_26_23_DESC" "Helyezz robbanóanyagot egy Belső-égetésű Erőműbe."
+ "NEW_ACHIEVEMENT_26_23_NAME" "Rossz ötlet"
+ "NEW_ACHIEVEMENT_26_23_DESC" "Helyezz robbanóanyagot egy égetőerőműbe."
"NEW_ACHIEVEMENT_26_24_NAME" "Szennyezés"
- "NEW_ACHIEVEMENT_26_24_DESC" "Robbanjon fel egy Neoplázia Reaktor a Neoplazma felhalmozódása miatt."
+ "NEW_ACHIEVEMENT_26_24_DESC" "Robbanjon fel egy neopláziareaktor a neoplazma felhalmozódása miatt."
"NEW_ACHIEVEMENT_26_25_NAME" "Módosított"
"NEW_ACHIEVEMENT_26_25_DESC" "Telepíts egy modot."
"NEW_ACHIEVEMENT_26_26_NAME" "Elosztó"
"NEW_ACHIEVEMENT_26_26_DESC" "Elosztó."
- "NEW_ACHIEVEMENT_26_27_NAME" "A Teljes Élmény"
+ "NEW_ACHIEVEMENT_26_27_NAME" "A teljes élmény"
"NEW_ACHIEVEMENT_26_27_DESC" "Csatlakozz egy közösségi szerverhez."
"NEW_ACHIEVEMENT_26_28_NAME" "Hackerman"
"NEW_ACHIEVEMENT_26_28_DESC" "Nyisd meg a szkript-konzolt."
- "NEW_ACHIEVEMENT_26_29_NAME" "Közvetlen Irányítás"
+ "NEW_ACHIEVEMENT_26_29_NAME" "Közvetlen irányítás"
"NEW_ACHIEVEMENT_26_29_DESC" "Irányíts te magad kézzel egy lövegtornyot."
- "NEW_ACHIEVEMENT_26_30_NAME" "Ellenséges Vonalak Mögött"
- "NEW_ACHIEVEMENT_26_30_DESC" "Dobj le egységeket egy ellenséges mag építési tilalmi zónájába."
+ "NEW_ACHIEVEMENT_26_30_NAME" "Ellenséges vonalak mögött"
+ "NEW_ACHIEVEMENT_26_30_DESC" "Dobj le egységeket egy ellenséges támaszpont építési tilalmi zónájába."
"NEW_ACHIEVEMENT_26_31_NAME" "Bosszú"
"NEW_ACHIEVEMENT_26_31_DESC" "Pusztíts el egy Scatter lövegtornyot egy Flare egységgel."
"NEW_ACHIEVEMENT_29_0_NAME" "Légierő"
"NEW_ACHIEVEMENT_29_0_DESC" "Használd egy földi egység erősítés funkcióját."
"NEW_ACHIEVEMENT_29_1_NAME" "Légpárnás"
"NEW_ACHIEVEMENT_29_1_DESC" "Használj egy Elude egységet a folyadékon való átkeléshez."
- "NEW_ACHIEVEMENT_29_2_NAME" "Terep Erősítés"
- "NEW_ACHIEVEMENT_29_2_DESC" "Növeld egy blokk hatékonyságát azáltal, hogy meghatározott terepre helyezed."
+ "NEW_ACHIEVEMENT_29_2_NAME" "Terep erősítés"
+ "NEW_ACHIEVEMENT_29_2_DESC" "Növeld egy blokk hatékonyságát azáltal, hogy egy meghatározott terepre helyezed."
"NEW_ACHIEVEMENT_29_3_NAME" "Takarítás"
"NEW_ACHIEVEMENT_29_3_DESC" "Törj össze 100 sziklát."
- "NEW_ACHIEVEMENT_29_4_NAME" "Globális Takarítás"
- "NEW_ACHIEVEMENT_29_4_DESC" "Törj össze 10,000 sziklát."
+ "NEW_ACHIEVEMENT_29_4_NAME" "Globális takarítás"
+ "NEW_ACHIEVEMENT_29_4_DESC" "Törj össze 10 000 sziklát."
"NEW_ACHIEVEMENT_29_5_NAME" "Semlegesítve"
"NEW_ACHIEVEMENT_29_5_DESC" "Használj egy Shockwave lövegtornyot, hogy semlegesítsd a beérkező lövedékeket."
"NEW_ACHIEVEMENT_29_6_NAME" "Sajnos"
diff --git a/fastlane/metadata/steam/hungarian/description.txt b/fastlane/metadata/steam/hungarian/description.txt
index 0931b27198..6d77a69dc1 100644
--- a/fastlane/metadata/steam/hungarian/description.txt
+++ b/fastlane/metadata/steam/hungarian/description.txt
@@ -1,6 +1,6 @@
-A Mindustry egy gyárépítő játék Toronyvédő és RTS elemekkel. Készíts bonyolult ellátási láncokat, hogy lőszert juttass a lövegtornyokba, termelj az építkezéshez használható nyersanyagokat, és állíts elő egységeket. Irányítsd az egységeket, hogy elfoglald az ellenséges bázisokat, és bővítsd a termelésedet. Védd meg a magodat a hullámokban támadó ellenségtől.
+A Mindustry egy gyárépítő játék Toronyvédő és RTS elemekkel. Készíts bonyolult ellátási láncokat, hogy lőszert juttass a lövegtornyokba, termelj az építkezéshez használható nyersanyagokat, és állíts elő egységeket. Irányítsd az egységeket, hogy elfoglald az ellenséges bázisokat, és bővítsd a termelésedet. Védd meg a támaszpontodat a hullámokban támadó ellenségektől.
-Játszd végig a hadjáratokat egyedül, vagy vállvetve a barátaiddal a platformokon átívelő többjátékos módban, vagy hívd ki őket csapat alapú PvP meccsekre
+Játszd végig a hadjáratokat egyedül, vagy vállvetve a barátaiddal a platformokon átívelő többjátékos módban, vagy hívd ki őket csapat alapú PvP mérkőzésekre
[img]{STEAM_APP_IMAGE}/extras/factory.gif[/img]
@@ -10,17 +10,17 @@ Játszd végig a hadjáratokat egyedül, vagy vállvetve a barátaiddal a platfo
[*] Hozz létre bonyolult szállítószalagokból álló ellátási láncokat, hogy lőszert juttass a lövegtornyokba és termelj nyersanyagokat az építkezésekhez
[*] Használd a gyártó-blokkokat a legkülönfélébb fejlett nyersanyagok létrehozásához
[*] Oszd szét a folyadékokat, és küzdj meg az állandó kihívásokkal, mint például a tűzkitörések, vagy az ellenséges repülőgépek rajtaütéseivel
-[*] Hozd ki a legtöbbet a termelésből az opcionális hűtő- és kenőanyag-ellátással
-[*] Egységek széles skáláját állíthatod elő a bázisod automatikus irányításához és az ellenséges bázisok megtámadásához
+[*] Hozd ki a legtöbbet a termelésből az opcionális hűtőfolyadék-ellátással
+[*] Egységek széles skáláját állíthatod elő a bázisod automatikus irányításához, és az ellenséges bázisok megtámadásához
[/list]
[h2]Toronyvédés[/h2]
[list]
[*] Védd meg építményeidet a hullámokban támadó ellenségektől
-[*] Stratégiailag helyezd el a tornyokat, hogy elpusztítsd a támadóidat, mielőtt elérnék a magodat
+[*] Stratégiailag helyezd el a lövegtornyokat, hogy elpusztítsd a támadóidat, mielőtt elérnék a támaszpontodat
[*] Lásd el a lövegtornyokat lőszerrel, hűtőfolyadékkal és energiával
-[*] Erősítsd meg a védelmed energiával működő pajzsokkal, regenerációs projektorokkal és egyéb támogató épületekkel
+[*] Erősítsd meg a védelmedet erőpajzs- és foltozó-kivetítőkkel és egyéb támogató épületekkel
[/list]
[img]{STEAM_APP_IMAGE}/extras/rts3.png[/img]
@@ -30,14 +30,14 @@ Játszd végig a hadjáratokat egyedül, vagy vállvetve a barátaiddal a platfo
[list]
[*] Állíts fel összeszerelősorokat a gépesített egységek hadainak előállításához
[*] Használd az egységeidet a hatékonyan felszerelt ellenséges bázisok ellen
-[*] Foglalj el minél több területet, hogy még több magot helyezhess el, és további erőforrásokhoz férhess hozzá a terjeszkedéshez
+[*] Foglalj el minél több területet, hogy még több támaszpontot helyezhess el, és további erőforrásokhoz férhess hozzá a terjeszkedéshez
[/list]
[h2]Hadjárat[/h2]
[list]
[*] Játssz végig a két különböző bolygó hadjáratait
-[*] Hódítsd meg a Serpulo és az Erekir bolygót, miközben 35 kézzel készített pályán és 250+ procedurálisan generált szektoron keresztül haladsz
+[*] Hódítsd meg a Serpulo és az Erekir bolygót, miközben 35 kézzel készített pályán és 250+ procedurálisan előállított szektoron keresztül haladsz
[*] Foglalj el területeket és építs gyárakat, hogy nyersanyagokat termelhess, miközben más szektorokban játszol
[*] Védd meg a szektorokat az időszakos invázióktól
[*] Koordináld az erőforrások elosztását a szektorok között az indítóállások felhasználásával
@@ -51,12 +51,12 @@ Játszd végig a hadjáratokat egyedül, vagy vállvetve a barátaiddal a platfo
[h2]Közösség és moddolás[/h2]
[list]
-[*] Használd a Steam Workshop-ot a közösség által készített pályák és vázlatok böngészéséhez.
-[*] Csatlakozz nyilvános közösségi szerverekhez, hogy másokkal játszhass platformokon keresztül
-[*] Játssz kooperatív, PvP-ben, vagy homokozóban
-[*] A közösségi szerverek támogatják az egyéni pályák és játékmódok bővítményeit
-[*] Hozz létre nyilvános dedikált szervert, vagy hívd meg a barátaidat a saját privát munkamenetedre
-[*] Testre szabható játékszabályok: Változtasd meg az épületek építési költségeit, az ellenséges statisztikákat, a kezdő elemeket, a hullámok időzítését és így tovább
+[*] Használd a Steam Műhelyt a közösség által készített pályák és vázlatok böngészéséhez.
+[*] Csatlakozz nyilvános és közösségi kiszolgálókhoz, hogy másokkal játszhass platformokon keresztül
+[*] Játssz vállvetve, PvP-ben, vagy homokozóban a barátaiddal
+[*] A közösségi kiszolgálók támogatják az egyéni pályák és játékmódok bővítményeit
+[*] Hozz létre nyilvános dedikált kiszolgálót, vagy hívd meg a barátaidat a saját privát munkamenetedre
+[*] Testre szabható játékszabályok: Változtasd meg az épületek építési költségeit, az ellenséges statisztikákat, a kezdő elemeket, a hullámok időzítését, vagy bármi mást
[*] A beépített pályaszerkesztővel saját pályákat készíthetsz, hogy játszhass másokkal és megoszthasd a közösséggel
[*] Böngéssz a közösség által készített modok között, hogy még több tartalmat adhass hozzá a játékodhoz, vagy keverj belőlük egy újat
[/list]
diff --git a/fastlane/metadata/steam/korean/achievements.vdf b/fastlane/metadata/steam/korean/achievements.vdf
new file mode 100644
index 0000000000..ef184e7f83
--- /dev/null
+++ b/fastlane/metadata/steam/korean/achievements.vdf
@@ -0,0 +1,183 @@
+"lang"
+{
+ "Language" "korean"
+ "Tokens"
+ {
+ "NEW_ACHIEVEMENT_20_1_NAME" "분쇄자"
+ "NEW_ACHIEVEMENT_20_1_DESC" "적 유닛을 1000기 사살하세요."
+ "NEW_ACHIEVEMENT_20_2_NAME" "숙청"
+ "NEW_ACHIEVEMENT_20_2_DESC" "적 유닛을 100,000기 사살하세요."
+ "NEW_ACHIEVEMENT_20_5_NAME" "무한의 배달부"
+ "NEW_ACHIEVEMENT_20_5_DESC" "자원을 총 100,000개 출격시키세요."
+ "NEW_ACHIEVEMENT_20_6_NAME" "정복자"
+ "NEW_ACHIEVEMENT_20_6_DESC" "공격 모드에서 10번 승리하세요."
+ "NEW_ACHIEVEMENT_20_7_NAME" "챔피언"
+ "NEW_ACHIEVEMENT_20_7_DESC" "멀티플레이어 PvP 매치에서 10번 승리하세요."
+ "NEW_ACHIEVEMENT_20_8_NAME" "진격!"
+ "NEW_ACHIEVEMENT_20_8_DESC" "공격 모드인 지역에서 5 단계 이하일 때 적의 코어를 파괴하세요."
+ "NEW_ACHIEVEMENT_20_9_NAME" "하늘에서 코어의 비가 쏟아진다!"
+ "NEW_ACHIEVEMENT_20_9_DESC" "캠페인 지역에 30번 도전하세요."
+ "NEW_ACHIEVEMENT_20_10_NAME" "끈질긴"
+ "NEW_ACHIEVEMENT_20_10_DESC" "100 단계를 생존하세요."
+ "NEW_ACHIEVEMENT_20_12_NAME" "연구원"
+ "NEW_ACHIEVEMENT_20_12_DESC" "모든 것을 연구하세요."
+ "NEW_ACHIEVEMENT_20_14_NAME" "과충전"
+ "NEW_ACHIEVEMENT_20_14_DESC" "물에 젖은 적을 전기로 지져버리세요."
+ "NEW_ACHIEVEMENT_20_15_NAME" "무지개 반사"
+ "NEW_ACHIEVEMENT_20_15_DESC" "적의 탄환을 반사해서 적을 사살하세요."
+ "NEW_ACHIEVEMENT_20_17_NAME" "한 중대한 실수"
+ "NEW_ACHIEVEMENT_20_17_DESC" "분배기를 연구하세요."
+ "NEW_ACHIEVEMENT_20_18_NAME" "창조"
+ "NEW_ACHIEVEMENT_20_18_DESC" "블록 10,000개를 설치하세요."
+ "NEW_ACHIEVEMENT_20_19_NAME" "잿더미"
+ "NEW_ACHIEVEMENT_20_19_DESC" "적 블록을 1,000개 파괴하세요."
+ "NEW_ACHIEVEMENT_20_20_NAME" "폭발은 예술이다!"
+ "NEW_ACHIEVEMENT_20_20_DESC" "토륨 원자로를 폭발시키세요."
+ "NEW_ACHIEVEMENT_20_21_NAME" "맵 제작자"
+ "NEW_ACHIEVEMENT_20_21_DESC" "새로운 맵을 10개 만드세요."
+ "NEW_ACHIEVEMENT_20_22_NAME" "브라우저"
+ "NEW_ACHIEVEMENT_20_22_DESC" "창작마당에서 맵을 1개 내려받으세요."
+ "NEW_ACHIEVEMENT_20_23_NAME" "크리에이터"
+ "NEW_ACHIEVEMENT_20_23_DESC" "창작마당에 맵을 1개 올리세요."
+ "NEW_ACHIEVEMENT_20_24_NAME" "슬레이어"
+ "NEW_ACHIEVEMENT_20_24_DESC" "보스를 처치하세요."
+ "NEW_ACHIEVEMENT_20_29_NAME" "자원 연구 II"
+ "NEW_ACHIEVEMENT_20_29_DESC" "토륨을 해금하세요."
+ "NEW_ACHIEVEMENT_20_31_NAME" "자원 연구 I"
+ "NEW_ACHIEVEMENT_20_31_DESC" "티타늄을 해금하세요."
+ "NEW_ACHIEVEMENT_21_0_NAME" "공포의 자폭 분대"
+ "NEW_ACHIEVEMENT_21_0_DESC" "당신의 유닛을 폭발성이 있는 자원으로 채우고 사망하여 폭발을 일으키세요."
+ "NEW_ACHIEVEMENT_21_1_NAME" "이제 시작이야"
+ "NEW_ACHIEVEMENT_21_1_DESC" "지상 유닛 공장을 건설하세요."
+ "NEW_ACHIEVEMENT_21_2_NAME" "직접 돌격"
+ "NEW_ACHIEVEMENT_21_2_DESC" "유닛에게 목표물을 공격하도록 명령하세요."
+ "NEW_ACHIEVEMENT_21_3_NAME" "물량"
+ "NEW_ACHIEVEMENT_21_3_DESC" "한 게임에서 활성화된 100기의 유닛을 가지세요."
+ "NEW_ACHIEVEMENT_21_4_NAME" "추종자들"
+ "NEW_ACHIEVEMENT_21_4_DESC" "한 게임에서 활성화된 10기의 폴리를 가지세요."
+ "NEW_ACHIEVEMENT_21_5_NAME" "로봇 공학자"
+ "NEW_ACHIEVEMENT_21_5_DESC" "모든 종류의 유닛을 만드세요."
+ "NEW_ACHIEVEMENT_21_6_NAME" "군단"
+ "NEW_ACHIEVEMENT_21_6_DESC" "유닛을 총 1,000기 생산하세요."
+ "NEW_ACHIEVEMENT_21_9_NAME" "당신은 사시입니다"
+ "NEW_ACHIEVEMENT_21_9_DESC" "적 착륙 지점에서 사망하세요."
+ "NEW_ACHIEVEMENT_21_10_NAME" "이 게임에는 해상 유닛이 있어요"
+ "NEW_ACHIEVEMENT_21_10_DESC" "익사하세요, 어떻게든."
+ "NEW_ACHIEVEMENT_21_11_NAME" "수집가"
+ "NEW_ACHIEVEMENT_21_11_DESC" "캠페인 지역에서 코어에 넣을 수 있는 모든 자원을 최대치로 넣으세요."
+ "NEW_ACHIEVEMENT_21_12_NAME" "왕관"
+ "NEW_ACHIEVEMENT_21_12_DESC" "서버를 열고 10명 이상의 플에이어를 유지하세요."
+ "NEW_ACHIEVEMENT_21_13_NAME" "진입 불가"
+ "NEW_ACHIEVEMENT_21_13_DESC" "멜트다운과 스펙터, 그리고 포어쉐도우를 건설하세요."
+ "NEW_ACHIEVEMENT_21_14_NAME" "출격!"
+ "NEW_ACHIEVEMENT_21_14_DESC" "지역 자원 수송기를 사용하세요."
+ "NEW_ACHIEVEMENT_21_16_NAME" "이단"
+ "NEW_ACHIEVEMENT_21_16_DESC" "분배기를 2개 붙여서 건설하세요."
+ "NEW_ACHIEVEMENT_21_17_NAME" "고독한 수호자"
+ "NEW_ACHIEVEMENT_21_17_DESC" "캠페인 지역에서 10 단계 이상을 아무 블록도 설치하지 않고 생존하세요."
+ "NEW_ACHIEVEMENT_21_18_NAME" "인화성"
+ "NEW_ACHIEVEMENT_21_18_DESC" "아무 포탑에 파이라타이트를 사용하세요."
+ "NEW_ACHIEVEMENT_21_19_NAME" "효율성"
+ "NEW_ACHIEVEMENT_21_19_DESC" "포탑을 물 혹은 냉각수를 사용하여 냉각하세요."
+ "NEW_ACHIEVEMENT_21_20_NAME" "클래식 모드"
+ "NEW_ACHIEVEMENT_21_20_DESC" "픽셀화를 활성화시키세요."
+ "NEW_ACHIEVEMENT_21_21_NAME" "학자"
+ "NEW_ACHIEVEMENT_21_21_DESC" "게임 내에서 위키를 여세요."
+ "NEW_ACHIEVEMENT_21_22_NAME" "힘찬 시작"
+ "NEW_ACHIEVEMENT_21_22_DESC" "캠페인 지역을 10,000개 혹은 그 이상의 시작 자원을 설정하고 시작하세요."
+ "NEW_ACHIEVEMENT_21_23_NAME" "점화"
+ "NEW_ACHIEVEMENT_21_23_DESC" "핵융합 원자로를 활성화시키세요."
+ "NEW_ACHIEVEMENT_21_25_NAME" "나선형"
+ "NEW_ACHIEVEMENT_21_25_DESC" "돌고 돌아 강강술래~!"
+ "NEW_ACHIEVEMENT_21_26_NAME" "상승!"
+ "NEW_ACHIEVEMENT_21_26_DESC" "5 티어 유닛을 만드세요."
+ "NEW_ACHIEVEMENT_21_27_NAME" "건축가"
+ "NEW_ACHIEVEMENT_21_27_DESC" "20개의 설계도를 생성하세요."
+ "NEW_ACHIEVEMENT_21_28_NAME" "글로벌 도미네이션"
+ "NEW_ACHIEVEMENT_21_28_DESC" "세르플로에 있는 모든 지역을 점령하세요."
+ "NEW_ACHIEVEMENT_21_29_NAME" "공수부대"
+ "NEW_ACHIEVEMENT_21_29_DESC" "옥트 유닛으로 5 티어 유닛을 수송하세요."
+ "NEW_ACHIEVEMENT_21_30_NAME" "궁극의 형태"
+ "NEW_ACHIEVEMENT_21_30_DESC" "그들과 함계 하십시오."
+ "NEW_ACHIEVEMENT_21_31_NAME" "생산 I"
+ "NEW_ACHIEVEMENT_21_31_DESC" "캠페인에서 총합 분당 5,000 자원 생산량에 도달하세요."
+ "NEW_ACHIEVEMENT_26_0_NAME" "생산 II"
+ "NEW_ACHIEVEMENT_26_0_DESC" "캠페인에서 총합 분당 50,000 자원 생산량에 도달하세요."
+ "NEW_ACHIEVEMENT_26_1_NAME" "확실한 승리"
+ "NEW_ACHIEVEMENT_26_1_DESC" "다른 지역에서 플레이하는 동안 한 지역을 점령하세요."
+ "NEW_ACHIEVEMENT_26_2_NAME" "작은 제국"
+ "NEW_ACHIEVEMENT_26_2_DESC" "한 번에 10개의 지역을 제어하세요."
+ "NEW_ACHIEVEMENT_26_3_NAME" "디자이너"
+ "NEW_ACHIEVEMENT_26_3_DESC" "500개의 설계도를 생성하세요."
+ "NEW_ACHIEVEMENT_26_4_NAME" "운반의 달인"
+ "NEW_ACHIEVEMENT_26_4_DESC" "단일 맵에서 모든 운송 블록(한 행성에서)을 사용하세요."
+ "NEW_ACHIEVEMENT_26_5_NAME" "과부하"
+ "NEW_ACHIEVEMENT_26_5_DESC" "과부하 프로젝터를 건설하세요."
+ "NEW_ACHIEVEMENT_26_6_NAME" "수선"
+ "NEW_ACHIEVEMENT_26_6_DESC" "멘더 또는 수리 프로젝터를 건설하세요."
+ "NEW_ACHIEVEMENT_26_7_NAME" "비효율성"
+ "NEW_ACHIEVEMENT_26_7_DESC" "물 위에 펌프 대신 물 추출기를 설치하세요."
+ "NEW_ACHIEVEMENT_26_8_NAME" "비축"
+ "NEW_ACHIEVEMENT_26_8_DESC" "캠페인에서 총 1,000만개의 자원을 수집하세요."
+ "NEW_ACHIEVEMENT_26_9_NAME" "모든 역경에 맞서"
+ "NEW_ACHIEVEMENT_26_9_DESC" "듀오 포탑으로 이클립스 유닛에 마지막 일격을 가하세요."
+ "NEW_ACHIEVEMENT_26_10_NAME" "에르키아 완료"
+ "NEW_ACHIEVEMENT_26_10_DESC" "에르키아의 마지막 지역을 점령하세요."
+ "NEW_ACHIEVEMENT_26_11_NAME" "세르플로 완료"
+ "NEW_ACHIEVEMENT_26_11_DESC" "세르플로의 마지막 지역을 점령하세요."
+ "NEW_ACHIEVEMENT_26_12_NAME" "미리 세팅"
+ "NEW_ACHIEVEMENT_26_12_DESC" "세르플로에서 제작한 코어 설계도로 지역을 시작하세요."
+ "NEW_ACHIEVEMENT_26_13_NAME" "과도하게 준비"
+ "NEW_ACHIEVEMENT_26_13_DESC" "전초기지의 코어를 핵으로 업그레이드하세요.."
+ "NEW_ACHIEVEMENT_26_14_NAME" "전염"
+ "NEW_ACHIEVEMENT_26_14_DESC" "물이 함유된 블록에 신생물을 퍼뜨리세요."
+ "NEW_ACHIEVEMENT_26_15_NAME" "불안정"
+ "NEW_ACHIEVEMENT_26_15_DESC" "빙결 상태 효과가 있는 유닛에 추가 폭발 피해를 입히세요."
+ "NEW_ACHIEVEMENT_26_16_NAME" "세르플로 구조물 마스터"
+ "NEW_ACHIEVEMENT_26_16_DESC" "세르플로에서 사용 가능한 모든 블록을 건설하세요."
+ "NEW_ACHIEVEMENT_26_17_NAME" "에르키아 구조물 마스터"
+ "NEW_ACHIEVEMENT_26_17_DESC" "에르키아에서 사용 가능한 모든 블록을 건설하세요."
+ "NEW_ACHIEVEMENT_26_18_NAME" "보호막 파괴!"
+ "NEW_ACHIEVEMENT_26_18_DESC" "적 보호막 프로젝터의 보호막을 파괴하세요."
+ "NEW_ACHIEVEMENT_26_19_NAME" "설명서는 어디에 있나요?"
+ "NEW_ACHIEVEMENT_26_19_DESC" "마이크로 프로세서를 연구하세요."
+ "NEW_ACHIEVEMENT_26_20_NAME" "정전"
+ "NEW_ACHIEVEMENT_26_20_DESC" "전력 소모 10k/초에 도달하세요."
+ "NEW_ACHIEVEMENT_26_21_NAME" "전력 급상승"
+ "NEW_ACHIEVEMENT_26_21_DESC" "전력 생산 100k/초에 도달하세요."
+ "NEW_ACHIEVEMENT_26_22_NAME" "고용량"
+ "NEW_ACHIEVEMENT_26_22_DESC" "배터리에 총 100만개의 전력을 저장하세요."
+ "NEW_ACHIEVEMENT_26_23_NAME" "나쁜 아이디어에요!"
+ "NEW_ACHIEVEMENT_26_23_DESC" "화력 발전기에 폭발물을 넣으세요."
+ "NEW_ACHIEVEMENT_26_24_NAME" "오염"
+ "NEW_ACHIEVEMENT_26_24_DESC" "신생물 축적으로 인해 신생물 반응로를 폭발하게 만드세요."
+ "NEW_ACHIEVEMENT_26_25_NAME" "수정됨"
+ "NEW_ACHIEVEMENT_26_25_DESC" "모드를 설치하세요."
+ "NEW_ACHIEVEMENT_26_26_NAME" "router"
+ "NEW_ACHIEVEMENT_26_26_DESC" "router"
+ "NEW_ACHIEVEMENT_26_27_NAME" "전체적 경험"
+ "NEW_ACHIEVEMENT_26_27_DESC" "커뮤니티 서버에 들어가세요."
+ "NEW_ACHIEVEMENT_26_28_NAME" "해커맨"
+ "NEW_ACHIEVEMENT_26_28_DESC" "스크립트 콘솔을 여세요."
+ "NEW_ACHIEVEMENT_26_29_NAME" "직접 제어"
+ "NEW_ACHIEVEMENT_26_29_DESC" "포탑을 직접 조종하세요."
+ "NEW_ACHIEVEMENT_26_30_NAME" "방어선 뒤에서 침입"
+ "NEW_ACHIEVEMENT_26_30_DESC" "적 코어의 건설 불가 구역 내에 유닛을 투하하세요."
+ "NEW_ACHIEVEMENT_26_31_NAME" "복수"
+ "NEW_ACHIEVEMENT_26_31_DESC" "플레어 유닛을 사용하여 스캐터 포탑을 파괴하세요."
+ "NEW_ACHIEVEMENT_29_0_NAME" "공수"
+ "NEW_ACHIEVEMENT_29_0_DESC" "지상 유닛의 이륙 기능을 사용하세요."
+ "NEW_ACHIEVEMENT_29_1_NAME" "호버크래프트"
+ "NEW_ACHIEVEMENT_29_1_DESC" "일루드 유닛을 사용해서 액체 위를 건너세요."
+ "NEW_ACHIEVEMENT_29_2_NAME" "지형 부스트"
+ "NEW_ACHIEVEMENT_29_2_DESC" "특정 타일에 구조물을 배치하여 효율성을 높이세요."
+ "NEW_ACHIEVEMENT_29_3_NAME" "대청소"
+ "NEW_ACHIEVEMENT_29_3_DESC" "바위 100개를 부수세요."
+ "NEW_ACHIEVEMENT_29_4_NAME" "광범위한 청소"
+ "NEW_ACHIEVEMENT_29_4_DESC" "바위 10,00개를 부수세요."
+ "NEW_ACHIEVEMENT_29_5_NAME" "중화됨"
+ "NEW_ACHIEVEMENT_29_5_DESC" "충격파 타워를 사용하여 들어오는 탄막을 흡수하세요."
+ "NEW_ACHIEVEMENT_29_6_NAME" "안타깝게도요,"
+ "NEW_ACHIEVEMENT_29_6_DESC" "멀티플레이어 채팅에서 :alphachan: 이모지를 사용하세요. 선택은 여러분의 몫입니다. 개발자의 취미을 찾으셨네요..."
+ }
+}
diff --git a/fastlane/metadata/steam/korean/description.txt b/fastlane/metadata/steam/korean/description.txt
new file mode 100644
index 0000000000..4b234545f7
--- /dev/null
+++ b/fastlane/metadata/steam/korean/description.txt
@@ -0,0 +1,62 @@
+Mindustry는 타워 디펜스와 RTS 요소가 있는 공장 건설 게임입니다. 포탑에 탄약을 공급하고, 건설에 사용할 재료를 생산하고, 유닛을 건설하기 위해 정교한 공급망을 만드세요. 유닛을 지휘하여 적의 기지를 점령하고, 생산을 확장하세요. 적으로부터 코어를 방어하세요.
+
+캠페인을 혼자 또는 여러 플랫폼의 멀티플레이어 협동 모드로 플레이하고, 팀 기반 PvP 매치에서 친구와 경쟁하세요.
+
+[img]{STEAM_APP_IMAGE}/extras/factory.gif[/img]
+
+[h2]공장 건물[/h2]
+
+[list]
+[*] 포탑에 탄약을 공급하고 건축에 사용할 재료를 생산하기 위해 컨베이어 벨트의 정교한 공급망을 만드세요.
+[*] 공장 블록을 사용하여 다양한 첨단 자원를 생산하세요.
+[*] 액체를 분배하고 화재 발생이나 적의 비행기 습격과 같은 끊임없는 도전에 맞서 싸우세요.
+[*] 선택적으로 제공되는 냉각수 및 윤활유를 공급하여 생산 효율을 극대화하세요.
+[*] 기지 자동 관리 또는 적 기지 공격을 위한 다양한 유닛을 생산하세요.
+[/list]
+
+[h2]타워 디펜스[/h2]
+
+[list]
+[*] 적으로부터 구조물을 보호하세요.
+[*] 적이 코어에 도달하기 전에 그들을 파괴할 수 있도록 전략적으로 포탑을 배치하세요.
+[*] 포탑에 탄약, 냉각수, 전력을 공급하세요.
+[*] 보호막, 재생 프로젝터 및 기타 지원 건물로 방어력을 강화하세요.
+[/list]
+
+[img]{STEAM_APP_IMAGE}/extras/rts3.png[/img]
+
+[h2]실시간 전략[/h2]
+
+[list]
+[*] 기계로 된 부대를 세우기 위한 조립 라인을 설정하세요.
+[*] 유닛을 사용해 완벽하게 기능하는 적 기지에 맞서세요.
+[*] 더 많은 영토를 확보하여 더 많은 코어를 배치하고 확장을 위한 추가 자원을 입수하세요.
+[/list]
+
+[h2]캠페인[/h2]
+
+[list]
+[*] 별도로 된 두 개의 행성의 캠페인을 플레이하세요.
+[*] 수작업으로 만들어진 35개의 맵과 절차적으로 생성된 250개 이상의 지역을 통과하면서 세르플로와 에르키아 행성을 정복하세요.
+[*] 다른 지역에서 플레이하는 동안 영토를 점령하고 공장을 설치하여 자원을 생산하세요.
+[*] 주기적인 침략으로부터 당신의 지역을 방어하세요.
+[*] 지역 자원 수송기를 통해 지역 간 자원 분배를 조정하세요.
+[*] 진행을 촉진하기 위해 새로운 블록을 연구하세요.
+[*] 친구를 초대하여 함께 미션을 완료하세요.
+[*] 마스터해야 할 250개 이상의 블록.
+[*] 50개 이상의 다양한 유형의 드론, 기계 및 함선.
+[*] 완료해야 할 80개 이상의 업적
+[/list]
+
+[h2]커뮤니티와 모딩[/h2]
+
+[list]
+[*] 커뮤니티에서 만든 맵과 설계도를 탐색하려면 Steam 창작마당을 사용하세요.
+[*] 여러 플랫폼에서 다른 사람들과 함께 플레이하려면 공개 커뮤니티 서버에 가입하세요.
+[*] 멀티플레이, PvP 또는 샌드박스 플레이.
+[*] 커뮤니티 서버는 사용자 지정 맵 및 게임 모드에 대한 플러그인을 지원합니다.
+[*] 공개 전용 서버를 만들거나 친구를 개인 서버에 초대하세요.
+[*] 사용자 지정 가능한 게임 규칙: 블록 비용, 적 통계, 시작 자원, 단계 시간 등을 변경하세요.
+[*] 내장된 맵 편집기를 사용하면 직접 플레이하고 커뮤니티와 공유할 수 있는 나만의 맵을 만들 수 있습니다.
+[*] 커뮤니티에서 만든 모드를 탐색하여 더 많은 콘텐츠를 추가하세요.
+[/list]
diff --git a/fastlane/metadata/steam/korean/short-description.txt b/fastlane/metadata/steam/korean/short-description.txt
new file mode 100644
index 0000000000..23868935ca
--- /dev/null
+++ b/fastlane/metadata/steam/korean/short-description.txt
@@ -0,0 +1 @@
+RTS와 타워 디펜스 요소를 갖춘 개방형 공장 관리 게임입니다.
diff --git a/gradle.properties b/gradle.properties
index 5c00967a82..c5d42ecc57 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -26,4 +26,4 @@ org.gradle.caching=true
org.gradle.internal.http.socketTimeout=100000
org.gradle.internal.http.connectionTimeout=100000
android.enableR8.fullMode=false
-archash=1fdfcdc213
+archash=4940b68158
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 0d1842103b..e1adfb4938 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-8.8-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/ios/src/mindustry/ios/IOSLauncher.java b/ios/src/mindustry/ios/IOSLauncher.java
index cf1b6b8208..776a2ec3e0 100644
--- a/ios/src/mindustry/ios/IOSLauncher.java
+++ b/ios/src/mindustry/ios/IOSLauncher.java
@@ -250,7 +250,7 @@ public class IOSLauncher extends IOSApplication.Delegate{
UIApplication.main(argv, null, IOSLauncher.class);
}catch(Throwable t){
//attempt to log the exception
- CrashSender.log(t);
+ CrashHandler.log(t);
Log.err(t);
//rethrow the exception so it actually crashes
throw t;
diff --git a/server/build.gradle b/server/build.gradle
index 7359fdac3c..f348e41dbf 100644
--- a/server/build.gradle
+++ b/server/build.gradle
@@ -47,6 +47,8 @@ task dist(type: Jar, dependsOn: configurations.runtimeClasspath){
exclude("icons/icon.ico")
exclude("icons/icon_64.png")
+ duplicatesStrategy = 'exclude'
+
manifest{
attributes 'Main-Class': project.mainClassName
}
diff --git a/server/src/mindustry/server/ServerLauncher.java b/server/src/mindustry/server/ServerLauncher.java
index 1aea11b2cc..d8737fc5e1 100644
--- a/server/src/mindustry/server/ServerLauncher.java
+++ b/server/src/mindustry/server/ServerLauncher.java
@@ -32,9 +32,9 @@ public class ServerLauncher implements ApplicationListener{
String result = "[" + dateTime.format(LocalDateTime.now()) + "] " + format(tags[level1.ordinal()] + " " + text + "&fr");
System.out.println(result);
};
- new HeadlessApplication(new ServerLauncher(), throwable -> CrashSender.send(throwable, f -> {}));
+ new HeadlessApplication(new ServerLauncher(), throwable -> CrashHandler.handle(throwable, f -> {}));
}catch(Throwable t){
- CrashSender.send(t, f -> {});
+ CrashHandler.handle(t, f -> {});
}
}
@@ -46,15 +46,15 @@ public class ServerLauncher implements ApplicationListener{
Vars.loadSettings();
Vars.init();
-
+
UI.loadColors();
Fonts.loadContentIconsHeadless();
-
+
content.createBaseContent();
mods.loadScripts();
content.createModContent();
content.init();
-
+
if(mods.hasContentErrors()){
err("Error occurred loading mod content:");
for(LoadedMod mod : mods.list()){
diff --git a/servers_be.json b/servers_be.json
deleted file mode 100644
index 6ba3d25ad2..0000000000
--- a/servers_be.json
+++ /dev/null
@@ -1,32 +0,0 @@
-[
- {
- "name": "Nydus",
- "address": ["be.mindustry.nydus.app:6567", "be.mindustry.nydus.app:6568"]
- },
- {
- "name": "mindustry.pl",
- "address": ["130.61.190.181:6567", "130.61.190.181:7777", "0.baseduser.eu.org:7777", "0.baseduser.eu.org:42001"]
- },
- {
- "address": "v7.mindurka.tk:9999"
- },
- {
- "name": "Chaotic Neutral",
- "address": ["37.187.73.180:7022"]
- },
- {
- "address": "n1.yeet.ml:6574"
- },
- {
- "name": "Phoenix-Network",
- "address": ["be.phoenix-network.dev"]
- },
- {
- "name": "Darkdustry",
- "address": ["darkdustry.tk"]
- },
- {
- "name": "TinyLake",
- "address": ["cn.mindustry.top:40500"]
- }
-]
diff --git a/servers_v7.json b/servers_v7.json
index 613e8bcac1..8da07d0128 100644
--- a/servers_v7.json
+++ b/servers_v7.json
@@ -1,335 +1,311 @@
[
{
- "name": "Redundancy Dept",
- "address": ["min7.include-once.org:8000", "min7.include-once.org:8001"]
+ "name": "EscoCorp",
+ "address": [
+ "121.127.37.17:6567",
+ "121.127.37.17:6568",
+ "121.127.37.17:6569",
+ "121.127.37.17:6570",
+ "121.127.37.17:6571"
+ ]
},
{
- "name": "TSR Network",
- "address": ["de-prem-01.hosts.optikservers.com:35526", "de-prem-01.hosts.optikservers.com:35915", "de-prem-01.hosts.optikservers.com:35250", "de-prem-01.hosts.optikservers.com:27526", "de-prem-01.hosts.optikservers.com:35376", "de-prem-01.hosts.optikservers.com:35895"]
- },
- {
- "name": "Toast Mindustry",
- "address": ["192.3.139.5:6567", "192.3.139.5:6568", "192.3.139.5:6569", "104.168.64.154:6567", "104.168.64.154:6568", "104.168.64.154:6569"]
+ "name": "EchoDustry",
+ "address": [
+ "node1.stellarch.org:7004"
+ ]
},
{
"name": "gods field",
- "address": ["n2.akiracloud.net:10225"]
- },
- {
- "name": "STP",
- "address": ["23.88.73.88:25617"]
- },
- {
- "name": "Meow Empire ≫ MEM PROJECT",
- "address": ["a2.corenodes.host:25514"]
- },
- {
- "name" : "LesGarsCools",
- "address": ["est1.be"]
- },
- {
- "name": "meiqiuMDT",
- "address": ["cn1.meiqiumdt.top","cn1.meiqiumdt.top:7000","cn1.meiqiumdt.top:8000","cn1.meiqiumdt.top:7013","cn1.meiqiumdt.top:9000"]
+ "address": [
+ "n2.akiracloud.net:10225",
+ "n2.akiracloud.net:10335"
+ ]
},
{
"name": "DontVin",
- "address": ["45.84.59.49:1342","45.137.205.185:1068","45.137.205.185:1190","45.137.205.185:1191","134.255.218.3:1142","45.137.205.185:1192","45.137.205.185:1193","45.137.205.185:1221","be.phoenix-network.dev","be.phoenix-network.dev:1111","be.phoenix-network.dev:2222","be.phoenix-network.dev:3333","be.phoenix-network.dev:4444","be.phoenix-network.dev:5555","be.phoenix-network.dev:6666","be.phoenix-network.dev:7777","be.phoenix-network.dev:8888","be.phoenix-network.dev:9999"]
- },
- {
- "name": "Crux's Citadel",
- "address": ["45.158.9.198:32865","45.158.9.198:30055","45.158.9.198:32175","45.158.9.198:30252","176.9.150.40:35899","129.154.47.57:26645","176.9.150.40:35930","129.154.47.57:27993","129.154.47.57:26881","176.9.150.40:35168","176.9.150.40:35900","176.9.150.40:35031","176.9.150.40:35154"]
- },
- {
- "name": "Chilldustry",
- "address": ["trelesco.xyz", "95.84.198.97"]
- },
- {
- "name": "ShardDustry Eventos",
- "address": ["45.158.9.198:31719"]
- },
- {
- "name": "ShardDustry ES",
- "address": ["45.158.9.198:32389"]
- },
- {
- "name": "Tamazia",
- "address": ["5.250.178.221:6567","5.250.178.221:6677"]
- },
- {
- "name": "Crux's Federation",
- "address": ["de-free-01.hosts.optikservers.com:32538", "de-free-01.hosts.optikservers.com:31421", "fsn1.bbn.one:37019"]
- },
- {
- "name": "RCM",
- "address": ["rcrms.ru:6567"]
- },
- {
- "name": "Tendhost",
- "address": ["tendhost.ddns.net:7576"]
- },
- {
- "name": "ECAN",
- "address": ["mindustry.ecansol.com:6597", "mindustry.ecansol.com:6499", "mindustry.ecansol.com:6599"]
- },
- {
- "name": "SMoke of Anarchy",
- "address": ["86.102.97.27"]
- },
- {
- "name": "Mindustry.pl",
- "address": ["1.baseduser.eu.org:6966", "1.baseduser.eu.org:6666", "1.baseduser.eu.org:6000"]
- },
- {
- "name": "SynapseOS",
- "address": ["0nera.ru:7777"]
- },
- {
- "name": "Voiddustry Servers",
- "address": ["45.144.66.250:6567", "185.189.14.201:6567"]
+ "address": [
+ "be.phoenix-network.dev:4444"
+ ]
},
{
"name": "thedimas",
- "address": ["130.162.212.232", "130.162.212.232:6503","130.162.212.232:6505", "130.162.212.232:6506", "130.162.212.232:6507", "130.162.212.232:6508", "130.162.212.232:6509", "130.162.212.232:6510", "130.162.212.232:6511", "130.162.212.232:6512", "130.162.212.232:6513"]
- },
- {
- "name": "HexPvP Network",
- "address": ["hexpvp.ddns.net", "kycb42148.ddns.net:6614"]
- },
- {
- "name": "Unidustry",
- "address": ["51.81.57.217:33703"]
+ "address": [
+ "130.162.212.232",
+ "130.162.212.232:6503",
+ "130.162.212.232:6505",
+ "130.162.212.232:6507",
+ "130.162.212.232:6508",
+ "130.162.212.232:6509",
+ "130.162.212.232:6510",
+ "130.162.212.232:6511",
+ "130.162.212.232:6513"
+ ]
},
{
"name": "KMWStudios",
- "address": ["kislota.kmwstudios.org:28101", "kislota.kmwstudios.org:28102", "kislota.kmwstudios.org:28103", "kislota.kmwstudios.org:28104", "kislota.kmwstudios.org:28105", "kislota.kmwstudios.org:28106", "kislota.kmwstudios.org:28107"]
+ "address": [
+ "kislota.kmwstudios.org:28102",
+ "kislota.kmwstudios.org:28103",
+ "kislota.kmwstudios.org:28104",
+ "kislota.kmwstudios.org:28105",
+ "kislota.kmwstudios.org:28106",
+ "kislota.kmwstudios.org:28107"
+ ]
},
{
"name": "XCore",
- "address": ["128.140.88.66", "128.140.88.66:6568", "128.140.88.66:6569", "128.140.88.66:6570", "128.140.88.66:6571", "128.140.88.66:6572", "128.140.88.66:6573", "128.140.88.66:6574", "128.140.88.66:6575"]
+ "address": [
+ "128.140.88.66",
+ "128.140.88.66:6568",
+ "128.140.88.66:6569",
+ "128.140.88.66:6570",
+ "128.140.88.66:6571",
+ "128.140.88.66:6572",
+ "128.140.88.66:6573",
+ "128.140.88.66:6574",
+ "128.140.88.66:6575"
+ ]
},
{
"name": "MinDurka",
- "address": ["mindurka.fun", "mindurka.fun:3001", "mindurka.fun:3002", "mindurka.fun:3003", "mindurka.fun:3004", "mindurka.fun:3005", "mindurka.fun:3006", "mindurka.fun:3007", "mindurka.fun:3008", "mindurka.fun:3009", "mindurka.fun:3010", "mindurka.fun:3011"]
+ "address": [
+ "mindurka.fun",
+ "mindurka.fun:3001",
+ "mindurka.fun:3002",
+ "mindurka.fun:3003",
+ "mindurka.fun:3004",
+ "mindurka.fun:3005",
+ "mindurka.fun:3006",
+ "mindurka.fun:3007",
+ "mindurka.fun:3008",
+ "mindurka.fun:3009",
+ "mindurka.fun:3010",
+ "mindurka.fun:3011"
+ ]
},
{
"name": "Chaotic Neutral",
- "address": ["37.187.73.180:7011", "37.187.73.180:7012", "37.187.73.180:7013", "37.187.73.180:7014", "37.187.73.180:7015", "37.187.73.180:7016", "37.187.73.180:7017"]
+ "address": [
+ "37.187.73.180:7011",
+ "37.187.73.180:7013",
+ "37.187.73.180:7014",
+ "37.187.73.180:7015",
+ "37.187.73.180:7016",
+ "37.187.73.180:7017"
+ ]
},
{
"name": "io",
- "address": ["159.69.7.83", "159.69.7.83:1000", "159.69.7.83:2000", "159.69.7.83:3000", "159.69.7.83:4000"]
- },
- {
- "name": "Korea",
- "address": ["mindustry.kr"]
- },
- {
- "name": "LatamDustry",
- "address": ["45.158.9.23:5532", "45.158.9.23:5422", "45.158.9.23:5463", "45.158.9.23:5520"]
- },
- {
- "name": "Pandorum",
- "address": ["pandorum.su:5018", "pandorum.su:5019", "pandorum.su:5020"]
+ "address": [
+ "148.251.184.58",
+ "148.251.184.58:1000",
+ "148.251.184.58:2000",
+ "148.251.184.58:3000",
+ "148.251.184.58:4000"
+ ]
},
{
"name": "Tinylake",
- "address": ["cn.mindustry.top", "g.mindustry.top", "cn.mindustry.top:40003", "cn.mindustry.top:40500"]
+ "address": [
+ "cn.mindustry.top"
+ ]
},
{
"name": "Fish",
- "address": ["162.248.101.95", "162.248.100.98", "162.248.100.133", "162.248.102.204", "162.248.101.53", "37.187.73.180:7012"]
+ "address": [
+ "162.248.101.95",
+ "162.248.100.98",
+ "162.248.100.133",
+ "162.248.101.53"
+ ]
},
{
"name": "OmniCorp Classic",
- "address": ["omnidustry.ru:6567", "omnidustry.ru:6568", "omnidustry.ru:6569", "omnidustry.ru:6570", "omnidustry.ru:6571", "omnidustry.ru:6572", "omnidustry.ru:6573", "omnidustry.ru:6574"]
+ "address": ["omnidustry.ru:6567", "omnidustry.ru:6568", "omnidustry.ru:6569", "omnidustry.ru:6570", "omnidustry.ru:6571", "omnidustry.ru:6572", "omnidustry.ru:6573", "omnidustry.ru:6574", "omnidustry.ru:6575"]
},
{
"name": "The Devil",
- "address": ["xem8k5.mindustry.top:8169", "test.xem8k5.top:8920", "other.xem8k5.top:10936", "n2.akiracloud.net:10404", "new.xem8k5.top"]
+ "address": [
+ "new.xem8k5.top"
+ ]
},
{
"name": "Eradication Mindustry",
- "address": ["140.238.246.78:7000", "140.238.246.78:7001", "140.238.246.78:7002", "140.238.246.78:7003", "140.238.246.78:7004", "130.61.22.183:7000", "130.61.22.183:7001", "130.61.22.183:7002", "130.61.22.183:7003", "130.61.22.183:7004", "130.61.22.183:7005", "130.61.22.183:7006", "62.30.47.117:7000", "62.30.47.117:7001", "62.30.47.117:7002", "62.30.47.117:7003", "62.30.47.116:7000", "62.30.47.116:7001"]
+ "address": [
+ "130.61.22.183:7000",
+ "130.61.22.183:7001",
+ "144.24.196.119:7000",
+ "144.24.196.119:7001",
+ "140.238.246.78:7000",
+ "140.238.246.78:7001",
+ "62.30.47.116:7000",
+ "62.30.47.116:7001",
+ "122.180.249.217:7000",
+ "122.180.249.217:7001",
+ "20.186.12.170:7000",
+ "20.2.202.238:7000"
+ ]
},
{
"name": "Conservatory",
- "address": ["165.232.137.170:6567", "165.232.137.170:6568"]
+ "address": [
+ "165.232.137.170:6567",
+ "165.232.137.170:6568"
+ ]
},
{
"name": "mindustry.ddns.net",
- "address": ["mindustry.ddns.net", "mindustry.ddns.net:1000", "mindustry.ddns.net:2000", "mindustry.ddns.net:3000", "mindustry.ddns.net:4000", "mindustry.ddns.net:5000"]
- },
- {
- "name": "EasyPlay.su",
- "address": ["easyplay.su", "s.easyplay.su:6577", "s.easyplay.su:6686", "s.easyplay.su:6567"]
+ "address": [
+ "mindustry.ddns.net",
+ "mindustry.ddns.net:1000",
+ "mindustry.ddns.net:2000",
+ "mindustry.ddns.net:3000",
+ "mindustry.ddns.net:4000",
+ "mindustry.ddns.net:5000"
+ ]
},
{
"name": "Sectorized",
- "address": ["sectorized.freeddns.org"]
+ "address": [
+ "sectorized.freeddns.org"
+ ]
},
{
"name": "Apricot Alliance",
- "address": ["apricotalliance.org"]
+ "address": [
+ "apricotalliance.org"
+ ]
},
{
- "name": "Sakura",
- "address": ["160.16.207.141:20527", "160.16.207.141:21527", "160.16.207.141:22527", "160.16.207.141:23527", "160.16.207.141:24527", "160.16.207.141:25527", "160.16.207.141:26527", "160.16.207.141:27527", "160.16.207.141:28527", "160.16.207.141:29527", "162.43.36.78:20527", "162.43.36.78:21527", "162.43.36.78:22527", "162.43.36.78:23527", "162.43.36.78:24527", "162.43.36.78:25527", "162.43.36.78:26527", "162.43.36.78:27527", "162.43.36.78:28527", "162.43.36.78:29527", "sakura-mindustry.jp:20527"]
- },
- {
- "name": "|RussianServers|[]",
- "address": ["02calm.ru:6567", "02calm.ru:6568", "02calm.ru:6569", "02calm.ru:6570", "02calm.ru:6571", "02calm.ru:6572", "02calm.ru:6573"]
- },
- {
- "name": "Hungarian",
- "address": ["play.hudustry.tk"]
- },
- {
- "name": "SubZero",
- "address": ["mintyserver.net"]
+ "name": "Sakura",
+ "address": [
+ "162.43.36.78:22527",
+ "162.43.36.78:24527",
+ "162.43.36.78:25527",
+ "162.43.36.78:27527",
+ "162.43.36.78:28527"
+ ]
},
{
"name": "Router Pi",
- "address": ["a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6568", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6569", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6570", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6571", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6572", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6573", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6574"]
+ "address": [
+ "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6569",
+ "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6570"
+ ]
},
{
- "name": "Anana",
- "address": ["mdt.mdtleague.top","mdt2.mdtleague.top"]
- },
- {
- "name": "Vortex",
- "address": ["vortex.org.ru", "vortex.org.ru:6568", "vortex.org.ru:6569", "vortex.org.ru:6570", "vortex.org.ru:6571"]
- },
- {
- "name": "Botipont",
- "address": ["213.181.206.126:6567", "213.181.206.126:6568", "213.181.206.126:6569"]
+ "name": "Anana",
+ "address": [
+ "mdt.mdtleague.top"
+ ]
},
{
"name": "Exploding Cowards",
- "address": ["193.31.31.165:25778", "193.31.31.165:25790"]
+ "address": [
+ "45.43.163.225:25538"
+ ]
},
{
"name": "Realm of Serene Lime",
- "address": ["mindustry.icu", "sx.mindustry.icu", "mod.mindustry.icu"]
- },
- {
- "name": "CreateDustry",
- "address": ["95.216.68.161:55639"]
- },
- {
- "name": "Official Mindustry Events",
- "address": ["event.baseduser.eu.org"],
- "prioritized": true
- },
- {
- "name": "LifeTime",
- "address": ["srv3.godlike.club:28561", "srv3.godlike.club:26508"]
+ "address": [
+ "mindustry.icu",
+ "sx.mindustry.icu"
+ ]
},
{
"name": "Cyandustry",
- "address": ["45.88.109.9:7000","45.88.109.9:7001", "45.88.109.9:7002", "45.88.109.9:7003", "45.88.109.9:7004", "45.88.109.9:7005", "45.88.109.9:7006", "45.88.109.9:7007", "45.88.109.9:7008"]
- },
- {
- "name": "Four Family",
- "address": ["118.127.8.162:25503"]
- },
- {
- "name": "ToxoFlame",
- "address": ["193.233.133.223", "193.233.133.223:6568", "193.233.133.223:6569"]
+ "address": [
+ "45.88.109.9:7000",
+ "45.88.109.9:7001",
+ "45.88.109.9:7003",
+ "45.88.109.9:7004",
+ "45.88.109.9:7006",
+ "45.88.109.9:7008"
+ ]
},
{
"name": "MeowIsland",
- "address": ["meowisland.ru:5000", "meowisland.ru:5001", "meowisland.ru:5002", "meowisland.ru:5003", "meowisland.ru:5004"]
+ "address": [
+ "meowisland.ru:5000",
+ "meowisland.ru:5001",
+ "meowisland.ru:5003",
+ "meowisland.ru:5004"
+ ]
},
{
"name": "Exdustry",
- "address": ["exd.noxia.cloud:6001", "exd.noxia.cloud:6002", "exd.noxia.cloud:6003", "exd.noxia.cloud:6004", "exd.noxia.cloud:6005", "exd.noxia.cloud:6006", "exd.noxia.cloud:6007", "exd.noxia.cloud:6008", "exd.noxia.cloud:6009", "exd.noxia.cloud:6010"]
- },
- {
- "name": "abcxyz remaster",
- "address": ["144.76.57.59:30302", "23.88.73.88:16895"]
+ "address": [
+ "exd.noxia.cloud:6001",
+ "exd.noxia.cloud:6002",
+ "exd.noxia.cloud:6003",
+ "exd.noxia.cloud:6004",
+ "exd.noxia.cloud:6006"
+ ]
},
{
"name": "CroCraft Network",
- "address": ["193.122.53.98:6567", "193.122.53.98:20130"]
- },
- {
- "name": "Extra Utilities",
- "address": ["p1.i9mr.com:44922", "p1.i9mr.com:44834", "p1.i9mr.com:43189", "203.135.99.189:15142", "203.135.99.189:15143", "203.135.99.190:15142", "203.135.99.190:15143"]
+ "address": [
+ "193.122.53.98:6567"
+ ]
},
{
"name": "Alex Multiverse",
- "address": ["alexmindustryv7.servegame.com:25588", "172.234.80.96:6768", "139.162.41.78:6767", "172.245.187.143:6868", "172.245.187.143:6869", "92.119.127.171:6888", "181.215.58.13:1025", "181.215.58.13:1027"]
- },
- {
- "name": "Open PVP",
- "address": ["162.55.42.21:5555"]
+ "address": [
+ "alexmindustryv7.servegame.com:25588",
+ "172.234.80.96:6768",
+ "139.162.41.78:6767",
+ "172.245.187.143:6868",
+ "172.245.187.143:6869",
+ "92.119.127.171:6888",
+ "23.95.107.12"
+ ]
},
{
"name": "XuwenHost",
- "address": ["mdt.xuwenblock.cn:6567","mdt.nekopark.cloud:6567"]
- },
- {
- "name": "Atomic",
- "address": ["atomic-de.ddns.net:35876", "atomic-de.ddns.net:35663", "atomic-de.ddns.net:35724", "atomic-de.ddns.net:35847"]
- },
- {
- "name": "Gadgetroch's Server",
- "address": ["mindustry.gadgetroch.com", "mindustry.gadgetroch.com:6568", "mindustry.gadgetroch.com:6569"]
- },
- {
- "name": "Duel.Server",
- "address":["160.251.41.148:6567","160.251.41.148:6568","160.251.41.148:6569","160.251.41.148:6570"]
- },
- {
- "name": "AZDustry",
- "address": ["8.245.23.28:25874"]
+ "address": [
+ "mdt.nekopark.cloud:6567"
+ ]
},
{
"name": "Erepulo",
- "address": ["95.84.198.97:5401", "95.84.198.97:5402", "95.84.198.97:5403", "95.84.198.97:5404", "95.84.198.97:2357", "95.84.198.97:5500"]
+ "address": [
+ "95.84.198.97:5401",
+ "95.84.198.97:5402",
+ "95.84.198.97:5403",
+ "frost-heaven.ru",
+ "frost-heaven.ru:6568",
+ "91.200.150.116"
+ ]
},
{
- "name": "MineCore",
- "address": ["194.247.42.11:27792", "194.247.42.11:27977", "194.247.42.61:27989", "194.247.42.181:28514"]
- },
- {
- "name": "Mindus•VN",
- "address": ["167.71.199.155:25550"]
- },
- {
- "name": "Impact",
- "address": ["impactmindustry.ddns.net"]
- },
- {
- "name": "2D2R",
- "address": ["45.137.205.185:1045", "51.89.173.50:1432", "45.137.205.185:1052", "45.137.205.185:1040"]
- },
- {
- "name": "TRFACT",
- "address": ["213.142.156.83:25565"]
+ "name": "FrostHeaven",
+ "address": [
+ "frost-heaven.ru",
+ "frost-heaven.ru:6568",
+ "91.200.150.116",
+ "frost-heaven.ru:6570"
+ ]
},
{
"name": "ArmyOFUkraine",
- "address": ["194.247.42.131:27715", "194.247.42.131:27512"]
- },
- {
- "name": "Erbium",
- "address": ["hp5.nexcord.com:12066", "hp5.nexcord.com:11999", "hp5.nexcord.com:12067"]
- },
- {
- "name": "Vndustry",
- "address": ["vndustry.ddns.net"]
- },
- {
- "name": "ChillOut",
- "address": ["87.228.8.133", "87.228.8.133:6568"]
+ "address": [
+ "194.247.42.131:27715",
+ "194.247.42.131:27512",
+ "194.247.42.130:27505"
+ ]
},
{
"name": "VNM",
- "address": ["server.mindustry-tool.app"]
+ "address": [
+ "server.mindustry-tool.com",
+ "server.mindustry-tool.com:6568"
+ ]
},
{
- "name": "LibreDUSTRY",
- "address": ["46.4.114.111"]
+ "name": "Korea",
+ "address": [
+ "mindustry.kr"
+ ]
}
]
diff --git a/settings.gradle b/settings.gradle
index b74305dad2..dafd6bdf99 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,5 +1,5 @@
-if(JavaVersion.current().ordinal() < JavaVersion.VERSION_16.ordinal()){
- throw new Exception("!!! YOU MUST USE JAVA 16 OR ABOVE TO COMPILE AND RUN MINDUSTRY !!! Read the README. Your version: ${System.properties["java.version"]}")
+if(JavaVersion.current().ordinal() < JavaVersion.VERSION_17.ordinal()){
+ throw new Exception("!!! YOU MUST USE JAVA 17 OR ABOVE TO COMPILE AND RUN MINDUSTRY !!! Read the README. Your version: ${System.properties["java.version"]}")
}
include 'desktop', 'core', 'server', 'ios', 'annotations', 'tools', 'tests'
diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java
index 773a91ffa3..4f6c608d19 100644
--- a/tests/src/test/java/ApplicationTests.java
+++ b/tests/src/test/java/ApplicationTests.java
@@ -226,7 +226,7 @@ public class ApplicationTests{
@Test
void serverListJson(){
- String[] files = {"servers_v6.json", "servers_v7.json", "servers_be.json"};
+ String[] files = {"servers_v6.json", "servers_v7.json"};
for(String file : files){
diff --git a/tests/src/test/java/ModTestHAI.java b/tests/src/test/java/ModTestHAI.java
deleted file mode 100644
index 5dfa3223e4..0000000000
--- a/tests/src/test/java/ModTestHAI.java
+++ /dev/null
@@ -1,43 +0,0 @@
-import arc.util.*;
-import mindustry.*;
-import mindustry.gen.*;
-import mindustry.type.*;
-import org.junit.jupiter.api.*;
-
-import static mindustry.Vars.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-//grabs a version-locked Heavy Armaments Industries commit and makes sure it initializes correctly
-//this mod was chosen because:
-//- it is one of the top JS mods, based on stars
-//- it contains both JS and JSON, which can be used to test compatibility of the two
-//- it can be used server-side (unlike FactoryDustry, which is a client-side texture pack that cannot be tested here)
-public class ModTestHAI extends GenericModTest{
-
- @Test
- public void begin(){
- //TODO broken as of 136+
- if(true) return;
-
- grabMod("https://github.com/Eschatologue/Heavy-Armaments-Industries/archive/d996e92dcf9a30a6acb7b3bfdfb6522dddc3804c.zip");
- checkExistence("heavy-armaments");
-
- UnitType type = Vars.content.units().find(u -> u.name.equals("heavy-armaments-t3A_copter"));
- assertNotNull(type, "A mod unit must be loaded.");
- assertTrue(type.weapons.size > 0, "A mod unit must have a weapon.");
-
- Vars.world.loadMap(maps.loadInternalMap("groundZero"));
-
- Unit unit = type.spawn(0, 0);
-
- //check for crash
- unit.update();
-
- assertTrue(unit.health > 0, "Unit must be spawned and alive.");
- assertTrue(Groups.unit.size() > 0, "Unit must be spawned and alive.");
-
- //just an extra sanity check
- Log.info("Modded units: @", Vars.content.units().select(u -> u.minfo.mod != null));
- }
-
-}
diff --git a/tools/src/mindustry/tools/ScriptMainGenerator.java b/tools/src/mindustry/tools/ScriptMainGenerator.java
index 75dd91d181..4b0fdac9e5 100644
--- a/tools/src/mindustry/tools/ScriptMainGenerator.java
+++ b/tools/src/mindustry/tools/ScriptMainGenerator.java
@@ -10,6 +10,7 @@ import arc.graphics.gl.*;
import arc.math.*;
import arc.struct.*;
import arc.util.*;
+import com.google.common.reflect.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.io.*;
@@ -23,7 +24,7 @@ public class ScriptMainGenerator{
public static void main(String[] args) throws Exception{
String base = "mindustry";
- Seq blacklist = Seq.with("plugin", "mod", "net", "io", "tools");
+ Seq blacklist = Seq.with("tools", "arc.flabel.effects");
Seq nameBlacklist = Seq.with();
Seq> whitelist = Seq.with(Draw.class, Fill.class, Lines.class, Core.class, TextureAtlas.class, TextureRegion.class, Time.class, System.class, PrintStream.class,
AtlasRegion.class, String.class, Mathf.class, Angles.class, Color.class, Runnable.class, Object.class, Icon.class, Tex.class, Shader.class,
@@ -40,13 +41,15 @@ public class ScriptMainGenerator{
getClasses("arc.audio"),
getClasses("arc.input"),
getClasses("arc.util"),
+ getClasses("arc.files"),
+ getClasses("arc.flabel"),
getClasses("arc.struct")
);
classes.addAll(whitelist);
classes.sort(Structs.comparing(Class::getName));
classes.removeAll(type -> type.isSynthetic() || type.isAnonymousClass() || type.getCanonicalName() == null || Modifier.isPrivate(type.getModifiers())
- || blacklist.contains(s -> type.getName().startsWith(base + "." + s + ".")) || nameBlacklist.contains(type.getSimpleName()));
+ || blacklist.contains(s -> type.getName().startsWith(base + "." + s + ".")) || nameBlacklist.contains(type.getSimpleName()) || blacklist.contains(type.getPackage().getName()));
classes.add(NetConnection.class, SaveIO.class, SystemCursor.class);
classes.distinct();
@@ -113,7 +116,15 @@ public class ScriptMainGenerator{
}
public static Seq getClasses(String packageName) throws Exception{
- //TODO doesn't work, a java release broke it, look into alternative solutions (or just don't, Javascript modding is a bad idea anyway)
- return new Seq<>();
+ final ClassLoader loader = Thread.currentThread().getContextClassLoader();
+
+ var result = new Seq();
+
+ for(ClassPath.ClassInfo info : ClassPath.from(loader).getAllClasses()){
+ if(info.getName().startsWith(packageName + ".")){
+ result.add(info.load());
+ }
+ }
+ return result;
}
}