diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 64b7650e62..85459446aa 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -7,8 +7,6 @@ assignees: ''
---
-**Note**: Do not report any new bugs directly relating to the v6 campaign. They will not be fixed or considered at this time.
-
**Platform**: *Android/iOS/Mac/Windows/Linux*
**Build**: *The build number under the title in the main menu. Required. "LATEST" IS NOT A VERSION, I NEED THE EXACT BUILD NUMBER OF YOUR GAME.*
diff --git a/README.md b/README.md
index 5c9c797297..13f620832f 100644
--- a/README.md
+++ b/README.md
@@ -9,34 +9,34 @@ _[Trello Board](https://trello.com/b/aE2tcUwF/mindustry-40-plans)_
_[Wiki](https://mindustrygame.github.io/wiki)_
_[Javadoc](https://mindustrygame.github.io/docs/)_
-### Contributing
+## Contributing
See [CONTRIBUTING](CONTRIBUTING.md).
-### Building
+## Building
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 14](https://adoptopenjdk.net/) installed. Open a terminal in the root directory, `cd` to the Mindustry folder and run the following commands:
-#### Windows
+### Windows
_Running:_ `gradlew desktop:run`
_Building:_ `gradlew desktop:dist`
_Sprite Packing:_ `gradlew tools:pack`
-#### Linux/Mac OS
+### Linux/Mac OS
_Running:_ `./gradlew desktop:run`
_Building:_ `./gradlew desktop:dist`
_Sprite Packing:_ `./gradlew tools:pack`
-#### Server
+### Server
Server builds are bundled with each released build (in Releases). If you'd rather compile on your own, replace 'desktop' with 'server', e.g. `gradlew server:dist`.
-#### Android
+### Android
1. Install the Android SDK [here.](https://developer.android.com/studio#downloads) Make sure you're downloading the "Command line tools only", as Android Studio is not required.
2. Set the `ANDROID_HOME` environment variable to point to your unzipped Android SDK directory.
@@ -44,7 +44,9 @@ Server builds are bundled with each released build (in Releases). If you'd rathe
To debug the application on a connected phone, run `gradlew android:installDebug android:run`.
-##### Troubleshooting
+### Troubleshooting
+
+#### Permission Denied
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.*
@@ -53,11 +55,11 @@ If the terminal returns `Permission denied` or `Command not found` on Mac/Linux,
Gradle may take up to several minutes to download files. Be patient.
After building, the output .JAR file should be in `/desktop/build/libs/Mindustry.jar` for desktop builds, and in `/server/build/libs/server-release.jar` for server builds.
-### Feature Requests
+## Feature Requests
Post feature requests and feedback [here](https://github.com/Anuken/Mindustry-Suggestions/issues/new/choose).
-### Downloads
+## Downloads
[
}SmtWKuXGqYz\P?E:Y
ΤԢh)(%UDK(.%#V0FN#
\ No newline at end of file
diff --git a/core/assets/baseparts/1603214967392.msch b/core/assets/baseparts/1603214967392.msch
new file mode 100644
index 0000000000..0e30b20a82
--- /dev/null
+++ b/core/assets/baseparts/1603214967392.msch
@@ -0,0 +1 @@
+mschx%A ᧀZc\.z$dФ/t?3o`Ɲ.L<$NV!b>=e%80r"^!GKug9耦{S_@+$jW\oJSM ܅0?CThqW
\ No newline at end of file
diff --git a/core/assets/baseparts/1603214996033.msch b/core/assets/baseparts/1603214996033.msch
new file mode 100644
index 0000000000..83690987ae
--- /dev/null
+++ b/core/assets/baseparts/1603214996033.msch
@@ -0,0 +1,3 @@
+mschx%
+ ӪmicC/{bU~A>:n^Xvw?ŧ[56ů'gX|qa=SAsCNNA0Q=Mb9MIDҒbQAјٟZ}<
+sFU.BI
\ No newline at end of file
diff --git a/core/assets/baseparts/1603215024189.msch b/core/assets/baseparts/1603215024189.msch
new file mode 100644
index 0000000000..75d8474c96
Binary files /dev/null and b/core/assets/baseparts/1603215024189.msch differ
diff --git a/core/assets/baseparts/1603215113546.msch b/core/assets/baseparts/1603215113546.msch
new file mode 100644
index 0000000000..bf1020f89f
--- /dev/null
+++ b/core/assets/baseparts/1603215113546.msch
@@ -0,0 +1,2 @@
+mschx%[n A}"
t'C$؎]
c.9gFcK8XƸ}>O}c|tt#-)䃑dqPҒr$b@*b2rtҳRZґ@Wr#
\ No newline at end of file
diff --git a/core/assets/baseparts/1603215171294.msch b/core/assets/baseparts/1603215171294.msch
new file mode 100644
index 0000000000..eaef917ff3
--- /dev/null
+++ b/core/assets/baseparts/1603215171294.msch
@@ -0,0 +1,2 @@
+mschx%ᎃ Ai߃pB`M
+!0;060/oK8J\k a|Tk~Sq)O-h_|M%35V⾸Ӌ\[}ٱ#ⶼ@0-'hh0@W@JCi4bjp2gㄽ_]䡎Eӱ-K+.
\ No newline at end of file
diff --git a/core/assets/baseparts/1603215272794.msch b/core/assets/baseparts/1603215272794.msch
new file mode 100644
index 0000000000..b2351a3857
--- /dev/null
+++ b/core/assets/baseparts/1603215272794.msch
@@ -0,0 +1 @@
+mschxMKn D1P$9yvtCY_%Jno>1-~K؎i?#BI%q;R8W;r˖#v)!F\7ٔoIy{4ïvg=!;^`4E`
ah:I:!u0hRFC7:TW0t=z*] %wX#H7G4}mWW03Įb6
e>
\ No newline at end of file
diff --git a/core/assets/baseparts/1603215345320.msch b/core/assets/baseparts/1603215345320.msch
new file mode 100644
index 0000000000..8c97534bdf
--- /dev/null
+++ b/core/assets/baseparts/1603215345320.msch
@@ -0,0 +1,4 @@
+mschxEn@\E!dͲ:iҐqvfاȇP^]|g7Bw
+Vp]ln5'?|`npr};МC0O[vM߆4vpߑ'*HY~2dJNV(BLr+bHw-cKM52e*WR!KL{X#SAJR5dCV6r]m`t~H覵RvX
+2HNk{8'L^+y#
+pU%%%JAJ$?M
\ No newline at end of file
diff --git a/core/assets/baseparts/1603215415778.msch b/core/assets/baseparts/1603215415778.msch
new file mode 100644
index 0000000000..6f7f75ab97
--- /dev/null
+++ b/core/assets/baseparts/1603215415778.msch
@@ -0,0 +1,2 @@
+mschx-k
+1MуP
PҮEdM?o2c1e_BϚ/guI08bI~e.pRwGO`madh{Nނ:'"IZ}äz}o)"
\ No newline at end of file
diff --git a/core/assets/baseparts/1603215454977.msch b/core/assets/baseparts/1603215454977.msch
new file mode 100644
index 0000000000..c0a53057ed
Binary files /dev/null and b/core/assets/baseparts/1603215454977.msch differ
diff --git a/core/assets/baseparts/1603215491407.msch b/core/assets/baseparts/1603215491407.msch
new file mode 100644
index 0000000000..ba578a4a55
--- /dev/null
+++ b/core/assets/baseparts/1603215491407.msch
@@ -0,0 +1,2 @@
+mschx5ኃ01mj9(h~H½eufCn
+jgA7}~K>@
}cNOv2a=oc\D[=qt0&?S(Р(p=R$тJT&geJIMʴ*~#d|EE4I#tFxpzpzʤ3% h'/4ol```SfffG?J
(,
\ No newline at end of file
diff --git a/core/assets/baseparts/1603215563717.msch b/core/assets/baseparts/1603215563717.msch
new file mode 100644
index 0000000000..460c1d9f8b
Binary files /dev/null and b/core/assets/baseparts/1603215563717.msch differ
diff --git a/core/assets/baseparts/1603215697527.msch b/core/assets/baseparts/1603215697527.msch
new file mode 100644
index 0000000000..427e52f671
Binary files /dev/null and b/core/assets/baseparts/1603215697527.msch differ
diff --git a/core/assets/baseparts/1603215771822.msch b/core/assets/baseparts/1603215771822.msch
new file mode 100644
index 0000000000..68ee586ea5
Binary files /dev/null and b/core/assets/baseparts/1603215771822.msch differ
diff --git a/core/assets/baseparts/1603215801163.msch b/core/assets/baseparts/1603215801163.msch
new file mode 100644
index 0000000000..09b9033d84
--- /dev/null
+++ b/core/assets/baseparts/1603215801163.msch
@@ -0,0 +1 @@
+mschx-[ DJJaQMӵ~g&31dSo=-q[[LޭFqav.0[
SA/ciF(dPD~+
\ No newline at end of file
diff --git a/core/assets/baseparts/1603216038407.msch b/core/assets/baseparts/1603216038407.msch
new file mode 100644
index 0000000000..85865ba123
Binary files /dev/null and b/core/assets/baseparts/1603216038407.msch differ
diff --git a/core/assets/baseparts/1603216102310.msch b/core/assets/baseparts/1603216102310.msch
new file mode 100644
index 0000000000..a05dbc61ed
--- /dev/null
+++ b/core/assets/baseparts/1603216102310.msch
@@ -0,0 +1 @@
+mschx%[j0EoؓK]e258 ;SJI]">O}\_~Hy
!K)
%Q5KzFNR2L/9uۋX|iX9u+8pz&։mOh!>t^m1%(M6Ae)
\ No newline at end of file
diff --git a/core/assets/baseparts/1603216240041.msch b/core/assets/baseparts/1603216240041.msch
new file mode 100644
index 0000000000..c0960c09d5
--- /dev/null
+++ b/core/assets/baseparts/1603216240041.msch
@@ -0,0 +1,3 @@
+mschxMIR0EJk.cp
+*cZrF_\n?2^x(RvHg^}N'ς$6r4Tl"=ZނbA4W'&wt3-l`PC?6s}+iyf$15a-~Y/gD>X
\ No newline at end of file
diff --git a/core/assets/baseparts/1603222833941.msch b/core/assets/baseparts/1603222833941.msch
new file mode 100644
index 0000000000..565eecf779
Binary files /dev/null and b/core/assets/baseparts/1603222833941.msch differ
diff --git a/core/assets/baseparts/1603222912251.msch b/core/assets/baseparts/1603222912251.msch
new file mode 100644
index 0000000000..6b33abac34
Binary files /dev/null and b/core/assets/baseparts/1603222912251.msch differ
diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties
index 651576c3de..f7a3a6dcfe 100644
--- a/core/assets/bundles/bundle.properties
+++ b/core/assets/bundles/bundle.properties
@@ -20,7 +20,7 @@ gameover = Game Over
gameover.pvp = The[accent] {0}[] team is victorious!
highscore = [accent]New highscore!
copied = Copied.
-indev.popup = [accent]v6[] is currently in [accent]alpha[].\n[lightgray]This means:[]\n[scarlet]- The campaign is completely unfinished[]\n- SFX and music are unfinished/missing\n- Everything you see is subject to change or removal.\n\nReport bugs or crashes on [accent]Github[].
+indev.popup = [accent]v6[] is currently in [accent]beta[].\n[lightgray]This means:[]\n[scarlet]- The campaign is completely unfinished[]\n- SFX and music are unfinished/missing\n- Everything you see is subject to change or removal.\n\nReport bugs or crashes on [accent]Github[].
indev.notready = This part of the game isn't ready yet
load.sound = Sounds
@@ -100,8 +100,7 @@ committingchanges = Comitting Changes
done = Done
feature.unsupported = Your device does not support this feature.
-mods.alphainfo = Keep in mind that mods are in alpha, and[scarlet] may be very buggy[].\nReport any issues you find to the Mindustry GitHub or Discord.
-mods.alpha = [accent](Alpha)
+mods.alphainfo = Keep in mind that mods are in alpha, and[scarlet] may be very buggy[].\nReport any issues you find to the Mindustry GitHub.
mods = Mods
mods.none = [lightgray]No mods found!
mods.guide = Modding Guide
@@ -285,6 +284,7 @@ selectschematic = [accent][[{0}][] to select+copy
pausebuilding = [accent][[{0}][] to pause building
resumebuilding = [scarlet][[{0}][] to resume building
wave = [accent]Wave {0}
+wave.cap = [accent]Wave {0}/{1}
wave.waiting = [lightgray]Wave in {0}
wave.waveInProgress = [lightgray]Wave in progress
waiting = [lightgray]Waiting...
@@ -478,7 +478,7 @@ requirement.research = Research {0}
requirement.capture = Capture {0}
bestwave = [lightgray]Best Wave: {0}
launch.text = Launch
-campaign.multiplayer = While playing multiplayer in campaign, you can only research using items from [accent]your[] sectors, [scarlet]not[] the host's sector that you are on right now.\n\nTo get items to [accent]your[] sectors in multiplayer, use a [accent]launch pad[].
+research.multiplayer = Only the host can research items.
uncover = Uncover
configure = Configure Loadout
#TODO
@@ -512,6 +512,7 @@ weather.rain.name = Rain
weather.snow.name = Snow
weather.sandstorm.name = Sandstorm
weather.sporestorm.name = Sporestorm
+weather.fog.name = Fog
sectors.unexplored = [lightgray]Unexplored
sectors.resources = Resources:
@@ -521,6 +522,11 @@ sectors.resume = Resume
sectors.launch = Launch
sectors.select = Select
sectors.nonelaunch = [lightgray]none (sun)
+sectors.rename = Rename Sector
+
+planet.serpulo.name = Serpulo
+#TODO better name
+planet.sun.name = Sun
#NOTE TO TRANSLATORS: don't bother editing these, they'll be removed and/or rewritten anyway
sector.groundZero.name = Ground Zero
@@ -576,50 +582,73 @@ error.title = [scarlet]An error has occured
error.crashtitle = An error has occured
unit.nobuild = [scarlet]Unit can't build
lastaccessed = [lightgray]Last Accessed: {0}
-blocks.input = Input
-blocks.output = Output
-blocks.booster = Booster
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Power Capacity
-blocks.powershot = Power/Shot
-blocks.damage = Damage
-blocks.targetsair = Targets Air
-blocks.targetsground = Targets Ground
-blocks.itemsmoved = Move Speed
-blocks.launchtime = Time Between Launches
-blocks.shootrange = Range
-blocks.size = Size
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Liquid Capacity
-blocks.powerrange = Power Range
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Max Connections
-blocks.poweruse = Power Use
-blocks.powerdamage = Power/Damage
-blocks.itemcapacity = Item Capacity
-blocks.memorycapacity = Memory Capacity
-blocks.basepowergeneration = Base Power Generation
-blocks.productiontime = Production Time
-blocks.repairtime = Block Full Repair Time
-blocks.speedincrease = Speed Increase
-blocks.range = Range
-blocks.drilltier = Drillables
-blocks.drillspeed = Base Drill Speed
-blocks.boosteffect = Boost Effect
-blocks.maxunits = Max Active Units
-blocks.health = Health
-blocks.buildtime = Build Time
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Build Cost
-blocks.inaccuracy = Inaccuracy
-blocks.shots = Shots
-blocks.reload = Shots/Second
-blocks.ammo = Ammo
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+
+stat.input = Input
+stat.output = Output
+stat.booster = Booster
+stat.tiles = Required Tiles
+stat.affinities = Affinities
+stat.powercapacity = Power Capacity
+stat.powershot = Power/Shot
+stat.damage = Damage
+stat.targetsair = Targets Air
+stat.targetsground = Targets Ground
+stat.itemsmoved = Move Speed
+stat.launchtime = Time Between Launches
+stat.shootrange = Range
+stat.size = Size
+stat.displaysize = Display Size
+stat.liquidcapacity = Liquid Capacity
+stat.powerrange = Power Range
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Max Connections
+stat.poweruse = Power Use
+stat.powerdamage = Power/Damage
+stat.itemcapacity = Item Capacity
+stat.memorycapacity = Memory Capacity
+stat.basepowergeneration = Base Power Generation
+stat.productiontime = Production Time
+stat.repairtime = Block Full Repair Time
+stat.speedincrease = Speed Increase
+stat.range = Range
+stat.drilltier = Drillables
+stat.drillspeed = Base Drill Speed
+stat.boosteffect = Boost Effect
+stat.maxunits = Max Active Units
+stat.health = Health
+stat.buildtime = Build Time
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Build Cost
+stat.inaccuracy = Inaccuracy
+stat.shots = Shots
+stat.reload = Shots/Second
+stat.ammo = Ammo
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
+stat.explosiveness = Explosiveness
+stat.basedeflectchance = Base Deflect Chance
+stat.lightningchance = Lightning Chance
+stat.lightningdamage = Lightning Damage
+stat.flammability = Flammability
+stat.radioactivity = Radioactivity
+stat.heatcapacity = HeatCapacity
+stat.viscosity = Viscosity
+stat.temperature = Temperature
+stat.speed = Speed
+stat.buildspeed = Build Speed
+stat.minespeed = Mine Speed
+stat.minetier = Mine Tier
+stat.payloadcapacity = Payload Capacity
+stat.commandlimit = Command Limit
+stat.abilities = Abilities
+
+ability.forcefield = Force Field
+ability.repairfield = Repair Field
+ability.statusfield = Status Field
+ability.unitspawn = {0} Factory
+ability.shieldregenfield = Shield Regen Field
bar.drilltierreq = Better Drill Required
bar.noresources = Missing Resources
@@ -652,12 +681,15 @@ bullet.homing = [stat]homing
bullet.shock = [stat]shock
bullet.frag = [stat]frag
bullet.knockback = [stat]{0}[lightgray] knockback
+bullet.pierce = [stat]{0}[lightgray]x pierce
+bullet.infinitepierce = [stat]pierce
bullet.freezing = [stat]freezing
bullet.tarred = [stat]tarred
bullet.multiplier = [stat]{0}[lightgray]x ammo multiplier
bullet.reload = [stat]{0}[lightgray]x fire rate
unit.blocks = blocks
+unit.blockssquared = blocks²
unit.powersecond = power units/second
unit.liquidsecond = liquid units/second
unit.itemssecond = items/second
@@ -689,7 +721,6 @@ setting.linear.name = Linear Filtering
setting.hints.name = Hints
setting.flow.name = Display Resource Flow Rate
setting.buildautopause.name = Auto-Pause Building
-setting.mapcenter.name = Auto Center Map To Player
setting.animatedwater.name = Animated Fluids
setting.animatedshields.name = Animated Shields
setting.antialias.name = Antialias[lightgray] (requires restart)[]
@@ -723,7 +754,6 @@ setting.fullscreen.name = Fullscreen
setting.borderlesswindow.name = Borderless Window[lightgray] (restart may be required)
setting.fps.name = Show FPS & Ping
setting.smoothcamera.name = Smooth Camera
-setting.blockselectkeys.name = Show Block Select Keys
setting.vsync.name = VSync
setting.pixelate.name = Pixelate
setting.minimap.name = Show Minimap
@@ -870,6 +900,7 @@ content.item.name = Items
content.liquid.name = Liquids
content.unit.name = Units
content.block.name = Blocks
+
item.copper.name = Copper
item.lead.name = Lead
item.coal.name = Coal
@@ -891,23 +922,6 @@ liquid.slag.name = Slag
liquid.oil.name = Oil
liquid.cryofluid.name = Cryofluid
-item.explosiveness = [lightgray]Explosiveness: {0}%
-item.flammability = [lightgray]Flammability: {0}%
-item.radioactivity = [lightgray]Radioactivity: {0}%
-
-unit.health = [lightgray]Health: {0}
-unit.speed = [lightgray]Speed: {0}
-unit.weapon = [lightgray]Weapon: {0}
-unit.itemcapacity = [lightgray]Item Capacity: {0}
-unit.minespeed = [lightgray]Mining Speed: {0}%
-unit.minepower = [lightgray]Mining Power: {0}
-unit.ability = [lightgray]Ability: {0}
-unit.buildspeed = [lightgray]Building Speed: {0}%
-
-liquid.heatcapacity = [lightgray]Heat Capacity: {0}
-liquid.viscosity = [lightgray]Viscosity: {0}
-liquid.temperature = [lightgray]Temperature: {0}
-
unit.dagger.name = Dagger
unit.mace.name = Mace
unit.fortress.name = Fortress
@@ -1319,5 +1333,4 @@ block.cyclone.description = A large anti-air and anti-ground turret. Fires explo
block.spectre.description = A massive dual-barreled cannon. Shoots large armor-piercing bullets at air and ground targets.
block.meltdown.description = A massive laser cannon. Charges and fires a persistent laser beam at nearby enemies. Requires coolant to operate.
block.repair-point.description = Continuously heals the closest damaged unit in its vicinity.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
-
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_be.properties b/core/assets/bundles/bundle_be.properties
index f62aba4377..590d8094f2 100644
--- a/core/assets/bundles/bundle_be.properties
+++ b/core/assets/bundles/bundle_be.properties
@@ -570,49 +570,49 @@ info.title = Інфармацыя
error.title = [crimson]Адбылася памылка
error.crashtitle = Адбылася памылка
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Уваход
-blocks.output = Выхад
-blocks.booster = Паскаральнік
-blocks.tiles = Неабходныя пліткі
-blocks.affinities = Павелічэнне эфектыўнасці
+stat.input = Уваход
+stat.output = Выхад
+stat.booster = Паскаральнік
+stat.tiles = Неабходныя пліткі
+stat.affinities = Павелічэнне эфектыўнасці
block.unknown = [lightgray]???
-blocks.powercapacity = Умяшчальнасць энергіі
-blocks.powershot = Энергія/Выстрэл
-blocks.damage = Страты
-blocks.targetsair = Паветраныя мэты
-blocks.targetsground = Наземныя мэты
-blocks.itemsmoved = Хуткасць перамяшчэння
-blocks.launchtime = Інтэрвал запускаў
-blocks.shootrange = Радыус дзеяння
-blocks.size = Памер
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Умяшчальнасць вадкасці
-blocks.powerrange = Далёкасць перадачы энергіі
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Колькасць злучэнняў
-blocks.poweruse = Спажывае энергіі
-blocks.powerdamage = Энергія/страты
-blocks.itemcapacity = Умяшчальнасць прадметаў
-blocks.basepowergeneration = Базавая генерацыя энергіі
-blocks.productiontime = Час вытворчасці
-blocks.repairtime = Час поўнай рэгенерацыі
-blocks.speedincrease = Павелічэнне хуткасці
-blocks.range = Радыус дзеяння
-blocks.drilltier = Бурит
-blocks.drillspeed = Базавая хуткасць свідравання
-blocks.boosteffect = паскараўся эфект
-blocks.maxunits = Максімальная колькасць актыўных адзінак
-blocks.health = Здароўе
-blocks.buildtime = Час будаўніцтва
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Кошт будаўніцтва
-blocks.inaccuracy = Роскід
-blocks.shots = Стрэлы
-blocks.reload = Стрэлы/секунду
-blocks.ammo = Боепрыпасы
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Умяшчальнасць энергіі
+stat.powershot = Энергія/Выстрэл
+stat.damage = Страты
+stat.targetsair = Паветраныя мэты
+stat.targetsground = Наземныя мэты
+stat.itemsmoved = Хуткасць перамяшчэння
+stat.launchtime = Інтэрвал запускаў
+stat.shootrange = Радыус дзеяння
+stat.size = Памер
+stat.displaysize = Display Size
+stat.liquidcapacity = Умяшчальнасць вадкасці
+stat.powerrange = Далёкасць перадачы энергіі
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Колькасць злучэнняў
+stat.poweruse = Спажывае энергіі
+stat.powerdamage = Энергія/страты
+stat.itemcapacity = Умяшчальнасць прадметаў
+stat.basepowergeneration = Базавая генерацыя энергіі
+stat.productiontime = Час вытворчасці
+stat.repairtime = Час поўнай рэгенерацыі
+stat.speedincrease = Павелічэнне хуткасці
+stat.range = Радыус дзеяння
+stat.drilltier = Бурит
+stat.drillspeed = Базавая хуткасць свідравання
+stat.boosteffect = паскараўся эфект
+stat.maxunits = Максімальная колькасць актыўных адзінак
+stat.health = Здароўе
+stat.buildtime = Час будаўніцтва
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Кошт будаўніцтва
+stat.inaccuracy = Роскід
+stat.shots = Стрэлы
+stat.reload = Стрэлы/секунду
+stat.ammo = Боепрыпасы
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Патрабуецца свідар лепей
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = Вялікая турэль, якая можа ве
block.spectre.description = Масіўная двуствольное гармата. Страляе буйнымі бранябойнымі кулямі па паветраных і наземных мэтах.
block.meltdown.description = Масіўная лазерная гармата. Зараджае і страляе пастаянным лазерным прамянём ў бліжэйшых ворагаў. Патрабуецца астуджальная вадкасць для працы.
block.repair-point.description = Бесперапынна лечыць бліжэйшую пашкоджаную баявую адзінку або мех у сваім радыусе.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties
index e0c66ff624..f9f98951dc 100644
--- a/core/assets/bundles/bundle_cs.properties
+++ b/core/assets/bundles/bundle_cs.properties
@@ -55,6 +55,7 @@ schematic.saved = Šablona byla uložena.
schematic.delete.confirm = Šablona bude kompletně vyhlazena.
schematic.rename = Přejmenovat šablonu
schematic.info = {0}x{1}, {2} bloků
+schematic.disabled = [scarlet]Šablony jsou zakázány[]\nNa této [accent]mapě[] nebo [accent]serveru[] nemůžeš používat šablony.
stat.wave = Vln poraženo: [accent]{0}
stat.enemiesDestroyed = Nepřátel zničeno: [accent]{0}[]
@@ -346,6 +347,7 @@ waves.invalid = Neplatné vlny ve schránce.
waves.copied = Vlny byly zkopírovány.
waves.none = Žádní nepřátelé nebyli definováni.\nVlny s prázdným rozložením budou automaticky upraveny na výchozí rozložení.
+#these are intentionally in lower case
wavemode.counts = počty
wavemode.totals = součty
wavemode.health = zdraví
@@ -471,22 +473,17 @@ requirement.wave = Dosáhni vlny {0} na mapě {1}
requirement.core = Znič nepřátelské jádro na mapě {0}
requirement.research = Vynalezeno {0}
requirement.capture = Polapeno {0}
-resume = Zpět do mapy:\n[lightgray]{0}[]
bestwave = [lightgray]Nejvyšší vlna: {0}
-launch = < VYSLAT >
launch.text = Vyslat
-launch.title = Vyslání bylo úspěšné
-launch.next = [lightgray]další možnost bude až ve vlně {0}[]
-launch.unable2 = [scarlet]Není možno se vyslat.[]
-launch.confirm = Toto vyšle veškeré suroviny ve Tvém jádře zpět.\nJiž se na tuto základnu nebudeš moci vrátit.
-launch.skip.confirm = Jestli teď zůstaneš, budeš moci odejít až po několika dalších vlnách.
+campaign.multiplayer = Když hraješ kampaň ve hře více hráčů, můžeš vynalézat pouze pomocí věcí ze [accent]svých[] sektorů, [scarlet]ne[] ze sektoru hostitele, kde jsi právě teď.\n\nAbys získal věci do [accent]svých[] sektorů ve hře více hráčů, použij [accent]vysílací plošinu[].
uncover = Odkrýt mapu
configure = Přizpůsobit vybavení
+#TODO
loadout = Načtení
resources = Zdroje
bannedblocks = Zakázané bloky
addall = Přidat vše
-launch.destination = Destination: {0}
+launch.destination = Cíl: {0}
configure.invalid = Hodnota musí být číslo mezi 0 a {0}.
zone.unlocked = [lightgray]Mapa {0} byla odemknuta.[]
zone.requirement.complete = Bylo dosaženo vlny {0},\nčímž byla splněna podmínka pro mapu {1}.
@@ -519,9 +516,10 @@ sectors.production = Výroba:
sectors.stored = Uskladněno:
sectors.resume = Pokračovat
sectors.launch = Vyslat
-sectors.select = Select
-sectors.nonelaunch = [lightgray]none (sun)
+sectors.select = Vybrat
+sectors.nonelaunch = [lightgray]žádné (slunce)[]
+#NOTE TO TRANSLATORS: don't bother editing these, they'll be removed and/or rewritten anyway
sector.groundZero.name = Základní tábor
sector.craters.name = Krátery
sector.frozenForest.name = Zamrzlý les
@@ -534,6 +532,10 @@ sector.tarFields.name = Dehtová pole
sector.saltFlats.name = Solné nížiny
sector.fungalPass.name = Plísňový průsmyk
+#unused
+#sector.impact0078.name = Impact 0078
+#sector.crags.name = Crags
+
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.
sector.saltFlats.description = Na okraji pouště leží Solné nížiny. V této lokaci se nachází jen několik málo surovin.\n\nNepřítel zde vybudoval zásobovací komplex. Znič jádro v jeho základně. Nenechej kámen na kameni.
@@ -570,49 +572,50 @@ info.title = Informace
error.title = [scarlet]Objevila se chyba[]
error.crashtitle = Objevila se chyba
unit.nobuild = [scarlet]Jednotka nemůže stavět
-blocks.input = Vstup
-blocks.output = Výstup
-blocks.booster = Posilovač
-blocks.tiles = Vyžadované dlaždice
-blocks.affinities = Synergie
+stat.input = Vstup
+stat.output = Výstup
+stat.booster = Posilovač
+stat.tiles = Vyžadované dlaždice
+stat.affinities = Synergie
block.unknown = [lightgray]???[]
-blocks.powercapacity = Kapacita energie
-blocks.powershot = Energie na 1 výstřel
-blocks.damage = Poškození
-blocks.targetsair = Zaměřuje vzdušné jednotky
-blocks.targetsground = Zaměřuje pozemní jednotky
-blocks.itemsmoved = Rychlost pohybu
-blocks.launchtime = Čas mezi vysláním
-blocks.shootrange = Dostřel
-blocks.size = Velikost
-blocks.displaysize = Velikost zobrazovače
-blocks.liquidcapacity = Kapacita kapalin
-blocks.powerrange = Rozsah energie
-blocks.linkrange = Dosah napojení
-blocks.instructions = Instrukce
-blocks.powerconnections = Nejvyšší počet spojení
-blocks.poweruse = Spotřeba energie
-blocks.powerdamage = Energie na jednotku poškození
-blocks.itemcapacity = Kapacita předmětů
-blocks.basepowergeneration = Základní generování energie
-blocks.productiontime = Čas produkce
-blocks.repairtime = Čas do úplné opravy
-blocks.speedincrease = Zvýšení rychlosti
-blocks.range = Dosah
-blocks.drilltier = Lze těžit
-blocks.drillspeed = Základní rychlost vrtu
-blocks.boosteffect = Účinek posílení
-blocks.maxunits = Nejvýše aktivních jednotek
-blocks.health = Životy
-blocks.buildtime = Čas stavby
-blocks.maxconsecutive = Nejvýše po sobě
-blocks.buildcost = Cena stavby
-blocks.inaccuracy = Nepřesnost
-blocks.shots = Střely
-blocks.reload = Střel za 1s
-blocks.ammo = Střelivo
-blocks.shieldhealth = Zdraví štítu
-blocks.cooldowntime = Čas na zchladnutí
+stat.powercapacity = Kapacita energie
+stat.powershot = Energie na 1 výstřel
+stat.damage = Poškození
+stat.targetsair = Zaměřuje vzdušné jednotky
+stat.targetsground = Zaměřuje pozemní jednotky
+stat.itemsmoved = Rychlost pohybu
+stat.launchtime = Čas mezi vysláním
+stat.shootrange = Dostřel
+stat.size = Velikost
+stat.displaysize = Velikost zobrazovače
+stat.liquidcapacity = Kapacita kapalin
+stat.powerrange = Rozsah energie
+stat.linkrange = Dosah napojení
+stat.instructions = Instrukce
+stat.powerconnections = Nejvyšší počet spojení
+stat.poweruse = Spotřeba energie
+stat.powerdamage = Energie na jednotku poškození
+stat.itemcapacity = Kapacita předmětů
+stat.memorycapacity = Kapacita paměti
+stat.basepowergeneration = Základní generování energie
+stat.productiontime = Čas produkce
+stat.repairtime = Čas do úplné opravy
+stat.speedincrease = Zvýšení rychlosti
+stat.range = Dosah
+stat.drilltier = Lze těžit
+stat.drillspeed = Základní rychlost vrtu
+stat.boosteffect = Účinek posílení
+stat.maxunits = Nejvýše aktivních jednotek
+stat.health = Životy
+stat.buildtime = Čas stavby
+stat.maxconsecutive = Nejvýše po sobě
+stat.buildcost = Cena stavby
+stat.inaccuracy = Nepřesnost
+stat.shots = Střely
+stat.reload = Střel za 1s
+stat.ammo = Střelivo
+stat.shieldhealth = Zdraví štítu
+stat.cooldowntime = Čas na zchladnutí
bar.drilltierreq = Je vyžadován lepší vrt
bar.noresources = Chybějí zdroje
@@ -635,6 +638,8 @@ bar.progress = Stavba v průběhu
bar.input = Vstup
bar.output = Výstup
+units.processorcontrol = [lightgray]Procesor je ovládán[]
+
bullet.damage = [stat]{0}[lightgray] poškození[]
bullet.splashdamage = [stat]{0}[lightgray] plošného poškození ~[stat] {1}[lightgray] dlaždic
bullet.incendiary = [stat]zápalné
@@ -822,6 +827,7 @@ mode.custom = Vlastní pravidla
rules.infiniteresources = Neomezeně surovin
rules.reactorexplosions = Výbuch reaktoru
+rules.schematic = Šablony povoleny
rules.wavetimer = Časovač vln
rules.waves = Vlny
rules.attack = Režim útoku
@@ -846,7 +852,8 @@ rules.title.enemy = Nepřátelé
rules.title.unit = Jednotky
rules.title.experimental = Experimentální
rules.title.environment = Environmentální
-rules.lighting = Světlo
+rules.lighting = Osvětlení
+rules.enemyLights = Světla nepřátel
rules.fire = Výstřel
rules.explosions = Výbušné poškození bloku/jednotky
rules.ambientlight = Světlo prostředí
@@ -915,8 +922,8 @@ unit.eclipse.name = Zatmění
unit.mono.name = Mono
unit.poly.name = Poly
unit.mega.name = Mega
-unit.quad.name = Quad
-unit.oct.name = Oct
+unit.quad.name = Tetra
+unit.oct.name = Hexo
unit.risso.name = Risso
unit.minke.name = Minke
unit.bryde.name = Bryde
@@ -928,7 +935,7 @@ unit.gamma.name = Gama
unit.scepter.name = Žezlo
unit.reign.name = Panovník
unit.vela.name = Vela
-unit.corvus.name = Corvus
+unit.corvus.name = Havran
block.resupply-point.name = Zásobovací místo
block.parallax.name = Paralaxa
@@ -1076,6 +1083,7 @@ block.unloader.name = Odbavovač
block.vault.name = Trezor
block.wave.name = Vlna
block.swarmer.name = Rojiště
+block.tsunami.name = Tsunami
block.salvo.name = Salva
block.ripple.name = Vlnění
block.phase-conveyor.name = Fázový přepravník
@@ -1112,8 +1120,9 @@ block.overdrive-projector.name = Urychlující projektor
block.force-projector.name = Silový projektor
block.arc.name = Oblouk
block.rtg-generator.name = RTG
-block.spectre.name = Spectre
-block.meltdown.name = Meltdown
+block.spectre.name = Přízrak
+block.meltdown.name = Rozpékač
+block.foreshadow.name = Znamení osudu
block.container.name = Kontejnér
block.launch-pad.name = Vysílací plošina
block.launch-pad-large.name = Velká vysílací plošina
@@ -1139,6 +1148,7 @@ block.hyper-processor.name = Hyperprocesor
block.logic-display.name = Zobrazovač logiky
block.large-logic-display.name = Velký zobrazovač logiky
block.memory-cell.name = Paměťová buňka
+block.memory-bank.name = Paměťová banka
team.blue.name = modrý
team.crux.name = červený
@@ -1302,4 +1312,4 @@ block.cyclone.description = Velká protiletecká a protipozemní střílna. Pál
block.spectre.description = Velká střílna s kanónem s dvěma hlavněmi. Střílí velké náboje, které pronikají brněním jak pozemních, tak vzdušných nepřátelských cílů.
block.meltdown.description = Masivní laserový kanón. Nabije se a pak pálí nepřetržitý laserový paprsek na nepřátele v okolí. Vyžaduje ke své funkci chlazení.
block.repair-point.description = Nepřetržitě léčí nejbližší poškozenou jednotku v poli své působnosti.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_da.properties b/core/assets/bundles/bundle_da.properties
index 0e9d2ce889..b65afebcd3 100644
--- a/core/assets/bundles/bundle_da.properties
+++ b/core/assets/bundles/bundle_da.properties
@@ -570,49 +570,49 @@ info.title = Info
error.title = [crimson]An error has occured
error.crashtitle = An error has occured
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Input
-blocks.output = Output
-blocks.booster = Booster
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Input
+stat.output = Output
+stat.booster = Booster
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Power Capacity
-blocks.powershot = Power/Shot
-blocks.damage = Damage
-blocks.targetsair = Targets Air
-blocks.targetsground = Targets Ground
-blocks.itemsmoved = Move Speed
-blocks.launchtime = Time Between Launches
-blocks.shootrange = Range
-blocks.size = Size
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Liquid Capacity
-blocks.powerrange = Power Range
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Max Connections
-blocks.poweruse = Power Use
-blocks.powerdamage = Power/Damage
-blocks.itemcapacity = Item Capacity
-blocks.basepowergeneration = Base Power Generation
-blocks.productiontime = Production Time
-blocks.repairtime = Block Full Repair Time
-blocks.speedincrease = Speed Increase
-blocks.range = Range
-blocks.drilltier = Drillables
-blocks.drillspeed = Base Drill Speed
-blocks.boosteffect = Boost Effect
-blocks.maxunits = Max Active Units
-blocks.health = Health
-blocks.buildtime = Build Time
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Build Cost
-blocks.inaccuracy = Inaccuracy
-blocks.shots = Shots
-blocks.reload = Shots/Second
-blocks.ammo = Ammo
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Power Capacity
+stat.powershot = Power/Shot
+stat.damage = Damage
+stat.targetsair = Targets Air
+stat.targetsground = Targets Ground
+stat.itemsmoved = Move Speed
+stat.launchtime = Time Between Launches
+stat.shootrange = Range
+stat.size = Size
+stat.displaysize = Display Size
+stat.liquidcapacity = Liquid Capacity
+stat.powerrange = Power Range
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Max Connections
+stat.poweruse = Power Use
+stat.powerdamage = Power/Damage
+stat.itemcapacity = Item Capacity
+stat.basepowergeneration = Base Power Generation
+stat.productiontime = Production Time
+stat.repairtime = Block Full Repair Time
+stat.speedincrease = Speed Increase
+stat.range = Range
+stat.drilltier = Drillables
+stat.drillspeed = Base Drill Speed
+stat.boosteffect = Boost Effect
+stat.maxunits = Max Active Units
+stat.health = Health
+stat.buildtime = Build Time
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Build Cost
+stat.inaccuracy = Inaccuracy
+stat.shots = Shots
+stat.reload = Shots/Second
+stat.ammo = Ammo
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Better Drill Required
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = A large anti-air and anti-ground turret. Fires explo
block.spectre.description = A massive dual-barreled cannon. Shoots large armor-piercing bullets at air and ground targets.
block.meltdown.description = A massive laser cannon. Charges and fires a persistent laser beam at nearby enemies. Requires coolant to operate.
block.repair-point.description = Continuously heals the closest damaged unit in its vicinity.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties
index 67311e3451..5d02ed2f85 100644
--- a/core/assets/bundles/bundle_de.properties
+++ b/core/assets/bundles/bundle_de.properties
@@ -570,49 +570,49 @@ info.title = Info
error.title = [crimson]Ein Fehler ist aufgetreten
error.crashtitle = Ein Fehler ist aufgetreten!
unit.nobuild = [scarlet]Einheit kann nicht bauen!
-blocks.input = Eingang
-blocks.output = Ausgang
-blocks.booster = Verstärkung
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Eingang
+stat.output = Ausgang
+stat.booster = Verstärkung
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Kapazität
-blocks.powershot = Stromverbrauch/Schuss
-blocks.damage = Schaden
-blocks.targetsair = Visiert Lufteinheiten an
-blocks.targetsground = Visiert Bodeneinheiten an
-blocks.itemsmoved = Bewegungsgeschwindigkeit
-blocks.launchtime = Zeit zwischen Starts
-blocks.shootrange = Reichweite
-blocks.size = Größe
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Flüssigkeitskapazität
-blocks.powerrange = Stromreichweite
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Maximale Stromverbindungen
-blocks.poweruse = Stromverbrauch
-blocks.powerdamage = Stromverbrauch/Schadenspunkt
-blocks.itemcapacity = Materialkapazität
-blocks.basepowergeneration = Basis-Stromerzeugung
-blocks.productiontime = Produktionszeit
-blocks.repairtime = Zeit zur vollständigen Reparatur
-blocks.speedincrease = Geschwindigkeitserhöhung
-blocks.range = Reichweite
-blocks.drilltier = Abbaubare Erze
-blocks.drillspeed = Bohrgeschwindigkeit
-blocks.boosteffect = Verstärkungseffekt
-blocks.maxunits = Max. aktive Einheiten
-blocks.health = Lebenspunkte
-blocks.buildtime = Baudauer
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Baukosten
-blocks.inaccuracy = Ungenauigkeit
-blocks.shots = Schüsse
-blocks.reload = Schüsse/Sekunde
-blocks.ammo = Munition
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Kapazität
+stat.powershot = Stromverbrauch/Schuss
+stat.damage = Schaden
+stat.targetsair = Visiert Lufteinheiten an
+stat.targetsground = Visiert Bodeneinheiten an
+stat.itemsmoved = Bewegungsgeschwindigkeit
+stat.launchtime = Zeit zwischen Starts
+stat.shootrange = Reichweite
+stat.size = Größe
+stat.displaysize = Display Size
+stat.liquidcapacity = Flüssigkeitskapazität
+stat.powerrange = Stromreichweite
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Maximale Stromverbindungen
+stat.poweruse = Stromverbrauch
+stat.powerdamage = Stromverbrauch/Schadenspunkt
+stat.itemcapacity = Materialkapazität
+stat.basepowergeneration = Basis-Stromerzeugung
+stat.productiontime = Produktionszeit
+stat.repairtime = Zeit zur vollständigen Reparatur
+stat.speedincrease = Geschwindigkeitserhöhung
+stat.range = Reichweite
+stat.drilltier = Abbaubare Erze
+stat.drillspeed = Bohrgeschwindigkeit
+stat.boosteffect = Verstärkungseffekt
+stat.maxunits = Max. aktive Einheiten
+stat.health = Lebenspunkte
+stat.buildtime = Baudauer
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Baukosten
+stat.inaccuracy = Ungenauigkeit
+stat.shots = Schüsse
+stat.reload = Schüsse/Sekunde
+stat.ammo = Munition
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Besserer Bohrer Benötigt
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = Ein großer Schnellfeuer-Geschützturm.
block.spectre.description = Ein großer Geschützturm, der zwei starke Schüsse gleichzeitig abfeuert.
block.meltdown.description = Ein großer Geschützturm, der starke Strahlen mit großer Reichweite abfeuert.
block.repair-point.description = Heilt durchgehend die nächste befreundete, beschädigte Einheit in der Umgebung.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties
index 8c538a6974..6c24039d7e 100644
--- a/core/assets/bundles/bundle_es.properties
+++ b/core/assets/bundles/bundle_es.properties
@@ -2,14 +2,14 @@ credits.text = Creado por [royal]Anuken[] - [sky]anukendev@gmail.com[]
credits = Créditos
contributors = Traductores y Contribuidores
discord = ¡Únete al Discord de Mindustry!
-link.discord.description = La sala oficial del Discord de Mindustry
+link.discord.description = El servidor official de Discord de Mindustry
link.reddit.description = El subreddit de Mindustry
link.github.description = Código fuente del juego
link.changelog.description = Lista de actualizaciones
-link.dev-builds.description = Versiones de desarrollo inestables
+link.dev-builds.description = Versiones en desarrollo inestables
link.trello.description = Tablero de Trello oficial para las características planificadas
link.itch.io.description = itch.io es la página donde podes descargar las versiones para PC y web
-link.google-play.description = Ficha en la Google Play Store
+link.google-play.description = Página de Mindustry en Google Play Store
link.f-droid.description = Página de F-Droid del juego
link.wiki.description = Wiki oficial de Mindustry
link.suggestions.description = Sugerir nuevas funciones
@@ -18,7 +18,7 @@ screenshot = Captura de pantalla guardada en {0}
screenshot.invalid = Mapa demasiado grande, no hay suficiente memoria para la captura de pantalla.
gameover = Tu núcleo ha sido destruido.
gameover.pvp = ¡El equipo[accent] {0}[] ha ganado!
-highscore = [accent]¡Nueva mejor puntuación!
+highscore = [accent]¡Nuevo récord de puntuación!
copied = Copiado.
indev.popup = [accent]v6[] is currently in [accent]alpha[].\n[lightgray]This means:[]\n[scarlet]- The campaign is completely unfinished[]\n- Content is missing\n - Most [scarlet]Unit AI[] does not work properly\n- Many units are unfinished\n- Everything you see is subject to change or removal.\n\nReport bugs or crashes on [accent]Github[].
indev.notready = This part of the game isn't ready yet
@@ -38,12 +38,12 @@ be.ignore = Ignorar
be.noupdates = No se encontraron actualizaciones.
be.check = Revisando actualizaciones
-schematic = Esquemático
-schematic.add = Guardar esquemático...
-schematics = Esquemáticos
-schematic.replace = Un esquemático con ese nombre ya existe. ¿Deseas remplazarlo?
-schematic.exists = Un esquemático con ese nombre ya existe.
-schematic.import = Importar esquemático...
+schematic = Esquema
+schematic.add = Guardar esquema...
+schematics = Esquemas
+schematic.replace = Un esquema con ese nombre ya existe. ¿Deseas remplazarlo?
+schematic.exists = Un esquema con ese nombre ya existe.
+schematic.import = Importar esquema...
schematic.exportfile = Exportar archivo
schematic.importfile = Importar archivo
schematic.browseworkshop = Buscar en el Steam Workshop
@@ -570,49 +570,49 @@ info.title = [accent]Información
error.title = [crimson]Un error ha ocurrido.
error.crashtitle = Un error ha ocurrido.
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Entrada
-blocks.output = Salida
-blocks.booster = Potenciador
-blocks.tiles = Tiles requeridos
-blocks.affinities = Afinidades
+stat.input = Entrada
+stat.output = Salida
+stat.booster = Potenciador
+stat.tiles = Tiles requeridos
+stat.affinities = Afinidades
block.unknown = [lightgray]???
-blocks.powercapacity = Capacidad de Energía
-blocks.powershot = Energía/Disparo
-blocks.damage = Daño
-blocks.targetsair = Apunta al Aire
-blocks.targetsground = Apunta a Tierra
-blocks.itemsmoved = Velocidad de movimiento
-blocks.launchtime = Tiempo entre lanzamientos
-blocks.shootrange = Rango de Disparo
-blocks.size = Tamaño
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Capacidad de Líquidos
-blocks.powerrange = Rango de Energía
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Conexiones maximas
-blocks.poweruse = Consumo de Energía
-blocks.powerdamage = Energía/Daño
-blocks.itemcapacity = Capacidad de Objetos
-blocks.basepowergeneration = Generación de energía base
-blocks.productiontime = Tiempo de producción
-blocks.repairtime = Tiempo para Reparar Bloque Completamente
-blocks.speedincrease = Aumento de Velocidad
-blocks.range = Rango
-blocks.drilltier = Taladrables
-blocks.drillspeed = Velocidad Base del Taladro
-blocks.boosteffect = Efecto del Potenciador
-blocks.maxunits = Máximo de Unidades Activas
-blocks.health = Vida
-blocks.buildtime = Tiempo de construcción
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Coste de construcción
-blocks.inaccuracy = Imprecisión
-blocks.shots = Disparos
-blocks.reload = Recarga
-blocks.ammo = Munición
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Capacidad de Energía
+stat.powershot = Energía/Disparo
+stat.damage = Daño
+stat.targetsair = Apunta al Aire
+stat.targetsground = Apunta a Tierra
+stat.itemsmoved = Velocidad de movimiento
+stat.launchtime = Tiempo entre lanzamientos
+stat.shootrange = Rango de Disparo
+stat.size = Tamaño
+stat.displaysize = Display Size
+stat.liquidcapacity = Capacidad de Líquidos
+stat.powerrange = Rango de Energía
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Conexiones maximas
+stat.poweruse = Consumo de Energía
+stat.powerdamage = Energía/Daño
+stat.itemcapacity = Capacidad de Objetos
+stat.basepowergeneration = Generación de energía base
+stat.productiontime = Tiempo de producción
+stat.repairtime = Tiempo para Reparar Bloque Completamente
+stat.speedincrease = Aumento de Velocidad
+stat.range = Rango
+stat.drilltier = Taladrables
+stat.drillspeed = Velocidad Base del Taladro
+stat.boosteffect = Efecto del Potenciador
+stat.maxunits = Máximo de Unidades Activas
+stat.health = Vida
+stat.buildtime = Tiempo de construcción
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Coste de construcción
+stat.inaccuracy = Imprecisión
+stat.shots = Disparos
+stat.reload = Recarga
+stat.ammo = Munición
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Se requiere un mejor taladro.
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = Una torre grande anti-aérea y anti-terrestre. Dispa
block.spectre.description = Un cañon masivo de dos barriles. Dispara balas perforantes a objetivos de aire y tierra.
block.meltdown.description = Un cañon láser masivo. Carga y dispara un rayo láser constante a enemigos cercanos. Requiere enfriamiento para operar.
block.repair-point.description = Repara la unidad dañada más cercana a su alrededor.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_et.properties b/core/assets/bundles/bundle_et.properties
index d5ac8cfb74..62b0002df6 100644
--- a/core/assets/bundles/bundle_et.properties
+++ b/core/assets/bundles/bundle_et.properties
@@ -570,49 +570,49 @@ info.title = Info
error.title = [crimson]Viga
error.crashtitle = Viga
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Sisend
-blocks.output = Väljund
-blocks.booster = Kiirendaja
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Sisend
+stat.output = Väljund
+stat.booster = Kiirendaja
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Energiamahtuvus
-blocks.powershot = Energia ühikut/lasu kohta
-blocks.damage = Hävituspunkte
-blocks.targetsair = Sihib õhku
-blocks.targetsground = Sihib maapinnale
-blocks.itemsmoved = Transportimise kiirus
-blocks.launchtime = Aeg lendutõusude vahel
-blocks.shootrange = Ulatus
-blocks.size = Suurus
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Vedelike mahutavus
-blocks.powerrange = Energia ulatus
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Max Connections
-blocks.poweruse = Energiatarve
-blocks.powerdamage = Energiatarve hävituspunkti kohta
-blocks.itemcapacity = Ressursside mahutavus
-blocks.basepowergeneration = Energiatootlus
-blocks.productiontime = Tootmisaeg
-blocks.repairtime = Täieliku parandamise aeg
-blocks.speedincrease = Kiiruse suurenemine
-blocks.range = Ulatus
-blocks.drilltier = Kaevandatav
-blocks.drillspeed = Puurimise kiirus
-blocks.boosteffect = Kiirendaja mõju
-blocks.maxunits = Maks. aktiivseid väeüksuseid
-blocks.health = Elud
-blocks.buildtime = Ehitamise aeg
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Ehitamise maksumus
-blocks.inaccuracy = Ebatäpsus
-blocks.shots = Laske
-blocks.reload = Lasku/s
-blocks.ammo = Laskemoon
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Energiamahtuvus
+stat.powershot = Energia ühikut/lasu kohta
+stat.damage = Hävituspunkte
+stat.targetsair = Sihib õhku
+stat.targetsground = Sihib maapinnale
+stat.itemsmoved = Transportimise kiirus
+stat.launchtime = Aeg lendutõusude vahel
+stat.shootrange = Ulatus
+stat.size = Suurus
+stat.displaysize = Display Size
+stat.liquidcapacity = Vedelike mahutavus
+stat.powerrange = Energia ulatus
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Max Connections
+stat.poweruse = Energiatarve
+stat.powerdamage = Energiatarve hävituspunkti kohta
+stat.itemcapacity = Ressursside mahutavus
+stat.basepowergeneration = Energiatootlus
+stat.productiontime = Tootmisaeg
+stat.repairtime = Täieliku parandamise aeg
+stat.speedincrease = Kiiruse suurenemine
+stat.range = Ulatus
+stat.drilltier = Kaevandatav
+stat.drillspeed = Puurimise kiirus
+stat.boosteffect = Kiirendaja mõju
+stat.maxunits = Maks. aktiivseid väeüksuseid
+stat.health = Elud
+stat.buildtime = Ehitamise aeg
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Ehitamise maksumus
+stat.inaccuracy = Ebatäpsus
+stat.shots = Laske
+stat.reload = Lasku/s
+stat.ammo = Laskemoon
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Nõuab paremat puuri
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = Suur lendavate ja maapealsete väeüksuste vastane k
block.spectre.description = Massiivne kaheraudne kahur, mis tulistab soomuskatteid läbistavaid mürske nii lendavate kui ka maapealsete väeüksuste pihta.
block.meltdown.description = Massiivne laserkahur, mis tekitab püsiva energiakiire. Vajab töötamiseks jahutusvedelikku.
block.repair-point.description = Parandab kõige lähemal asuvat liitlaste väeüksust.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_eu.properties b/core/assets/bundles/bundle_eu.properties
index 5ef1a41b71..7afde97031 100644
--- a/core/assets/bundles/bundle_eu.properties
+++ b/core/assets/bundles/bundle_eu.properties
@@ -570,49 +570,49 @@ info.title = Informazioa
error.title = [crimson]Errore bat gertatu da
error.crashtitle = Errore bat gertatu da
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Sarrera
-blocks.output = Irteera
-blocks.booster = Indargarria
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Sarrera
+stat.output = Irteera
+stat.booster = Indargarria
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Energia-edukiera
-blocks.powershot = Energia/tiroko
-blocks.damage = Kaltea
-blocks.targetsair = Airera tirokatzen du
-blocks.targetsground = Lurrera tirokatzen du
-blocks.itemsmoved = Garraio-abiadura
-blocks.launchtime = Egozketen arteko denbora
-blocks.shootrange = Irismena
-blocks.size = Neurria
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Likido-edukiera
-blocks.powerrange = Energia irismena
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Gehieneko konexioak
-blocks.poweruse = Energia-erabilera
-blocks.powerdamage = Energia/Kaltea
-blocks.itemcapacity = Elementu-edukiera
-blocks.basepowergeneration = Oinarrizko energia sorrera
-blocks.productiontime = Eraikitze denbora
-blocks.repairtime = Blokearen konpontze denbora osoa
-blocks.speedincrease = Abiadura areagotzea
-blocks.range = Irismena
-blocks.drilltier = Ustiagarriak
-blocks.drillspeed = Oinarrizko ustiatze-abiadura
-blocks.boosteffect = Indartze-efektua
-blocks.maxunits = Gehieneko unitate aktiboak
-blocks.health = Osasuna
-blocks.buildtime = Eraikitze-denbora
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Eraikitze-kostua
-blocks.inaccuracy = Zehazgabetasuna
-blocks.shots = Tiroak
-blocks.reload = Tiroak/segundoko
-blocks.ammo = Munizioa
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Energia-edukiera
+stat.powershot = Energia/tiroko
+stat.damage = Kaltea
+stat.targetsair = Airera tirokatzen du
+stat.targetsground = Lurrera tirokatzen du
+stat.itemsmoved = Garraio-abiadura
+stat.launchtime = Egozketen arteko denbora
+stat.shootrange = Irismena
+stat.size = Neurria
+stat.displaysize = Display Size
+stat.liquidcapacity = Likido-edukiera
+stat.powerrange = Energia irismena
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Gehieneko konexioak
+stat.poweruse = Energia-erabilera
+stat.powerdamage = Energia/Kaltea
+stat.itemcapacity = Elementu-edukiera
+stat.basepowergeneration = Oinarrizko energia sorrera
+stat.productiontime = Eraikitze denbora
+stat.repairtime = Blokearen konpontze denbora osoa
+stat.speedincrease = Abiadura areagotzea
+stat.range = Irismena
+stat.drilltier = Ustiagarriak
+stat.drillspeed = Oinarrizko ustiatze-abiadura
+stat.boosteffect = Indartze-efektua
+stat.maxunits = Gehieneko unitate aktiboak
+stat.health = Osasuna
+stat.buildtime = Eraikitze-denbora
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Eraikitze-kostua
+stat.inaccuracy = Zehazgabetasuna
+stat.shots = Tiroak
+stat.reload = Tiroak/segundoko
+stat.ammo = Munizioa
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Zulagailu hobea behar da
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = Aire zein lurreko defentsarako dorre handia. Torpedo
block.spectre.description = Kanoi bikoitz erraldoia. Blindajea zulatu dezaketen bala handiak tirokatzen ditu aireko zein lurreko xedeei.
block.meltdown.description = Laser kanoi erraldoia. Etengabeko laser izpi bat kargatu eta jauritzen die inguruko etsaiei. Hozgarria behar du jarduteko.
block.repair-point.description = Etengabe konpontzen du inguruko kaltetutako unitate hurbilena.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_fi.properties b/core/assets/bundles/bundle_fi.properties
index ae351b8764..30a231333c 100644
--- a/core/assets/bundles/bundle_fi.properties
+++ b/core/assets/bundles/bundle_fi.properties
@@ -570,49 +570,49 @@ info.title = Informaatio
error.title = [crimson]An error has occured
error.crashtitle = An error has occured
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Sisääntulo
-blocks.output = Ulostulo
-blocks.booster = Tehostaja
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Sisääntulo
+stat.output = Ulostulo
+stat.booster = Tehostaja
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Energiakapasiteetti
-blocks.powershot = Energiaa/Ammus
-blocks.damage = Vahinko
-blocks.targetsair = Hyökkää ilmaan
-blocks.targetsground = Hyökkää maahan
-blocks.itemsmoved = Liikkumisnopeus
-blocks.launchtime = Aika laukaisujen välillä
-blocks.shootrange = Kantama
-blocks.size = Koko
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Nestekapasiteetti
-blocks.powerrange = Energiakantama
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Maksimimäärä yhdistyksiä
-blocks.poweruse = Energian käyttö
-blocks.powerdamage = Energia/Vahinko
-blocks.itemcapacity = Tavarakapasiteetti
-blocks.basepowergeneration = Perus energiantuotto
-blocks.productiontime = Tuotantoaika
-blocks.repairtime = Kokonaisen palikan korjausaika
-blocks.speedincrease = Nopeuden kasvu
-blocks.range = Etäisyys
-blocks.drilltier = Porattavat
-blocks.drillspeed = Kanta Poran Nopeus
-blocks.boosteffect = Tehostamisem vaikutus
-blocks.maxunits = Maksimimäärä yksikköjä
-blocks.health = Elämäpisteet
-blocks.buildtime = Rakentamisaika
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Rakentamishinta
-blocks.inaccuracy = Epätarkkuus
-blocks.shots = Ammusta
-blocks.reload = Ammusta/sekunnissa
-blocks.ammo = Ammus
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Energiakapasiteetti
+stat.powershot = Energiaa/Ammus
+stat.damage = Vahinko
+stat.targetsair = Hyökkää ilmaan
+stat.targetsground = Hyökkää maahan
+stat.itemsmoved = Liikkumisnopeus
+stat.launchtime = Aika laukaisujen välillä
+stat.shootrange = Kantama
+stat.size = Koko
+stat.displaysize = Display Size
+stat.liquidcapacity = Nestekapasiteetti
+stat.powerrange = Energiakantama
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Maksimimäärä yhdistyksiä
+stat.poweruse = Energian käyttö
+stat.powerdamage = Energia/Vahinko
+stat.itemcapacity = Tavarakapasiteetti
+stat.basepowergeneration = Perus energiantuotto
+stat.productiontime = Tuotantoaika
+stat.repairtime = Kokonaisen palikan korjausaika
+stat.speedincrease = Nopeuden kasvu
+stat.range = Etäisyys
+stat.drilltier = Porattavat
+stat.drillspeed = Kanta Poran Nopeus
+stat.boosteffect = Tehostamisem vaikutus
+stat.maxunits = Maksimimäärä yksikköjä
+stat.health = Elämäpisteet
+stat.buildtime = Rakentamisaika
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Rakentamishinta
+stat.inaccuracy = Epätarkkuus
+stat.shots = Ammusta
+stat.reload = Ammusta/sekunnissa
+stat.ammo = Ammus
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Parempi pora vaadittu
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = A large anti-air and anti-ground turret. Fires explo
block.spectre.description = A massive dual-barreled cannon. Shoots large armor-piercing bullets at air and ground targets.
block.meltdown.description = A massive laser cannon. Charges and fires a persistent laser beam at nearby enemies. Requires coolant to operate.
block.repair-point.description = Continuously heals the closest damaged unit in its vicinity.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_fil.properties b/core/assets/bundles/bundle_fil.properties
index 86c3c0737a..0fa6608526 100644
--- a/core/assets/bundles/bundle_fil.properties
+++ b/core/assets/bundles/bundle_fil.properties
@@ -570,49 +570,49 @@ info.title = Info
error.title = [scarlet]An error has occured
error.crashtitle = An error has occured
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Input
-blocks.output = Output
-blocks.booster = Booster
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Input
+stat.output = Output
+stat.booster = Booster
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Power Capacity
-blocks.powershot = Power/Shot
-blocks.damage = Damage
-blocks.targetsair = Targets Air
-blocks.targetsground = Targets Ground
-blocks.itemsmoved = Move Speed
-blocks.launchtime = Time Between Launches
-blocks.shootrange = Range
-blocks.size = Size
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Liquid Capacity
-blocks.powerrange = Power Range
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Max Connections
-blocks.poweruse = Power Use
-blocks.powerdamage = Power/Damage
-blocks.itemcapacity = Item Capacity
-blocks.basepowergeneration = Base Power Generation
-blocks.productiontime = Production Time
-blocks.repairtime = Block Full Repair Time
-blocks.speedincrease = Speed Increase
-blocks.range = Range
-blocks.drilltier = Drillables
-blocks.drillspeed = Base Drill Speed
-blocks.boosteffect = Boost Effect
-blocks.maxunits = Max Active Units
-blocks.health = Health
-blocks.buildtime = Build Time
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Build Cost
-blocks.inaccuracy = Inaccuracy
-blocks.shots = Shots
-blocks.reload = Shots/Second
-blocks.ammo = Ammo
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Power Capacity
+stat.powershot = Power/Shot
+stat.damage = Damage
+stat.targetsair = Targets Air
+stat.targetsground = Targets Ground
+stat.itemsmoved = Move Speed
+stat.launchtime = Time Between Launches
+stat.shootrange = Range
+stat.size = Size
+stat.displaysize = Display Size
+stat.liquidcapacity = Liquid Capacity
+stat.powerrange = Power Range
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Max Connections
+stat.poweruse = Power Use
+stat.powerdamage = Power/Damage
+stat.itemcapacity = Item Capacity
+stat.basepowergeneration = Base Power Generation
+stat.productiontime = Production Time
+stat.repairtime = Block Full Repair Time
+stat.speedincrease = Speed Increase
+stat.range = Range
+stat.drilltier = Drillables
+stat.drillspeed = Base Drill Speed
+stat.boosteffect = Boost Effect
+stat.maxunits = Max Active Units
+stat.health = Health
+stat.buildtime = Build Time
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Build Cost
+stat.inaccuracy = Inaccuracy
+stat.shots = Shots
+stat.reload = Shots/Second
+stat.ammo = Ammo
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Better Drill Required
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = A large anti-air and anti-ground turret. Fires explo
block.spectre.description = A massive dual-barreled cannon. Shoots large armor-piercing bullets at air and ground targets.
block.meltdown.description = A massive laser cannon. Charges and fires a persistent laser beam at nearby enemies. Requires coolant to operate.
block.repair-point.description = Continuously heals the closest damaged unit in its vicinity.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties
index e7749d7347..925465c595 100644
--- a/core/assets/bundles/bundle_fr.properties
+++ b/core/assets/bundles/bundle_fr.properties
@@ -570,49 +570,49 @@ info.title = Info
error.title = [crimson]Une erreur s'est produite
error.crashtitle = Une erreur s'est produite
unit.nobuild = [scarlet]Cette unité ne peut construire
-blocks.input = Entrée
-blocks.output = Sortie
-blocks.booster = Booster
-blocks.tiles = Pré-requis
-blocks.affinities = Affinités
+stat.input = Entrée
+stat.output = Sortie
+stat.booster = Booster
+stat.tiles = Pré-requis
+stat.affinities = Affinités
block.unknown = [lightgray]???
-blocks.powercapacity = Capacité d'énergie
-blocks.powershot = Énergie/Tir
-blocks.damage = Dégâts
-blocks.targetsair = Cibles Aériennes
-blocks.targetsground = Cibles Terrestres
-blocks.itemsmoved = Vitesse de Déplacement
-blocks.launchtime = Temps entre chaque lancement
-blocks.shootrange = Portée de tir
-blocks.size = Taille
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Capacité liquide
-blocks.powerrange = Portée électrique
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Nombre maximal de connections
-blocks.poweruse = Énergie utilisée
-blocks.powerdamage = Dégâts d'énergie
-blocks.itemcapacity = Stockage
-blocks.basepowergeneration = Production d'énergie
-blocks.productiontime = Durée de production
-blocks.repairtime = Durée de réparation complète du Bloc
-blocks.speedincrease = Accélération
-blocks.range = Portée
-blocks.drilltier = Forable
-blocks.drillspeed = Vitesse de forage de base
-blocks.boosteffect = Effet du Boost
-blocks.maxunits = Unités actives max
-blocks.health = Santé
-blocks.buildtime = Durée de construction
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Coût de construction
-blocks.inaccuracy = Imprécision
-blocks.shots = Tirs
-blocks.reload = Tirs/Seconde
-blocks.ammo = Munitions
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Capacité d'énergie
+stat.powershot = Énergie/Tir
+stat.damage = Dégâts
+stat.targetsair = Cibles Aériennes
+stat.targetsground = Cibles Terrestres
+stat.itemsmoved = Vitesse de Déplacement
+stat.launchtime = Temps entre chaque lancement
+stat.shootrange = Portée de tir
+stat.size = Taille
+stat.displaysize = Display Size
+stat.liquidcapacity = Capacité liquide
+stat.powerrange = Portée électrique
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Nombre maximal de connections
+stat.poweruse = Énergie utilisée
+stat.powerdamage = Dégâts d'énergie
+stat.itemcapacity = Stockage
+stat.basepowergeneration = Production d'énergie
+stat.productiontime = Durée de production
+stat.repairtime = Durée de réparation complète du Bloc
+stat.speedincrease = Accélération
+stat.range = Portée
+stat.drilltier = Forable
+stat.drillspeed = Vitesse de forage de base
+stat.boosteffect = Effet du Boost
+stat.maxunits = Unités actives max
+stat.health = Santé
+stat.buildtime = Durée de construction
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Coût de construction
+stat.inaccuracy = Imprécision
+stat.shots = Tirs
+stat.reload = Tirs/Seconde
+stat.ammo = Munitions
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Meilleure Foreuse Requise
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = Une grande tourelle qui tire rapidement des débris
block.spectre.description = Une tourelle massive à double cannon et qui tire de puissantes balles perce-blindages simultanément.
block.meltdown.description = Une tourelle massive chargeant et tirant de puissants rayons lasers. Nécessite un liquide de refroidissement.
block.repair-point.description = Soigne en permanence l'unité endommagée la plus proche à proximité.
-block.segment.description = Endommage et détruit les tirs ennemis. Cependant, les lasers ne peuvent pas être ciblés.
+block.segment.description = Endommage et détruit les tirs ennemis. Cependant, les lasers ne peuvent pas être ciblés.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_fr_BE.properties b/core/assets/bundles/bundle_fr_BE.properties
index 02fe5e58b1..869da14c46 100644
--- a/core/assets/bundles/bundle_fr_BE.properties
+++ b/core/assets/bundles/bundle_fr_BE.properties
@@ -570,49 +570,49 @@ info.title = Info
error.title = [crimson]Une erreur s'est produite
error.crashtitle = Une erreur s'est produite
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Ressource(s) requise(s)
-blocks.output = Ressource(s) produite(s)
-blocks.booster = Booster
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Ressource(s) requise(s)
+stat.output = Ressource(s) produite(s)
+stat.booster = Booster
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]Inconnu
-blocks.powercapacity = Capacité d'énergie
-blocks.powershot = Énergie/Tir
-blocks.damage = Damage
-blocks.targetsair = Cible les unités aériennes
-blocks.targetsground = Cible les unités terrestres
-blocks.itemsmoved = Vitesse de déplacement
-blocks.launchtime = Temps entre chaque lancement
-blocks.shootrange = Portée
-blocks.size = Taille
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Capacité en liquide
-blocks.powerrange = Distance de transmission
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Max Connections
-blocks.poweruse = Énergie utilisée
-blocks.powerdamage = Énergie/Dégâts
-blocks.itemcapacity = Stockage
-blocks.basepowergeneration = Production d'énergie de base
-blocks.productiontime = Temps de production
-blocks.repairtime = Temps pour la réparation totale du bloc
-blocks.speedincrease = Augmentation de la vitesse
-blocks.range = Portée
-blocks.drilltier = Forable
-blocks.drillspeed = Vitesse de forage de base
-blocks.boosteffect = Effet boostant
-blocks.maxunits = Maximum d'unitée active
-blocks.health = Santé
-blocks.buildtime = Temps de construction
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Coût de construction
-blocks.inaccuracy = Précision
-blocks.shots = Tirs
-blocks.reload = Tirs/Seconde
-blocks.ammo = Munition
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Capacité d'énergie
+stat.powershot = Énergie/Tir
+stat.damage = Damage
+stat.targetsair = Cible les unités aériennes
+stat.targetsground = Cible les unités terrestres
+stat.itemsmoved = Vitesse de déplacement
+stat.launchtime = Temps entre chaque lancement
+stat.shootrange = Portée
+stat.size = Taille
+stat.displaysize = Display Size
+stat.liquidcapacity = Capacité en liquide
+stat.powerrange = Distance de transmission
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Max Connections
+stat.poweruse = Énergie utilisée
+stat.powerdamage = Énergie/Dégâts
+stat.itemcapacity = Stockage
+stat.basepowergeneration = Production d'énergie de base
+stat.productiontime = Temps de production
+stat.repairtime = Temps pour la réparation totale du bloc
+stat.speedincrease = Augmentation de la vitesse
+stat.range = Portée
+stat.drilltier = Forable
+stat.drillspeed = Vitesse de forage de base
+stat.boosteffect = Effet boostant
+stat.maxunits = Maximum d'unitée active
+stat.health = Santé
+stat.buildtime = Temps de construction
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Coût de construction
+stat.inaccuracy = Précision
+stat.shots = Tirs
+stat.reload = Tirs/Seconde
+stat.ammo = Munition
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Better Drill Required
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = Une grande tourelle à tir rapide.
block.spectre.description = Une grande tourelle qui tire deux balles puissantes à la fois.
block.meltdown.description = Une grande tourelle qui tire de puissants faisceaux à longue portée.
block.repair-point.description = Soigne en permanence l'unité endommagée la plus proche à proximité.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_hu.properties b/core/assets/bundles/bundle_hu.properties
index b28d471cdd..c24c9a24ee 100644
--- a/core/assets/bundles/bundle_hu.properties
+++ b/core/assets/bundles/bundle_hu.properties
@@ -570,49 +570,49 @@ info.title = Info
error.title = [crimson]An error has occured
error.crashtitle = An error has occured
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Input
-blocks.output = Output
-blocks.booster = Booster
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Input
+stat.output = Output
+stat.booster = Booster
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Power Capacity
-blocks.powershot = Power/Shot
-blocks.damage = Damage
-blocks.targetsair = Targets Air
-blocks.targetsground = Targets Ground
-blocks.itemsmoved = Move Speed
-blocks.launchtime = Time Between Launches
-blocks.shootrange = Range
-blocks.size = Size
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Liquid Capacity
-blocks.powerrange = Power Range
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Max Connections
-blocks.poweruse = Power Use
-blocks.powerdamage = Power/Damage
-blocks.itemcapacity = Item Capacity
-blocks.basepowergeneration = Base Power Generation
-blocks.productiontime = Production Time
-blocks.repairtime = Block Full Repair Time
-blocks.speedincrease = Speed Increase
-blocks.range = Range
-blocks.drilltier = Drillables
-blocks.drillspeed = Base Drill Speed
-blocks.boosteffect = Boost Effect
-blocks.maxunits = Max Active Units
-blocks.health = Health
-blocks.buildtime = Build Time
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Build Cost
-blocks.inaccuracy = Inaccuracy
-blocks.shots = Shots
-blocks.reload = Shots/Second
-blocks.ammo = Ammo
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Power Capacity
+stat.powershot = Power/Shot
+stat.damage = Damage
+stat.targetsair = Targets Air
+stat.targetsground = Targets Ground
+stat.itemsmoved = Move Speed
+stat.launchtime = Time Between Launches
+stat.shootrange = Range
+stat.size = Size
+stat.displaysize = Display Size
+stat.liquidcapacity = Liquid Capacity
+stat.powerrange = Power Range
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Max Connections
+stat.poweruse = Power Use
+stat.powerdamage = Power/Damage
+stat.itemcapacity = Item Capacity
+stat.basepowergeneration = Base Power Generation
+stat.productiontime = Production Time
+stat.repairtime = Block Full Repair Time
+stat.speedincrease = Speed Increase
+stat.range = Range
+stat.drilltier = Drillables
+stat.drillspeed = Base Drill Speed
+stat.boosteffect = Boost Effect
+stat.maxunits = Max Active Units
+stat.health = Health
+stat.buildtime = Build Time
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Build Cost
+stat.inaccuracy = Inaccuracy
+stat.shots = Shots
+stat.reload = Shots/Second
+stat.ammo = Ammo
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Better Drill Required
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = A large anti-air and anti-ground turret. Fires explo
block.spectre.description = A massive dual-barreled cannon. Shoots large armor-piercing bullets at air and ground targets.
block.meltdown.description = A massive laser cannon. Charges and fires a persistent laser beam at nearby enemies. Requires coolant to operate.
block.repair-point.description = Continuously heals the closest damaged unit in its vicinity.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_in_ID.properties b/core/assets/bundles/bundle_in_ID.properties
index 32aabb9eb5..e9f6f933eb 100644
--- a/core/assets/bundles/bundle_in_ID.properties
+++ b/core/assets/bundles/bundle_in_ID.properties
@@ -20,22 +20,22 @@ gameover = Permainan Habis
gameover.pvp = Tim[accent] {0}[] menang!
highscore = [accent]Rekor Baru!
copied = Tersalin.
-indev.popup = [accent]v6[] is currently in [accent]alpha[].\n[lightgray]This means:[]\n[scarlet]- The campaign is completely unfinished[]\n- Content is missing\n - Most [scarlet]Unit AI[] does not work properly\n- Many units are unfinished\n- Everything you see is subject to change or removal.\n\nReport bugs or crashes on [accent]Github[].
-indev.notready = This part of the game isn't ready yet
+indevpopup = [accent]v6[] saat ini dalam versi [accent]alpha[].\n[lightgray]Artinya:[]\n[scarlet]- Kampanye belum sepenuhnya selesai[]\n- Beberapa konten tidak tersedia\n - Beberapa [scarlet]Unit AI[] tidak sepenuhnya bekerja\n- Beberapa unit belum sepenuhnya selesai\n- Semua yang kamu lihat dapat berubah atau dihapus sewaktu-waktu.\n\nLaporkan bug atau crash di [accent]Github[].
+indev.notready = Bagian tersebut saat ini belum siap
load.sound = Suara
load.map = Peta
load.image = Gambar
load.content = Konten
load.system = Sistem
-load.mod = Mods
+load.mod = Mod
load.scripts = Skrip
be.update = Versi Bleeding Edge terbaru tersedia:
be.update.confirm = Unduh dan ulang kembali sekarang?
be.updating = Memperbarui...
-be.ignore = Biarkan
-be.noupdates = Tidak ada hal baru yang ditemukan.
+be.ignore = Abaikan
+be.noupdates = Tidak ada pembaruan yang ditemukan.
be.check = Cek versi baru
schematic = Skema
@@ -52,9 +52,10 @@ schematic.copy.import = Impor dari papan klip
schematic.shareworkshop = Bagikan di Workshop
schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Balik Skema
schematic.saved = Skema telah disimpan.
-schematic.delete.confirm = Skema ini akan benar - benar dihapus
+schematic.delete.confirm = Skema ini akan benar-benar dihapus.
schematic.rename = Ganti nama Skema
schematic.info = {0}x{1}, {2} blok
+schematic.disabled = [scarlet]Skema dilarang[]\nAnda tidak diperbolehkan untuk menggunakan skema di [accent]peta[] atau [accent]server ini.
stat.wave = Gelombang Terkalahkan:[accent] {0}
stat.enemiesDestroyed = Musuh Terhancurkan:[accent] {0}
@@ -65,7 +66,7 @@ stat.delivered = Sumber Daya yang Diluncurkan:
stat.playtime = Waktu Bermain:[accent] {0}
stat.rank = Nilai Akhir: [accent]{0}
-globalitems = [accent]Global Items
+globalitems = [accent]Item Global
map.delete = Apakah Anda yakin ingin menghapus peta "[accent]{0}[]"?
level.highscore = Nilai Tertinggi: [accent]{0}
level.select = Pilih Level
@@ -85,7 +86,7 @@ close = Tutup
website = Situs Jaringan
quit = Keluar
save.quit = Simpan & Keluar
-maps = Maps
+maps = Peta
maps.browse = Cari Peta
continue = Lanjutkan
maps.none = [lightgray]Peta tidak ditemukan!
@@ -106,16 +107,16 @@ mods.none = [lightgray]Tidak ada mod yang ditemukan!
mods.guide = Panduan Modding
mods.report = Lapor Kesalahan
mods.openfolder = Buka Folder Mod
-mods.reload = mengulangi
-mods.reloadexit = game akan keluar, untuk mengulang mod.
+mods.reload = Muat Ulang
+mods.reloadexit = Game akan keluar, untuk mengulang mod.
mod.display = [gray]Mod:[orange] {0}
mod.enabled = [lightgray]Aktif
mod.disabled = [scarlet]Nonaktif
mod.disable = Aktif
-mod.content = konten:
+mod.content = Konten:
mod.delete.error = Tidak bisa menghapus mod. File mungkin sedang digunakan.
mod.requiresversion = [scarlet]Versi game minimal yang dibutuhkan: [accent]{0}
-mod.outdated = [scarlet]Not compatible with V6 (no minGameVersion: 105)
+mod.outdated = [scarlet]Tidak cocok dengan V6 (minGameVersion: 105)
mod.missingdependencies = [scarlet]Ketergantungan hilang: {0}
mod.erroredcontent = [scarlet]Konten Mengalami Kesalahan
mod.errors = Kesalahan terjadi disaat memuat konten.
@@ -125,22 +126,22 @@ mod.enable = Aktif
mod.requiresrestart = Game akan keluar untuk mengaktifkan mod.
mod.reloadrequired = [scarlet]Dibutuhkan untuk memuat ulang
mod.import = Impor Mod
-mod.import.file = Import File
+mod.import.file = Impor File
mod.import.github = Impor Mod GitHub
-mod.jarwarn = [scarlet]mod dari JAR sebenarnya tidak aman.[]\nPastikan anda mengimpor mod dari sumber terpercaya!
+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}'[] mod. Untuk dihilangkan, hapus mod ini.
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.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!
about.button = Tentang
name = Nama:
noname = Pilih[accent] nama pemain[] dahulu.
-planetmap = Planet Map
-launchcore = Launch Core
+planetmap = Peta Planet
+launchcore = Luncurkan Inti
filename = Nama File:
unlocked = Konten baru terbuka!
completed = [accent]Terselesaikan
@@ -148,17 +149,17 @@ techtree = Cabang Teknologi
research.list = [lightgray]Penelitian:
research = Penelitian
researched = [lightgray]{0} telah diteliti.
-research.progress = {0}% complete
+research.progress = {0}% diteliti
players = {0} pemain aktif
players.single = {0} pemain aktif
-players.search = cari
-players.notfound = [gray]tidak ada pemain ditemukan
+players.search = Cari
+players.notfound = [gray]Tidak ada pemain ditemukan
server.closing = [accent]Menutup server...
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 = Client kadaluarsa! Perbarui mindustry Anda!
+server.kicked.clientOutdated = Client kadaluarsa! Perbarui game Anda!
server.kicked.serverOutdated = Server kadaluarsa! Tanya pemilik untuk memperbarui!
server.kicked.banned = Anda telah dilarang untuk memasuki server ini.
server.kicked.typeMismatch = Server ini tidak cocok dengan versi build Anda.
@@ -197,7 +198,7 @@ trace.mobile = Client Mobile: [accent]{0}
trace.modclient = Client Modifikasi: [accent]{0}
invalidid = Client ID tidak valid! Laporkan masalah.
server.bans = Pemain Dilarang Masuk
-server.bans.none = Tidak ada pemain yang diberiizin masuk!
+server.bans.none = Tidak ada pemain yang tidak diberi izin masuk!
server.admins = Admin
server.admins.none = Tidak ada admin!
server.add = Tambahkan Server
@@ -262,7 +263,7 @@ view.workshop = Lihat di Workshop
workshop.listing = Sunting Daftar Workshop
ok = OK
open = Buka
-customize = edit
+customize = Sunting Peraturan
cancel = Batal
openlink = Buka Tautan
copylink = Salin Tautan
@@ -335,7 +336,7 @@ waves.never =
waves.every = setiap
waves.waves = gelombang
waves.perspawn = per muncul
-waves.shields = shields/wave
+waves.shields = perisai/gelombang
waves.to = sampai
waves.guardian = Guardian
waves.preview = Pratinjau
@@ -346,9 +347,10 @@ 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.
-wavemode.counts = counts
-wavemode.totals = totals
-wavemode.health = health
+#memang sengaja diberi huruf kecil
+wavemode.counts = jumlah
+wavemode.totals = total
+wavemode.health = darah
editor.default = [lightgray]
details = Detail...
@@ -357,9 +359,9 @@ editor.name = Nama:
editor.spawn = Munculkan Unit
editor.removeunit = Hapus Unit
editor.teams = Tim
-editor.errorload = Terjadi kesalahan saat memuat file:\n[accent]{0}
-editor.errorsave = Terjadi kesalahan saat menyimpan file:\n[accent]{0}
-editor.errorimage = Itu gambar biasa, bukan peta. Jangan merubah ekstensi dan megharapkan akan berhasil.\n\nJika anda ingin mengimpor peta "Legacy", gunakan tombol 'impor peta legacy ' di penyunting.
+editor.errorload = Terjadi kesalahan saat memuat file.
+editor.errorsave = Terjadi kesalahan saat menyimpan file.
+editor.errorimage = Itu gambar biasa, bukan peta. Jangan merubah ekstensi dan megharapkan akan berhasil.\n\nJika anda ingin mengimpor peta "Legacy", gunakan tombol 'Impor Peta Legacy ' di penyunting.
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.
@@ -415,8 +417,8 @@ toolmode.drawteams.description = Menggambar tim bukannya blok.
filters.empty = [lightgray]Tidak ada filter! Tambahkan dengan tombol dibawah.
filter.distort = Kerusakkan
filter.noise = Kebisingan
-filter.enemyspawn = Enemy Spawn Select
-filter.corespawn = Core Select
+filter.enemyspawn = Pilih Munculnya Musuh
+filter.corespawn = Pilih Inti
filter.median = Median
filter.oremedian = Median Bijih
filter.blend = Campur
@@ -436,7 +438,7 @@ filter.option.circle-scale = Ukuran Lingkaran
filter.option.octaves = Oktaf
filter.option.falloff = Kemerosotan
filter.option.angle = Sudut
-filter.option.amount = Amount
+filter.option.amount = Jumlah
filter.option.block = Blok
filter.option.floor = Lantai
filter.option.flooronto = Target Lantai
@@ -451,7 +453,7 @@ width = Lebar:
height = Tinggi:
menu = Menu
play = Bermain
-campaign = kampanye
+campaign = Kampanye
load = Memuat
save = Simpan
fps = FPS: {0}
@@ -469,24 +471,19 @@ locked = Terkunci
complete = [lightgray]Mencapai:
requirement.wave = Capai gelombang {0} dalam {1}
requirement.core = Hancurkan inti musuh dalam {0}
-requirement.research = Research {0}
-requirement.capture = Capture {0}
-resume = Lanjutkan Zona:\n[lightgray]{0}
+requirement.research = Kembangkan {0}
+requirement.capture = Kuasai {0}
bestwave = [lightgray]Gelombang Terbaik: {0}
-launch = < MELUNCUR >
-launch.text = Launch
-launch.title = Berhasil Meluncur
-launch.next = [lightgray]kesempatan berikutnya di gelombang {0}
-launch.unable2 = [scarlet]Tidak dapat MELUNCUR.[]
-launch.confirm = Ini akan meluncurkan semua sumber daya di inti.\nAnda tidak bisa kembali lagi ke tempat ini.
-launch.skip.confirm = Jika Anda lewati sekarang, Anda tidak akan dapat meluncur hingga gelombang berikutnya.
+launch.text = Luncurkan
+campaign.multiplayer = Saat bermain bersama di kampanye, Kamu hanya bisa kembangkan menggunakan item dari sektor [accent]kamu[], [scarlet]Bukan[] sektor milik host yang kamu berada sekarang.\n\nUntuk mendapatkan item tersebut ke sektor [accent]kamu[] saat bermain bersama, gunakan [accent]alas peluncur[].
uncover = Buka
configure = Konfigurasi Muatan
-loadout = Loadout
-resources = Resources
+#TODO
+loadout = Muatan
+resources = Sumber Daya
bannedblocks = Balok yang dilarang
-addall = Tambah Semu
-launch.destination = Destination: {0}
+addall = Tambah Semua
+launch.destination = Destinasi: {0}
configure.invalid = Jumlah harus berupa angka diantara 0 dan {0}.
zone.unlocked = [lightgray]{0} terbuka.
zone.requirement.complete = Gelombang {0} terselesaikan:\nPersyaratan zona {1} tercapai.
@@ -508,20 +505,21 @@ error.io = Terjadi kesalahan jaringan I/O.
error.any = Terjadi kesalahan Jaringan tidak diketahui.
error.bloom = Gagal untuk menginisialisasi bloom.\nPerangkat Anda mungkin tidak mendukung fitur ini.
-weather.rain.name = Rain
-weather.snow.name = Snow
-weather.sandstorm.name = Sandstorm
-weather.sporestorm.name = Sporestorm
+weather.rain.name = Hujan
+weather.snow.name = Salju
+weather.sandstorm.name = Badai Pasir
+weather.sporestorm.name = Badai Spora
-sectors.unexplored = [lightgray]Unexplored
-sectors.resources = Resources:
-sectors.production = Production:
-sectors.stored = Stored:
-sectors.resume = Resume
-sectors.launch = Launch
-sectors.select = Select
-sectors.nonelaunch = [lightgray]none (sun)
+sectors.unexplored = [lightgray]Belum Ditelusuri
+sectors.resources = Sumber Daya:
+sectors.production = Produksi:
+sectors.stored = Terisi:
+sectors.resume = Lanjutkan
+sectors.launch = Luncurkan
+sectors.select = Pilih
+sectors.nonelaunch = [lightgray]tidak ada
+#NOTE TO TRANSLATORS: don't bother editing these, they'll be removed and/or rewritten anyway
sector.groundZero.name = Ground Zero
sector.craters.name = The Craters
sector.frozenForest.name = Frozen Forest
@@ -534,8 +532,12 @@ sector.tarFields.name = Tar Fields
sector.saltFlats.name = Salt Flats
sector.fungalPass.name = Fungal Pass
-sector.groundZero.description = lokasi yang optimal untuk bermain satu kali lagi. Sangat sedikit musuh. Beberapa sumber daya.\nKumpulkan timah dan tembaga sebanyak yang anda bisa.\nPindah.
-sector.frozenForest.description = disini, dekat dengan gunung, spora spora sudah menyebar. Temperatur yang sangat rendah tidak dapat mempertahankan selamanya.\n\nBerusaha untuk kekuatan. Bangun generator pembakaran. Pelajari cara menggunakan mender.
+#unused
+#sector.impact0078.name = Impact 0078
+#sector.crags.name = Crags
+
+sector.groundZero.description = Lokasi yang optimal untuk bermain satu kali lagi. Sangat sedikit musuh. Beberapa sumber daya.\nKumpulkan timah dan tembaga sebanyak yang anda bisa.\nPindah.
+sector.frozenForest.description = Disini, dekat dengan gunung, spora spora sudah menyebar. Temperatur yang sangat rendah tidak dapat mempertahankan selamanya.\n\nBerusaha untuk kekuatan. Bangun generator pembakaran. Pelajari cara menggunakan mender.
sector.saltFlats.description = On the outskirts of the desert lie the Salt Flats. Few resources can be found in this location.\n\nThe enemy has erected a resource storage complex here. Eradicate their core. Leave nothing standing.
sector.craters.description = Water has accumulated in this crater, relic of the old wars. Reclaim the area. Collect sand. Smelt metaglass. Pump water to cool turrets and drills.
sector.ruinousShores.description = Past the wastes, is the shoreline. Once, this location housed a coastal defense array. Not much of it remains. Only the most basic defense structures have remained unscathed, everything else reduced to scrap.\nContinue the expansion outwards. Rediscover the technology.
@@ -547,7 +549,7 @@ sector.nuclearComplex.description = A former facility for the production and pro
sector.fungalPass.description = A transition area between high mountains and lower, spore-ridden lands. A small enemy reconnaissance base is located here.\nDestroy it.\nUse Dagger and Crawler units. Take out the two cores.
settings.language = Bahasa
-settings.data = Game Data
+settings.data = Data Game
settings.reset = Atur ulang ke Default (standar)
settings.rebind = Ganti tombol
settings.resetKey = Atur ulang
@@ -558,65 +560,66 @@ settings.graphics = Grafik
settings.cleardata = Menghapus Data Permainan...
settings.clear.confirm = Anda yakin ingin menghapus data ini?\nWaktu tidak bisa diulang kembali!
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 = Are you sure you want to clear all your saves?
-settings.clearsaves = Clear Saves
+settings.clearsaves.confirm = Anda yakin ingin menghapus semua simpanan?
+settings.clearsaves = Bersihkan Simpanan
paused = [accent]< Jeda >
clear = Bersih
banned = [scarlet]Dilarang
-unplaceable.sectorcaptured = [scarlet]Requires captured sector
+unplaceable.sectorcaptured = [scarlet]Membutuhkan sektor yang dikuasai
yes = Ya
no = Tidak
info.title = Info
error.title = [crimson]Sebuah kesalahan telah terjadi
error.crashtitle = Sebuah kesalahan telah terjadi
-unit.nobuild = [scarlet]Unit can't build
-blocks.input = Masukan
-blocks.output = Pengeluaran
-blocks.booster = Pendorong
-blocks.tiles = Kotak yang dibutuhkan
-blocks.affinities = Afinitas
+unit.nobuild = [scarlet]Unit tidak dapat membangun
+stat.input = Masukan
+stat.output = Pengeluaran
+stat.booster = Pendorong
+stat.tiles = Kotak yang dibutuhkan
+stat.affinities = Afinitas
block.unknown = [lightgray]???
-blocks.powercapacity = Kapasitas Tenaga
-blocks.powershot = Tenaga/Tembakan
-blocks.damage = Kerusakan
-blocks.targetsair = Menargetkan Udara
-blocks.targetsground = Menargetkan Darat
-blocks.itemsmoved = Kecepatan Gerak
-blocks.launchtime = Waktu Diantara Peluncuran
-blocks.shootrange = Jarak
-blocks.size = Ukuran
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Kapasitas Zat Cair
-blocks.powerrange = Jarak Tenaga
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Koneksi Maksimal
-blocks.poweruse = Penggunaan Tenaga
-blocks.powerdamage = Tenaga/Pukulan
-blocks.itemcapacity = Kapasitas Item
-blocks.basepowergeneration = Basis Generasi Tenaga
-blocks.productiontime = Waktu Produksi
-blocks.repairtime = Waktu Memperbaiki Blok Penuh
-blocks.speedincrease = Tambahan Kecepatan
-blocks.range = Jarak
-blocks.drilltier = Sumber Daya yang Bisa di Bor
-blocks.drillspeed = Basis Kecepatan Bor
-blocks.boosteffect = Efek Pendorong
-blocks.maxunits = Maks Unit Aktif
-blocks.health = Darah
-blocks.buildtime = Waktu Pembuatan
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Biaya Bangunan
-blocks.inaccuracy = Jarak Melenceng
-blocks.shots = Tembakan
-blocks.reload = Tembakan/Detik
-blocks.ammo = Amunisi
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Kapasitas Tenaga
+stat.powershot = Tenaga/Tembakan
+stat.damage = Kerusakan
+stat.targetsair = Menargetkan Udara
+stat.targetsground = Menargetkan Darat
+stat.itemsmoved = Kecepatan Gerak
+stat.launchtime = Waktu Diantara Peluncuran
+stat.shootrange = Jarak
+stat.size = Ukuran
+stat.displaysize = Ukuran Tampilan
+stat.liquidcapacity = Kapasitas Zat Cair
+stat.powerrange = Jarak Tenaga
+stat.linkrange = Jarak Tautan
+stat.instructions = Instruksi
+stat.powerconnections = Koneksi Maksimal
+stat.poweruse = Penggunaan Tenaga
+stat.powerdamage = Tenaga/Pukulan
+stat.itemcapacity = Kapasitas Item
+stat.memorycapacity = Kapasitas Memori
+stat.basepowergeneration = Basis Generasi Tenaga
+stat.productiontime = Waktu Produksi
+stat.repairtime = Waktu Memperbaiki Blok Penuh
+stat.speedincrease = Tambahan Kecepatan
+stat.range = Jarak
+stat.drilltier = Sumber Daya yang Bisa di Bor
+stat.drillspeed = Basis Kecepatan Bor
+stat.boosteffect = Efek Pendorong
+stat.maxunits = Maks Unit Aktif
+stat.health = Darah
+stat.buildtime = Waktu Pembuatan
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Biaya Bangunan
+stat.inaccuracy = Jarak Melenceng
+stat.shots = Tembakan
+stat.reload = Tembakan/Detik
+stat.ammo = Amunisi
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Membutuhkan Bor yang Lebih Baik
-bar.noresources = Missing Resources
-bar.corereq = Core Base Required
+bar.noresources = Sumber Daya Tidak Ditemukan
+bar.corereq = Memerlukan Inti Dasar
bar.drillspeed = Kecepatan Bor: {0}/s
bar.pumpspeed = Kecepatan Pompa: {0}/s
bar.efficiency = Daya Guna: {0}%
@@ -655,16 +658,16 @@ unit.liquidunits = unit zat cair
unit.powerunits = unit tenaga
unit.degrees = derajat
unit.seconds = detik
-unit.minutes = mins
+unit.minutes = menit
unit.persecond = /detik
-unit.perminute = /min
+unit.perminute = /menit
unit.timesspeed = x kecepatan
unit.percent = %
unit.shieldhealth = shield health
unit.items = item
-unit.thousands = ribu
-unit.millions = juta
-unit.billions = b
+unit.thousands = rb
+unit.millions = jt
+unit.billions = m
category.general = Umum
category.power = Tenaga
category.liquids = Zat Cair
@@ -677,13 +680,13 @@ setting.shadows.name = Bayangan
setting.blockreplace.name = Usulan Blok Otomatis
setting.linear.name = Filter Bergaris
setting.hints.name = Petunjuk
-setting.flow.name = Display Resource Flow Rate[scarlet] (experimental)
+setting.flow.name = Tampilan Laju Aliran Sumber Daya
setting.buildautopause.name = Jeda Otomatis saat Membangun
-setting.mapcenter.name = Auto Center Map To Player
+setting.mapcenter.name = Pusatkan Peta Otomatis Ke Pemain
setting.animatedwater.name = Animasi Perairan
setting.animatedshields.name = Animasi Pelindung
setting.antialias.name = Antialiasi[lightgray] (membutuhkan restart)[]
-setting.playerindicators.name = Player Indicators
+setting.playerindicators.name = Indikasi Pemain
setting.indicators.name = Indikasi Musuh/Teman Lain
setting.autotarget.name = Target Secara Otomatis
setting.keyboard.name = Kontrol Mouse+Papan Ketik
@@ -702,7 +705,7 @@ setting.difficulty.name = Tingkat Kesulitan:
setting.screenshake.name = Layar Getar
setting.effects.name = Munculkan Efek
setting.destroyedblocks.name = Tunjukkan Blok yang Telah Hancur
-setting.blockstatus.name = Display Block Status
+setting.blockstatus.name = Tunjukan Status Blok
setting.conveyorpathfinding.name = Navigasi Pengantar Otomatis
setting.sensitivity.name = Sensitivitas Kontroler
setting.saveinterval.name = Jarak Menyimpan
@@ -712,15 +715,15 @@ setting.milliseconds = {0} milisekon
setting.fullscreen.name = Layar Penuh
setting.borderlesswindow.name = Jendela tak Berbatas[lightgray] (mungkin memerlukan mengulang kembali)
setting.fps.name = Tunjukkan FPS
-setting.smoothcamera.name = Smooth Camera
+setting.smoothcamera.name = Kamera Halus
setting.blockselectkeys.name = Tunjukkan Kunci Pilih Blok
setting.vsync.name = VSync
setting.pixelate.name = Mode Pixel[lightgray] (menonaktifkan animasi)
setting.minimap.name = Tunjukkan Peta Kecil
-setting.coreitems.name = Display Core Items (WIP)
+setting.coreitems.name = Tunjukkan Item Inti (WIP)
setting.position.name = Tunjukkan Posisi Pemain
setting.musicvol.name = Volume Musik
-setting.atmosphere.name = Show Planet Atmosphere
+setting.atmosphere.name = Tunjukkan Atmosfer Planet
setting.ambientvol.name = Volume Sekeliling
setting.mutemusic.name = Diamkan Musik
setting.sfxvol.name = Volume Efek Suara
@@ -738,30 +741,30 @@ public.beta = Ingat bahwa game 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
-keybind.title = Ganti Kunci
-keybinds.mobile = [scarlet]Mayoritas kunci tidak mendukung mobile. Hanya gerakan dasar yang didukung.
+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.multiplayer.name = Bermain Bersama
-category.blocks.name = Block Select
+category.blocks.name = Pilih Blok
command.attack = Serang
command.rally = Kumpul/Patroli
command.retreat = Mundur
-command.idle = Idle
-placement.blockselectkeys = \n[lightgray]Kunci: [{0},
-keybind.respawn.name = Respawn
-keybind.control.name = Control Unit
+command.idle = Diam di Tempat
+placement.blockselectkeys = \n[lightgray]Tombol: [{0},
+keybind.respawn.name = Muncul Kembali
+keybind.control.name = Kontrol Unit
keybind.clear_building.name = Hapus Bangunan
-keybind.press = Tekan kunci...
-keybind.press.axis = Tekan sumbu atau kunci...
+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_block_status.name = Toggle Block Statuses
-keybind.move_x.name = Pindah x
-keybind.move_y.name = Pindah y
-keybind.mouse_move.name = Ikut Mouse
-keybind.pan.name = Pan View
-keybind.boost.name = Boost
+keybind.toggle_block_status.name = Status Blok
+keybind.move_x.name = Pindah X
+keybind.move_y.name = Pindah Y
+keybind.mouse_move.name = Ikuti Mouse
+keybind.pan.name = Tampilan Geser
+keybind.boost.name = Dorongan
keybind.schematic_select.name = Pilih Daerah
keybind.schematic_menu.name = Menu Skema
keybind.schematic_flip_x.name = Balik Skema X
@@ -788,9 +791,9 @@ keybind.diagonal_placement.name = Penaruhan Diagonal
keybind.pick.name = Memilih Blok
keybind.break_block.name = Menghancurkan Blok
keybind.deselect.name = Batal Memilih
-keybind.pickupCargo.name = Pickup Cargo
-keybind.dropCargo.name = Drop Cargo
-keybind.command.name = Command
+keybind.pickupCargo.name = Muat Kargo
+keybind.dropCargo.name = Turunkan Kargo
+keybind.command.name = Perintah
keybind.shoot.name = Menembak
keybind.zoom.name = Perbesar
keybind.menu.name = Menu
@@ -801,7 +804,7 @@ keybind.chat.name = Pesan
keybind.player_list.name = Daftar pemain
keybind.console.name = Papan Konsol
keybind.rotate.name = Putar
-keybind.rotateplaced.name = Putar yang ada (Tekan)
+keybind.rotateplaced.name = Putar yang ada (Tekan dan Tahan)
keybind.toggle_menus.name = Muncul Tidaknya Menu
keybind.chat_history_prev.name = Sejarah Pesan Sebelumnya
keybind.chat_history_next.name = Sejarah Pesan Setelahnya
@@ -822,13 +825,14 @@ mode.custom = Pengaturan Modifikasi
rules.infiniteresources = Sumber Daya Tak Terbatas
rules.reactorexplosions = Ledakan Reaktor
+rules.schematic = Skema Diperbolehkan
rules.wavetimer = Pengaturan Waktu Gelombang
rules.waves = Gelombang
rules.attack = Mode Penyerangan
-rules.buildai = AI Building
+rules.buildai = Bangunan A.I.
rules.enemyCheat = Sumber Daya A.I Musuh (Tim Merah) Tak Terbatas
rules.blockhealthmultiplier = Multiplikasi Darah Blok
-rules.blockdamagemultiplier = Block Damage Multiplier
+rules.blockdamagemultiplier = Multiplikasi Kekuatan Blok
rules.unitbuildspeedmultiplier = Multiplikasi Kecepatan Munculnya Unit
rules.unithealthmultiplier = Multiplikasi Darah Unit
rules.unitdamagemultiplier = Multiplikasi Kekuatan Unit
@@ -836,23 +840,24 @@ rules.enemycorebuildradius = Dilarang Membangun Radius Inti Musuh :[lightgray] (
rules.wavespacing = Jarak Gelombang:[lightgray] (detik)
rules.buildcostmultiplier = Multiplikasi Harga Bangunan
rules.buildspeedmultiplier = Multiplikasi Waktu Pembuatan Bangunan
-rules.deconstructrefundmultiplier = Penggembalian Dana Mendekonstraksi Blok
+rules.deconstructrefundmultiplier = Penggembalian Dana Mendekonstruksi Blok
rules.waitForWaveToEnd = Gelombang menunggu musuh
rules.dropzoneradius = Radius Titik Muncul:[lightgray] (Blok)
-rules.unitammo = Units Require Ammo
+rules.unitammo = Unit Membutuhkan AMunisi
rules.title.waves = Gelombang
rules.title.resourcesbuilding = Sumber Daya & Bangunan
rules.title.enemy = Musuh
rules.title.unit = Unit
rules.title.experimental = Eksperimental
-rules.title.environment = Environment
+rules.title.environment = Lingkungan
rules.lighting = Penerangan
-rules.fire = Fire
-rules.explosions = Block/Unit Explosion Damage
+rules.enemyLights = Sinar dari Musuh
+rules.fire = Api
+rules.explosions = Kekuatan Ledakan Blok/Unit
rules.ambientlight = Sinar Disekeliling
-rules.weather = Weather
-rules.weather.frequency = Frequency:
-rules.weather.duration = Duration:
+rules.weather = Cuaca
+rules.weather.frequency = Frekuensi:
+rules.weather.duration = Durasi:
content.item.name = Item
content.liquid.name = Zat Cair
@@ -877,7 +882,7 @@ item.scrap.name = Kepingan
liquid.water.name = Air
liquid.slag.name = Terak
liquid.oil.name = Minyak
-liquid.cryofluid.name = Cairan Dingin
+liquid.cryofluid.name = Cairan Pendingin
item.explosiveness = [lightgray]Tingkat Keledakan: {0}%
item.flammability = [lightgray]Tingkat Kebakaran: {0}%
@@ -885,12 +890,12 @@ item.radioactivity = [lightgray]Tingkat Radioaktif: {0}%
unit.health = [lightgray]Darah: {0}
unit.speed = [lightgray]Kecepatan: {0}
-unit.weapon = [lightgray]Weapon: {0}
-unit.itemcapacity = [lightgray]Item Capacity: {0}
-unit.minespeed = [lightgray]Mining Speed: {0}%
-unit.minepower = [lightgray]Mining Power: {0}
-unit.ability = [lightgray]Ability: {0}
-unit.buildspeed = [lightgray]Building Speed: {0}%
+unit.weapon = [lightgray]Senjata: {0}
+unit.itemcapacity = [lightgray]Kapasitas Item: {0}
+unit.minespeed = [lightgray]Kecepatan Menambang: {0}%
+unit.minepower = [lightgray]Kekuatan Menambang: {0}
+unit.ability = [lightgray]Kemampuan: {0}
+unit.buildspeed = [lightgray]Kecepatan Membangun: {0}%
liquid.heatcapacity = [lightgray]Kapasitas Panas: {0}
liquid.viscosity = [lightgray]Kelekatan: {0}
@@ -930,7 +935,7 @@ unit.reign.name = Reign
unit.vela.name = Vela
unit.corvus.name = Corvus
-block.resupply-point.name = Resupply Point
+block.resupply-point.name = Titik Pemasok Ulang
block.parallax.name = Parallax
block.cliff.name = Cliff
block.sand-boulder.name = Batu Pasir
@@ -979,17 +984,17 @@ block.craters.name = Kawah
block.sand-water.name = Air Pasir
block.darksand-water.name = Air Pasir Hitam
block.char.name = Bara
-block.dacite.name = Dacite
-block.dacite-wall.name = Dacite Wall
+block.dacite.name = Dasit
+block.dacite-wall.name = Dinding Dasit
block.ice-snow.name = Salju Es
-block.stone-wall.name = Stone Wall
-block.ice-wall.name = Ice Wall
-block.snow-wall.name = Snow Wall
-block.dune-wall.name = Dune Wall
+block.stone-wall.name = Dinding Batu
+block.ice-wall.name = Dinding Es
+block.snow-wall.name = Dinding Salju
+block.dune-wall.name = Dinding Pasir
block.pine.name = Cemara
-block.dirt.name = Dirt
-block.dirt-wall.name = Dirt Wall
-block.mud.name = Mud
+block.dirt.name = Tanah
+block.dirt-wall.name = Dinding Tanah
+block.mud.name = Lumpur
block.white-tree-dead.name = Pohon Putih Mati
block.white-tree.name = Pohon Putih
block.spore-cluster.name = Kumpulan Spora
@@ -1005,7 +1010,7 @@ block.dark-panel-4.name = Panel Gelap 4
block.dark-panel-5.name = Panel Gelap 5
block.dark-panel-6.name = Panel Gelap 6
block.dark-metal.name = Besi Gelap
-block.basalt.name = Basalt
+block.basalt.name = Basal
block.hotrock.name = Batu Panas
block.magmarock.name = Batu Lahar
block.copper-wall.name = Dinding Tembaga
@@ -1021,13 +1026,13 @@ block.thorium-wall-large.name = Dinding Thorium Besar
block.door.name = Pintu
block.door-large.name = Pintu Besar
block.duo.name = Duo
-block.scorch.name = Penghangus
-block.scatter.name = Penabur
-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 = Plastanium Conveyor
+block.plastanium-conveyor.name = Pengantar Berbahan Plastanium
block.armored-conveyor.name = Pengantar Berlapis Pelindung
block.armored-conveyor.description = Memindahkan barang sama cepatnya dengan pengantar titanium, namun memiliki lebih banyak armor. Tidak dapat menerima masukan dari samping dari apapun kecuali dari pengantar.
block.junction.name = Simpangan
@@ -1074,10 +1079,11 @@ block.power-void.name = Penghilang Tenaga
block.power-source.name = Sumber Tenaga
block.unloader.name = Pembongkar Muatan
block.vault.name = Gudang
-block.wave.name = Ombak
-block.swarmer.name = Pengurung
+block.wave.name = Wave
+block.tsunami.name = Tsunami
+block.swarmer.name = Swarmer
block.salvo.name = Salvo
-block.ripple.name = Periak
+block.ripple.name = Ripple
block.phase-conveyor.name = Pengantar Berbahan Phase
block.bridge-conveyor.name = Jembatan Pengantar
block.plastanium-compressor.name = Kompresor Plastanium
@@ -1105,46 +1111,48 @@ block.mender.name = Reparator
block.mend-projector.name = Proyeksi Reparator
block.surge-wall.name = Dinding Listrik
block.surge-wall-large.name = Dinding Listrik Besar
-block.cyclone.name = Topan
-block.fuse.name = Padu
+block.cyclone.name = Cyclone
+block.fuse.name = Fuse
block.shock-mine.name = Ranjau Listrik
block.overdrive-projector.name = Proyeksi Pencepat
block.force-projector.name = Proyeksi Medan Gaya
-block.arc.name = Arca
+block.arc.name = Arc
block.rtg-generator.name = Generator RTG
-block.spectre.name = Iblis
-block.meltdown.name = Pelebur
+block.spectre.name = Spectre
+block.meltdown.name = Meltdown
+block.foreshadow.name = Foreshadow
block.container.name = Kontainer
block.launch-pad.name = Alas Peluncur
block.launch-pad-large.name = Alas Peluncur Besar
block.segment.name = Segment
-block.command-center.name = Command Center
-block.ground-factory.name = Ground Factory
-block.air-factory.name = Air Factory
-block.naval-factory.name = Naval Factory
-block.additive-reconstructor.name = Additive Reconstructor
-block.multiplicative-reconstructor.name = Multiplicative Reconstructor
-block.exponential-reconstructor.name = Exponential Reconstructor
-block.tetrative-reconstructor.name = Tetrative Reconstructor
-block.payload-conveyor.name = Mass Conveyor
-block.payload-router.name = Payload Router
-block.disassembler.name = Disassembler
-block.silicon-crucible.name = Silicon Crucible
-block.overdrive-dome.name = Overdrive Dome
+block.command-center.name = Pusat Perintah
+block.ground-factory.name = Pabrik Angkatan Darat
+block.air-factory.name = Pabrik Angkatan Udara
+block.naval-factory.name = Pabrik Angkatan Laut
+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.disassembler.name = Pembongkar
+block.silicon-crucible.name = Multi-Lebur
+block.overdrive-dome.name = Kubah Proyeksi Percepat
-block.switch.name = Switch
-block.micro-processor.name = Micro Processor
-block.logic-processor.name = Logic Processor
-block.hyper-processor.name = Hyper Processor
-block.logic-display.name = Logic Display
-block.large-logic-display.name = Large Logic Display
-block.memory-cell.name = Memory Cell
+block.switch.name = Saklar
+block.micro-processor.name = Prosesor Mikro
+block.logic-processor.name = Prosesor Logika
+block.hyper-processor.name = Prosesor Cepat
+block.logic-display.name = Tampilan Logika
+block.large-logic-display.name = Tampilan Logika Besar
+block.memory-cell.name = Sel Memori
+block.memory-bank.name = Bank Memori
team.blue.name = biru
team.crux.name = merah
team.sharded.name = oranye
team.orange.name = jingga
-team.derelict.name = derelict
+team.derelict.name = abu-abu
team.green.name = hijau
team.purple.name = ungu
@@ -1235,7 +1243,7 @@ block.force-projector.description = Membentuk medan gaya berbentuk heksagon dise
block.shock-mine.description = Mencedera musuh yang menginjak ranjau. Hampir tak kasat mata kepada musuh.
block.conveyor.description = Blok transportasi dasar. Memindahkan item ke kubah ataupun pabrik. Bisa diputar.
block.titanium-conveyor.description = Blok transportasi canggih. Memindahkan item lebih cepat daripada pengantar biasa.
-block.plastanium-conveyor.description = Moves items in batches.\nAccepts items at the back, and unloads them in three directions at the front.
+block.plastanium-conveyor.description = Memindahkan barang secara bertumpuk.\nMenerima barang dari belakang, dan membaginya ke tiga arah di depan.\nMembutuhkan beberapa titik pemuat dan pembongkar untuk hasil yang maksimal.
block.junction.description = Berguna seperti jembatan untuk dua pengantar yang bersimpangan. Berguna di situasi dimana dua pengantar berbeda membawa bahan berbeda ke lokasi yang berbeda.
block.bridge-conveyor.description = Blok transportasi item canggih. bisa memindahkan item hingga 3 blok panjang melewati apapun lapangan atau bangunan.
block.phase-conveyor.description = Blok transportasi canggih. Menggunakan tenaga untuk teleportasi item ke sambungan pengantar phase melewati beberapa blok.
@@ -1302,4 +1310,4 @@ block.cyclone.description = Menara penembak beruntun besar.
block.spectre.description = Menara besar yang menembak dua peluru kuat sekaligus.
block.meltdown.description = Menara besar ini menembak sinar panjang yang kuat.
block.repair-point.description = Terus menerus memulihkan unit terluka disekitar.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Merusakkan dan menghancurkan proyektil yang datang. Proyektil laser tidak akan ditargetkan.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties
index c10f894851..5fc3245ed6 100644
--- a/core/assets/bundles/bundle_it.properties
+++ b/core/assets/bundles/bundle_it.properties
@@ -570,49 +570,49 @@ info.title = Info
error.title = [crimson]Si è verificato un errore
error.crashtitle = Si è verificato un errore
unit.nobuild = [scarlet]L'unità non può costruire
-blocks.input = Ingresso
-blocks.output = Uscita
-blocks.booster = Potenziamenti
-blocks.tiles = Blocchi Richiesti
-blocks.affinities = Affinità
+stat.input = Ingresso
+stat.output = Uscita
+stat.booster = Potenziamenti
+stat.tiles = Blocchi Richiesti
+stat.affinities = Affinità
block.unknown = [lightgray]???
-blocks.powercapacity = Capacità Energetica
-blocks.powershot = Danno/Colpo
-blocks.damage = Danno
-blocks.targetsair = Attacca Nemici Aerei
-blocks.targetsground = Attacca Nemici Terreni
-blocks.itemsmoved = Velocità di Movimento
-blocks.launchtime = Tempo fra Decolli
-blocks.shootrange = Raggio
-blocks.size = Dimensioni
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Capacità del Liquido
-blocks.powerrange = Raggio Energia
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Connessioni Massime
-blocks.poweruse = Utilizzo Energia
-blocks.powerdamage = Energia/Danno
-blocks.itemcapacity = Capacità
-blocks.basepowergeneration = Generazione Energia di Base
-blocks.productiontime = Tempo di Produzione
-blocks.repairtime = Tempo di Riparazione Completa
-blocks.speedincrease = Aumento Velocità
-blocks.range = Raggio
-blocks.drilltier = Scavabili
-blocks.drillspeed = Velocità di Scavo Stabile
-blocks.boosteffect = Effetto Boost
-blocks.maxunits = Unità Attive Max
-blocks.health = Salute
-blocks.buildtime = Tempo di Costruzione
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Costo di Costruzione
-blocks.inaccuracy = Inaccuratezza
-blocks.shots = Colpi
-blocks.reload = Ricarica
-blocks.ammo = Munizioni
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Capacità Energetica
+stat.powershot = Danno/Colpo
+stat.damage = Danno
+stat.targetsair = Attacca Nemici Aerei
+stat.targetsground = Attacca Nemici Terreni
+stat.itemsmoved = Velocità di Movimento
+stat.launchtime = Tempo fra Decolli
+stat.shootrange = Raggio
+stat.size = Dimensioni
+stat.displaysize = Display Size
+stat.liquidcapacity = Capacità del Liquido
+stat.powerrange = Raggio Energia
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Connessioni Massime
+stat.poweruse = Utilizzo Energia
+stat.powerdamage = Energia/Danno
+stat.itemcapacity = Capacità
+stat.basepowergeneration = Generazione Energia di Base
+stat.productiontime = Tempo di Produzione
+stat.repairtime = Tempo di Riparazione Completa
+stat.speedincrease = Aumento Velocità
+stat.range = Raggio
+stat.drilltier = Scavabili
+stat.drillspeed = Velocità di Scavo Stabile
+stat.boosteffect = Effetto Boost
+stat.maxunits = Unità Attive Max
+stat.health = Salute
+stat.buildtime = Tempo di Costruzione
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Costo di Costruzione
+stat.inaccuracy = Inaccuratezza
+stat.shots = Colpi
+stat.reload = Ricarica
+stat.ammo = Munizioni
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Miglior Trivella Richiesta
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = Una grande torretta a fuoco rapido.
block.spectre.description = Una grande torretta che spara due potenti proiettili contemporaneamente.
block.meltdown.description = Una grande torretta che spara un potente laser a lungo raggio.
block.repair-point.description = Cura continuamente l'unità danneggiata più vicina.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_ja.properties b/core/assets/bundles/bundle_ja.properties
index fdb915ff96..68c766e79b 100644
--- a/core/assets/bundles/bundle_ja.properties
+++ b/core/assets/bundles/bundle_ja.properties
@@ -570,49 +570,49 @@ info.title = 情報
error.title = [crimson]エラーが発生しました
error.crashtitle = エラーが発生しました
unit.nobuild = [scarlet]ユニットを構築できません
-blocks.input = 搬入
-blocks.output = 搬出
-blocks.booster = ブースト
-blocks.tiles = 必要なタイル
-blocks.affinities = 親和性
+stat.input = 搬入
+stat.output = 搬出
+stat.booster = ブースト
+stat.tiles = 必要なタイル
+stat.affinities = 親和性
block.unknown = [lightgray]???
-blocks.powercapacity = 電力容量
-blocks.powershot = 電力/ショット
-blocks.damage = ダメージ
-blocks.targetsair = 対空攻撃
-blocks.targetsground = 対地攻撃
-blocks.itemsmoved = 輸送速度
-blocks.launchtime = 発射の待機時間
-blocks.shootrange = 範囲
-blocks.size = 大きさ
-blocks.displaysize = Display Size
-blocks.liquidcapacity = 液体容量
-blocks.powerrange = 電力範囲
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = 最大接続数
-blocks.poweruse = 電力使用量
-blocks.powerdamage = 電力/ダメージ
-blocks.itemcapacity = アイテム容量
-blocks.basepowergeneration = 基本発電量
-blocks.productiontime = 製造速度
-blocks.repairtime = ブロックの完全修復速度
-blocks.speedincrease = 速度向上
-blocks.range = 範囲
-blocks.drilltier = ドリル
-blocks.drillspeed = 基本採掘速度
-blocks.boosteffect = ブースト効果
-blocks.maxunits = 最大ユニット数
-blocks.health = 耐久値
-blocks.buildtime = 建設時間
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = 建設費用
-blocks.inaccuracy = 誤差
-blocks.shots = ショット
-blocks.reload = リロード速度
-blocks.ammo = 弾薬
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = 電力容量
+stat.powershot = 電力/ショット
+stat.damage = ダメージ
+stat.targetsair = 対空攻撃
+stat.targetsground = 対地攻撃
+stat.itemsmoved = 輸送速度
+stat.launchtime = 発射の待機時間
+stat.shootrange = 範囲
+stat.size = 大きさ
+stat.displaysize = Display Size
+stat.liquidcapacity = 液体容量
+stat.powerrange = 電力範囲
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = 最大接続数
+stat.poweruse = 電力使用量
+stat.powerdamage = 電力/ダメージ
+stat.itemcapacity = アイテム容量
+stat.basepowergeneration = 基本発電量
+stat.productiontime = 製造速度
+stat.repairtime = ブロックの完全修復速度
+stat.speedincrease = 速度向上
+stat.range = 範囲
+stat.drilltier = ドリル
+stat.drillspeed = 基本採掘速度
+stat.boosteffect = ブースト効果
+stat.maxunits = 最大ユニット数
+stat.health = 耐久値
+stat.buildtime = 建設時間
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = 建設費用
+stat.inaccuracy = 誤差
+stat.shots = ショット
+stat.reload = リロード速度
+stat.ammo = 弾薬
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = より高性能なドリルを使用してください
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = 大型の連射型ターレットです。
block.spectre.description = 一度に2発の強力な弾を放つ大型のターレットです。
block.meltdown.description = 強力な長距離攻撃が可能な大型のターレットです。
block.repair-point.description = 近くの負傷したユニットを修復します。
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties
index 87f3d00a1b..82bb299642 100644
--- a/core/assets/bundles/bundle_ko.properties
+++ b/core/assets/bundles/bundle_ko.properties
@@ -115,7 +115,7 @@ mod.disable = 비활성화
mod.content = 콘텐츠:
mod.delete.error = 모드를 삭제할 수 없습니다. 파일이 사용 중일 수 있습니다.
mod.requiresversion = [scarlet]필요한 최소 게임 버전: [accent]{0}
-mod.outdated = [scarlet]Not compatible with V6 (no minGameVersion: 105)
+mod.outdated = [scarlet]V6 전용이 아닌 모드 (minGameVersion: 105 누락)
mod.missingdependencies = [scarlet]누락된 요구 모드: {0}
mod.erroredcontent = [scarlet]콘텐츠 오류
mod.errors = 콘텐츠를 로드하는 동안 오류가 발생함.
@@ -148,7 +148,7 @@ techtree = 연구 기록
research.list = [lightgray]연구:
research = 연구
researched = [lightgray]{0} 연구 완료.
-research.progress = {0}% complete
+research.progress = {0}% 완료
players = {0} 플레이어들
players.single = {0} 플레이어
players.search = 검색
@@ -335,7 +335,7 @@ waves.never = 여기까지 유닛생성
waves.every = 매
waves.waves = 웨이브마다
waves.perspawn = 생성
-waves.shields = 보호막/웨이브
+waves.shields = 방어막/웨이브
waves.to = 부터
waves.guardian = 보호자
waves.preview = 미리보기
@@ -469,8 +469,8 @@ locked = 잠김
complete = [lightgray]해금 조건 :
requirement.wave = {1}지역에서 {0}웨이브 달성
requirement.core = {0}지역에서 적 코어를 파괴
-requirement.research = Research {0}
-requirement.capture = Capture {0}
+requirement.research = {0} 연구
+requirement.capture = {0} 점령
resume = 지역 재개:\n[lightgray]{0}
bestwave = [lightgray]최고 웨이브: {0}
launch = < 출격 >
@@ -508,10 +508,10 @@ error.io = 네트워크 I/O 오류.
error.any = 알 수 없는 네트워크 오류.
error.bloom = 블룸 그래픽 효과를 적용하지 못했습니다.\n당신의 기기가 이 기능을 지원하지 않는 것일 수도 있습니다.
-weather.rain.name = Rain
-weather.snow.name = Snow
-weather.sandstorm.name = Sandstorm
-weather.sporestorm.name = Sporestorm
+weather.rain.name = 비
+weather.snow.name = 눈
+weather.sandstorm.name = 모래폭풍
+weather.sporestorm.name = 포자폭풍
sectors.unexplored = [lightgray]Unexplored
sectors.resources = Resources:
@@ -570,49 +570,49 @@ info.title = 정보
error.title = [scarlet]오류가 발생했습니다.
error.crashtitle = 오류가 발생했습니다
unit.nobuild = [scarlet]이 유닛은 건설할 수 없습니다.
-blocks.input = 입력
-blocks.output = 출력
-blocks.booster = 가속
-blocks.tiles = 필요한 타일
-blocks.affinities = 친화력
+stat.input = 입력
+stat.output = 출력
+stat.booster = 가속
+stat.tiles = 필요한 타일
+stat.affinities = 친화력
block.unknown = [lightgray]???
-blocks.powercapacity = 전력 용량
-blocks.powershot = 전력/발
-blocks.damage = 공격력
-blocks.targetsair = 공중 공격
-blocks.targetsground = 지상 공격
-blocks.itemsmoved = 이동 속도
-blocks.launchtime = 출격 간격
-blocks.shootrange = 사거리
-blocks.size = 크기
-blocks.displaysize = Display Size
-blocks.liquidcapacity = 액체 용량
-blocks.powerrange = 전력 범위
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = 최대 연결 수
-blocks.poweruse = 전력 사용
-blocks.powerdamage = 전력/데미지
-blocks.itemcapacity = 저장 용량
-blocks.basepowergeneration = 기본 전력 생성량
-blocks.productiontime = 제작 시간
-blocks.repairtime = 전체 블록 수리시간
-blocks.speedincrease = 속도 증가
-blocks.range = 사거리
-blocks.drilltier = 드릴
-blocks.drillspeed = 기본 드릴 속도
-blocks.boosteffect = 가속 효과
-blocks.maxunits = 최대 활성 유닛수
-blocks.health = 체력
-blocks.buildtime = 건설 시간
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = 건설 재료
-blocks.inaccuracy = 오차각
-blocks.shots = 공격 속도
-blocks.reload = 발/초
-blocks.ammo = 탄약
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = 전력 용량
+stat.powershot = 전력/발
+stat.damage = 공격력
+stat.targetsair = 공중 공격
+stat.targetsground = 지상 공격
+stat.itemsmoved = 이동 속도
+stat.launchtime = 출격 간격
+stat.shootrange = 사거리
+stat.size = 크기
+stat.displaysize = Display Size
+stat.liquidcapacity = 액체 용량
+stat.powerrange = 전력 범위
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = 최대 연결 수
+stat.poweruse = 전력 사용
+stat.powerdamage = 전력/데미지
+stat.itemcapacity = 저장 용량
+stat.basepowergeneration = 기본 전력 생성량
+stat.productiontime = 제작 시간
+stat.repairtime = 전체 블록 수리시간
+stat.speedincrease = 속도 증가
+stat.range = 사거리
+stat.drilltier = 드릴
+stat.drillspeed = 기본 드릴 속도
+stat.boosteffect = 가속 효과
+stat.maxunits = 최대 활성 유닛수
+stat.health = 체력
+stat.buildtime = 건설 시간
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = 건설 재료
+stat.inaccuracy = 오차각
+stat.shots = 공격 속도
+stat.reload = 발/초
+stat.ammo = 탄약
+stat.shieldhealth = 보호막 체력
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = 더 좋은 드릴이 필요
bar.noresources = 자원 부족
@@ -1109,7 +1109,7 @@ block.cyclone.name = 사이클론
block.fuse.name = 퓨즈
block.shock-mine.name = 전격 지뢰
block.overdrive-projector.name = 과부하 프로젝터
-block.force-projector.name = 포스 프로젝터
+block.force-projector.name = 보호막 프로젝터
block.arc.name = 아크
block.rtg-generator.name = RTG 발전기
block.spectre.name = 스펙터
@@ -1118,27 +1118,27 @@ block.container.name = 컨테이너
block.launch-pad.name = 출격 패드
block.launch-pad-large.name = 대형 출격 패드
block.segment.name = 세그먼트
-block.command-center.name = Command Center
+block.command-center.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.tetrative-reconstructor.name = 발산 재구성기
block.payload-conveyor.name = 화물 컨베이어
block.payload-router.name = 화물 분배기
block.disassembler.name = 가속 분해기
block.silicon-crucible.name = 실리콘 도가니
block.overdrive-dome.name = 대형 과부하 프로젝터
-block.switch.name = Switch
-block.micro-processor.name = Micro Processor
-block.logic-processor.name = Logic Processor
-block.hyper-processor.name = Hyper Processor
-block.logic-display.name = Logic Display
-block.large-logic-display.name = Large Logic Display
-block.memory-cell.name = Memory Cell
+block.switch.name = 스위치
+block.micro-processor.name = 소형 프로세서
+block.logic-processor.name = 명령 프로세서
+block.hyper-processor.name = 하이퍼 프로세서
+block.logic-display.name = 화면
+block.large-logic-display.name = 대형 화면
+block.memory-cell.name = 기억 블록
team.blue.name = 파랑색 팀
team.crux.name = 빨강색 팀
@@ -1241,7 +1241,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.distributor.description = 고급 분배기. 자원을 최대 7개의 다른 방향으로 동일하게 분할합니다.
block.overflow-gate.description = 전면 경로가 차단 된 경우에만 왼쪽과 오른쪽으로 출력됩니다.
block.underflow-gate.description = 오버플로 게이트의 반대. 왼쪽 및 오른쪽 경로가 차단되면 전면으로 출력됩니다.
@@ -1252,7 +1252,7 @@ block.thermal-pump.description = 가장 강력한 펌프.
block.conduit.description = 기본 액체 운송 블록. 액체를 앞으로 이동시킵미다. 펌프 및 기타 파이프와 함께 사용됩니다.
block.pulse-conduit.description = 고급 액체 운송 블록. 액체를 더 빠르게 운반하고 표준 파이프보다 더 많이 저장합니다.
block.plated-conduit.description = 펄스 파이프와 같은 속도로 이동하지만 더 높은 방어력을 가지고 있습니다. 파이프 이외의 물체로 측면의 액체를 받아들이지 않습니다.\n누설이 적습니다.
-block.liquid-router.description = 한 방향에서 액체를 받아 최대 3개의 다른 방향으로 동일하게 출력합니다. 일정량의 액체를 저장할 수도 있으며 한 소스에서 여러 대상으로 액체를 분할하는 데 유용합니다.
+block.liquid-router.description = 한 방향에서 액체를 받아 최대 3개의 다른 방향으로 동일하게 출력합니다. 일정량의 액체를 저장할 수도 있으며 한 공급원에서 여러 대상으로 액체를 분할하는 데 유용합니다.
block.liquid-tank.description = 대량의 액체를 저장합니다. 재료가 일정하지 않은 상황에서 버퍼를 생성하거나 중요한 블록을 냉각하기 위한 보호 장치로 사용하세요.
block.liquid-junction.description = 두 개의 교차 파이프를 위한 다리 역할을 합니다. 다른 액체를 다른 위치로 운반하는 두 개의 다른 파이프가 있는 상황에서 유용합니다.
block.bridge-conduit.description = 고급 액체 운송 블록. 지형이나 건물을 넘어 최대 3개 타일 위로 액체를 운반할 수 있습니다.
@@ -1302,4 +1302,4 @@ block.cyclone.description = 대공 및 대지 포탑. 근처 유닛에게 폭발
block.spectre.description = 거대한 이중 배럴 대포. 공중 및 지상 목표물에 큰 관통 철갑탄을 발사합니다.
block.meltdown.description = 거대한 레이저 대포. 근처의 적에게 지속적인 레이버 빔을 충전하여 발사합니다. 냉각수가 있어야 작동합니다.
block.repair-point.description = 주변에서 가장 가까운 유닛을 지속적으로 치료합니다.
-block.segment.description = 날아오는 발사체를 요격합니다. 레이저는 목표 대상이 아닙니다.
+block.segment.description = 날아오는 발사체를 요격합니다. 레이저는 목표 대상이 아닙니다.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_lt.properties b/core/assets/bundles/bundle_lt.properties
index a318c53f5f..2ebd273b5a 100644
--- a/core/assets/bundles/bundle_lt.properties
+++ b/core/assets/bundles/bundle_lt.properties
@@ -570,49 +570,49 @@ info.title = Informacija
error.title = [crimson]Įvyko klaida
error.crashtitle = Įvyko klaida
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Įeiga
-blocks.output = Išeiga
-blocks.booster = Stiprintuvas
-blocks.tiles = Privalomi
-blocks.affinities = Affinities
+stat.input = Įeiga
+stat.output = Išeiga
+stat.booster = Stiprintuvas
+stat.tiles = Privalomi
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Energijos Talpumas
-blocks.powershot = Energija per šūvį
-blocks.damage = Žala
-blocks.targetsair = Šaudo į oro taikinius
-blocks.targetsground = Šaudo į žemės taikinius
-blocks.itemsmoved = Judėjimo Greitis
-blocks.launchtime = Laikas Tarp Paleidimų
-blocks.shootrange = Atstumas
-blocks.size = Dydis
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Skysčių Talpumas
-blocks.powerrange = Energijos Skleidimo Atstumas
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Maks. Jungčių Kiekis
-blocks.poweruse = Energijos Suvartojimas
-blocks.powerdamage = Power/Damage
-blocks.itemcapacity = Daiktų Talpumas
-blocks.basepowergeneration = Bazinis Energijos Generavimas
-blocks.productiontime = Gamybos Laikas
-blocks.repairtime = Pilnas bloko sutaisymo laikas
-blocks.speedincrease = Greičio Padidėjimas
-blocks.range = Atstumas
-blocks.drilltier = Gręžiama
-blocks.drillspeed = Bazinis Grąžto Greitis
-blocks.boosteffect = Pastiprinimo Efektas
-blocks.maxunits = Maks. Aktyvių Vienetų Kiekis
-blocks.health = Gyvybės
-blocks.buildtime = Statymo Laikas
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Statymo Kaina
-blocks.inaccuracy = Netikslumas
-blocks.shots = Šūviai
-blocks.reload = Šūviai per sekundę
-blocks.ammo = Šoviniai
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Energijos Talpumas
+stat.powershot = Energija per šūvį
+stat.damage = Žala
+stat.targetsair = Šaudo į oro taikinius
+stat.targetsground = Šaudo į žemės taikinius
+stat.itemsmoved = Judėjimo Greitis
+stat.launchtime = Laikas Tarp Paleidimų
+stat.shootrange = Atstumas
+stat.size = Dydis
+stat.displaysize = Display Size
+stat.liquidcapacity = Skysčių Talpumas
+stat.powerrange = Energijos Skleidimo Atstumas
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Maks. Jungčių Kiekis
+stat.poweruse = Energijos Suvartojimas
+stat.powerdamage = Power/Damage
+stat.itemcapacity = Daiktų Talpumas
+stat.basepowergeneration = Bazinis Energijos Generavimas
+stat.productiontime = Gamybos Laikas
+stat.repairtime = Pilnas bloko sutaisymo laikas
+stat.speedincrease = Greičio Padidėjimas
+stat.range = Atstumas
+stat.drilltier = Gręžiama
+stat.drillspeed = Bazinis Grąžto Greitis
+stat.boosteffect = Pastiprinimo Efektas
+stat.maxunits = Maks. Aktyvių Vienetų Kiekis
+stat.health = Gyvybės
+stat.buildtime = Statymo Laikas
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Statymo Kaina
+stat.inaccuracy = Netikslumas
+stat.shots = Šūviai
+stat.reload = Šūviai per sekundę
+stat.ammo = Šoviniai
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Privalomas Geresnis Grąžtas
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = Didelis bokštas puolantis, tiek žemę, tiek orą.
block.spectre.description = Milžiniškas dvivamzdis bokštas. Šaudo didelius, kiaurai per šarvus einančius šovinius į taikinius esančius ant žemės ir ore.
block.meltdown.description = Milžiniška lazerinė patranka. Užsikrauna ir šaudo lazerinius spindulius į aplinkinius priešus. Veikimui reikalingas aušinimo skystis.
block.repair-point.description = Pastoviai gydo artimiausius netoliese esančius vienetus.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_nl.properties b/core/assets/bundles/bundle_nl.properties
index 634b6eb00e..41d6e8a8fc 100644
--- a/core/assets/bundles/bundle_nl.properties
+++ b/core/assets/bundles/bundle_nl.properties
@@ -570,49 +570,49 @@ info.title = Informatie
error.title = [crimson]Een fout is opgetreden
error.crashtitle = Een fout is opgetreden
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Input
-blocks.output = Output
-blocks.booster = Booster
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Input
+stat.output = Output
+stat.booster = Booster
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Stroomcapaciteit
-blocks.powershot = Stroom/Schot
-blocks.damage = Schade
-blocks.targetsair = Luchtdoelwitten
-blocks.targetsground = Gronddoelwitten
-blocks.itemsmoved = Beweegingssnelheid
-blocks.launchtime = Tijd tussen lanceringen
-blocks.shootrange = Bereik
-blocks.size = Formaat
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Vloeistofcapaciteit
-blocks.powerrange = Stroombereik
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Maximale Hoeveelheid Connecties
-blocks.poweruse = Stroomverbruik
-blocks.powerdamage = Stroom/Schade
-blocks.itemcapacity = Materiaalcapaciteit
-blocks.basepowergeneration = Standaard Stroom Generatie
-blocks.productiontime = Productie Tijd
-blocks.repairtime = Volledige Blok Repareertijd
-blocks.speedincrease = Snelheidsverhoging
-blocks.range = Bereik
-blocks.drilltier = Valt te delven
-blocks.drillspeed = Standaard mine snelheid
-blocks.boosteffect = Boost Effect
-blocks.maxunits = Maximaal Actieve Units
-blocks.health = Levenspunten
-blocks.buildtime = Bouwtijd
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Bouwkosten
-blocks.inaccuracy = Onnauwkeurigheid
-blocks.shots = Shoten
-blocks.reload = Schoten/Seconde
-blocks.ammo = Ammunitie
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Stroomcapaciteit
+stat.powershot = Stroom/Schot
+stat.damage = Schade
+stat.targetsair = Luchtdoelwitten
+stat.targetsground = Gronddoelwitten
+stat.itemsmoved = Beweegingssnelheid
+stat.launchtime = Tijd tussen lanceringen
+stat.shootrange = Bereik
+stat.size = Formaat
+stat.displaysize = Display Size
+stat.liquidcapacity = Vloeistofcapaciteit
+stat.powerrange = Stroombereik
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Maximale Hoeveelheid Connecties
+stat.poweruse = Stroomverbruik
+stat.powerdamage = Stroom/Schade
+stat.itemcapacity = Materiaalcapaciteit
+stat.basepowergeneration = Standaard Stroom Generatie
+stat.productiontime = Productie Tijd
+stat.repairtime = Volledige Blok Repareertijd
+stat.speedincrease = Snelheidsverhoging
+stat.range = Bereik
+stat.drilltier = Valt te delven
+stat.drillspeed = Standaard mine snelheid
+stat.boosteffect = Boost Effect
+stat.maxunits = Maximaal Actieve Units
+stat.health = Levenspunten
+stat.buildtime = Bouwtijd
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Bouwkosten
+stat.inaccuracy = Onnauwkeurigheid
+stat.shots = Shoten
+stat.reload = Schoten/Seconde
+stat.ammo = Ammunitie
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Betere miner nodig
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = A large rapid fire turret.
block.spectre.description = A large turret which shoots two powerful bullets at once.
block.meltdown.description = A large turret which shoots powerful long-range beams.
block.repair-point.description = Continuously heals the closest damaged unit in its vicinity.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_nl_BE.properties b/core/assets/bundles/bundle_nl_BE.properties
index ce59b257f7..4f2ed1fdcd 100644
--- a/core/assets/bundles/bundle_nl_BE.properties
+++ b/core/assets/bundles/bundle_nl_BE.properties
@@ -570,49 +570,49 @@ info.title = Info
error.title = [crimson]An error has occured
error.crashtitle = An error has occured
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Input
-blocks.output = Output
-blocks.booster = Booster
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Input
+stat.output = Output
+stat.booster = Booster
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Power Capacity
-blocks.powershot = Power/Shot
-blocks.damage = Damage
-blocks.targetsair = Targets Air
-blocks.targetsground = Targets Ground
-blocks.itemsmoved = Move Speed
-blocks.launchtime = Time Between Launches
-blocks.shootrange = Range
-blocks.size = Size
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Liquid Capacity
-blocks.powerrange = Power Range
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Max Connections
-blocks.poweruse = Power Use
-blocks.powerdamage = Power/Damage
-blocks.itemcapacity = Item Capacity
-blocks.basepowergeneration = Base Power Generation
-blocks.productiontime = Production Time
-blocks.repairtime = Block Full Repair Time
-blocks.speedincrease = Speed Increase
-blocks.range = Range
-blocks.drilltier = Drillables
-blocks.drillspeed = Base Drill Speed
-blocks.boosteffect = Boost Effect
-blocks.maxunits = Max Active Units
-blocks.health = Health
-blocks.buildtime = Build Time
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Build Cost
-blocks.inaccuracy = Inaccuracy
-blocks.shots = Shots
-blocks.reload = Shots/Second
-blocks.ammo = Ammo
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Power Capacity
+stat.powershot = Power/Shot
+stat.damage = Damage
+stat.targetsair = Targets Air
+stat.targetsground = Targets Ground
+stat.itemsmoved = Move Speed
+stat.launchtime = Time Between Launches
+stat.shootrange = Range
+stat.size = Size
+stat.displaysize = Display Size
+stat.liquidcapacity = Liquid Capacity
+stat.powerrange = Power Range
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Max Connections
+stat.poweruse = Power Use
+stat.powerdamage = Power/Damage
+stat.itemcapacity = Item Capacity
+stat.basepowergeneration = Base Power Generation
+stat.productiontime = Production Time
+stat.repairtime = Block Full Repair Time
+stat.speedincrease = Speed Increase
+stat.range = Range
+stat.drilltier = Drillables
+stat.drillspeed = Base Drill Speed
+stat.boosteffect = Boost Effect
+stat.maxunits = Max Active Units
+stat.health = Health
+stat.buildtime = Build Time
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Build Cost
+stat.inaccuracy = Inaccuracy
+stat.shots = Shots
+stat.reload = Shots/Second
+stat.ammo = Ammo
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Better Drill Required
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = A large rapid fire turret.
block.spectre.description = A large turret which shoots two powerful bullets at once.
block.meltdown.description = A large turret which shoots powerful long-range beams.
block.repair-point.description = Continuously heals the closest damaged unit in its vicinity.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties
index f0c67c6a88..80502bb870 100644
--- a/core/assets/bundles/bundle_pl.properties
+++ b/core/assets/bundles/bundle_pl.properties
@@ -570,49 +570,49 @@ info.title = Informacje
error.title = [crimson]Wystąpił błąd
error.crashtitle = Wystąpił błąd
unit.nobuild = [scarlet]Jednostka nie może budować
-blocks.input = Wejście
-blocks.output = Wyjście
-blocks.booster = Wzmacniacz
-blocks.tiles = Wymagane Pola
-blocks.affinities = Uwydajnienie
+stat.input = Wejście
+stat.output = Wyjście
+stat.booster = Wzmacniacz
+stat.tiles = Wymagane Pola
+stat.affinities = Uwydajnienie
block.unknown = [lightgray]???
-blocks.powercapacity = Pojemność mocy
-blocks.powershot = moc/strzał
-blocks.damage = Obrażenia
-blocks.targetsair = Namierzanie wrogów powietrznych
-blocks.targetsground = Namierzanie wrogów lądowych
-blocks.itemsmoved = Prędkość poruszania się
-blocks.launchtime = Czas pomiędzy wystrzeleniami
-blocks.shootrange = Zasięg
-blocks.size = Rozmiar
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Pojemność cieczy
-blocks.powerrange = Zakres mocy
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Maksymalna ilość połączeń
-blocks.poweruse = Zużycie prądu
-blocks.powerdamage = Moc/Zniszczenia
-blocks.itemcapacity = Pojemność przedmiotów
-blocks.basepowergeneration = Podstawowa generacja mocy
-blocks.productiontime = Czas produkcji
-blocks.repairtime = Czas pełnej naprawy bloku
-blocks.speedincrease = Zwiększenie prędkości
-blocks.range = Zasięg
-blocks.drilltier = Co może wykopać
-blocks.drillspeed = Podstawowa szybkość kopania
-blocks.boosteffect = Efekt wzmocnienia
-blocks.maxunits = Maksymalna ilość jednostek
-blocks.health = Zdrowie
-blocks.buildtime = Czas budowy
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Koszt budowy
-blocks.inaccuracy = Niecelność
-blocks.shots = Strzały
-blocks.reload = Strzałów/sekundę
-blocks.ammo = Amunicja
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Pojemność mocy
+stat.powershot = moc/strzał
+stat.damage = Obrażenia
+stat.targetsair = Namierzanie wrogów powietrznych
+stat.targetsground = Namierzanie wrogów lądowych
+stat.itemsmoved = Prędkość poruszania się
+stat.launchtime = Czas pomiędzy wystrzeleniami
+stat.shootrange = Zasięg
+stat.size = Rozmiar
+stat.displaysize = Display Size
+stat.liquidcapacity = Pojemność cieczy
+stat.powerrange = Zakres mocy
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Maksymalna ilość połączeń
+stat.poweruse = Zużycie prądu
+stat.powerdamage = Moc/Zniszczenia
+stat.itemcapacity = Pojemność przedmiotów
+stat.basepowergeneration = Podstawowa generacja mocy
+stat.productiontime = Czas produkcji
+stat.repairtime = Czas pełnej naprawy bloku
+stat.speedincrease = Zwiększenie prędkości
+stat.range = Zasięg
+stat.drilltier = Co może wykopać
+stat.drillspeed = Podstawowa szybkość kopania
+stat.boosteffect = Efekt wzmocnienia
+stat.maxunits = Maksymalna ilość jednostek
+stat.health = Zdrowie
+stat.buildtime = Czas budowy
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Koszt budowy
+stat.inaccuracy = Niecelność
+stat.shots = Strzały
+stat.reload = Strzałów/sekundę
+stat.ammo = Amunicja
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Wymagane Lepsze Wiertło
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = Duża szybkostrzelna wieża.
block.spectre.description = Duże działo dwulufowe, które strzela potężnymi pociskami przebijającymi pancerz w jednostki naziemne i powietrzne.
block.meltdown.description = Duże działo laserowe, które strzela potężnymi wiązkami dalekiego zasięgu. Wymaga chłodzenia.
block.repair-point.description = Bez przerw naprawia najbliższą uszkodzoną jednostkę w jego zasięgu.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties
index 7754faa059..7f2659d839 100644
--- a/core/assets/bundles/bundle_pt_BR.properties
+++ b/core/assets/bundles/bundle_pt_BR.properties
@@ -570,49 +570,49 @@ info.title = [accent]Informação
error.title = [crimson]Ocorreu um Erro.
error.crashtitle = Ocorreu um Erro
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Entrada
-blocks.output = Saída
-blocks.booster = Apoio
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Entrada
+stat.output = Saída
+stat.booster = Apoio
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Capacidade de Energia
-blocks.powershot = Energia/tiro
-blocks.damage = Dano
-blocks.targetsair = Mira no ar
-blocks.targetsground = Mira no chão
-blocks.itemsmoved = Velocidade de movimento
-blocks.launchtime = Tempo entre Disparos.
-blocks.shootrange = Alcance
-blocks.size = Tamanho
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Capacidade de Líquido
-blocks.powerrange = Alcance da Energia
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Conexões Máximas
-blocks.poweruse = Uso de energia
-blocks.powerdamage = Dano/Poder
-blocks.itemcapacity = Capacidade de Itens
-blocks.basepowergeneration = Geração de poder base
-blocks.productiontime = Tempo de produção
-blocks.repairtime = Tempo de reparo total do bloco
-blocks.speedincrease = Aumento de velocidade
-blocks.range = Distância
-blocks.drilltier = Brocas
-blocks.drillspeed = Velocidade base da Broca
-blocks.boosteffect = Efeito do Impulso
-blocks.maxunits = Máximo de unidades ativas
-blocks.health = Saúde
-blocks.buildtime = Tempo de construção
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Custo de construção
-blocks.inaccuracy = Imprecisão
-blocks.shots = Tiros
-blocks.reload = Tiros por segundo
-blocks.ammo = Munição
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Capacidade de Energia
+stat.powershot = Energia/tiro
+stat.damage = Dano
+stat.targetsair = Mira no ar
+stat.targetsground = Mira no chão
+stat.itemsmoved = Velocidade de movimento
+stat.launchtime = Tempo entre Disparos.
+stat.shootrange = Alcance
+stat.size = Tamanho
+stat.displaysize = Display Size
+stat.liquidcapacity = Capacidade de Líquido
+stat.powerrange = Alcance da Energia
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Conexões Máximas
+stat.poweruse = Uso de energia
+stat.powerdamage = Dano/Poder
+stat.itemcapacity = Capacidade de Itens
+stat.basepowergeneration = Geração de poder base
+stat.productiontime = Tempo de produção
+stat.repairtime = Tempo de reparo total do bloco
+stat.speedincrease = Aumento de velocidade
+stat.range = Distância
+stat.drilltier = Brocas
+stat.drillspeed = Velocidade base da Broca
+stat.boosteffect = Efeito do Impulso
+stat.maxunits = Máximo de unidades ativas
+stat.health = Saúde
+stat.buildtime = Tempo de construção
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Custo de construção
+stat.inaccuracy = Imprecisão
+stat.shots = Tiros
+stat.reload = Tiros por segundo
+stat.ammo = Munição
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Broca melhor necessária.
bar.noresources = Missing Resources
@@ -1021,7 +1021,7 @@ block.thorium-wall-large.name = Muralha de Tório
block.door.name = Porta
block.door-large.name = Portão
block.duo.name = Torreta dupla
-block.scorch.name = Lança-fogo
+block.scorch.name = Lança-chamas
block.scatter.name = Dispersão
block.hail.name = Artilharia
block.lancer.name = Lanceiro
@@ -1038,8 +1038,8 @@ block.inverted-sorter.name = Ordenador invertido
block.message.name = Mensagem
block.illuminator.name = Iluminador
block.illuminator.description = Uma pequena, compacta e configurável fonte de luz. Precisa de energia para funcionar.
-block.overflow-gate.name = Comporta
-block.underflow-gate.name = Comporta invertida
+block.overflow-gate.name = Portão Sobrecarregado
+block.underflow-gate.name = Portão Sobrecarregado invertida
block.silicon-smelter.name = Fundidora de silicio
block.phase-weaver.name = Palheta de fase
block.pulverizer.name = Pulverizador
@@ -1077,7 +1077,7 @@ block.vault.name = Cofre
block.wave.name = Onda
block.swarmer.name = Enxame
block.salvo.name = Salvo
-block.ripple.name = Ondulação
+block.ripple.name = Morteiro
block.phase-conveyor.name = Transportador de Fase
block.bridge-conveyor.name = Esteira-Ponte
block.plastanium-compressor.name = Compressor de Plastânio
@@ -1087,8 +1087,8 @@ block.solar-panel.name = Painel Solar
block.solar-panel-large.name = Painel Solar Grande
block.oil-extractor.name = Bomba de Petróleo
block.repair-point.name = Ponto de Reparo
-block.pulse-conduit.name = Cano de Tinânio
-block.plated-conduit.name = Cano blindado
+block.pulse-conduit.name = Cano de Pulso
+block.plated-conduit.name = Cano Blindado
block.phase-conduit.name = Cano de Fase
block.liquid-router.name = Roteador de Líquido
block.liquid-tank.name = Tanque de Líquido
@@ -1110,7 +1110,7 @@ block.fuse.name = Fusivel
block.shock-mine.name = Mina de choque
block.overdrive-projector.name = Projetor de sobrecarga
block.force-projector.name = Projetor de campo de força
-block.arc.name = Bobina de Tesla
+block.arc.name = Tesla
block.rtg-generator.name = Gerador GTR
block.spectre.name = Espectro
block.meltdown.name = Fusão
@@ -1302,4 +1302,4 @@ block.cyclone.description = Uma grande torre que dispara balas explosivas que se
block.spectre.description = Um grande canhão massivo. Dispara grandes tiros perfuradores de blindagem em inimigos aéreos e terrestres.
block.meltdown.description = Um grande canhão laser massivo. Carrega e dispara um poderoso e persistente feixe nos seus inimigos. Requer uma refrigeração para ser operada.
block.repair-point.description = Continuamente repara a unidade danificada mais proxima.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Destrói projéteis inimigos. Projéteis de laser não são afetados.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_pt_PT.properties b/core/assets/bundles/bundle_pt_PT.properties
index 0b6948191b..c4b5070b3a 100644
--- a/core/assets/bundles/bundle_pt_PT.properties
+++ b/core/assets/bundles/bundle_pt_PT.properties
@@ -570,49 +570,49 @@ info.title = [accent]Informação
error.title = [crimson]Ocorreu um Erro.
error.crashtitle = Ocorreu um Erro
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Entrada
-blocks.output = Saida
-blocks.booster = Booster
-blocks.tiles = Telhas Requeridas
-blocks.affinities = Afinidades
+stat.input = Entrada
+stat.output = Saida
+stat.booster = Booster
+stat.tiles = Telhas Requeridas
+stat.affinities = Afinidades
block.unknown = [lightgray]???
-blocks.powercapacity = Capacidade de Energia
-blocks.powershot = Energia/tiro
-blocks.damage = Dano
-blocks.targetsair = Mirar no ar
-blocks.targetsground = Mirar no chão
-blocks.itemsmoved = Velocidade de movimento
-blocks.launchtime = Tempo entre tiros
-blocks.shootrange = Alcance
-blocks.size = Tamanho
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Capacidade de Líquido
-blocks.powerrange = Alcance da Energia
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Max Connections
-blocks.poweruse = Uso de energia
-blocks.powerdamage = Dano/Poder
-blocks.itemcapacity = Capacidade de Itens
-blocks.basepowergeneration = Geração de poder base
-blocks.productiontime = Tempo de produção
-blocks.repairtime = Tempo de reparo total do bloco
-blocks.speedincrease = Aumento de velocidade
-blocks.range = Distância
-blocks.drilltier = Furáveis
-blocks.drillspeed = Velocidade da broca base
-blocks.boosteffect = Efeito do Boost
-blocks.maxunits = Máximo de unidades ativas
-blocks.health = Saúde
-blocks.buildtime = Tempo de construção
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Custo de construção
-blocks.inaccuracy = Imprecisão
-blocks.shots = Tiros
-blocks.reload = Tiros por segundo
-blocks.ammo = Munição
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Capacidade de Energia
+stat.powershot = Energia/tiro
+stat.damage = Dano
+stat.targetsair = Mirar no ar
+stat.targetsground = Mirar no chão
+stat.itemsmoved = Velocidade de movimento
+stat.launchtime = Tempo entre tiros
+stat.shootrange = Alcance
+stat.size = Tamanho
+stat.displaysize = Display Size
+stat.liquidcapacity = Capacidade de Líquido
+stat.powerrange = Alcance da Energia
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Max Connections
+stat.poweruse = Uso de energia
+stat.powerdamage = Dano/Poder
+stat.itemcapacity = Capacidade de Itens
+stat.basepowergeneration = Geração de poder base
+stat.productiontime = Tempo de produção
+stat.repairtime = Tempo de reparo total do bloco
+stat.speedincrease = Aumento de velocidade
+stat.range = Distância
+stat.drilltier = Furáveis
+stat.drillspeed = Velocidade da broca base
+stat.boosteffect = Efeito do Boost
+stat.maxunits = Máximo de unidades ativas
+stat.health = Saúde
+stat.buildtime = Tempo de construção
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Custo de construção
+stat.inaccuracy = Imprecisão
+stat.shots = Tiros
+stat.reload = Tiros por segundo
+stat.ammo = Munição
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Broca melhor necessária.
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = Uma grande torre de tiro rapido.
block.spectre.description = Uma grande torre que da dois tiros poderosos ao mesmo tempo.
block.meltdown.description = Uma grande torre que atira dois raios poderosos ao mesmo tempo.
block.repair-point.description = Continuamente repara a unidade danificada mais proxima.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_ro.properties b/core/assets/bundles/bundle_ro.properties
index 221ab0aab6..aa9fd2f18d 100644
--- a/core/assets/bundles/bundle_ro.properties
+++ b/core/assets/bundles/bundle_ro.properties
@@ -55,6 +55,7 @@ schematic.saved = Schemă salvată.
schematic.delete.confirm = Schema această va fi ștearsă permanent.
schematic.rename = Redenumește Schema
schematic.info = {0}x{1}, {2} blocuri
+schematic.disabled = [scarlet]Schemele sunt dezactivate[]\nNu ai voie să folosești scheme pe această [accent]hartă[] sau [accent]server.
stat.wave = Valuri Învinse:[accent] {0}
stat.enemiesDestroyed = Inamici Distruși:[accent] {0}
@@ -290,6 +291,8 @@ waiting = [lightgray]În așteptare...
waiting.players = Se așteaptă jucătorii...
wave.enemies = [lightgray]Mai sunt {0} inamici
wave.enemy = [lightgray]Mai e {0} inamic
+wave.guardianwarn = Gardianul va veni în [accent]{0}[] valuri.
+wave.guardianwarn.one = Gardianul va veni într-[accent]un[] val.
loadimage = Încarcă Imagine
saveimage = Salvează Imagine
unknown = Necunoscut
@@ -328,6 +331,7 @@ editor.generation = Generare:
editor.ingame = Editează în Joc
editor.publish.workshop = Publică pe Workshop
editor.newmap = Hartă Nouă
+editor.center = Centrează
workshop = Workshop
waves.title = Valuri
waves.remove = Elimină
@@ -420,7 +424,7 @@ filter.corespawn = Selectare Nucleu
filter.median = Mediană
filter.oremedian = Mediană Minereu
filter.blend = Amestecare
-filter.defaultores = Miercuri Prestabilite
+filter.defaultores = Minereuri Prestabilite
filter.ore = Minereu
filter.rivernoise = Zgomot Vizual Râuri
filter.mirror = Oglindă
@@ -471,22 +475,16 @@ requirement.wave = Ajungi la valul {0} în {1}
requirement.core = Distruge Nucleu Inamic în{0}
requirement.research = Cercetează {0}
requirement.capture = Capturează {0}
-resume = Revin la Zonă:\n[lightgray]{0}
bestwave = [lightgray]Cel Mai Bun Val: {0}
-launch = < LANSARE >
launch.text = Lansează
-launch.title = Lansare Finalizată
-launch.next = [lightgray]următoarea ocazie la valul {0}
-launch.unable2 = [scarlet]Imposibil de LANSAT.[]
-launch.confirm = Asta va lansa toate resursele din nucleu.\nNu te vei mai putea întoarce la această bază.
-launch.skip.confirm = Dacă sari acum, Nu vei mai putea lansa decât valurile viitoare.
+campaign.multiplayer = Când joci muliplayer în campanie, nu poți cerceta noi tehnologii decât folosind materiale din sectoarele [accent]tale[], [scarlet]nu[] din sectorul gazdei jocului, unde te afli acum.\n\nPt a transfera materialele către sectoarele [accent]tale[] în multiplayer, folosește o [accent]platformă de lansare[].
uncover = Descoperă
configure = Configurează Încărcarea
loadout = Încărcare
resources = Resurse
bannedblocks = Blocuri Interzise
addall = Adaugă-le pe toate
-launch.destination = Destination: {0}
+launch.destination = Destinație: {0}
configure.invalid = Cantitatea trebuie să fie un număr între 0 și {0}.
zone.unlocked = [lightgray]{0} deblocat(ă).
zone.requirement.complete = Cerințele pt {0} finalizate:[lightgray]\n{1}
@@ -519,8 +517,8 @@ sectors.production = Producție:
sectors.stored = Stocat:
sectors.resume = Revino
sectors.launch = Lansare
-sectors.select = Select
-sectors.nonelaunch = [lightgray]none (sun)
+sectors.select = Selectează
+sectors.nonelaunch = [lightgray]nimic (soarele)
sector.groundZero.name = Ground Zero
sector.craters.name = The Craters
@@ -570,49 +568,51 @@ info.title = Info
error.title = [scarlet]A apărut o eroare.
error.crashtitle = A apărut o eroare.
unit.nobuild = [scarlet]Unitatea nu poate construi.
-blocks.input = Necesită
-blocks.output = Produce
-blocks.booster = Booster
-blocks.tiles = Teren Necesar
-blocks.affinities = Efecte Teren
+lastaccessed = [lightgray]Ultima Accesare: {0}
+stat.input = Necesită
+stat.output = Produce
+stat.booster = Booster
+stat.tiles = Teren Necesar
+stat.affinities = Efecte Teren
block.unknown = [lightgray]???
-blocks.powercapacity = Capacitate electrică
-blocks.powershot = Electricitate/Glonț
-blocks.damage = Forță
-blocks.targetsair = Lovește Aeronave
-blocks.targetsground = Lovește Artilerie
-blocks.itemsmoved = Viteza de Mișcare a Materialelor
-blocks.launchtime = Timp între Lansări
-blocks.shootrange = Rază
-blocks.size = Mărime
-blocks.displaysize = Mărimea Monitorului Logic
-blocks.liquidcapacity = Capacitate Lichid
-blocks.powerrange = Raza Electrică
-blocks.linkrange = Raza Legăturilor
-blocks.instructions = Instrucțiuni
-blocks.powerconnections = Maxim Conexiuni
-blocks.poweruse = Consum Electricitate
-blocks.powerdamage = Electricitate/Forța Glonțului
-blocks.itemcapacity = Capacitate Materiale
-blocks.basepowergeneration = Generare Electricitate (Bază)
-blocks.productiontime = Timp Producție
-blocks.repairtime = Durata Reparării Blocului
-blocks.speedincrease = Creștere Viteză
-blocks.range = Rază
-blocks.drilltier = Minabile
-blocks.drillspeed = Viteză Burghiu (Bază)
-blocks.boosteffect = Efect de Boost
-blocks.maxunits = Maxim Unități Active
-blocks.health = Viață
-blocks.buildtime = Timp Construcție
-blocks.maxconsecutive = Maxim Consecutive
-blocks.buildcost = Cost Construcție
-blocks.inaccuracy = Inacuratețe
-blocks.shots = Lovituri
-blocks.reload = Lovituri/Secundă
-blocks.ammo = Muniție
-blocks.shieldhealth = Viața Scutului
-blocks.cooldowntime = Timp de Reîncărcare
+stat.powercapacity = Capacitate electrică
+stat.powershot = Electricitate/Glonț
+stat.damage = Forță
+stat.targetsair = Lovește Aeronave
+stat.targetsground = Lovește Artilerie
+stat.itemsmoved = Viteza de Mișcare a Materialelor
+stat.launchtime = Timp între Lansări
+stat.shootrange = Rază
+stat.size = Mărime
+stat.displaysize = Mărimea Monitorului Logic
+stat.liquidcapacity = Capacitate Lichid
+stat.powerrange = Raza Electrică
+stat.linkrange = Raza Legăturilor
+stat.instructions = Instrucțiuni
+stat.powerconnections = Maxim Conexiuni
+stat.poweruse = Consum Electricitate
+stat.powerdamage = Electricitate/Forța Glonțului
+stat.itemcapacity = Capacitate Materiale
+stat.memorycapacity = Capacitate Memorie
+stat.basepowergeneration = Generare Electricitate (Bază)
+stat.productiontime = Timp Producție
+stat.repairtime = Durata Reparării Blocului
+stat.speedincrease = Creștere Viteză
+stat.range = Rază
+stat.drilltier = Minabile
+stat.drillspeed = Viteză Burghiu (Bază)
+stat.boosteffect = Efect de Boost
+stat.maxunits = Maxim Unități Active
+stat.health = Viață
+stat.buildtime = Timp Construcție
+stat.maxconsecutive = Maxim Consecutive
+stat.buildcost = Cost Construcție
+stat.inaccuracy = Inacuratețe
+stat.shots = Lovituri
+stat.reload = Lovituri/Secundă
+stat.ammo = Muniție
+stat.shieldhealth = Viața Scutului
+stat.cooldowntime = Timp de Reîncărcare
bar.drilltierreq = Burghiu Mai Bun Necesar
bar.noresources = Resurse lipsă
@@ -624,6 +624,7 @@ bar.powerbalance = Electricitate: {0}/s
bar.powerstored = Stocată: {0}/{1}
bar.poweramount = Electricitate: {0}
bar.poweroutput = Electricitate Produsă: {0}
+bar.powerlines = Conexiuni: {0}/{1}
bar.items = Materiale: {0}
bar.capacity = Capacitate: {0}
bar.unitcap = {0} {1}/{2}
@@ -635,6 +636,8 @@ bar.progress = Progres
bar.input = Necesită
bar.output = Produce
+units.processorcontrol = [lightgray]Controlat de Procesor
+
bullet.damage = [stat]{0}[lightgray] forță
bullet.splashdamage = [stat]{0}[lightgray] forță explozivă ~[stat] {1}[lightgray] pătrate
bullet.incendiary = [stat]incendiar
@@ -821,7 +824,8 @@ mode.attack.description = Distruge baza inamicului. \n[gray]E nevoie de un nucle
mode.custom = Reguli Personalizate
rules.infiniteresources = Resurse Infinite
-rules.reactorexplosions = Explozia Reactoarelor
+rules.reactorexplosions = Reactoarele Explodează
+rules.schematic = Se Pot Folosi Scheme
rules.wavetimer = Valuri pe Timp
rules.waves = Valuri
rules.attack = Modul Atac
@@ -846,7 +850,8 @@ rules.title.enemy = Inamici
rules.title.unit = Unități
rules.title.experimental = Experimental
rules.title.environment = Mediu
-rules.lighting = Luminozitate
+rules.lighting = Luminozitate Ambientală
+rules.enemyLights = Inamicii Luminează
rules.fire = Foc
rules.explosions = Explozia Deteriorează Blocul/Unitatea
rules.ambientlight = Ambient
@@ -936,6 +941,7 @@ block.cliff.name = Deal
block.sand-boulder.name = Bolovan de Nisip
block.grass.name = Iarbă
block.slag.name = Zgură
+block.space.name = Cosmos
block.salt.name = Sare
block.salt-wall.name = Perete de Sare
block.pebbles.name = Pietricele
@@ -1075,6 +1081,7 @@ block.power-source.name = Electricitate Infinită
block.unloader.name = Descărcător
block.vault.name = Seif
block.wave.name = Wave
+block.tsunami.name = Tsunami
block.swarmer.name = Swarmer
block.salvo.name = Salvo
block.ripple.name = Ripple
@@ -1114,6 +1121,7 @@ block.arc.name = Arc
block.rtg-generator.name = Generator RTG
block.spectre.name = Specter
block.meltdown.name = Meltdown
+block.foreshadow.name = Foreshadow
block.container.name = Container
block.launch-pad.name = Platformă de Lansare
block.launch-pad-large.name = Platformă de Lansare Mare
@@ -1139,12 +1147,13 @@ block.hyper-processor.name = Hyperprocesor
block.logic-display.name = Monitor Logic
block.large-logic-display.name = Monitor Logic Mare
block.memory-cell.name = Celulă de Memorie
+block.memory-bank.name = Bancă de Memorie
team.blue.name = albastră
team.crux.name = roșie
team.sharded.name = portocalie
team.orange.name = portocalie
-team.derelict.name = abandon
+team.derelict.name = abandonat
team.green.name = verde
team.purple.name = mov
@@ -1251,7 +1260,7 @@ block.rotary-pump.description = O pompă avansată. Pompează mai mult lichid da
block.thermal-pump.description = Cea mai bună pompă.
block.conduit.description = Un bloc de transport al lichidelor. Împinge lichidele în față. Folosit cu pompe și alte conducte.
block.pulse-conduit.description = Un bloc avansat de transport al lichidelor. Transportă lichidele mai rapid și stochează mai mult decât conductele standard.
-block.plated-conduit.description = Transportă lichidele lafel de rapid precum conductele cu puls, dar este mai rezistent. Nu acceptă fluide din lateral de la altceva în afară de conducte.\nCurge mai puțin.
+block.plated-conduit.description = Transportă lichidele lafel de rapid precum conductele cu puls, dar este mai rezistentă. Nu acceptă fluide din lateral de la altceva în afară de conducte.\nLichidul nu se varsă la exterior.
block.liquid-router.description = Acceptă lichide dintr-o direcție și le distribuie în alte 3 direcții în mod egal. Poate stoca o anumită cantitate de lichid. Folositor pt a distribui lichidele dintr-o sursă către mai multe destinații.
block.liquid-tank.description = Stochează o mare cantitate de lichid. Util pt depozita lichide pt situațiile în care cererea de materiale nu e constantă sau ca extra securitate pt răcirea blocurilor vitale.
block.liquid-junction.description = Acționează ca un pod pt două conducte care se intersectează. Util în situația în care se intersectează 2 conducte diferite ce cară divesre lichide către diverse locații.
@@ -1302,4 +1311,4 @@ block.cyclone.description = O mare armă anti-artilerie și anti-aer. Trage cu g
block.spectre.description = O armă masivă cu două țevi. Trage cu gloanțe mari care găuresc armurile țintelor aeriene și artileriei.
block.meltdown.description = O armă cu laser masivă. Trage cu un laser continuu la inamicii din apropiere. Necesită răcitor pt a opera.
block.repair-point.description = Repară încontinuu cea mai deteriorată unitate din vecinătate.
-block.segment.description = Deteriorează și distruge proiectilele din apropiere. Laserele nu sunt afectate.
+block.segment.description = Deteriorează și distruge proiectilele din apropiere. Laserele nu sunt afectate.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties
index c46f94874a..d6410aa9d9 100644
--- a/core/assets/bundles/bundle_ru.properties
+++ b/core/assets/bundles/bundle_ru.properties
@@ -643,10 +643,9 @@ stat.minetier = Уровень добычи
stat.payloadcapacity = Грузоподъёмность
stat.commandlimit = Лимит командования
stat.abilities = Способности
-
ability.forcefield = Силовое поле
ability.repairfield = Ремонтирующее поле
- #TODO туду тудум
+#TODO туду тудум
ability.statusfield = Status Field
ability.unitspawn = Завод единиц «{0}»
ability.shieldregenfield = Поле восстановления щита
diff --git a/core/assets/bundles/bundle_sv.properties b/core/assets/bundles/bundle_sv.properties
index 0d29e6a89e..8d3942eccb 100644
--- a/core/assets/bundles/bundle_sv.properties
+++ b/core/assets/bundles/bundle_sv.properties
@@ -570,49 +570,49 @@ info.title = Info
error.title = [crimson]An error has occured
error.crashtitle = An error has occured
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Inmatning
-blocks.output = Utmatning
-blocks.booster = Booster
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Inmatning
+stat.output = Utmatning
+stat.booster = Booster
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Power Capacity
-blocks.powershot = Power/Shot
-blocks.damage = Skada
-blocks.targetsair = Targets Air
-blocks.targetsground = Targets Ground
-blocks.itemsmoved = Move Speed
-blocks.launchtime = Time Between Launches
-blocks.shootrange = Range
-blocks.size = Storlek
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Liquid Capacity
-blocks.powerrange = Power Range
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Max Connections
-blocks.poweruse = Power Use
-blocks.powerdamage = Power/Damage
-blocks.itemcapacity = Item Capacity
-blocks.basepowergeneration = Base Power Generation
-blocks.productiontime = Production Time
-blocks.repairtime = Block Full Repair Time
-blocks.speedincrease = Speed Increase
-blocks.range = Range
-blocks.drilltier = Drillables
-blocks.drillspeed = Base Drill Speed
-blocks.boosteffect = Boost Effect
-blocks.maxunits = Max Active Units
-blocks.health = Health
-blocks.buildtime = Build Time
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Build Cost
-blocks.inaccuracy = Inaccuracy
-blocks.shots = Skott
-blocks.reload = Shots/Second
-blocks.ammo = Ammunition
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Power Capacity
+stat.powershot = Power/Shot
+stat.damage = Skada
+stat.targetsair = Targets Air
+stat.targetsground = Targets Ground
+stat.itemsmoved = Move Speed
+stat.launchtime = Time Between Launches
+stat.shootrange = Range
+stat.size = Storlek
+stat.displaysize = Display Size
+stat.liquidcapacity = Liquid Capacity
+stat.powerrange = Power Range
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Max Connections
+stat.poweruse = Power Use
+stat.powerdamage = Power/Damage
+stat.itemcapacity = Item Capacity
+stat.basepowergeneration = Base Power Generation
+stat.productiontime = Production Time
+stat.repairtime = Block Full Repair Time
+stat.speedincrease = Speed Increase
+stat.range = Range
+stat.drilltier = Drillables
+stat.drillspeed = Base Drill Speed
+stat.boosteffect = Boost Effect
+stat.maxunits = Max Active Units
+stat.health = Health
+stat.buildtime = Build Time
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Build Cost
+stat.inaccuracy = Inaccuracy
+stat.shots = Skott
+stat.reload = Shots/Second
+stat.ammo = Ammunition
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Bättre Borr Krävs
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = A large anti-air and anti-ground turret. Fires explo
block.spectre.description = A massive dual-barreled cannon. Shoots large armor-piercing bullets at air and ground targets.
block.meltdown.description = A massive laser cannon. Charges and fires a persistent laser beam at nearby enemies. Requires coolant to operate.
block.repair-point.description = Continuously heals the closest damaged unit in its vicinity.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_th.properties b/core/assets/bundles/bundle_th.properties
index 6a89ac29ca..b86d8e7182 100644
--- a/core/assets/bundles/bundle_th.properties
+++ b/core/assets/bundles/bundle_th.properties
@@ -570,49 +570,49 @@ info.title = ข้อมูล
error.title = [crimson]มีบางอย่างผิดพลาดเกิดขึ้น
error.crashtitle = มีบางอย่างผิดพลาดเกิดขึ้น
unit.nobuild = [scarlet]Unit can't build
-blocks.input = นำเข้า
-blocks.output = ส่งออก
-blocks.booster = บูสเตอร์
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = นำเข้า
+stat.output = ส่งออก
+stat.booster = บูสเตอร์
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = ความจุพลังงาน
-blocks.powershot = หน่วยพลังงาน/นัด
-blocks.damage = ดาเมจ
-blocks.targetsair = ยิงอากาศยาน
-blocks.targetsground = ยิงภาคพื้นดิน
-blocks.itemsmoved = ความเร็วเคลื่อนที่
-blocks.launchtime = เวลาระหว่างการส่ง
-blocks.shootrange = ระยะยิง
-blocks.size = ขนาด
-blocks.displaysize = Display Size
-blocks.liquidcapacity = จุของเหลว
-blocks.powerrange = ระยะพลังงาน
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = จำนวนการเชื่อมต่อสูงสุด
-blocks.poweruse = ใช้พลังงาน
-blocks.powerdamage = หน่วยพลังงาน/ดาเมจ
-blocks.itemcapacity = จุไอเท็ม
-blocks.basepowergeneration = กำเนิดพลังงานพื้นฐาน
-blocks.productiontime = เวลาที่ใช้ในการผลิต
-blocks.repairtime = เวลาที่ใช้ในการซ่อมแซมให้สมบูรณ์
-blocks.speedincrease = เพิ่มความเร็ว
-blocks.range = ระยะ
-blocks.drilltier = ขุดได้
-blocks.drillspeed = ความเร็วขุดพื้นฐาน
-blocks.boosteffect = แอฟเฟ็คของบูสต์
-blocks.maxunits = จำนวนยูนิตสูงสุด
-blocks.health = เลือด
-blocks.buildtime = เวลาในการสร้าง
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = ใช้
-blocks.inaccuracy = ความคลาดเคลื่อน
-blocks.shots = นัด
-blocks.reload = นัด/วินาที
-blocks.ammo = กระสุน
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = ความจุพลังงาน
+stat.powershot = หน่วยพลังงาน/นัด
+stat.damage = ดาเมจ
+stat.targetsair = ยิงอากาศยาน
+stat.targetsground = ยิงภาคพื้นดิน
+stat.itemsmoved = ความเร็วเคลื่อนที่
+stat.launchtime = เวลาระหว่างการส่ง
+stat.shootrange = ระยะยิง
+stat.size = ขนาด
+stat.displaysize = Display Size
+stat.liquidcapacity = จุของเหลว
+stat.powerrange = ระยะพลังงาน
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = จำนวนการเชื่อมต่อสูงสุด
+stat.poweruse = ใช้พลังงาน
+stat.powerdamage = หน่วยพลังงาน/ดาเมจ
+stat.itemcapacity = จุไอเท็ม
+stat.basepowergeneration = กำเนิดพลังงานพื้นฐาน
+stat.productiontime = เวลาที่ใช้ในการผลิต
+stat.repairtime = เวลาที่ใช้ในการซ่อมแซมให้สมบูรณ์
+stat.speedincrease = เพิ่มความเร็ว
+stat.range = ระยะ
+stat.drilltier = ขุดได้
+stat.drillspeed = ความเร็วขุดพื้นฐาน
+stat.boosteffect = แอฟเฟ็คของบูสต์
+stat.maxunits = จำนวนยูนิตสูงสุด
+stat.health = เลือด
+stat.buildtime = เวลาในการสร้าง
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = ใช้
+stat.inaccuracy = ความคลาดเคลื่อน
+stat.shots = นัด
+stat.reload = นัด/วินาที
+stat.ammo = กระสุน
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = จำเป็นต้องใช้เครื่องขุดที่ดีกว่า
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = ป้อมปืนต่อต้านอาก
block.spectre.description = ปืนใหญ่ลำกล้องคูขนาดยักษ์. ยิงกระสุนเจาะเกราะใส่ศัตรูทั้งบนอากาศและภาดพื้นดิน.
block.meltdown.description = ปืนใหญ่เลเซอร์ขนาดยักษ์. ชาร์จแล้วยิงลำแสงเลเซอร์ใส่ศัตรูที่อยู่ใกล้. จำเป็นต้องใช้สารหล่อเย็น.
block.repair-point.description = ซ่อมแซมยูนิตที่อยู่ในรัศมีอย่างต่อเนื่อง.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties
index edfae05b29..cfac48c897 100644
--- a/core/assets/bundles/bundle_tk.properties
+++ b/core/assets/bundles/bundle_tk.properties
@@ -570,49 +570,49 @@ info.title = [accent]Bilgi
error.title = [crimson]Bir hata olustu
error.crashtitle = Bir hata olustu
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Input
-blocks.output = Output
-blocks.booster = Booster
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Input
+stat.output = Output
+stat.booster = Booster
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Guc kapasitesi
-blocks.powershot = Guc/Saldiri hizi
-blocks.damage = Damage
-blocks.targetsair = Havayi hedef alir mi?
-blocks.targetsground = Targets Ground
-blocks.itemsmoved = Move Speed
-blocks.launchtime = Time Between Launches
-blocks.shootrange = Menzil
-blocks.size = Buyukluk
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Sivi kapasitesi
-blocks.powerrange = Menzil
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Max Connections
-blocks.poweruse = Guc kullanimi
-blocks.powerdamage = Power/Damage
-blocks.itemcapacity = Esya kapasitesi
-blocks.basepowergeneration = Base Power Generation
-blocks.productiontime = Production Time
-blocks.repairtime = Block Full Repair Time
-blocks.speedincrease = Speed Increase
-blocks.range = Range
-blocks.drilltier = Kazilabilirler
-blocks.drillspeed = Ana kazma hizi
-blocks.boosteffect = Boost Effect
-blocks.maxunits = Max Active Units
-blocks.health = Can
-blocks.buildtime = Build Time
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = Build Cost
-blocks.inaccuracy = sekme
-blocks.shots = vuruslar
-blocks.reload = Yeniden doldurma
-blocks.ammo = Ammo
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Guc kapasitesi
+stat.powershot = Guc/Saldiri hizi
+stat.damage = Damage
+stat.targetsair = Havayi hedef alir mi?
+stat.targetsground = Targets Ground
+stat.itemsmoved = Move Speed
+stat.launchtime = Time Between Launches
+stat.shootrange = Menzil
+stat.size = Buyukluk
+stat.displaysize = Display Size
+stat.liquidcapacity = Sivi kapasitesi
+stat.powerrange = Menzil
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Max Connections
+stat.poweruse = Guc kullanimi
+stat.powerdamage = Power/Damage
+stat.itemcapacity = Esya kapasitesi
+stat.basepowergeneration = Base Power Generation
+stat.productiontime = Production Time
+stat.repairtime = Block Full Repair Time
+stat.speedincrease = Speed Increase
+stat.range = Range
+stat.drilltier = Kazilabilirler
+stat.drillspeed = Ana kazma hizi
+stat.boosteffect = Boost Effect
+stat.maxunits = Max Active Units
+stat.health = Can
+stat.buildtime = Build Time
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = Build Cost
+stat.inaccuracy = sekme
+stat.shots = vuruslar
+stat.reload = Yeniden doldurma
+stat.ammo = Ammo
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Better Drill Required
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = A large rapid fire turret.
block.spectre.description = A large turret which shoots two powerful bullets at once.
block.meltdown.description = A large turret which shoots powerful long-range beams.
block.repair-point.description = Continuously heals the closest damaged unit in its vicinity.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties
index 1fd6a6618e..395e062453 100644
--- a/core/assets/bundles/bundle_tr.properties
+++ b/core/assets/bundles/bundle_tr.properties
@@ -570,49 +570,49 @@ info.title = Bilgi
error.title = [crimson]Bir hata oldu
error.crashtitle = Bir hata oldu
unit.nobuild = [scarlet]Unit can't build
-blocks.input = Giriş
-blocks.output = Çıkış
-blocks.booster = Güçlendirici
-blocks.tiles = Required Tiles
-blocks.affinities = Affinities
+stat.input = Giriş
+stat.output = Çıkış
+stat.booster = Güçlendirici
+stat.tiles = Required Tiles
+stat.affinities = Affinities
block.unknown = [lightgray]???
-blocks.powercapacity = Enerji Kapasitesi
-blocks.powershot = Enerji/Atış
-blocks.damage = Hasar
-blocks.targetsair = Havayı Hedefler Mi
-blocks.targetsground = Yeri Hedefler Mi
-blocks.itemsmoved = Hareket Hızı
-blocks.launchtime = Fırlatmalar Arasındaki Süre
-blocks.shootrange = Menzil
-blocks.size = Boyut
-blocks.displaysize = Display Size
-blocks.liquidcapacity = Sıvı Kapasitesi
-blocks.powerrange = Enerji Menzili
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = Bağlantı sayısı
-blocks.poweruse = Enerji Kullanımı
-blocks.powerdamage = Enerji/Hasar
-blocks.itemcapacity = Eşya Kapasitesi
-blocks.basepowergeneration = Temel Enerji Üretimi
-blocks.productiontime = Üretim Süresi
-blocks.repairtime = Tamir Tamir Edilme Süresi
-blocks.speedincrease = Hız Artışı
-blocks.range = Menzil
-blocks.drilltier = Kazılabilenler
-blocks.drillspeed = Temel Matkap Hızı
-blocks.boosteffect = Hızlandırma Efekti
-blocks.maxunits = Maksimum Aktif Birim
-blocks.health = Can
-blocks.buildtime = İnşaat Süresi
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = İnşaat Fiyatı
-blocks.inaccuracy = İskalama Oranı
-blocks.shots = Atışlar
-blocks.reload = Atışlar/Sn
-blocks.ammo = Mermi
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Enerji Kapasitesi
+stat.powershot = Enerji/Atış
+stat.damage = Hasar
+stat.targetsair = Havayı Hedefler Mi
+stat.targetsground = Yeri Hedefler Mi
+stat.itemsmoved = Hareket Hızı
+stat.launchtime = Fırlatmalar Arasındaki Süre
+stat.shootrange = Menzil
+stat.size = Boyut
+stat.displaysize = Display Size
+stat.liquidcapacity = Sıvı Kapasitesi
+stat.powerrange = Enerji Menzili
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = Bağlantı sayısı
+stat.poweruse = Enerji Kullanımı
+stat.powerdamage = Enerji/Hasar
+stat.itemcapacity = Eşya Kapasitesi
+stat.basepowergeneration = Temel Enerji Üretimi
+stat.productiontime = Üretim Süresi
+stat.repairtime = Tamir Tamir Edilme Süresi
+stat.speedincrease = Hız Artışı
+stat.range = Menzil
+stat.drilltier = Kazılabilenler
+stat.drillspeed = Temel Matkap Hızı
+stat.boosteffect = Hızlandırma Efekti
+stat.maxunits = Maksimum Aktif Birim
+stat.health = Can
+stat.buildtime = İnşaat Süresi
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = İnşaat Fiyatı
+stat.inaccuracy = İskalama Oranı
+stat.shots = Atışlar
+stat.reload = Atışlar/Sn
+stat.ammo = Mermi
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = Daha İyi Matkap Gerekli
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = Büyük bir anti hava ve anti kara tareti. Yakının
block.spectre.description = Dev bir çift namlulu top. Hava ve kara birimlerine iri, zırh delici mermiler atar.
block.meltdown.description = Dev bir lazer topu. Yüklenip yakındaki düşmanlara uzun süreli lazer ışınları yollar. Çalışması için soğutucu gerekir.
block.repair-point.description = Kendisine en yakın hasarlı birimi tamir eder.
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties
index df5bfc1db1..dfc4bae48b 100644
--- a/core/assets/bundles/bundle_uk_UA.properties
+++ b/core/assets/bundles/bundle_uk_UA.properties
@@ -1,4 +1,4 @@
-credits.text = Створив [royal]Anuken[] — [sky]anukendev@gmail.com[]\n\nЄ ігрові питання або помилки в перекладі?\nЗавітайте до офіційного Discord-сервера Mindustry\nв канал #український.\nПереклав українською: [blue]Prosta4ok_ua[green]#[yellow]6336
+credits.text = Створив [royal]Anuken[] — [sky]anukendev@gmail.com[]\n\nМаєте питання по грі або знайшли помилки в перекладі?\nДолучайтеся до офіційного сервера Mindustry у Discord\nв канал #українська.\nУкраїнський перекладач — Prosta4ok_ua#6336.
credits = Творці
contributors = Перекладачі та помічники
discord = Офіційний сервер Mindustry в Discord
@@ -21,7 +21,7 @@ gameover.pvp = [accent]{0}[] команда перемогла!
highscore = [accent]Новий рекорд!
copied = Скопійовано.
indev.popup = Наразі [accent]6.0[] знаходиться у стадії [accent]альфа[].\n[lightgray]Це означає наступне:[]\n- Не вистачає наповнення гри;\n- Більшість [scarlet]ШІ бойових одиниць[] не працює належним чином;\n- Багато одиниць [scarlet]відсутні[] або незавершені;\n- Кампанія повністю не є завершеною;\n- Усе, що ви бачите, може змінитися або видалитися.\n\nПовідомляйте про вади або збої на [accent]Github[], а про помилки в перекладі в Discord.
-indev.notready = Ця частина гри ще не готова
+indev.notready = Ця частина гри ще не готова.
load.sound = Звуки
load.map = Мапи
@@ -54,7 +54,8 @@ schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Обернути схему
schematic.saved = Схема збережена.
schematic.delete.confirm = Ви справді хочете видалити цю схему?
schematic.rename = Перейменувати схему
-schematic.info = {0}x{1}, {2} блоків
+schematic.info = {0}x{1}, блоків: {2}
+schematic.disabled = [scarlet]Схеми вимкнені[]\nВам не дозволяється використовувати схеми на цій [accent]мапі[] чи [accent]сервері.
stat.wave = Хвиль відбито:[accent] {0}
stat.enemiesDestroyed = Противників знищено:[accent] {0}
@@ -471,22 +472,16 @@ requirement.wave = Досягніть хвилі {0} у зоні «{1}»
requirement.core = Знищте вороже ядро в зоні «{0}»
requirement.research = Research {0}
requirement.capture = Capture {0}
-resume = Відновити зону:\n[lightgray]{0}
bestwave = [lightgray]Найкраща хвиля: {0}
-launch = < ЗАПУСК >
launch.text = Запуск
-launch.title = Запуск вдалий
-launch.next = [lightgray]наступна можливість буде на {0}-тій хвилі
-launch.unable2 = [scarlet]ЗАПУСК неможливий.[]
-launch.confirm = Це видалить усі ресурси у вашому ядрі.\nВи не зможете повернутися до цієї бази.
-launch.skip.confirm = Якщо ви пропустите зараз, ви не зможете не запускати до більш пізніх хвиль.
+campaign.multiplayer = Коли ви граєте з кимось в кампанії, то ви можете дослідити лише використовуючи предмети з [accent]ваших[] секторів, [scarlet]гн[] з сектора власника, на якому ви перебуваєте прямо зараз.\n\nЗадля отримання предметів у [accent]своїх[] секторах в багатокористувацькій грі використайте [accent]Стартовий майданчик[].
uncover = Розкрити
configure = Налаштувати вивантаження
loadout = Вивантаження
resources = Ресурси
bannedblocks = Заборонені блоки
addall = Додати все
-launch.destination = Destination: {0}
+launch.destination = Пункт призначення: {0}
configure.invalid = Кількість має бути числом між 0 та {0}.
zone.unlocked = Зона «[lightgray]{0}» тепер розблокована.
zone.requirement.complete = Вимоги до зони «{0}» виконані:[lightgray]\n{1}
@@ -519,8 +514,8 @@ sectors.production = Виробництво:
sectors.stored = Зберігає:
sectors.resume = Продовжити
sectors.launch = Запуск
-sectors.select = Select
-sectors.nonelaunch = [lightgray]none (sun)
+sectors.select = Вибрати
+sectors.nonelaunch = [lightgray]нічого (сонце)
sector.groundZero.name = Відправний пункт
sector.craters.name = Кратери
@@ -570,49 +565,50 @@ info.title = Інформація
error.title = [crimson]Виникла помилка
error.crashtitle = Виникла помилка
unit.nobuild = [scarlet]Ця одиниця не може будувати
-blocks.input = Ввід
-blocks.output = Вивід
-blocks.booster = Прискорювач
-blocks.tiles = Необхідні плитки
-blocks.affinities = Збільшення ефективності
+stat.input = Ввід
+stat.output = Вивід
+stat.booster = Прискорювач
+stat.tiles = Необхідні плитки
+stat.affinities = Збільшення ефективності
block.unknown = [lightgray]???
-blocks.powercapacity = Місткість енергії
-blocks.powershot = Енергія за постріл
-blocks.damage = Шкода
-blocks.targetsair = Повітряні противники
-blocks.targetsground = Наземні противники
-blocks.itemsmoved = Швидкість переміщення
-blocks.launchtime = Час між запусками
-blocks.shootrange = Радіус дії
-blocks.size = Розмір
-blocks.displaysize = Розмір дисплею
-blocks.liquidcapacity = Рідинна місткість
-blocks.powerrange = Радіус передачі енергії
-blocks.linkrange = Радіус з’єднання
-blocks.instructions = Інструкції
-blocks.powerconnections = Максимальна кількість з’єднань
-blocks.poweruse = Енергії використовує
-blocks.powerdamage = Енергії за од. шкоди
-blocks.itemcapacity = Місткість предметів
-blocks.basepowergeneration = Базова генерація енергії
-blocks.productiontime = Час виробництва
-blocks.repairtime = Час повного відновлення блоку
-blocks.speedincrease = Збільшення швидкості
-blocks.range = Радіус дії
-blocks.drilltier = Видобуває
-blocks.drillspeed = Базова швидкість буріння
-blocks.boosteffect = Прискорювальний ефект
-blocks.maxunits = Максимальна кількість активних одиниць
-blocks.health = Здоров’я
-blocks.buildtime = Час будування
-blocks.maxconsecutive = Максимальна послідовність
-blocks.buildcost = Вартість будування
-blocks.inaccuracy = Розкид
-blocks.shots = Постріли
-blocks.reload = Постріли/секунду
-blocks.ammo = Боєприпаси
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = Місткість енергії
+stat.powershot = Енергія за постріл
+stat.damage = Шкода
+stat.targetsair = Повітряні противники
+stat.targetsground = Наземні противники
+stat.itemsmoved = Швидкість переміщення
+stat.launchtime = Час між запусками
+stat.shootrange = Радіус дії
+stat.size = Розмір
+stat.displaysize = Розмір дисплею
+stat.liquidcapacity = Рідинна місткість
+stat.powerrange = Радіус передачі енергії
+stat.linkrange = Радіус з’єднання
+stat.instructions = Інструкції
+stat.powerconnections = Максимальна кількість з’єднань
+stat.poweruse = Енергії використовує
+stat.powerdamage = Енергії за од. шкоди
+stat.itemcapacity = Місткість предметів
+stat.memorycapacity = Ємність пам’яті
+stat.basepowergeneration = Базова генерація енергії
+stat.productiontime = Час виробництва
+stat.repairtime = Час повного відновлення блоку
+stat.speedincrease = Збільшення швидкості
+stat.range = Радіус дії
+stat.drilltier = Видобуває
+stat.drillspeed = Базова швидкість буріння
+stat.boosteffect = Прискорювальний ефект
+stat.maxunits = Максимальна кількість активних одиниць
+stat.health = Здоров’я
+stat.buildtime = Час будування
+stat.maxconsecutive = Максимальна послідовність
+stat.buildcost = Вартість будування
+stat.inaccuracy = Розкид
+stat.shots = Постріли
+stat.reload = Постріли/секунду
+stat.ammo = Боєприпаси
+stat.shieldhealth = Міцність щита
+stat.cooldowntime = Тривалість охолодження
bar.drilltierreq = Потребується кращий бур
bar.noresources = Бракує ресурсів
@@ -660,7 +656,7 @@ unit.persecond = за секунду
unit.perminute = за хвилину
unit.timesspeed = x швидкість
unit.percent = %
-unit.shieldhealth = shield health
+unit.shieldhealth = міцність щита
unit.items = предм.
unit.thousands = тис
unit.millions = млн
@@ -788,14 +784,14 @@ keybind.diagonal_placement.name = Діагональне розміщення
keybind.pick.name = Вибрати блок
keybind.break_block.name = Зламати блок
keybind.deselect.name = Скасувати
-keybind.pickupCargo.name = Pickup Cargo
-keybind.dropCargo.name = Drop Cargo
-keybind.command.name = Command
+keybind.pickupCargo.name = Взяти вантаж
+keybind.dropCargo.name = Скинути вантаж
+keybind.command.name = Взяти командування над одиницями
keybind.shoot.name = Постріл
keybind.zoom.name = Наблизити
keybind.menu.name = Меню
keybind.pause.name = Пауза
-keybind.pause_building.name = Призупинити/Продовжити будування
+keybind.pause_building.name = Призупинити/продовжити будування
keybind.minimap.name = Мінімапа
keybind.chat.name = Чат
keybind.player_list.name = Список гравців
@@ -822,6 +818,7 @@ mode.custom = Користувацькі правила
rules.infiniteresources = Нескінченні ресурси
rules.reactorexplosions = Вибухи реактора
+rules.schematic = Використання схем дозволено
rules.wavetimer = Таймер для хвиль
rules.waves = Хвилі
rules.attack = Режим атаки
@@ -912,11 +909,11 @@ unit.horizon.name = Горизонт
unit.zenith.name = Зеніт
unit.antumbra.name = Тіньовик
unit.eclipse.name = Затьмарник
-unit.mono.name = Єдинак
-unit.poly.name = Багацько
+unit.mono.name = Моно
+unit.poly.name = Полі
unit.mega.name = Мега
-unit.quad.name = Quad
-unit.oct.name = Oct
+unit.quad.name = Квал
+unit.oct.name = Окт
unit.risso.name = Грампус
unit.minke.name = Смугач малий
unit.bryde.name = Смугач Брайда
@@ -927,8 +924,8 @@ unit.beta.name = Бета
unit.gamma.name = Гамма
unit.scepter.name = Верховна влада
unit.reign.name = Верховний Порядок
-unit.vela.name = Vela
-unit.corvus.name = Corvus
+unit.vela.name = Пульсар Вітрил
+unit.corvus.name = Ворон
block.resupply-point.name = Пункт постачання
block.parallax.name = Паралакс
@@ -989,7 +986,7 @@ block.dune-wall.name = Дюнова стіна
block.pine.name = Сосна
block.dirt.name = Ґрунт
block.dirt-wall.name = Ґрунтова стіна
-block.mud.name = Mud
+block.mud.name = Багно
block.white-tree-dead.name = Мертве біле дерево
block.white-tree.name = Біле дерево
block.spore-cluster.name = Скупчення спор
@@ -1130,7 +1127,7 @@ block.payload-conveyor.name = Вантажний конвеєр
block.payload-router.name = Розвантажувальний маршрутизатор
block.disassembler.name = Розбирач
block.silicon-crucible.name = Кремнієвий тигель
-block.overdrive-dome.name = Overdrive Dome
+block.overdrive-dome.name = Величний Прискорювач
block.switch.name = Перемикач
block.micro-processor.name = Мікропроцесор
@@ -1139,12 +1136,13 @@ block.hyper-processor.name = Гіперпроцесор
block.logic-display.name = Логічний дисплей
block.large-logic-display.name = Великий логічний дисплей
block.memory-cell.name = Комірка пам’яті
+block.memory-bank.name = Блок пам’яті
team.blue.name = Синя
team.crux.name = Червона
team.sharded.name = Помаранчева
team.orange.name = Помаранчева
-team.derelict.name = Залишена
+team.derelict.name = Знедолена
team.green.name = Зелена
team.purple.name = Фіолетова
@@ -1302,4 +1300,4 @@ block.cyclone.description = Велика протиповітряна та пр
block.spectre.description = Масивна двоствольна гармата. Стріляє великими бронебійними кулями в повітряні та наземні цілі.
block.meltdown.description = Масивна лазерна гармата. Заряджає і стріляє лазерним променем у найближчих противників. Для роботи потрібен теплоносій.
block.repair-point.description = Безперервно ремонтує найближчу пошкоджену бойову одиницю.
-block.segment.description = Пошкоджує та руйнує вхідні снаряди. Окрім лазерних.
+block.segment.description = Пошкоджує та руйнує вхідні снаряди. Окрім лазерних.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties
index 506a29aa99..5744d3d0fd 100644
--- a/core/assets/bundles/bundle_zh_CN.properties
+++ b/core/assets/bundles/bundle_zh_CN.properties
@@ -1,4 +1,4 @@
-credits.text = 作者[royal]Anuken[] - [sky]anukendev@gmail.com[]
+credits.text = 作者[royal]Anuken[] - [sky]anukendev@gmail.com[] 译者[orange]老滑稽[] - [cyan]QQ:1290419934[]
credits = 致谢
contributors = 翻译者和贡献者
discord = 加入 Mindustry 的 Discord!
@@ -20,8 +20,8 @@ gameover = 游戏结束
gameover.pvp = [accent] {0}[]队获胜!
highscore = [accent]新纪录!
copied = 已复制。
-indev.popup = [accent]v6[] is currently in [accent]alpha[].\n[lightgray]This means:[]\n[scarlet]- The campaign is completely unfinished[]\n- Content is missing\n - Most [scarlet]Unit AI[] does not work properly\n- Many units are unfinished\n- Everything you see is subject to change or removal.\n\nReport bugs or crashes on [accent]Github[].
-indev.notready = This part of the game isn't ready yet
+indev.popup = [accent]v6[]仍在[accent]测试版[].\n[lightgray]这意味着:[]\n[scarlet]- 战役不完善[]\n- 内容不完整\n - 大多[scarlet]单位AI[]运行不佳\n- 单位系统不完整\n- 一切内容都可能发生变动或调整。\n\n向[accent]主群(QQ681962751)[]提交错误报告。
+indev.notready = 还没做好看NM
load.sound = 音乐加载中
load.map = 地图加载中
@@ -99,15 +99,15 @@ committingchanges = 正在提交更改
done = 已完成
feature.unsupported = 您的设备不支持此功能。
-mods.alphainfo = 请注意,测试版本(alpha)中的模组[scarlet]很容易存在缺陷[]。\n在 Mindustry 的 GitHub 或 Discord 上报告你发现的问题。
-mods.alpha = [accent](Alpha)
+mods.alphainfo = 请注意,测试版本中的模组[scarlet]很容易存在缺陷[]。\n在 Mindustry 的 GitHub 或 Discord 上报告你发现的问题。
+mods.alpha = [accent](测试)
mods = 模组
mods.none = [lightgray]没有找到模组!
mods.guide = 模组制作教程
mods.report = 报告 Bug
mods.openfolder = 打开模组文件夹
mods.reload = 重载
-mods.reloadexit = The game will now exit, to reload mods.
+mods.reloadexit = 游戏将退出以重载模组。
mod.display = [gray]模组:[orange] {0}
mod.enabled = [lightgray]已启用
mod.disabled = [scarlet]已禁用
@@ -115,7 +115,7 @@ mod.disable = 禁用
mod.content = 内容:
mod.delete.error = 无法删除模组。可能文件被占用。
mod.requiresversion = [scarlet]所需的游戏版本:[accent]{0}
-mod.outdated = [scarlet]Not compatible with V6 (no minGameVersion: 105)
+mod.outdated = [scarlet]模组不兼容6.0(缺失 minGameVersion: 105)
mod.missingdependencies = [scarlet]缺少前置模组:{0}
mod.erroredcontent = [scarlet]内容错误
mod.errors = 读取内容时发生错误.
@@ -127,7 +127,7 @@ mod.reloadrequired = [scarlet]需要重启
mod.import = 导入模组
mod.import.file = 导入文件
mod.import.github = 从 GitHub 导入模组
-mod.jarwarn = [scarlet]JAR mods are inherently unsafe.[]\nMake sure you're importing this mod from a trustworthy source!
+mod.jarwarn = [scarlet]JAR模组存在危险性。[]\n请确保此模组来源安全可靠!
mod.item.remove = 这个物品是[accent] '{0}'[]模组的一部分. 删除物品需要先卸载此模组.
mod.remove.confirm = 此模组将被删除。
mod.author = [lightgray]作者:[] {0}
@@ -139,8 +139,8 @@ mod.scripts.disable = 你的设备不支持含有脚本的模组。必须禁用
about.button = 关于
name = 名字:
noname = 先取一个[accent]玩家名[]。
-planetmap = Planet Map
-launchcore = Launch Core
+planetmap = 行星地图
+launchcore = 发射核心
filename = 文件名:
unlocked = 解锁了新内容!
completed = [accent]己研究
@@ -148,14 +148,14 @@ techtree = 科技树
research.list = [lightgray]研究:
research = 研究
researched = [lightgray]{0}己研究。
-research.progress = {0}% complete
+research.progress = {0}% 完成度
players = {0} 位玩家在线
players.single = {0} 位玩家在线
players.search = search
players.notfound = [gray]没有找到玩家。
server.closing = [accent]服务器关闭…
server.kicked.kick = 你被踢出了服务器。
-server.kicked.whitelist = 你并没有受邀请在此服务器上游玩。(不在白名单中)
+server.kicked.whitelist = 你不在服务器白名单中。
server.kicked.serverClose = 服务器已关闭。
server.kicked.vote = 你被投票踢出了服务器。
server.kicked.clientOutdated = 客户端过旧,请更新你的游戏。
@@ -278,7 +278,7 @@ quit.confirm.tutorial = 确定要跳过教程?\n您可以通过[accent]设置-
loading = [accent]加载中…
reloading = [accent]重载模组中…
saving = [accent]保存中…
-respawn = [accent][[{0}][] to respawn in core
+respawn = [accent][[{0}][]来重生
cancelbuilding = [accent][[{0}][]来清除规划
selectschematic = [accent][[{0}][]来选择复制
pausebuilding = [accent][[{0}][]来暂停建造
@@ -335,9 +335,9 @@ waves.never = < 无限 >
waves.every = 每
waves.waves = 波
waves.perspawn = 每次生成
-waves.shields = shields/wave
+waves.shields = 护盾/波次
waves.to = 至
-waves.guardian = Guardian
+waves.guardian = 首领
waves.preview = 预览
waves.edit = 编辑…
waves.copy = 复制到剪贴板
@@ -346,9 +346,9 @@ waves.invalid = 剪贴板中的波次信息无效。
waves.copied = 波次信息已复制。
waves.none = 没有定义敌人。\n请注意,这将自动替换为默认的敌人列表。
-wavemode.counts = counts
-wavemode.totals = totals
-wavemode.health = health
+wavemode.counts = 数目
+wavemode.totals = 总和
+wavemode.health = 生命值
editor.default = [lightgray]<默认>
details = 详情…
@@ -415,8 +415,8 @@ toolmode.drawteams.description = 绘制团队而不是方块。
filters.empty = [lightgray]没有过滤条件!用下方的按钮添加。
filter.distort = 扭曲程度
filter.noise = 波动程度
-filter.enemyspawn = Enemy Spawn Select
-filter.corespawn = Core Select
+filter.enemyspawn = 敌人生成点选择
+filter.corespawn = 核心降落点选择
filter.median = 平均数
filter.oremedian = 矿石平均数
filter.blend = 混合程度
@@ -469,12 +469,12 @@ locked = 已锁定
complete = [lightgray]完成:
requirement.wave = {1}中的第{0}波次
requirement.core = 在{0}中摧毁敌方核心
-requirement.research = Research {0}
-requirement.capture = Capture {0}
+requirement.research = 研究 {0}
+requirement.capture = 占领 {0}
resume = 暂停:\n[lightgray]{0}
bestwave = [lightgray]最高波次:{0}
launch = < 发射 >
-launch.text = Launch
+launch.text = 发射
launch.title = 发射成功
launch.next = [lightgray]下个发射窗口在第{0}波
launch.unable2 = [scarlet]无法发射[]
@@ -482,11 +482,11 @@ launch.confirm = 您将装载并发射核心中的所有资源。\n此地图将
launch.skip.confirm = 如果现在跳过,在下一个发射窗口到来前,您都无法发射。
uncover = 解锁
configure = 设定装运的数量
-loadout = Loadout
-resources = Resources
+loadout = 装运
+resources = 资源
bannedblocks = 禁用建筑
addall = 添加所有
-launch.destination = Destination: {0}
+launch.destination = 目的地: {0}
configure.invalid = 数量必须是0到{0}之间的数字。
zone.unlocked = [lightgray]{0} 已解锁。
zone.requirement.complete = 完成{0}。\n已达成解锁{1}的要求。
@@ -508,43 +508,43 @@ error.io = 网络 I/O 错误。
error.any = 未知网络错误。
error.bloom = 未能初始化特效。\n您的设备可能不支持。
-weather.rain.name = Rain
-weather.snow.name = Snow
-weather.sandstorm.name = Sandstorm
-weather.sporestorm.name = Sporestorm
+weather.rain.name = 降雨
+weather.snow.name = 降雪
+weather.sandstorm.name = 沙尘暴
+weather.sporestorm.name = 孢子雾
-sectors.unexplored = [lightgray]Unexplored
-sectors.resources = Resources:
-sectors.production = Production:
-sectors.stored = Stored:
-sectors.resume = Resume
-sectors.launch = Launch
-sectors.select = Select
-sectors.nonelaunch = [lightgray]none (sun)
+sectors.unexplored = [lightgray]未探索
+sectors.resources = 资源:
+sectors.production = 产出:
+sectors.stored = 贮存:
+sectors.resume = 继续
+sectors.launch = 发射
+sectors.select = 选择
+sectors.nonelaunch = [lightgray]无 (太阳)
-sector.groundZero.name = Ground Zero
-sector.craters.name = The Craters
-sector.frozenForest.name = Frozen Forest
-sector.ruinousShores.name = Ruinous Shores
-sector.stainedMountains.name = Stained Mountains
-sector.desolateRift.name = Desolate Rift
-sector.nuclearComplex.name = Nuclear Production Complex
-sector.overgrowth.name = Overgrowth
-sector.tarFields.name = Tar Fields
-sector.saltFlats.name = Salt Flats
-sector.fungalPass.name = Fungal Pass
+sector.groundZero.name = 零号地区
+sector.craters.name = 陨石带
+sector.frozenForest.name = 冰冻森林
+sector.ruinousShores.name = 遗迹海岸
+sector.stainedMountains.name = 绵延群山
+sector.desolateRift.name = 荒芜裂谷
+sector.nuclearComplex.name = 核裂阵
+sector.overgrowth.name = 增生区
+sector.tarFields.name = 油田
+sector.saltFlats.name = 盐碱荒滩
+sector.crags.name = 悬崖
-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.
-sector.saltFlats.description = On the outskirts of the desert lie the Salt Flats. Few resources can be found in this location.\n\nThe enemy has erected a resource storage complex here. Eradicate their core. Leave nothing standing.
-sector.craters.description = Water has accumulated in this crater, relic of the old wars. Reclaim the area. Collect sand. Smelt metaglass. Pump water to cool turrets and drills.
-sector.ruinousShores.description = Past the wastes, is the shoreline. Once, this location housed a coastal defense array. Not much of it remains. Only the most basic defense structures have remained unscathed, everything else reduced to scrap.\nContinue the expansion outwards. Rediscover the technology.
-sector.stainedMountains.description = Further inland lie the mountains, yet untainted by spores.\nExtract the abundant titanium in this area. Learn how to use it.\n\nThe enemy presence is greater here. Do not give them time to send their strongest units.
-sector.overgrowth.description = This area is overgrown, closer to the source of the spores.\nThe enemy has established an outpost here. Build Titan units. Destroy it. Reclaim that which was lost.
-sector.tarFields.description = The outskirts of an oil production zone, between the mountains and desert. One of the few areas with usable tar reserves.\nAlthough abandoned, this area has some dangerous enemy forces nearby. Do not underestimate them.\n\n[lightgray]Research oil processing technology if possible.
-sector.desolateRift.description = An extremely dangerous zone. Plentiful resources, but little space. High risk of destruction. Leave as soon as possible. Do not be fooled by the long spacing between enemy attacks.
-sector.nuclearComplex.description = A former facility for the production and processing of thorium, reduced to ruins.\n[lightgray]Research the thorium and its many uses.\n\nThe enemy is present here in great numbers, constantly scouting for attackers.
-sector.fungalPass.description = A transition area between high mountains and lower, spore-ridden lands. A small enemy reconnaissance base is located here.\nDestroy it.\nUse Dagger and Crawler units. Take out the two cores.
+sector.groundZero.description = 踏上旅程的最佳位置。这儿的敌人威胁很小,但资源也少。\n收集尽可能多的铅和铜。\n出发吧!
+sector.frozenForest.description = 即使是靠近山脉的这里,孢子也已经扩散。他们不能长期停留在寒冷的温度中。\n\n开始运用电力。建造火力发电机并学会使用修理者。
+sector.saltFlats.description = 在沙漠的郊区有盐滩。在这个地方几乎找不到资源。\n\n敌人在这里建立了一个资源存储区。摧毁他们的核心。不要留下任何东西。
+sector.craters.description = 水在这个火山口积聚,这是旧战争的遗迹。夺下该区域。收集沙子来冶炼玻璃。用水泵抽水来加速炮塔和钻头。
+sector.ruinousShores.description = 穿过荒地,就是海岸线。这个地方曾经建造了一个海岸防御线。但现在所剩无几,只有最基本的防御结构仍然毫发无损,其他一切都被摧毁了。\n继续向外扩展。继续研究科技。
+sector.stainedMountains.description = 在更远的内陆地区是山脉,但这里没有被孢子污染。\n这一地区分布着丰富的钛,学习如何使用它。\n\n这里的敌人势力更大,不要给他们时间派出最强的部队。
+sector.overgrowth.description = 这个地区靠近孢子的来源,因此生长过度。\n敌人在这里建立了一个前哨站。建造尖刀单位来摧毁它并找回丢失的东西。
+sector.tarFields.description = 产油区边缘,位于山脉和沙漠之间。它少数几个有石油储量的地区之一。\n尽管被废弃,这附近仍有一些危险的敌方单位。不要低估他们。\n\n[lightgray]如果可能,研究石油加工技术。
+sector.desolateRift.description = 非常危险的区域。这儿的资源丰富但空间很小。敌人十分危险。尽快离开,不要被敌人的攻击间隔太长所愚弄。
+sector.nuclearComplex.description = 以前生产和加工钍的设施已变成废墟。\n[lightgray]研究钍及其多种用途。\n\n敌人在这里大量存在,不断消灭入侵者。
+sector.fungalPass.description = 介于高山和低矮孢子丛生的土地之间的过渡地带。这里有一个小型的敌方侦察基地。\n侦察它。\n使用尖刀和爬行者单位来摧毁两个核心。
settings.language = 语言
settings.data = 游戏数据
@@ -558,65 +558,65 @@ settings.graphics = 图像
settings.cleardata = 清除游戏数据…
settings.clear.confirm = 您确定要清除此数据?\n此操作无法撤销!
settings.clearall.confirm = [scarlet]警告![]\n这将清除所有数据,包括存档、地图、解锁和按键绑定。\n按「是」后,游戏将删除所有数据并自动退出。
-settings.clearsaves.confirm = Are you sure you want to clear all your saves?
-settings.clearsaves = Clear Saves
+settings.clearsaves.confirm = 您确定要清除存档?
+settings.clearsaves = 清除存档
paused = [accent]< 暂停 >
clear = 清除
banned = [scarlet]已禁止
-unplaceable.sectorcaptured = [scarlet]Requires captured sector
+unplaceable.sectorcaptured = [scarlet]需要占领区块
yes = 是
no = 否
info.title = [accent]详情
error.title = [crimson]发生了一个错误
error.crashtitle = 发生了一个错误
unit.nobuild = [scarlet]单位未能建造
-blocks.input = 输入
-blocks.output = 输出
-blocks.booster = 增强物品/液体
-blocks.tiles = 所需地型
-blocks.affinities = 相关
+stat.input = 输入
+stat.output = 输出
+stat.booster = 增强物品/液体
+stat.tiles = 所需地型
+stat.affinities = 相关
block.unknown = [lightgray]???
-blocks.powercapacity = 能量容量
-blocks.powershot = 能量/发射
-blocks.damage = 伤害
-blocks.targetsair = 攻击空中单位
-blocks.targetsground = 攻击地面单位
-blocks.itemsmoved = 移动速度
-blocks.launchtime = 发射间隔时间
-blocks.shootrange = 范围
-blocks.size = 尺寸
-blocks.displaysize = Display Size
-blocks.liquidcapacity = 液体容量
-blocks.powerrange = 能量范围
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = 最多连接
-blocks.poweruse = 使用能量
-blocks.powerdamage = 功率/损伤
-blocks.itemcapacity = 物品容量
-blocks.basepowergeneration = 基础能源输出
-blocks.productiontime = 生产时间
-blocks.repairtime = 建筑完全修复时间
-blocks.speedincrease = 提速
-blocks.range = 范围
-blocks.drilltier = 可钻探矿物
-blocks.drillspeed = 基础钻探速度
-blocks.boosteffect = 增强效果
-blocks.maxunits = 最大单位数量
-blocks.health = 生命值
-blocks.buildtime = 建造时间
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = 建造花费
-blocks.inaccuracy = 误差
-blocks.shots = 发射数
-blocks.reload = 每秒发射数
-blocks.ammo = 弹药
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = 能量容量
+stat.powershot = 能量/发射
+stat.damage = 伤害
+stat.targetsair = 攻击空中单位
+stat.targetsground = 攻击地面单位
+stat.itemsmoved = 移动速度
+stat.launchtime = 发射间隔时间
+stat.shootrange = 范围
+stat.size = 尺寸
+stat.displaysize = 显示尺寸
+stat.liquidcapacity = 液体容量
+stat.powerrange = 能量范围
+stat.linkrange = 连接范围
+stat.instructions = 指令数量
+stat.powerconnections = 最多连接
+stat.poweruse = 使用能量
+stat.powerdamage = 功率/损伤
+stat.itemcapacity = 物品容量
+stat.basepowergeneration = 基础能源输出
+stat.productiontime = 生产时间
+stat.repairtime = 建筑完全修复时间
+stat.speedincrease = 提速
+stat.range = 范围
+stat.drilltier = 可钻探矿物
+stat.drillspeed = 基础钻探速度
+stat.boosteffect = 增强效果
+stat.maxunits = 最大单位数量
+stat.health = 生命值
+stat.buildtime = 建造时间
+stat.maxconsecutive = 最大连续
+stat.buildcost = 建造花费
+stat.inaccuracy = 误差
+stat.shots = 发射数
+stat.reload = 每秒发射数
+stat.ammo = 弹药
+stat.shieldhealth = 盾容
+stat.cooldowntime = 冷却时间
bar.drilltierreq = 需要更好的钻头
-bar.noresources = Missing Resources
-bar.corereq = Core Base Required
+bar.noresources = 缺失资源
+bar.corereq = 缺失核心基座
bar.drillspeed = 挖掘速度:{0}/秒
bar.pumpspeed = 泵压速度:{0}/秒
bar.efficiency = 效率:{0}%
@@ -627,7 +627,7 @@ bar.poweroutput = 能量输出:{0}
bar.items = 物品:{0}
bar.capacity = 容量:{0}
bar.unitcap = {0} {1}/{2}
-bar.limitreached = [scarlet] {0} / {1}[white] {2}\n[lightgray][[unit disabled]
+bar.limitreached = [scarlet] {0} / {1}[white] {2}\n[lightgray][[单位上限]
bar.liquid = 液体
bar.heat = 热量
bar.power = 电力
@@ -639,7 +639,7 @@ bullet.damage = [stat]{0}[lightgray] 伤害
bullet.splashdamage = [stat]{0}[lightgray] 范围伤害 ~[stat] {1}[lightgray] 格
bullet.incendiary = [stat] 燃烧
bullet.homing = [stat] 追踪
-bullet.shock = [stat] 击晕
+bullet.shock = [stat] 电击
bullet.frag = [stat] 分裂
bullet.knockback = [stat]{0}[lightgray] 击退
bullet.freezing = [stat] 冰冻
@@ -655,16 +655,16 @@ unit.liquidunits = 液体
unit.powerunits = 能量
unit.degrees = 度
unit.seconds = 秒
-unit.minutes = mins
+unit.minutes = 分
unit.persecond = /秒
-unit.perminute = /min
+unit.perminute = /分
unit.timesspeed = 倍 速度
unit.percent = %
-unit.shieldhealth = shield health
+unit.shieldhealth = 盾容
unit.items = 物品
-unit.thousands = k
-unit.millions = mil
-unit.billions = b
+unit.thousands = K
+unit.millions = M
+unit.billions = B
category.general = 普通
category.power = 能量
category.liquids = 液体
@@ -720,7 +720,7 @@ setting.minimap.name = 显示小地图
setting.coreitems.name = 显示核心 (开发中)
setting.position.name = 显示玩家坐标
setting.musicvol.name = 音乐音量
-setting.atmosphere.name = Show Planet Atmosphere
+setting.atmosphere.name = 显示行星大气层
setting.ambientvol.name = 环境音量
setting.mutemusic.name = 无音乐
setting.sfxvol.name = 音效音量
@@ -743,14 +743,14 @@ keybinds.mobile = [scarlet]这里的大多数按键绑定在移动设备上都
category.general.name = 常规
category.view.name = 视图
category.multiplayer.name = 多人
-category.blocks.name = Block Select
+category.blocks.name = 选择方块
command.attack = 攻击
command.rally = 集合
command.retreat = 撤退
-command.idle = Idle
+command.idle = 闲置
placement.blockselectkeys = \n[lightgray]按键:[{0},
keybind.respawn.name = 重生
-keybind.control.name = Control Unit
+keybind.control.name = 控制单位
keybind.clear_building.name = 清除建筑
keybind.press = 请按一个键…
keybind.press.axis = 请按一个轴或键…
@@ -760,8 +760,8 @@ keybind.toggle_block_status.name = 显隐方块状态
keybind.move_x.name = 水平移动
keybind.move_y.name = 竖直移动
keybind.mouse_move.name = 跟随鼠标
-keybind.pan.name = Pan View
-keybind.boost.name = 推送
+keybind.pan.name = 平移视图
+keybind.boost.name = 推进
keybind.schematic_select.name = 选择区域
keybind.schematic_menu.name = 蓝图目录
keybind.schematic_flip_x.name = 水平翻转
@@ -788,9 +788,9 @@ keybind.diagonal_placement.name = 斜线建造
keybind.pick.name = 选择建筑
keybind.break_block.name = 破坏建筑
keybind.deselect.name = 取消选择
-keybind.pickupCargo.name = Pickup Cargo
-keybind.dropCargo.name = Drop Cargo
-keybind.command.name = Command
+keybind.pickupCargo.name = 拾取货物
+keybind.dropCargo.name = 释放货物
+keybind.command.name = 指挥
keybind.shoot.name = 射击
keybind.zoom.name = 缩放
keybind.menu.name = 菜单
@@ -825,10 +825,10 @@ rules.reactorexplosions = 反应堆爆炸
rules.wavetimer = 波次计时器
rules.waves = 波次
rules.attack = 攻击模式
-rules.buildai = AI Building
+rules.buildai = AI建造
rules.enemyCheat = 敌人(红队)无限资源
rules.blockhealthmultiplier = 建筑生命倍数
-rules.blockdamagemultiplier = Block Damage Multiplier
+rules.blockdamagemultiplier = 建筑伤害倍数
rules.unitbuildspeedmultiplier = 单位生产速度倍数
rules.unithealthmultiplier = 单位生命倍数
rules.unitdamagemultiplier = 单位伤害倍数
@@ -839,20 +839,20 @@ rules.buildspeedmultiplier = 建设时间倍数
rules.deconstructrefundmultiplier = 拆除返还倍数
rules.waitForWaveToEnd = 等待敌人时间
rules.dropzoneradius = 敌人出生点禁区大小:[lightgray](格)
-rules.unitammo = Units Require Ammo
+rules.unitammo = 单位消耗子弹
rules.title.waves = 波次
rules.title.resourcesbuilding = 资源和建造
rules.title.enemy = 敌人
rules.title.unit = 单位
rules.title.experimental = 实验性
-rules.title.environment = Environment
+rules.title.environment = 环境性
rules.lighting = 光照
rules.fire = Fire
-rules.explosions = Block/Unit Explosion Damage
+rules.explosions = 建筑/单位爆炸伤害
rules.ambientlight = 环境光
-rules.weather = Weather
-rules.weather.frequency = Frequency:
-rules.weather.duration = Duration:
+rules.weather = 气候
+rules.weather.frequency = 频率:
+rules.weather.duration = 时长:
content.item.name = 物品
content.liquid.name = 液体
@@ -897,61 +897,61 @@ liquid.viscosity = [lightgray]粘度:{0}
liquid.temperature = [lightgray]温度:{0}
unit.dagger.name = 尖刀
-unit.mace.name = Mace
+unit.mace.name = 牙狼
unit.fortress.name = 堡垒
-unit.nova.name = Nova
-unit.pulsar.name = Pulsar
-unit.quasar.name = Quasar
-unit.crawler.name = 爬行者
-unit.atrax.name = Atrax
-unit.spiroct.name = Spiroct
-unit.arkyid.name = Arkyid
-unit.toxopid.name = Toxopid
-unit.flare.name = Flare
-unit.horizon.name = Horizon
-unit.zenith.name = Zenith
-unit.antumbra.name = Antumbra
-unit.eclipse.name = Eclipse
-unit.mono.name = Mono
-unit.poly.name = Poly
-unit.mega.name = Mega
-unit.quad.name = Quad
-unit.oct.name = Oct
-unit.risso.name = Risso
-unit.minke.name = Minke
-unit.bryde.name = Bryde
-unit.sei.name = Sei
-unit.omura.name = Omura
-unit.alpha.name = Alpha
-unit.beta.name = Beta
-unit.gamma.name = Gamma
-unit.scepter.name = Scepter
-unit.reign.name = Reign
-unit.vela.name = Vela
-unit.corvus.name = Corvus
+unit.nova.name = 新星
+unit.pulsar.name = 脉冲星
+unit.quasar.name = 超星
+unit.crawler.name = 爬虫
+unit.atrax.name = 火蛛
+unit.spiroct.name = 天蝎
+unit.arkyid.name = 血蛭
+unit.toxopid.name = 毒蟒
+unit.flare.name = 星耀
+unit.horizon.name = 天垠
+unit.zenith.name = 苍穹
+unit.antumbra.name = 半影
+unit.eclipse.name = 日蚀
+unit.mono.name = 独影
+unit.poly.name = 聚幻
+unit.mega.name = 巨像
+unit.quad.name = 雷霆
+unit.oct.name = 要塞
+unit.risso.name = 梭鱼
+unit.minke.name = 刺鲸
+unit.bryde.name = 虎鲨
+unit.sei.name = 湖妖
+unit.omura.name = 海神
+unit.alpha.name = 阿尔法
+unit.beta.name = 贝塔
+unit.gamma.name = 伽玛
+unit.scepter.name = 权杖
+unit.reign.name = 君王
+unit.vela.name = 灾星
+unit.corvus.name = 死星
-block.resupply-point.name = Resupply Point
-block.parallax.name = Parallax
+block.resupply-point.name = 补给点
+block.parallax.name = 阻滞光束
block.cliff.name = 悬崖
block.sand-boulder.name = 沙砂巨石
block.grass.name = 草地
block.slag.name = 矿渣
block.salt.name = 盐碱地
-block.salt-wall.name = Salt Wall
+block.salt-wall.name = 盐墙
block.pebbles.name = 鹅卵石
block.tendrils.name = 卷须
-block.sand-wall.name = Sand Wall
+block.sand-wall.name = 沙墙
block.spore-pine.name = 孢子树
-block.spore-wall.name = Spore Wall
-block.boulder.name = Boulder
-block.snow-boulder.name = Snow Boulder
+block.spore-wall.name = 孢子墙
+block.boulder.name = 巨石
+block.snow-boulder.name = 雪石
block.snow-pine.name = 雪树
block.shale.name = 页岩地
block.shale-boulder.name = 页岩巨石
block.moss.name = 苔藓地
block.shrubs.name = 灌木丛
block.spore-moss.name = 孢子苔藓地
-block.shale-wall.name = Shale Wall
+block.shale-wall.name = 页岩墙
block.scrap-wall.name = 废墙
block.scrap-wall-large.name = 大型废墙
block.scrap-wall-huge.name = 巨型废墙
@@ -979,17 +979,17 @@ block.craters.name = 陨石坑
block.sand-water.name = 沙 水
block.darksand-water.name = 暗沙 水
block.char.name = 焦土
-block.dacite.name = Dacite
-block.dacite-wall.name = Dacite Wall
+block.dacite.name = 英安岩
+block.dacite-wall.name = 英安岩墙
block.ice-snow.name = 冰雪地
-block.stone-wall.name = Stone Wall
-block.ice-wall.name = Ice Wall
-block.snow-wall.name = Snow Wall
-block.dune-wall.name = Dune Wall
+block.stone-wall.name = 石墙
+block.ice-wall.name = 冰墙
+block.snow-wall.name = 雪墙
+block.dune-wall.name = 沙丘岩
block.pine.name = 松树
-block.dirt.name = Dirt
-block.dirt-wall.name = Dirt Wall
-block.mud.name = Mud
+block.dirt.name = 泥土
+block.dirt-wall.name = 泥土墙
+block.mud.name = 泥巴
block.white-tree-dead.name = 枯萎的白树
block.white-tree.name = 白树
block.spore-cluster.name = 孢子簇
@@ -1005,7 +1005,7 @@ block.dark-panel-4.name = 暗面板4
block.dark-panel-5.name = 暗面板5
block.dark-panel-6.name = 暗面板6
block.dark-metal.name = 暗金属
-block.basalt.name = Basalt
+block.basalt.name = 玄武岩
block.hotrock.name = 热石头
block.magmarock.name = 岩浆石头
block.copper-wall.name = 铜墙
@@ -1081,8 +1081,8 @@ block.ripple.name = 浪涌
block.phase-conveyor.name = 相织物传送带桥
block.bridge-conveyor.name = 传送带桥
block.plastanium-compressor.name = 塑钢压缩机
-block.pyratite-mixer.name = 硫混合器
-block.blast-mixer.name = 爆炸混合器
+block.pyratite-mixer.name = 硫化物混合器
+block.blast-mixer.name = 爆炸物混合器
block.solar-panel.name = 太阳能板
block.solar-panel-large.name = 大型太阳能板
block.oil-extractor.name = 石油钻井
@@ -1101,12 +1101,12 @@ block.blast-drill.name = 爆破钻头
block.thermal-pump.name = 热能泵
block.thermal-generator.name = 热能发电机
block.alloy-smelter.name = 合金冶炼厂
-block.mender.name = 修理者
+block.mender.name = 修复器
block.mend-projector.name = 修理投影器
block.surge-wall.name = 波动墙
block.surge-wall-large.name = 大型波动墙
-block.cyclone.name = 气旋炮
-block.fuse.name = 雷光炮
+block.cyclone.name = 气旋
+block.fuse.name = 雷光
block.shock-mine.name = 脉冲地雷
block.overdrive-projector.name = 超速投影器
block.force-projector.name = 力墙投影器
@@ -1117,28 +1117,28 @@ block.meltdown.name = 熔毁
block.container.name = 容器
block.launch-pad.name = 发射台
block.launch-pad-large.name = 大型发射台
-block.segment.name = 分割机
-block.command-center.name = Command Center
-block.ground-factory.name = 地面工厂
-block.air-factory.name = Air Factory
-block.naval-factory.name = Naval Factory
-block.additive-reconstructor.name = Additive Reconstructor
-block.multiplicative-reconstructor.name = Multiplicative Reconstructor
-block.exponential-reconstructor.name = Exponential Reconstructor
-block.tetrative-reconstructor.name = Tetrative Reconstructor
-block.payload-conveyor.name = Mass Conveyor
-block.payload-router.name = Payload Router
-block.disassembler.name = Disassembler
-block.silicon-crucible.name = Silicon Crucible
-block.overdrive-dome.name = Overdrive Dome
+block.segment.name = 裂解光束
+block.command-center.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.payload-conveyor.name = 载荷传送带
+block.payload-router.name = 载荷路由器
+block.disassembler.name = 分离机
+block.silicon-crucible.name = 热能坩埚
+block.overdrive-dome.name = 超速场投射器
-block.switch.name = Switch
-block.micro-processor.name = Micro Processor
-block.logic-processor.name = Logic Processor
-block.hyper-processor.name = Hyper Processor
-block.logic-display.name = Logic Display
-block.large-logic-display.name = Large Logic Display
-block.memory-cell.name = Memory Cell
+block.switch.name = 开关
+block.micro-processor.name = 微型处理器
+block.logic-processor.name = 逻辑处理器
+block.hyper-processor.name = 超频处理器
+block.logic-display.name = 逻辑显示屏
+block.large-logic-display.name = 大型逻辑显示屏
+block.memory-cell.name = 存储单元
team.blue.name = 蓝
team.crux.name = 红
@@ -1299,7 +1299,7 @@ block.salvo.description = 双管炮的升级版。中型,快速射出一串子
block.fuse.description = 大型近程炮塔,发射三道刺穿敌人的短程光束。
block.ripple.description = 大型远程炮台,非常强力,向远处的敌人投射一簇弹药。
block.cyclone.description = 大型炮塔,对空对地,发射在敌人周围引爆的爆炸物。
-block.spectre.description = 超大型炮塔,对空对地,一次射出两颗强大的穿甲弹药。
+block.spectre.description = 超大型炮塔,对空对地,一次射出两颗强大的破甲弹。
block.meltdown.description = 超大型激光炮塔,充能之后持续发射光束,需要冷却剂。
-block.repair-point.description = 持续治疗其附近伤势最重的单位。
-block.segment.description = 对行进中的导弹进行破坏和摧毁, 除激光以外.
+block.repair-point.description = 持续治疗其附近受损最严重的单位。
+block.segment.description = 摧毁袭来的除激光以外的子弹或导弹.
\ No newline at end of file
diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties
index 85efa9a527..e495f4b768 100644
--- a/core/assets/bundles/bundle_zh_TW.properties
+++ b/core/assets/bundles/bundle_zh_TW.properties
@@ -570,49 +570,49 @@ info.title = 資訊
error.title = [crimson]發生錯誤
error.crashtitle = 發生錯誤
unit.nobuild = [scarlet]單位不能建造
-blocks.input = 輸入
-blocks.output = 輸出
-blocks.booster = 強化
-blocks.tiles = 需求方塊
-blocks.affinities = 親和方塊
+stat.input = 輸入
+stat.output = 輸出
+stat.booster = 強化
+stat.tiles = 需求方塊
+stat.affinities = 親和方塊
block.unknown = [lightgray]???
-blocks.powercapacity = 蓄電量
-blocks.powershot = 能量/射擊
-blocks.damage = 傷害
-blocks.targetsair = 攻擊空中目標
-blocks.targetsground = 攻擊地面目標
-blocks.itemsmoved = 移動速度
-blocks.launchtime = 發射間隔
-blocks.shootrange = 範圍
-blocks.size = 尺寸
-blocks.displaysize = Display Size
-blocks.liquidcapacity = 液體容量
-blocks.powerrange = 輸出範圍
-blocks.linkrange = Link Range
-blocks.instructions = Instructions
-blocks.powerconnections = 最大連接數
-blocks.poweruse = 能量使用
-blocks.powerdamage = 能量/傷害
-blocks.itemcapacity = 物品容量
-blocks.basepowergeneration = 基礎能量生產
-blocks.productiontime = 生產時間
-blocks.repairtime = 方塊完全修復時間
-blocks.speedincrease = 速度提升
-blocks.range = 範圍
-blocks.drilltier = 可鑽取礦物
-blocks.drillspeed = 基本鑽取速度
-blocks.boosteffect = 提升效應
-blocks.maxunits = 最大活躍單位
-blocks.health = 耐久度
-blocks.buildtime = 建設時間
-blocks.maxconsecutive = Max Consecutive
-blocks.buildcost = 建造成本
-blocks.inaccuracy = 誤差
-blocks.shots = 射擊數
-blocks.reload = 射擊次數/秒
-blocks.ammo = 彈藥
-blocks.shieldhealth = Shield Health
-blocks.cooldowntime = Cooldown Time
+stat.powercapacity = 蓄電量
+stat.powershot = 能量/射擊
+stat.damage = 傷害
+stat.targetsair = 攻擊空中目標
+stat.targetsground = 攻擊地面目標
+stat.itemsmoved = 移動速度
+stat.launchtime = 發射間隔
+stat.shootrange = 範圍
+stat.size = 尺寸
+stat.displaysize = Display Size
+stat.liquidcapacity = 液體容量
+stat.powerrange = 輸出範圍
+stat.linkrange = Link Range
+stat.instructions = Instructions
+stat.powerconnections = 最大連接數
+stat.poweruse = 能量使用
+stat.powerdamage = 能量/傷害
+stat.itemcapacity = 物品容量
+stat.basepowergeneration = 基礎能量生產
+stat.productiontime = 生產時間
+stat.repairtime = 方塊完全修復時間
+stat.speedincrease = 速度提升
+stat.range = 範圍
+stat.drilltier = 可鑽取礦物
+stat.drillspeed = 基本鑽取速度
+stat.boosteffect = 提升效應
+stat.maxunits = 最大活躍單位
+stat.health = 耐久度
+stat.buildtime = 建設時間
+stat.maxconsecutive = Max Consecutive
+stat.buildcost = 建造成本
+stat.inaccuracy = 誤差
+stat.shots = 射擊數
+stat.reload = 射擊次數/秒
+stat.ammo = 彈藥
+stat.shieldhealth = Shield Health
+stat.cooldowntime = Cooldown Time
bar.drilltierreq = 需要更好的鑽頭
bar.noresources = Missing Resources
@@ -1302,4 +1302,4 @@ block.cyclone.description = 一種對空和對地的大型砲塔。向附近單
block.spectre.description = 一種雙炮管的巨型砲塔。向空中及地面敵人發射大型的穿甲彈。
block.meltdown.description = 一種巨型激光砲塔。充能並發射持續性的激光光束。需要冷卻液以運作。
block.repair-point.description = 持續治療附近最近的受損單位。
-block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
+block.segment.description = Damages and destroys incoming projectiles. Laser projectiles are not targeted.
\ No newline at end of file
diff --git a/core/assets/contributors b/core/assets/contributors
index 69de5a3d8e..9f1cf8c9f4 100644
--- a/core/assets/contributors
+++ b/core/assets/contributors
@@ -95,3 +95,4 @@ ThePlayerA
YellOw139
PetrGasparik
LeoDog896
+Summet
diff --git a/core/assets/maps/caldera.msav b/core/assets/maps/caldera.msav
index fae2a2e862..57bb5c382f 100644
Binary files a/core/assets/maps/caldera.msav and b/core/assets/maps/caldera.msav differ
diff --git a/core/assets/maps/craters.msav b/core/assets/maps/craters.msav
index b10b354bf0..04c1aa73d3 100644
Binary files a/core/assets/maps/craters.msav and b/core/assets/maps/craters.msav differ
diff --git a/core/assets/maps/fork.msav b/core/assets/maps/fork.msav
index f4bf6985fe..2fd62bd91b 100644
Binary files a/core/assets/maps/fork.msav and b/core/assets/maps/fork.msav differ
diff --git a/core/assets/maps/frozenForest.msav b/core/assets/maps/frozenForest.msav
index a2a1f52354..0eb9f1fe56 100644
Binary files a/core/assets/maps/frozenForest.msav and b/core/assets/maps/frozenForest.msav differ
diff --git a/core/assets/maps/fungalPass.msav b/core/assets/maps/fungalPass.msav
index c154c2e4db..1e3a26f520 100644
Binary files a/core/assets/maps/fungalPass.msav and b/core/assets/maps/fungalPass.msav differ
diff --git a/core/assets/maps/islands.msav b/core/assets/maps/islands.msav
index 1b833e98d0..90159d57e0 100644
Binary files a/core/assets/maps/islands.msav and b/core/assets/maps/islands.msav differ
diff --git a/core/assets/maps/moltenLake.msav b/core/assets/maps/moltenLake.msav
new file mode 100644
index 0000000000..a409307c6f
Binary files /dev/null and b/core/assets/maps/moltenLake.msav differ
diff --git a/core/assets/maps/mudFlats.msav b/core/assets/maps/mudFlats.msav
new file mode 100644
index 0000000000..1ba2e25ceb
Binary files /dev/null and b/core/assets/maps/mudFlats.msav differ
diff --git a/core/assets/maps/ruinousShores.msav b/core/assets/maps/ruinousShores.msav
index a0ef267a99..41e957c0ff 100644
Binary files a/core/assets/maps/ruinousShores.msav and b/core/assets/maps/ruinousShores.msav differ
diff --git a/core/assets/maps/saltFlats.msav b/core/assets/maps/saltFlats.msav
index 9a70ba342a..556b33700f 100644
Binary files a/core/assets/maps/saltFlats.msav and b/core/assets/maps/saltFlats.msav differ
diff --git a/core/assets/maps/shattered.msav b/core/assets/maps/shattered.msav
index a822e2d121..549e42cab7 100644
Binary files a/core/assets/maps/shattered.msav and b/core/assets/maps/shattered.msav differ
diff --git a/core/assets/maps/tarFields.msav b/core/assets/maps/tarFields.msav
index 06eaed164d..bf8b306f95 100644
Binary files a/core/assets/maps/tarFields.msav and b/core/assets/maps/tarFields.msav differ
diff --git a/core/assets/maps/tendrils.msav b/core/assets/maps/tendrils.msav
index 3034fb5ec1..825437d6c5 100644
Binary files a/core/assets/maps/tendrils.msav and b/core/assets/maps/tendrils.msav differ
diff --git a/core/assets/scripts/base.js b/core/assets/scripts/base.js
index c6d7be846b..ace7d878ee 100755
--- a/core/assets/scripts/base.js
+++ b/core/assets/scripts/base.js
@@ -9,8 +9,8 @@ const readBytes = path => Vars.mods.getScripts().readBytes(path)
const loadMusic = path => Vars.mods.getScripts().loadMusic(path)
const loadSound = path => Vars.mods.getScripts().loadSound(path)
-var scriptName = "base.js"
-var modName = "none"
+let scriptName = "base.js"
+let modName = "none"
const print = text => log(modName + "/" + scriptName, text);
diff --git a/core/assets/shaders/default.frag b/core/assets/shaders/default.frag
new file mode 100644
index 0000000000..93be3cffc9
--- /dev/null
+++ b/core/assets/shaders/default.frag
@@ -0,0 +1,9 @@
+varying lowp vec4 v_color;
+varying lowp vec4 v_mix_color;
+varying vec2 v_texCoords;
+uniform sampler2D u_texture;
+
+void main(){
+ vec4 c = texture2D(u_texture, v_texCoords);
+ gl_FragColor = v_color * mix(c, vec4(v_mix_color.rgb, c.a), v_mix_color.a);
+}
\ No newline at end of file
diff --git a/core/assets/shaders/planet.vert b/core/assets/shaders/planet.vert
index f500af0ecf..4723e2bfff 100755
--- a/core/assets/shaders/planet.vert
+++ b/core/assets/shaders/planet.vert
@@ -10,7 +10,7 @@ uniform vec3 u_ambientColor;
varying vec4 v_col;
-const vec3 diffuse = vec3(0);
+const vec3 diffuse = vec3(0.01);
const float shinefalloff = 4.0;
const float shinelen = 0.2;
diff --git a/core/assets/sprites/block_colors.png b/core/assets/sprites/block_colors.png
index 3e19c96e61..e8845aa072 100644
Binary files a/core/assets/sprites/block_colors.png and b/core/assets/sprites/block_colors.png differ
diff --git a/core/assets/sprites/fallback/sprites5.png b/core/assets/sprites/fallback/sprites5.png
index e413db1a18..87ee3a7b46 100644
Binary files a/core/assets/sprites/fallback/sprites5.png and b/core/assets/sprites/fallback/sprites5.png differ
diff --git a/core/assets/sprites/fallback/sprites6.png b/core/assets/sprites/fallback/sprites6.png
index 94069305e4..a47c2d47eb 100644
Binary files a/core/assets/sprites/fallback/sprites6.png and b/core/assets/sprites/fallback/sprites6.png differ
diff --git a/core/assets/sprites/fallback/sprites7.png b/core/assets/sprites/fallback/sprites7.png
index 9e083fdec4..dd3d40dc80 100644
Binary files a/core/assets/sprites/fallback/sprites7.png and b/core/assets/sprites/fallback/sprites7.png differ
diff --git a/core/assets/sprites/fallback/sprites8.png b/core/assets/sprites/fallback/sprites8.png
index 4c47261514..212d169c38 100644
Binary files a/core/assets/sprites/fallback/sprites8.png and b/core/assets/sprites/fallback/sprites8.png differ
diff --git a/core/assets/sprites/fog.png b/core/assets/sprites/fog.png
new file mode 100644
index 0000000000..5121693e58
Binary files /dev/null and b/core/assets/sprites/fog.png differ
diff --git a/core/assets/sprites/sprites2.png b/core/assets/sprites/sprites2.png
index fba6d8fe48..4a26e4dbe9 100644
Binary files a/core/assets/sprites/sprites2.png and b/core/assets/sprites/sprites2.png differ
diff --git a/core/assets/sprites/sprites3.png b/core/assets/sprites/sprites3.png
index 6e26e044e2..627f4e763c 100644
Binary files a/core/assets/sprites/sprites3.png and b/core/assets/sprites/sprites3.png differ
diff --git a/core/assets/sprites/sprites4.png b/core/assets/sprites/sprites4.png
index 4a76287a49..20eed12539 100644
Binary files a/core/assets/sprites/sprites4.png and b/core/assets/sprites/sprites4.png differ
diff --git a/core/assets/sprites/sprites5.png b/core/assets/sprites/sprites5.png
index a85adcfbb9..2fe5605d60 100644
Binary files a/core/assets/sprites/sprites5.png and b/core/assets/sprites/sprites5.png differ
diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java
index 37ba22d3cb..2cf07cbea6 100644
--- a/core/src/mindustry/Vars.java
+++ b/core/src/mindustry/Vars.java
@@ -36,6 +36,8 @@ public class Vars implements Loadable{
public static boolean loadLocales = true;
/** Whether the logger is loaded. */
public static boolean loadedLogger = false, loadedFileLogger = false;
+ /** Whether to show the cliff button in the editor*/
+ public static boolean addCliffButton = false;
/** Maximum extra padding around deployment schematics. */
public static final int maxLoadoutSchematicPad = 5;
/** Maximum schematic size.*/
@@ -86,8 +88,10 @@ public class Vars implements Loadable{
public static final float logicItemTransferRange = 45f;
/** duration of time between turns in ticks */
public static final float turnDuration = 2 * Time.toMinutes;
- /** turns needed to destroy a sector completely */
- public static final float sectorDestructionTurns = 2f;
+ /** chance of an invasion per turn, 1 = 100% */
+ public static final float baseInvasionChance = 1f / 30f;
+ /** how many turns have to pass before invasions start */
+ public static final int invasionGracePeriod = 20;
/** min armor fraction damage; e.g. 0.05 = at least 5% damage */
public static final float minArmorDamage = 0.1f;
/** launch animation duration */
@@ -281,10 +285,10 @@ public class Vars implements Loadable{
if(loadedLogger) return;
String[] tags = {"[green][D][]", "[royal][I][]", "[yellow][W][]", "[scarlet][E][]", ""};
- String[] stags = {"&lc&fb[D]", "&lg&fb[I]", "&ly&fb[W]", "&lr&fb[E]", ""};
+ String[] stags = {"&lc&fb[D]", "&lb&fb[I]", "&ly&fb[W]", "&lr&fb[E]", ""};
Seq logBuffer = new Seq<>();
- Log.setLogger((level, text) -> {
+ Log.logger = (level, text) -> {
String result = text;
String rawText = Log.format(stags[level.ordinal()] + "&fr " + text);
System.out.println(rawText);
@@ -300,9 +304,9 @@ public class Vars implements Loadable{
}
}
- ui.scriptfrag.addMessage(Log.removeCodes(result));
+ ui.scriptfrag.addMessage(Log.removeColors(result));
}
- });
+ };
Events.on(ClientLoadEvent.class, e -> logBuffer.each(ui.scriptfrag::addMessage));
@@ -315,18 +319,19 @@ public class Vars implements Loadable{
settings.setAppName(appName);
Writer writer = settings.getDataDirectory().child("last_log.txt").writer(false);
- LogHandler log = Log.getLogger();
- Log.setLogger((level, text) -> {
+ LogHandler log = Log.logger;
+ //ignore it
+ Log.logger = (level, text) -> {
log.log(level, text);
try{
- writer.write("[" + Character.toUpperCase(level.name().charAt(0)) +"] " + Log.removeCodes(text) + "\n");
+ writer.write("[" + Character.toUpperCase(level.name().charAt(0)) +"] " + Log.removeColors(text) + "\n");
writer.flush();
}catch(IOException e){
e.printStackTrace();
//ignore it
}
- });
+ };
loadedFileLogger = true;
}
diff --git a/core/src/mindustry/ai/BaseAI.java b/core/src/mindustry/ai/BaseAI.java
index 3b45d8a17b..2c1fb11617 100644
--- a/core/src/mindustry/ai/BaseAI.java
+++ b/core/src/mindustry/ai/BaseAI.java
@@ -7,6 +7,7 @@ import arc.util.*;
import mindustry.*;
import mindustry.ai.BaseRegistry.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.game.*;
import mindustry.game.Schematic.*;
import mindustry.game.Teams.*;
@@ -23,7 +24,7 @@ public class BaseAI{
private static final Vec2 axis = new Vec2(), rotator = new Vec2();
private static final float correctPercent = 0.5f;
private static final float step = 5;
- private static final int attempts = 5;
+ private static final int attempts = 4;
private static final float emptyChance = 0.01f;
private static final int timerStep = 0, timerSpawn = 1;
@@ -40,11 +41,11 @@ public class BaseAI{
}
public void update(){
- if(timer.get(timerSpawn, 60) && data.hasCore()){
+ if(data.team.rules().aiCoreSpawn && timer.get(timerSpawn, 60 * 2.5f) && data.hasCore()){
CoreBlock block = (CoreBlock)data.core().block;
//create AI core unit
- if(!state.isEditor() && !Groups.unit.contains(u -> u.team() == data.team && u.type() == block.unitType)){
+ if(!state.isEditor() && !Groups.unit.contains(u -> u.team() == data.team && u.type == block.unitType)){
Unit unit = block.unitType.create(data.team);
unit.set(data.core());
unit.add();
@@ -68,9 +69,14 @@ public class BaseAI{
if(pos == null) return;
Tmp.v1.rnd(Mathf.random(range));
- int wx = (int)(world.toTile(pos.getX()) + Tmp.v1.x), wy = (int)(world.toTile(pos.getY()) + Tmp.v1.y);
+ int wx = (int)(World.toTile(pos.getX()) + Tmp.v1.x), wy = (int)(World.toTile(pos.getY()) + Tmp.v1.y);
Tile tile = world.tiles.getc(wx, wy);
+ //try not to block the spawn point
+ if(spawner.getSpawns().contains(t -> t.within(tile, tilesize * 40f))){
+ continue;
+ }
+
Seq parts = null;
//pick a completely random base part, and place it a random location
diff --git a/core/src/mindustry/ai/BlockIndexer.java b/core/src/mindustry/ai/BlockIndexer.java
index 63151e0d11..a75b0758ea 100644
--- a/core/src/mindustry/ai/BlockIndexer.java
+++ b/core/src/mindustry/ai/BlockIndexer.java
@@ -8,8 +8,10 @@ import arc.struct.EnumSet;
import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
+import mindustry.game.Teams.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.*;
@@ -178,8 +180,8 @@ public class BlockIndexer{
public boolean eachBlock(Team team, float wx, float wy, float range, Boolf pred, Cons cons){
intSet.clear();
- int tx = world.toTile(wx);
- int ty = world.toTile(wy);
+ int tx = World.toTile(wx);
+ int ty = World.toTile(wy);
int tileRange = (int)(range / tilesize + 1);
boolean any = false;
@@ -205,13 +207,14 @@ public class BlockIndexer{
/** Get all enemy blocks with a flag. */
public Seq getEnemy(Team team, BlockFlag type){
returnArray.clear();
- for(Team enemy : team.enemies()){
- if(state.teams.isActive(enemy)){
- TileArray set = getFlagged(enemy)[type.ordinal()];
- if(set != null){
- for(Tile tile : set){
- returnArray.add(tile);
- }
+ Seq data = state.teams.present;
+ for(int i = 0; i < data.size; i++){
+ Team enemy = data.items[i].team;
+ if(enemy == team) continue;
+ TileArray set = getFlagged(enemy)[type.ordinal()];
+ if(set != null){
+ for(Tile tile : set){
+ returnArray.add(tile);
}
}
}
diff --git a/core/src/mindustry/ai/Pathfinder.java b/core/src/mindustry/ai/Pathfinder.java
index c24cecd49c..78a596bb9d 100644
--- a/core/src/mindustry/ai/Pathfinder.java
+++ b/core/src/mindustry/ai/Pathfinder.java
@@ -7,6 +7,7 @@ import arc.struct.*;
import arc.util.*;
import arc.util.async.*;
import mindustry.annotations.Annotations.*;
+import mindustry.core.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.gen.*;
@@ -85,9 +86,6 @@ public class Pathfinder implements Runnable{
tiles[tile.x][tile.y] = packTile(tile);
}
- //special preset which may help speed things up; this is optional
- preloadPath(getField(state.rules.waveTeam, costGround, fieldCore));
-
start();
});
@@ -105,7 +103,7 @@ public class Pathfinder implements Runnable{
boolean nearLiquid = false, nearSolid = false, nearGround = false;
for(int i = 0; i < 4; i++){
- Tile other = tile.getNearby(i);
+ Tile other = tile.nearby(i);
if(other != null){
if(other.floor().isLiquid) nearLiquid = true;
if(other.solid()) nearSolid = true;
@@ -114,7 +112,7 @@ public class Pathfinder implements Runnable{
}
return PathTile.get(
- tile.build == null ? 0 : Math.min((int)(tile.build.health / 40), 80),
+ tile.build == null || !tile.solid() ? 0 : Math.min((int)(tile.build.health / 40), 80),
tile.getTeamID(),
tile.solid(),
tile.floor().isLiquid,
@@ -444,7 +442,7 @@ public class Pathfinder implements Runnable{
@Override
public void getPositions(IntSeq out){
- out.add(Point2.pack(world.toTile(position.getX()), world.toTile(position.getY())));
+ out.add(Point2.pack(World.toTile(position.getX()), World.toTile(position.getY())));
}
}
@@ -453,7 +451,7 @@ public class Pathfinder implements Runnable{
* Data for a flow field to some set of destinations.
* Concrete subclasses must specify a way to fetch costs and destinations.
* */
- static abstract class Flowfield{
+ public static abstract class Flowfield{
/** Refresh rate in milliseconds. Return any number <= 0 to disable. */
protected int refreshRate;
/** Team this path is for. Set before using. */
@@ -462,7 +460,7 @@ public class Pathfinder implements Runnable{
protected PathCost cost = costTypes.get(costGround);
/** costs of getting to a specific tile */
- int[][] weights;
+ public int[][] weights;
/** search IDs of each position - the highest, most recent search is prioritized and overwritten */
int[][] searches;
/** search frontier, these are Pos objects */
diff --git a/core/src/mindustry/ai/WaveSpawner.java b/core/src/mindustry/ai/WaveSpawner.java
index 9cecf32ac1..c420972457 100644
--- a/core/src/mindustry/ai/WaveSpawner.java
+++ b/core/src/mindustry/ai/WaveSpawner.java
@@ -8,6 +8,7 @@ import arc.struct.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.entities.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
@@ -23,11 +24,21 @@ public class WaveSpawner{
private Seq spawns = new Seq<>();
private boolean spawning = false;
private boolean any = false;
+ private Tile firstSpawn = null;
public WaveSpawner(){
Events.on(WorldLoadEvent.class, e -> reset());
}
+ @Nullable
+ public Tile getFirstSpawn(){
+ firstSpawn = null;
+ eachGroundSpawn((cx, cy) -> {
+ firstSpawn = world.tile(cx, cy);
+ });
+ return firstSpawn;
+ }
+
public int countSpawns(){
return spawns.size;
}
@@ -38,7 +49,7 @@ public class WaveSpawner{
/** @return true if the player is near a ground spawn point. */
public boolean playerNear(){
- return !player.dead() && spawns.contains(g -> Mathf.dst(g.x * tilesize, g.y * tilesize, player.x, player.y) < state.rules.dropZoneRadius && player.team() != state.rules.waveTeam);
+ return state.hasSpawns() && !player.dead() && spawns.contains(g -> Mathf.dst(g.x * tilesize, g.y * tilesize, player.x, player.y) < state.rules.dropZoneRadius && player.team() != state.rules.waveTeam);
}
public void spawnEnemies(){
@@ -47,7 +58,7 @@ public class WaveSpawner{
for(SpawnGroup group : state.rules.spawns){
if(group.type == null) continue;
- int spawned = group.getUnitsSpawned(state.wave - 1);
+ int spawned = group.getSpawned(state.wave - 1);
if(group.type.flying){
float spread = margin / 1.5f;
@@ -69,7 +80,7 @@ public class WaveSpawner{
Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1);
unit.set(spawnX + Tmp.v1.x, spawnY + Tmp.v1.y);
- Time.run(Math.min(i * 5, 60 * 2), () -> spawnEffect(unit));
+ spawnEffect(unit);
}
});
}
@@ -89,9 +100,15 @@ public class WaveSpawner{
Time.run(40f, () -> Damage.damage(state.rules.waveTeam, x, y, state.rules.dropZoneRadius, 99999999f, true));
}
+ public void eachGroundSpawn(Intc2 cons){
+ eachGroundSpawn((x, y, shock) -> cons.get(World.toTile(x), World.toTile(y)));
+ }
+
private void eachGroundSpawn(SpawnConsumer cons){
- for(Tile spawn : spawns){
- cons.accept(spawn.worldx(), spawn.worldy(), true);
+ if(state.hasSpawns()){
+ for(Tile spawn : spawns){
+ cons.accept(spawn.worldx(), spawn.worldy(), true);
+ }
}
if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam) && !state.teams.playerCores().isEmpty()){
@@ -104,7 +121,7 @@ public class WaveSpawner{
//keep moving forward until the max step amount is reached
while(steps++ < maxSteps){
- int tx = world.toTile(core.x + Tmp.v1.x), ty = world.toTile(core.y + Tmp.v1.y);
+ int tx = World.toTile(core.x + Tmp.v1.x), ty = World.toTile(core.y + Tmp.v1.y);
any = false;
Geometry.circle(tx, ty, world.width(), world.height(), 3, (x, y) -> {
if(world.solid(x, y)){
@@ -161,7 +178,7 @@ public class WaveSpawner{
}
private void spawnEffect(Unit unit){
- Call.spawnEffect(unit.x, unit.y, unit.type());
+ Call.spawnEffect(unit.x, unit.y, unit.type);
Time.run(30f, unit::add);
}
diff --git a/core/src/mindustry/ai/types/BuilderAI.java b/core/src/mindustry/ai/types/BuilderAI.java
index 8e8c74f986..c3558ca58a 100644
--- a/core/src/mindustry/ai/types/BuilderAI.java
+++ b/core/src/mindustry/ai/types/BuilderAI.java
@@ -79,7 +79,7 @@ public class BuilderAI extends AIController{
float dist = Math.min(cons.dst(unit) - buildingRange, 0);
//make sure you can reach the request in time
- if(dist / unit.type().speed < cons.buildCost * 0.9f){
+ if(dist / unit.type.speed < cons.buildCost * 0.9f){
following = b;
found = true;
}
@@ -112,7 +112,7 @@ public class BuilderAI extends AIController{
@Override
public AIController fallback(){
- return unit.type().flying ? new FlyingAI() : new GroundAI();
+ return unit.type.flying ? new FlyingAI() : new GroundAI();
}
@Override
diff --git a/core/src/mindustry/ai/types/FlyingAI.java b/core/src/mindustry/ai/types/FlyingAI.java
index 0758f9016a..7262ae216a 100644
--- a/core/src/mindustry/ai/types/FlyingAI.java
+++ b/core/src/mindustry/ai/types/FlyingAI.java
@@ -12,11 +12,11 @@ public class FlyingAI extends AIController{
@Override
public void updateMovement(){
if(target != null && unit.hasWeapons() && command() == UnitCommand.attack){
- if(unit.type().weapons.first().rotate){
+ if(unit.type.weapons.first().rotate){
moveTo(target, unit.range() * 0.8f);
unit.lookAt(target);
}else{
- attack(100f);
+ attack(120f);
}
}
@@ -34,17 +34,15 @@ public class FlyingAI extends AIController{
Teamc result = target(x, y, range, air, ground);
if(result != null) return result;
- if(ground) result = targetFlag(x, y, BlockFlag.producer, true);
+ if(ground) result = targetFlag(x, y, BlockFlag.generator, true);
if(result != null) return result;
- if(ground) result = targetFlag(x, y, BlockFlag.turret, true);
+ if(ground) result = targetFlag(x, y, BlockFlag.core, true);
if(result != null) return result;
return null;
}
- //TODO clean up
-
protected void attack(float circleLength){
vec.set(target).sub(unit);
@@ -57,7 +55,7 @@ public class FlyingAI extends AIController{
vec.setAngle(Mathf.slerpDelta(unit.vel().angle(), vec.angle(), 0.6f));
}
- vec.setLength(unit.type().speed);
+ vec.setLength(unit.type.speed);
unit.moveAt(vec);
}
diff --git a/core/src/mindustry/ai/types/FormationAI.java b/core/src/mindustry/ai/types/FormationAI.java
index cbe12a565e..3c5a2b99b4 100644
--- a/core/src/mindustry/ai/types/FormationAI.java
+++ b/core/src/mindustry/ai/types/FormationAI.java
@@ -7,6 +7,7 @@ import mindustry.ai.formations.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.type.*;
+import mindustry.world.blocks.storage.CoreBlock.*;
public class FormationAI extends AIController implements FormationMember{
public Unit leader;
@@ -26,15 +27,15 @@ public class FormationAI extends AIController implements FormationMember{
@Override
public void updateUnit(){
- UnitType type = unit.type();
+ UnitType type = unit.type;
if(leader.dead){
unit.resetController();
return;
}
- if(unit.type().canBoost && unit.canPassOn()){
- unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f);
+ if(unit.type.canBoost){
+ unit.elevation = Mathf.approachDelta(unit.elevation, !unit.canPassOn() ? 1f : leader.type.canBoost ? leader.elevation : 0f, 0.08f);
}
unit.controlWeapons(true, leader.isShooting);
@@ -42,7 +43,7 @@ public class FormationAI extends AIController implements FormationMember{
unit.aim(leader.aimX(), leader.aimY());
- if(unit.type().rotateShooting){
+ if(unit.type.rotateShooting){
unit.lookAt(leader.aimX(), leader.aimY());
}else if(unit.moving()){
unit.lookAt(unit.vel.angle());
@@ -52,10 +53,36 @@ public class FormationAI extends AIController implements FormationMember{
float margin = 3f;
+ float speed = unit.realSpeed();
+
if(unit.dst(realtarget) <= margin){
- unit.vel.approachDelta(Vec2.ZERO, type.speed * type.accel / 2f);
+ unit.vel.approachDelta(Vec2.ZERO, speed * type.accel / 2f);
}else{
- unit.moveAt(realtarget.sub(unit).limit(type.speed));
+ unit.moveAt(realtarget.sub(unit).limit(speed));
+ }
+
+ if(unit instanceof Minerc mine && leader instanceof Minerc com){
+ if(mine.validMine(com.mineTile())){
+ mine.mineTile(com.mineTile());
+
+ CoreBuild core = unit.team.core();
+
+ if(core != null && com.mineTile().drop() != null && unit.within(core, unit.type.range) && !unit.acceptsItem(com.mineTile().drop())){
+ if(core.acceptStack(unit.stack.item, unit.stack.amount, unit) > 0){
+ Call.transferItemTo(unit.stack.item, unit.stack.amount, unit.x, unit.y, core);
+
+ unit.clearItem();
+ }
+ }
+ }else{
+ mine.mineTile(null);
+ }
+
+ }
+
+ if(unit instanceof Builderc build && leader instanceof Builderc com && com.activelyBuilding()){
+ build.clearBuilding();
+ build.addBuild(com.buildPlan());
}
}
@@ -69,7 +96,7 @@ public class FormationAI extends AIController implements FormationMember{
@Override
public float formationSize(){
- return unit.hitSize * 1f;
+ return unit.hitSize * 1.1f;
}
@Override
diff --git a/core/src/mindustry/ai/types/GroundAI.java b/core/src/mindustry/ai/types/GroundAI.java
index 157ed2eb9d..2a711235c9 100644
--- a/core/src/mindustry/ai/types/GroundAI.java
+++ b/core/src/mindustry/ai/types/GroundAI.java
@@ -13,8 +13,6 @@ import java.util.*;
import static mindustry.Vars.*;
public class GroundAI extends AIController{
- //static final float commandCooldown = 60f * 10;
- //float commandTimer = 60*3;
@Override
public void updateMovement(){
@@ -45,31 +43,17 @@ public class GroundAI extends AIController{
}
}
- if(unit.type().canBoost && !unit.onSolid()){
+ if(unit.type.canBoost && !unit.onSolid()){
unit.elevation = Mathf.approachDelta(unit.elevation, 0f, 0.08f);
}
- if(!Units.invalidateTarget(target, unit, unit.range()) && unit.type().rotateShooting){
- if(unit.type().hasWeapons()){
- unit.lookAt(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed));
+ if(!Units.invalidateTarget(target, unit, unit.range()) && unit.type.rotateShooting){
+ if(unit.type.hasWeapons()){
+ unit.lookAt(Predict.intercept(unit, target, unit.type.weapons.first().bullet.speed));
}
}else if(unit.moving()){
unit.lookAt(unit.vel().angle());
}
- //auto-command works but it's very buggy
- /*
- if(unit instanceof Commanderc){
- Commanderc c = (Commanderc)unit;
- //try to command when missing members
- if(c.controlling().size <= unit.type().commandLimit/2){
- commandTimer -= Time.delta;
-
- if(commandTimer <= 0){
- c.commandNearby(new SquareFormation(), u -> !(u.controller() instanceof FormationAI) && !(u instanceof Commanderc));
- commandTimer = commandCooldown;
- }
- }
- }*/
}
}
diff --git a/core/src/mindustry/ai/types/LogicAI.java b/core/src/mindustry/ai/types/LogicAI.java
index a7b606b932..1166c2ff96 100644
--- a/core/src/mindustry/ai/types/LogicAI.java
+++ b/core/src/mindustry/ai/types/LogicAI.java
@@ -14,7 +14,7 @@ import static mindustry.Vars.*;
public class LogicAI extends AIController{
/** Minimum delay between item transfers. */
- public static final float transferDelay = 60f * 2f;
+ public static final float transferDelay = 60f * 3f;
/** Time after which the unit resets its controlled and reverts to a normal unit. */
public static final float logicControlTimeout = 10f * 60f;
@@ -98,7 +98,7 @@ public class LogicAI extends AIController{
}
}
- if(unit.type().canBoost && !unit.type().flying){
+ if(unit.type.canBoost && !unit.type.flying){
unit.elevation = Mathf.approachDelta(unit.elevation, Mathf.num(boost || unit.onSolid()), 0.08f);
}
@@ -129,7 +129,7 @@ public class LogicAI extends AIController{
@Override
protected boolean shouldShoot(){
- return shoot && !(unit.type().canBoost && boost);
+ return shoot && !(unit.type.canBoost && boost);
}
//always aim for the main target
diff --git a/core/src/mindustry/ai/types/MinerAI.java b/core/src/mindustry/ai/types/MinerAI.java
index a03481768f..aa7d1403c5 100644
--- a/core/src/mindustry/ai/types/MinerAI.java
+++ b/core/src/mindustry/ai/types/MinerAI.java
@@ -19,12 +19,14 @@ public class MinerAI extends AIController{
if(!(unit instanceof Minerc miner) || core == null) return;
- if(miner.mineTile() != null && !miner.mineTile().within(unit, unit.type().range)){
+ if(miner.mineTile() != null && !miner.mineTile().within(unit, unit.type.range)){
miner.mineTile(null);
}
if(mining){
- targetItem = unit.team.data().mineItems.min(i -> indexer.hasOre(i) && miner.canMine(i), i -> core.items.get(i));
+ if(timer.get(timerTarget2, 60 * 4) || targetItem == null){
+ targetItem = unit.team.data().mineItems.min(i -> indexer.hasOre(i) && miner.canMine(i), i -> core.items.get(i));
+ }
//core full of the target item, do nothing
if(targetItem != null && core.acceptStack(targetItem, 1, unit) == 0){
@@ -34,7 +36,7 @@ public class MinerAI extends AIController{
}
//if inventory is full, drop it off.
- if(unit.stack.amount >= unit.type().itemCapacity || (targetItem != null && !unit.acceptsItem(targetItem))){
+ if(unit.stack.amount >= unit.type.itemCapacity || (targetItem != null && !unit.acceptsItem(targetItem))){
mining = false;
}else{
if(retarget() && targetItem != null){
@@ -42,9 +44,9 @@ public class MinerAI extends AIController{
}
if(ore != null){
- moveTo(ore, unit.type().range / 2f);
+ moveTo(ore, unit.type.range / 2f);
- if(unit.within(ore, unit.type().range)){
+ if(unit.within(ore, unit.type.range)){
miner.mineTile(ore);
}
@@ -61,7 +63,7 @@ public class MinerAI extends AIController{
return;
}
- if(unit.within(core, unit.type().range)){
+ if(unit.within(core, unit.type.range)){
if(core.acceptStack(unit.stack.item, unit.stack.amount, unit) > 0){
Call.transferItemTo(unit.stack.item, unit.stack.amount, unit.x, unit.y, core);
}
@@ -70,7 +72,7 @@ public class MinerAI extends AIController{
mining = true;
}
- circle(core, unit.type().range / 1.8f);
+ circle(core, unit.type.range / 1.8f);
}
}
diff --git a/core/src/mindustry/ai/types/RepairAI.java b/core/src/mindustry/ai/types/RepairAI.java
index 5f021ae828..36504f908d 100644
--- a/core/src/mindustry/ai/types/RepairAI.java
+++ b/core/src/mindustry/ai/types/RepairAI.java
@@ -12,7 +12,7 @@ public class RepairAI extends AIController{
if(target instanceof Building){
boolean shoot = false;
- if(target.within(unit, unit.type().range)){
+ if(target.within(unit, unit.type.range)){
unit.aim(target);
shoot = true;
}
@@ -23,8 +23,8 @@ public class RepairAI extends AIController{
}
if(target != null){
- if(!target.within(unit, unit.type().range * 0.65f)){
- moveTo(target, unit.type().range * 0.65f);
+ if(!target.within(unit, unit.type.range * 0.65f) && target instanceof Building){
+ moveTo(target, unit.type.range * 0.65f);
}
unit.lookAt(target);
@@ -33,12 +33,14 @@ public class RepairAI extends AIController{
@Override
protected void updateTargeting(){
- target = Units.findDamagedTile(unit.team, unit.x, unit.y);
+ Building target = Units.findDamagedTile(unit.team, unit.x, unit.y);
if(target instanceof ConstructBuild) target = null;
if(target == null){
super.updateTargeting();
+ }else{
+ this.target = target;
}
}
diff --git a/core/src/mindustry/ai/types/SuicideAI.java b/core/src/mindustry/ai/types/SuicideAI.java
index 2eae6e409f..0ef3ece228 100644
--- a/core/src/mindustry/ai/types/SuicideAI.java
+++ b/core/src/mindustry/ai/types/SuicideAI.java
@@ -21,7 +21,7 @@ public class SuicideAI extends GroundAI{
}
if(retarget()){
- target = target(unit.x, unit.y, unit.range(), unit.type().targetAir, unit.type().targetGround);
+ target = target(unit.x, unit.y, unit.range(), unit.type.targetAir, unit.type.targetGround);
}
Building core = unit.closestEnemyCore();
@@ -30,11 +30,11 @@ public class SuicideAI extends GroundAI{
if(!Units.invalidateTarget(target, unit, unit.range()) && unit.hasWeapons()){
rotate = true;
- shoot = unit.within(target, unit.type().weapons.first().bullet.range() +
+ shoot = unit.within(target, unit.type.weapons.first().bullet.range() +
(target instanceof Building ? ((Building)target).block.size * Vars.tilesize / 2f : ((Hitboxc)target).hitSize() / 2f));
- if(unit.type().hasWeapons()){
- unit.aimLook(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed));
+ if(unit.type.hasWeapons()){
+ unit.aimLook(Predict.intercept(unit, target, unit.type.weapons.first().bullet.speed));
}
//do not move toward walls or transport blocks
@@ -65,7 +65,7 @@ public class SuicideAI extends GroundAI{
if(!blocked){
moveToTarget = true;
//move towards target directly
- unit.moveAt(vec.set(target).sub(unit).limit(unit.type().speed));
+ unit.moveAt(vec.set(target).sub(unit).limit(unit.type.speed));
}
}
diff --git a/core/src/mindustry/async/PhysicsProcess.java b/core/src/mindustry/async/PhysicsProcess.java
index 07d44d4717..a60dab7f68 100644
--- a/core/src/mindustry/async/PhysicsProcess.java
+++ b/core/src/mindustry/async/PhysicsProcess.java
@@ -57,7 +57,7 @@ public class PhysicsProcess implements AsyncProcess{
PhysicRef ref = entity.physref();
ref.body.layer =
- entity.type().allowLegStep ? layerLegs :
+ entity.type.allowLegStep ? layerLegs :
entity.isGrounded() ? layerGround : layerFlying;
ref.x = entity.x();
ref.y = entity.y();
diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java
index 05ed572f7e..1ab4e13252 100644
--- a/core/src/mindustry/content/Blocks.java
+++ b/core/src/mindustry/content/Blocks.java
@@ -14,6 +14,8 @@ import mindustry.world.blocks.*;
import mindustry.world.blocks.campaign.*;
import mindustry.world.blocks.defense.*;
import mindustry.world.blocks.defense.turrets.*;
+import mindustry.world.blocks.defense.turrets.PointDefenseTurret;
+import mindustry.world.blocks.defense.turrets.TractorBeamTurret;
import mindustry.world.blocks.distribution.*;
import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.experimental.*;
@@ -119,6 +121,7 @@ public class Blocks implements ContentList{
spawn = new OverlayFloor("spawn"){
{
variants = 0;
+ needsSurface = false;
}
@Override
public void drawBase(Tile tile){}
@@ -579,7 +582,7 @@ public class Blocks implements ContentList{
phaseWeaver = new GenericCrafter("phase-weaver"){{
requirements(Category.crafting, with(Items.silicon, 130, Items.lead, 120, Items.thorium, 75));
craftEffect = Fx.smeltsmoke;
- outputItem = new ItemStack(Items.phasefabric, 1);
+ outputItem = new ItemStack(Items.phaseFabric, 1);
craftTime = 120f;
size = 2;
hasPower = true;
@@ -593,7 +596,7 @@ public class Blocks implements ContentList{
surgeSmelter = new GenericSmelter("alloy-smelter"){{
requirements(Category.crafting, with(Items.silicon, 80, Items.lead, 80, Items.thorium, 70));
craftEffect = Fx.smeltsmoke;
- outputItem = new ItemStack(Items.surgealloy, 1);
+ outputItem = new ItemStack(Items.surgeAlloy, 1);
craftTime = 75f;
size = 3;
hasPower = true;
@@ -672,7 +675,7 @@ public class Blocks implements ContentList{
}};
disassembler = new Separator("disassembler"){{
- requirements(Category.crafting, with(Items.graphite, 140, Items.titanium, 100, Items.silicon, 150, Items.surgealloy, 70));
+ requirements(Category.crafting, with(Items.graphite, 140, Items.titanium, 100, Items.silicon, 150, Items.surgeAlloy, 70));
results = with(
Items.sand, 4,
Items.graphite, 2,
@@ -790,20 +793,22 @@ public class Blocks implements ContentList{
}};
phaseWall = new Wall("phase-wall"){{
- requirements(Category.defense, with(Items.phasefabric, 6));
+ requirements(Category.defense, with(Items.phaseFabric, 6));
health = 150 * wallHealthMultiplier;
- flashHit = deflect = true;
+ chanceDeflect = 10f;
+ flashHit = true;
}};
phaseWallLarge = new Wall("phase-wall-large"){{
requirements(Category.defense, ItemStack.mult(phaseWall.requirements, 4));
health = 150 * 4 * wallHealthMultiplier;
size = 2;
- flashHit = deflect = true;
+ chanceDeflect = 10f;
+ flashHit = true;
}};
surgeWall = new Wall("surge-wall"){{
- requirements(Category.defense, with(Items.surgealloy, 6));
+ requirements(Category.defense, with(Items.surgeAlloy, 6));
health = 230 * wallHealthMultiplier;
lightningChance = 0.05f;
}};
@@ -881,25 +886,25 @@ public class Blocks implements ContentList{
healPercent = 11f;
phaseBoost = 15f;
health = 80 * size * size;
- consumes.item(Items.phasefabric).boost();
+ consumes.item(Items.phaseFabric).boost();
}};
overdriveProjector = new OverdriveProjector("overdrive-projector"){{
requirements(Category.effect, with(Items.lead, 100, Items.titanium, 75, Items.silicon, 75, Items.plastanium, 30));
consumes.power(3.50f);
size = 2;
- consumes.item(Items.phasefabric).boost();
+ consumes.item(Items.phaseFabric).boost();
}};
overdriveDome = new OverdriveProjector("overdrive-dome"){{
- requirements(Category.effect, with(Items.lead, 200, Items.titanium, 130, Items.silicon, 130, Items.plastanium, 80, Items.surgealloy, 120));
+ requirements(Category.effect, with(Items.lead, 200, Items.titanium, 130, Items.silicon, 130, Items.plastanium, 80, Items.surgeAlloy, 120));
consumes.power(10f);
size = 3;
range = 200f;
speedBoost = 2.5f;
useTime = 300f;
hasBoost = false;
- consumes.items(with(Items.phasefabric, 1, Items.silicon, 1));
+ consumes.items(with(Items.phaseFabric, 1, Items.silicon, 1));
}};
forceProjector = new ForceProjector("force-projector"){{
@@ -912,15 +917,15 @@ public class Blocks implements ContentList{
cooldownLiquid = 1.2f;
cooldownBrokenBase = 0.35f;
- consumes.item(Items.phasefabric).boost();
+ consumes.item(Items.phaseFabric).boost();
consumes.power(4f);
}};
shockMine = new ShockMine("shock-mine"){{
requirements(Category.effect, with(Items.lead, 25, Items.silicon, 12));
hasShadow = false;
- health = 40;
- damage = 23;
+ health = 50;
+ damage = 25;
tileDamage = 7f;
length = 10;
tendrils = 4;
@@ -974,7 +979,7 @@ public class Blocks implements ContentList{
}};
phaseConveyor = new ItemBridge("phase-conveyor"){{
- requirements(Category.distribution, with(Items.phasefabric, 5, Items.silicon, 7, Items.lead, 10, Items.graphite, 10));
+ requirements(Category.distribution, with(Items.phaseFabric, 5, Items.silicon, 7, Items.lead, 10, Items.graphite, 10));
range = 12;
canOverdrive = false;
hasPower = true;
@@ -1100,7 +1105,7 @@ public class Blocks implements ContentList{
}};
phaseConduit = new LiquidBridge("phase-conduit"){{
- requirements(Category.liquid, with(Items.phasefabric, 5, Items.silicon, 7, Items.metaglass, 20, Items.titanium, 10));
+ requirements(Category.liquid, with(Items.phaseFabric, 5, Items.silicon, 7, Items.metaglass, 20, Items.titanium, 10));
range = 12;
hasPower = true;
canOverdrive = false;
@@ -1124,7 +1129,7 @@ public class Blocks implements ContentList{
}};
surgeTower = new PowerNode("surge-tower"){{
- requirements(Category.power, with(Items.titanium, 7, Items.lead, 10, Items.silicon, 15, Items.surgealloy, 15));
+ requirements(Category.power, with(Items.titanium, 7, Items.lead, 10, Items.silicon, 15, Items.surgeAlloy, 15));
size = 2;
maxNodes = 2;
laserRange = 40f;
@@ -1181,10 +1186,10 @@ public class Blocks implements ContentList{
}};
rtgGenerator = new DecayGenerator("rtg-generator"){{
- requirements(Category.power, with(Items.lead, 100, Items.silicon, 75, Items.phasefabric, 25, Items.plastanium, 75, Items.thorium, 50));
+ requirements(Category.power, with(Items.lead, 100, Items.silicon, 75, Items.phaseFabric, 25, Items.plastanium, 75, Items.thorium, 50));
size = 2;
powerProduction = 4.5f;
- itemDuration = 60 * 15f;
+ itemDuration = 60 * 18f;
}};
solarPanel = new SolarGenerator("solar-panel"){{
@@ -1193,7 +1198,7 @@ public class Blocks implements ContentList{
}};
largeSolarPanel = new SolarGenerator("solar-panel-large"){{
- requirements(Category.power, with(Items.lead, 100, Items.silicon, 145, Items.phasefabric, 15));
+ requirements(Category.power, with(Items.lead, 100, Items.silicon, 145, Items.phaseFabric, 15));
size = 3;
powerProduction = 0.95f;
}};
@@ -1210,7 +1215,7 @@ public class Blocks implements ContentList{
}};
impactReactor = new ImpactReactor("impact-reactor"){{
- requirements(Category.power, with(Items.lead, 500, Items.silicon, 300, Items.graphite, 400, Items.thorium, 100, Items.surgealloy, 250, Items.metaglass, 250));
+ requirements(Category.power, with(Items.lead, 500, Items.silicon, 300, Items.graphite, 400, Items.thorium, 100, Items.surgeAlloy, 250, Items.metaglass, 250));
size = 4;
health = 900;
powerProduction = 130f;
@@ -1353,19 +1358,21 @@ public class Blocks implements ContentList{
size = 5;
unitCapModifier = 20;
- researchCostMultiplier = 0.06f;
+ researchCostMultiplier = 0.05f;
}};
vault = new StorageBlock("vault"){{
requirements(Category.effect, with(Items.titanium, 250, Items.thorium, 125));
size = 3;
itemCapacity = 1000;
+ flags = EnumSet.of(BlockFlag.storage);
}};
container = new StorageBlock("container"){{
requirements(Category.effect, with(Items.titanium, 100));
size = 2;
itemCapacity = 300;
+ flags = EnumSet.of(BlockFlag.storage);
}};
unloader = new Unloader("unloader"){{
@@ -1549,7 +1556,7 @@ public class Blocks implements ContentList{
ammo(
Items.blastCompound, Bullets.missileExplosive,
Items.pyratite, Bullets.missileIncendiary,
- Items.surgealloy, Bullets.missileSurge
+ Items.surgeAlloy, Bullets.missileSurge
);
reloadTime = 30f;
shots = 4;
@@ -1588,7 +1595,7 @@ public class Blocks implements ContentList{
}};
segment = new PointDefenseTurret("segment"){{
- requirements(Category.turret, with(Items.silicon, 130, Items.thorium, 80, Items.phasefabric, 40));
+ requirements(Category.turret, with(Items.silicon, 130, Items.thorium, 80, Items.phaseFabric, 40));
health = 250 * size * size;
range = 160f;
@@ -1642,11 +1649,20 @@ public class Blocks implements ContentList{
float brange = range + 10f;
- ammo(Items.thorium, new ShrapnelBulletType(){{
+ ammo(
+ Items.thorium, new ShrapnelBulletType(){{
length = brange;
damage = 105f;
- ammoMultiplier = 6f;
- }});
+ ammoMultiplier = 5f;
+ }},
+ Items.titanium, new ShrapnelBulletType(){{
+ length = brange;
+ damage = 66f;
+ ammoMultiplier = 4f;
+ width = 17f;
+ reloadMultiplier = 1.3f;
+ }}
+ );
}};
ripple = new ItemTurret("ripple"){{
@@ -1685,7 +1701,7 @@ public class Blocks implements ContentList{
Items.metaglass, Bullets.fragGlass,
Items.blastCompound, Bullets.fragExplosive,
Items.plastanium, Bullets.fragPlastic,
- Items.surgealloy, Bullets.fragSurge
+ Items.surgeAlloy, Bullets.fragSurge
);
xRand = 4f;
reloadTime = 8f;
@@ -1703,9 +1719,9 @@ public class Blocks implements ContentList{
foreshadow = new ItemTurret("foreshadow"){{
float brange = range = 500f;
- requirements(Category.turret, with(Items.copper, 1000, Items.metaglass, 600, Items.surgealloy, 300, Items.plastanium, 200, Items.silicon, 600));
+ requirements(Category.turret, with(Items.copper, 1000, Items.metaglass, 600, Items.surgeAlloy, 300, Items.plastanium, 200, Items.silicon, 600));
ammo(
- Items.surgealloy, new PointBulletType(){{
+ Items.surgeAlloy, new PointBulletType(){{
shootEffect = Fx.instShoot;
hitEffect = Fx.instHit;
smokeEffect = Fx.smokeCloud;
@@ -1713,7 +1729,7 @@ public class Blocks implements ContentList{
despawnEffect = Fx.instBomb;
trailSpacing = 20f;
damage = 1350;
- tileDamageMultiplier = 0.5f;
+ tileDamageMultiplier = 0.3f;
speed = brange;
hitShake = 6f;
ammoMultiplier = 1f;
@@ -1743,7 +1759,7 @@ public class Blocks implements ContentList{
}};
spectre = new ItemTurret("spectre"){{
- requirements(Category.turret, with(Items.copper, 900, Items.graphite, 300, Items.surgealloy, 250, Items.plastanium, 175, Items.thorium, 250));
+ requirements(Category.turret, with(Items.copper, 900, Items.graphite, 300, Items.surgeAlloy, 250, Items.plastanium, 175, Items.thorium, 250));
ammo(
Items.graphite, Bullets.standardDenseBig,
Items.pyratite, Bullets.standardIncendiaryBig,
@@ -1769,7 +1785,7 @@ public class Blocks implements ContentList{
}};
meltdown = new LaserTurret("meltdown"){{
- requirements(Category.turret, with(Items.copper, 1200, Items.lead, 350, Items.graphite, 300, Items.surgealloy, 325, Items.silicon, 325));
+ requirements(Category.turret, with(Items.copper, 1200, Items.lead, 350, Items.graphite, 300, Items.surgeAlloy, 325, Items.silicon, 325));
shootEffect = Fx.shootBigSmoke2;
shootCone = 40f;
recoilAmount = 4f;
@@ -1877,7 +1893,7 @@ public class Blocks implements ContentList{
}};
exponentialReconstructor = new Reconstructor("exponential-reconstructor"){{
- requirements(Category.units, with(Items.lead, 2000, Items.silicon, 1000, Items.titanium, 2000, Items.thorium, 750, Items.plastanium, 450, Items.phasefabric, 600));
+ requirements(Category.units, with(Items.lead, 2000, Items.silicon, 1000, Items.titanium, 2000, Items.thorium, 750, Items.plastanium, 450, Items.phaseFabric, 600));
size = 7;
consumes.power(13f);
@@ -1898,11 +1914,11 @@ public class Blocks implements ContentList{
}};
tetrativeReconstructor = new Reconstructor("tetrative-reconstructor"){{
- requirements(Category.units, with(Items.lead, 4000, Items.silicon, 3000, Items.thorium, 1000, Items.plastanium, 600, Items.phasefabric, 600, Items.surgealloy, 800));
+ requirements(Category.units, with(Items.lead, 4000, Items.silicon, 3000, Items.thorium, 1000, Items.plastanium, 600, Items.phaseFabric, 600, Items.surgeAlloy, 800));
size = 9;
consumes.power(25f);
- consumes.items(with(Items.silicon, 1000, Items.plastanium, 600, Items.surgealloy, 500, Items.phasefabric, 350));
+ consumes.items(with(Items.silicon, 1000, Items.plastanium, 600, Items.surgeAlloy, 500, Items.phaseFabric, 350));
consumes.liquid(Liquids.cryofluid, 3f);
constructTime = 60f * 60f * 4;
@@ -1912,7 +1928,7 @@ public class Blocks implements ContentList{
new UnitType[]{UnitTypes.antumbra, UnitTypes.eclipse},
new UnitType[]{UnitTypes.arkyid, UnitTypes.toxopid},
new UnitType[]{UnitTypes.scepter, UnitTypes.reign},
- new UnitType[] {UnitTypes.sei, UnitTypes.omura},
+ new UnitType[]{UnitTypes.sei, UnitTypes.omura},
new UnitType[]{UnitTypes.quad, UnitTypes.oct},
new UnitType[]{UnitTypes.vela, UnitTypes.corvus}
);
@@ -2035,7 +2051,7 @@ public class Blocks implements ContentList{
}};
hyperProcessor = new LogicBlock("hyper-processor"){{
- requirements(Category.logic, with(Items.lead, 450, Items.silicon, 150, Items.thorium, 75, Items.surgealloy, 50));
+ requirements(Category.logic, with(Items.lead, 450, Items.silicon, 150, Items.thorium, 75, Items.surgeAlloy, 50));
consumes.liquid(Liquids.cryofluid, 0.08f);
hasLiquids = true;
@@ -2054,7 +2070,7 @@ public class Blocks implements ContentList{
}};
memoryBank = new MemoryBlock("memory-bank"){{
- requirements(Category.logic, with(Items.graphite, 80, Items.silicon, 80, Items.phasefabric, 30));
+ requirements(Category.logic, with(Items.graphite, 80, Items.silicon, 80, Items.phaseFabric, 30));
memoryCapacity = 512;
size = 2;
@@ -2069,7 +2085,7 @@ public class Blocks implements ContentList{
}};
largeLogicDisplay = new LogicDisplay("large-logic-display"){{
- requirements(Category.logic, with(Items.lead, 200, Items.silicon, 150, Items.metaglass, 100, Items.phasefabric, 75));
+ requirements(Category.logic, with(Items.lead, 200, Items.silicon, 150, Items.metaglass, 100, Items.phaseFabric, 75));
displaySize = 176;
diff --git a/core/src/mindustry/content/Bullets.java b/core/src/mindustry/content/Bullets.java
index 221dc44e8d..e2d42c0ef0 100644
--- a/core/src/mindustry/content/Bullets.java
+++ b/core/src/mindustry/content/Bullets.java
@@ -510,7 +510,7 @@ public class Bullets implements ContentList{
speed = 4f;
knockback = 1.3f;
puddleSize = 8f;
- damage = 6f;
+ damage = 5f;
drag = 0.001f;
ammoMultiplier = 2f;
statusDuration = 60f * 4f;
diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java
index 6ca6ccb24d..5d0c45348d 100644
--- a/core/src/mindustry/content/Fx.java
+++ b/core/src/mindustry/content/Fx.java
@@ -56,7 +56,7 @@ public class Fx{
mixcol(Pal.accent, 1f);
alpha(e.fout());
- rect(block ? ((BlockUnitc)select).tile().block.icon(Cicon.full) : select.type().icon(Cicon.full), select.x, select.y, block ? 0f : select.rotation - 90f);
+ rect(block ? ((BlockUnitc)select).tile().block.icon(Cicon.full) : select.type.icon(Cicon.full), select.x, select.y, block ? 0f : select.rotation - 90f);
alpha(1f);
Lines.stroke(e.fslope() * 1f);
Lines.square(select.x, select.y, e.fout() * select.hitSize * 2f, 45);
@@ -66,7 +66,7 @@ public class Fx{
}),
unitDespawn = new Effect(100f, e -> {
- if(!(e.data instanceof Unit) || e.data().type() == null) return;
+ if(!(e.data instanceof Unit) || e.data().type == null) return;
Unit select = e.data();
float scl = e.fout(Interp.pow2Out);
@@ -74,7 +74,7 @@ public class Fx{
Draw.scl *= scl;
mixcol(Pal.accent, 1f);
- rect(select.type().icon(Cicon.full), select.x, select.y, select.rotation - 90f);
+ rect(select.type.icon(Cicon.full), select.x, select.y, select.rotation - 90f);
reset();
Draw.scl = p;
@@ -1293,6 +1293,14 @@ public class Fx{
});
}),
+ coreBurn = new Effect(23, e -> {
+ randLenVectors(e.id, 5, e.fin() * 9f, (x, y) -> {
+ float len = e.fout() * 4f;
+ color(Pal.accent, Color.gray, e.fin());
+ Fill.circle(e.x + x, e.y + y, len/2f);
+ });
+ }),
+
plasticburn = new Effect(40, e -> {
randLenVectors(e.id, 5, 3f + e.fin() * 5f, (x, y) -> {
color(Color.valueOf("e9ead3"), Color.gray, e.fin());
diff --git a/core/src/mindustry/content/Items.java b/core/src/mindustry/content/Items.java
index e16784a61b..6d3964fd2c 100644
--- a/core/src/mindustry/content/Items.java
+++ b/core/src/mindustry/content/Items.java
@@ -5,7 +5,7 @@ import mindustry.ctype.*;
import mindustry.type.*;
public class Items implements ContentList{
- public static Item scrap, copper, lead, graphite, coal, titanium, thorium, silicon, plastanium, phasefabric, surgealloy,
+ public static Item scrap, copper, lead, graphite, coal, titanium, thorium, silicon, plastanium, phaseFabric, surgeAlloy,
sporePod, sand, blastCompound, pyratite, metaglass;
@Override
@@ -66,12 +66,12 @@ public class Items implements ContentList{
cost = 1.3f;
}};
- phasefabric = new Item("phase-fabric", Color.valueOf("f4ba6e")){{
+ phaseFabric = new Item("phase-fabric", Color.valueOf("f4ba6e")){{
cost = 1.3f;
radioactivity = 0.6f;
}};
- surgealloy = new Item("surge-alloy", Color.valueOf("f3e979")){{
+ surgeAlloy = new Item("surge-alloy", Color.valueOf("f3e979")){{
}};
sporePod = new Item("spore-pod", Color.valueOf("7457ce")){{
diff --git a/core/src/mindustry/content/Planets.java b/core/src/mindustry/content/Planets.java
index 873ba1c054..e07203313c 100644
--- a/core/src/mindustry/content/Planets.java
+++ b/core/src/mindustry/content/Planets.java
@@ -15,6 +15,7 @@ public class Planets implements ContentList{
public void load(){
sun = new Planet("sun", null, 0, 2){{
bloom = true;
+ accessible = false;
//lightColor = Color.valueOf("f4ee8e");
diff --git a/core/src/mindustry/content/SectorPresets.java b/core/src/mindustry/content/SectorPresets.java
index 3b76795c1d..e516bab740 100644
--- a/core/src/mindustry/content/SectorPresets.java
+++ b/core/src/mindustry/content/SectorPresets.java
@@ -18,47 +18,54 @@ public class SectorPresets implements ContentList{
groundZero = new SectorPreset("groundZero", serpulo, 15){{
alwaysUnlocked = true;
captureWave = 10;
+ difficulty = 1;
}};
saltFlats = new SectorPreset("saltFlats", serpulo, 101){{
-
+ difficulty = 5;
}};
frozenForest = new SectorPreset("frozenForest", serpulo, 86){{
- captureWave = 40;
+ captureWave = 20;
+ difficulty = 2;
}};
craters = new SectorPreset("craters", serpulo, 18){{
- captureWave = 40;
+ captureWave = 20;
+ difficulty = 2;
}};
ruinousShores = new SectorPreset("ruinousShores", serpulo, 19){{
- captureWave = 40;
+ captureWave = 30;
+ difficulty = 3;
}};
stainedMountains = new SectorPreset("stainedMountains", serpulo, 20){{
captureWave = 30;
+ difficulty = 3;
}};
fungalPass = new SectorPreset("fungalPass", serpulo, 21){{
-
+ difficulty = 4;
}};
overgrowth = new SectorPreset("overgrowth", serpulo, 22){{
-
+ difficulty = 5;
}};
tarFields = new SectorPreset("tarFields", serpulo, 23){{
- captureWave = 40;
+ captureWave = 50;
+ difficulty = 5;
}};
desolateRift = new SectorPreset("desolateRift", serpulo, 123){{
captureWave = 40;
+ difficulty = 8;
}};
-
nuclearComplex = new SectorPreset("nuclearComplex", serpulo, 130){{
captureWave = 60;
+ difficulty = 7;
}};
}
}
diff --git a/core/src/mindustry/content/TechTree.java b/core/src/mindustry/content/TechTree.java
index e9aa178388..6118ca7b74 100644
--- a/core/src/mindustry/content/TechTree.java
+++ b/core/src/mindustry/content/TechTree.java
@@ -161,7 +161,7 @@ public class TechTree implements ContentList{
node(Items.plastanium, with(Items.titanium, 10000, Items.silicon, 10000), () -> {
node(plastaniumCompressor, () -> {
- node(Items.phasefabric, with(Items.thorium, 15000, Items.sand, 30000, Items.silicon, 5000), () -> {
+ node(Items.phaseFabric, with(Items.thorium, 15000, Items.sand, 30000, Items.silicon, 5000), () -> {
node(phaseWeaver, () -> {
});
@@ -177,7 +177,7 @@ public class TechTree implements ContentList{
node(Items.scrap, with(Items.copper, 20000, Items.sand, 10000), () -> {
node(Liquids.slag, with(Items.scrap, 4000), () -> {
node(melter, () -> {
- node(Items.surgealloy, with(Items.thorium, 20000, Items.silicon, 30000, Items.lead, 40000), () -> {
+ node(Items.surgeAlloy, with(Items.thorium, 20000, Items.silicon, 30000, Items.lead, 40000), () -> {
node(surgeSmelter, () -> {
});
diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java
index 9a1b851118..03937d09eb 100644
--- a/core/src/mindustry/content/UnitTypes.java
+++ b/core/src/mindustry/content/UnitTypes.java
@@ -10,6 +10,7 @@ import mindustry.entities.bullet.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
+import mindustry.world.meta.*;
import static mindustry.Vars.*;
@@ -275,7 +276,7 @@ public class UnitTypes implements ContentList{
armor = 1f;
commandLimit = 8;
- abilities.add(new HealFieldAbility(10f, 60f * 4, 60f));
+ abilities.add(new RepairFieldAbility(10f, 60f * 4, 60f));
ammoType = AmmoTypes.power;
weapons.add(new Weapon("heal-weapon"){{
@@ -304,7 +305,7 @@ public class UnitTypes implements ContentList{
mineSpeed = 5f;
commandLimit = 8;
- abilities.add(new ShieldFieldAbility(20f, 40f, 60f * 5, 60f));
+ abilities.add(new ShieldRegenFieldAbility(20f, 40f, 60f * 5, 60f));
ammoType = AmmoTypes.power;
weapons.add(new Weapon("heal-shotgun-weapon"){{
@@ -872,7 +873,6 @@ public class UnitTypes implements ContentList{
drag = 0.01f;
flying = true;
health = 75;
- faceTarget = false;
engineOffset = 5.5f;
range = 140f;
@@ -898,6 +898,7 @@ public class UnitTypes implements ContentList{
range = 140f;
faceTarget = false;
armor = 4f;
+ targetFlag = BlockFlag.factory;
weapons.add(new Weapon(){{
minShootVelocity = 0.75f;
@@ -978,6 +979,7 @@ public class UnitTypes implements ContentList{
engineOffset = 21;
engineSize = 5.3f;
hitSize = 56f;
+ targetFlag = BlockFlag.battery;
BulletType missiles = new MissileBulletType(2.7f, 10){{
width = 8f;
@@ -1052,6 +1054,7 @@ public class UnitTypes implements ContentList{
hitSize = 58f;
destructibleWreck = false;
armor = 13f;
+ targetFlag = BlockFlag.reactor;
BulletType fragBullet = new FlakBulletType(4f, 5){{
shootEffect = Fx.shootBig;
@@ -1142,7 +1145,7 @@ public class UnitTypes implements ContentList{
flying = true;
drag = 0.05f;
- speed = 1.9f;
+ speed = 2.6f;
rotateSpeed = 15f;
accel = 0.1f;
range = 130f;
@@ -1158,7 +1161,7 @@ public class UnitTypes implements ContentList{
mineTier = 2;
mineSpeed = 3.5f;
- abilities.add(new HealFieldAbility(5f, 60f * 5, 50f));
+ abilities.add(new RepairFieldAbility(5f, 60f * 5, 50f));
weapons.add(new Weapon("heal-weapon-mount"){{
top = false;
@@ -1197,9 +1200,8 @@ public class UnitTypes implements ContentList{
mineTier = 3;
health = 500;
- armor = 2f;
armor = 5f;
- speed = 1.8f;
+ speed = 2.3f;
accel = 0.06f;
drag = 0.017f;
lowAltitude = true;
@@ -1233,7 +1235,7 @@ public class UnitTypes implements ContentList{
quad = new UnitType("quad"){{
armor = 8f;
health = 6000;
- speed = 1.2f;
+ speed = 1.4f;
rotateSpeed = 2f;
accel = 0.05f;
drag = 0.017f;
@@ -1247,6 +1249,7 @@ public class UnitTypes implements ContentList{
buildSpeed = 2.5f;
range = 140f;
targetAir = false;
+ targetFlag = BlockFlag.battery;
ammoType = AmmoTypes.powerHigh;
@@ -1297,7 +1300,7 @@ public class UnitTypes implements ContentList{
oct = new UnitType("oct"){{
armor = 16f;
health = 24000;
- speed = 0.6f;
+ speed = 0.8f;
rotateSpeed = 1f;
accel = 0.04f;
drag = 0.018f;
@@ -1315,7 +1318,7 @@ public class UnitTypes implements ContentList{
ammoCapacity = 1300;
ammoResupplyAmount = 20;
- abilities.add(new ForceFieldAbility(140f, 4f, 7000f, 60f * 8), new HealFieldAbility(130f, 60f * 2, 140f));
+ abilities.add(new ForceFieldAbility(140f, 4f, 7000f, 60f * 8), new RepairFieldAbility(130f, 60f * 2, 140f));
}};
//endregion
@@ -1427,7 +1430,7 @@ public class UnitTypes implements ContentList{
trailY = -9f;
trailScl = 1.5f;
- abilities.add(new ShieldFieldAbility(20f, 40f, 60f * 4, 60f));
+ abilities.add(new ShieldRegenFieldAbility(20f, 40f, 60f * 4, 60f));
weapons.add(new Weapon("large-artillery"){{
reload = 65f;
@@ -1449,13 +1452,13 @@ public class UnitTypes implements ContentList{
trailMult = 0.8f;
hitEffect = Fx.massiveExplosion;
knockback = 1.5f;
- lifetime = 140f;
+ lifetime = 100f;
height = 15.5f;
width = 15f;
collidesTiles = false;
ammoMultiplier = 4f;
splashDamageRadius = 60f;
- splashDamage = 85f;
+ splashDamage = 80f;
backColor = Pal.missileYellowBack;
frontColor = Pal.missileYellow;
trailEffect = Fx.artilleryTrail;
@@ -1651,11 +1654,11 @@ public class UnitTypes implements ContentList{
mineTier = 1;
buildSpeed = 0.5f;
drag = 0.05f;
- speed = 2.8f;
+ speed = 3f;
rotateSpeed = 15f;
accel = 0.1f;
itemCapacity = 30;
- health = 120f;
+ health = 150f;
engineOffset = 6f;
hitSize = 8f;
commandLimit = 3;
@@ -1666,13 +1669,13 @@ public class UnitTypes implements ContentList{
y = 1f;
top = false;
- bullet = new BasicBulletType(2.5f, 9){{
+ bullet = new BasicBulletType(2.5f, 10){{
width = 7f;
height = 9f;
lifetime = 60f;
shootEffect = Fx.shootSmall;
smokeEffect = Fx.shootSmallSmoke;
- tileDamageMultiplier = 0.09f;
+ tileDamageMultiplier = 0.03f;
}};
}});
}};
@@ -1686,11 +1689,11 @@ public class UnitTypes implements ContentList{
mineTier = 1;
buildSpeed = 0.75f;
drag = 0.05f;
- speed = 3f;
+ speed = 3.3f;
rotateSpeed = 17f;
accel = 0.1f;
itemCapacity = 50;
- health = 150f;
+ health = 170f;
engineOffset = 6f;
hitSize = 9f;
rotateShooting = false;
@@ -1707,13 +1710,13 @@ public class UnitTypes implements ContentList{
shotDelay = 4f;
spacing = 0f;
- bullet = new BasicBulletType(3f, 9){{
+ bullet = new BasicBulletType(3f, 10){{
width = 7f;
height = 9f;
lifetime = 60f;
shootEffect = Fx.shootSmall;
smokeEffect = Fx.shootSmallSmoke;
- tileDamageMultiplier = 0.1f;
+ tileDamageMultiplier = 0.03f;
}};
}});
}};
@@ -1727,11 +1730,11 @@ public class UnitTypes implements ContentList{
mineTier = 2;
buildSpeed = 1f;
drag = 0.05f;
- speed = 3.5f;
+ speed = 3.55f;
rotateSpeed = 19f;
accel = 0.11f;
itemCapacity = 70;
- health = 190f;
+ health = 220f;
engineOffset = 6f;
hitSize = 10f;
commandLimit = 7;
@@ -1746,13 +1749,13 @@ public class UnitTypes implements ContentList{
inaccuracy = 3f;
shotDelay = 3f;
- bullet = new BasicBulletType(3.5f, 9){{
+ bullet = new BasicBulletType(3.5f, 10){{
width = 6.5f;
height = 11f;
lifetime = 70f;
shootEffect = Fx.shootSmall;
smokeEffect = Fx.shootSmallSmoke;
- tileDamageMultiplier = 0.1f;
+ tileDamageMultiplier = 0.03f;
homingPower = 0.04f;
}};
}});
diff --git a/core/src/mindustry/content/Weathers.java b/core/src/mindustry/content/Weathers.java
index 273fdb5899..b120b7ef2b 100644
--- a/core/src/mindustry/content/Weathers.java
+++ b/core/src/mindustry/content/Weathers.java
@@ -1,339 +1,89 @@
package mindustry.content;
-import arc.*;
import arc.graphics.*;
-import arc.graphics.Texture.*;
-import arc.graphics.g2d.*;
-import arc.math.*;
import arc.util.*;
import mindustry.ctype.*;
-import mindustry.gen.*;
import mindustry.type.*;
-import mindustry.world.*;
+import mindustry.type.weather.*;
import mindustry.world.meta.*;
-import static mindustry.Vars.*;
-
public class Weathers implements ContentList{
public static Weather
rain,
snow,
sandstorm,
- sporestorm;
+ sporestorm,
+ fog;
@Override
public void load(){
- snow = new Weather("snow"){
- TextureRegion region;
- float yspeed = 2f, xspeed = 0.25f, padding = 16f, size = 12f, density = 1200f;
+ snow = new ParticleWeather("snow"){{
+ sizeMax = 13f;
+ sizeMin = 2.6f;
+ density = 1200f;
+ attrs.set(Attribute.light, -0.15f);
+ }};
- {
- attrs.set(Attribute.light, -0.15f);
- }
+ rain = new RainWeather("rain"){{
+ attrs.set(Attribute.light, -0.2f);
+ attrs.set(Attribute.water, 0.2f);
+ status = StatusEffects.wet;
+ }};
- @Override
- public void load(){
- super.load();
+ sandstorm = new ParticleWeather("sandstorm"){{
+ color = noiseColor = Color.valueOf("f7cba4");
+ drawNoise = true;
+ useWindVector = true;
+ sizeMax = 140f;
+ sizeMin = 70f;
+ minAlpha = 0f;
+ maxAlpha = 0.2f;
+ density = 1500f;
+ baseSpeed = 6.1f;
+ attrs.set(Attribute.light, -0.1f);
+ attrs.set(Attribute.water, -0.1f);
+ opacityMultiplier = 0.8f;
+ force = 0.1f;
+ }};
- region = Core.atlas.find("circle-shadow");
- }
+ sporestorm = new ParticleWeather("sporestorm"){{
+ color = noiseColor = Color.valueOf("7457ce");
+ particleRegion = "circle";
+ drawNoise = true;
+ statusGround = false;
+ useWindVector = true;
+ sizeMax = 5f;
+ sizeMin = 2.5f;
+ minAlpha = 0.1f;
+ maxAlpha = 0.8f;
+ density = 2000f;
+ baseSpeed = 4.3f;
+ attrs.set(Attribute.spores, 1f);
+ attrs.set(Attribute.light, -0.15f);
+ status = StatusEffects.sporeSlowed;
+ opacityMultiplier = 0.85f;
+ force = 0.1f;
+ }};
- @Override
- public void drawOver(WeatherState state){
- rand.setSeed(0);
- Tmp.r1.setCentered(Core.camera.position.x, Core.camera.position.y, Core.graphics.getWidth() / renderer.minScale(), Core.graphics.getHeight() / renderer.minScale());
- Tmp.r1.grow(padding);
- Core.camera.bounds(Tmp.r2);
- int total = (int)(Tmp.r1.area() / density * state.intensity());
-
- for(int i = 0; i < total; i++){
- float scl = rand.random(0.5f, 1f);
- float scl2 = rand.random(0.5f, 1f);
- float sscl = rand.random(0.2f, 1f);
- float x = (rand.random(0f, world.unitWidth()) + Time.time() * xspeed * scl2);
- float y = (rand.random(0f, world.unitHeight()) - Time.time() * yspeed * scl);
-
- x += Mathf.sin(y, rand.random(30f, 80f), rand.random(1f, 7f));
-
- x -= Tmp.r1.x;
- y -= Tmp.r1.y;
- x = Mathf.mod(x, Tmp.r1.width);
- y = Mathf.mod(y, Tmp.r1.height);
- x += Tmp.r1.x;
- y += Tmp.r1.y;
-
- if(Tmp.r3.setCentered(x, y, size * sscl).overlaps(Tmp.r2)){
- Draw.rect(region, x, y, size * sscl, size * sscl);
- }
- }
- }
- };
-
- rain = new Weather("rain"){
- float yspeed = 5f, xspeed = 1.5f, padding = 16f, size = 40f, density = 1200f;
- TextureRegion[] splashes = new TextureRegion[12];
-
- {
- attrs.set(Attribute.light, -0.2f);
- attrs.set(Attribute.water, 0.2f);
- status = StatusEffects.wet;
- }
-
- @Override
- public void load(){
- super.load();
-
- for(int i = 0; i < splashes.length; i++){
- splashes[i] = Core.atlas.find("splash-" + i);
- }
- }
-
- @Override
- public void drawOver(WeatherState state){
- Tmp.r1.setCentered(Core.camera.position.x, Core.camera.position.y, Core.graphics.getWidth() / renderer.minScale(), Core.graphics.getHeight() / renderer.minScale());
- Tmp.r1.grow(padding);
- Core.camera.bounds(Tmp.r2);
- int total = (int)(Tmp.r1.area() / density * state.intensity());
- Lines.stroke(0.75f);
- float alpha = Draw.getColor().a;
- Draw.color(Color.royal, Color.white, 0.3f);
-
- for(int i = 0; i < total; i++){
- float scl = rand.random(0.5f, 1f);
- float scl2 = rand.random(0.5f, 1f);
- float sscl = rand.random(0.2f, 1f);
- float x = (rand.random(0f, world.unitWidth()) + Time.time() * xspeed * scl2);
- float y = (rand.random(0f, world.unitHeight()) - Time.time() * yspeed * scl);
- float tint = rand.random(1f) * alpha;
-
- x -= Tmp.r1.x;
- y -= Tmp.r1.y;
- x = Mathf.mod(x, Tmp.r1.width);
- y = Mathf.mod(y, Tmp.r1.height);
- x += Tmp.r1.x;
- y += Tmp.r1.y;
-
- if(Tmp.r3.setCentered(x, y, size * sscl).overlaps(Tmp.r2)){
- Draw.alpha(tint);
- Lines.lineAngle(x, y, Angles.angle(xspeed * scl2, - yspeed * scl), size*sscl/2f);
- }
- }
- }
-
- @Override
- public void drawUnder(WeatherState state){
- Tmp.r1.setCentered(Core.camera.position.x, Core.camera.position.y, Core.graphics.getWidth() / renderer.minScale(), Core.graphics.getHeight() / renderer.minScale());
- Tmp.r1.grow(padding);
- Core.camera.bounds(Tmp.r2);
- int total = (int)(Tmp.r1.area() / density * state.intensity()) / 2;
- Lines.stroke(0.75f);
-
- float t = Time.time() / 22f;
-
- for(int i = 0; i < total; i++){
- float offset = rand.random(0f, 1f);
- float time = t + offset;
-
- int pos = (int)((time));
- float life = time % 1f;
- float x = (rand.random(0f, world.unitWidth()) + pos*953);
- float y = (rand.random(0f, world.unitHeight()) - pos*453);
-
- x -= Tmp.r1.x;
- y -= Tmp.r1.y;
- x = Mathf.mod(x, Tmp.r1.width);
- y = Mathf.mod(y, Tmp.r1.height);
- x += Tmp.r1.x;
- y += Tmp.r1.y;
-
- if(Tmp.r3.setCentered(x, y, life * 4f).overlaps(Tmp.r2)){
- Tile tile = world.tileWorld(x, y);
-
- if(tile != null && tile.floor().liquidDrop == Liquids.water){
- Draw.color(Tmp.c1.set(tile.floor().mapColor).mul(1.5f).a(state.opacity()));
- Draw.rect(splashes[(int)(life * (splashes.length - 1))], x, y);
- }else if(tile != null && tile.floor().liquidDrop == null && !tile.floor().solid){
- Draw.color(Color.royal, Color.white, 0.3f);
- Draw.alpha(Mathf.slope(life) * state.opacity());
-
- float space = 45f;
- for(int j : new int[]{-1, 1}){
- Tmp.v1.trns(90f + j*space, 1f + 5f * life);
- Lines.lineAngle(x + Tmp.v1.x, y + Tmp.v1.y, 90f + j*space, 3f * (1f - life));
- }
- }
- }
- }
- }
- };
-
- sandstorm = new Weather("sandstorm"){
- TextureRegion region;
- float size = 140f, padding = size, invDensity = 1500f, baseSpeed = 6.1f;
- float force = 0.4f * 0;
- Color color = Color.valueOf("f7cba4");
- Texture noise;
-
- {
- attrs.set(Attribute.light, -0.1f);
- opacityMultiplier = 0.8f;
- }
-
- @Override
- public void load(){
- region = Core.atlas.find("circle-shadow");
- noise = new Texture("sprites/noiseAlpha.png");
- noise.setWrap(TextureWrap.repeat);
- noise.setFilter(TextureFilter.linear);
- }
-
- @Override
- public void dispose(){
- noise.dispose();
- }
-
- @Override
- public void update(WeatherState state){
- float speed = force * state.intensity;
- float windx = state.windVector.x * speed, windy = state.windVector.y * speed;
-
- for(Unit unit : Groups.unit){
- unit.impulse(windx, windy);
- }
- }
-
- @Override
- public void drawOver(WeatherState state){
- Draw.tint(color);
- float speed = baseSpeed * state.intensity;
- float windx = state.windVector.x * speed, windy = state.windVector.y * speed;
-
- float scale = 1f / 2000f;
- float scroll = Time.time() * scale;
- Tmp.tr1.texture = noise;
- Core.camera.bounds(Tmp.r1);
- Tmp.tr1.set(Tmp.r1.x*scale, Tmp.r1.y*scale, (Tmp.r1.x + Tmp.r1.width)*scale, (Tmp.r1.y + Tmp.r1.height)*scale);
- Tmp.tr1.scroll(-windx * scroll, windy * scroll);
- Draw.rect(Tmp.tr1, Core.camera.position.x, Core.camera.position.y, Core.camera.width, -Core.camera.height);
-
- rand.setSeed(0);
- Tmp.r1.setCentered(Core.camera.position.x, Core.camera.position.y, Core.graphics.getWidth() / renderer.minScale(), Core.graphics.getHeight() / renderer.minScale());
- Tmp.r1.grow(padding);
- Core.camera.bounds(Tmp.r2);
- int total = (int)(Tmp.r1.area() / invDensity * state.intensity());
- Draw.tint(color);
- float baseAlpha = Draw.getColor().a;
-
- for(int i = 0; i < total; i++){
- float scl = rand.random(0.5f, 1f);
- float scl2 = rand.random(0.5f, 1f);
- float sscl = rand.random(0.5f, 1f);
- float x = (rand.random(0f, world.unitWidth()) + Time.time() * windx * scl2);
- float y = (rand.random(0f, world.unitHeight()) + Time.time() * windy * scl);
- float alpha = rand.random(0.2f);
-
- x += Mathf.sin(y, rand.random(30f, 80f), rand.random(1f, 7f));
-
- x -= Tmp.r1.x;
- y -= Tmp.r1.y;
- x = Mathf.mod(x, Tmp.r1.width);
- y = Mathf.mod(y, Tmp.r1.height);
- x += Tmp.r1.x;
- y += Tmp.r1.y;
-
- if(Tmp.r3.setCentered(x, y, size * sscl).overlaps(Tmp.r2)){
- Draw.alpha(alpha * baseAlpha);
- Draw.rect(region, x, y, size * sscl, size * sscl);
- }
- }
- }
- };
-
- sporestorm = new Weather("sporestorm"){
- TextureRegion region;
- float size = 5f, padding = size, invDensity = 2000f, baseSpeed = 4.3f, force = 0.28f * 0;
- Color color = Color.valueOf("7457ce");
- Texture noise;
-
- {
- attrs.set(Attribute.spores, 1f);
- attrs.set(Attribute.light, -0.15f);
- status = StatusEffects.sporeSlowed;
- statusGround = false;
- opacityMultiplier = 0.85f;
- }
-
- @Override
- public void load(){
- region = Core.atlas.find("circle-shadow");
- noise = new Texture("sprites/noiseAlpha.png");
- noise.setWrap(TextureWrap.repeat);
- noise.setFilter(TextureFilter.linear);
- }
-
- @Override
- public void update(WeatherState state){
- float speed = force * state.intensity;
- float windx = state.windVector.x * speed, windy = state.windVector.y * speed;
-
- for(Unit unit : Groups.unit){
- unit.impulse(windx, windy);
- }
- }
-
- @Override
- public void dispose(){
- noise.dispose();
- }
-
- @Override
- public void drawOver(WeatherState state){
- Draw.alpha(state.opacity * 0.8f);
- Draw.tint(color);
-
- float speed = baseSpeed * state.intensity;
- float windx = state.windVector.x * speed, windy = state.windVector.y * speed;
-
- float scale = 1f / 2000f;
- float scroll = Time.time() * scale;
- Tmp.tr1.texture = noise;
- Core.camera.bounds(Tmp.r1);
- Tmp.tr1.set(Tmp.r1.x*scale, Tmp.r1.y*scale, (Tmp.r1.x + Tmp.r1.width)*scale, (Tmp.r1.y + Tmp.r1.height)*scale);
- Tmp.tr1.scroll(-windx * scroll, windy * scroll);
- Draw.rect(Tmp.tr1, Core.camera.position.x, Core.camera.position.y, Core.camera.width, -Core.camera.height);
-
- rand.setSeed(0);
- Tmp.r1.setCentered(Core.camera.position.x, Core.camera.position.y, Core.graphics.getWidth() / renderer.minScale(), Core.graphics.getHeight() / renderer.minScale());
- Tmp.r1.grow(padding);
- Core.camera.bounds(Tmp.r2);
- int total = (int)(Tmp.r1.area() / invDensity * state.intensity());
- Draw.tint(color);
- float baseAlpha = state.opacity;
- Draw.alpha(baseAlpha);
-
- for(int i = 0; i < total; i++){
- float scl = rand.random(0.5f, 1f);
- float scl2 = rand.random(0.5f, 1f);
- float sscl = rand.random(0.5f, 1f);
- float x = (rand.random(0f, world.unitWidth()) + Time.time() * windx * scl2);
- float y = (rand.random(0f, world.unitHeight()) + Time.time() * windy * scl);
- float alpha = rand.random(0.1f, 0.8f);
-
- x += Mathf.sin(y, rand.random(30f, 80f), rand.random(1f, 7f));
-
- x -= Tmp.r1.x;
- y -= Tmp.r1.y;
- x = Mathf.mod(x, Tmp.r1.width);
- y = Mathf.mod(y, Tmp.r1.height);
- x += Tmp.r1.x;
- y += Tmp.r1.y;
-
- if(Tmp.r3.setCentered(x, y, size * sscl).overlaps(Tmp.r2)){
- Draw.alpha(alpha * baseAlpha);
- Fill.circle(x, y, size * sscl / 2f);
- }
- }
- }
- };
+ fog = new ParticleWeather("fog"){{
+ duration = 15f * Time.toMinutes;
+ noiseLayers = 3;
+ noiseLayerSclM = 0.8f;
+ noiseLayerAlphaM = 0.7f;
+ noiseLayerSpeedM = 2f;
+ noiseLayerSclM = 0.6f;
+ baseSpeed = 0.05f;
+ color = noiseColor = Color.grays(0.4f);
+ noiseScale = 1100f;
+ noisePath = "fog";
+ drawParticles = false;
+ drawNoise = true;
+ useWindVector = false;
+ xspeed = 1f;
+ yspeed = 0.01f;
+ attrs.set(Attribute.light, -0.3f);
+ attrs.set(Attribute.water, 0.05f);
+ opacityMultiplier = 0.47f;
+ }};
}
}
diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java
index efe2327074..3d904c1826 100644
--- a/core/src/mindustry/core/Control.java
+++ b/core/src/mindustry/core/Control.java
@@ -9,7 +9,6 @@ import arc.math.*;
import arc.scene.ui.*;
import arc.struct.*;
import arc.util.*;
-import mindustry.*;
import mindustry.audio.*;
import mindustry.content.*;
import mindustry.core.GameState.*;
@@ -25,7 +24,6 @@ import mindustry.maps.Map;
import mindustry.type.*;
import mindustry.ui.dialogs.*;
import mindustry.world.*;
-import mindustry.world.blocks.storage.CoreBlock.*;
import java.io.*;
import java.text.*;
@@ -37,7 +35,7 @@ import static mindustry.Vars.*;
/**
* Control module.
- * Handles all input, saving, keybinds and keybinds.
+ * Handles all input, saving and keybinds.
* Should not handle any logic-critical state.
* This class is not created in the headless server.
*/
@@ -160,9 +158,7 @@ public class Control implements ApplicationListener, Loadable{
//delete the save, it is gone.
if(saves.getCurrent() != null && !state.rules.tutorial){
- Sector sector = state.getSector();
- sector.save = null;
- saves.getCurrent().delete();
+ saves.getCurrent().save();
}
}
});
@@ -252,19 +248,6 @@ public class Control implements ApplicationListener, Loadable{
});
}
- //TODO move
- public void handleLaunch(CoreBuild tile){
- LaunchCorec ent = LaunchCore.create();
- ent.set(tile);
- ent.block(Blocks.coreShard);
- ent.lifetime(Vars.launchDuration);
- ent.add();
-
- //remove schematic requirements from core
- tile.items.remove(universe.getLastLoadout().requirements());
- tile.items.remove(universe.getLaunchResources());
- }
-
public void playSector(Sector sector){
playSector(sector, sector);
}
@@ -281,21 +264,29 @@ public class Control implements ApplicationListener, Loadable{
slot.load();
slot.setAutosave(true);
state.rules.sector = sector;
+ state.secinfo = state.rules.sector.info;
//if there is no base, simulate a new game and place the right loadout at the spawn position
- //TODO this is broken?
if(state.rules.defaultTeam.cores().isEmpty()){
- //kill all friendly units, since they should be dead anwyay
- for(Unit unit : Groups.unit){
- if(unit.team() == state.rules.defaultTeam){
- unit.remove();
- }
+ //no spawn set -> delete the sector save
+ if(sector.info.spawnPosition == 0){
+ //delete old save
+ sector.save = null;
+ slot.delete();
+ //play again
+ playSector(origin, sector);
+ return;
}
- Tile spawn = world.tile(sector.getSpawnPosition());
- //TODO PLACE CORRECT LOADOUT
- Schematics.placeLoadout(universe.getLastLoadout(), spawn.x, spawn.y);
+ //reset wave so things are more fair
+ state.wave = 1;
+
+ //kill all units, since they should be dead anwyay
+ Groups.unit.clear();
+
+ Tile spawn = world.tile(sector.info.spawnPosition);
+ Schematics.placeLaunchLoadout(spawn.x, spawn.y);
//set up camera/player locations
player.set(spawn.x * tilesize, spawn.y * tilesize);
@@ -317,7 +308,6 @@ public class Control implements ApplicationListener, Loadable{
}else{
net.reset();
logic.reset();
- sector.setSecondsPassed(0);
world.loadSector(sector);
state.rules.sector = sector;
//assign origin when launching
diff --git a/core/src/mindustry/core/GameState.java b/core/src/mindustry/core/GameState.java
index 949e40d02d..41f14074c8 100644
--- a/core/src/mindustry/core/GameState.java
+++ b/core/src/mindustry/core/GameState.java
@@ -23,7 +23,7 @@ public class GameState{
/** The current game rules. */
public Rules rules = new Rules();
/** Statistics for this save/game. Displayed after game over. */
- public Stats stats = new Stats();
+ public GameStats stats = new GameStats();
/** Global attributes of the environment, calculated by weather. */
public Attributes envAttrs = new Attributes();
/** Sector information. Only valid in the campaign. */
@@ -41,10 +41,17 @@ public class GameState{
}
public void set(State astate){
+ //cannot pause when in multiplayer
+ if(astate == State.paused && net.active()) return;
+
Events.fire(new StateChangeEvent(state, astate));
state = astate;
}
+ public boolean hasSpawns(){
+ return rules.waves && !(isCampaign() && rules.attackMode);
+ }
+
/** Note that being in a campaign does not necessarily mean having a sector. */
public boolean isCampaign(){
return rules.sector != null;
@@ -68,7 +75,7 @@ public class GameState{
}
public boolean isPlaying(){
- return state == State.playing;
+ return (state == State.playing) || (state == State.paused && !isPaused());
}
/** @return whether the current state is *not* the menu. */
diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java
index df536552df..a96ea101a9 100644
--- a/core/src/mindustry/core/Logic.java
+++ b/core/src/mindustry/core/Logic.java
@@ -5,16 +5,15 @@ import arc.math.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.core.GameState.*;
+import mindustry.ctype.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.game.Teams.*;
import mindustry.gen.*;
+import mindustry.maps.*;
import mindustry.type.*;
import mindustry.type.Weather.*;
import mindustry.world.*;
-import mindustry.world.blocks.*;
-import mindustry.world.blocks.ConstructBlock.*;
-import mindustry.world.blocks.storage.CoreBlock.*;
import java.util.*;
@@ -39,32 +38,7 @@ public class Logic implements ApplicationListener{
//skip null entities or un-rebuildables, for obvious reasons; also skip client since they can't modify these requests
if(tile.build == null || !tile.block().rebuildable || net.client()) return;
- if(block instanceof ConstructBlock){
-
- ConstructBuild entity = tile.bc();
-
- //update block to reflect the fact that something was being constructed
- if(entity.cblock != null && entity.cblock.synthetic()){
- block = entity.cblock;
- }else{
- //otherwise this was a deconstruction that was interrupted, don't want to rebuild that
- return;
- }
- }
-
- TeamData data = state.teams.get(tile.team());
-
- //remove existing blocks that have been placed here.
- //painful O(n) iteration + copy
- for(int i = 0; i < data.blocks.size; i++){
- BlockPlan b = data.blocks.get(i);
- if(b.x == tile.x && b.y == tile.y){
- data.blocks.removeIndex(i);
- break;
- }
- }
-
- data.blocks.addFirst(new BlockPlan(tile.x, tile.y, (short)tile.build.rotation, block.id, tile.build.config()));
+ tile.build.addPlan(true);
});
Events.on(BlockBuildEndEvent.class, event -> {
@@ -84,51 +58,61 @@ public class Logic implements ApplicationListener{
Events.on(LaunchItemEvent.class, e -> state.secinfo.handleItemExport(e.stack));
//when loading a 'damaged' sector, propagate the damage
- Events.on(WorldLoadEvent.class, e -> {
+ Events.on(SaveLoadEvent.class, e -> {
if(state.isCampaign()){
- long seconds = state.rules.sector.getSecondsPassed();
- CoreBuild core = state.rules.defaultTeam.core();
- //THE WAVES NEVER END
- state.rules.waves = true;
+ state.secinfo.write();
- //apply fractional damage based on how many turns have passed for this sector
- //float turnsPassed = seconds / (turnDuration / 60f);
+ //how much wave time has passed
+ int wavesPassed = state.secinfo.wavesPassed;
- //TODO sector damage disabled for now
- //if(state.rules.sector.hasWaves() && turnsPassed > 0 && state.rules.sector.hasBase()){
- // SectorDamage.apply(turnsPassed / sectorDestructionTurns);
- //}
-
- //add resources based on turns passed
- if(state.rules.sector.save != null && core != null){
- //update correct storage capacity
- state.rules.sector.save.meta.secinfo.storageCapacity = core.storageCapacity;
-
- //add new items received
- state.rules.sector.calculateReceivedItems().each((item, amount) -> core.items.add(item, amount));
-
- //clear received items
- state.rules.sector.setExtraItems(new ItemSeq());
-
- //validation
- for(Item item : content.items()){
- //ensure positive items
- if(core.items.get(item) < 0) core.items.set(item, 0);
- //cap the items
- if(core.items.get(item) > core.storageCapacity) core.items.set(item, core.storageCapacity);
- }
+ //wave has passed, remove all enemies, they are assumed to be dead
+ if(wavesPassed > 0){
+ Groups.unit.each(u -> {
+ if(u.team == state.rules.waveTeam){
+ u.remove();
+ }
+ });
}
- state.rules.sector.setSecondsPassed(0);
- }
+ //simulate passing of waves
+ if(wavesPassed > 0){
+ //simulate wave counter moving forward
+ state.wave += wavesPassed;
+ state.wavetime = state.rules.waveSpacing;
+ SectorDamage.applyCalculatedDamage();
+ }
+
+ //reset values
+ state.secinfo.damage = 0f;
+ state.secinfo.wavesPassed = 0;
+ state.secinfo.hasCore = true;
+ state.secinfo.secondsPassed = 0;
+
+ state.rules.sector.saveInfo();
+ }
+ });
+
+ Events.on(WorldLoadEvent.class, e -> {
//enable infinite ammo for wave team by default
state.rules.waveTeam.rules().infiniteAmmo = true;
+ if(state.isCampaign()){
+ //enable building AI
+ state.rules.waveTeam.rules().ai = true;
+ state.rules.waveTeam.rules().infiniteResources = true;
+ }
//save settings
Core.settings.manualSave();
});
+ //sync research
+ Events.on(ResearchEvent.class, e -> {
+ if(net.server()){
+ Call.researched(e.content);
+ }
+ });
+
}
/** Adds starting items, resets wave time, and sets state to playing. */
@@ -168,11 +152,6 @@ public class Logic implements ApplicationListener{
}
public void skipWave(){
- if(state.isCampaign()){
- //warp time spent forward because the wave was just skipped.
- state.secinfo.internalTimeSpent += state.wavetime;
- }
-
state.wavetime = 0;
}
@@ -199,12 +178,13 @@ public class Logic implements ApplicationListener{
state.rules.waves = false;
}
- //TODO capturing is disabled
- /*
//if there's a "win" wave and no enemies are present, win automatically
- if(state.rules.waves && state.enemies == 0 && state.rules.winWave > 0 && state.wave >= state.rules.winWave && !spawner.isSpawning()){
+ if(state.rules.waves && (state.enemies == 0 && state.rules.winWave > 0 && state.wave >= state.rules.winWave && !spawner.isSpawning()) ||
+ (state.rules.attackMode && state.rules.waveTeam.cores().isEmpty())){
//the sector has been conquered - waves get disabled
state.rules.waves = false;
+ //disable attack mode
+ state.rules.attackMode = false;
//fire capture event
Events.fire(new SectorCaptureEvent(state.rules.sector));
@@ -213,7 +193,7 @@ public class Logic implements ApplicationListener{
if(!headless){
control.saves.saveSector(state.rules.sector);
}
- }*/
+ }
}else{
if(!state.rules.attackMode && state.teams.playerCores().size == 0 && !state.gameOver){
state.gameOver = true;
@@ -266,6 +246,15 @@ public class Logic implements ApplicationListener{
netClient.setQuiet();
}
+ //called when the remote server researches something
+ @Remote
+ public static void researched(Content content){
+ if(!(content instanceof UnlockableContent u)) return;
+
+ state.rules.researched.add(u.name);
+ ui.hudfrag.showUnlock(u);
+ }
+
@Override
public void dispose(){
//save the settings before quitting
@@ -283,7 +272,7 @@ public class Logic implements ApplicationListener{
if(state.isGame()){
if(!net.client()){
- state.enemies = Groups.unit.count(u -> u.team() == state.rules.waveTeam && u.type().isCounted);
+ state.enemies = Groups.unit.count(u -> u.team() == state.rules.waveTeam && u.type.isCounted);
}
if(!state.isPaused()){
diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java
index ae8c7d9a7c..3c6214fd85 100644
--- a/core/src/mindustry/core/NetClient.java
+++ b/core/src/mindustry/core/NetClient.java
@@ -194,14 +194,14 @@ public class NetClient implements ApplicationListener{
}
//server console logging
- Log.info("&y@: &lb@", player.name, message);
+ Log.info("&fi@: @", "&lc" + player.name, "&lw" + message);
//invoke event for all clients but also locally
//this is required so other clients get the correct name even if they don't know who's sending it yet
Call.sendMessage(message, colorizeName(player.id(), player.name), player);
}else{
//log command to console but with brackets
- Log.info("<&y@: &lm@&lg>", player.name, message);
+ Log.info("<&fi@: @&fr>", "&lk" + player.name, "&lw" + message);
//a command was sent, now get the output
if(response.type != ResponseType.valid){
diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java
index 77ab732cf6..00f0bc78e8 100644
--- a/core/src/mindustry/core/NetServer.java
+++ b/core/src/mindustry/core/NetServer.java
@@ -18,6 +18,7 @@ import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.game.Teams.*;
import mindustry.gen.*;
+import mindustry.graphics.*;
import mindustry.net.*;
import mindustry.net.Administration.*;
import mindustry.net.Packets.*;
@@ -299,6 +300,15 @@ public class NetServer implements ApplicationListener{
}
});
+ clientCommands.register("a", "", "Send a message only to admins.", (args, player) -> {
+ if(!player.admin){
+ player.sendMessage("[scarlet]You must be admin to use this command.");
+ return;
+ }
+
+ Groups.player.each(Player::admin, a -> a.sendMessage(args[0], player, "[#" + Pal.adminChat.toString() + "]" + NetClient.colorizeName(player.id, player.name)));
+ });
+
//duration of a a kick in seconds
int kickDuration = 60 * 60;
//voting round duration in seconds
@@ -508,7 +518,8 @@ public class NetServer implements ApplicationListener{
Call.playerDisconnect(player.id());
}
- if(Config.showConnectMessages.bool()) Log.info("&lm[@] &lc@ has disconnected. &lg&fi(@)", player.uuid(), player.name, reason);
+ String message = Strings.format("&lb@&fi&lk has disconnected. &fi&lk[&lb@&fi&lk] (@)", player.name, player.uuid(), reason);
+ if(Config.showConnectMessages.bool()) Log.info(message);
}
player.remove();
@@ -575,7 +586,7 @@ public class NetServer implements ApplicationListener{
shooting = false;
}
- if(!player.dead() && (player.unit().type().flying || !player.unit().type().canBoost)){
+ if(!player.dead() && (player.unit().type.flying || !player.unit().type.canBoost)){
boosting = false;
}
@@ -629,7 +640,7 @@ public class NetServer implements ApplicationListener{
Unit unit = player.unit();
long elapsed = Time.timeSinceMillis(con.lastReceivedClientTime);
- float maxSpeed = ((player.unit().type().canBoost && player.unit().isFlying()) ? player.unit().type().boostMultiplier : 1f) * player.unit().type().speed;
+ float maxSpeed = ((player.unit().type.canBoost && player.unit().isFlying()) ? player.unit().type.boostMultiplier : 1f) * player.unit().type.speed;
if(unit.isGrounded()){
maxSpeed *= unit.floorSpeedMultiplier();
}
@@ -736,7 +747,8 @@ public class NetServer implements ApplicationListener{
if(Config.showConnectMessages.bool()){
Call.sendMessage("[accent]" + player.name + "[accent] has connected.");
- Log.info("&lm[@] &y@ has connected.", player.uuid(), player.name);
+ String message = Strings.format("&lb@&fi&lk has connected. &fi&lk[&lb@&fi&lk]", player.name, player.uuid());
+ Log.info(message);
}
if(!Config.motd.string().equalsIgnoreCase("off")){
@@ -785,7 +797,7 @@ public class NetServer implements ApplicationListener{
public void openServer(){
try{
net.host(Config.port.num());
- info("&lcOpened a server on port @.", Config.port.num());
+ info("Opened a server on port @.", Config.port.num());
}catch(BindException e){
Log.err("Unable to host: Port already in use! Make sure no other servers are running on the same port in your network.");
state.set(State.menu);
diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java
index 03a18c01ed..60beec266b 100644
--- a/core/src/mindustry/core/World.java
+++ b/core/src/mindustry/core/World.java
@@ -148,7 +148,17 @@ public class World{
return build(Math.round(x / tilesize), Math.round(y / tilesize));
}
- public int toTile(float coord){
+ /** Convert from world to logic tile coordinates. Whole numbers are at centers of tiles. */
+ public static float conv(float coord){
+ return coord / tilesize;
+ }
+
+ /** Convert from tile to world coordinates. */
+ public static float unconv(float coord){
+ return coord * tilesize;
+ }
+
+ public static int toTile(float coord){
return Math.round(coord / tilesize);
}
@@ -253,7 +263,7 @@ public class World{
setSectorRules(sector);
if(state.rules.defaultTeam.core() != null){
- sector.setSpawnPosition(state.rules.defaultTeam.core().pos());
+ sector.info.spawnPosition = state.rules.defaultTeam.core().pos();
}
}
@@ -267,8 +277,6 @@ public class World{
ObjectIntMap floorc = new ObjectIntMap<>();
ObjectSet content = new ObjectSet<>();
- float waterFloors = 0, totalFloors = 0;
-
for(Tile tile : world.tiles){
if(world.getDarkness(tile.x, tile.y) >= 3){
continue;
@@ -280,10 +288,6 @@ public class World{
if(liquid != null) content.add(liquid);
if(!tile.block().isStatic()){
- totalFloors ++;
- if(liquid == Liquids.water){
- waterFloors += tile.floor().isDeep() ? 1f : 0.7f;
- }
floorc.increment(tile.floor());
if(tile.overlay() != Blocks.air){
floorc.increment(tile.overlay());
@@ -306,7 +310,7 @@ public class World{
//TODO bad code
boolean hasSnow = floors[0].name.contains("ice") || floors[0].name.contains("snow");
- boolean hasRain = !hasSnow && floors[0].name.contains("water");
+ boolean hasRain = !hasSnow && content.contains(Liquids.water) && !floors[0].name.contains("sand");
boolean hasDesert = !hasSnow && !hasRain && floors[0].name.contains("sand");
boolean hasSpores = floors[0].name.contains("spore") || floors[0].name.contains("moss") || floors[0].name.contains("tainted");
@@ -316,6 +320,7 @@ public class World{
if(hasRain){
state.rules.weather.add(new WeatherEntry(Weathers.rain));
+ state.rules.weather.add(new WeatherEntry(Weathers.fog));
}
if(hasDesert){
@@ -326,9 +331,9 @@ public class World{
state.rules.weather.add(new WeatherEntry(Weathers.sporestorm));
}
- state.secinfo.resources = content.asArray();
- state.secinfo.resources.sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id)));
-
+ sector.info.resources = content.asArray();
+ sector.info.resources.sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id)));
+ sector.saveInfo();
}
public Context filterContext(Map map){
diff --git a/core/src/mindustry/ctype/UnlockableContent.java b/core/src/mindustry/ctype/UnlockableContent.java
index f6e6d0a2dc..9020cd0ff1 100644
--- a/core/src/mindustry/ctype/UnlockableContent.java
+++ b/core/src/mindustry/ctype/UnlockableContent.java
@@ -10,11 +10,14 @@ import mindustry.game.EventType.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
+import mindustry.world.meta.*;
import static mindustry.Vars.*;
/** Base interface for an unlockable content type. */
public abstract class UnlockableContent extends MappableContent{
+ /** Stat storage for this content. Initialized on demand. */
+ public Stats stats = new Stats();
/** Localized, formal name. Never null. Set to internal name if not found in bundle. */
public String localizedName;
/** Localized description. May be null. */
@@ -38,6 +41,18 @@ public abstract class UnlockableContent extends MappableContent{
return minfo.mod == null ? description : description + "\n" + Core.bundle.format("mod.display", minfo.mod.meta.displayName());
}
+ /** Checks stat initialization state. Call before displaying stats. */
+ public void checkStats(){
+ if(!stats.intialized){
+ setStats();
+ stats.intialized = true;
+ }
+ }
+
+ /** Intializes stats on demand. Should only be called once. Only called before something is displayed. */
+ public void setStats(){
+ }
+
/** Generate any special icons for this content. Called asynchronously.*/
@CallSuper
public void createIcons(MultiPacker packer){
@@ -73,7 +88,9 @@ public abstract class UnlockableContent extends MappableContent{
}
/** This should show all necessary info about this content in the specified table. */
- public abstract void displayInfo(Table table);
+ public void display(Table table){
+
+ }
/** Called when this content is unlocked. Use this to unlock other related content. */
public void onUnlock(){
@@ -95,16 +112,25 @@ public abstract class UnlockableContent extends MappableContent{
}
}
- public final boolean unlocked(){
+ /** Unlocks this content, but does not fire any events. */
+ public void quiteUnlock(){
+ if(!unlocked()){
+ unlocked = true;
+ Core.settings.put(name + "-unlocked", true);
+ }
+ }
+
+ public boolean unlocked(){
+ if(net.client()) return state.rules.researched.contains(name);
return unlocked || alwaysUnlocked;
}
/** @return whether this content is unlocked, or the player is in a custom (non-campaign) game. */
- public final boolean unlockedNow(){
- return unlocked || alwaysUnlocked || !state.isCampaign();
+ public boolean unlockedNow(){
+ return unlocked() || !state.isCampaign();
}
- public final boolean locked(){
+ public boolean locked(){
return !unlocked();
}
}
diff --git a/core/src/mindustry/editor/EditorTile.java b/core/src/mindustry/editor/EditorTile.java
index 5ff533325d..f735bd790c 100644
--- a/core/src/mindustry/editor/EditorTile.java
+++ b/core/src/mindustry/editor/EditorTile.java
@@ -26,7 +26,7 @@ public class EditorTile extends Tile{
if(type instanceof OverlayFloor){
//don't place on liquids
- if(floor.hasSurface()){
+ if(floor.hasSurface() || !type.needsSurface){
setOverlayID(type.id);
}
return;
@@ -75,7 +75,7 @@ public class EditorTile extends Tile{
return;
}
- if(floor.isLiquid) return;
+ if(!floor.hasSurface() && overlay.asFloor().needsSurface) return;
if(overlay() == overlay) return;
op(OpType.overlay, this.overlay.id);
super.setOverlay(overlay);
@@ -105,9 +105,9 @@ public class EditorTile extends Tile{
}
@Override
- protected void changeEntity(Team team, Prov entityprov, int rotation){
+ protected void changeBuild(Team team, Prov entityprov, int rotation){
if(skip()){
- super.changeEntity(team, entityprov, rotation);
+ super.changeBuild(team, entityprov, rotation);
return;
}
diff --git a/core/src/mindustry/editor/EditorTool.java b/core/src/mindustry/editor/EditorTool.java
index 194ec97e4c..cd4b63935e 100644
--- a/core/src/mindustry/editor/EditorTool.java
+++ b/core/src/mindustry/editor/EditorTool.java
@@ -118,7 +118,7 @@ public enum EditorTool{
if(editor.drawBlock.isOverlay()){
Block dest = tile.overlay();
if(dest == editor.drawBlock) return;
- tester = t -> t.overlay() == dest && t.floor().hasSurface();
+ tester = t -> t.overlay() == dest && (t.floor().hasSurface() || !t.floor().needsSurface);
setter = t -> t.setOverlay(editor.drawBlock);
}else if(editor.drawBlock.isFloor()){
Block dest = tile.floor();
diff --git a/core/src/mindustry/editor/MapEditor.java b/core/src/mindustry/editor/MapEditor.java
index 49d174779b..1c33964e08 100644
--- a/core/src/mindustry/editor/MapEditor.java
+++ b/core/src/mindustry/editor/MapEditor.java
@@ -4,6 +4,7 @@ import arc.files.*;
import arc.func.*;
import arc.graphics.*;
import arc.math.*;
+import arc.math.geom.*;
import arc.struct.*;
import mindustry.content.*;
import mindustry.editor.DrawOperation.*;
@@ -180,6 +181,52 @@ public class MapEditor{
return false;
}
+ public void addCliffs(){
+ for(Tile tile : world.tiles){
+ if(!tile.block().isStatic() || tile.block() == Blocks.cliff) continue;
+
+ 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);
+ if(other != null && !other.block().isStatic()){
+ rotation |= (1 << i);
+ }
+ }
+
+ if(rotation != 0){
+ tile.setBlock(Blocks.cliff);
+ }
+
+ tile.data = (byte)rotation;
+ }
+
+ for(Tile tile : world.tiles){
+ if(tile.block() != Blocks.cliff && tile.block().isStatic()){
+ tile.setBlock(Blocks.air);
+ }
+ }
+ }
+
+ public void addFloorCliffs(){
+ for(Tile tile : world.tiles){
+ if(!tile.floor().hasSurface() || tile.block() == Blocks.cliff) continue;
+
+ 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);
+ if(other != null && !other.floor().hasSurface()){
+ rotation |= (1 << i);
+ }
+ }
+
+ if(rotation != 0){
+ tile.setBlock(Blocks.cliff);
+ }
+
+ tile.data = (byte)rotation;
+ }
+ }
+
public void drawCircle(int x, int y, Cons drawer){
for(int rx = -brushSize; rx <= brushSize; rx++){
for(int ry = -brushSize; ry <= brushSize; ry++){
diff --git a/core/src/mindustry/editor/MapEditorDialog.java b/core/src/mindustry/editor/MapEditorDialog.java
index 4f7eb008fd..dfad7c03ab 100644
--- a/core/src/mindustry/editor/MapEditorDialog.java
+++ b/core/src/mindustry/editor/MapEditorDialog.java
@@ -385,7 +385,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
}
public void build(){
- float size = 60f;
+ float size = 58f;
clearChildren();
table(cont -> {
@@ -559,10 +559,19 @@ public class MapEditorDialog extends Dialog implements Disposable{
mid.row();
- mid.table(t -> {
- t.button("@editor.center", Icon.move, Styles.cleart, () -> view.center()).growX().margin(9f);
- }).growX().top();
+ if(!mobile){
+ mid.table(t -> {
+ t.button("@editor.center", Icon.move, Styles.cleart, view::center).growX().margin(9f);
+ }).growX().top();
+ }
+ if(addCliffButton){
+ mid.row();
+
+ mid.table(t -> {
+ t.button("Cliffs", Icon.terrain, Styles.cleart, editor::addCliffs).growX().margin(9f);
+ }).growX().top();
+ }
}).margin(0).left().growY();
diff --git a/core/src/mindustry/editor/MapGenerateDialog.java b/core/src/mindustry/editor/MapGenerateDialog.java
index fae31dc7d5..c0292cbf74 100644
--- a/core/src/mindustry/editor/MapGenerateDialog.java
+++ b/core/src/mindustry/editor/MapGenerateDialog.java
@@ -51,7 +51,7 @@ public class MapGenerateDialog extends BaseDialog{
CachedTile ctile = new CachedTile(){
//nothing.
@Override
- protected void changeEntity(Team team, Prov entityprov, int rotation){
+ protected void changeBuild(Team team, Prov entityprov, int rotation){
}
};
@@ -417,7 +417,7 @@ public class MapGenerateDialog extends BaseDialog{
public void set(Block floor, Block wall, Block ore, Team team){
this.floor = floor.id;
this.block = wall.id;
- this.ore = !floor.asFloor().hasSurface() ? 0 : ore.id;
+ this.ore = (!floor.asFloor().hasSurface() && ore.asFloor().needsSurface) ? 0 : ore.id;
this.team = (byte)team.id;
}
diff --git a/core/src/mindustry/editor/WaveGraph.java b/core/src/mindustry/editor/WaveGraph.java
index 14b2416085..2436c62c2a 100644
--- a/core/src/mindustry/editor/WaveGraph.java
+++ b/core/src/mindustry/editor/WaveGraph.java
@@ -154,7 +154,7 @@ public class WaveGraph extends Table{
int sum = 0;
for(SpawnGroup spawn : groups){
- int spawned = spawn.getUnitsSpawned(i);
+ int spawned = spawn.getSpawned(i);
values[index][spawn.type.id] += spawned;
if(spawned > 0){
used.add(spawn.type);
diff --git a/core/src/mindustry/entities/Damage.java b/core/src/mindustry/entities/Damage.java
index e22891eba5..b6c9abe807 100644
--- a/core/src/mindustry/entities/Damage.java
+++ b/core/src/mindustry/entities/Damage.java
@@ -9,6 +9,7 @@ import arc.struct.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.gen.*;
@@ -82,7 +83,7 @@ public class Damage{
furthest = null;
- boolean found = world.raycast(b.tileX(), b.tileY(), world.toTile(b.x + Tmp.v1.x), world.toTile(b.y + Tmp.v1.y),
+ boolean found = world.raycast(b.tileX(), b.tileY(), World.toTile(b.x + Tmp.v1.x), World.toTile(b.y + Tmp.v1.y),
(x, y) -> (furthest = world.tile(x, y)) != null && furthest.team() != b.team && furthest.block().absorbLasers);
return found && furthest != null ? Math.max(6f, b.dst(furthest.worldx(), furthest.worldy())) : length;
diff --git a/core/src/mindustry/entities/Fires.java b/core/src/mindustry/entities/Fires.java
index 2906b4e7d7..754a8766b9 100644
--- a/core/src/mindustry/entities/Fires.java
+++ b/core/src/mindustry/entities/Fires.java
@@ -23,14 +23,14 @@ public class Fires{
if(fire == null){
fire = Fire.create();
- fire.tile(tile);
- fire.lifetime(baseLifetime);
+ fire.tile = tile;
+ fire.lifetime = baseLifetime;
fire.set(tile.worldx(), tile.worldy());
fire.add();
map.put(tile.pos(), fire);
}else{
- fire.lifetime(baseLifetime);
- fire.time(0f);
+ fire.lifetime = baseLifetime;
+ fire.time = 0f;
}
}
diff --git a/core/src/mindustry/entities/Lightning.java b/core/src/mindustry/entities/Lightning.java
index 738bfa1f1e..2d647bfb1e 100644
--- a/core/src/mindustry/entities/Lightning.java
+++ b/core/src/mindustry/entities/Lightning.java
@@ -5,6 +5,7 @@ import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.entities.bullet.*;
import mindustry.game.*;
import mindustry.gen.*;
@@ -48,7 +49,7 @@ public class Lightning{
bhit = false;
Vec2 from = lines.get(lines.size - 2);
Vec2 to = lines.get(lines.size - 1);
- world.raycastEach(world.toTile(from.getX()), world.toTile(from.getY()), world.toTile(to.getX()), world.toTile(to.getY()), (wx, wy) -> {
+ world.raycastEach(World.toTile(from.getX()), World.toTile(from.getY()), World.toTile(to.getX()), World.toTile(to.getY()), (wx, wy) -> {
Tile tile = world.tile(wx, wy);
if(tile != null && tile.block().insulated){
diff --git a/core/src/mindustry/entities/Units.java b/core/src/mindustry/entities/Units.java
index c6f592f30f..e4591a0ed0 100644
--- a/core/src/mindustry/entities/Units.java
+++ b/core/src/mindustry/entities/Units.java
@@ -3,9 +3,11 @@ package mindustry.entities;
import arc.*;
import arc.func.*;
import arc.math.geom.*;
+import arc.struct.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.game.*;
+import mindustry.game.Teams.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.*;
@@ -124,7 +126,7 @@ public class Units{
nearby(x, y, width, height, unit -> {
if(boolResult) return;
- if((unit.isGrounded() && !unit.type().hovering) == ground){
+ if((unit.isGrounded() && !unit.type.hovering) == ground){
unit.hitbox(hitrect);
if(hitrect.overlaps(x, y, width, height)){
@@ -308,20 +310,12 @@ public class Units{
/** Iterates over all units that are enemies of this team. */
public static void nearbyEnemies(Team team, float x, float y, float width, float height, Cons cons){
- if(team.active()){
- for(Team enemy : state.teams.enemiesOf(team)){
- nearby(enemy, x, y, width, height, cons);
- }
- }else{
- //inactive teams have no cache, check everything
- //TODO cache all teams with units OR blocks
- for(Team other : Team.all){
- if(other != team && other.data().unitCount > 0){
- nearby(other, x, y, width, height, cons);
- }
+ Seq data = state.teams.present;
+ for(int i = 0; i < data.size; i++){
+ if(data.items[i].team != team){
+ nearby(data.items[i].team, x, y, width, height, cons);
}
}
-
}
/** Iterates over all units that are enemies of this team. */
diff --git a/core/src/mindustry/entities/abilities/Ability.java b/core/src/mindustry/entities/abilities/Ability.java
index 466bfc1980..cb6e94547b 100644
--- a/core/src/mindustry/entities/abilities/Ability.java
+++ b/core/src/mindustry/entities/abilities/Ability.java
@@ -1,5 +1,6 @@
package mindustry.entities.abilities;
+import arc.*;
import mindustry.gen.*;
public abstract class Ability implements Cloneable{
@@ -14,4 +15,9 @@ public abstract class Ability implements Cloneable{
throw new RuntimeException("java sucks", e);
}
}
+
+ /** @return localized ability name; mods should override this. */
+ public String localized(){
+ return Core.bundle.get("ability." + getClass().getSimpleName().replace("Ability", "").toLowerCase());
+ }
}
diff --git a/core/src/mindustry/entities/abilities/ForceFieldAbility.java b/core/src/mindustry/entities/abilities/ForceFieldAbility.java
index fa9fa5e2c8..d341191a74 100644
--- a/core/src/mindustry/entities/abilities/ForceFieldAbility.java
+++ b/core/src/mindustry/entities/abilities/ForceFieldAbility.java
@@ -94,7 +94,7 @@ public class ForceFieldAbility extends Ability{
}
}
- private void checkRadius(Unit unit){
+ 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/HealFieldAbility.java b/core/src/mindustry/entities/abilities/RepairFieldAbility.java
similarity index 86%
rename from core/src/mindustry/entities/abilities/HealFieldAbility.java
rename to core/src/mindustry/entities/abilities/RepairFieldAbility.java
index 90f800ec84..8df0a96e2c 100644
--- a/core/src/mindustry/entities/abilities/HealFieldAbility.java
+++ b/core/src/mindustry/entities/abilities/RepairFieldAbility.java
@@ -5,7 +5,7 @@ import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
-public class HealFieldAbility extends Ability{
+public class RepairFieldAbility extends Ability{
public float amount = 1, reload = 100, range = 60;
public Effect healEffect = Fx.heal;
public Effect activeEffect = Fx.healWaveDynamic;
@@ -13,9 +13,9 @@ public class HealFieldAbility extends Ability{
protected float timer;
protected boolean wasHealed = false;
- HealFieldAbility(){}
+ RepairFieldAbility(){}
- public HealFieldAbility(float amount, float reload, float range){
+ public RepairFieldAbility(float amount, float reload, float range){
this.amount = amount;
this.reload = reload;
this.range = range;
diff --git a/core/src/mindustry/entities/abilities/ShieldFieldAbility.java b/core/src/mindustry/entities/abilities/ShieldRegenFieldAbility.java
similarity index 86%
rename from core/src/mindustry/entities/abilities/ShieldFieldAbility.java
rename to core/src/mindustry/entities/abilities/ShieldRegenFieldAbility.java
index 739751f6c1..8af8d2390a 100644
--- a/core/src/mindustry/entities/abilities/ShieldFieldAbility.java
+++ b/core/src/mindustry/entities/abilities/ShieldRegenFieldAbility.java
@@ -5,7 +5,7 @@ import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
-public class ShieldFieldAbility extends Ability{
+public class ShieldRegenFieldAbility extends Ability{
public float amount = 1, max = 100f, reload = 100, range = 60;
public Effect applyEffect = Fx.shieldApply;
public Effect activeEffect = Fx.shieldWave;
@@ -13,9 +13,9 @@ public class ShieldFieldAbility extends Ability{
protected float timer;
protected boolean applied = false;
- ShieldFieldAbility(){}
+ ShieldRegenFieldAbility(){}
- public ShieldFieldAbility(float amount, float max, float reload, float range){
+ public ShieldRegenFieldAbility(float amount, float max, float reload, float range){
this.amount = amount;
this.max = max;
this.reload = reload;
diff --git a/core/src/mindustry/entities/abilities/UnitSpawnAbility.java b/core/src/mindustry/entities/abilities/UnitSpawnAbility.java
index 74140114d9..95eb3bcf5b 100644
--- a/core/src/mindustry/entities/abilities/UnitSpawnAbility.java
+++ b/core/src/mindustry/entities/abilities/UnitSpawnAbility.java
@@ -1,5 +1,6 @@
package mindustry.entities.abilities;
+import arc.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.*;
@@ -56,4 +57,9 @@ public class UnitSpawnAbility extends Ability{
});
}
}
+
+ @Override
+ public String localized(){
+ return Core.bundle.format("ability.unitspawn", type.localizedName);
+ }
}
diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java
index 0c3a605f1b..8e06cf466e 100644
--- a/core/src/mindustry/entities/bullet/BulletType.java
+++ b/core/src/mindustry/entities/bullet/BulletType.java
@@ -104,6 +104,8 @@ public abstract class BulletType extends Content{
public float incendChance = 1f;
public float homingPower = 0f;
public float homingRange = 50f;
+ /** Use a negative value to disable homing delay. */
+ public float homingDelay = -1f;
public Color lightningColor = Pal.surge;
public int lightning;
@@ -137,6 +139,15 @@ public abstract class BulletType extends Content{
this(1f, 1f);
}
+ /** @return estimated damage per shot. this can be very inaccurate. */
+ public float estimateDPS(){
+ float sum = damage + splashDamage*0.75f;
+ if(fragBullet != null && fragBullet != this){
+ sum += fragBullet.estimateDPS() * fragBullets / 2f;
+ }
+ return sum;
+ }
+
/** Returns maximum distance the bullet this bullet type has can travel. */
public float range(){
return Math.max(speed * lifetime * (1f - drag), range);
@@ -251,7 +262,7 @@ public abstract class BulletType extends Content{
}
public void update(Bullet b){
- if(homingPower > 0.0001f){
+ if(homingPower > 0.0001f && b.time >= homingDelay){
Teamc target = Units.closestTarget(b.team, b.x, b.y, homingRange, e -> (e.isGrounded() && collidesGround) || (e.isFlying() && collidesAir), t -> collidesGround);
if(target != null){
b.vel.setAngle(Mathf.slerpDelta(b.rotation(), b.angleTo(target), homingPower));
diff --git a/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java b/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java
index a862671040..4c52105b26 100644
--- a/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java
+++ b/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java
@@ -44,6 +44,12 @@ public class ContinuousLaserBulletType extends BulletType{
this(0);
}
+ @Override
+ public float estimateDPS(){
+ //assume firing duration is about 100 by default, may not be accurate there's no way of knowing in this method
+ return damage * 100f / 5f;
+ }
+
@Override
public float range(){
return length;
diff --git a/core/src/mindustry/entities/bullet/LaserBulletType.java b/core/src/mindustry/entities/bullet/LaserBulletType.java
index ad5965f3b8..6d43baf95c 100644
--- a/core/src/mindustry/entities/bullet/LaserBulletType.java
+++ b/core/src/mindustry/entities/bullet/LaserBulletType.java
@@ -39,6 +39,11 @@ public class LaserBulletType extends BulletType{
this(1f);
}
+ @Override
+ public float estimateDPS(){
+ return super.estimateDPS() * 2f;
+ }
+
@Override
public void init(){
super.init();
diff --git a/core/src/mindustry/entities/bullet/LiquidBulletType.java b/core/src/mindustry/entities/bullet/LiquidBulletType.java
index 2d3de79977..5da33f95e0 100644
--- a/core/src/mindustry/entities/bullet/LiquidBulletType.java
+++ b/core/src/mindustry/entities/bullet/LiquidBulletType.java
@@ -22,6 +22,8 @@ public class LiquidBulletType extends BulletType{
if(liquid != null){
this.liquid = liquid;
this.status = liquid.effect;
+ lightColor = liquid.lightColor;
+ lightOpacity = liquid.lightColor.a;
}
ammoMultiplier = 1f;
diff --git a/core/src/mindustry/entities/comp/BuilderComp.java b/core/src/mindustry/entities/comp/BuilderComp.java
index 0aafd4d0c0..0ef4d8bed0 100644
--- a/core/src/mindustry/entities/comp/BuilderComp.java
+++ b/core/src/mindustry/entities/comp/BuilderComp.java
@@ -207,7 +207,8 @@ abstract class BuilderComp implements Unitc{
BuildPlan plan = buildPlan();
Tile tile = world.tile(plan.x, plan.y);
- if((!within(tile, buildingRange) && !state.isEditor()) || tile == null){
+
+ if(tile == null || (!within(tile, buildingRange) && !state.isEditor())){
return;
}
diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java
index 15d79a8942..84b6160d25 100644
--- a/core/src/mindustry/entities/comp/BuildingComp.java
+++ b/core/src/mindustry/entities/comp/BuildingComp.java
@@ -17,16 +17,19 @@ import arc.util.io.*;
import mindustry.annotations.Annotations.*;
import mindustry.audio.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.entities.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
+import mindustry.game.Teams.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.logic.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
+import mindustry.world.blocks.ConstructBlock.*;
import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.payloads.*;
import mindustry.world.blocks.power.*;
@@ -191,6 +194,36 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
//endregion
//region utility methods
+ public void addPlan(boolean checkPrevious){
+ if(!block.rebuildable) return;
+
+ if(self() instanceof ConstructBuild entity){
+ //update block to reflect the fact that something was being constructed
+ if(entity.cblock != null && entity.cblock.synthetic()){
+ block = entity.cblock;
+ }else{
+ //otherwise this was a deconstruction that was interrupted, don't want to rebuild that
+ return;
+ }
+ }
+
+ TeamData data = state.teams.get(team);
+
+ if(checkPrevious){
+ //remove existing blocks that have been placed here.
+ //painful O(n) iteration + copy
+ for(int i = 0; i < data.blocks.size; i++){
+ BlockPlan b = data.blocks.get(i);
+ if(b.x == tile.x && b.y == tile.y){
+ data.blocks.removeIndex(i);
+ break;
+ }
+ }
+ }
+
+ data.blocks.addFirst(new BlockPlan(tile.x, tile.y, (short)rotation, block.id, config()));
+ }
+
/** Configure with the current, local player. */
public void configure(Object value){
//save last used config
@@ -431,7 +464,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
*/
public boolean movePayload(Payload todump){
int trns = block.size/2 + 1;
- Tile next = tile.getNearby(Geometry.d4(rotation).x * trns, Geometry.d4(rotation).y * trns);
+ Tile next = tile.nearby(Geometry.d4(rotation).x * trns, Geometry.d4(rotation).y * trns);
if(next != null && next.build != null && next.build.team == team && next.build.acceptPayload(self(), todump)){
next.build.handlePayload(self(), todump);
@@ -514,7 +547,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
public float moveLiquidForward(boolean leaks, Liquid liquid){
- Tile next = tile.getNearby(rotation);
+ Tile next = tile.nearby(rotation);
if(next == null) return 0;
@@ -766,9 +799,9 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
public void drawCracks(){
- if(!damaged() || block.size > Block.maxCrackSize) return;
+ if(!damaged() || block.size > BlockRenderer.maxCrackSize) return;
int id = pos();
- TextureRegion region = Block.cracks[block.size - 1][Mathf.clamp((int)((1f - healthf()) * Block.crackRegions), 0, Block.crackRegions-1)];
+ TextureRegion region = renderer.blocks.cracks[block.size - 1][Mathf.clamp((int)((1f - healthf()) * BlockRenderer.crackRegions), 0, BlockRenderer.crackRegions-1)];
Draw.colorl(0.2f, 0.1f + (1f - healthf())* 0.6f);
Draw.rect(region, x, y, (id%4)*90);
Draw.color();
@@ -878,7 +911,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Called when arbitrary configuration is applied to a tile. */
public void configured(@Nullable Unit builder, @Nullable Object value){
//null is of type void.class; anonymous classes use their superclass.
- Class> type = value == null ? void.class : value.getClass().isAnonymousClass() ? value.getClass().getSuperclass() : value.getClass();
+ Class> type = value == null ? void.class : value.getClass().isAnonymousClass() || value.getClass().getSimpleName().startsWith("adapter") ? value.getClass().getSuperclass() : value.getClass();
if(builder != null && builder.isPlayer()){
lastAccessed = builder.getPlayer().name;
@@ -1234,8 +1267,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
@Override
public double sense(LAccess sensor){
return switch(sensor){
- case x -> x;
- case y -> y;
+ case x -> World.conv(x);
+ case y -> World.conv(y);
case team -> team.id;
case health -> health;
case maxHealth -> maxHealth;
@@ -1244,8 +1277,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
case totalItems -> items == null ? 0 : items.total();
case totalLiquids -> liquids == null ? 0 : liquids.total();
case totalPower -> power == null || !block.consumes.hasPower() ? 0 : power.status * (block.consumes.getPower().buffered ? block.consumes.getPower().capacity : 1f);
- case itemCapacity -> block.itemCapacity;
- case liquidCapacity -> block.liquidCapacity;
+ case itemCapacity -> block.hasItems ? block.itemCapacity : 0;
+ case liquidCapacity -> block.hasLiquids ? block.liquidCapacity : 0;
case powerCapacity -> block.consumes.hasPower() ? block.consumes.getPower().capacity : 0f;
case powerNetIn -> power == null ? 0 : power.graph.getLastScaledPowerIn() * 60;
case powerNetOut -> power == null ? 0 : power.graph.getLastScaledPowerOut() * 60;
@@ -1263,7 +1296,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
case type -> block;
case firstItem -> items == null ? null : items.first();
case config -> block.configurations.containsKey(Item.class) || block.configurations.containsKey(Liquid.class) ? config() : null;
- case payloadType -> getPayload() instanceof UnitPayload p1 ? p1.unit.type() : getPayload() instanceof BuildPayload p2 ? p2.block() : null;
+ case payloadType -> getPayload() instanceof UnitPayload p1 ? p1.unit.type : getPayload() instanceof BuildPayload p2 ? p2.block() : null;
default -> noSensed;
};
diff --git a/core/src/mindustry/entities/comp/BulletComp.java b/core/src/mindustry/entities/comp/BulletComp.java
index 4deb7cc9dc..5a08710762 100644
--- a/core/src/mindustry/entities/comp/BulletComp.java
+++ b/core/src/mindustry/entities/comp/BulletComp.java
@@ -7,8 +7,10 @@ import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
+import mindustry.core.*;
import mindustry.entities.bullet.*;
import mindustry.game.*;
+import mindustry.game.Teams.*;
import mindustry.gen.*;
import mindustry.graphics.*;
@@ -28,15 +30,10 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
@Override
public void getCollisions(Cons consumer){
- if(team.active()){
- for(Team team : team.enemies()){
- consumer.get(team.data().tree());
- }
- }else{
- for(Team other : Team.all){
- if(other != team && team.data().unitCount > 0){
- consumer.get(team.data().tree());
- }
+ Seq data = state.teams.present;
+ for(int i = 0; i < data.size; i++){
+ if(data.items[i].team != team){
+ consumer.get(data.items[i].tree());
}
}
}
@@ -114,7 +111,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
type.update(self());
if(type.collidesTiles && type.collides && type.collidesGround){
- world.raycastEach(world.toTile(lastX()), world.toTile(lastY()), tileX(), tileY(), (x, y) -> {
+ world.raycastEach(World.toTile(lastX()), World.toTile(lastY()), tileX(), tileY(), (x, y) -> {
Building tile = world.build(x, y);
if(tile == null || !isAdded()) return false;
diff --git a/core/src/mindustry/entities/comp/CommanderComp.java b/core/src/mindustry/entities/comp/CommanderComp.java
index b0fbddcf85..2fe2bf83a0 100644
--- a/core/src/mindustry/entities/comp/CommanderComp.java
+++ b/core/src/mindustry/entities/comp/CommanderComp.java
@@ -30,7 +30,7 @@ abstract class CommanderComp implements Entityc, Posc{
public void update(){
if(formation != null){
- formation.anchor.set(x, y, /*rotation*/ 0); //TODO rotation set to 0 because rotating is pointless
+ formation.anchor.set(x, y, 0);
formation.updateSlots();
}
}
@@ -59,7 +59,7 @@ abstract class CommanderComp implements Entityc, Posc{
units.clear();
Units.nearby(team, x, y, 150f, u -> {
- if(u.isAI() && include.get(u) && u != self() && u.type().flying == type.flying && u.hitSize <= hitSize * 1.1f){
+ if(u.isAI() && include.get(u) && u != self() && u.type.flying == type.flying && u.hitSize <= hitSize * 1.1f){
units.add(u);
}
});
@@ -74,7 +74,7 @@ abstract class CommanderComp implements Entityc, Posc{
void command(Formation formation, Seq units){
clearCommand();
- float spacing = hitSize * 0.65f;
+ float spacing = hitSize * 0.8f;
minFormationSpeed = type.speed;
controlling.addAll(units);
@@ -82,7 +82,7 @@ abstract class CommanderComp implements Entityc, Posc{
FormationAI ai;
unit.controller(ai = new FormationAI(self(), formation));
spacing = Math.max(spacing, ai.formationSize());
- minFormationSpeed = Math.min(minFormationSpeed, unit.type().speed);
+ minFormationSpeed = Math.min(minFormationSpeed, unit.type.speed);
}
this.formation = formation;
@@ -106,7 +106,7 @@ abstract class CommanderComp implements Entityc, Posc{
//reset controlled units
for(Unit unit : controlling){
if(unit.controller().isBeingControlled(self())){
- unit.controller(unit.type().createController());
+ unit.controller(unit.type.createController());
}
}
diff --git a/core/src/mindustry/entities/comp/FireComp.java b/core/src/mindustry/entities/comp/FireComp.java
index ea67ca9e19..84fcb6b3b5 100644
--- a/core/src/mindustry/entities/comp/FireComp.java
+++ b/core/src/mindustry/entities/comp/FireComp.java
@@ -16,7 +16,7 @@ import static mindustry.Vars.*;
@EntityDef(value = {Firec.class}, pooled = true)
@Component(base = true)
abstract class FireComp implements Timedc, Posc, Firec, Syncc{
- private static final float spreadChance = 0.05f, fireballChance = 0.07f;
+ private static final float spreadChance = 0.04f, fireballChance = 0.06f;
@Import float time, lifetime, x, y;
diff --git a/core/src/mindustry/entities/comp/MinerComp.java b/core/src/mindustry/entities/comp/MinerComp.java
index 6bac9dbd60..764e6ed4d3 100644
--- a/core/src/mindustry/entities/comp/MinerComp.java
+++ b/core/src/mindustry/entities/comp/MinerComp.java
@@ -54,7 +54,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
}
}
- if(core == null || !validMine(mineTile)){
+ if(!validMine(mineTile)){
mineTile = null;
mineTimer = 0f;
}else if(mining()){
@@ -69,7 +69,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{
if(mineTimer >= 50f + item.hardness*15f){
mineTimer = 0;
- if(within(core, mineTransferRange) && core.acceptStack(item, 1, this) == 1 && offloadImmediately()){
+ if(core != null && within(core, mineTransferRange) && core.acceptStack(item, 1, this) == 1 && offloadImmediately()){
Call.transferItemTo(item, 1,
mineTile.worldx() + Mathf.range(tilesize / 2f),
mineTile.worldy() + Mathf.range(tilesize / 2f), core);
diff --git a/core/src/mindustry/entities/comp/PayloadComp.java b/core/src/mindustry/entities/comp/PayloadComp.java
index ac1f4fa323..e2945d08f7 100644
--- a/core/src/mindustry/entities/comp/PayloadComp.java
+++ b/core/src/mindustry/entities/comp/PayloadComp.java
@@ -6,6 +6,7 @@ import arc.util.*;
import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.type.*;
@@ -120,7 +121,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
/** @return whether the tile has been successfully placed. */
boolean dropBlock(BuildPayload payload){
Building tile = payload.build;
- int tx = Vars.world.toTile(x - tile.block.offset), ty = Vars.world.toTile(y - tile.block.offset);
+ int tx = World.toTile(x - tile.block.offset), ty = World.toTile(y - tile.block.offset);
Tile on = Vars.world.tile(tx, ty);
if(on != null && Build.validPlace(tile.block, tile.team, tx, ty, tile.rotation, false)){
int rot = (int)((rotation + 45f) / 90f) % 4;
diff --git a/core/src/mindustry/entities/comp/PlayerComp.java b/core/src/mindustry/entities/comp/PlayerComp.java
index 4ee481b032..736a1b68e5 100644
--- a/core/src/mindustry/entities/comp/PlayerComp.java
+++ b/core/src/mindustry/entities/comp/PlayerComp.java
@@ -79,7 +79,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
admin = typing = false;
textFadeTime = 0f;
if(!dead()){
- unit.controller(unit.type().createController());
+ unit.controller(unit.type.createController());
unit = Nulls.unit;
}
}
@@ -91,7 +91,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
@Replace
public float clipSize(){
- return unit.isNull() ? 20 : unit.type().hitSize * 2f;
+ return unit.isNull() ? 20 : unit.type.hitSize * 2f;
}
@Override
@@ -123,7 +123,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
deathTimer = 0;
//update some basic state to sync things
- if(unit.type().canBoost){
+ if(unit.type.canBoost){
Tile tile = unit.tileOn();
unit.elevation = Mathf.approachDelta(unit.elevation, (tile != null && tile.solid()) || boosting ? 1f : 0f, 0.08f);
}
@@ -177,7 +177,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
if(this.unit != Nulls.unit){
//un-control the old unit
- this.unit.controller(this.unit.type().createController());
+ this.unit.controller(this.unit.type.createController());
}
this.unit = unit;
if(unit != Nulls.unit){
diff --git a/core/src/mindustry/entities/comp/PosComp.java b/core/src/mindustry/entities/comp/PosComp.java
index 15c665739e..6446c0f91f 100644
--- a/core/src/mindustry/entities/comp/PosComp.java
+++ b/core/src/mindustry/entities/comp/PosComp.java
@@ -2,9 +2,9 @@ package mindustry.entities.comp;
import arc.math.geom.*;
import arc.util.*;
-import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.world.*;
import mindustry.world.blocks.environment.*;
@@ -32,11 +32,11 @@ abstract class PosComp implements Position{
}
int tileX(){
- return Vars.world.toTile(x);
+ return World.toTile(x);
}
int tileY(){
- return Vars.world.toTile(y);
+ return World.toTile(y);
}
/** Returns air if this unit is on a non-air top block. */
diff --git a/core/src/mindustry/entities/comp/PuddleComp.java b/core/src/mindustry/entities/comp/PuddleComp.java
index 669ee7e1f2..a447bd633a 100644
--- a/core/src/mindustry/entities/comp/PuddleComp.java
+++ b/core/src/mindustry/entities/comp/PuddleComp.java
@@ -74,7 +74,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{
unit.apply(liquid.effect, 60 * 2);
if(unit.vel.len() > 0.1){
- Fx.ripple.at(unit.x, unit.y, unit.type().rippleScale, liquid.color);
+ Fx.ripple.at(unit.x, unit.y, unit.type.rippleScale, liquid.color);
}
}
}
@@ -98,7 +98,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{
boolean onLiquid = tile.floor().isLiquid;
float f = Mathf.clamp(amount / (maxLiquid / 1.5f));
float smag = onLiquid ? 0.8f : 0f;
- float sscl = 20f;
+ float sscl = 25f;
Draw.color(tmp.set(liquid.color).shiftValue(-0.05f));
Fill.circle(x + Mathf.sin(Time.time() + seeds * 532, sscl, smag), y + Mathf.sin(Time.time() + seeds * 53, sscl, smag), f * 8f);
diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java
index 1cf0f7e216..ca85eacd07 100644
--- a/core/src/mindustry/entities/comp/UnitComp.java
+++ b/core/src/mindustry/entities/comp/UnitComp.java
@@ -10,6 +10,7 @@ import arc.util.*;
import mindustry.ai.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.entities.*;
import mindustry.entities.abilities.*;
@@ -36,7 +37,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Import int id;
private UnitController controller;
- private UnitType type;
+ UnitType type;
boolean spawnedByCore;
double flag;
@@ -88,12 +89,14 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
case rotation -> rotation;
case health -> health;
case maxHealth -> maxHealth;
- case x -> x;
- case y -> y;
+ case ammo -> !state.rules.unitAmmo ? type.ammoCapacity : ammo;
+ case ammoCapacity -> type.ammoCapacity;
+ case x -> World.conv(x);
+ case y -> World.conv(y);
case team -> team.id;
case shooting -> isShooting() ? 1 : 0;
- case shootX -> aimX();
- case shootY -> aimY();
+ case shootX -> World.conv(aimX());
+ case shootY -> World.conv(aimY());
case flag -> flag;
case payloadCount -> self() instanceof Payloadc pay ? pay.payloads().size : 0;
default -> 0;
@@ -108,7 +111,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
case firstItem -> stack().amount == 0 ? null : item();
case payloadType -> self() instanceof Payloadc pay ?
(pay.payloads().isEmpty() ? null :
- pay.payloads().peek() instanceof UnitPayload p1 ? p1.unit.type() :
+ pay.payloads().peek() instanceof UnitPayload p1 ? p1.unit.type :
pay.payloads().peek() instanceof BuildPayload p2 ? p2.block() : null) : null;
default -> noSensed;
};
@@ -161,22 +164,12 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override
public void set(UnitType def, UnitController controller){
- type(type);
+ if(this.type != def){
+ setType(def);
+ }
controller(controller);
}
- @Override
- public void type(UnitType type){
- if(this.type == type) return;
-
- setStats(type);
- }
-
- @Override
- public UnitType type(){
- return type;
- }
-
/** @return pathfinder path type for calculating costs */
public int pathType(){
return Pathfinder.costGround;
@@ -206,7 +199,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
return Units.getCap(team);
}
- public void setStats(UnitType type){
+ public void setType(UnitType type){
this.type = type;
this.maxHealth = type.health;
this.drag = type.drag;
@@ -224,7 +217,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override
public void afterSync(){
//set up type info after reading
- setStats(this.type);
+ setType(this.type);
controller.unit(self());
}
@@ -284,7 +277,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f);
//apply knockback based on spawns
- if(team != state.rules.waveTeam){
+ if(team != state.rules.waveTeam && state.hasSpawns()){
float relativeSize = state.rules.dropZoneRadius + hitSize/2f + 1f;
for(Tile spawn : spawner.getSpawns()){
if(within(spawn.worldx(), spawn.worldy(), relativeSize)){
diff --git a/core/src/mindustry/entities/comp/WeaponsComp.java b/core/src/mindustry/entities/comp/WeaponsComp.java
index d891dbc1e4..dec0105c14 100644
--- a/core/src/mindustry/entities/comp/WeaponsComp.java
+++ b/core/src/mindustry/entities/comp/WeaponsComp.java
@@ -166,7 +166,7 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc, Statusc{
Weapon weapon = mount.weapon;
float baseX = this.x, baseY = this.y;
- boolean delay = weapon.firstShotDelay > 0f;
+ boolean delay = weapon.firstShotDelay + weapon.shotDelay > 0f;
(delay ? weapon.chargeSound : weapon.shootSound).at(x, y, Mathf.random(0.8f, 1.0f));
diff --git a/core/src/mindustry/entities/units/AIController.java b/core/src/mindustry/entities/units/AIController.java
index b02fa5dc00..ca005fe25d 100644
--- a/core/src/mindustry/entities/units/AIController.java
+++ b/core/src/mindustry/entities/units/AIController.java
@@ -95,7 +95,7 @@ public class AIController implements UnitController{
if(tile == targetTile || (costType == Pathfinder.costWater && !targetTile.floor().isLiquid)) return;
- unit.moveAt(vec.trns(unit.angleTo(targetTile), unit.type().speed));
+ unit.moveAt(vec.trns(unit.angleTo(targetTile), unit.type.speed));
}
protected void updateWeapons(){
@@ -105,7 +105,7 @@ public class AIController implements UnitController{
boolean ret = retarget();
if(ret){
- target = findTarget(unit.x, unit.y, unit.range(), unit.type().targetAir, unit.type().targetGround);
+ target = findTarget(unit.x, unit.y, unit.range(), unit.type.targetAir, unit.type.targetGround);
}
if(invalid(target)){
@@ -119,7 +119,7 @@ public class AIController implements UnitController{
float mountX = unit.x + Angles.trnsx(rotation, weapon.x, weapon.y),
mountY = unit.y + Angles.trnsy(rotation, weapon.x, weapon.y);
- if(unit.type().singleTarget){
+ if(unit.type.singleTarget){
targets[i] = target;
}else{
if(ret){
@@ -176,7 +176,7 @@ public class AIController implements UnitController{
}
protected void circle(Position target, float circleLength){
- circle(target, circleLength, unit.type().speed);
+ circle(target, circleLength, unit.type.speed);
}
protected void circle(Position target, float circleLength, float speed){
diff --git a/core/src/mindustry/game/DefaultWaves.java b/core/src/mindustry/game/DefaultWaves.java
index 53a0bfa99c..d33af5a41a 100644
--- a/core/src/mindustry/game/DefaultWaves.java
+++ b/core/src/mindustry/game/DefaultWaves.java
@@ -18,6 +18,7 @@ public class DefaultWaves{
new SpawnGroup(dagger){{
end = 10;
unitScaling = 2f;
+ max = 30;
}},
new SpawnGroup(crawler){{
@@ -45,6 +46,7 @@ public class DefaultWaves{
begin = 13;
spacing = 3;
unitScaling = 0.5f;
+ max = 25;
}},
new SpawnGroup(mace){{
@@ -61,7 +63,7 @@ public class DefaultWaves{
unitAmount = 4;
spacing = 2;
shieldScaling = 10f;
- max = 20;
+ max = 14;
}},
new SpawnGroup(mace){{
@@ -81,7 +83,7 @@ public class DefaultWaves{
effect = StatusEffects.overdrive;
}},
- new SpawnGroup(mace){{
+ new SpawnGroup(pulsar){{
begin = 120;
spacing = 2;
unitScaling = 3;
@@ -94,6 +96,7 @@ public class DefaultWaves{
unitScaling = 1;
spacing = 2;
shieldScaling = 20f;
+ max = 20;
}},
new SpawnGroup(quasar){{
@@ -111,6 +114,7 @@ public class DefaultWaves{
unitAmount = 1;
unitScaling = 3;
effect = StatusEffects.shielded;
+ max = 25;
}},
new SpawnGroup(fortress){{
@@ -122,7 +126,7 @@ public class DefaultWaves{
shieldScaling = 30;
}},
- new SpawnGroup(dagger){{
+ new SpawnGroup(nova){{
begin = 35;
spacing = 3;
unitAmount = 4;
@@ -138,6 +142,7 @@ public class DefaultWaves{
effect = StatusEffects.overdrive;
items = new ItemStack(Items.pyratite, 100);
end = 130;
+ max = 30;
}},
new SpawnGroup(horizon){{
@@ -156,6 +161,7 @@ public class DefaultWaves{
shields = 100f;
shieldScaling = 10f;
effect = StatusEffects.overdrive;
+ max = 20;
}},
new SpawnGroup(zenith){{
@@ -233,7 +239,7 @@ public class DefaultWaves{
shieldScaling = 20f;
}},
- new SpawnGroup(atrax){{
+ new SpawnGroup(toxopid){{
begin = 210;
unitAmount = 1;
unitScaling = 1;
@@ -248,12 +254,17 @@ public class DefaultWaves{
//TODO move elsewhere
public static Seq generate(float difficulty){
+ return generate(new Rand(), difficulty);
+ }
+
+ //TODO move elsewhere
+ public static Seq generate(Rand rand, float difficulty){
UnitType[][] species = {
{dagger, mace, fortress, scepter, reign},
{nova, pulsar, quasar, vela, corvus},
{crawler, atrax, spiroct, arkyid, toxopid},
//{risso, minke, bryde, sei, omura}, //questionable choices
- //{mono, poly, mega, quad, oct}, //do not attack
+ {poly, poly, mega, quad, quad},
{flare, horizon, zenith, antumbra, eclipse}
};
@@ -263,7 +274,7 @@ public class DefaultWaves{
Seq out = new Seq<>();
//max reasonable wave, after which everything gets boring
- int cap = 200;
+ int cap = 150;
float shieldStart = 30, shieldsPerWave = 20 + difficulty*30f;
@@ -274,18 +285,18 @@ public class DefaultWaves{
for(int i = start; i < cap;){
int f = i;
- int next = Mathf.random(8, 16);
+ int next = rand.random(8, 16);
float shieldAmount = Math.max((i - shieldStart) * shieldsPerWave, 0);
- int space = start == 0 ? 1 : Mathf.random(1, 2);
+ int space = start == 0 ? 1 : rand.random(1, 2);
//main progression
out.add(new SpawnGroup(curSpecies[Math.min(curTier, curSpecies.length - 1)]){{
unitAmount = f == 0 ? 1 : 10;
begin = f;
end = f + next >= cap ? never : f + next;
- max = 20;
- unitScaling = Mathf.random(1f, 2f);
+ max = 14;
+ unitScaling = rand.random(1f, 3f);
shields = shieldAmount;
shieldScaling = shieldsPerWave;
spacing = space;
@@ -295,16 +306,16 @@ public class DefaultWaves{
out.add(new SpawnGroup(curSpecies[Math.min(curTier, curSpecies.length - 1)]){{
unitAmount = 6;
begin = f + next;
- end = f + next + Mathf.random(8, 12);
- max = 14;
- unitScaling = Mathf.random(2f);
- spacing = Mathf.random(2, 3);
+ end = f + next + rand.random(8, 12);
+ max = 11;
+ unitScaling = rand.random(2f);
+ spacing = rand.random(2, 3);
shields = shieldAmount;
shieldScaling = shieldsPerWave;
}});
i += next;
- if(curTier < 3 || Mathf.chance(0.2)){
+ if(curTier < 3 || rand.chance(0.2)){
curTier ++;
}
@@ -312,7 +323,7 @@ public class DefaultWaves{
curTier = Math.min(curTier, 3);
//small chance to switch species
- if(Mathf.chance(0.3)){
+ if(rand.chance(0.3)){
curSpecies = Structs.random(species);
}
}
@@ -320,15 +331,15 @@ public class DefaultWaves{
createProgression.get(0);
- int step = 5 + Mathf.random(3);
+ int step = 5 + rand.random(3);
while(step <= cap){
createProgression.get(step);
- step += (int)(Mathf.random(12, 25) * Mathf.lerp(1f, 0.4f, difficulty));
+ step += (int)(rand.random(13, 25) * Mathf.lerp(1f, 0.5f, difficulty));
}
- int bossWave = (int)(Mathf.random(30, 60) * Mathf.lerp(1f, 0.7f, difficulty));
- int bossSpacing = (int)(Mathf.random(25, 40) * Mathf.lerp(1f, 0.6f, difficulty));
+ int bossWave = (int)(rand.random(30, 60) * Mathf.lerp(1f, 0.7f, difficulty));
+ int bossSpacing = (int)(rand.random(25, 40) * Mathf.lerp(1f, 0.6f, difficulty));
//main boss progression
out.add(new SpawnGroup(Structs.random(species)[4]){{
@@ -339,17 +350,45 @@ public class DefaultWaves{
max = 16;
unitScaling = bossSpacing;
shieldScaling = shieldsPerWave;
+ effect = StatusEffects.boss;
}});
//alt boss progression
out.add(new SpawnGroup(Structs.random(species)[4]){{
unitAmount = 1;
- begin = bossWave + Mathf.random(3, 5) * bossSpacing;
+ begin = bossWave + rand.random(3, 5) * bossSpacing;
spacing = bossSpacing;
end = never;
max = 16;
unitScaling = bossSpacing;
shieldScaling = shieldsPerWave;
+ effect = StatusEffects.boss;
+ }});
+
+ int finalBossStart = 120 + rand.random(30);
+
+ //final boss waves
+ out.add(new SpawnGroup(Structs.random(species)[4]){{
+ unitAmount = 1;
+ begin = finalBossStart;
+ spacing = bossSpacing/2;
+ end = never;
+ unitScaling = bossSpacing;
+ shields = 500;
+ shieldScaling = shieldsPerWave * 4;
+ effect = StatusEffects.boss;
+ }});
+
+ //final boss waves (alt)
+ out.add(new SpawnGroup(Structs.random(species)[4]){{
+ unitAmount = 1;
+ begin = finalBossStart + 15;
+ spacing = bossSpacing/2;
+ end = never;
+ unitScaling = bossSpacing;
+ shields = 500;
+ shieldScaling = shieldsPerWave * 4;
+ effect = StatusEffects.boss;
}});
//shift back waves on higher difficulty for a harder start
diff --git a/core/src/mindustry/game/EventType.java b/core/src/mindustry/game/EventType.java
index 272c26363f..1ab946c4ac 100644
--- a/core/src/mindustry/game/EventType.java
+++ b/core/src/mindustry/game/EventType.java
@@ -35,7 +35,13 @@ public class EventType{
preDraw,
postDraw,
uiDrawBegin,
- uiDrawEnd
+ uiDrawEnd,
+ //before/after bloom used, skybox or planets drawn
+ universeDrawBegin,
+ //skybox drawn and bloom is enabled - use Vars.renderer.planets
+ universeDraw,
+ //planets drawn and bloom disabled
+ universeDrawEnd
}
public static class WinEvent{}
@@ -73,6 +79,15 @@ public class EventType{
}
}
+ /** Called when a sector is destroyed by waves when you're not there. */
+ public static class SectorInvasionEvent{
+ public final Sector sector;
+
+ public SectorInvasionEvent(Sector sector){
+ this.sector = sector;
+ }
+ }
+
public static class LaunchItemEvent{
public final ItemStack stack;
@@ -214,8 +229,8 @@ public class EventType{
}
/**
- * Called when block building begins by placing down the BuildBlock.
- * The tile's block will nearly always be a BuildBlock.
+ * Called when block building begins by placing down the ConstructBlock.
+ * The tile's block will nearly always be a ConstructBlock.
*/
public static class BlockBuildBeginEvent{
public final Tile tile;
@@ -247,7 +262,7 @@ public class EventType{
/**
* Called when a player or drone begins building something.
- * This does not necessarily happen when a new BuildBlock is created.
+ * This does not necessarily happen when a new ConstructBlock is created.
*/
public static class BuildSelectEvent{
public final Tile tile;
diff --git a/core/src/mindustry/game/Stats.java b/core/src/mindustry/game/GameStats.java
similarity index 96%
rename from core/src/mindustry/game/Stats.java
rename to core/src/mindustry/game/GameStats.java
index 1d175607ba..8108f2ddad 100644
--- a/core/src/mindustry/game/Stats.java
+++ b/core/src/mindustry/game/GameStats.java
@@ -6,7 +6,7 @@ import mindustry.type.*;
//TODO more stats:
//- units constructed
-public class Stats{
+public class GameStats{
/** Total items delivered to global resoure counter. Campaign only. */
public ObjectIntMap- itemsDelivered = new ObjectIntMap<>();
/** Enemy (red team) units destroyed. */
@@ -40,7 +40,7 @@ public class Stats{
//weigh used fractions
float frac = 0f;
- Seq
- obtainable = zone.save == null ? new Seq<>() : zone.save.meta.secinfo.resources.select(i -> i instanceof Item).as();
+ Seq
- obtainable = zone.save == null ? new Seq<>() : zone.info.resources.select(i -> i instanceof Item).as();
for(Item item : obtainable){
frac += Mathf.clamp((float)itemsDelivered.get(item, 0) / capacity) / (float)obtainable.size;
}
diff --git a/core/src/mindustry/game/Gamemode.java b/core/src/mindustry/game/Gamemode.java
index 9de5e71052..f2bb95130a 100644
--- a/core/src/mindustry/game/Gamemode.java
+++ b/core/src/mindustry/game/Gamemode.java
@@ -23,7 +23,6 @@ public enum Gamemode{
rules.waveTimer = true;
rules.waveSpacing /= 2f;
- rules.teams.get(rules.waveTeam).ai = true;
rules.teams.get(rules.waveTeam).infiniteResources = true;
}, map -> map.teams.contains(state.rules.waveTeam.id)),
pvp(rules -> {
diff --git a/core/src/mindustry/game/Objectives.java b/core/src/mindustry/game/Objectives.java
index a4097c51fc..7fc844a180 100644
--- a/core/src/mindustry/game/Objectives.java
+++ b/core/src/mindustry/game/Objectives.java
@@ -28,7 +28,6 @@ public class Objectives{
}
}
- //TODO fix
public static class SectorComplete extends SectorObjective{
public SectorComplete(SectorPreset zone){
@@ -39,12 +38,12 @@ public class Objectives{
@Override
public boolean complete(){
- return preset.sector.save != null && preset.sector.save.meta.wave >= preset.sector.save.meta.rules.winWave;
+ return preset.sector.save != null && preset.sector.save.meta.wave >= preset.captureWave;
}
@Override
public String display(){
- return Core.bundle.format("requirement.wave", preset.sector.save == null ? "" : preset.sector.save.meta.rules.winWave, preset.localizedName);
+ return Core.bundle.format("requirement.capture", preset.localizedName);
}
}
diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java
index a101fe8592..2a927cc59b 100644
--- a/core/src/mindustry/game/Rules.java
+++ b/core/src/mindustry/game/Rules.java
@@ -82,6 +82,8 @@ public class Rules{
public Seq weather = new Seq<>(1);
/** Blocks that cannot be placed. */
public ObjectSet bannedBlocks = new ObjectSet<>();
+ /** Unlocked content names. Only used in multiplayer when the campaign is enabled. */
+ public ObjectSet researched = new ObjectSet<>();
/** Whether ambient lighting is enabled. */
public boolean lighting = false;
/** Whether enemy lighting is visible.
@@ -104,6 +106,8 @@ public class Rules{
public boolean ai;
/** TODO Tier of blocks/designs that the AI uses for building. [0, 1]*/
public float aiTier = 0f;
+ /** Whether, when AI is enabled, ships should be spawned from the core. */
+ public boolean aiCoreSpawn = true;
/** If true, blocks don't require power or resources. */
public boolean cheat;
/** If true, resources are not consumed when building. */
diff --git a/core/src/mindustry/game/Schematics.java b/core/src/mindustry/game/Schematics.java
index 596a571d3a..20fe7c36c4 100644
--- a/core/src/mindustry/game/Schematics.java
+++ b/core/src/mindustry/game/Schematics.java
@@ -16,6 +16,7 @@ import arc.util.pooling.*;
import arc.util.serialization.*;
import mindustry.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.entities.units.*;
import mindustry.game.EventType.*;
@@ -608,8 +609,8 @@ public class Schematics implements Loadable{
wx = wy;
wy = -x;
}
- req.x = (short)(world.toTile(wx - req.block.offset) + ox);
- req.y = (short)(world.toTile(wy - req.block.offset) + oy);
+ req.x = (short)(World.toTile(wx - req.block.offset) + ox);
+ req.y = (short)(World.toTile(wy - req.block.offset) + oy);
req.rotation = (byte)Mathf.mod(req.rotation + direction, 4);
});
diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java
index b66dc5bf95..3b2b4df3dd 100644
--- a/core/src/mindustry/game/SectorInfo.java
+++ b/core/src/mindustry/game/SectorInfo.java
@@ -5,6 +5,7 @@ import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.ctype.*;
+import mindustry.maps.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.storage.CoreBlock.*;
@@ -25,9 +26,9 @@ public class SectorInfo{
/** Export statistics. */
public ObjectMap
- export = new ObjectMap<>();
/** Items stored in all cores. */
- public ItemSeq coreItems = new ItemSeq();
+ public ItemSeq items = new ItemSeq();
/** The best available core type. */
- public Block bestCoreType = Blocks.air;
+ public Block bestCoreType = Blocks.coreShard;
/** Max storage capacity. */
public int storageCapacity = 0;
/** Whether a core is available here. */
@@ -38,8 +39,27 @@ public class SectorInfo{
public @Nullable Sector destination;
/** Resources known to occur at this sector. */
public Seq resources = new Seq<>();
- /** Time spent at this sector. Do not use unless you know what you're doing. */
- public transient float internalTimeSpent;
+ /** Whether waves are enabled here. */
+ public boolean waves = true;
+ /** Whether attack mode is enabled here. */
+ public boolean attack = false;
+ /** Wave # from state */
+ public int wave = 1, winWave = -1;
+ /** Time between waves. */
+ public float waveSpacing = 60 * 60 * 2;
+ /** Damage dealt to sector. */
+ public float damage;
+ /** How many waves have passed while the player was away. */
+ public int wavesPassed;
+ /** Packed core spawn position. */
+ public int spawnPosition;
+ /** How long the player has been playing elsewhere. */
+ public float secondsPassed;
+ /** Display name. */
+ public @Nullable String name;
+
+ /** Special variables for simulation. */
+ public float sumHealth, sumRps, sumDps, waveHealthBase, waveHealthSlope, waveDpsBase, waveDpsSlope;
/** Counter refresh state. */
private transient Interval time = new Interval();
@@ -79,26 +99,68 @@ public class SectorInfo{
return export.get(item, ExportStat::new).mean;
}
+ /** Write contents of meta into main storage. */
+ public void write(){
+ //enable attack mode when there's a core.
+ if(state.rules.waveTeam.core() != null){
+ attack = true;
+ winWave = 0;
+ }
+
+ //if there are infinite waves and no win wave, add a win wave.
+ if(waves && winWave <= 0 && !attack){
+ winWave = 30;
+ }
+
+ state.wave = wave;
+ state.rules.waves = waves;
+ state.rules.waveSpacing = waveSpacing;
+ state.rules.winWave = winWave;
+ state.rules.attackMode = attack;
+
+ CoreBuild entity = state.rules.defaultTeam.core();
+ if(entity != null){
+ entity.items.clear();
+ entity.items.add(items);
+ //ensure capacity.
+ entity.items.each((i, a) -> entity.items.set(i, Math.min(a, entity.storageCapacity)));
+ }
+ }
+
/** Prepare data for writing to a save. */
public void prepare(){
//update core items
- coreItems.clear();
+ items.clear();
CoreBuild entity = state.rules.defaultTeam.core();
if(entity != null){
ItemModule items = entity.items;
for(int i = 0; i < items.length(); i++){
- coreItems.set(content.item(i), items.get(i));
+ this.items.set(content.item(i), items.get(i));
}
+
+ spawnPosition = entity.pos();
}
+ waveSpacing = state.rules.waveSpacing;
+ wave = state.wave;
+ winWave = state.rules.winWave;
+ waves = state.rules.waves;
+ attack = state.rules.attackMode;
hasCore = entity != null;
bestCoreType = !hasCore ? Blocks.air : state.rules.defaultTeam.cores().max(e -> e.block.size).block;
storageCapacity = entity != null ? entity.storageCapacity : 0;
+ secondsPassed = 0;
+ wavesPassed = 0;
+ damage = 0;
- //update sector's internal time spent counter
- state.rules.sector.setTimeSpent(internalTimeSpent);
+ if(state.rules.sector != null){
+ state.rules.sector.info = this;
+ state.rules.sector.saveInfo();
+ }
+
+ SectorDamage.writeParameters(this);
}
/** Update averages of various stats, updates some special sector logic.
@@ -107,14 +169,6 @@ public class SectorInfo{
//updating in multiplayer as a client doesn't make sense
if(net.client()) return;
- internalTimeSpent += Time.delta;
-
- //autorun turns
- if(internalTimeSpent >= turnDuration){
- internalTimeSpent = 0;
- universe.runTurn();
- }
-
CoreBuild ent = state.rules.defaultTeam.core();
//refresh throughput
diff --git a/core/src/mindustry/game/SpawnGroup.java b/core/src/mindustry/game/SpawnGroup.java
index f9ae7c74d3..86ba7b6324 100644
--- a/core/src/mindustry/game/SpawnGroup.java
+++ b/core/src/mindustry/game/SpawnGroup.java
@@ -9,6 +9,8 @@ import mindustry.gen.*;
import mindustry.io.legacy.*;
import mindustry.type.*;
+import java.util.*;
+
import static mindustry.Vars.*;
/**
@@ -52,8 +54,8 @@ public class SpawnGroup implements Serializable{
//serialization use only
}
- /** Returns the amount of units spawned on a specific wave. */
- public int getUnitsSpawned(int wave){
+ /** @return amount of units spawned on a specific wave. */
+ public int getSpawned(int wave){
if(spacing == 0) spacing = 1;
if(wave < begin || wave > end || (wave - begin) % spacing != 0){
return 0;
@@ -61,6 +63,11 @@ public class SpawnGroup implements Serializable{
return Math.min(unitAmount + (int)(((wave - begin) / spacing) / unitScaling), max);
}
+ /** @return amount of shields each unit has at a specific wave. */
+ public float getShield(int wave){
+ return Math.max(shields + shieldScaling*(wave - begin), 0);
+ }
+
/**
* Creates a unit, and assigns correct values based on this group's data.
* This method does not add() the unit.
@@ -76,7 +83,7 @@ public class SpawnGroup implements Serializable{
unit.addItem(items.item, items.amount);
}
- unit.shield(Math.max(shields + shieldScaling*(wave - begin), 0));
+ unit.shield = getShield(wave);
return unit;
}
@@ -133,4 +140,20 @@ public class SpawnGroup implements Serializable{
", items=" + items +
'}';
}
+
+ @Override
+ public boolean equals(Object o){
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
+ SpawnGroup group = (SpawnGroup)o;
+ return end == group.end && begin == group.begin && spacing == group.spacing && max == group.max
+ && Float.compare(group.unitScaling, unitScaling) == 0 && Float.compare(group.shields, shields) == 0
+ && Float.compare(group.shieldScaling, shieldScaling) == 0 && unitAmount == group.unitAmount &&
+ type == group.type && effect == group.effect && Structs.eq(items, group.items);
+ }
+
+ @Override
+ public int hashCode(){
+ return Arrays.hashCode(new Object[]{type, end, begin, spacing, max, unitScaling, shields, shieldScaling, unitAmount, effect, items});
+ }
}
diff --git a/core/src/mindustry/game/Team.java b/core/src/mindustry/game/Team.java
index 1ab345dc10..cbed06f4e7 100644
--- a/core/src/mindustry/game/Team.java
+++ b/core/src/mindustry/game/Team.java
@@ -31,9 +31,9 @@ public class Team implements Comparable{
Color.valueOf("ffd37f"), Color.valueOf("eab678"), Color.valueOf("d4816b")),
crux = new Team(2, "crux", Color.valueOf("f25555"),
Color.valueOf("fc8e6c"), Color.valueOf("f25555"), Color.valueOf("a04553")),
- green = new Team(3, "green", Color.valueOf("4dd98b")),
- purple = new Team(4, "purple", Color.valueOf("9a4bdf")),
- blue = new Team(5, "blue", Color.royal.cpy());
+ green = new Team(3, "green", Color.valueOf("54d67d")),
+ purple = new Team(4, "purple", Color.valueOf("995bb0")),
+ blue = new Team(5, "blue", Color.valueOf("5a4deb"));
static{
Mathf.rand.setSeed(8);
@@ -83,10 +83,6 @@ public class Team implements Comparable{
return state.rules.teams.get(this);
}
- public Team[] enemies(){
- return state.teams.enemiesOf(this);
- }
-
public TeamData data(){
return state.teams.get(this);
}
diff --git a/core/src/mindustry/game/Teams.java b/core/src/mindustry/game/Teams.java
index 5e38b43eb2..6a2972f074 100644
--- a/core/src/mindustry/game/Teams.java
+++ b/core/src/mindustry/game/Teams.java
@@ -23,7 +23,9 @@ public class Teams{
/** Maps team IDs to team data. */
private TeamData[] map = new TeamData[256];
/** Active teams. */
- private Seq active = new Seq<>();
+ public Seq active = new Seq<>();
+ /** Teams with block or unit presence. */
+ public Seq present = new Seq<>(TeamData.class);
public Teams(){
active.add(get(Team.crux));
@@ -31,7 +33,7 @@ public class Teams{
@Nullable
public CoreBuild closestEnemyCore(float x, float y, Team team){
- for(Team enemy : team.enemies()){
+ for(Team enemy : team.data().coreEnemies){
CoreBuild tile = Geometry.findClosest(x, y, enemy.cores());
if(tile != null) return tile;
}
@@ -43,10 +45,6 @@ public class Teams{
return Geometry.findClosest(x, y, get(team).cores);
}
- public Team[] enemiesOf(Team team){
- return get(team).enemies;
- }
-
public boolean eachEnemyCore(Team team, Boolf ret){
for(TeamData data : active){
if(areEnemies(team, data.team)){
@@ -133,7 +131,7 @@ public class Teams{
}
private void count(Unit unit){
- unit.team.data().updateCount(unit.type(), 1);
+ unit.team.data().updateCount(unit.type, 1);
if(unit instanceof Payloadc){
((Payloadc)unit).payloads().each(p -> {
@@ -145,9 +143,12 @@ public class Teams{
}
public void updateTeamStats(){
+ present.clear();
+
for(Team team : Team.all){
TeamData data = team.data();
+ data.presentFlag = false;
data.unitCount = 0;
data.units.clear();
if(data.tree != null){
@@ -168,23 +169,36 @@ public class Teams{
}
}
+ //update presence flag.
+ Groups.build.each( b -> b.team.data().presentFlag = true);
+
for(Unit unit : Groups.unit){
TeamData data = unit.team.data();
data.tree().insert(unit);
data.units.add(unit);
+ data.presentFlag = true;
- if(data.unitsByType == null || data.unitsByType.length <= unit.type().id){
+ if(data.unitsByType == null || data.unitsByType.length <= unit.type.id){
data.unitsByType = new Seq[content.units().size];
}
- if(data.unitsByType[unit.type().id] == null){
- data.unitsByType[unit.type().id] = new Seq<>();
+ if(data.unitsByType[unit.type.id] == null){
+ data.unitsByType[unit.type.id] = new Seq<>();
}
- data.unitsByType[unit.type().id].add(unit);
+ data.unitsByType[unit.type.id].add(unit);
count(unit);
}
+
+ //update presence of each team.
+ for(Team team : Team.all){
+ TeamData data = team.data();
+
+ if(data.presentFlag || data.active()){
+ present.add(data);
+ }
+ }
}
private void updateEnemies(){
@@ -201,7 +215,7 @@ public class Teams{
}
}
- data.enemies = enemies.toArray(Team.class);
+ data.coreEnemies = enemies.toArray(Team.class);
}
}
@@ -210,7 +224,10 @@ public class Teams{
public final Team team;
public final BaseAI ai;
- public Team[] enemies = {};
+ private boolean presentFlag;
+
+ /** Enemies with cores or spawn points. */
+ public Team[] coreEnemies = {};
/** Planned blocks for drones. This is usually only blocks that have been broken. */
public Queue blocks = new Queue<>();
/** The current command for units to follow. */
diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java
index 892b93b731..9b1064a791 100644
--- a/core/src/mindustry/game/Universe.java
+++ b/core/src/mindustry/game/Universe.java
@@ -6,6 +6,8 @@ import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.game.EventType.*;
+import mindustry.io.legacy.*;
+import mindustry.maps.*;
import mindustry.type.*;
import mindustry.world.blocks.storage.*;
@@ -17,6 +19,7 @@ public class Universe{
private int netSeconds;
private float secondCounter;
private int turn;
+ private float turnCounter;
private Schematic lastLoadout;
private ItemSeq lastLaunchResources = new ItemSeq();
@@ -53,17 +56,19 @@ public class Universe{
}
}
- /** @return sectors attacked on the current planet, minus the ones that are being played on right now. */
- public Seq getAttacked(Planet planet){
- return planet.sectors.select(s -> s.hasWaves() && s.hasBase() && !s.isBeingPlayed() && s.getSecondsPassed() > 1);
- }
-
/** Update planet rotations, global time and relevant state. */
public void update(){
//only update time when not in multiplayer
if(!net.client()){
secondCounter += Time.delta / 60f;
+ turnCounter += Time.delta;
+
+ //auto-run turns
+ if(turnCounter >= turnDuration){
+ turnCounter = 0;
+ runTurn();
+ }
if(secondCounter >= 1){
seconds += (int)secondCounter;
@@ -132,42 +137,81 @@ public class Universe{
//update relevant sectors
for(Planet planet : content.planets()){
for(Sector sector : planet.sectors){
- if(sector.hasSave()){
- int spent = (int)(sector.getTimeSpent() / 60);
- int actuallyPassed = Math.max(newSecondsPassed - spent, 0);
+ if(sector.hasSave() && sector.hasBase()){
//increment seconds passed for this sector by the time that just passed with this turn
if(!sector.isBeingPlayed()){
- sector.setSecondsPassed(sector.getSecondsPassed() + actuallyPassed);
+ //increment time
+ sector.info.secondsPassed += turnDuration/60f;
+
+ int wavesPassed = (int)(sector.info.secondsPassed*60f / sector.info.waveSpacing);
+ boolean attacked = sector.info.waves;
+
+ if(attacked){
+ sector.info.wavesPassed = wavesPassed;
+ }
+
+ float damage = attacked ? SectorDamage.getDamage(sector.info) : 0f;
+
+ //damage never goes down until the player visits the sector, so use max
+ sector.info.damage = Math.max(sector.info.damage, damage);
- //TODO sector damage disabled for now
//check if the sector has been attacked too many times...
- /*if(sector.hasBase() && sector.hasWaves() && sector.getSecondsPassed() * 60f > turnDuration * sectorDestructionTurns){
+ if(attacked && damage >= 0.999f){
//fire event for losing the sector
Events.fire(new SectorLoseEvent(sector));
- //if so, just delete the save for now. it's lost.
- //TODO don't delete it later maybe
- sector.save.delete();
- //clear recieved
- sector.setExtraItems(new ItemSeq());
- sector.save = null;
- }*/
+ //sector is dead.
+ sector.info.items.clear();
+ sector.info.damage = 1f;
+ sector.info.hasCore = false;
+ sector.info.production.clear();
+ }else if(attacked && wavesPassed > 0 && sector.info.winWave > 1 && sector.info.wave + wavesPassed >= sector.info.winWave && !sector.hasEnemyBase()){
+ //autocapture the sector
+ sector.info.waves = false;
+
+ //fire the event
+ Events.fire(new SectorCaptureEvent(sector));
+ }
+
+ float scl = sector.getProductionScale();
+
+ //export to another sector
+ if(sector.info.destination != null){
+ Sector to = sector.info.destination;
+ if(to.hasBase()){
+ ItemSeq items = new ItemSeq();
+ //calculated exported items to this sector
+ sector.info.export.each((item, stat) -> items.add(item, (int)(stat.mean * newSecondsPassed * scl)));
+ to.addItems(items);
+ }
+ }
+
+ //add production, making sure that it's capped
+ sector.info.production.each((item, stat) -> sector.info.items.add(item, Math.min((int)(stat.mean * newSecondsPassed * scl), sector.info.storageCapacity - sector.info.items.get(item))));
+
+ sector.saveInfo();
}
- //export to another sector
- if(sector.save != null && sector.save.meta != null && sector.save.meta.secinfo != null && sector.save.meta.secinfo.destination != null){
- Sector to = sector.save.meta.secinfo.destination;
- if(to.save != null){
- ItemSeq items = new ItemSeq();
- //calculated exported items to this sector
- sector.save.meta.secinfo.export.each((item, stat) -> items.add(item, (int)(stat.mean * newSecondsPassed)));
- to.addItems(items);
+ //queue random invasions
+ if(!sector.isAttacked() && turn > invasionGracePeriod){
+ //invasion chance depends on # of nearby bases
+ if(Mathf.chance(baseInvasionChance * sector.near().count(Sector::hasEnemyBase))){
+ int waveMax = Math.max(sector.info.winWave, sector.isBeingPlayed() ? state.wave : 0) + Mathf.random(2, 5) * 5;
+
+ //assign invasion-related things
+ if(sector.isBeingPlayed()){
+ state.rules.winWave = waveMax;
+ state.rules.waves = true;
+ }else{
+ sector.info.winWave = waveMax;
+ sector.info.waves = true;
+ sector.saveInfo();
+ }
+
+ Events.fire(new SectorInvasionEvent(sector));
}
}
-
- //reset time spent to 0
- sector.setTimeSpent(0f);
}
}
}
@@ -184,7 +228,7 @@ public class Universe{
for(Planet planet : content.planets()){
for(Sector sector : planet.sectors){
if(sector.hasSave()){
- count.add(sector.calculateItems());
+ count.add(sector.items());
}
}
}
@@ -217,6 +261,11 @@ public class Universe{
private void load(){
seconds = Core.settings.getInt("utimei");
turn = Core.settings.getInt("turn");
+
+ if(Core.settings.has("unlocks")){
+ LegacyIO.readResearch();
+ Core.settings.remove("unlocks");
+ }
}
}
diff --git a/core/src/mindustry/graphics/BlockRenderer.java b/core/src/mindustry/graphics/BlockRenderer.java
index a36230f0aa..afe2e3182b 100644
--- a/core/src/mindustry/graphics/BlockRenderer.java
+++ b/core/src/mindustry/graphics/BlockRenderer.java
@@ -20,11 +20,14 @@ import static arc.Core.*;
import static mindustry.Vars.*;
public class BlockRenderer implements Disposable{
+ public static final int crackRegions = 8, maxCrackSize = 9;
+
private static final int initialRequests = 32 * 32;
private static final int expandr = 9;
private static final Color shadowColor = new Color(0, 0, 0, 0.71f);
public final FloorRenderer floor = new FloorRenderer();
+ public TextureRegion[][] cracks;
private Seq tileview = new Seq<>(false, initialRequests, Tile.class);
private Seq lightview = new Seq<>(false, initialRequests, Tile.class);
@@ -35,11 +38,20 @@ public class BlockRenderer implements Disposable{
private FrameBuffer dark = new FrameBuffer();
private Seq outArray2 = new Seq<>();
private Seq shadowEvents = new Seq<>();
- private IntSet processedEntities = new IntSet(), processedLinks = new IntSet();
+ private IntSet procEntities = new IntSet(), procLinks = new IntSet(), procLights = new IntSet();
private boolean displayStatus = false;
public BlockRenderer(){
+ Events.on(ClientLoadEvent.class, e -> {
+ cracks = new TextureRegion[maxCrackSize][crackRegions];
+ for(int size = 1; size <= maxCrackSize; size++){
+ for(int i = 0; i < crackRegions; i++){
+ cracks[size - 1][i] = Core.atlas.find("cracks-" + size + "-" + i);
+ }
+ }
+ });
+
Events.on(WorldLoadEvent.class, event -> {
shadowEvents.clear();
lastCamY = lastCamX = -99; //invalidate camera position so blocks get updated
@@ -179,8 +191,9 @@ public class BlockRenderer implements Disposable{
tileview.clear();
lightview.clear();
- processedEntities.clear();
- processedLinks.clear();
+ procEntities.clear();
+ procLinks.clear();
+ procLights.clear();
int minx = Math.max(avgx - rangex - expandr, 0);
int miny = Math.max(avgy - rangey - expandr, 0);
@@ -197,25 +210,25 @@ public class BlockRenderer implements Disposable{
tile = tile.build.tile;
}
- if(block != Blocks.air && block.cacheLayer == CacheLayer.normal && (tile.build == null || !processedEntities.contains(tile.build.id))){
+ if(block != Blocks.air && block.cacheLayer == CacheLayer.normal && (tile.build == null || !procEntities.contains(tile.build.id))){
if(block.expanded || !expanded){
- if(tile.build == null || processedLinks.add(tile.build.id)){
+ if(tile.build == null || procLinks.add(tile.build.id)){
tileview.add(tile);
if(tile.build != null){
- processedEntities.add(tile.build.id);
- processedLinks.add(tile.build.id);
+ procEntities.add(tile.build.id);
+ procLinks.add(tile.build.id);
}
}
}
//lights are drawn even in the expanded range
- if(tile.build != null || tile.block().emitLight){
+ if(((tile.build != null && procLights.add(tile.build.pos())) || tile.block().emitLight)){
lightview.add(tile);
}
if(tile.build != null && tile.build.power != null && tile.build.power.links.size > 0){
for(Building other : tile.build.getPowerConnections(outArray2)){
- if(other.block instanceof PowerNode && processedLinks.add(other.id)){ //TODO need a generic way to render connections!
+ if(other.block instanceof PowerNode && procLinks.add(other.id)){ //TODO need a generic way to render connections!
tileview.add(other.tile);
}
}
@@ -223,7 +236,7 @@ public class BlockRenderer implements Disposable{
}
//special case for floors
- if(block == Blocks.air && tile.floor().emitLight){
+ if((block == Blocks.air && tile.floor().emitLight) && procLights.add(tile.pos())){
lightview.add(tile);
}
}
diff --git a/core/src/mindustry/graphics/LightRenderer.java b/core/src/mindustry/graphics/LightRenderer.java
index 10ffa727b6..0a05c7409b 100644
--- a/core/src/mindustry/graphics/LightRenderer.java
+++ b/core/src/mindustry/graphics/LightRenderer.java
@@ -100,7 +100,6 @@ public class LightRenderer{
Draw.vert(ledge.texture, vertices, 0, vertices.length);
-
Vec2 v3 = Tmp.v2.trnsExact(rot, stroke);
u = ledge.u;
diff --git a/core/src/mindustry/graphics/MinimapRenderer.java b/core/src/mindustry/graphics/MinimapRenderer.java
index cdb84e9044..1c34b4424e 100644
--- a/core/src/mindustry/graphics/MinimapRenderer.java
+++ b/core/src/mindustry/graphics/MinimapRenderer.java
@@ -96,7 +96,7 @@ public class MinimapRenderer implements Disposable{
Draw.mixcol(unit.team().color, 1f);
float scale = Scl.scl(1f) / 2f * scaling * 32f;
- Draw.rect(unit.type().icon(Cicon.full), x + rx, y + ry, scale, scale, unit.rotation() - 90);
+ Draw.rect(unit.type.icon(Cicon.full), x + rx, y + ry, scale, scale, unit.rotation() - 90);
Draw.reset();
//only disable player names in multiplayer
diff --git a/core/src/mindustry/graphics/OverlayRenderer.java b/core/src/mindustry/graphics/OverlayRenderer.java
index 19569ed1a3..9bb3a95fa3 100644
--- a/core/src/mindustry/graphics/OverlayRenderer.java
+++ b/core/src/mindustry/graphics/OverlayRenderer.java
@@ -85,7 +85,7 @@ public class OverlayRenderer{
//special selection for block "units"
Fill.square(select.x, select.y, ((BlockUnitc)select).tile().block.size * tilesize/2f);
}else{
- Draw.rect(select.type().icon(Cicon.full), select.x(), select.y(), select.rotation() - 90);
+ Draw.rect(select.type.icon(Cicon.full), select.x(), select.y(), select.rotation() - 90);
}
Lines.stroke(unitFade);
@@ -121,10 +121,12 @@ public class OverlayRenderer{
Lines.stroke(2f);
Draw.color(Color.gray, Color.lightGray, Mathf.absin(Time.time(), 8f, 1f));
- for(Tile tile : spawner.getSpawns()){
- if(tile.within(player.x, player.y, state.rules.dropZoneRadius + spawnerMargin)){
- Draw.alpha(Mathf.clamp(1f - (player.dst(tile) - state.rules.dropZoneRadius) / spawnerMargin));
- Lines.dashCircle(tile.worldx(), tile.worldy(), state.rules.dropZoneRadius);
+ if(state.hasSpawns()){
+ for(Tile tile : spawner.getSpawns()){
+ if(tile.within(player.x, player.y, state.rules.dropZoneRadius + spawnerMargin)){
+ Draw.alpha(Mathf.clamp(1f - (player.dst(tile) - state.rules.dropZoneRadius) / spawnerMargin));
+ Lines.dashCircle(tile.worldx(), tile.worldy(), state.rules.dropZoneRadius);
+ }
}
}
diff --git a/core/src/mindustry/graphics/Pal.java b/core/src/mindustry/graphics/Pal.java
index 753bbbbbed..8bb3cd9e70 100644
--- a/core/src/mindustry/graphics/Pal.java
+++ b/core/src/mindustry/graphics/Pal.java
@@ -94,5 +94,7 @@ public class Pal{
redDust = Color.valueOf("ffa480"),
redderDust = Color.valueOf("ff7b69"),
- plasticSmoke = Color.valueOf("f1e479");
+ plasticSmoke = Color.valueOf("f1e479"),
+
+ adminChat = Color.valueOf("ff4000");
}
diff --git a/core/src/mindustry/graphics/g3d/PlanetGrid.java b/core/src/mindustry/graphics/g3d/PlanetGrid.java
index e4972e3eb7..380f937658 100644
--- a/core/src/mindustry/graphics/g3d/PlanetGrid.java
+++ b/core/src/mindustry/graphics/g3d/PlanetGrid.java
@@ -22,15 +22,16 @@ public class PlanetGrid{
{5, 3, 10, 1, 4}, {2, 5, 4, 0, 11}, {3, 7, 6, 1, 8}, {7, 2, 9, 0, 6}
};
- public final int size;
- public final Ptile[] tiles;
- public final Corner[] corners;
- public final Edge[] edges;
+ public int size;
+ public Ptile[] tiles;
+ public Corner[] corners;
+ public Edge[] edges;
- PlanetGrid(int size){
+ //this is protected so if you want to make strange grids you should know what you're doing.
+ protected PlanetGrid(int size){
this.size = size;
- tiles = new Ptile[Buildingount(size)];
+ tiles = new Ptile[tileCount(size)];
for(int i = 0; i < tiles.length; i++){
tiles[i] = new Ptile(i, i < 12 ? 5 : 6);
}
@@ -67,7 +68,7 @@ public class PlanetGrid{
return result;
}
- static PlanetGrid initialGrid(){
+ public static PlanetGrid initialGrid(){
PlanetGrid grid = new PlanetGrid(0);
for(Ptile t : grid.tiles){
@@ -111,7 +112,7 @@ public class PlanetGrid{
return grid;
}
- static PlanetGrid subdividedGrid(PlanetGrid prev){
+ public static PlanetGrid subdividedGrid(PlanetGrid prev){
PlanetGrid grid = new PlanetGrid(prev.size + 1);
int prevTiles = prev.tiles.length;
@@ -207,7 +208,7 @@ public class PlanetGrid{
return -1;
}
- static int Buildingount(int size){
+ static int tileCount(int size){
return 10 * Mathf.pow(3, size) + 2;
}
@@ -220,12 +221,12 @@ public class PlanetGrid{
}
public static class Ptile{
- public final int id;
- public final int edgeCount;
+ public int id;
+ public int edgeCount;
- public final Ptile[] tiles;
- public final Corner[] corners;
- public final Edge[] edges;
+ public Ptile[] tiles;
+ public Corner[] corners;
+ public Edge[] edges;
public Vec3 v = new Vec3();
@@ -240,11 +241,11 @@ public class PlanetGrid{
}
public static class Corner{
- public final int id;
- public final Ptile[] tiles = new Ptile[3];
- public final Corner[] corners = new Corner[3];
- public final Edge[] edges = new Edge[3];
- public final Vec3 v = new Vec3();
+ public int id;
+ public Ptile[] tiles = new Ptile[3];
+ public Corner[] corners = new Corner[3];
+ public Edge[] edges = new Edge[3];
+ public Vec3 v = new Vec3();
public Corner(int id){
this.id = id;
@@ -252,9 +253,9 @@ public class PlanetGrid{
}
public static class Edge{
- public final int id;
- public final Ptile[] tiles = new Ptile[2];
- public final Corner[] corners = new Corner[2];
+ public int id;
+ public Ptile[] tiles = new Ptile[2];
+ public Corner[] corners = new Corner[2];
public Edge(int id){
this.id = id;
diff --git a/core/src/mindustry/graphics/g3d/PlanetRenderer.java b/core/src/mindustry/graphics/g3d/PlanetRenderer.java
index e3eb74a7b5..405d668333 100644
--- a/core/src/mindustry/graphics/g3d/PlanetRenderer.java
+++ b/core/src/mindustry/graphics/g3d/PlanetRenderer.java
@@ -10,6 +10,7 @@ import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
+import mindustry.game.EventType.*;
import mindustry.graphics.*;
import mindustry.graphics.g3d.PlanetGrid.*;
import mindustry.type.*;
@@ -38,19 +39,19 @@ public class PlanetRenderer implements Disposable{
public float zoom = 1f;
private final Mesh[] outlines = new Mesh[10];
- private final PlaneBatch3D projector = new PlaneBatch3D();
- private final Mat3D mat = new Mat3D();
- private final FrameBuffer buffer = new FrameBuffer(2, 2, true);
- private PlanetInterfaceRenderer irenderer;
+ public final PlaneBatch3D projector = new PlaneBatch3D();
+ public final Mat3D mat = new Mat3D();
+ public final FrameBuffer buffer = new FrameBuffer(2, 2, true);
+ public PlanetInterfaceRenderer irenderer;
- private final Bloom bloom = new Bloom(Core.graphics.getWidth()/4, Core.graphics.getHeight()/4, true, false){{
+ public final Bloom bloom = new Bloom(Core.graphics.getWidth()/4, Core.graphics.getHeight()/4, true, false){{
setThreshold(0.8f);
blurPasses = 6;
}};
- private final Mesh atmosphere = MeshBuilder.buildHex(Color.white, 2, false, 1.5f);
+ public final Mesh atmosphere = MeshBuilder.buildHex(Color.white, 2, false, 1.5f);
//seed: 8kmfuix03fw
- private final CubemapMesh skybox = new CubemapMesh(new Cubemap("cubemaps/stars/"));
+ public final CubemapMesh skybox = new CubemapMesh(new Cubemap("cubemaps/stars/"));
public PlanetRenderer(){
camPos.set(0, 0f, camLength);
@@ -82,14 +83,20 @@ public class PlanetRenderer implements Disposable{
projector.proj(cam.combined);
batch.proj(cam.combined);
+ Events.fire(Trigger.universeDrawBegin);
+
beginBloom();
skybox.render(cam.combined);
+ Events.fire(Trigger.universeDraw);
+
renderPlanet(solarSystem);
endBloom();
+ Events.fire(Trigger.universeDrawEnd);
+
Gl.enable(Gl.blend);
irenderer.renderProjections();
@@ -100,18 +107,21 @@ public class PlanetRenderer implements Disposable{
cam.update();
}
- private void beginBloom(){
+ public void beginBloom(){
bloom.resize(Core.graphics.getWidth() / 4, Core.graphics.getHeight() / 4);
bloom.capture();
}
- private void endBloom(){
+ public void endBloom(){
bloom.render();
}
- private void renderPlanet(Planet planet){
+
+ public void renderPlanet(Planet planet){
+ if(!planet.visible()) return;
+
//render planet at offsetted position in the world
- planet.mesh.render(cam.combined, planet.getTransform(mat));
+ planet.draw(cam.combined, planet.getTransform(mat));
renderOrbit(planet);
@@ -137,8 +147,8 @@ public class PlanetRenderer implements Disposable{
}
}
- private void renderOrbit(Planet planet){
- if(planet.parent == null) return;
+ public void renderOrbit(Planet planet){
+ if(planet.parent == null || !planet.visible()) return;
Vec3 center = planet.parent.position;
float radius = planet.orbitRadius;
@@ -147,7 +157,7 @@ public class PlanetRenderer implements Disposable{
batch.flush(Gl.lineLoop);
}
- private void renderSectors(Planet planet){
+ public void renderSectors(Planet planet){
//apply transformed position
batch.proj().mul(planet.getTransform(mat));
@@ -268,7 +278,7 @@ public class PlanetRenderer implements Disposable{
}
}
- private Mesh outline(int size){
+ public Mesh outline(int size){
if(outlines[size] == null){
outlines[size] = MeshBuilder.buildHex(new HexMesher(){
@Override
diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java
index 7099f254dd..049853c864 100644
--- a/core/src/mindustry/input/DesktopInput.java
+++ b/core/src/mindustry/input/DesktopInput.java
@@ -12,6 +12,7 @@ import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.util.*;
import mindustry.*;
+import mindustry.core.*;
import mindustry.entities.units.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
@@ -352,9 +353,7 @@ public class DesktopInput extends InputHandler{
ui.planet.show();
}).visible(() -> state.isCampaign()).tooltip("@planetmap");
- table.button(Icon.up, Styles.clearPartiali, () -> {
- ui.planet.showLaunch(state.getSector(), player.team().core());
- }).visible(() -> state.isCampaign()).tooltip("@launchcore").disabled(b -> player.team().core() == null);
+ table.add();
}
void pollInput(){
@@ -363,7 +362,7 @@ public class DesktopInput extends InputHandler{
Tile selected = tileAt(Core.input.mouseX(), Core.input.mouseY());
int cursorX = tileX(Core.input.mouseX());
int cursorY = tileY(Core.input.mouseY());
- int rawCursorX = world.toTile(Core.input.mouseWorld().x), rawCursorY = world.toTile(Core.input.mouseWorld().y);
+ int rawCursorX = World.toTile(Core.input.mouseWorld().x), rawCursorY = World.toTile(Core.input.mouseWorld().y);
// automatically pause building if the current build queue is empty
if(Core.settings.getBool("buildautopause") && isBuilding && !player.builder().isBuilding()){
@@ -599,11 +598,11 @@ public class DesktopInput extends InputHandler{
}
protected void updateMovement(Unit unit){
- boolean omni = unit.type().omniMovement;
+ boolean omni = unit.type.omniMovement;
boolean ground = unit.isGrounded();
- float strafePenalty = ground ? 1f : Mathf.lerp(1f, unit.type().strafePenalty, Angles.angleDist(unit.vel().angle(), unit.rotation()) / 180f);
- float baseSpeed = unit.type().speed;
+ float strafePenalty = ground ? 1f : Mathf.lerp(1f, unit.type.strafePenalty, Angles.angleDist(unit.vel().angle(), unit.rotation()) / 180f);
+ float baseSpeed = unit.type.speed;
//limit speed to minimum formation speed to preserve formation
if(unit.isCommanding()){
@@ -611,7 +610,7 @@ public class DesktopInput extends InputHandler{
baseSpeed = unit.minFormationSpeed * 0.95f;
}
- float speed = baseSpeed * Mathf.lerp(1f, unit.isCommanding() ? 1f : unit.type().canBoost ? unit.type().boostMultiplier : 1f, unit.elevation) * strafePenalty;
+ float speed = baseSpeed * Mathf.lerp(1f, unit.type.canBoost ? unit.type.boostMultiplier : 1f, unit.elevation) * strafePenalty;
float xa = Core.input.axis(Binding.move_x);
float ya = Core.input.axis(Binding.move_y);
boolean boosted = (unit instanceof Mechc && unit.isFlying());
@@ -622,7 +621,7 @@ public class DesktopInput extends InputHandler{
}
float mouseAngle = Angles.mouseAngle(unit.x, unit.y);
- boolean aimCursor = omni && player.shooting && unit.type().hasWeapons() && unit.type().faceTarget && !boosted && unit.type().rotateShooting;
+ boolean aimCursor = omni && player.shooting && unit.type.hasWeapons() && unit.type.faceTarget && !boosted && unit.type.rotateShooting;
if(aimCursor){
unit.lookAt(mouseAngle);
@@ -637,11 +636,11 @@ public class DesktopInput extends InputHandler{
}else{
unit.moveAt(Tmp.v2.trns(unit.rotation, movement.len()));
if(!movement.isZero() && ground){
- unit.vel.rotateTo(movement.angle(), unit.type().rotateSpeed);
+ unit.vel.rotateTo(movement.angle(), unit.type.rotateSpeed);
}
}
- unit.aim(unit.type().faceTarget ? Core.input.mouseWorld() : Tmp.v1.trns(unit.rotation, Core.input.mouseWorld().dst(unit)).add(unit.x, unit.y));
+ unit.aim(unit.type.faceTarget ? Core.input.mouseWorld() : Tmp.v1.trns(unit.rotation, Core.input.mouseWorld().dst(unit)).add(unit.x, unit.y));
unit.controlWeapons(true, player.shooting && !boosted);
player.boosting = Core.input.keyDown(Binding.boost) && !movement.isZero();
@@ -660,7 +659,7 @@ public class DesktopInput extends InputHandler{
}
}
- //update commander inut
+ //update commander unit
if(Core.input.keyTap(Binding.command)){
Call.unitCommand(player);
}
diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java
index eebe40e15b..99103da3d7 100644
--- a/core/src/mindustry/input/InputHandler.java
+++ b/core/src/mindustry/input/InputHandler.java
@@ -16,6 +16,7 @@ import arc.util.*;
import mindustry.ai.formations.patterns.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.entities.*;
import mindustry.entities.units.*;
import mindustry.game.EventType.*;
@@ -158,7 +159,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
Payloadc pay = (Payloadc)unit;
if(target.isAI() && target.isGrounded() && pay.canPickup(target)
- && target.within(unit, unit.type().hitSize * 2f + target.type().hitSize * 2f)){
+ && target.within(unit, unit.type.hitSize * 2f + target.type.hitSize * 2f)){
Call.pickedUnitPayload(unit, target);
}
}
@@ -240,6 +241,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
pay.set(x, y);
pay.dropLastPayload();
pay.set(prevx, prevy);
+ pay.controlling().each(u -> {
+ if(u instanceof Payloadc){
+ Call.payloadDropped(u, u.x, u.y);
+ }
+ });
}
}
@@ -365,7 +371,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
if(commander.isCommanding()){
commander.clearCommand();
- }else if(player.unit().type().commandLimit > 0){
+ }else if(player.unit().type.commandLimit > 0){
//TODO try out some other formations
commander.commandNearby(new CircleFormation());
@@ -398,17 +404,17 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
if(player.shooting && !wasShooting && player.unit().hasWeapons() && state.rules.unitAmmo && player.unit().ammo <= 0){
- player.unit().type().weapons.first().noAmmoSound.at(player.unit());
+ player.unit().type.weapons.first().noAmmoSound.at(player.unit());
}
wasShooting = player.shooting;
if(!player.dead()){
- controlledType = player.unit().type();
+ controlledType = player.unit().type;
}
if(controlledType != null && player.dead()){
- Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type() == controlledType && !u.dead);
+ Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type == controlledType && !u.dead);
if(unit != null){
Call.unitControl(player, unit);
@@ -418,9 +424,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public void checkUnit(){
if(controlledType != null){
- Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type() == controlledType && !u.dead);
+ Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type == controlledType && !u.dead);
if(unit == null && controlledType == UnitTypes.block){
- unit = world.buildWorld(player.x, player.y) instanceof ControlBlock ? ((ControlBlock)world.buildWorld(player.x, player.y)).unit() : null;
+ unit = world.buildWorld(player.x, player.y) instanceof ControlBlock cont && cont.canControl() ? cont.unit() : null;
}
if(unit != null){
@@ -437,7 +443,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
Unit unit = player.unit();
if(!(unit instanceof Payloadc pay)) return;
- Unit target = Units.closest(player.team(), pay.x(), pay.y(), unit.type().hitSize * 2.5f, u -> u.isAI() && u.isGrounded() && pay.canPickup(u) && u.within(unit, u.hitSize + unit.hitSize * 1.2f));
+ Unit target = Units.closest(player.team(), pay.x(), pay.y(), unit.type.hitSize * 2.5f, u -> u.isAI() && u.isGrounded() && pay.canPickup(u) && u.within(unit, u.hitSize + unit.hitSize * 1.2f));
if(target != null){
Call.requestUnitPayload(player, target);
}else{
@@ -568,8 +574,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
wx = wy;
wy = -x;
}
- req.x = world.toTile(wx - req.block.offset) + ox;
- req.y = world.toTile(wy - req.block.offset) + oy;
+ req.x = World.toTile(wx - req.block.offset) + ox;
+ req.y = World.toTile(wy - req.block.offset) + oy;
req.rotation = Mathf.mod(req.rotation + direction, 4);
});
}
@@ -934,11 +940,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
int rawTileX(){
- return world.toTile(Core.input.mouseWorld().x);
+ return World.toTile(Core.input.mouseWorld().x);
}
int rawTileY(){
- return world.toTile(Core.input.mouseWorld().y);
+ return World.toTile(Core.input.mouseWorld().y);
}
int tileX(float cursorX){
@@ -946,7 +952,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
if(selectedBlock()){
vec.sub(block.offset, block.offset);
}
- return world.toTile(vec.x);
+ return World.toTile(vec.x);
}
int tileY(float cursorY){
@@ -954,7 +960,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
if(selectedBlock()){
vec.sub(block.offset, block.offset);
}
- return world.toTile(vec.y);
+ return World.toTile(vec.y);
}
public boolean selectedBlock(){
@@ -984,8 +990,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
Building tile = world.buildWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y);
- if(tile instanceof ControlBlock && tile.team == player.team()){
- return ((ControlBlock)tile).unit();
+ if(tile instanceof ControlBlock cont && cont.canControl() && tile.team == player.team()){
+ return cont.unit();
}
return null;
diff --git a/core/src/mindustry/input/MobileInput.java b/core/src/mindustry/input/MobileInput.java
index 19f458ea88..63df6c151b 100644
--- a/core/src/mindustry/input/MobileInput.java
+++ b/core/src/mindustry/input/MobileInput.java
@@ -14,6 +14,7 @@ import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.entities.*;
import mindustry.entities.units.*;
import mindustry.game.EventType.*;
@@ -23,6 +24,7 @@ import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
+import mindustry.world.blocks.*;
import static mindustry.Vars.*;
import static mindustry.input.PlaceMode.*;
@@ -85,7 +87,7 @@ public class MobileInput extends InputHandler implements GestureListener{
if(tile != null && player.team().isEnemy(tile.team)){
player.miner().mineTile(null);
target = tile;
- }else if(tile != null && player.unit().type().canHeal && tile.team == player.team() && tile.damaged()){
+ }else if(tile != null && player.unit().type.canHeal && tile.team == player.team() && tile.damaged()){
player.miner().mineTile(null);
target = tile;
}
@@ -405,14 +407,14 @@ public class MobileInput extends InputHandler implements GestureListener{
protected int schemOriginX(){
Tmp.v1.setZero();
selectRequests.each(r -> Tmp.v1.add(r.drawx(), r.drawy()));
- return world.toTile(Tmp.v1.scl(1f / selectRequests.size).x);
+ return World.toTile(Tmp.v1.scl(1f / selectRequests.size).x);
}
@Override
protected int schemOriginY(){
Tmp.v1.setZero();
selectRequests.each(r -> Tmp.v1.add(r.drawx(), r.drawy()));
- return world.toTile(Tmp.v1.scl(1f / selectRequests.size).y);
+ return World.toTile(Tmp.v1.scl(1f / selectRequests.size).y);
}
@Override
@@ -834,10 +836,10 @@ public class MobileInput extends InputHandler implements GestureListener{
protected void updateMovement(Unit unit){
Rect rect = Tmp.r3;
- UnitType type = unit.type();
+ UnitType type = unit.type;
if(type == null) return;
- boolean omni = unit.type().omniMovement;
+ boolean omni = unit.type.omniMovement;
boolean legs = unit.isGrounded();
boolean allowHealing = type.canHeal;
boolean validHealTarget = allowHealing && target instanceof Building && ((Building)target).isValid() && target.team() == unit.team &&
@@ -855,7 +857,7 @@ public class MobileInput extends InputHandler implements GestureListener{
float attractDst = 15f;
float strafePenalty = legs ? 1f : Mathf.lerp(1f, type.strafePenalty, Angles.angleDist(unit.vel.angle(), unit.rotation) / 180f);
- float baseSpeed = unit.type().speed;
+ float baseSpeed = unit.type.speed;
//limit speed to minimum formation speed to preserve formation
if(unit.isCommanding()){
@@ -863,7 +865,7 @@ public class MobileInput extends InputHandler implements GestureListener{
baseSpeed = unit.minFormationSpeed * 0.98f;
}
- float speed = baseSpeed * Mathf.lerp(1f, unit.isCommanding() ? 1f : type.canBoost ? type.boostMultiplier : 1f, unit.elevation) * strafePenalty;
+ float speed = baseSpeed * Mathf.lerp(1f, type.canBoost ? type.boostMultiplier : 1f, unit.elevation) * strafePenalty;
float range = unit.hasWeapons() ? unit.range() : 0f;
float bulletSpeed = unit.hasWeapons() ? type.weapons.first().bullet.speed : 0f;
float mouseAngle = unit.angleTo(unit.aimX(), unit.aimY());
@@ -935,7 +937,7 @@ public class MobileInput extends InputHandler implements GestureListener{
unit.aim(player.mouseX = Core.input.mouseWorldX(), player.mouseY = Core.input.mouseWorldY());
}else if(target == null){
player.shooting = false;
- if(Core.settings.getBool("autotarget")){
+ if(Core.settings.getBool("autotarget") && !(player.unit() instanceof BlockUnitUnit u && u.tile() instanceof ControlBlock c && !c.shouldAutoTarget())){
target = Units.closestTarget(unit.team, unit.x, unit.y, range, u -> u.team != Team.derelict, u -> u.team != Team.derelict);
if(allowHealing && target == null){
diff --git a/core/src/mindustry/io/JsonIO.java b/core/src/mindustry/io/JsonIO.java
index 39c3a1a821..eb3815ba76 100644
--- a/core/src/mindustry/io/JsonIO.java
+++ b/core/src/mindustry/io/JsonIO.java
@@ -165,6 +165,18 @@ public class JsonIO{
}
});
+ json.setSerializer(UnitType.class, new Serializer<>(){
+ @Override
+ public void write(Json json, UnitType object, Class knownType){
+ json.writeValue(object.name);
+ }
+
+ @Override
+ public UnitType read(Json json, JsonValue jsonData, Class type){
+ return Vars.content.getByName(ContentType.unit, jsonData.asString());
+ }
+ });
+
json.setSerializer(ItemStack.class, new Serializer<>(){
@Override
public void write(Json json, ItemStack object, Class knownType){
diff --git a/core/src/mindustry/io/SaveMeta.java b/core/src/mindustry/io/SaveMeta.java
index f2e039f634..c6133889bc 100644
--- a/core/src/mindustry/io/SaveMeta.java
+++ b/core/src/mindustry/io/SaveMeta.java
@@ -14,12 +14,10 @@ public class SaveMeta{
public Map map;
public int wave;
public Rules rules;
- public SectorInfo secinfo;
public StringMap tags;
public String[] mods;
- public boolean hasProduction;
- public SaveMeta(int version, long timestamp, long timePlayed, int build, String map, int wave, Rules rules, SectorInfo secinfo, StringMap tags){
+ public SaveMeta(int version, long timestamp, long timePlayed, int build, String map, int wave, Rules rules, StringMap tags){
this.version = version;
this.build = build;
this.timestamp = timestamp;
@@ -29,8 +27,5 @@ public class SaveMeta{
this.rules = rules;
this.tags = tags;
this.mods = JsonIO.read(String[].class, tags.get("mods", "[]"));
- this.secinfo = secinfo;
-
- secinfo.production.each((e, amount) -> hasProduction |= amount.mean > 0.001f);
}
}
diff --git a/core/src/mindustry/io/SaveVersion.java b/core/src/mindustry/io/SaveVersion.java
index cacac7700a..b76a5156e8 100644
--- a/core/src/mindustry/io/SaveVersion.java
+++ b/core/src/mindustry/io/SaveVersion.java
@@ -40,7 +40,6 @@ public abstract class SaveVersion extends SaveFileReader{
map.get("mapname"),
map.getInt("wave"),
JsonIO.read(Rules.class, map.get("rules", "{}")),
- JsonIO.read(SectorInfo.class, map.get("secinfo", "{}")),
map
);
}
@@ -74,6 +73,7 @@ public abstract class SaveVersion extends SaveFileReader{
//prepare campaign data for writing
if(state.isCampaign()){
state.secinfo.prepare();
+ state.rules.sector.saveInfo();
}
//flush tech node progress
@@ -89,7 +89,6 @@ public abstract class SaveVersion extends SaveFileReader{
"wave", state.wave,
"wavetime", state.wavetime,
"stats", JsonIO.write(state.stats),
- "secinfo", state.isCampaign() ? JsonIO.write(state.secinfo) : "{}",
"rules", JsonIO.write(state.rules),
"mods", JsonIO.write(mods.getModStrings().toArray(String.class)),
"width", world.width(),
@@ -106,15 +105,14 @@ public abstract class SaveVersion extends SaveFileReader{
state.wave = map.getInt("wave");
state.wavetime = map.getFloat("wavetime", state.rules.waveSpacing);
- state.stats = JsonIO.read(Stats.class, map.get("stats", "{}"));
- state.secinfo = JsonIO.read(SectorInfo.class, map.get("secinfo", "{}"));
+ state.stats = JsonIO.read(GameStats.class, map.get("stats", "{}"));
state.rules = JsonIO.read(Rules.class, map.get("rules", "{}"));
if(state.rules.spawns.isEmpty()) state.rules.spawns = defaultWaves.get();
lastReadBuild = map.getInt("build", -1);
- //load time spent on sector into state
+ //load in sector info
if(state.rules.sector != null){
- state.secinfo.internalTimeSpent = state.rules.sector.getStoredTimeSpent();
+ state.secinfo = state.rules.sector.info;
}
if(!headless){
diff --git a/core/src/mindustry/io/TypeIO.java b/core/src/mindustry/io/TypeIO.java
index 669cd65d53..2c2c19dcfc 100644
--- a/core/src/mindustry/io/TypeIO.java
+++ b/core/src/mindustry/io/TypeIO.java
@@ -185,7 +185,7 @@ public class TypeIO{
return unit == null ? Nulls.unit : unit;
}else if(type == 1){ //block
Building tile = world.build(id);
- return tile instanceof ControlBlock ? ((ControlBlock)tile).unit() : Nulls.unit;
+ return tile instanceof ControlBlock cont ? cont.unit() : Nulls.unit;
}
return Nulls.unit;
}
@@ -450,6 +450,16 @@ public class TypeIO{
return color.set(read.i());
}
+ public static void writeContent(Writes write, Content cont){
+ write.b(cont.getContentType().ordinal());
+ write.s(cont.id);
+ }
+
+ public static Content readContent(Reads read){
+ byte id = read.b();
+ return content.getByID(ContentType.all[id], read.s());
+ }
+
public static void writeLiquid(Writes write, Liquid liquid){
write.s(liquid == null ? -1 : liquid.id);
}
diff --git a/core/src/mindustry/io/legacy/LegacyIO.java b/core/src/mindustry/io/legacy/LegacyIO.java
index 545487d8ca..0bb84f3fc7 100644
--- a/core/src/mindustry/io/legacy/LegacyIO.java
+++ b/core/src/mindustry/io/legacy/LegacyIO.java
@@ -2,6 +2,8 @@ package mindustry.io.legacy;
import arc.*;
import arc.struct.*;
+import mindustry.*;
+import mindustry.ctype.*;
import mindustry.ui.dialogs.JoinDialog.*;
import java.io.*;
@@ -48,4 +50,35 @@ public class LegacyIO{
return arr;
}
+ public static void readResearch(){
+ try{
+ byte[] bytes = Core.settings.getBytes("unlocks");
+ DataInputStream stream = new DataInputStream(new ByteArrayInputStream(bytes));
+
+ int length = stream.readInt();
+ if(length > 0){
+ stream.readUTF(); //name of key type
+ stream.readUTF(); //name of value type
+
+ //each element is an array list
+ for(int i = 0; i < length; i++){
+ ContentType type = ContentType.all[stream.readInt()];
+ int arrLength = stream.readInt();
+ if(arrLength > 0){
+ stream.readUTF(); //type of contents (String)
+ for(int j = 0; j < arrLength; j++){
+ String name = stream.readUTF();
+ Content out = Vars.content.getByName(type, name);
+ if(out instanceof UnlockableContent u){
+ u.unlock();
+ }
+ }
+ }
+ }
+ }
+ }catch(Exception e){
+ e.printStackTrace();
+ }
+ }
+
}
diff --git a/core/src/mindustry/logic/Controllable.java b/core/src/mindustry/logic/Controllable.java
index 3785eae4b6..025559b4b9 100644
--- a/core/src/mindustry/logic/Controllable.java
+++ b/core/src/mindustry/logic/Controllable.java
@@ -1,7 +1,10 @@
package mindustry.logic;
+import mindustry.game.*;
+
/** An object that can be controlled with logic. */
public interface Controllable{
void control(LAccess type, double p1, double p2, double p3, double p4);
void control(LAccess type, Object p1, double p2, double p3, double p4);
+ Team team();
}
diff --git a/core/src/mindustry/logic/LAccess.java b/core/src/mindustry/logic/LAccess.java
index 5dc881a778..0d678554d1 100644
--- a/core/src/mindustry/logic/LAccess.java
+++ b/core/src/mindustry/logic/LAccess.java
@@ -15,6 +15,8 @@ public enum LAccess{
powerNetCapacity,
powerNetIn,
powerNetOut,
+ ammo,
+ ammoCapacity,
health,
maxHealth,
heat,
diff --git a/core/src/mindustry/logic/LAssembler.java b/core/src/mindustry/logic/LAssembler.java
index 4f72d121aa..57c2004320 100644
--- a/core/src/mindustry/logic/LAssembler.java
+++ b/core/src/mindustry/logic/LAssembler.java
@@ -189,16 +189,28 @@ public class LAssembler{
return putConst("___" + symbol, symbol.substring(1, symbol.length() - 1).replace("\\n", "\n")).id;
}
+ //remove spaces for non-strings
+ symbol = symbol.replace(' ', '_');
+
try{
- double value = Double.parseDouble(symbol);
+ double value = parseDouble(symbol);
+ if(Double.isNaN(value) || Double.isInfinite(value)) value = 0;
+
//this creates a hidden const variable with the specified value
- String key = "___" + value;
- return putConst(key, value).id;
+ return putConst("___" + value, value).id;
}catch(NumberFormatException e){
return putVar(symbol).id;
}
}
+ double parseDouble(String symbol) throws NumberFormatException{
+ //parse hex/binary syntax
+ if(symbol.startsWith("0b")) return Long.parseLong(symbol.substring(2), 2);
+ if(symbol.startsWith("0x")) return Long.parseLong(symbol.substring(2), 16);
+
+ return Double.parseDouble(symbol);
+ }
+
/** Adds a constant value by name. */
public BVar putConst(String name, Object value){
BVar var = putVar(name);
diff --git a/core/src/mindustry/logic/LCanvas.java b/core/src/mindustry/logic/LCanvas.java
index ed98bee8ff..e16aab6621 100644
--- a/core/src/mindustry/logic/LCanvas.java
+++ b/core/src/mindustry/logic/LCanvas.java
@@ -305,7 +305,7 @@ public class LCanvas extends Table{
statements.finishLayout();
}
});
- }).growX();
+ }).growX().height(38);
row();
diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java
index 3bcfaf46ee..be029c2305 100644
--- a/core/src/mindustry/logic/LExecutor.java
+++ b/core/src/mindustry/logic/LExecutor.java
@@ -7,9 +7,11 @@ import arc.util.noise.*;
import mindustry.*;
import mindustry.ai.types.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.entities.*;
import mindustry.game.*;
+import mindustry.game.Teams.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.*;
@@ -45,6 +47,7 @@ public class LExecutor{
public LongSeq graphicsBuffer = new LongSeq();
public StringBuilder textBuffer = new StringBuilder();
public Building[] links = {};
+ public IntSet linkIds = new IntSet();
public Team team = Team.derelict;
public boolean initialized(){
@@ -109,12 +112,12 @@ public class LExecutor{
public double num(int index){
Var v = vars[index];
- return v.isobj ? v.objval != null ? 1 : 0 : v.numval;
+ return v.isobj ? v.objval != null ? 1 : 0 : Double.isNaN(v.numval) || Double.isInfinite(v.numval) ? 0 : v.numval;
}
public float numf(int index){
Var v = vars[index];
- return v.isobj ? v.objval != null ? 1 : 0 : (float)v.numval;
+ return v.isobj ? v.objval != null ? 1 : 0 : Double.isNaN(v.numval) || Double.isInfinite(v.numval) ? 0 : (float)v.numval;
}
public int numi(int index){
@@ -128,7 +131,7 @@ public class LExecutor{
public void setnum(int index, double value){
Var v = vars[index];
if(v.constant) return;
- v.numval = value;
+ v.numval = Double.isNaN(value) || Double.isInfinite(value) ? 0 : value;
v.objval = null;
v.isobj = false;
}
@@ -210,9 +213,9 @@ public class LExecutor{
public LLocate locate = LLocate.building;
public BlockFlag flag = BlockFlag.core;
public int enemy, ore;
- public int outX, outY, outFound;
+ public int outX, outY, outFound, outBuild;
- public UnitLocateI(LLocate locate, BlockFlag flag, int enemy, int ore, int outX, int outY, int outFound){
+ public UnitLocateI(LLocate locate, BlockFlag flag, int enemy, int ore, int outX, int outY, int outFound, int outBuild){
this.locate = locate;
this.flag = flag;
this.enemy = enemy;
@@ -262,13 +265,14 @@ public class LExecutor{
if(res != null && (!build || res.build != null)){
cache.found = true;
//set result if found
- exec.setnum(outX, cache.x = build ? res.build.x : res.worldx());
- exec.setnum(outY, cache.y = build ? res.build.y : res.worldy());
+ exec.setnum(outX, cache.x = World.conv(build ? res.build.x : res.worldx()));
+ exec.setnum(outY, cache.y = World.conv(build ? res.build.y : res.worldy()));
exec.setnum(outFound, 1);
}else{
cache.found = false;
exec.setnum(outFound, 0);
}
+ exec.setobj(outFound, res != null && res.build != null && res.build.team == exec.team ? res.build : null);
}else{
exec.setbool(outFound, cache.found);
exec.setnum(outX, cache.x);
@@ -331,14 +335,15 @@ public class LExecutor{
//only control standard AI units
if(unitObj instanceof Unit unit && ai != null){
ai.controlTimer = LogicAI.logicControlTimeout;
+ float x1 = World.unconv(exec.numf(p1)), y1 = World.unconv(exec.numf(p2)), d1 = World.unconv(exec.numf(p3));
switch(type){
case move, stop, approach -> {
ai.control = type;
- ai.moveX = exec.numf(p1);
- ai.moveY = exec.numf(p2);
+ ai.moveX = x1;
+ ai.moveY = y1;
if(type == LUnitControl.approach){
- ai.moveRad = exec.numf(p3);
+ ai.moveRad = d1;
}
//stop mining/building
@@ -352,13 +357,13 @@ public class LExecutor{
}
}
case within -> {
- exec.setnum(p4, unit.within(exec.numf(p1), exec.numf(p2), exec.numf(p3)) ? 1 : 0);
+ exec.setnum(p4, unit.within(x1, y1, d1) ? 1 : 0);
}
case pathfind -> {
ai.control = type;
}
case target -> {
- ai.posTarget.set(exec.numf(p1), exec.numf(p2));
+ ai.posTarget.set(x1, y1);
ai.aimControl = type;
ai.mainTarget = null;
ai.shoot = exec.bool(p3);
@@ -375,7 +380,7 @@ public class LExecutor{
unit.flag = exec.num(p1);
}
case mine -> {
- Tile tile = world.tileWorld(exec.numf(p1), exec.numf(p2));
+ Tile tile = world.tileWorld(x1, y1);
if(unit instanceof Minerc miner){
miner.mineTile(miner.validMine(tile) ? tile : null);
}
@@ -394,7 +399,7 @@ public class LExecutor{
if(unit instanceof Payloadc pay){
//units
if(exec.bool(p1)){
- Unit result = Units.closest(unit.team, unit.x, unit.y, unit.type().hitSize * 2f, u -> u.isAI() && u.isGrounded() && pay.canPickup(u) && u.within(unit, u.hitSize + unit.hitSize * 1.2f));
+ Unit result = Units.closest(unit.team, unit.x, unit.y, unit.type.hitSize * 2f, u -> u.isAI() && u.isGrounded() && pay.canPickup(u) && u.within(unit, u.hitSize + unit.hitSize * 1.2f));
if(result != null){
Call.pickedUnitPayload(unit, result);
@@ -419,7 +424,7 @@ public class LExecutor{
}
case build -> {
if(unit instanceof Builderc builder && exec.obj(p3) instanceof Block block){
- int x = world.toTile(exec.numf(p1)), y = world.toTile(exec.numf(p2));
+ int x = World.toTile(x1), y = World.toTile(y1);
int rot = exec.numi(p4);
//reset state of last request when necessary
@@ -432,25 +437,25 @@ public class LExecutor{
ai.plan.set(x, y, rot, block);
ai.plan.config = null;
+ builder.clearBuilding();
+
if(ai.plan.tile() != null){
- builder.clearBuilding();
builder.updateBuilding(true);
builder.addBuild(ai.plan);
}
}
}
case getBlock -> {
- float x = exec.numf(p1), y = exec.numf(p2);
float range = Math.max(unit.range(), buildingRange);
- if(!unit.within(x, y, range)){
+ if(!unit.within(x1, y1, range)){
exec.setobj(p3, null);
- exec.setnum(p4, 0);
+ exec.setobj(p4, null);
}else{
- Tile tile = world.tileWorld(x, y);
+ Tile tile = world.tileWorld(x1, y1);
//any environmental solid block is returned as StoneWall, aka "@solid"
Block block = tile == null ? null : !tile.synthetic() ? (tile.solid() ? Blocks.stoneWall : Blocks.air) : tile.block();
exec.setobj(p3, block);
- exec.setnum(p4, tile != null && tile.build != null ? tile.build.rotation : 0);
+ exec.setobj(p4, tile != null && tile.build != null ? tile.build : null);
}
}
case itemDrop -> {
@@ -508,11 +513,11 @@ public class LExecutor{
@Override
public void run(LExecutor exec){
Object obj = exec.obj(target);
- if(obj instanceof Controllable cont){
+ if(obj instanceof Building b && b.team == exec.team && exec.linkIds.contains(b.id)){
if(type.isObj){
- cont.control(type, exec.obj(p1), exec.num(p2), exec.num(p3), exec.num(p4));
+ b.control(type, exec.obj(p1), exec.num(p2), exec.num(p3), exec.num(p4));
}else{
- cont.control(type, exec.num(p1), exec.num(p2), exec.num(p3), exec.num(p4));
+ b.control(type, exec.num(p1), exec.num(p2), exec.num(p3), exec.num(p4));
}
}
}
@@ -605,6 +610,7 @@ public class LExecutor{
Object target = exec.obj(from);
Object sense = exec.obj(type);
+ //TODO should remote enemy buildings be senseable?
if(target instanceof Senseable se){
if(sense instanceof Content){
exec.setnum(to, se.sense(((Content)sense)));
@@ -674,8 +680,11 @@ public class LExecutor{
bestValue = 0;
if(enemies){
- for(Team enemy : state.teams.enemiesOf(r.team())){
- find(r, range, sortDir, enemy);
+ Seq data = state.teams.present;
+ for(int i = 0; i < data.size; i++){
+ if(data.items[i].team != r.team()){
+ find(r, range, sortDir, data.items[i].team);
+ }
}
}else{
find(r, range, sortDir, r.team());
@@ -733,7 +742,7 @@ public class LExecutor{
v.objval = f.objval;
v.isobj = true;
}else{
- v.numval = f.numval;
+ v.numval = Double.isNaN(f.numval) || Double.isInfinite(f.numval) ? 0 : f.numval;
v.isobj = false;
}
}
diff --git a/core/src/mindustry/logic/LStatements.java b/core/src/mindustry/logic/LStatements.java
index ba4d31e9a1..517d53bcc6 100644
--- a/core/src/mindustry/logic/LStatements.java
+++ b/core/src/mindustry/logic/LStatements.java
@@ -704,7 +704,7 @@ public class LStatements{
@RegisterStatement("ubind")
public static class UnitBindStatement extends LStatement{
- public String type = "@mono";
+ public String type = "@poly";
@Override
public void build(Table table){
@@ -819,7 +819,7 @@ public class LStatements{
public LLocate locate = LLocate.building;
public BlockFlag flag = BlockFlag.core;
public String enemy = "true", ore = "@copper";
- public String outX = "outx", outY = "outy", outFound = "found";
+ public String outX = "outx", outY = "outy", outFound = "found", outBuild = "building";
@Override
public void build(Table table){
@@ -905,6 +905,8 @@ public class LStatements{
table.add(" found ").left();
fields(table, outFound, str -> outFound = str);
+ table.add(" building ").left();
+ fields(table, outBuild, str -> outBuild = str);
}
@@ -915,7 +917,7 @@ public class LStatements{
@Override
public LInstruction build(LAssembler builder){
- return new UnitLocateI(locate, flag, builder.var(enemy), builder.var(ore), builder.var(outX), builder.var(outY), builder.var(outFound));
+ return new UnitLocateI(locate, flag, builder.var(enemy), builder.var(ore), builder.var(outX), builder.var(outY), builder.var(outFound), builder.var(outBuild));
}
}
}
diff --git a/core/src/mindustry/logic/LUnitControl.java b/core/src/mindustry/logic/LUnitControl.java
index 2166b00690..b4c7f8254c 100644
--- a/core/src/mindustry/logic/LUnitControl.java
+++ b/core/src/mindustry/logic/LUnitControl.java
@@ -15,7 +15,7 @@ public enum LUnitControl{
mine("x", "y"),
flag("value"),
build("x", "y", "block", "rotation"),
- getBlock("x", "y", "result", "resRot"),
+ getBlock("x", "y", "type", "building"),
within("x", "y", "radius", "result");
public final String[] params;
diff --git a/core/src/mindustry/maps/Map.java b/core/src/mindustry/maps/Map.java
index edef90cea7..0fdc818139 100644
--- a/core/src/mindustry/maps/Map.java
+++ b/core/src/mindustry/maps/Map.java
@@ -98,7 +98,9 @@ public class Map implements Comparable