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 209775b7f6..13f620832f 100644
--- a/README.md
+++ b/README.md
@@ -50,13 +50,6 @@ To debug the application on a connected phone, run `gradlew android:installDebug
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.*
-#### Can not attach to current VM / Error during attachment using [...]
-
-This is a problem related to [Jabel](https://github.com/bsideup/jabel), which I use to compile Java 8-compatible bytecode while using Java 9+ language features.
-I don't know of a complete fix to this issue. However, if you're getting the error when running through IntelliJ, a workaround is to launch through Gradle *once*, which starts a daemon and avoids the problem in future runs through IntelliJ.
-
-
-
---
Gradle may take up to several minutes to download files. Be patient.
diff --git a/annotations/src/main/java/mindustry/annotations/BaseProcessor.java b/annotations/src/main/java/mindustry/annotations/BaseProcessor.java
index 710bef22ca..3cf9ac44b0 100644
--- a/annotations/src/main/java/mindustry/annotations/BaseProcessor.java
+++ b/annotations/src/main/java/mindustry/annotations/BaseProcessor.java
@@ -204,10 +204,10 @@ public abstract class BaseProcessor extends AbstractProcessor{
context = ((JavacProcessingEnvironment)env).getContext();
maker = TreeMaker.instance(javacProcessingEnv.getContext());
- Log.setLogLevel(LogLevel.info);
+ Log.level = LogLevel.info;
if(System.getProperty("debug") != null){
- Log.setLogLevel(LogLevel.debug);
+ Log.level = LogLevel.debug;
}
}
diff --git a/build.gradle b/build.gradle
index e54f6b56b2..c94a79598a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -262,6 +262,8 @@ project(":ios"){
project(":core"){
apply plugin: "java-library"
+ compileJava.options.fork = true
+
task preGen{
outputs.upToDateWhen{ false }
generateLocales()
@@ -303,7 +305,7 @@ project(":core"){
compileOnly project(":annotations")
annotationProcessor project(":annotations")
- annotationProcessor 'com.github.Anuken:jabel:40eec868af'
+ annotationProcessor 'com.github.Anuken:jabel:34e4c172e65b3928cd9eabe1993654ea79c409cd'
}
}
diff --git a/core/assets/baseparts/1603214918168.msch b/core/assets/baseparts/1603214918168.msch
new file mode 100644
index 0000000000..6d69a2c362
--- /dev/null
+++ b/core/assets/baseparts/1603214918168.msch
@@ -0,0 +1,2 @@
+mschx5
+!Ey-J(qG&'.}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 196b6e87af..3e88aef2e1 100644
--- a/core/assets/bundles/bundle.properties
+++ b/core/assets/bundles/bundle.properties
@@ -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:
@@ -581,50 +582,64 @@ 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
bar.drilltierreq = Better Drill Required
bar.noresources = Missing Resources
@@ -875,6 +890,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
@@ -896,23 +912,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
@@ -1324,5 +1323,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 8bcd567380..f9f98951dc 100644
--- a/core/assets/bundles/bundle_cs.properties
+++ b/core/assets/bundles/bundle_cs.properties
@@ -572,50 +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.memorycapacity = Kapacita paměti
-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
@@ -1312,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 500f40bc20..976b74c885 100644
--- a/core/assets/bundles/bundle_es.properties
+++ b/core/assets/bundles/bundle_es.properties
@@ -569,6 +569,7 @@ no = No
info.title = [accent]Información
error.title = [crimson]Un error ha ocurrido.
error.crashtitle = Un error ha ocurrido.
+
unit.nobuild = [scarlet]Unidad no puede construir
blocks.input = Entrada
blocks.output = Salida
@@ -614,6 +615,7 @@ blocks.ammo = Munición
blocks.shieldhealth = Vida del escudo
blocks.cooldowntime = Tiempo de Enfriamiento
+
bar.drilltierreq = Se requiere un mejor taladro.
bar.noresources = Recursos faltantes
bar.corereq = Base de núcleo requerida
@@ -1303,3 +1305,4 @@ block.spectre.description = Un cañon masivo de dos barriles. Dispara balas perf
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 = Daña y destruye los proyectiles entrantes. Los proyectiles láser no están dirigidos.
+
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 d601b9e904..e9f6f933eb 100644
--- a/core/assets/bundles/bundle_in_ID.properties
+++ b/core/assets/bundles/bundle_in_ID.properties
@@ -572,50 +572,50 @@ info.title = Info
error.title = [crimson]Sebuah kesalahan telah terjadi
error.crashtitle = Sebuah kesalahan telah terjadi
unit.nobuild = [scarlet]Unit tidak dapat membangun
-blocks.input = Masukan
-blocks.output = Pengeluaran
-blocks.booster = Pendorong
-blocks.tiles = Kotak yang dibutuhkan
-blocks.affinities = Afinitas
+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 = Ukuran Tampilan
-blocks.liquidcapacity = Kapasitas Zat Cair
-blocks.powerrange = Jarak Tenaga
-blocks.linkrange = Jarak Tautan
-blocks.instructions = Instruksi
-blocks.powerconnections = Koneksi Maksimal
-blocks.poweruse = Penggunaan Tenaga
-blocks.powerdamage = Tenaga/Pukulan
-blocks.itemcapacity = Kapasitas Item
-blocks.memorycapacity = Kapasitas Memori
-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 = Sumber Daya Tidak Ditemukan
@@ -1310,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 = Merusakkan dan menghancurkan proyektil yang datang. Proyektil laser tidak akan ditargetkan.
+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 f03ff17264..82bb299642 100644
--- a/core/assets/bundles/bundle_ko.properties
+++ b/core/assets/bundles/bundle_ko.properties
@@ -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 = 보호막 체력
-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 = 자원 부족
@@ -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 c2d8b20dcf..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
@@ -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 = Destrói projéteis inimigos. Projéteis de laser não são afetados.
+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 053fbdc7d7..aa9fd2f18d 100644
--- a/core/assets/bundles/bundle_ro.properties
+++ b/core/assets/bundles/bundle_ro.properties
@@ -569,50 +569,50 @@ error.title = [scarlet]A apărut o eroare.
error.crashtitle = A apărut o eroare.
unit.nobuild = [scarlet]Unitatea nu poate construi.
lastaccessed = [lightgray]Ultima Accesare: {0}
-blocks.input = Necesită
-blocks.output = Produce
-blocks.booster = Booster
-blocks.tiles = Teren Necesar
-blocks.affinities = Efecte Teren
+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.memorycapacity = Capacitate Memorie
-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ă
@@ -1311,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 1e12db9ee4..078a1cf6f4 100644
--- a/core/assets/bundles/bundle_ru.properties
+++ b/core/assets/bundles/bundle_ru.properties
@@ -576,50 +576,50 @@ error.title = [scarlet]Произошла ошибка
error.crashtitle = Произошла ошибка
unit.nobuild = [scarlet]Боевая единица не может строить
lastaccessed = [lightgray]Последняя конфигурация от {0}
-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.memorycapacity = Размер памяти
-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 = Прочность щита
-blocks.cooldowntime = Время восстановления
+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 = Недостаточно ресурсов
@@ -1321,5 +1321,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_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 05deecc5b3..dfc4bae48b 100644
--- a/core/assets/bundles/bundle_uk_UA.properties
+++ b/core/assets/bundles/bundle_uk_UA.properties
@@ -565,50 +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.memorycapacity = Ємність пам’яті
-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 = Міцність щита
-blocks.cooldowntime = Тривалість охолодження
+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 = Бракує ресурсів
@@ -1300,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 5c5c529ae2..5744d3d0fd 100644
--- a/core/assets/bundles/bundle_zh_CN.properties
+++ b/core/assets/bundles/bundle_zh_CN.properties
@@ -570,49 +570,49 @@ 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 = 显示尺寸
-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 = 盾容
-blocks.cooldowntime = 冷却时间
+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 = 缺失资源
@@ -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_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/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/mudFlats.msav b/core/assets/maps/mudFlats.msav
new file mode 100644
index 0000000000..0fb8fd21ab
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/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/src/mindustry/Vars.java b/core/src/mindustry/Vars.java
index 2653b55975..2cf07cbea6 100644
--- a/core/src/mindustry/Vars.java
+++ b/core/src/mindustry/Vars.java
@@ -89,7 +89,7 @@ public class Vars implements Loadable{
/** duration of time between turns in ticks */
public static final float turnDuration = 2 * Time.toMinutes;
/** chance of an invasion per turn, 1 = 100% */
- public static final float baseInvasionChance = 1f / 25f;
+ 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 */
@@ -285,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);
@@ -304,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));
@@ -319,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 b1f83d95d2..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;
@@ -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 6092c83910..a75b0758ea 100644
--- a/core/src/mindustry/ai/BlockIndexer.java
+++ b/core/src/mindustry/ai/BlockIndexer.java
@@ -8,6 +8,7 @@ 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.*;
@@ -179,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;
diff --git a/core/src/mindustry/ai/Pathfinder.java b/core/src/mindustry/ai/Pathfinder.java
index 0d8624baa3..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.*;
@@ -102,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;
@@ -111,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,
@@ -441,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())));
}
}
diff --git a/core/src/mindustry/ai/WaveSpawner.java b/core/src/mindustry/ai/WaveSpawner.java
index 91c7f61467..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.*;
@@ -48,7 +49,7 @@ public class WaveSpawner{
/** @return true if the player is near a ground spawn point. */
public boolean playerNear(){
- return state.rules.waves && !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(){
@@ -79,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);
}
});
}
@@ -100,12 +101,14 @@ public class WaveSpawner{
}
public void eachGroundSpawn(Intc2 cons){
- eachGroundSpawn((x, y, shock) -> cons.get(world.toTile(x), world.toTile(y)));
+ 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()){
@@ -118,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)){
diff --git a/core/src/mindustry/ai/types/FlyingAI.java b/core/src/mindustry/ai/types/FlyingAI.java
index 9d4c2d38f9..7262ae216a 100644
--- a/core/src/mindustry/ai/types/FlyingAI.java
+++ b/core/src/mindustry/ai/types/FlyingAI.java
@@ -16,7 +16,7 @@ public class FlyingAI extends AIController{
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);
diff --git a/core/src/mindustry/ai/types/FormationAI.java b/core/src/mindustry/ai/types/FormationAI.java
index ed175524d8..3226fbc300 100644
--- a/core/src/mindustry/ai/types/FormationAI.java
+++ b/core/src/mindustry/ai/types/FormationAI.java
@@ -94,7 +94,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 0134a424fc..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(){
@@ -57,19 +55,5 @@ public class GroundAI extends AIController{
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/content/Blocks.java b/core/src/mindustry/content/Blocks.java
index d18b011bea..8c2d6e2c8f 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.*;
@@ -792,14 +794,16 @@ public class Blocks implements ContentList{
phaseWall = new Wall("phase-wall"){{
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"){{
@@ -919,8 +923,8 @@ public class Blocks implements ContentList{
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;
@@ -1184,7 +1188,7 @@ public class Blocks implements ContentList{
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"){{
@@ -1353,7 +1357,7 @@ public class Blocks implements ContentList{
size = 5;
unitCapModifier = 20;
- researchCostMultiplier = 0.06f;
+ researchCostMultiplier = 0.05f;
}};
vault = new StorageBlock("vault"){{
@@ -1642,11 +1646,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"){{
@@ -1912,7 +1925,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}
);
diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java
index ca5bf9a0d0..5d0c45348d 100644
--- a/core/src/mindustry/content/Fx.java
+++ b/core/src/mindustry/content/Fx.java
@@ -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/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java
index b9189ec64e..f7ba45b156 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.*;
@@ -897,6 +898,7 @@ public class UnitTypes implements ContentList{
range = 140f;
faceTarget = false;
armor = 4f;
+ targetFlag = BlockFlag.factory;
weapons.add(new Weapon(){{
minShootVelocity = 0.75f;
@@ -977,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;
@@ -1051,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;
@@ -1196,7 +1200,6 @@ public class UnitTypes implements ContentList{
mineTier = 3;
health = 500;
- armor = 2f;
armor = 5f;
speed = 1.8f;
accel = 0.06f;
@@ -1246,6 +1249,7 @@ public class UnitTypes implements ContentList{
buildSpeed = 2.5f;
range = 140f;
targetAir = false;
+ targetFlag = BlockFlag.battery;
ammoType = AmmoTypes.powerHigh;
@@ -1650,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;
@@ -1665,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;
}};
}});
}};
@@ -1685,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;
@@ -1706,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;
}};
}});
}};
@@ -1726,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;
@@ -1745,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 0b789d14fd..e24881692f 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.*;
@@ -250,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);
}
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/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 d9f944c1aa..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();
@@ -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 d6fcb40a97..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);
}
@@ -300,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");
@@ -310,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){
diff --git a/core/src/mindustry/ctype/UnlockableContent.java b/core/src/mindustry/ctype/UnlockableContent.java
index 21b72374ec..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,6 +112,14 @@ public abstract class UnlockableContent extends MappableContent{
}
}
+ /** 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;
diff --git a/core/src/mindustry/editor/EditorTile.java b/core/src/mindustry/editor/EditorTile.java
index 5ff533325d..2d08b9d3d2 100644
--- a/core/src/mindustry/editor/EditorTile.java
+++ b/core/src/mindustry/editor/EditorTile.java
@@ -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/MapGenerateDialog.java b/core/src/mindustry/editor/MapGenerateDialog.java
index fae31dc7d5..6a06e0b966 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){
}
};
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/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/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 6891744fce..84b6160d25 100644
--- a/core/src/mindustry/entities/comp/BuildingComp.java
+++ b/core/src/mindustry/entities/comp/BuildingComp.java
@@ -17,6 +17,7 @@ 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.*;
@@ -463,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);
@@ -546,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;
@@ -910,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;
@@ -1266,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;
@@ -1276,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;
diff --git a/core/src/mindustry/entities/comp/BulletComp.java b/core/src/mindustry/entities/comp/BulletComp.java
index d9aa007c5e..5a08710762 100644
--- a/core/src/mindustry/entities/comp/BulletComp.java
+++ b/core/src/mindustry/entities/comp/BulletComp.java
@@ -7,6 +7,7 @@ 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.*;
@@ -110,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 e03147d63c..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();
}
}
@@ -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);
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/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/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 d83408c734..a447bd633a 100644
--- a/core/src/mindustry/entities/comp/PuddleComp.java
+++ b/core/src/mindustry/entities/comp/PuddleComp.java
@@ -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 897305e87a..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.*;
@@ -88,14 +89,14 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
case rotation -> rotation;
case health -> health;
case maxHealth -> maxHealth;
- case ammo -> state.rules.unitAmmo ? type.ammoCapacity : ammo;
+ case ammo -> !state.rules.unitAmmo ? type.ammoCapacity : ammo;
case ammoCapacity -> type.ammoCapacity;
- case x -> x;
- case y -> y;
+ 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;
@@ -276,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 && state.rules.waves){
+ 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/game/DefaultWaves.java b/core/src/mindustry/game/DefaultWaves.java
index f3c98f9fb4..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){{
@@ -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){{
@@ -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){{
diff --git a/core/src/mindustry/game/EventType.java b/core/src/mindustry/game/EventType.java
index 0ffb2f7369..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{}
@@ -223,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;
@@ -256,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 99%
rename from core/src/mindustry/game/Stats.java
rename to core/src/mindustry/game/GameStats.java
index b963223518..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. */
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/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 f9e30f7d02..3b2b4df3dd 100644
--- a/core/src/mindustry/game/SectorInfo.java
+++ b/core/src/mindustry/game/SectorInfo.java
@@ -28,7 +28,7 @@ public class SectorInfo{
/** Items stored in all cores. */
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. */
diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java
index 30f0100b2d..9b1064a791 100644
--- a/core/src/mindustry/game/Universe.java
+++ b/core/src/mindustry/game/Universe.java
@@ -6,6 +6,7 @@ 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.*;
@@ -187,7 +188,7 @@ public class Universe{
}
//add production, making sure that it's capped
- sector.info.production.each((item, stat) -> sector.info.items.add(item, Math.min((int)(stat.mean * seconds * scl), sector.info.storageCapacity - sector.info.items.get(item))));
+ 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();
}
@@ -260,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/OverlayRenderer.java b/core/src/mindustry/graphics/OverlayRenderer.java
index 524ee79ea6..9bb3a95fa3 100644
--- a/core/src/mindustry/graphics/OverlayRenderer.java
+++ b/core/src/mindustry/graphics/OverlayRenderer.java
@@ -121,7 +121,7 @@ public class OverlayRenderer{
Lines.stroke(2f);
Draw.color(Color.gray, Color.lightGray, Mathf.absin(Time.time(), 8f, 1f));
- if(state.rules.waves){
+ 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));
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/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 e66f119f8f..906d96d56e 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()){
@@ -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 4a5c26eb9d..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.*;
@@ -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);
+ }
+ });
}
}
@@ -420,7 +426,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
if(controlledType != null){
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){
@@ -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 d5d45192b0..981f55bd6f 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.*;
@@ -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
@@ -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/SaveVersion.java b/core/src/mindustry/io/SaveVersion.java
index e153b74587..b76a5156e8 100644
--- a/core/src/mindustry/io/SaveVersion.java
+++ b/core/src/mindustry/io/SaveVersion.java
@@ -105,7 +105,7 @@ 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.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);
diff --git a/core/src/mindustry/io/TypeIO.java b/core/src/mindustry/io/TypeIO.java
index bba4ffeb0a..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;
}
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/LAssembler.java b/core/src/mindustry/logic/LAssembler.java
index f353a8c38c..57c2004320 100644
--- a/core/src/mindustry/logic/LAssembler.java
+++ b/core/src/mindustry/logic/LAssembler.java
@@ -189,17 +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/LExecutor.java b/core/src/mindustry/logic/LExecutor.java
index 124f3e0d50..6b4f9ced0a 100644
--- a/core/src/mindustry/logic/LExecutor.java
+++ b/core/src/mindustry/logic/LExecutor.java
@@ -7,6 +7,7 @@ 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.*;
@@ -46,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(){
@@ -211,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;
@@ -263,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);
@@ -332,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
@@ -353,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);
@@ -376,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);
}
@@ -420,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
@@ -441,17 +445,16 @@ public class LExecutor{
}
}
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 -> {
@@ -509,11 +512,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));
}
}
}
@@ -606,6 +609,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)));
diff --git a/core/src/mindustry/logic/LStatements.java b/core/src/mindustry/logic/LStatements.java
index ba4d31e9a1..57adbdb7fe 100644
--- a/core/src/mindustry/logic/LStatements.java
+++ b/core/src/mindustry/logic/LStatements.java
@@ -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/Maps.java b/core/src/mindustry/maps/Maps.java
index 7741f0942f..e6fcaff68a 100644
--- a/core/src/mindustry/maps/Maps.java
+++ b/core/src/mindustry/maps/Maps.java
@@ -29,7 +29,7 @@ import static mindustry.Vars.*;
public class Maps{
/** List of all built-in maps. Filenames only. */
- private static String[] defaultMapNames = {"maze", "fortress", "labyrinth", "islands", "tendrils", "caldera", "wasteland", "shattered", "fork", "triad", "veins", "glacier"};
+ private static String[] defaultMapNames = {"maze", "fortress", "labyrinth", "islands", "tendrils", "caldera", "wasteland", "shattered", "fork", "triad", "mudFlats", "veins", "glacier"};
/** Maps tagged as PvP */
static final String[] pvpMaps = {"veins", "glacier"};
/** All maps stored in an ordered array. */
@@ -82,9 +82,7 @@ public class Maps{
}
public Maps(){
- Events.on(ClientLoadEvent.class, event -> {
- maps.sort();
- });
+ Events.on(ClientLoadEvent.class, event -> maps.sort());
if(Core.assets != null){
((CustomLoader)Core.assets.getLoader(ContentLoader.class)).loaded = this::createAllPreviews;
diff --git a/core/src/mindustry/maps/SectorDamage.java b/core/src/mindustry/maps/SectorDamage.java
index 02e2c20016..b084f75c10 100644
--- a/core/src/mindustry/maps/SectorDamage.java
+++ b/core/src/mindustry/maps/SectorDamage.java
@@ -185,14 +185,18 @@ public class SectorDamage{
}
//create sparse tile array for fast range query
- int sparseSkip = 6;
+ int sparseSkip = 5, sparseSkip2 = 3;
//TODO if this is slow, use a quadtree
Seq sparse = new Seq<>(path.size / sparseSkip + 1);
+ Seq sparse2 = new Seq<>(path.size / sparseSkip2 + 1);
for(int i = 0; i < path.size; i++){
if(i % sparseSkip == 0){
sparse.add(path.get(i));
}
+ if(i % sparseSkip2 == 0){
+ sparse2.add(path.get(i));
+ }
}
//regen is in health per second
@@ -202,8 +206,11 @@ public class SectorDamage{
//first, calculate the total health of blocks in the path
- for(Tile t : path){
- int radius = 2;
+ //radius around the path that gets counted
+ int radius = 7;
+ IntSet counted = new IntSet();
+
+ for(Tile t : sparse2){
//radius is square.
for(int dx = -radius; dx <= radius; dx++){
@@ -212,7 +219,7 @@ public class SectorDamage{
if(wx >= 0 && wy >= 0 && wx < world.width() && wy < world.height()){
Tile tile = world.rawTile(wx, wy);
- if(tile.build != null && tile.team() == state.rules.defaultTeam){
+ if(tile.build != null && tile.team() == state.rules.defaultTeam && counted.add(tile.pos())){
//health is divided by block size, because multiblocks are counted multiple times.
sumHealth += tile.build.health / tile.block().size;
totalPathBuild += 1f / tile.block().size;
@@ -228,7 +235,7 @@ public class SectorDamage{
for(Building build : Groups.build){
float e = build.efficiency();
if(e > 0.08f){
- if(build.team == state.rules.defaultTeam && build instanceof Ranged ranged && sparse.contains(t -> t.within(build, ranged.range()))){
+ if(build.team == state.rules.defaultTeam && build instanceof Ranged ranged && sparse.contains(t -> t.within(build, ranged.range() + radius*tilesize))){
if(build.block instanceof Turret t && build instanceof TurretBuild b && b.hasAmmo()){
sumDps += t.shots / t.reloadTime * 60f * b.peekAmmo().estimateDPS() * e;
}
@@ -303,7 +310,8 @@ public class SectorDamage{
//enemy units like to aim for a lot of non-essential things, so increase resulting health slightly
info.sumHealth = sumHealth * 1.2f;
- info.sumDps = sumDps;
+ //players tend to have longer range units/turrets, so assume DPS is higher
+ info.sumDps = sumDps * 1.5f;
info.sumRps = sumRps;
//finally, find an equation to put it all together and produce a 0-1 number
diff --git a/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java b/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java
index 9065467dff..7e2b5e9aaa 100644
--- a/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java
+++ b/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java
@@ -414,7 +414,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
state.rules.attackMode = sector.info.attack = true;
}else{
- state.rules.winWave = sector.info.winWave = 15 * (int)Math.max(difficulty * 10, 1);
+ state.rules.winWave = sector.info.winWave = 10 + 5 * (int)Math.max(difficulty * 10, 1);
}
state.rules.waves = sector.info.waves = true;
diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java
index c8085ae8c8..0d88d01034 100644
--- a/core/src/mindustry/mod/ContentParser.java
+++ b/core/src/mindustry/mod/ContentParser.java
@@ -190,6 +190,7 @@ public class ContentParser{
"mindustry.world.blocks.defense",
"mindustry.world.blocks.defense.turrets",
"mindustry.world.blocks.distribution",
+ "mindustry.world.blocks.environment",
"mindustry.world.blocks.liquid",
"mindustry.world.blocks.logic",
"mindustry.world.blocks.power",
@@ -302,6 +303,20 @@ public class ContentParser{
return unit;
},
+ ContentType.weather, (TypeParser)(mod, name, value) -> {
+ Weather item;
+ if(locate(ContentType.weather, name) != null){
+ item = locate(ContentType.weather, name);
+ readBundle(ContentType.weather, name, value);
+ }else{
+ readBundle(ContentType.weather, name, value);
+ Class extends Weather> type = resolve(getType(value), "mindustry.type.weather");
+ item = make(type);
+ }
+ currentContent = item;
+ read(() -> readFields(item, value));
+ return item;
+ },
ContentType.item, parser(ContentType.item, Item::new),
ContentType.liquid, parser(ContentType.liquid, Liquid::new)
//ContentType.sector, parser(ContentType.sector, SectorPreset::new)
diff --git a/core/src/mindustry/mod/Scripts.java b/core/src/mindustry/mod/Scripts.java
index 1aa260e8fa..f372586863 100644
--- a/core/src/mindustry/mod/Scripts.java
+++ b/core/src/mindustry/mod/Scripts.java
@@ -59,12 +59,12 @@ public class Scripts implements Disposable{
if(o instanceof Undefined) o = "undefined";
return String.valueOf(o);
}catch(Throwable t){
- return getError(t);
+ return getError(t, false);
}
}
- private String getError(Throwable t){
- t.printStackTrace();
+ private String getError(Throwable t, boolean log){
+ if(log) Log.err(t);
return t.getClass().getSimpleName() + (t.getMessage() == null ? "" : ": " + t.getMessage());
}
@@ -138,7 +138,7 @@ public class Scripts implements Disposable{
if(currentMod != null){
file = currentMod.name + "/" + file;
}
- log(LogLevel.err, file, "" + getError(t));
+ log(LogLevel.err, file, "" + getError(t, true));
return false;
}
}
diff --git a/core/src/mindustry/net/Administration.java b/core/src/mindustry/net/Administration.java
index f185744c28..ccf5f76755 100644
--- a/core/src/mindustry/net/Administration.java
+++ b/core/src/mindustry/net/Administration.java
@@ -577,7 +577,10 @@ public class Administration{
autosave("Whether the periodically save the map when playing.", false),
autosaveAmount("The maximum amount of autosaves. Older ones get replaced.", 10),
autosaveSpacing("Spacing between autosaves in seconds.", 60 * 5),
- debug("Enable debug logging", false, () -> Log.setLogLevel(debug() ? LogLevel.debug : LogLevel.info));
+ debug("Enable debug logging", false, () -> {
+ LogLevel level = debug() ? LogLevel.debug : LogLevel.info;
+ Log.level = level;
+ });
public static final Config[] all = values();
diff --git a/core/src/mindustry/net/NetworkIO.java b/core/src/mindustry/net/NetworkIO.java
index acaf9f9640..f4494e1c4f 100644
--- a/core/src/mindustry/net/NetworkIO.java
+++ b/core/src/mindustry/net/NetworkIO.java
@@ -58,8 +58,6 @@ public class NetworkIO{
state.rules = JsonIO.read(Rules.class, stream.readUTF());
state.map = new Map(SaveIO.getSaveWriter().readStringMap(stream));
- Log.info("READ RULES: @", state.rules.researched);
-
state.wave = stream.readInt();
state.wavetime = stream.readFloat();
diff --git a/core/src/mindustry/type/AmmoTypes.java b/core/src/mindustry/type/AmmoTypes.java
index 534bdbe703..761bcbc8d0 100644
--- a/core/src/mindustry/type/AmmoTypes.java
+++ b/core/src/mindustry/type/AmmoTypes.java
@@ -41,7 +41,7 @@ public class AmmoTypes implements ContentList{
@Override
public void resupply(Unit unit){
float range = unit.hitSize + 60f;
- Tile closest = Vars.indexer.findClosestFlag(unit.x, unit.y, unit.team, BlockFlag.powerRes);
+ Tile closest = Vars.indexer.findClosestFlag(unit.x, unit.y, unit.team, BlockFlag.battery);
if(closest != null && closest.build != null && unit.within(closest.build, range) && closest.build.power != null){
var build = closest.build;
diff --git a/core/src/mindustry/type/Item.java b/core/src/mindustry/type/Item.java
index 9329efb47e..f52323d655 100644
--- a/core/src/mindustry/type/Item.java
+++ b/core/src/mindustry/type/Item.java
@@ -1,16 +1,15 @@
package mindustry.type;
import arc.graphics.*;
-import arc.scene.ui.layout.*;
import arc.struct.*;
import mindustry.ctype.*;
-import mindustry.ui.*;
import mindustry.world.blocks.environment.*;
+import mindustry.world.meta.*;
import static mindustry.Vars.*;
public class Item extends UnlockableContent{
- public final Color color;
+ public Color color;
/** how explosive this item is. */
public float explosiveness = 0f;
@@ -36,8 +35,10 @@ public class Item extends UnlockableContent{
}
@Override
- public void displayInfo(Table table){
- ContentDisplay.displayItem(table, this);
+ public void setStats(){
+ stats.addPercent(Stat.explosiveness, explosiveness);
+ stats.addPercent(Stat.flammability, flammability);
+ stats.addPercent(Stat.radioactivity, radioactivity);
}
@Override
diff --git a/core/src/mindustry/type/ItemSeq.java b/core/src/mindustry/type/ItemSeq.java
index 0407f6a3f8..49055fb5b9 100644
--- a/core/src/mindustry/type/ItemSeq.java
+++ b/core/src/mindustry/type/ItemSeq.java
@@ -21,6 +21,13 @@ public class ItemSeq implements Iterable, Serializable{
stacks.each(this::add);
}
+ public ItemSeq copy(){
+ ItemSeq out = new ItemSeq();
+ out.total = total;
+ System.arraycopy(values, 0, out.values, 0, values.length);
+ return out;
+ }
+
public void each(ItemConsumer cons){
for(int i = 0; i < values.length; i++){
if(values[i] != 0){
@@ -46,6 +53,19 @@ public class ItemSeq implements Iterable, Serializable{
return values[item.id] > 0;
}
+ public boolean has(ItemSeq seq){
+ for(int i = 0; i < values.length; i++){
+ if(seq.values[i] > values[i]){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean has(Item item, int amount){
+ return values[item.id] >= amount;
+ }
+
public int get(Item item){
return values[item.id];
}
diff --git a/core/src/mindustry/type/Liquid.java b/core/src/mindustry/type/Liquid.java
index 19e77a9987..e62805e60b 100644
--- a/core/src/mindustry/type/Liquid.java
+++ b/core/src/mindustry/type/Liquid.java
@@ -1,15 +1,14 @@
package mindustry.type;
import arc.graphics.*;
-import arc.scene.ui.layout.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.ctype.*;
-import mindustry.ui.*;
+import mindustry.world.meta.*;
public class Liquid extends UnlockableContent{
/** Color used in pipes and on the ground. */
- public final Color color;
+ public Color color;
/** Color used in bars. */
public @Nullable Color barColor;
/** Color used to draw lights. Note that the alpha channel is used to dictate brightness. */
@@ -46,8 +45,12 @@ public class Liquid extends UnlockableContent{
}
@Override
- public void displayInfo(Table table){
- ContentDisplay.displayLiquid(table, this);
+ public void setStats(){
+ stats.addPercent(Stat.explosiveness, explosiveness);
+ stats.addPercent(Stat.flammability, flammability);
+ stats.addPercent(Stat.temperature, temperature);
+ stats.addPercent(Stat.heatCapacity, heatCapacity);
+ stats.addPercent(Stat.viscosity, viscosity);
}
@Override
diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java
index 911939b870..4550ae6805 100644
--- a/core/src/mindustry/type/Planet.java
+++ b/core/src/mindustry/type/Planet.java
@@ -5,7 +5,6 @@ import arc.func.*;
import arc.graphics.*;
import arc.math.*;
import arc.math.geom.*;
-import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import arc.util.noise.*;
@@ -259,13 +258,16 @@ public class Planet extends UnlockableContent{
return true;
}
- @Override
- public void displayInfo(Table table){
-
- }
-
@Override
public ContentType getContentType(){
return ContentType.planet;
}
+
+ public boolean visible(){
+ return true;
+ }
+
+ public void draw(Mat3D projection, Mat3D transform){
+ mesh.render(projection, transform);
+ }
}
diff --git a/core/src/mindustry/type/Sector.java b/core/src/mindustry/type/Sector.java
index 37535bffca..975c8b82c8 100644
--- a/core/src/mindustry/type/Sector.java
+++ b/core/src/mindustry/type/Sector.java
@@ -40,9 +40,22 @@ public class Sector{
this.id = tile.id;
}
+ /** @return a copy of the items in this sector - may be core items, or stored data. */
+ public ItemSeq getItems(){
+ if(isBeingPlayed()){
+ ItemSeq out = new ItemSeq();
+ if(state.rules.defaultTeam.core() != null) out.add(state.rules.defaultTeam.core().items);
+ return out;
+ }else{
+ return info.items;
+ }
+ }
+
public Seq near(){
tmpSeq1.clear();
- near(tmpSeq1::add);
+ for(Ptile tile : tile.tiles){
+ tmpSeq1.add(planet.getSector(tile));
+ }
return tmpSeq1;
}
@@ -131,6 +144,12 @@ public class Sector{
removeItem(item, -amount);
}
+ public void removeItems(ItemSeq items){
+ ItemSeq copy = items.copy();
+ copy.each((i, a) -> copy.set(i, -a));
+ addItems(copy);
+ }
+
public void removeItem(Item item, int amount){
ItemSeq seq = new ItemSeq();
seq.add(item, -amount);
diff --git a/core/src/mindustry/type/SectorPreset.java b/core/src/mindustry/type/SectorPreset.java
index f08374fa70..0e9b90fb30 100644
--- a/core/src/mindustry/type/SectorPreset.java
+++ b/core/src/mindustry/type/SectorPreset.java
@@ -2,7 +2,6 @@ package mindustry.type;
import arc.func.*;
import arc.graphics.g2d.*;
-import arc.scene.ui.layout.*;
import mindustry.ctype.*;
import mindustry.game.*;
import mindustry.gen.*;
@@ -39,11 +38,6 @@ public class SectorPreset extends UnlockableContent{
return true;
}
- //neither of these are implemented, as zones are not displayed in a normal fashion... yet
- @Override
- public void displayInfo(Table table){
- }
-
@Override
public ContentType getContentType(){
return ContentType.sector;
diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java
index 7d0c3fd98b..43d5f05bd9 100644
--- a/core/src/mindustry/type/UnitType.java
+++ b/core/src/mindustry/type/UnitType.java
@@ -28,6 +28,8 @@ import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.payloads.*;
import mindustry.world.blocks.units.*;
import mindustry.world.consumers.*;
+import mindustry.world.meta.*;
+import mindustry.world.meta.values.*;
import static mindustry.Vars.*;
@@ -41,7 +43,7 @@ public class UnitType extends UnlockableContent{
public Prov extends UnitController> defaultController = () -> !flying ? new GroundAI() : new FlyingAI();
public float speed = 1.1f, boostMultiplier = 1f, rotateSpeed = 5f, baseRotateSpeed = 5f;
public float drag = 0.3f, accel = 0.5f, landShake = 0f, rippleScale = 1f, fallSpeed = 0.018f;
- public float health = 200f, range = -1, armor = 0f;
+ public float health = 200f, range = -1, armor = 0f, maxRange = -1f;
public float crashDamageMultiplier = 1f;
public boolean targetAir = true, targetGround = true;
public boolean faceTarget = true, rotateShooting = true, isCounted = true, lowAltitude = false;
@@ -58,6 +60,7 @@ public class UnitType extends UnlockableContent{
public Effect fallEffect = Fx.fallSmoke;
public Effect fallThrusterEffect = Fx.fallSmoke;
public Seq abilities = new Seq<>();
+ public BlockFlag targetFlag = BlockFlag.generator;
public int legCount = 4, legGroupSize = 2;
public float legLength = 10f, legSpeed = 0.1f, legTrns = 1f, legBaseOffset = 0f, legMoveSpace = 1f, legExtension = 0, legPairOffset = 0, legLengthScl = 1f, kinematicScl = 1f, maxStretch = 1.75f;
@@ -156,11 +159,11 @@ public class UnitType extends UnlockableContent{
table.table(bars -> {
bars.defaults().growX().height(20f).pad(4);
- bars.add(new Bar("blocks.health", Pal.health, unit::healthf).blink(Color.white));
+ bars.add(new Bar("stat.health", Pal.health, unit::healthf).blink(Color.white));
bars.row();
if(state.rules.unitAmmo){
- bars.add(new Bar(ammoType.icon + " " + Core.bundle.get("blocks.ammo"), ammoType.barColor, () -> unit.ammo / ammoCapacity));
+ bars.add(new Bar(ammoType.icon + " " + Core.bundle.get("stat.ammo"), ammoType.barColor, () -> unit.ammo / ammoCapacity));
bars.row();
}
}).growX();
@@ -188,10 +191,21 @@ public class UnitType extends UnlockableContent{
}
}
-
@Override
- public void displayInfo(Table table){
- ContentDisplay.displayUnit(table, this);
+ public void setStats(){
+ Unit inst = constructor.get();
+
+ stats.add(Stat.health, health);
+ stats.add(Stat.speed, speed);
+ stats.add(Stat.itemCapacity, health);
+ stats.add(Stat.range, (int)(maxRange / tilesize), StatUnit.blocks);
+ //TODO abilities, maybe try something like DPS
+
+ if(inst instanceof Minerc && mineTier >= 1){
+ stats.addPercent(Stat.mineSpeed, mineSpeed);
+ stats.add(Stat.mineTier, new BlockFilterValue(b -> b instanceof Floor f && f.itemDrop != null && f.itemDrop.hardness <= mineTier && !f.playerUnmineable));
+ }
+ if(inst instanceof Builderc) stats.addPercent(Stat.buildSpeed, buildSpeed);
}
@CallSuper
@@ -217,8 +231,10 @@ public class UnitType extends UnlockableContent{
//set up default range
if(range < 0){
range = Float.MAX_VALUE;
+ maxRange = 0f;
for(Weapon weapon : weapons){
range = Math.min(range, weapon.bullet.range() + hitSize /2f);
+ maxRange = Math.max(maxRange, weapon.bullet.range() + hitSize /2f);
}
}
@@ -322,7 +338,7 @@ public class UnitType extends UnlockableContent{
if(stacks != null){
ItemStack[] out = new ItemStack[stacks.length];
for(int i = 0; i < out.length; i++){
- out[i] = new ItemStack(stacks[i].item, UI.roundAmount((int)(Math.pow(stacks[i].amount, 1.1) * 50)));
+ out[i] = new ItemStack(stacks[i].item, UI.roundAmount((int)(Math.pow(stacks[i].amount, 1) * 50)));
}
return out;
diff --git a/core/src/mindustry/type/Weather.java b/core/src/mindustry/type/Weather.java
index 8fb30aecb6..4d17ab7c0e 100644
--- a/core/src/mindustry/type/Weather.java
+++ b/core/src/mindustry/type/Weather.java
@@ -1,16 +1,18 @@
package mindustry.type;
+import arc.*;
import arc.func.*;
+import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
-import arc.scene.ui.layout.*;
import arc.util.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.ctype.*;
import mindustry.gen.*;
import mindustry.graphics.*;
+import mindustry.world.*;
import mindustry.world.blocks.*;
import static mindustry.Vars.*;
@@ -91,9 +93,136 @@ public abstract class Weather extends UnlockableContent{
}
- @Override
- public void displayInfo(Table table){
- //do not
+ public void drawParticles(TextureRegion region, Color color,
+ float sizeMin, float sizeMax,
+ float density, float intensity, float opacity,
+ float windx, float windy,
+ float minAlpha, float maxAlpha,
+ float sinSclMin, float sinSclMax, float sinMagMin, float sinMagMax){
+ 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(sizeMax * 1.5f);
+ Core.camera.bounds(Tmp.r2);
+ int total = (int)(Tmp.r1.area() / density * intensity);
+ Draw.color(color, opacity);
+
+ for(int i = 0; i < total; i++){
+ float scl = rand.random(0.5f, 1f);
+ float scl2 = rand.random(0.5f, 1f);
+ float size = rand.random(sizeMin, sizeMax);
+ 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(minAlpha, maxAlpha);
+
+ x += Mathf.sin(y, rand.random(sinSclMin, sinSclMax), rand.random(sinMagMin, sinMagMax));
+
+ 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).overlaps(Tmp.r2)){
+ Draw.alpha(alpha * opacity);
+ Draw.rect(region, x, y, size, size);
+ }
+ }
+ }
+
+ public void drawRain(float sizeMin, float sizeMax, float xspeed, float yspeed, float density, float intensity, float stroke, Color color){
+ float padding = sizeMax*0.9f;
+
+ 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 * intensity);
+ Lines.stroke(stroke);
+ float alpha = Draw.getColor().a;
+ Draw.color(color);
+
+ for(int i = 0; i < total; i++){
+ float scl = rand.random(0.5f, 1f);
+ float scl2 = rand.random(0.5f, 1f);
+ float size = rand.random(sizeMin, sizeMax);
+ 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).overlaps(Tmp.r2)){
+ Draw.alpha(tint);
+ Lines.lineAngle(x, y, Angles.angle(xspeed * scl2, - yspeed * scl), size/2f);
+ }
+ }
+ }
+
+ public void drawSplashes(TextureRegion[] splashes, float padding, float density, float intensity, float opacity, float timeScale, float stroke, Color color, Liquid splasher){
+ 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 * intensity) / 2;
+ Lines.stroke(stroke);
+
+ float t = Time.time() / timeScale;
+
+ 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);
+
+ //only create splashes on specific liquid.
+ if(tile != null && tile.floor().liquidDrop == splasher){
+ Draw.color(Tmp.c1.set(tile.floor().mapColor).mul(1.5f).a(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);
+ Draw.alpha(Mathf.slope(life) * 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));
+ }
+ }
+ }
+ }
+ }
+
+ public void drawNoise(Texture noise, Color color, float noisescl, float opacity, float baseSpeed, float intensity, float vwindx, float vwindy, float offset){
+ Draw.alpha(opacity);
+ Draw.tint(color);
+
+ float speed = baseSpeed * intensity;
+ float windx = vwindx * speed, windy = vwindy * speed;
+
+ float scale = 1f / noisescl;
+ float scroll = Time.time() * scale + offset;
+ 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);
}
@Override
diff --git a/core/src/mindustry/type/weather/ParticleWeather.java b/core/src/mindustry/type/weather/ParticleWeather.java
new file mode 100644
index 0000000000..060e9cbe62
--- /dev/null
+++ b/core/src/mindustry/type/weather/ParticleWeather.java
@@ -0,0 +1,90 @@
+package mindustry.type.weather;
+
+import arc.*;
+import arc.graphics.*;
+import arc.graphics.Texture.*;
+import arc.graphics.g2d.*;
+import arc.util.*;
+import mindustry.gen.*;
+import mindustry.type.*;
+
+public class ParticleWeather extends Weather{
+ public String particleRegion = "circle-shadow";
+ public Color color = Color.white.cpy();
+ public TextureRegion region;
+ public float yspeed = -2f, xspeed = 0.25f, padding = 16f, sizeMin = 2.4f, sizeMax = 12f, density = 1200f, minAlpha = 1f, maxAlpha = 1f, force = 0, noiseScale = 2000f, baseSpeed = 6.1f;
+ public float sinSclMin = 30f, sinSclMax = 80f, sinMagMin = 1f, sinMagMax = 7f;
+
+ public Color noiseColor = color;
+ public boolean drawNoise = false, drawParticles = true, useWindVector = false;
+ public int noiseLayers = 1;
+ public float noiseLayerSpeedM = 1.1f, noiseLayerAlphaM = 0.8f, noiseLayerSclM = 0.99f, noiseLayerColorM = 1f;
+ public String noisePath = "noiseAlpha";
+ public @Nullable Texture noise;
+
+ public ParticleWeather(String name){
+ super(name);
+ }
+
+ @Override
+ public void load(){
+ super.load();
+
+ region = Core.atlas.find(particleRegion);
+
+ //load noise texture
+ //TODO mod support
+ if(drawNoise){
+ Core.assets.load("sprites/" + noisePath + ".png", Texture.class);
+ }
+ }
+
+ @Override
+ public void update(WeatherState state){
+ float speed = force * state.intensity;
+ if(speed > 0.001f){
+ 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){
+
+ float windx, windy;
+ if(useWindVector){
+ float speed = baseSpeed * state.intensity;
+ windx = state.windVector.x * speed;
+ windy = state.windVector.y * speed;
+ }else{
+ windx = this.xspeed;
+ windy = this.yspeed;
+ }
+
+ if(drawNoise){
+ if(noise == null){
+ noise = Core.assets.get("sprites/" + noisePath + ".png", Texture.class);
+ noise.setWrap(TextureWrap.repeat);
+ noise.setFilter(TextureFilter.linear);
+ }
+
+ float sspeed = 1f, sscl = 1f, salpha = 1f, offset = 0f;
+ Color col = Tmp.c1.set(noiseColor);
+ for(int i = 0; i < noiseLayers; i++){
+ drawNoise(noise, noiseColor, noiseScale * sscl, state.opacity * salpha * opacityMultiplier, baseSpeed * sspeed, state.intensity, windx, windy, offset);
+ sspeed *= noiseLayerSpeedM;
+ salpha *= noiseLayerAlphaM;
+ sscl *= noiseLayerSclM;
+ offset += 0.29f;
+ col.mul(noiseLayerColorM);
+ }
+ }
+
+ if(drawParticles){
+ drawParticles(region, color, sizeMin, sizeMax, density, state.intensity, state.opacity, windx, windy, minAlpha, maxAlpha, sinSclMin, sinSclMax, sinMagMin, sinMagMax);
+ }
+ }
+}
diff --git a/core/src/mindustry/type/weather/RainWeather.java b/core/src/mindustry/type/weather/RainWeather.java
new file mode 100644
index 0000000000..78fd096062
--- /dev/null
+++ b/core/src/mindustry/type/weather/RainWeather.java
@@ -0,0 +1,38 @@
+package mindustry.type.weather;
+
+import arc.*;
+import arc.graphics.*;
+import arc.graphics.g2d.*;
+import mindustry.content.*;
+import mindustry.gen.*;
+import mindustry.type.*;
+
+public class RainWeather extends Weather{
+ public float yspeed = 5f, xspeed = 1.5f, padding = 16f, density = 1200f, stroke = 0.75f, sizeMin = 8f, sizeMax = 40f, splashTimeScale = 22f;
+ public Liquid liquid = Liquids.water;
+ public TextureRegion[] splashes = new TextureRegion[12];
+ public Color color = Color.valueOf("7a95eaff");
+
+ public RainWeather(String name){
+ super(name);
+ }
+
+ @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){
+ drawRain(sizeMin, sizeMax, xspeed, yspeed, density, state.intensity, stroke, color);
+ }
+
+ @Override
+ public void drawUnder(WeatherState state){
+ drawSplashes(splashes, sizeMax, density, state.intensity, state.opacity, splashTimeScale, stroke, color, liquid);
+ }
+}
diff --git a/core/src/mindustry/ui/ContentDisplay.java b/core/src/mindustry/ui/ContentDisplay.java
deleted file mode 100644
index 6eefedcd53..0000000000
--- a/core/src/mindustry/ui/ContentDisplay.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package mindustry.ui;
-
-import arc.*;
-import arc.graphics.*;
-import arc.scene.ui.layout.*;
-import arc.struct.*;
-import arc.util.*;
-import mindustry.gen.*;
-import mindustry.graphics.*;
-import mindustry.type.*;
-import mindustry.world.*;
-import mindustry.world.meta.*;
-
-public class ContentDisplay{
-
- public static void displayBlock(Table table, Block block){
-
- table.table(title -> {
- int size = 8 * 6;
-
- title.image(block.icon(Cicon.xlarge)).size(size);
- title.add("[accent]" + block.localizedName).padLeft(5);
- });
-
- table.row();
-
- table.image().height(3).color(Color.lightGray).pad(8).padLeft(0).padRight(0).fillX();
-
- table.row();
-
- if(block.description != null){
- table.add(block.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
- table.row();
-
- table.image().height(3).color(Color.lightGray).pad(8).padLeft(0).padRight(0).fillX();
- table.row();
- }
-
- BlockStats stats = block.stats;
-
- for(StatCategory cat : stats.toMap().keys()){
- OrderedMap> map = stats.toMap().get(cat);
-
- if(map.size == 0) continue;
-
- table.add("@category." + cat.name()).color(Pal.accent).fillX();
- table.row();
-
- for(BlockStat stat : map.keys()){
- table.table(inset -> {
- inset.left();
- inset.add("[lightgray]" + stat.localized() + ":[] ").left();
- Seq arr = map.get(stat);
- for(StatValue value : arr){
- value.display(inset);
- inset.add().size(10f);
- }
-
- }).fillX().padLeft(10);
- table.row();
- }
- }
- }
-
- public static void displayItem(Table table, Item item){
-
- table.table(title -> {
- title.image(item.icon(Cicon.xlarge)).size(8 * 6);
- title.add("[accent]" + item.localizedName).padLeft(5);
- });
-
- table.row();
-
- table.image().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
-
- table.row();
-
- if(item.description != null){
- table.add(item.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
- table.row();
-
- table.image().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
- table.row();
- }
-
- table.left().defaults().fillX();
-
- table.add(Core.bundle.format("item.explosiveness", (int)(item.explosiveness * 100)));
- table.row();
- table.add(Core.bundle.format("item.flammability", (int)(item.flammability * 100)));
- table.row();
- table.add(Core.bundle.format("item.radioactivity", (int)(item.radioactivity * 100)));
- table.row();
- }
-
- public static void displayLiquid(Table table, Liquid liquid){
-
- table.table(title -> {
- title.image(liquid.icon(Cicon.xlarge)).size(8 * 6);
- title.add("[accent]" + liquid.localizedName).padLeft(5);
- });
-
- table.row();
-
- table.image().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
-
- table.row();
-
- if(liquid.description != null){
- table.add(liquid.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
- table.row();
-
- table.image().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
- table.row();
- }
-
- table.left().defaults().fillX();
-
- table.add(Core.bundle.format("item.explosiveness", (int)(liquid.explosiveness * 100)));
- table.row();
- table.add(Core.bundle.format("item.flammability", (int)(liquid.flammability * 100)));
- table.row();
- table.add(Core.bundle.format("liquid.heatcapacity", (int)(liquid.heatCapacity * 100)));
- table.row();
- table.add(Core.bundle.format("liquid.temperature", (int)(liquid.temperature * 100)));
- table.row();
- table.add(Core.bundle.format("liquid.viscosity", (int)(liquid.viscosity * 100)));
- table.row();
- }
-
- public static void displayUnit(Table table, UnitType unit){
- table.table(title -> {
- title.image(unit.icon(Cicon.xlarge)).size(8 * 6).scaling(Scaling.fit);
- title.add("[accent]" + unit.localizedName).padLeft(5);
- });
-
- table.row();
-
- table.image().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
-
- table.row();
-
- if(unit.description != null){
- table.add(unit.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
- table.row();
-
- table.image().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
- table.row();
- }
-
- table.left().defaults().fillX();
-
- Unit inst = unit.constructor.get();
-
- //TODO more stats
- table.add(Core.bundle.format("unit.health", unit.health)).row();
- table.add(Core.bundle.format("unit.speed", Strings.fixed(unit.speed, 1))).row();
- table.add(Core.bundle.format("unit.itemcapacity", unit.itemCapacity)).row();
-
- if(inst instanceof Minerc) table.add(Core.bundle.format("unit.minespeed", (int)(unit.mineSpeed * 100f))).row();
- if(inst instanceof Builderc) table.add(Core.bundle.format("unit.buildspeed", (int)(unit.buildSpeed * 100f))).row();
-
- table.row();
- }
-}
diff --git a/core/src/mindustry/ui/dialogs/ContentInfoDialog.java b/core/src/mindustry/ui/dialogs/ContentInfoDialog.java
index 0ee1960f9f..89cf556cb1 100644
--- a/core/src/mindustry/ui/dialogs/ContentInfoDialog.java
+++ b/core/src/mindustry/ui/dialogs/ContentInfoDialog.java
@@ -1,8 +1,14 @@
package mindustry.ui.dialogs;
+import arc.graphics.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
+import arc.struct.*;
+import arc.util.*;
import mindustry.ctype.*;
+import mindustry.graphics.*;
+import mindustry.ui.*;
+import mindustry.world.meta.*;
public class ContentInfoDialog extends BaseDialog{
@@ -18,11 +24,62 @@ public class ContentInfoDialog extends BaseDialog{
Table table = new Table();
table.margin(10);
- content.displayInfo(table);
+ //initialize stats if they haven't been yet
+ content.checkStats();
+
+ table.table(title1 -> {
+ int size = 8 * 6;
+
+ title1.image(content.icon(Cicon.xlarge)).size(size).scaling(Scaling.fit);
+ title1.add("[accent]" + content.localizedName).padLeft(5);
+ });
+
+ table.row();
+
+ table.image().height(3).color(Color.lightGray).pad(8).padLeft(0).padRight(0).fillX();
+
+ table.row();
+
+ if(content.description != null){
+ table.add(content.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
+ table.row();
+
+ table.image().height(3).color(Color.lightGray).pad(8).padLeft(0).padRight(0).fillX();
+ table.row();
+ }
+
+ Stats stats = content.stats;
+
+ for(StatCat cat : stats.toMap().keys()){
+ OrderedMap> map = stats.toMap().get(cat);
+
+ if(map.size == 0) continue;
+
+ //TODO check
+ if(stats.useCategories){
+ table.add("@category." + cat.name()).color(Pal.accent).fillX();
+ table.row();
+ }
+
+ for(Stat stat : map.keys()){
+ table.table(inset -> {
+ inset.left();
+ inset.add("[lightgray]" + stat.localized() + ":[] ").left();
+ Seq arr = map.get(stat);
+ for(StatValue value : arr){
+ value.display(inset);
+ inset.add().size(10f);
+ }
+
+ }).fillX().padLeft(10);
+ table.row();
+ }
+ }
ScrollPane pane = new ScrollPane(table);
cont.add(pane);
show();
}
+
}
diff --git a/core/src/mindustry/ui/dialogs/GameOverDialog.java b/core/src/mindustry/ui/dialogs/GameOverDialog.java
index b9967e6564..ceea590826 100644
--- a/core/src/mindustry/ui/dialogs/GameOverDialog.java
+++ b/core/src/mindustry/ui/dialogs/GameOverDialog.java
@@ -2,7 +2,7 @@ package mindustry.ui.dialogs;
import arc.*;
import mindustry.game.EventType.*;
-import mindustry.game.Stats.*;
+import mindustry.game.GameStats.*;
import mindustry.game.*;
import mindustry.type.*;
import mindustry.ui.*;
diff --git a/core/src/mindustry/ui/dialogs/LaunchLoadoutDialog.java b/core/src/mindustry/ui/dialogs/LaunchLoadoutDialog.java
index 1ba7a0084b..62db818bf7 100644
--- a/core/src/mindustry/ui/dialogs/LaunchLoadoutDialog.java
+++ b/core/src/mindustry/ui/dialogs/LaunchLoadoutDialog.java
@@ -30,7 +30,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
super("@configure");
}
- public void show(CoreBlock core, Building build, Runnable confirm){
+ public void show(CoreBlock core, Sector sector, Runnable confirm){
cont.clear();
buttons.clear();
@@ -43,12 +43,14 @@ public class LaunchLoadoutDialog extends BaseDialog{
}
});
+ ItemSeq sitems = sector.getItems();
+
//updates sum requirements
Runnable update = () -> {
total.clear();
selected.requirements().each(total::add);
universe.getLaunchResources().each(total::add);
- valid = build.items.has(total);
+ valid = sitems.has(total);
};
Cons
rebuild = table -> {
@@ -65,8 +67,8 @@ public class LaunchLoadoutDialog extends BaseDialog{
String amountStr = "[lightgray]" + (al + " + [accent]" + as + "[lightgray]");
table.add(
- build.items.has(s.item, s.amount) ? amountStr :
- "[scarlet]" + (Math.min(build.items.get(s.item), s.amount) + "[lightgray]/" + amountStr)).padLeft(2).left().padRight(4);
+ sitems.has(s.item, s.amount) ? amountStr :
+ "[scarlet]" + (Math.min(sitems.get(s.item), s.amount) + "[lightgray]/" + amountStr)).padLeft(2).left().padRight(4);
if(++i % 4 == 0){
table.row();
@@ -108,7 +110,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
selected = s;
update.run();
rebuildItems.run();
- }).group(group).pad(4).disabled(!build.items.has(s.requirements())).checked(s == selected).size(200f);
+ }).group(group).pad(4).disabled(!sitems.has(s.requirements())).checked(s == selected).size(200f);
if(++i % cols == 0){
t.row();
diff --git a/core/src/mindustry/ui/dialogs/PausedDialog.java b/core/src/mindustry/ui/dialogs/PausedDialog.java
index 5bd1e5abd3..fce68f3044 100644
--- a/core/src/mindustry/ui/dialogs/PausedDialog.java
+++ b/core/src/mindustry/ui/dialogs/PausedDialog.java
@@ -78,10 +78,7 @@ public class PausedDialog extends BaseDialog{
cont.buttonRow("@load", Icon.download, load::show).disabled(b -> net.active());
}else if(state.isCampaign()){
- cont.buttonRow("@launchcore", Icon.up, () -> {
- hide();
- ui.planet.showLaunch(state.getSector(), player.team().core());
- }).disabled(b -> player.team().core() == null || net.client());
+ cont.buttonRow("@research", Icon.tree, ui.research::show);
cont.row();
@@ -93,11 +90,7 @@ public class PausedDialog extends BaseDialog{
cont.row();
}
- if(state.isCampaign() && net.active()){
- cont.buttonRow("@research", Icon.tree, ui.research::show);
- }else{
- cont.buttonRow("@hostserver.mobile", Icon.host, ui.host::show).disabled(b -> net.active());
- }
+ cont.buttonRow("@hostserver.mobile", Icon.host, ui.host::show).disabled(b -> net.active());
cont.buttonRow("@quit", Icon.exit, this::showQuitConfirm).update(s -> {
s.setText(control.saves.getCurrent() != null && control.saves.getCurrent().isAutosave() ? "@save.quit" : "@quit");
diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java
index 2d32588faa..d14314977b 100644
--- a/core/src/mindustry/ui/dialogs/PlanetDialog.java
+++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java
@@ -13,6 +13,7 @@ import arc.scene.event.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.util.*;
+import mindustry.content.*;
import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.game.*;
@@ -22,7 +23,6 @@ import mindustry.graphics.g3d.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.blocks.storage.*;
-import mindustry.world.blocks.storage.CoreBlock.*;
import static mindustry.Vars.*;
import static mindustry.graphics.g3d.PlanetRenderer.*;
@@ -40,7 +40,6 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
public int launchRange;
public float zoom = 1f, selectAlpha = 1f;
public @Nullable Sector selected, hovered, launchSector;
- public CoreBuild launcher;
public Mode mode = look;
public boolean launching;
public Cons listener = s -> {};
@@ -91,9 +90,16 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
mode = look;
selected = hovered = launchSector = null;
launching = false;
+
+ zoom = 1f;
+ planets.zoom = 1f;
+ selectAlpha = 0f;
+ launchSector = state.getSector();
+
if(planets.planet.getLastSector() != null){
lookAt(planets.planet.getLastSector());
}
+
return super.show();
}
@@ -106,7 +112,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
//update view to sector
lookAt(sector);
zoom = 1f;
- planets.zoom = 2f;
+ planets.zoom = 1f;
selectAlpha = 0f;
launchSector = sector;
@@ -115,37 +121,33 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
super.show();
}
- public void showLaunch(Sector sector, CoreBuild launcher){
- if(launcher == null) return;
-
- this.launcher = launcher;
- selected = null;
- hovered = null;
- launching = false;
-
- //update view to sector
- lookAt(sector);
- zoom = 1f;
- planets.zoom = 2f;
- selectAlpha = 0f;
- launchRange = ((CoreBlock)launcher.block).launchRange;
- launchSector = sector;
-
- mode = launch;
-
- super.show();
- }
-
- private void lookAt(Sector sector){
+ void lookAt(Sector sector){
planets.camPos.set(Tmp.v33.set(sector.tile.v).rotate(Vec3.Y, -sector.planet.getRotation()));
}
boolean canSelect(Sector sector){
if(mode == select) return sector.hasBase();
- return mode == launch &&
- (sector.tile.v.within(launchSector.tile.v, (launchRange + 0.5f) * planets.planet.sectorApproxRadius*2) //within range
- || (sector.preset != null && sector.preset.unlocked())); //is an unlocked preset
+ return sector.near().contains(Sector::hasBase)//(sector.tile.v.within(launchSector.tile.v, (launchRange + 0.5f) * planets.planet.sectorApproxRadius*2) //within range
+ || (sector.preset != null && sector.preset.unlocked()); //is an unlocked preset
+ }
+
+ Sector findLauncher(Sector to){
+ //directly nearby.
+ if(to.near().contains(launchSector)) return launchSector;
+
+ Sector launchFrom = launchSector;
+ if(launchFrom == null){
+ //TODO pick one with the most resources
+ launchFrom = to.near().find(Sector::hasBase);
+ if(launchFrom == null && to.preset != null){
+ if(launchSector != null) return launchSector;
+ launchFrom = planets.planet.sectors.min(s -> !s.hasBase() ? Float.MAX_VALUE : s.tile.v.dst2(to.tile.v));
+ if(!launchFrom.hasBase()) launchFrom = null;
+ }
+ }
+
+ return launchFrom;
}
@Override
@@ -157,9 +159,6 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
if(selectAlpha > 0.01f){
if(canSelect(sec) || sec.unlocked()){
- if(sec.baseCoverage > 0){
- planets.fill(sec, Tmp.c1.set(Team.crux.color).a(0.5f * sec.baseCoverage * selectAlpha), -0.002f);
- }
Color color =
sec.hasBase() ? Team.sharded.color :
@@ -177,8 +176,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
}
}
- if(launchSector != null){
- planets.fill(launchSector, hoverColor, -0.001f);
+ Sector current = state.getSector() != null && state.getSector().isBeingPlayed() ? state.getSector() : null;
+
+ if(current != null){
+ planets.fill(current, hoverColor, -0.001f);
}
//draw hover border
@@ -195,9 +196,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
planets.batch.flush(Gl.triangles);
- if(mode == launch || mode == select){
- if(hovered != launchSector && hovered != null && canSelect(hovered)){
- planets.drawArc(planet, launchSector.tile.v, hovered.tile.v);
+ if(hovered != null && !hovered.hasBase()){
+ Sector launchFrom = findLauncher(hovered);
+ if(launchFrom != null && hovered != launchFrom && canSelect(hovered)){
+ planets.drawArc(planet, launchFrom.tile.v, hovered.tile.v);
}
}
@@ -244,7 +246,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
addListener(new ElementGestureListener(){
@Override
public void tap(InputEvent event, float x, float y, int count, KeyCode button){
- if(hovered != null && ((mode == launch ? canSelect(hovered) && hovered != launchSector : hovered.unlocked()) || debugSelect)){
+ if(hovered != null && ((mode == look ? canSelect(hovered) && hovered != launchSector : hovered.unlocked()) || debugSelect)){
selected = hovered;
}
@@ -263,9 +265,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
},
new Table(t -> {
t.touchable = Touchable.disabled;
- //TODO localize
t.top();
- t.label(() -> mode == select ? "@sectors.select" : mode == launch ? "Select Launch Sector" : "").style(Styles.outlineLabel).color(Pal.accent);
+ t.label(() -> mode == select ? "@sectors.select" : "").style(Styles.outlineLabel).color(Pal.accent);
}),
new Table(t -> {
t.right();
@@ -322,7 +323,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
stable.toFront();
//smooth camera toward the sector
- if(mode == launch && launching){
+ if(mode == look && launching){
float len = planets.camPos.len();
planets.camPos.slerp(Tmp.v31.set(selected.tile.v).rotate(Vec3.Y,-selected.planet.getRotation()).setLength(len), 0.1f);
}
@@ -453,17 +454,26 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
}
}
- if(mode == launch && !sector.hasBase()){
- Sector current = state.rules.sector;
+ if(mode == look && !sector.hasBase()){
shouldHide = false;
- loadouts.show((CoreBlock)launcher.block, launcher, () -> {
- control.handleLaunch(launcher);
- launching = true;
- zoom = 0.5f;
+ Sector from = findLauncher(sector);
+ if(from == null){
+ //free launch.
+ control.playSector(sector);
+ }else{
+ CoreBlock block = from.info.bestCoreType instanceof CoreBlock b ? b : (CoreBlock)Blocks.coreShard;
- ui.hudfrag.showLaunchDirect();
- Time.runTask(launchDuration, () -> control.playSector(current, sector));
- });
+ loadouts.show(block, from, () -> {
+ from.removeItems(universe.getLastLoadout().requirements());
+ from.removeItems(universe.getLaunchResources());
+
+ launching = true;
+ zoom = 0.5f;
+
+ ui.hudfrag.showLaunchDirect();
+ Time.runTask(launchDuration, () -> control.playSector(from, sector));
+ });
+ }
}else if(mode == select){
listener.get(sector);
}else{
@@ -491,7 +501,6 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
selected = null;
}
}
-
}
});
@@ -501,8 +510,6 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
public enum Mode{
/** Look around for existing sectors. Can only deploy. */
look,
- /** Launch to a new location. */
- launch,
/** Select a sector for some purpose. */
select
}
diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java
index 53dde34460..09814e1333 100644
--- a/core/src/mindustry/world/Block.java
+++ b/core/src/mindustry/world/Block.java
@@ -14,6 +14,7 @@ import arc.struct.*;
import arc.util.*;
import arc.util.pooling.*;
import mindustry.annotations.Annotations.*;
+import mindustry.content.*;
import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.entities.*;
@@ -50,7 +51,6 @@ public class Block extends UnlockableContent{
public float liquidCapacity = 10f;
public float liquidPressure = 1f;
- public final BlockStats stats = new BlockStats();
public final BlockBars bars = new BlockBars();
public final Consumers consumes = new Consumers();
@@ -320,27 +320,30 @@ public class Block extends UnlockableContent{
return update || destructible;
}
+ @Override
public void setStats(){
- stats.add(BlockStat.size, "@x@", size, size);
- stats.add(BlockStat.health, health, StatUnit.none);
+ super.setStats();
+
+ stats.add(Stat.size, "@x@", size, size);
+ stats.add(Stat.health, health, StatUnit.none);
if(canBeBuilt()){
- stats.add(BlockStat.buildTime, buildCost / 60, StatUnit.seconds);
- stats.add(BlockStat.buildCost, new ItemListValue(false, requirements));
+ stats.add(Stat.buildTime, buildCost / 60, StatUnit.seconds);
+ stats.add(Stat.buildCost, new ItemListValue(false, requirements));
}
if(instantTransfer){
- stats.add(BlockStat.maxConsecutive, 2, StatUnit.none);
+ stats.add(Stat.maxConsecutive, 2, StatUnit.none);
}
consumes.display(stats);
- // Note: Power stats are added by the consumers.
- if(hasLiquids) stats.add(BlockStat.liquidCapacity, liquidCapacity, StatUnit.liquidUnits);
- if(hasItems && itemCapacity > 0) stats.add(BlockStat.itemCapacity, itemCapacity, StatUnit.items);
+ //Note: Power stats are added by the consumers.
+ if(hasLiquids) stats.add(Stat.liquidCapacity, liquidCapacity, StatUnit.liquidUnits);
+ if(hasItems && itemCapacity > 0) stats.add(Stat.itemCapacity, itemCapacity, StatUnit.items);
}
public void setBars(){
- bars.add("health", entity -> new Bar("blocks.health", Pal.health, entity::healthf).blink(Color.white));
+ bars.add("health", entity -> new Bar("stat.health", Pal.health, entity::healthf).blink(Color.white));
if(hasLiquids){
Func current;
@@ -348,7 +351,7 @@ public class Block extends UnlockableContent{
Liquid liquid = consumes.get(ConsumeType.liquid).liquid;
current = entity -> liquid;
}else{
- current = entity -> entity.liquids.current();
+ current = entity -> entity.liquids == null ? Liquids.water : entity.liquids.current();
}
bars.add("liquid", entity -> new Bar(() -> entity.liquids.get(current.get(entity)) <= 0.001f ? Core.bundle.get("bar.liquid") : current.get(entity).localizedName,
() -> current.get(entity).barColor(), () -> entity.liquids.get(current.get(entity)) / liquidCapacity));
@@ -617,7 +620,7 @@ public class Block extends UnlockableContent{
public ItemStack[] researchRequirements(){
ItemStack[] out = new ItemStack[requirements.length];
for(int i = 0; i < out.length; i++){
- int quantity = 40 + Mathf.round(Mathf.pow(requirements[i].amount, 1.25f) * 20 * researchCostMultiplier, 10);
+ int quantity = 40 + Mathf.round(Mathf.pow(requirements[i].amount, 1.15f) * 20 * researchCostMultiplier, 10);
out[i] = new ItemStack(requirements[i].item, UI.roundAmount(quantity));
}
@@ -633,11 +636,6 @@ public class Block extends UnlockableContent{
}
}
- @Override
- public void displayInfo(Table table){
- ContentDisplay.displayBlock(table, this);
- }
-
@Override
public ContentType getContentType(){
return ContentType.block;
@@ -668,9 +666,10 @@ public class Block extends UnlockableContent{
if(consumes.has(ConsumeType.item)) hasItems = true;
if(consumes.has(ConsumeType.liquid)) hasLiquids = true;
- setStats();
setBars();
+ stats.useCategories = true;
+
consumes.init();
if(!outputsPower && consumes.hasPower() && consumes.getPower().buffered){
diff --git a/core/src/mindustry/world/Build.java b/core/src/mindustry/world/Build.java
index 070ddab553..98409e6d18 100644
--- a/core/src/mindustry/world/Build.java
+++ b/core/src/mindustry/world/Build.java
@@ -45,7 +45,7 @@ public class Build{
Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(tile, team, true)));
}
- /** Places a BuildBlock at this location. */
+ /** Places a ConstructBlock at this location. */
@Remote(called = Loc.server)
public static void beginPlace(Block result, Team team, int x, int y, int rotation){
if(!validPlace(result, team, x, y, rotation)){
diff --git a/core/src/mindustry/world/CachedTile.java b/core/src/mindustry/world/CachedTile.java
index 3c14ade132..5777ece759 100644
--- a/core/src/mindustry/world/CachedTile.java
+++ b/core/src/mindustry/world/CachedTile.java
@@ -21,7 +21,7 @@ public class CachedTile extends Tile{
}
@Override
- protected void changeEntity(Team team, Prov entityprov, int rotation){
+ protected void changeBuild(Team team, Prov entityprov, int rotation){
build = null;
Block block = block();
diff --git a/core/src/mindustry/world/Tile.java b/core/src/mindustry/world/Tile.java
index 8fdfd6c009..18696d8930 100644
--- a/core/src/mindustry/world/Tile.java
+++ b/core/src/mindustry/world/Tile.java
@@ -45,7 +45,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{
this.block = wall;
//update entity and create it if needed
- changeEntity(Team.derelict, wall::newBuilding, 0);
+ changeBuild(Team.derelict, wall::newBuilding, 0);
changed();
}
@@ -186,7 +186,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{
this.block = type;
preChanged();
- changeEntity(team, entityprov, (byte)Mathf.mod(rotation, 4));
+ changeBuild(team, entityprov, (byte)Mathf.mod(rotation, 4));
if(build != null){
build.team(team);
@@ -430,15 +430,15 @@ public class Tile implements Position, QuadTreeObject, Displayable{
getHitbox(rect);
}
- public Tile getNearby(Point2 relative){
+ public Tile nearby(Point2 relative){
return world.tile(x + relative.x, y + relative.y);
}
- public Tile getNearby(int dx, int dy){
+ public Tile nearby(int dx, int dy){
return world.tile(x + dx, y + dy);
}
- public Tile getNearby(int rotation){
+ public Tile nearby(int rotation){
if(rotation == 0) return world.tile(x + 1, y);
if(rotation == 1) return world.tile(x, y + 1);
if(rotation == 2) return world.tile(x - 1, y);
@@ -446,7 +446,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{
return null;
}
- public Building getNearbyEntity(int rotation){
+ public Building nearbyBuild(int rotation){
if(rotation == 0) return world.build(x + 1, y);
if(rotation == 1) return world.build(x, y + 1);
if(rotation == 2) return world.build(x - 1, y);
@@ -503,7 +503,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{
}
}
- protected void changeEntity(Team team, Prov entityprov, int rotation){
+ protected void changeBuild(Team team, Prov entityprov, int rotation){
if(build != null){
int size = build.block.size;
build.remove();
diff --git a/core/src/mindustry/world/blocks/Autotiler.java b/core/src/mindustry/world/blocks/Autotiler.java
index 2989436fac..027ac93b31 100644
--- a/core/src/mindustry/world/blocks/Autotiler.java
+++ b/core/src/mindustry/world/blocks/Autotiler.java
@@ -133,7 +133,7 @@ public interface Autotiler{
for(int i = 0; i < 4; i++){
int realDir = Mathf.mod(rotation - i, 4);
- if(blends(tile, rotation, directional, i, world) && (tile != null && tile.getNearbyEntity(realDir) != null && !tile.getNearbyEntity(realDir).block.squareSprite)){
+ if(blends(tile, rotation, directional, i, world) && (tile != null && tile.nearbyBuild(realDir) != null && !tile.nearbyBuild(realDir).block.squareSprite)){
blendresult[4] |= (1 << i);
}
}
@@ -194,7 +194,7 @@ public interface Autotiler{
// TODO docs -- use for direction?
default boolean blends(Tile tile, int rotation, int direction){
- Building other = tile.getNearbyEntity(Mathf.mod(rotation - direction, 4));
+ Building other = tile.nearbyBuild(Mathf.mod(rotation - direction, 4));
return other != null && other.team == tile.team() && blends(tile, rotation, other.tileX(), other.tileY(), other.rotation, other.block);
}
diff --git a/core/src/mindustry/world/blocks/ConstructBlock.java b/core/src/mindustry/world/blocks/ConstructBlock.java
index c228397a32..cefdfa6887 100644
--- a/core/src/mindustry/world/blocks/ConstructBlock.java
+++ b/core/src/mindustry/world/blocks/ConstructBlock.java
@@ -42,7 +42,7 @@ public class ConstructBlock extends Block{
consBlocks[size - 1] = this;
}
- /** Returns a BuildBlock by size. */
+ /** Returns a ConstructBlock by size. */
public static ConstructBlock get(int size){
if(size > maxSize) throw new IllegalArgumentException("No. Don't place ConstructBlock of size greater than " + maxSize);
return consBlocks[size - 1];
diff --git a/core/src/mindustry/world/blocks/ControlBlock.java b/core/src/mindustry/world/blocks/ControlBlock.java
index 6724ff9205..7688cdab6a 100644
--- a/core/src/mindustry/world/blocks/ControlBlock.java
+++ b/core/src/mindustry/world/blocks/ControlBlock.java
@@ -10,4 +10,14 @@ public interface ControlBlock{
default boolean isControlled(){
return unit().isPlayer();
}
+
+ /** @return whether this block can be controlled at all. */
+ default boolean canControl(){
+ return true;
+ }
+
+ /** @return whether targets should automatically be selected (on mobile) */
+ default boolean shouldAutoTarget(){
+ return true;
+ }
}
diff --git a/core/src/mindustry/world/blocks/campaign/LaunchPad.java b/core/src/mindustry/world/blocks/campaign/LaunchPad.java
index 860eb522d2..ff069acc48 100644
--- a/core/src/mindustry/world/blocks/campaign/LaunchPad.java
+++ b/core/src/mindustry/world/blocks/campaign/LaunchPad.java
@@ -42,7 +42,7 @@ public class LaunchPad extends Block{
public void setStats(){
super.setStats();
- stats.add(BlockStat.launchTime, launchTime / 60f, StatUnit.seconds);
+ stats.add(Stat.launchTime, launchTime / 60f, StatUnit.seconds);
}
@Override
@@ -124,7 +124,7 @@ public class LaunchPad extends Block{
return Core.bundle.format("launch.destination",
dest == null ? Core.bundle.get("sectors.nonelaunch") :
"[accent]" + dest.name());
- }).pad(4);
+ }).pad(4).wrap().width(200f).left();
}
@Override
diff --git a/core/src/mindustry/world/blocks/defense/ForceProjector.java b/core/src/mindustry/world/blocks/defense/ForceProjector.java
index 3b90533745..46fb01d7d5 100644
--- a/core/src/mindustry/world/blocks/defense/ForceProjector.java
+++ b/core/src/mindustry/world/blocks/defense/ForceProjector.java
@@ -61,11 +61,11 @@ public class ForceProjector extends Block{
@Override
public void setStats(){
super.setStats();
- stats.add(BlockStat.shieldHealth, breakage, StatUnit.none);
- stats.add(BlockStat.cooldownTime, (int) (breakage / cooldownBrokenBase / 60f), StatUnit.seconds);
- stats.add(BlockStat.powerUse, basePowerDraw * 60f, StatUnit.powerSecond);
- stats.add(BlockStat.boostEffect, phaseRadiusBoost / tilesize, StatUnit.blocks);
- stats.add(BlockStat.boostEffect, phaseShieldBoost, StatUnit.shieldHealth);
+ stats.add(Stat.shieldHealth, breakage, StatUnit.none);
+ stats.add(Stat.cooldownTime, (int) (breakage / cooldownBrokenBase / 60f), StatUnit.seconds);
+ stats.add(Stat.powerUse, basePowerDraw * 60f, StatUnit.powerSecond);
+ stats.add(Stat.boostEffect, phaseRadiusBoost / tilesize, StatUnit.blocks);
+ stats.add(Stat.boostEffect, phaseShieldBoost, StatUnit.shieldHealth);
}
@Override
diff --git a/core/src/mindustry/world/blocks/defense/MendProjector.java b/core/src/mindustry/world/blocks/defense/MendProjector.java
index 2bc50d6d7a..cf71928f26 100644
--- a/core/src/mindustry/world/blocks/defense/MendProjector.java
+++ b/core/src/mindustry/world/blocks/defense/MendProjector.java
@@ -44,11 +44,11 @@ public class MendProjector extends Block{
public void setStats(){
super.setStats();
- stats.add(BlockStat.repairTime, (int)(100f / healPercent * reload / 60f), StatUnit.seconds);
- stats.add(BlockStat.range, range / tilesize, StatUnit.blocks);
+ stats.add(Stat.repairTime, (int)(100f / healPercent * reload / 60f), StatUnit.seconds);
+ stats.add(Stat.range, range / tilesize, StatUnit.blocks);
- stats.add(BlockStat.boostEffect, phaseRangeBoost / tilesize, StatUnit.blocks);
- stats.add(BlockStat.boostEffect, (phaseBoost + healPercent) / healPercent, StatUnit.timesSpeed);
+ stats.add(Stat.boostEffect, phaseRangeBoost / tilesize, StatUnit.blocks);
+ stats.add(Stat.boostEffect, (phaseBoost + healPercent) / healPercent, StatUnit.timesSpeed);
}
@Override
diff --git a/core/src/mindustry/world/blocks/defense/OverdriveProjector.java b/core/src/mindustry/world/blocks/defense/OverdriveProjector.java
index ae3c10f3fd..7cadaede81 100644
--- a/core/src/mindustry/world/blocks/defense/OverdriveProjector.java
+++ b/core/src/mindustry/world/blocks/defense/OverdriveProjector.java
@@ -51,13 +51,13 @@ public class OverdriveProjector extends Block{
public void setStats(){
super.setStats();
- stats.add(BlockStat.speedIncrease, (int)(100f * speedBoost), StatUnit.percent);
- stats.add(BlockStat.range, range / tilesize, StatUnit.blocks);
- stats.add(BlockStat.productionTime, useTime / 60f, StatUnit.seconds);
+ stats.add(Stat.speedIncrease, (int)(100f * speedBoost), StatUnit.percent);
+ stats.add(Stat.range, range / tilesize, StatUnit.blocks);
+ stats.add(Stat.productionTime, useTime / 60f, StatUnit.seconds);
if(hasBoost){
- stats.add(BlockStat.boostEffect, phaseRangeBoost / tilesize, StatUnit.blocks);
- stats.add(BlockStat.boostEffect, (int)((speedBoost + speedBoostPhase) * 100f), StatUnit.percent);
+ stats.add(Stat.boostEffect, phaseRangeBoost / tilesize, StatUnit.blocks);
+ stats.add(Stat.boostEffect, (int)((speedBoost + speedBoostPhase) * 100f), StatUnit.percent);
}
}
diff --git a/core/src/mindustry/world/blocks/defense/Wall.java b/core/src/mindustry/world/blocks/defense/Wall.java
index abb941b899..a23a2583cd 100644
--- a/core/src/mindustry/world/blocks/defense/Wall.java
+++ b/core/src/mindustry/world/blocks/defense/Wall.java
@@ -17,16 +17,17 @@ import static mindustry.Vars.*;
public class Wall extends Block{
public int variants = 0;
- public float lightningChance = -0.001f;
+ /** Lighting chance. -1 to disable */
+ public float lightningChance = -1f;
public float lightningDamage = 20f;
public int lightningLength = 17;
public Color lightningColor = Pal.surge;
public Sound lightningSound = Sounds.spark;
- public float chanceDeflect = 10f;
+ /** Bullet deflection chance. -1 to disable */
+ public float chanceDeflect = -1f;
public boolean flashHit;
public Color flashColor = Color.white;
- public boolean deflect;
public Sound deflectSound = Sounds.none;
public Wall(String name){
@@ -38,6 +39,17 @@ public class Wall extends Block{
canOverdrive = false;
}
+ @Override
+ public void setStats(){
+ super.setStats();
+
+ if(chanceDeflect > 0f) stats.add(Stat.baseDeflectChance, chanceDeflect, StatUnit.none);
+ if(lightningChance > 0f){
+ stats.add(Stat.lightningChance, lightningChance * 100f, StatUnit.percent);
+ stats.add(Stat.lightningDamage, lightningDamage, StatUnit.none);
+ }
+ }
+
@Override
public void load(){
super.load();
@@ -96,7 +108,7 @@ public class Wall extends Block{
hit = 1f;
//create lightning if necessary
- if(lightningChance > 0){
+ if(lightningChance > 0f){
if(Mathf.chance(lightningChance)){
Lightning.create(team, lightningColor, lightningDamage, x, y, bullet.rotation() + 180f, lightningLength);
lightningSound.at(tile, Mathf.random(0.9f, 1.1f));
@@ -104,7 +116,7 @@ public class Wall extends Block{
}
//deflect bullets if necessary
- if(deflect){
+ if(chanceDeflect > 0f){
//slow bullets are not deflected
if(bullet.vel().len() <= 0.1f || !bullet.type.reflectable) return true;
diff --git a/core/src/mindustry/world/blocks/defense/turrets/BaseTurret.java b/core/src/mindustry/world/blocks/defense/turrets/BaseTurret.java
new file mode 100644
index 0000000000..e10b1612e9
--- /dev/null
+++ b/core/src/mindustry/world/blocks/defense/turrets/BaseTurret.java
@@ -0,0 +1,67 @@
+package mindustry.world.blocks.defense.turrets;
+
+import mindustry.content.*;
+import mindustry.entities.*;
+import mindustry.gen.*;
+import mindustry.graphics.*;
+import mindustry.logic.*;
+import mindustry.world.*;
+import mindustry.world.consumers.*;
+import mindustry.world.meta.*;
+
+import static mindustry.Vars.*;
+
+public abstract class BaseTurret extends Block{
+ public float range = 80f;
+ public float rotateSpeed = 5;
+
+ public boolean acceptCoolant = true;
+ /** Effect displayed when coolant is used. */
+ public Effect coolEffect = Fx.fuelburn;
+ /** How much reload is lowered by for each unit of liquid of heat capacity. */
+ public float coolantMultiplier = 5f;
+
+ public BaseTurret(String name){
+ super(name);
+
+ update = true;
+ solid = true;
+ outlineIcon = true;
+ }
+
+ @Override
+ public void init(){
+ if(acceptCoolant && !consumes.has(ConsumeType.liquid)){
+ hasLiquids = true;
+ consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.2f)).update(false).boost();
+ }
+
+ super.init();
+ }
+
+ @Override
+ public void drawPlace(int x, int y, int rotation, boolean valid){
+ Drawf.dashCircle(x * tilesize + offset, y * tilesize + offset, range, Pal.placing);
+ }
+
+ @Override
+ public void setStats(){
+ super.setStats();
+
+ stats.add(Stat.shootRange, range / tilesize, StatUnit.blocks);
+ }
+
+ public class BaseTurretBuild extends Building implements Ranged{
+ public float rotation = 90;
+
+ @Override
+ public float range(){
+ return range;
+ }
+
+ @Override
+ public void drawSelect(){
+ Drawf.dashCircle(x, y, range, team.color);
+ }
+ }
+}
diff --git a/core/src/mindustry/world/blocks/defense/turrets/ItemTurret.java b/core/src/mindustry/world/blocks/defense/turrets/ItemTurret.java
index 521e6dc19b..7550f23e79 100644
--- a/core/src/mindustry/world/blocks/defense/turrets/ItemTurret.java
+++ b/core/src/mindustry/world/blocks/defense/turrets/ItemTurret.java
@@ -35,14 +35,18 @@ public class ItemTurret extends Turret{
public void setStats(){
super.setStats();
- stats.remove(BlockStat.itemCapacity);
- stats.add(BlockStat.ammo, new AmmoListValue<>(ammoTypes));
+ stats.remove(Stat.itemCapacity);
+ stats.add(Stat.ammo, new AmmoListValue<>(ammoTypes));
+ }
+
+ @Override
+ public void init(){
consumes.add(new ConsumeItemFilter(i -> ammoTypes.containsKey(i)){
@Override
public void build(Building tile, Table table){
MultiReqImage image = new MultiReqImage();
content.items().each(i -> filter.get(i) && i.unlockedNow(), item -> image.add(new ReqImage(new ItemImage(item.icon(Cicon.medium)),
- () -> tile != null && !((ItemTurretBuild)tile).ammo.isEmpty() && ((ItemEntry)((ItemTurretBuild)tile).ammo.peek()).item == item)));
+ () -> tile != null && !((ItemTurretBuild)tile).ammo.isEmpty() && ((ItemEntry)((ItemTurretBuild)tile).ammo.peek()).item == item)));
table.add(image).size(8 * 4);
}
@@ -54,10 +58,12 @@ public class ItemTurret extends Turret{
}
@Override
- public void display(BlockStats stats){
+ public void display(Stats stats){
//don't display
}
});
+
+ super.init();
}
public class ItemTurretBuild extends TurretBuild{
@@ -83,7 +89,7 @@ public class ItemTurret extends Turret{
public void displayBars(Table bars){
super.displayBars(bars);
- bars.add(new Bar("blocks.ammo", Pal.ammo, () -> (float)totalAmmo / maxAmmo)).growX();
+ bars.add(new Bar("stat.ammo", Pal.ammo, () -> (float)totalAmmo / maxAmmo)).growX();
bars.row();
}
diff --git a/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java b/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java
index c47a279414..3aefcdd33c 100644
--- a/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java
+++ b/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java
@@ -33,11 +33,11 @@ public class LaserTurret extends PowerTurret{
public void setStats(){
super.setStats();
- stats.remove(BlockStat.booster);
- stats.add(BlockStat.input, new BoosterListValue(reloadTime, consumes.get(ConsumeType.liquid).amount, coolantMultiplier, false, l -> consumes.liquidfilters.get(l.id)));
- stats.remove(BlockStat.damage);
+ stats.remove(Stat.booster);
+ stats.add(Stat.input, new BoosterListValue(reloadTime, consumes.get(ConsumeType.liquid).amount, coolantMultiplier, false, l -> consumes.liquidfilters.get(l.id)));
+ stats.remove(Stat.damage);
//damages every 5 ticks, at least in meltdown's case
- stats.add(BlockStat.damage, shootType.damage * 60f / 5f, StatUnit.perSecond);
+ stats.add(Stat.damage, shootType.damage * 60f / 5f, StatUnit.perSecond);
}
public class LaserTurretBuild extends PowerTurretBuild{
diff --git a/core/src/mindustry/world/blocks/defense/turrets/LiquidTurret.java b/core/src/mindustry/world/blocks/defense/turrets/LiquidTurret.java
index 11d6213aa5..25725cd0a9 100644
--- a/core/src/mindustry/world/blocks/defense/turrets/LiquidTurret.java
+++ b/core/src/mindustry/world/blocks/defense/turrets/LiquidTurret.java
@@ -36,7 +36,11 @@ public class LiquidTurret extends Turret{
public void setStats(){
super.setStats();
- stats.add(BlockStat.ammo, new AmmoListValue<>(ammoTypes));
+ stats.add(Stat.ammo, new AmmoListValue<>(ammoTypes));
+ }
+
+ @Override
+ public void init(){
consumes.add(new ConsumeLiquidFilter(i -> ammoTypes.containsKey(i), 1f){
@Override
public boolean valid(Building entity){
@@ -49,10 +53,12 @@ public class LiquidTurret extends Turret{
}
@Override
- public void display(BlockStats stats){
+ public void display(Stats stats){
}
});
+
+ super.init();
}
public class LiquidTurretBuild extends TurretBuild{
diff --git a/core/src/mindustry/world/blocks/defense/PointDefenseTurret.java b/core/src/mindustry/world/blocks/defense/turrets/PointDefenseTurret.java
similarity index 76%
rename from core/src/mindustry/world/blocks/defense/PointDefenseTurret.java
rename to core/src/mindustry/world/blocks/defense/turrets/PointDefenseTurret.java
index 06746bcfaa..0184f9ff7a 100644
--- a/core/src/mindustry/world/blocks/defense/PointDefenseTurret.java
+++ b/core/src/mindustry/world/blocks/defense/turrets/PointDefenseTurret.java
@@ -1,4 +1,4 @@
-package mindustry.world.blocks.defense;
+package mindustry.world.blocks.defense.turrets;
import arc.graphics.*;
import arc.graphics.g2d.*;
@@ -11,12 +11,9 @@ import mindustry.content.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
-import mindustry.world.*;
import mindustry.world.meta.*;
-import static mindustry.Vars.*;
-
-public class PointDefenseTurret extends Block{
+public class PointDefenseTurret extends ReloadTurret{
public final int timerTarget = timers++;
public float retargetTime = 5f;
@@ -27,9 +24,6 @@ public class PointDefenseTurret extends Block{
public Effect hitEffect = Fx.pointHit;
public Effect shootEffect = Fx.sparkShoot;
- public float range = 80f;
- public float reloadTime = 30f;
- public float rotateSpeed = 20;
public float shootCone = 5f;
public float bulletDamage = 10f;
public float shootLength = 3f;
@@ -37,13 +31,12 @@ public class PointDefenseTurret extends Block{
public PointDefenseTurret(String name){
super(name);
- outlineIcon = true;
- update = true;
- }
+ rotateSpeed = 20f;
+ reloadTime = 30f;
- @Override
- public void drawPlace(int x, int y, int rotation, boolean valid){
- Drawf.dashCircle(x * tilesize + offset, y * tilesize + offset, range, Pal.accent);
+ coolantMultiplier = 2f;
+ //disabled due to version mismatch problems
+ acceptCoolant = false;
}
@Override
@@ -55,12 +48,10 @@ public class PointDefenseTurret extends Block{
public void setStats(){
super.setStats();
- stats.add(BlockStat.shootRange, range / tilesize, StatUnit.blocks);
- stats.add(BlockStat.reload, 60f / reloadTime, StatUnit.none);
+ stats.add(Stat.reload, 60f / reloadTime, StatUnit.none);
}
- public class PointDefenseBuild extends Building{
- public float rotation = 90, reload;
+ public class PointDefenseBuild extends ReloadTurretBuild{
public @Nullable Bullet target;
@Override
@@ -76,14 +67,18 @@ public class PointDefenseTurret extends Block{
target = null;
}
+ if(acceptCoolant){
+ updateCooling();
+ }
+
//look at target
if(target != null && target.within(this, range) && target.team != team && target.type() != null && target.type().hittable){
float dest = angleTo(target);
rotation = Angles.moveToward(rotation, dest, rotateSpeed * edelta());
- reload -= edelta();
+ reload += edelta();
//shoot when possible
- if(Angles.within(rotation, dest, shootCone) && reload <= 0f){
+ if(Angles.within(rotation, dest, shootCone) && reload >= reloadTime){
if(target.damage() > bulletDamage){
target.damage(target.damage() - bulletDamage);
}else{
@@ -95,18 +90,13 @@ public class PointDefenseTurret extends Block{
beamEffect.at(x + Tmp.v1.x, y + Tmp.v1.y, rotation, color, new Vec2().set(target));
shootEffect.at(x + Tmp.v1.x, y + Tmp.v1.y, rotation, color);
hitEffect.at(target.x, target.y, color);
- reload = reloadTime;
+ reload = 0;
}
}else{
target = null;
}
}
- @Override
- public void drawSelect(){
- Drawf.dashCircle(x, y, range, Pal.accent);
- }
-
@Override
public void draw(){
Draw.rect(baseRegion, x, y);
diff --git a/core/src/mindustry/world/blocks/defense/turrets/PowerTurret.java b/core/src/mindustry/world/blocks/defense/turrets/PowerTurret.java
index 85e5243e2f..bf365f4439 100644
--- a/core/src/mindustry/world/blocks/defense/turrets/PowerTurret.java
+++ b/core/src/mindustry/world/blocks/defense/turrets/PowerTurret.java
@@ -16,7 +16,7 @@ public class PowerTurret extends Turret{
@Override
public void setStats(){
super.setStats();
- stats.add(BlockStat.damage, shootType.damage, StatUnit.none);
+ stats.add(Stat.damage, shootType.damage, StatUnit.none);
}
@Override
diff --git a/core/src/mindustry/world/blocks/defense/turrets/ReloadTurret.java b/core/src/mindustry/world/blocks/defense/turrets/ReloadTurret.java
new file mode 100644
index 0000000000..33538771a1
--- /dev/null
+++ b/core/src/mindustry/world/blocks/defense/turrets/ReloadTurret.java
@@ -0,0 +1,49 @@
+package mindustry.world.blocks.defense.turrets;
+
+import arc.math.*;
+import arc.util.*;
+import mindustry.type.*;
+import mindustry.world.consumers.*;
+import mindustry.world.meta.*;
+import mindustry.world.meta.values.*;
+
+import static mindustry.Vars.*;
+
+public abstract class ReloadTurret extends BaseTurret{
+ public float reloadTime = 10f;
+
+ public ReloadTurret(String name){
+ super(name);
+ }
+
+ @Override
+ public void setStats(){
+ super.setStats();
+
+ if(acceptCoolant){
+ stats.add(Stat.booster, new BoosterListValue(reloadTime, consumes.get(ConsumeType.liquid).amount, coolantMultiplier, true, l -> consumes.liquidfilters.get(l.id)));
+ }
+ }
+
+ public class ReloadTurretBuild extends BaseTurretBuild{
+ public float reload;
+
+ protected void updateCooling(){
+ float maxUsed = consumes.get(ConsumeType.liquid).amount;
+
+ Liquid liquid = liquids.current();
+
+ float used = Math.min(Math.min(liquids.get(liquid), maxUsed * Time.delta), Math.max(0, ((reloadTime - reload) / coolantMultiplier) / liquid.heatCapacity)) * baseReloadSpeed();
+ reload += used * liquid.heatCapacity * coolantMultiplier;
+ liquids.remove(liquid, used);
+
+ if(Mathf.chance(0.06 * used)){
+ coolEffect.at(x + Mathf.range(size * tilesize / 2f), y + Mathf.range(size * tilesize / 2f));
+ }
+ }
+
+ protected float baseReloadSpeed(){
+ return efficiency();
+ }
+ }
+}
diff --git a/core/src/mindustry/world/blocks/defense/TractorBeamTurret.java b/core/src/mindustry/world/blocks/defense/turrets/TractorBeamTurret.java
similarity index 72%
rename from core/src/mindustry/world/blocks/defense/TractorBeamTurret.java
rename to core/src/mindustry/world/blocks/defense/turrets/TractorBeamTurret.java
index 3808f7c360..debe26f7e6 100644
--- a/core/src/mindustry/world/blocks/defense/TractorBeamTurret.java
+++ b/core/src/mindustry/world/blocks/defense/turrets/TractorBeamTurret.java
@@ -1,4 +1,4 @@
-package mindustry.world.blocks.defense;
+package mindustry.world.blocks.defense.turrets;
import arc.graphics.*;
import arc.graphics.g2d.*;
@@ -9,12 +9,13 @@ import mindustry.annotations.Annotations.*;
import mindustry.entities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
-import mindustry.world.*;
+import mindustry.type.*;
+import mindustry.world.consumers.*;
import mindustry.world.meta.*;
import static mindustry.Vars.*;
-public class TractorBeamTurret extends Block{
+public class TractorBeamTurret extends BaseTurret{
public final int timerTarget = timers++;
public float retargetTime = 5f;
@@ -22,8 +23,6 @@ public class TractorBeamTurret extends Block{
public @Load("@-laser") TextureRegion laser;
public @Load("@-laser-end") TextureRegion laserEnd;
- public float range = 80f;
- public float rotateSpeed = 10;
public float shootCone = 6f;
public float laserWidth = 0.6f;
public float force = 0.3f;
@@ -35,14 +34,11 @@ public class TractorBeamTurret extends Block{
public TractorBeamTurret(String name){
super(name);
- update = true;
- solid = true;
- outlineIcon = true;
- }
+ rotateSpeed = 10f;
+ coolantMultiplier = 1f;
- @Override
- public void drawPlace(int x, int y, int rotation, boolean valid){
- Drawf.dashCircle(x * tilesize + offset, y * tilesize + offset, range, Pal.accent);
+ //disabled due to version mismatch problems
+ acceptCoolant = false;
}
@Override
@@ -54,17 +50,16 @@ public class TractorBeamTurret extends Block{
public void setStats(){
super.setStats();
- stats.add(BlockStat.shootRange, range / tilesize, StatUnit.blocks);
- stats.add(BlockStat.targetsAir, targetAir);
- stats.add(BlockStat.targetsGround, targetGround);
- stats.add(BlockStat.damage, damage * 60f, StatUnit.perSecond);
+ stats.add(Stat.targetsAir, targetAir);
+ stats.add(Stat.targetsGround, targetGround);
+ stats.add(Stat.damage, damage * 60f, StatUnit.perSecond);
}
- public class TractorBeamBuild extends Building{
- public float rotation = 90;
+ public class TractorBeamBuild extends BaseTurretBuild{
public @Nullable Unit target;
public float lastX, lastY, strength;
public boolean any;
+ public float coolant = 1f;
@Override
public void updateTile(){
@@ -74,6 +69,23 @@ public class TractorBeamTurret extends Block{
target = Units.closestEnemy(team, x, y, range, u -> u.checkTarget(targetAir, targetGround));
}
+ //consume coolant
+ if(target != null && acceptCoolant){
+ float maxUsed = consumes.get(ConsumeType.liquid).amount;
+
+ Liquid liquid = liquids.current();
+
+ float used = Math.min(Math.min(liquids.get(liquid), maxUsed * Time.delta), Math.max(0, (1f / coolantMultiplier) / liquid.heatCapacity));
+
+ liquids.remove(liquid, used);
+
+ if(Mathf.chance(0.06 * used)){
+ coolEffect.at(x + Mathf.range(size * tilesize / 2f), y + Mathf.range(size * tilesize / 2f));
+ }
+
+ coolant = 1f + (used * liquid.heatCapacity * coolantMultiplier);
+ }
+
//look at target
if(target != null && target.within(this, range) && target.team() != team && target.type.flying && efficiency() > 0.01f){
any = true;
@@ -98,8 +110,8 @@ public class TractorBeamTurret extends Block{
}
@Override
- public void drawSelect(){
- Drawf.dashCircle(x, y, range, Pal.accent);
+ public float efficiency() {
+ return super.efficiency() * coolant;
}
@Override
diff --git a/core/src/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/mindustry/world/blocks/defense/turrets/Turret.java
index 4199c4b3fb..58abb26b12 100644
--- a/core/src/mindustry/world/blocks/defense/turrets/Turret.java
+++ b/core/src/mindustry/world/blocks/defense/turrets/Turret.java
@@ -12,6 +12,7 @@ import arc.util.*;
import arc.util.io.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
+import mindustry.core.*;
import mindustry.entities.*;
import mindustry.entities.Units.*;
import mindustry.entities.bullet.*;
@@ -20,15 +21,13 @@ import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.logic.*;
import mindustry.type.*;
-import mindustry.world.*;
import mindustry.world.blocks.*;
import mindustry.world.consumers.*;
import mindustry.world.meta.*;
-import mindustry.world.meta.values.*;
import static mindustry.Vars.*;
-public abstract class Turret extends Block{
+public abstract class Turret extends ReloadTurret{
//after being logic-controlled and this amount of time passes, the turret will resume normal AI
public final static float logicControlCooldown = 60 * 2;
@@ -44,8 +43,6 @@ public abstract class Turret extends Block{
public int maxAmmo = 30;
public int ammoPerShot = 1;
public float ammoEjectBack = 1f;
- public float range = 50f;
- public float reloadTime = 10f;
public float inaccuracy = 0f;
public float velocityInaccuracy = 0f;
public int shots = 1;
@@ -53,7 +50,6 @@ public abstract class Turret extends Block{
public float recoilAmount = 1f;
public float restitution = 0.02f;
public float cooldown = 0.02f;
- public float rotateSpeed = 5f; //in degrees per tick
public float shootCone = 8f;
public float shootShake = 0f;
public float xRand = 0f;
@@ -63,11 +59,7 @@ public abstract class Turret extends Block{
public boolean alternate = false;
public boolean targetAir = true;
public boolean targetGround = true;
- public boolean acceptCoolant = true;
- /** How much reload is lowered by for each unit of liquid of heat capacity. */
- public float coolantMultiplier = 5f;
- /** Effect displayed when coolant is used. */
- public Effect coolEffect = Fx.fuelburn;
+
public Sortf unitSort = Unit::dst2;
protected Vec2 tr = new Vec2();
@@ -107,15 +99,10 @@ public abstract class Turret extends Block{
public void setStats(){
super.setStats();
- stats.add(BlockStat.shootRange, range / tilesize, StatUnit.blocks);
- stats.add(BlockStat.inaccuracy, (int)inaccuracy, StatUnit.degrees);
- stats.add(BlockStat.reload, 60f / reloadTime * shots, StatUnit.none);
- stats.add(BlockStat.targetsAir, targetAir);
- stats.add(BlockStat.targetsGround, targetGround);
-
- if(acceptCoolant){
- stats.add(BlockStat.booster, new BoosterListValue(reloadTime, consumes.get(ConsumeType.liquid).amount, coolantMultiplier, true, l -> consumes.liquidfilters.get(l.id)));
- }
+ stats.add(Stat.inaccuracy, (int)inaccuracy, StatUnit.degrees);
+ stats.add(Stat.reload, 60f / reloadTime * shots, StatUnit.none);
+ stats.add(Stat.targetsAir, targetAir);
+ stats.add(Stat.targetsGround, targetGround);
}
@Override
@@ -133,32 +120,22 @@ public abstract class Turret extends Block{
return new TextureRegion[]{baseRegion, region};
}
- @Override
- public void drawPlace(int x, int y, int rotation, boolean valid){
- Drawf.dashCircle(x * tilesize + offset, y * tilesize + offset, range, Pal.placing);
- }
-
public static abstract class AmmoEntry{
public int amount;
public abstract BulletType type();
}
- public class TurretBuild extends Building implements ControlBlock, Ranged{
+ public class TurretBuild extends ReloadTurretBuild implements ControlBlock{
public Seq ammo = new Seq<>();
public int totalAmmo;
- public float reload, rotation = 90, recoil, heat, logicControlTime = -1;
+ public float recoil, heat, logicControlTime = -1;
public int shotCounter;
public boolean logicShooting = false;
public @Nullable Posc target;
public Vec2 targetPos = new Vec2();
public BlockUnitc unit = Nulls.blockUnit;
- @Override
- public float range(){
- return range;
- }
-
@Override
public void created(){
unit = (BlockUnitc)UnitTypes.block.create(team);
@@ -168,7 +145,7 @@ public abstract class Turret extends Block{
@Override
public void control(LAccess type, double p1, double p2, double p3, double p4){
if(type == LAccess.shoot && !unit.isPlayer()){
- targetPos.set((float)p1, (float)p2);
+ targetPos.set(World.unconv((float)p1), World.unconv((float)p2));
logicControlTime = logicControlCooldown;
logicShooting = !Mathf.zero(p3);
}
@@ -196,8 +173,8 @@ public abstract class Turret extends Block{
case ammo -> totalAmmo;
case ammoCapacity -> maxAmmo;
case rotation -> rotation;
- case shootX -> targetPos.x;
- case shootY -> targetPos.y;
+ case shootX -> World.conv(targetPos.x);
+ case shootY -> World.conv(targetPos.y);
case shooting -> (isControlled() ? unit.isShooting() : logicControlled() ? logicShooting : validateTarget()) ? 1 : 0;
default -> super.sense(sensor);
};
@@ -300,11 +277,6 @@ public abstract class Turret extends Block{
}
}
- @Override
- public void drawSelect(){
- Drawf.dashCircle(x, y, range, team.color);
- }
-
@Override
public void handleLiquid(Building source, Liquid liquid, float amount){
if(acceptCoolant && liquids.currentAmount() <= 0.001f){
@@ -314,20 +286,6 @@ public abstract class Turret extends Block{
super.handleLiquid(source, liquid, amount);
}
- protected void updateCooling(){
- float maxUsed = consumes.get(ConsumeType.liquid).amount;
-
- Liquid liquid = liquids.current();
-
- float used = Math.min(Math.min(liquids.get(liquid), maxUsed * Time.delta), Math.max(0, ((reloadTime - reload) / coolantMultiplier) / liquid.heatCapacity)) * baseReloadSpeed();
- reload += used * liquid.heatCapacity * coolantMultiplier;
- liquids.remove(liquid, used);
-
- if(Mathf.chance(0.06 * used)){
- coolEffect.at(x + Mathf.range(size * tilesize / 2f), y + Mathf.range(size * tilesize / 2f));
- }
- }
-
protected boolean validateTarget(){
return !Units.invalidateTarget(target, team, x, y) || isControlled() || logicControlled();
}
@@ -452,10 +410,6 @@ public abstract class Turret extends Block{
ammoUseEffect.at(x - Angles.trnsx(rotation, ammoEjectBack), y - Angles.trnsy(rotation, ammoEjectBack), rotation);
}
- protected float baseReloadSpeed(){
- return efficiency();
- }
-
@Override
public void write(Writes write){
super.write(write);
diff --git a/core/src/mindustry/world/blocks/distribution/Conveyor.java b/core/src/mindustry/world/blocks/distribution/Conveyor.java
index 60ab45f159..9ad1f01bea 100644
--- a/core/src/mindustry/world/blocks/distribution/Conveyor.java
+++ b/core/src/mindustry/world/blocks/distribution/Conveyor.java
@@ -52,7 +52,7 @@ public class Conveyor extends Block implements Autotiler{
super.setStats();
//have to add a custom calculated speed, since the actual movement speed is apparently not linear
- stats.add(BlockStat.itemsMoved, displayedSpeed, StatUnit.itemsSecond);
+ stats.add(Stat.itemsMoved, displayedSpeed, StatUnit.itemsSecond);
}
@Override
diff --git a/core/src/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/mindustry/world/blocks/distribution/ItemBridge.java
index 2d09c69eba..6e310d0e55 100644
--- a/core/src/mindustry/world/blocks/distribution/ItemBridge.java
+++ b/core/src/mindustry/world/blocks/distribution/ItemBridge.java
@@ -202,7 +202,7 @@ public class ItemBridge extends Block{
for(int i = 1; i <= range; i++){
for(int j = 0; j < 4; j++){
- Tile other = tile.getNearby(Geometry.d4[j].x * i, Geometry.d4[j].y * i);
+ Tile other = tile.nearby(Geometry.d4[j].x * i, Geometry.d4[j].y * i);
if(linkValid(tile, other)){
boolean linked = other.pos() == link;
@@ -336,16 +336,18 @@ public class ItemBridge extends Block{
Tile other = world.tile(link);
+ if(items.total() >= itemCapacity) return false;
+
+ if(linked(source)) return true;
+
if(linkValid(tile, other)){
int rel = relativeTo(other);
int rel2 = relativeTo(Edges.getFacingEdge(source, this));
- if(rel == rel2) return false;
- }else{
- return linked(source) && items.total() < itemCapacity;
+ return rel != rel2;
}
- return items.total() < itemCapacity;
+ return false;
}
@Override
@@ -359,16 +361,18 @@ public class ItemBridge extends Block{
Tile other = world.tile(link);
+ if(!(liquids.current() == liquid || liquids.get(liquids.current()) < 0.2f)) return false;
+
+ if(linked(source)) return true;
+
if(linkValid(tile, other)){
int rel = relativeTo(other.x, other.y);
int rel2 = relativeTo(Edges.getFacingEdge(source, this));
- if(rel == rel2) return false;
- }else if(!(linked(source))){
- return false;
+ return rel != rel2;
}
- return (liquids.current() == liquid || liquids.get(liquids.current()) < 0.2f);
+ return false;
}
protected boolean linked(Building source){
diff --git a/core/src/mindustry/world/blocks/distribution/PayloadConveyor.java b/core/src/mindustry/world/blocks/distribution/PayloadConveyor.java
index 7c0bbb7821..08035d9c84 100644
--- a/core/src/mindustry/world/blocks/distribution/PayloadConveyor.java
+++ b/core/src/mindustry/world/blocks/distribution/PayloadConveyor.java
@@ -87,7 +87,7 @@ public class PayloadConveyor extends Block{
}
int ntrns = 1 + size/2;
- Tile next = tile.getNearby(Geometry.d4(rotation).x * ntrns, Geometry.d4(rotation).y * ntrns);
+ Tile next = tile.nearby(Geometry.d4(rotation).x * ntrns, Geometry.d4(rotation).y * ntrns);
blocked = (next != null && next.solid() && !next.block().outputsPayload) || (this.next != null && (this.next.rotation + 2)%4 == rotation);
}
diff --git a/core/src/mindustry/world/blocks/distribution/Router.java b/core/src/mindustry/world/blocks/distribution/Router.java
index 5b107d5a0e..766a1bafff 100644
--- a/core/src/mindustry/world/blocks/distribution/Router.java
+++ b/core/src/mindustry/world/blocks/distribution/Router.java
@@ -1,9 +1,12 @@
package mindustry.world.blocks.distribution;
+import arc.math.*;
+import arc.util.*;
import mindustry.content.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.*;
+import mindustry.world.blocks.*;
import mindustry.world.meta.*;
public class Router extends Block{
@@ -20,10 +23,30 @@ public class Router extends Block{
noUpdateDisabled = true;
}
- public class RouterBuild extends Building{
+ public class RouterBuild extends Building implements ControlBlock{
public Item lastItem;
public Tile lastInput;
public float time;
+ public @Nullable BlockUnitc unit;
+
+ @Override
+ public Unit unit(){
+ if(unit == null){
+ unit = (BlockUnitc)UnitTypes.block.create(team);
+ unit.tile(this);
+ }
+ return (Unit)unit;
+ }
+
+ @Override
+ public boolean canControl(){
+ return size == 1;
+ }
+
+ @Override
+ public boolean shouldAutoTarget(){
+ return false;
+ }
@Override
public void updateTile(){
@@ -72,6 +95,23 @@ public class Router extends Block{
}
public Building getTileTarget(Item item, Tile from, boolean set){
+ if(unit != null && isControlled()){
+ unit.health(health);
+ unit.ammo(unit.type().ammoCapacity * (items.total() > 0 ? 1f : 0f));
+ unit.team(team);
+
+ int angle = Mathf.mod((int)((angleTo(unit.aimX(), unit.aimY()) + 45) / 90), 4);
+
+ if(unit.isShooting()){
+ Building other = nearby(angle);
+ if(other != null && other.acceptItem(this, item)){
+ return other;
+ }
+ }
+
+ return null;
+ }
+
int counter = rotation;
for(int i = 0; i < proximity.size; i++){
Building other = proximity.get((i + counter) % proximity.size);
diff --git a/core/src/mindustry/world/blocks/distribution/StackConveyor.java b/core/src/mindustry/world/blocks/distribution/StackConveyor.java
index 3327c62c15..f3c400ad9b 100644
--- a/core/src/mindustry/world/blocks/distribution/StackConveyor.java
+++ b/core/src/mindustry/world/blocks/distribution/StackConveyor.java
@@ -53,7 +53,7 @@ public class StackConveyor extends Block implements Autotiler{
public void setStats(){
super.setStats();
- stats.add(BlockStat.itemsMoved, Mathf.round(itemCapacity * speed * 60), StatUnit.itemsSecond);
+ stats.add(Stat.itemsMoved, Mathf.round(itemCapacity * speed * 60), StatUnit.itemsSecond);
}
@Override
diff --git a/core/src/mindustry/world/blocks/environment/Floor.java b/core/src/mindustry/world/blocks/environment/Floor.java
index a70056717a..cacf375cef 100644
--- a/core/src/mindustry/world/blocks/environment/Floor.java
+++ b/core/src/mindustry/world/blocks/environment/Floor.java
@@ -183,7 +183,7 @@ public class Floor extends Block{
for(int i = 0; i < 8; i++){
Point2 point = Geometry.d8[i];
- Tile other = tile.getNearby(point);
+ Tile other = tile.nearby(point);
if(other != null && other.floor().cacheLayer == layer && other.floor().edges() != null){
if(!blended.getAndSet(other.floor().id)){
blenders.add(other.floor());
@@ -200,7 +200,7 @@ public class Floor extends Block{
for(int i = 0; i < 8; i++){
Point2 point = Geometry.d8[i];
- Tile other = tile.getNearby(point);
+ Tile other = tile.nearby(point);
if(other != null && doEdge(other.floor()) && other.floor().cacheLayer == cacheLayer && other.floor().edges() != null){
if(!blended.getAndSet(other.floor().id)){
blenders.add(other.floor());
@@ -217,7 +217,7 @@ public class Floor extends Block{
for(Block block : blenders){
for(int i = 0; i < 8; i++){
Point2 point = Geometry.d8[i];
- Tile other = tile.getNearby(point);
+ Tile other = tile.nearby(point);
if(other != null && other.floor() == block){
TextureRegion region = edge((Floor)block, 1 - point.x, 1 - point.y);
Draw.rect(region, tile.worldx(), tile.worldy());
@@ -229,7 +229,7 @@ public class Floor extends Block{
//'new' style of edges with shadows instead of colors, not used currently
protected void drawEdgesFlat(Tile tile, boolean sameLayer){
for(int i = 0; i < 4; i++){
- Tile other = tile.getNearby(i);
+ Tile other = tile.nearby(i);
if(other != null && doEdge(other.floor())){
Color color = other.floor().mapColor;
Draw.color(color.r, color.g, color.b, 1f);
diff --git a/core/src/mindustry/world/blocks/environment/StaticTree.java b/core/src/mindustry/world/blocks/environment/StaticTree.java
index 78c6133d2f..9b1a7063f4 100644
--- a/core/src/mindustry/world/blocks/environment/StaticTree.java
+++ b/core/src/mindustry/world/blocks/environment/StaticTree.java
@@ -21,7 +21,7 @@ public class StaticTree extends StaticWall{
float oy = 0;
for(int i = 0; i < 4; i++){
- if(tile.getNearby(i) != null && tile.getNearby(i).block() instanceof StaticWall){
+ if(tile.nearby(i) != null && tile.nearby(i).block() instanceof StaticWall){
if(i == 0){
r.setWidth(r.width - crop);
diff --git a/core/src/mindustry/world/blocks/experimental/BlockForge.java b/core/src/mindustry/world/blocks/experimental/BlockForge.java
index 52509674a7..251c6820a0 100644
--- a/core/src/mindustry/world/blocks/experimental/BlockForge.java
+++ b/core/src/mindustry/world/blocks/experimental/BlockForge.java
@@ -99,7 +99,7 @@ public class BlockForge extends PayloadAcceptor{
public void buildConfiguration(Table table){
Seq blocks = Vars.content.blocks().select(b -> b.isVisible() && b.size <= 2);
- ItemSelection.buildTable(table, blocks, () -> recipe, block -> recipe = block);
+ ItemSelection.buildTable(table, blocks, () -> recipe, this::configure);
}
@Override
diff --git a/core/src/mindustry/world/blocks/liquid/LiquidJunction.java b/core/src/mindustry/world/blocks/liquid/LiquidJunction.java
index 09e5b70bb0..80881e2c17 100644
--- a/core/src/mindustry/world/blocks/liquid/LiquidJunction.java
+++ b/core/src/mindustry/world/blocks/liquid/LiquidJunction.java
@@ -14,7 +14,7 @@ public class LiquidJunction extends LiquidBlock{
@Override
public void setStats(){
super.setStats();
- stats.remove(BlockStat.liquidCapacity);
+ stats.remove(Stat.liquidCapacity);
}
@Override
diff --git a/core/src/mindustry/world/blocks/logic/LogicBlock.java b/core/src/mindustry/world/blocks/logic/LogicBlock.java
index aecf5d4149..488c44604d 100644
--- a/core/src/mindustry/world/blocks/logic/LogicBlock.java
+++ b/core/src/mindustry/world/blocks/logic/LogicBlock.java
@@ -8,6 +8,7 @@ import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.*;
+import mindustry.core.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.io.*;
@@ -116,8 +117,8 @@ public class LogicBlock extends Block{
public void setStats(){
super.setStats();
- stats.add(BlockStat.linkRange, range / 8, StatUnit.blocks);
- stats.add(BlockStat.instructions, instructionsPerTick * 60, StatUnit.perSecond);
+ stats.add(Stat.linkRange, range / 8, StatUnit.blocks);
+ stats.add(Stat.instructions, instructionsPerTick * 60, StatUnit.perSecond);
}
@Override
@@ -278,10 +279,13 @@ public class LogicBlock extends Block{
//store link objects
executor.links = new Building[links.count(l -> l.valid && l.active)];
+ executor.linkIds.clear();
int index = 0;
for(LogicLink link : links){
if(link.active && link.valid){
- executor.links[index ++] = world.build(link.x, link.y);
+ Building build = world.build(link.x, link.y);
+ executor.links[index ++] = build;
+ if(build != null) executor.linkIds.add(build.id);
}
}
@@ -304,8 +308,8 @@ public class LogicBlock extends Block{
}
asm.getVar("@this").value = this;
- asm.putConst("@thisx", x);
- asm.putConst("@thisy", y);
+ asm.putConst("@thisx", World.conv(x));
+ asm.putConst("@thisy", World.conv(y));
executor.load(asm);
}catch(Exception e){
diff --git a/core/src/mindustry/world/blocks/logic/LogicDisplay.java b/core/src/mindustry/world/blocks/logic/LogicDisplay.java
index cb062259b8..505791e1b0 100644
--- a/core/src/mindustry/world/blocks/logic/LogicDisplay.java
+++ b/core/src/mindustry/world/blocks/logic/LogicDisplay.java
@@ -38,7 +38,7 @@ public class LogicDisplay extends Block{
public void setStats(){
super.setStats();
- stats.add(BlockStat.displaySize, "@x@", displaySize, displaySize);
+ stats.add(Stat.displaySize, "@x@", displaySize, displaySize);
}
public class LogicDisplayBuild extends Building{
diff --git a/core/src/mindustry/world/blocks/logic/MemoryBlock.java b/core/src/mindustry/world/blocks/logic/MemoryBlock.java
index d215238ced..0329744168 100644
--- a/core/src/mindustry/world/blocks/logic/MemoryBlock.java
+++ b/core/src/mindustry/world/blocks/logic/MemoryBlock.java
@@ -18,7 +18,7 @@ public class MemoryBlock extends Block{
public void setStats(){
super.setStats();
- stats.add(BlockStat.memoryCapacity, memoryCapacity, StatUnit.none);
+ stats.add(Stat.memoryCapacity, memoryCapacity, StatUnit.none);
}
public class MemoryBuild extends Building{
diff --git a/core/src/mindustry/world/blocks/power/Battery.java b/core/src/mindustry/world/blocks/power/Battery.java
index 7c1f364b37..e78cb31b3a 100644
--- a/core/src/mindustry/world/blocks/power/Battery.java
+++ b/core/src/mindustry/world/blocks/power/Battery.java
@@ -20,7 +20,7 @@ public class Battery extends PowerDistributor{
super(name);
outputsPower = true;
consumesPower = true;
- flags = EnumSet.of(BlockFlag.powerRes);
+ flags = EnumSet.of(BlockFlag.battery);
}
public class BatteryBuild extends Building{
diff --git a/core/src/mindustry/world/blocks/power/ImpactReactor.java b/core/src/mindustry/world/blocks/power/ImpactReactor.java
index a24fecf2b4..f5dc985d1e 100644
--- a/core/src/mindustry/world/blocks/power/ImpactReactor.java
+++ b/core/src/mindustry/world/blocks/power/ImpactReactor.java
@@ -55,7 +55,7 @@ public class ImpactReactor extends PowerGenerator{
super.setStats();
if(hasItems){
- stats.add(BlockStat.productionTime, itemDuration / 60f, StatUnit.seconds);
+ stats.add(Stat.productionTime, itemDuration / 60f, StatUnit.seconds);
}
}
diff --git a/core/src/mindustry/world/blocks/power/ItemLiquidGenerator.java b/core/src/mindustry/world/blocks/power/ItemLiquidGenerator.java
index 2d82bfa4c7..12b3f6d691 100644
--- a/core/src/mindustry/world/blocks/power/ItemLiquidGenerator.java
+++ b/core/src/mindustry/world/blocks/power/ItemLiquidGenerator.java
@@ -72,7 +72,7 @@ public class ItemLiquidGenerator extends PowerGenerator{
super.setStats();
if(hasItems){
- stats.add(BlockStat.productionTime, itemDuration / 60f, StatUnit.seconds);
+ stats.add(Stat.productionTime, itemDuration / 60f, StatUnit.seconds);
}
}
diff --git a/core/src/mindustry/world/blocks/power/NuclearReactor.java b/core/src/mindustry/world/blocks/power/NuclearReactor.java
index ac449d90db..85fe183993 100644
--- a/core/src/mindustry/world/blocks/power/NuclearReactor.java
+++ b/core/src/mindustry/world/blocks/power/NuclearReactor.java
@@ -5,6 +5,7 @@ import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
+import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.annotations.Annotations.*;
@@ -47,6 +48,7 @@ public class NuclearReactor extends PowerGenerator{
hasItems = true;
hasLiquids = true;
rebuildable = false;
+ flags = EnumSet.of(BlockFlag.reactor);
}
@Override
@@ -54,7 +56,7 @@ public class NuclearReactor extends PowerGenerator{
super.setStats();
if(hasItems){
- stats.add(BlockStat.productionTime, itemDuration / 60f, StatUnit.seconds);
+ stats.add(Stat.productionTime, itemDuration / 60f, StatUnit.seconds);
}
}
diff --git a/core/src/mindustry/world/blocks/power/PowerGenerator.java b/core/src/mindustry/world/blocks/power/PowerGenerator.java
index 2307093f27..ae9453d675 100644
--- a/core/src/mindustry/world/blocks/power/PowerGenerator.java
+++ b/core/src/mindustry/world/blocks/power/PowerGenerator.java
@@ -12,13 +12,13 @@ import mindustry.world.meta.*;
public class PowerGenerator extends PowerDistributor{
/** The amount of power produced per tick in case of an efficiency of 1.0, which represents 100%. */
public float powerProduction;
- public BlockStat generationType = BlockStat.basePowerGeneration;
+ public Stat generationType = Stat.basePowerGeneration;
public PowerGenerator(String name){
super(name);
sync = true;
baseExplosiveness = 5f;
- flags = EnumSet.of(BlockFlag.producer);
+ flags = EnumSet.of(BlockFlag.generator);
}
@Override
diff --git a/core/src/mindustry/world/blocks/power/PowerNode.java b/core/src/mindustry/world/blocks/power/PowerNode.java
index 5d033c99b7..042b03099e 100644
--- a/core/src/mindustry/world/blocks/power/PowerNode.java
+++ b/core/src/mindustry/world/blocks/power/PowerNode.java
@@ -124,8 +124,8 @@ public class PowerNode extends PowerBlock{
public void setStats(){
super.setStats();
- stats.add(BlockStat.powerRange, laserRange, StatUnit.blocks);
- stats.add(BlockStat.powerConnections, maxNodes, StatUnit.none);
+ stats.add(Stat.powerRange, laserRange, StatUnit.blocks);
+ stats.add(Stat.powerConnections, maxNodes, StatUnit.none);
}
@Override
diff --git a/core/src/mindustry/world/blocks/power/ThermalGenerator.java b/core/src/mindustry/world/blocks/power/ThermalGenerator.java
index e29b7a6bdb..154bd02a0c 100644
--- a/core/src/mindustry/world/blocks/power/ThermalGenerator.java
+++ b/core/src/mindustry/world/blocks/power/ThermalGenerator.java
@@ -22,7 +22,7 @@ public class ThermalGenerator extends PowerGenerator{
public void setStats(){
super.setStats();
- stats.add(BlockStat.tiles, attribute, floating);
+ stats.add(Stat.tiles, attribute, floating);
}
@Override
diff --git a/core/src/mindustry/world/blocks/production/AttributeSmelter.java b/core/src/mindustry/world/blocks/production/AttributeSmelter.java
index 987b14e63b..c2650ab030 100644
--- a/core/src/mindustry/world/blocks/production/AttributeSmelter.java
+++ b/core/src/mindustry/world/blocks/production/AttributeSmelter.java
@@ -37,7 +37,7 @@ public class AttributeSmelter extends GenericSmelter{
public void setStats(){
super.setStats();
- stats.add(BlockStat.affinities, attribute, boostScale);
+ stats.add(Stat.affinities, attribute, boostScale);
}
public class AttributeSmelterBuild extends SmelterBuild{
diff --git a/core/src/mindustry/world/blocks/production/Cultivator.java b/core/src/mindustry/world/blocks/production/Cultivator.java
index 2dc97d82f6..a5aede4e25 100644
--- a/core/src/mindustry/world/blocks/production/Cultivator.java
+++ b/core/src/mindustry/world/blocks/production/Cultivator.java
@@ -42,7 +42,7 @@ public class Cultivator extends GenericCrafter{
public void setStats(){
super.setStats();
- stats.add(BlockStat.affinities, attribute);
+ stats.add(Stat.affinities, attribute);
}
@Override
diff --git a/core/src/mindustry/world/blocks/production/Drill.java b/core/src/mindustry/world/blocks/production/Drill.java
index 7b86f1d1f5..ef4ab64b27 100644
--- a/core/src/mindustry/world/blocks/production/Drill.java
+++ b/core/src/mindustry/world/blocks/production/Drill.java
@@ -16,7 +16,9 @@ import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
+import mindustry.world.blocks.environment.*;
import mindustry.world.meta.*;
+import mindustry.world.meta.values.*;
import static mindustry.Vars.*;
@@ -135,29 +137,11 @@ public class Drill extends Block{
public void setStats(){
super.setStats();
- stats.add(BlockStat.drillTier, table -> {
- Seq list = content.blocks().select(b -> b.isFloor() && b.asFloor().itemDrop != null && b.asFloor().itemDrop.hardness <= tier);
+ stats.add(Stat.drillTier, new BlockFilterValue(b -> b instanceof Floor f && f.itemDrop != null && f.itemDrop.hardness <= tier));
- table.table(l -> {
- l.left();
-
- for(int i = 0; i < list.size; i++){
- Block item = list.get(i);
-
- l.image(item.icon(Cicon.small)).size(8 * 3).padRight(2).padLeft(2).padTop(3).padBottom(3);
- l.add(item.localizedName).left().padLeft(1).padRight(4);
- if(i % 5 == 4){
- l.row();
- }
- }
- });
-
-
- });
-
- stats.add(BlockStat.drillSpeed, 60f / drillTime * size * size, StatUnit.itemsSecond);
+ stats.add(Stat.drillSpeed, 60f / drillTime * size * size, StatUnit.itemsSecond);
if(liquidBoostIntensity != 1){
- stats.add(BlockStat.boostEffect, liquidBoostIntensity * liquidBoostIntensity, StatUnit.timesSpeed);
+ stats.add(Stat.boostEffect, liquidBoostIntensity * liquidBoostIntensity, StatUnit.timesSpeed);
}
}
diff --git a/core/src/mindustry/world/blocks/production/Fracker.java b/core/src/mindustry/world/blocks/production/Fracker.java
index d894cf05b5..d2dbd5bf69 100644
--- a/core/src/mindustry/world/blocks/production/Fracker.java
+++ b/core/src/mindustry/world/blocks/production/Fracker.java
@@ -21,7 +21,7 @@ public class Fracker extends SolidPump{
public void setStats(){
super.setStats();
- stats.add(BlockStat.productionTime, itemUseTime / 60f, StatUnit.seconds);
+ stats.add(Stat.productionTime, itemUseTime / 60f, StatUnit.seconds);
}
@Override
@@ -45,7 +45,7 @@ public class Fracker extends SolidPump{
Draw.rect(region, x, y);
super.drawCracks();
- Drawf.liquid(liquidRegion, x, y, liquids.total() / liquidCapacity, result.color);
+ Drawf.liquid(liquidRegion, x, y, liquids.get(result) / liquidCapacity, result.color);
Draw.rect(rotatorRegion, x, y, pumpTime);
Draw.rect(topRegion, x, y);
diff --git a/core/src/mindustry/world/blocks/production/GenericCrafter.java b/core/src/mindustry/world/blocks/production/GenericCrafter.java
index 434c9f4b65..c992be7d78 100644
--- a/core/src/mindustry/world/blocks/production/GenericCrafter.java
+++ b/core/src/mindustry/world/blocks/production/GenericCrafter.java
@@ -2,6 +2,7 @@ package mindustry.world.blocks.production;
import arc.graphics.g2d.*;
import arc.math.*;
+import arc.struct.*;
import arc.util.io.*;
import mindustry.content.*;
import mindustry.entities.*;
@@ -23,9 +24,6 @@ public class GenericCrafter extends Block{
public DrawBlock drawer = new DrawBlock();
- //public Cons drawer = null;
- //public Prov drawIcons = null;
-
public GenericCrafter(String name){
super(name);
update = true;
@@ -34,6 +32,7 @@ public class GenericCrafter extends Block{
idleSound = Sounds.machine;
sync = true;
idleSoundVolume = 0.03f;
+ flags = EnumSet.of(BlockFlag.factory);
}
@Override
@@ -44,14 +43,14 @@ public class GenericCrafter extends Block{
}
super.setStats();
- stats.add(BlockStat.productionTime, craftTime / 60f, StatUnit.seconds);
+ stats.add(Stat.productionTime, craftTime / 60f, StatUnit.seconds);
if(outputItem != null){
- stats.add(BlockStat.output, outputItem);
+ stats.add(Stat.output, outputItem);
}
if(outputLiquid != null){
- stats.add(BlockStat.output, outputLiquid.liquid, outputLiquid.amount, false);
+ stats.add(Stat.output, outputLiquid.liquid, outputLiquid.amount, false);
}
}
diff --git a/core/src/mindustry/world/blocks/production/LiquidConverter.java b/core/src/mindustry/world/blocks/production/LiquidConverter.java
index 84868d9b61..8a9725d42d 100644
--- a/core/src/mindustry/world/blocks/production/LiquidConverter.java
+++ b/core/src/mindustry/world/blocks/production/LiquidConverter.java
@@ -26,8 +26,8 @@ public class LiquidConverter extends GenericCrafter{
@Override
public void setStats(){
super.setStats();
- stats.remove(BlockStat.output);
- stats.add(BlockStat.output, outputLiquid.liquid, outputLiquid.amount * craftTime, false);
+ stats.remove(Stat.output);
+ stats.add(Stat.output, outputLiquid.liquid, outputLiquid.amount * craftTime, false);
}
public class LiquidConverterBuild extends GenericCrafterBuild{
diff --git a/core/src/mindustry/world/blocks/production/PayloadAcceptor.java b/core/src/mindustry/world/blocks/production/PayloadAcceptor.java
index 75cfde865f..3b4693c250 100644
--- a/core/src/mindustry/world/blocks/production/PayloadAcceptor.java
+++ b/core/src/mindustry/world/blocks/production/PayloadAcceptor.java
@@ -95,7 +95,7 @@ public class PayloadAcceptor extends Block{
updatePayload();
payRotation = Mathf.slerpDelta(payRotation, rotate ? rotdeg() : 90f, 0.3f);
- payVector.approachDelta(Vec2.ZERO, payloadSpeed);
+ payVector.approach(Vec2.ZERO, payloadSpeed * delta());
return hasArrived();
}
@@ -105,7 +105,7 @@ public class PayloadAcceptor extends Block{
updatePayload();
- payVector.trns(rotdeg(), payVector.len() + edelta() * payloadSpeed);
+ payVector.trns(rotdeg(), payVector.len() + delta() * payloadSpeed);
payRotation = rotdeg();
if(payVector.len() >= size * tilesize/2f){
diff --git a/core/src/mindustry/world/blocks/production/Pump.java b/core/src/mindustry/world/blocks/production/Pump.java
index fa2f67999f..c4a6313129 100644
--- a/core/src/mindustry/world/blocks/production/Pump.java
+++ b/core/src/mindustry/world/blocks/production/Pump.java
@@ -26,7 +26,7 @@ public class Pump extends LiquidBlock{
@Override
public void setStats(){
super.setStats();
- stats.add(BlockStat.output, 60f * pumpAmount * size * size, StatUnit.liquidSecond);
+ stats.add(Stat.output, 60f * pumpAmount * size * size, StatUnit.liquidSecond);
}
@Override
diff --git a/core/src/mindustry/world/blocks/production/Separator.java b/core/src/mindustry/world/blocks/production/Separator.java
index bcf66984e3..d9b355cc70 100644
--- a/core/src/mindustry/world/blocks/production/Separator.java
+++ b/core/src/mindustry/world/blocks/production/Separator.java
@@ -41,14 +41,14 @@ public class Separator extends Block{
super.setStats();
- stats.add(BlockStat.output, new ItemFilterValue(item -> {
+ stats.add(Stat.output, new ItemFilterValue(item -> {
for(ItemStack i : results){
if(item == i.item) return true;
}
return false;
}));
- stats.add(BlockStat.productionTime, craftTime / 60f, StatUnit.seconds);
+ stats.add(Stat.productionTime, craftTime / 60f, StatUnit.seconds);
}
public class SeparatorBuild extends Building{
diff --git a/core/src/mindustry/world/blocks/production/SolidPump.java b/core/src/mindustry/world/blocks/production/SolidPump.java
index 3b29665fde..d49a6499ac 100644
--- a/core/src/mindustry/world/blocks/production/SolidPump.java
+++ b/core/src/mindustry/world/blocks/production/SolidPump.java
@@ -53,10 +53,10 @@ public class SolidPump extends Pump{
public void setStats(){
super.setStats();
- stats.remove(BlockStat.output);
- stats.add(BlockStat.output, result, 60f * pumpAmount, true);
+ stats.remove(Stat.output);
+ stats.add(Stat.output, result, 60f * pumpAmount, true);
if(attribute != null){
- stats.add(baseEfficiency > 0.0001f ? BlockStat.affinities : BlockStat.tiles, attribute);
+ stats.add(baseEfficiency > 0.0001f ? Stat.affinities : Stat.tiles, attribute);
}
}
diff --git a/core/src/mindustry/world/blocks/sandbox/PowerVoid.java b/core/src/mindustry/world/blocks/sandbox/PowerVoid.java
index c423ba6caf..e97622c609 100644
--- a/core/src/mindustry/world/blocks/sandbox/PowerVoid.java
+++ b/core/src/mindustry/world/blocks/sandbox/PowerVoid.java
@@ -11,8 +11,8 @@ public class PowerVoid extends PowerBlock{
}
@Override
- public void init(){
- super.init();
- stats.remove(BlockStat.powerUse);
+ public void setStats(){
+ super.setStats();
+ stats.remove(Stat.powerUse);
}
}
diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java
index 1acf5d61c3..039c7cc3cf 100644
--- a/core/src/mindustry/world/blocks/storage/CoreBlock.java
+++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java
@@ -47,7 +47,7 @@ public class CoreBlock extends StorageBlock{
update = true;
hasItems = true;
priority = TargetPriority.core;
- flags = EnumSet.of(BlockFlag.core, BlockFlag.producer, BlockFlag.unitModifier);
+ flags = EnumSet.of(BlockFlag.core, BlockFlag.unitModifier);
unitCapModifier = 10;
activeSound = Sounds.respawning;
activeSoundVolume = 1f;
@@ -77,12 +77,16 @@ public class CoreBlock extends StorageBlock{
public void setStats(){
super.setStats();
- stats.add(BlockStat.buildTime, 0, StatUnit.seconds);
+ stats.add(Stat.buildTime, 0, StatUnit.seconds);
+ }
- bars.add("capacity", (CoreBuild e) ->
- new Bar(
- () -> Core.bundle.format("bar.capacity", UI.formatAmount(e.storageCapacity)),
- () -> Pal.items,
+ @Override
+ public void setBars(){
+ super.setBars();
+
+ bars.add("capacity", (CoreBuild e) -> new Bar(
+ () -> Core.bundle.format("bar.capacity", UI.formatAmount(e.storageCapacity)),
+ () -> Pal.items,
() -> e.items.total() / ((float)e.storageCapacity * content.items().count(i -> i.unlockedNow()))
));
}
diff --git a/core/src/mindustry/world/blocks/storage/StorageBlock.java b/core/src/mindustry/world/blocks/storage/StorageBlock.java
index 71045e166b..32b3713350 100644
--- a/core/src/mindustry/world/blocks/storage/StorageBlock.java
+++ b/core/src/mindustry/world/blocks/storage/StorageBlock.java
@@ -30,7 +30,7 @@ public class StorageBlock extends Block{
Tile edge = Edges.getFacingEdge(source, self);
Tile edge2 = Edges.getFacingEdge(self, source);
if(edge != null && edge2 != null){
- Fx.fuelburn.at((edge.worldx() + edge2.worldx())/2f, (edge.worldy() + edge2.worldy())/2f);
+ Fx.coreBurn.at((edge.worldx() + edge2.worldx())/2f, (edge.worldy() + edge2.worldy())/2f);
}
}
}
diff --git a/core/src/mindustry/world/blocks/units/Reconstructor.java b/core/src/mindustry/world/blocks/units/Reconstructor.java
index 326a9f06eb..9374e0d801 100644
--- a/core/src/mindustry/world/blocks/units/Reconstructor.java
+++ b/core/src/mindustry/world/blocks/units/Reconstructor.java
@@ -63,7 +63,23 @@ public class Reconstructor extends UnitBlock{
public void setStats(){
super.setStats();
- stats.add(BlockStat.productionTime, constructTime / 60f, StatUnit.seconds);
+ stats.add(Stat.productionTime, constructTime / 60f, StatUnit.seconds);
+ stats.add(Stat.output, table -> {
+ table.row();
+ for(var upgrade : upgrades){
+ float size = 8*3;
+ if(upgrade[0].unlockedNow() && upgrade[1].unlockedNow()){
+ table.image(upgrade[0].icon(Cicon.small)).size(size).padRight(4).padLeft(10).scaling(Scaling.fit).right();
+ table.add(upgrade[0].localizedName).left();
+
+ table.add("[lightgray] -> ");
+
+ table.image(upgrade[1].icon(Cicon.small)).size(size).padRight(4).scaling(Scaling.fit);
+ table.add(upgrade[1].localizedName).left();
+ table.row();
+ }
+ }
+ });
}
@Override
diff --git a/core/src/mindustry/world/blocks/units/RepairPoint.java b/core/src/mindustry/world/blocks/units/RepairPoint.java
index abcc4bf738..789f7a8901 100644
--- a/core/src/mindustry/world/blocks/units/RepairPoint.java
+++ b/core/src/mindustry/world/blocks/units/RepairPoint.java
@@ -42,7 +42,7 @@ public class RepairPoint extends Block{
@Override
public void setStats(){
super.setStats();
- stats.add(BlockStat.range, repairRadius / tilesize, StatUnit.blocks);
+ stats.add(Stat.range, repairRadius / tilesize, StatUnit.blocks);
}
@Override
diff --git a/core/src/mindustry/world/blocks/units/UnitFactory.java b/core/src/mindustry/world/blocks/units/UnitFactory.java
index 52a3af85c7..500385966e 100644
--- a/core/src/mindustry/world/blocks/units/UnitFactory.java
+++ b/core/src/mindustry/world/blocks/units/UnitFactory.java
@@ -87,7 +87,7 @@ public class UnitFactory extends UnitBlock{
public void setStats(){
super.setStats();
- stats.remove(BlockStat.itemCapacity);
+ stats.remove(Stat.itemCapacity);
}
@Override
diff --git a/core/src/mindustry/world/consumers/Consume.java b/core/src/mindustry/world/consumers/Consume.java
index 410d041a03..3066dbb9bb 100644
--- a/core/src/mindustry/world/consumers/Consume.java
+++ b/core/src/mindustry/world/consumers/Consume.java
@@ -69,5 +69,5 @@ public abstract class Consume{
public abstract boolean valid(Building entity);
- public abstract void display(BlockStats stats);
+ public abstract void display(Stats stats);
}
diff --git a/core/src/mindustry/world/consumers/ConsumeItemDynamic.java b/core/src/mindustry/world/consumers/ConsumeItemDynamic.java
index a2dd079c20..0c18e77741 100644
--- a/core/src/mindustry/world/consumers/ConsumeItemDynamic.java
+++ b/core/src/mindustry/world/consumers/ConsumeItemDynamic.java
@@ -73,7 +73,7 @@ public class ConsumeItemDynamic extends Consume{
}
@Override
- public void display(BlockStats stats){
+ public void display(Stats stats){
//should be handled by the block
}
}
diff --git a/core/src/mindustry/world/consumers/ConsumeItemFilter.java b/core/src/mindustry/world/consumers/ConsumeItemFilter.java
index e9e98041c4..93d70a46f3 100644
--- a/core/src/mindustry/world/consumers/ConsumeItemFilter.java
+++ b/core/src/mindustry/world/consumers/ConsumeItemFilter.java
@@ -70,7 +70,7 @@ public class ConsumeItemFilter extends Consume{
}
@Override
- public void display(BlockStats stats){
- stats.add(booster ? BlockStat.booster : BlockStat.input, new ItemFilterValue(filter));
+ public void display(Stats stats){
+ stats.add(booster ? Stat.booster : Stat.input, new ItemFilterValue(filter));
}
}
diff --git a/core/src/mindustry/world/consumers/ConsumeItems.java b/core/src/mindustry/world/consumers/ConsumeItems.java
index 01909e2a14..f43746db87 100644
--- a/core/src/mindustry/world/consumers/ConsumeItems.java
+++ b/core/src/mindustry/world/consumers/ConsumeItems.java
@@ -63,7 +63,7 @@ public class ConsumeItems extends Consume{
}
@Override
- public void display(BlockStats stats){
- stats.add(booster ? BlockStat.booster : BlockStat.input, new ItemListValue(items));
+ public void display(Stats stats){
+ stats.add(booster ? Stat.booster : Stat.input, new ItemListValue(items));
}
}
diff --git a/core/src/mindustry/world/consumers/ConsumeLiquid.java b/core/src/mindustry/world/consumers/ConsumeLiquid.java
index 90f3bf0687..839b59c607 100644
--- a/core/src/mindustry/world/consumers/ConsumeLiquid.java
+++ b/core/src/mindustry/world/consumers/ConsumeLiquid.java
@@ -45,7 +45,7 @@ public class ConsumeLiquid extends ConsumeLiquidBase{
}
@Override
- public void display(BlockStats stats){
- stats.add(booster ? BlockStat.booster : BlockStat.input, liquid, amount * timePeriod, timePeriod == 60);
+ public void display(Stats stats){
+ stats.add(booster ? Stat.booster : Stat.input, liquid, amount * timePeriod, timePeriod == 60);
}
}
diff --git a/core/src/mindustry/world/consumers/ConsumeLiquidFilter.java b/core/src/mindustry/world/consumers/ConsumeLiquidFilter.java
index 962023488b..851cf75fd2 100644
--- a/core/src/mindustry/world/consumers/ConsumeLiquidFilter.java
+++ b/core/src/mindustry/world/consumers/ConsumeLiquidFilter.java
@@ -49,7 +49,7 @@ public class ConsumeLiquidFilter extends ConsumeLiquidBase{
}
@Override
- public void display(BlockStats stats){
- stats.add(booster ? BlockStat.booster : BlockStat.input, new LiquidFilterValue(filter, amount * timePeriod, timePeriod == 60f));
+ public void display(Stats stats){
+ stats.add(booster ? Stat.booster : Stat.input, new LiquidFilterValue(filter, amount * timePeriod, timePeriod == 60f));
}
}
diff --git a/core/src/mindustry/world/consumers/ConsumePower.java b/core/src/mindustry/world/consumers/ConsumePower.java
index 2dc55dbb11..67b23d6c4c 100644
--- a/core/src/mindustry/world/consumers/ConsumePower.java
+++ b/core/src/mindustry/world/consumers/ConsumePower.java
@@ -54,11 +54,11 @@ public class ConsumePower extends Consume{
}
@Override
- public void display(BlockStats stats){
+ public void display(Stats stats){
if(buffered){
- stats.add(BlockStat.powerCapacity, capacity, StatUnit.none);
+ stats.add(Stat.powerCapacity, capacity, StatUnit.none);
}else{
- stats.add(BlockStat.powerUse, usage * 60f, StatUnit.powerSecond);
+ stats.add(Stat.powerUse, usage * 60f, StatUnit.powerSecond);
}
}
diff --git a/core/src/mindustry/world/consumers/Consumers.java b/core/src/mindustry/world/consumers/Consumers.java
index 4ce410aa04..a811a24d52 100644
--- a/core/src/mindustry/world/consumers/Consumers.java
+++ b/core/src/mindustry/world/consumers/Consumers.java
@@ -109,7 +109,7 @@ public class Consumers{
return optionalResults;
}
- public void display(BlockStats stats){
+ public void display(Stats stats){
for(Consume c : map){
if(c != null){
c.display(stats);
diff --git a/core/src/mindustry/world/meta/BlockFlag.java b/core/src/mindustry/world/meta/BlockFlag.java
index 5c9bf2e920..a3fe674e37 100644
--- a/core/src/mindustry/world/meta/BlockFlag.java
+++ b/core/src/mindustry/world/meta/BlockFlag.java
@@ -4,18 +4,22 @@ package mindustry.world.meta;
public enum BlockFlag{
/** Enemy core; primary target for all units. */
core,
- /** Producer of important goods. */
- producer,
- /** A turret. */
+ /** Something that generates power. */
+ generator,
+ /** Any turret. */
turret,
+ /** A block that transforms resources. */
+ factory,
/** Repair point. */
repair,
/** Rally point. */
rally,
/** Block that stored power for resupply. */
- powerRes,
+ battery,
/** Block used for resupply. */
resupply,
+ /** Any reactor block. */
+ reactor,
/** Any block that boosts unit capacity. */
unitModifier;
diff --git a/core/src/mindustry/world/meta/BlockStat.java b/core/src/mindustry/world/meta/BlockStat.java
deleted file mode 100644
index 05e45acbfe..0000000000
--- a/core/src/mindustry/world/meta/BlockStat.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package mindustry.world.meta;
-
-import arc.*;
-
-import java.util.*;
-
-/** Describes one type of stat for a block. */
-public enum BlockStat{
- health(StatCategory.general),
- size(StatCategory.general),
- displaySize(StatCategory.general),
- buildTime(StatCategory.general),
- buildCost(StatCategory.general),
- memoryCapacity(StatCategory.general),
-
- itemCapacity(StatCategory.items),
- itemsMoved(StatCategory.items),
- launchTime(StatCategory.items),
- maxConsecutive(StatCategory.items),
-
- liquidCapacity(StatCategory.liquids),
-
- powerCapacity(StatCategory.power),
- powerUse(StatCategory.power),
- powerDamage(StatCategory.power),
- powerRange(StatCategory.power),
- powerConnections(StatCategory.power),
- basePowerGeneration(StatCategory.power),
-
- tiles(StatCategory.crafting),
- input(StatCategory.crafting),
- output(StatCategory.crafting),
- productionTime(StatCategory.crafting),
- drillTier(StatCategory.crafting),
- drillSpeed(StatCategory.crafting),
- maxUnits(StatCategory.crafting),
- linkRange(StatCategory.crafting),
- instructions(StatCategory.crafting),
-
- speedIncrease(StatCategory.shooting),
- repairTime(StatCategory.shooting),
- range(StatCategory.shooting),
- shootRange(StatCategory.shooting),
- inaccuracy(StatCategory.shooting),
- shots(StatCategory.shooting),
- reload(StatCategory.shooting),
- powerShot(StatCategory.shooting),
- targetsAir(StatCategory.shooting),
- targetsGround(StatCategory.shooting),
- damage(StatCategory.shooting),
- ammo(StatCategory.shooting),
- shieldHealth(StatCategory.shooting),
- cooldownTime(StatCategory.shooting),
-
- booster(StatCategory.optional),
- boostEffect(StatCategory.optional),
- affinities(StatCategory.optional);
-
- public final StatCategory category;
-
- BlockStat(StatCategory category){
- this.category = category;
- }
-
- public String localized(){
- return Core.bundle.get("blocks." + name().toLowerCase(Locale.ROOT));
- }
-}
diff --git a/core/src/mindustry/world/meta/Stat.java b/core/src/mindustry/world/meta/Stat.java
new file mode 100644
index 0000000000..94e4c17b2c
--- /dev/null
+++ b/core/src/mindustry/world/meta/Stat.java
@@ -0,0 +1,85 @@
+package mindustry.world.meta;
+
+import arc.*;
+
+import java.util.*;
+
+/** Describes one type of stat for content. */
+public enum Stat{
+ health,
+ size,
+ displaySize,
+ buildTime,
+ buildCost,
+ memoryCapacity,
+ explosiveness,
+ flammability,
+ radioactivity,
+ heatCapacity,
+ viscosity,
+ temperature,
+ speed,
+ buildSpeed,
+ mineSpeed,
+ mineTier,
+ baseDeflectChance,
+ lightningChance,
+ lightningDamage,
+
+ itemCapacity(StatCat.items),
+ itemsMoved(StatCat.items),
+ launchTime(StatCat.items),
+ maxConsecutive(StatCat.items),
+
+ liquidCapacity(StatCat.liquids),
+
+ powerCapacity(StatCat.power),
+ powerUse(StatCat.power),
+ powerDamage(StatCat.power),
+ powerRange(StatCat.power),
+ powerConnections(StatCat.power),
+ basePowerGeneration(StatCat.power),
+
+ tiles(StatCat.crafting),
+ input(StatCat.crafting),
+ output(StatCat.crafting),
+ productionTime(StatCat.crafting),
+ drillTier(StatCat.crafting),
+ drillSpeed(StatCat.crafting),
+ maxUnits(StatCat.crafting),
+ linkRange(StatCat.crafting),
+ instructions(StatCat.crafting),
+
+ speedIncrease(StatCat.shooting),
+ repairTime(StatCat.shooting),
+ range(StatCat.shooting),
+ shootRange(StatCat.shooting),
+ inaccuracy(StatCat.shooting),
+ shots(StatCat.shooting),
+ reload(StatCat.shooting),
+ powerShot(StatCat.shooting),
+ targetsAir(StatCat.shooting),
+ targetsGround(StatCat.shooting),
+ damage(StatCat.shooting),
+ ammo(StatCat.shooting),
+ shieldHealth(StatCat.shooting),
+ cooldownTime(StatCat.shooting),
+
+ booster(StatCat.optional),
+ boostEffect(StatCat.optional),
+ affinities(StatCat.optional);
+
+ public final StatCat category;
+
+ Stat(StatCat category){
+ this.category = category;
+ }
+
+ Stat(){
+ this.category = StatCat.general;
+ }
+
+ public String localized(){
+ return Core.bundle.get("stat." + name().toLowerCase(Locale.ROOT));
+ }
+}
diff --git a/core/src/mindustry/world/meta/StatCategory.java b/core/src/mindustry/world/meta/StatCat.java
similarity index 91%
rename from core/src/mindustry/world/meta/StatCategory.java
rename to core/src/mindustry/world/meta/StatCat.java
index e6c91b04bb..8dfd42d3c5 100644
--- a/core/src/mindustry/world/meta/StatCategory.java
+++ b/core/src/mindustry/world/meta/StatCat.java
@@ -3,7 +3,7 @@ package mindustry.world.meta;
import arc.*;
/** A specific category for a stat. */
-public enum StatCategory{
+public enum StatCat{
general,
power,
liquids,
diff --git a/core/src/mindustry/world/meta/BlockStats.java b/core/src/mindustry/world/meta/Stats.java
similarity index 55%
rename from core/src/mindustry/world/meta/BlockStats.java
rename to core/src/mindustry/world/meta/Stats.java
index ff93a217a9..68f96ff260 100644
--- a/core/src/mindustry/world/meta/BlockStats.java
+++ b/core/src/mindustry/world/meta/Stats.java
@@ -2,54 +2,71 @@ package mindustry.world.meta;
import arc.struct.ObjectMap.*;
import arc.struct.*;
+import arc.util.*;
import mindustry.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.meta.values.*;
/** Hold and organizes a list of block stats. */
-public class BlockStats{
- private final OrderedMap>> map = new OrderedMap<>();
+public class Stats{
+ /** Whether to display stats with categories. If false, categories are completely ignored during display. */
+ public boolean useCategories = false;
+ /** Whether these stats are initialized yet. */
+ public boolean intialized = false;
+
+ @Nullable
+ private OrderedMap>> map;
private boolean dirty;
/** Adds a single float value with this stat, formatted to 2 decimal places. */
- public void add(BlockStat stat, float value, StatUnit unit){
+ public void add(Stat stat, float value, StatUnit unit){
add(stat, new NumberValue(value, unit));
}
+ /** Adds a single float value with this stat and no unit. */
+ public void add(Stat stat, float value){
+ add(stat, value, StatUnit.none);
+ }
+
+ /** Adds an integer percent stat value. Value is assumed to be in the 0-1 range. */
+ public void addPercent(Stat stat, float value){
+ add(stat, new NumberValue((int)(value * 100), StatUnit.percent));
+ }
+
/** Adds a single y/n boolean value. */
- public void add(BlockStat stat, boolean value){
+ public void add(Stat stat, boolean value){
add(stat, new BooleanValue(value));
}
/** Adds an item value. */
- public void add(BlockStat stat, Item item){
+ public void add(Stat stat, Item item){
add(stat, new ItemListValue(new ItemStack(item, 1)));
}
/** Adds an item value. */
- public void add(BlockStat stat, ItemStack item){
+ public void add(Stat stat, ItemStack item){
add(stat, new ItemListValue(item));
}
/** Adds an item value. */
- public void add(BlockStat stat, Liquid liquid, float amount, boolean perSecond){
+ public void add(Stat stat, Liquid liquid, float amount, boolean perSecond){
add(stat, new LiquidValue(liquid, amount, perSecond));
}
- public void add(BlockStat stat, Attribute attr){
+ public void add(Stat stat, Attribute attr){
add(stat, attr, false, 1f);
}
- public void add(BlockStat stat, Attribute attr, float scale){
+ public void add(Stat stat, Attribute attr, float scale){
add(stat, attr, false, scale);
}
- public void add(BlockStat stat, Attribute attr, boolean floating){
+ public void add(Stat stat, Attribute attr, boolean floating){
add(stat, attr, floating, 1f);
}
- public void add(BlockStat stat, Attribute attr, boolean floating, float scale){
+ public void add(Stat stat, Attribute attr, boolean floating, float scale){
for(Block block : Vars.content.blocks()){
if(!block.isFloor() || block.asFloor().attributes.get(attr) == 0 || (block.asFloor().isLiquid && !floating)) continue;
add(stat, new FloorEfficiencyValue(block.asFloor(), block.asFloor().attributes.get(attr) * scale));
@@ -57,12 +74,14 @@ public class BlockStats{
}
/** Adds a single string value with this stat. */
- public void add(BlockStat stat, String format, Object... args){
+ public void add(Stat stat, String format, Object... args){
add(stat, new StringValue(format, args));
}
/** Adds a stat value. */
- public void add(BlockStat stat, StatValue value){
+ public void add(Stat stat, StatValue value){
+ if(map == null) map = new OrderedMap<>();
+
if(!map.containsKey(stat.category)){
map.put(stat.category, new OrderedMap<>());
}
@@ -73,7 +92,9 @@ public class BlockStats{
}
/** Removes a stat, if it exists. */
- public void remove(BlockStat stat){
+ public void remove(Stat stat){
+ if(map == null) map = new OrderedMap<>();
+
if(!map.containsKey(stat.category) || !map.get(stat.category).containsKey(stat)){
throw new RuntimeException("No stat entry found: \"" + stat + "\" in block.");
}
@@ -83,11 +104,13 @@ public class BlockStats{
dirty = true;
}
- public OrderedMap>> toMap(){
+ public OrderedMap>> toMap(){
+ if(map == null) map = new OrderedMap<>();
+
//sort stats by index if they've been modified
if(dirty){
map.orderedKeys().sort();
- for(Entry>> entry : map.entries()){
+ for(Entry>> entry : map.entries()){
entry.value.orderedKeys().sort();
}
diff --git a/core/src/mindustry/world/meta/values/BlockFilterValue.java b/core/src/mindustry/world/meta/values/BlockFilterValue.java
new file mode 100644
index 0000000000..3c4d0fe56e
--- /dev/null
+++ b/core/src/mindustry/world/meta/values/BlockFilterValue.java
@@ -0,0 +1,37 @@
+package mindustry.world.meta.values;
+
+import arc.func.*;
+import arc.scene.ui.layout.*;
+import arc.struct.*;
+import mindustry.ui.*;
+import mindustry.world.*;
+import mindustry.world.meta.*;
+
+import static mindustry.Vars.*;
+
+public class BlockFilterValue implements StatValue{
+ public final Boolf pred;
+
+ public BlockFilterValue(Boolf pred){
+ this.pred = pred;
+ }
+
+ @Override
+ public void display(Table table){
+ Seq list = content.blocks().select(pred);
+
+ table.table(l -> {
+ l.left();
+
+ for(int i = 0; i < list.size; i++){
+ Block item = list.get(i);
+
+ l.image(item.icon(Cicon.small)).size(8 * 3).padRight(2).padLeft(2).padTop(3).padBottom(3);
+ l.add(item.localizedName).left().padLeft(1).padRight(4);
+ if(i % 5 == 4){
+ l.row();
+ }
+ }
+ });
+ }
+}
diff --git a/core/src/mindustry/world/meta/values/BlockListValue.java b/core/src/mindustry/world/meta/values/BlockListValue.java
new file mode 100644
index 0000000000..a1cd5adffe
--- /dev/null
+++ b/core/src/mindustry/world/meta/values/BlockListValue.java
@@ -0,0 +1,33 @@
+package mindustry.world.meta.values;
+
+import arc.scene.ui.layout.*;
+import arc.struct.*;
+import mindustry.ui.*;
+import mindustry.world.*;
+import mindustry.world.meta.*;
+
+public class BlockListValue implements StatValue{
+ public final Seq list;
+
+ public BlockListValue(Seq list){
+ this.list = list;
+ }
+
+ @Override
+ public void display(Table table){
+
+ table.table(l -> {
+ l.left();
+
+ for(int i = 0; i < list.size; i++){
+ Block item = list.get(i);
+
+ l.image(item.icon(Cicon.small)).size(8 * 3).padRight(2).padLeft(2).padTop(3).padBottom(3);
+ l.add(item.localizedName).left().padLeft(1).padRight(4);
+ if(i % 5 == 4){
+ l.row();
+ }
+ }
+ });
+ }
+}
diff --git a/desktop/src/mindustry/desktop/steam/SStats.java b/desktop/src/mindustry/desktop/steam/SStats.java
index 925c670223..9338aafc5b 100644
--- a/desktop/src/mindustry/desktop/steam/SStats.java
+++ b/desktop/src/mindustry/desktop/steam/SStats.java
@@ -7,7 +7,7 @@ import mindustry.*;
import mindustry.content.*;
import mindustry.entities.units.*;
import mindustry.game.EventType.*;
-import mindustry.game.Stats.*;
+import mindustry.game.GameStats.*;
import mindustry.gen.*;
import mindustry.type.*;
diff --git a/fastlane/metadata/android/en-US/changelogs/29672.txt b/fastlane/metadata/android/en-US/changelogs/29672.txt
new file mode 100644
index 0000000000..04c1a277ad
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/29672.txt
@@ -0,0 +1,6 @@
+- Fixed "host game" crash, as well as some other prominent bugs
+- Logic: Breaking change: All coordinates are now in tiles, not in "world units"
+- Logic: Added sensors for ammo (units/turrets)
+- Campaign: Added research button in mobile multiplayer (check pause menu)
+- Campaign: Added tech tree sharing in multiplayer - only the host can research
+- Campaign: Re-added sector invasions, any sector near an enemy base can be invaded
diff --git a/gradle.properties b/gradle.properties
index 0ebd9ffd28..1642144d7a 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,3 +1,3 @@
org.gradle.daemon=true
org.gradle.jvmargs=-Xms256m -Xmx1024m
-archash=46ebdb4aeb1e03ca6b3b4c27a93533dc92278a33
+archash=4965359d2857f529f7010c73bc89876d347fa424
diff --git a/server/src/mindustry/server/ServerControl.java b/server/src/mindustry/server/ServerControl.java
index 48f529b187..7e1be67c52 100644
--- a/server/src/mindustry/server/ServerControl.java
+++ b/server/src/mindustry/server/ServerControl.java
@@ -30,6 +30,7 @@ import java.time.*;
import java.time.format.*;
import java.util.*;
+import static arc.util.ColorCodes.*;
import static arc.util.Log.*;
import static mindustry.Vars.*;
@@ -37,7 +38,7 @@ public class ServerControl implements ApplicationListener{
private static final int roundExtraTime = 12;
private static final int maxLogLength = 1024 * 512;
- protected static String[] tags = {"&lc&fb[D]", "&lg&fb[I]", "&ly&fb[W]", "&lr&fb[E]", ""};
+ protected static String[] tags = {"&lc&fb[D]&fr", "&lb&fb[I]&fr", "&ly&fb[W]&fr", "&lr&fb[E]", ""};
protected static DateTimeFormatter dateTime = DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm:ss"),
autosaveDate = DateTimeFormatter.ofPattern("MM-dd-yyyy_HH-mm-ss");
@@ -74,22 +75,27 @@ public class ServerControl implements ApplicationListener{
lastMode = Gamemode.survival;
}
- Log.setLogger((level, text) -> {
- String result = "[" + dateTime.format(LocalDateTime.now()) + "] " + format(tags[level.ordinal()] + " " + text + "&fr");
+ logger = (level1, text) -> {
+ String result = bold + lightBlack + "[" + dateTime.format(LocalDateTime.now()) + "] " + reset + format(tags[level1.ordinal()] + " " + text + "&fr");
System.out.println(result);
if(Config.logging.bool()){
- logToFile("[" + dateTime.format(LocalDateTime.now()) + "] " + formatColors(tags[level.ordinal()] + " " + text + "&fr", false));
+ logToFile("[" + dateTime.format(LocalDateTime.now()) + "] " + formatColors(tags[level1.ordinal()] + " " + text + "&fr", false));
}
if(socketOutput != null){
try{
socketOutput.println(formatColors(text + "&fr", false));
- }catch(Throwable e){
- err("Error occurred logging to socket: @", e.getClass().getSimpleName());
+ }catch(Throwable e1){
+ err("Error occurred logging to socket: @", e1.getClass().getSimpleName());
}
}
- });
+ };
+
+ formatter = (text, useColors, arg) -> {
+ text = Strings.format(text.replace("@", "&fb&lb@&fr"), arg);
+ return useColors ? addColors(text) : removeColors(text);
+ };
Time.setDeltaProvider(() -> Core.graphics.getDeltaTime() * 60f);
@@ -115,12 +121,12 @@ public class ServerControl implements ApplicationListener{
if(args.length > 0){
commands.addAll(Strings.join(" ", args).split(","));
- info("&lmFound @ command-line arguments to parse.", commands.size);
+ info("Found @ command-line arguments to parse.", commands.size);
}
if(!Config.startCommands.string().isEmpty()){
String[] startup = Strings.join(" ", Config.startCommands.string()).split(",");
- info("&lmFound @ startup commands.", startup.length);
+ info("Found @ startup commands.", startup.length);
commands.addAll(startup);
}
@@ -128,7 +134,7 @@ public class ServerControl implements ApplicationListener{
CommandResponse response = handler.handleMessage(s);
if(response.type != ResponseType.valid){
err("Invalid command argument sent: '@': @", s, response.type.name());
- err("Argument usage: &lc , ");
+ err("Argument usage: &lb , ");
}
}
});
@@ -141,7 +147,7 @@ public class ServerControl implements ApplicationListener{
if(Version.build == -1){
warn("&lyYour server is running a custom build, which means that client checking is disabled.");
- warn("&lyIt is highly advised to specify which version you're using by building with gradle args &lc-Pbuildversion=&lm&ly.");
+ warn("&lyIt is highly advised to specify which version you're using by building with gradle args &lb&fb-Pbuildversion=&lr");
}
//set up default shuffle mode
@@ -154,9 +160,9 @@ public class ServerControl implements ApplicationListener{
Events.on(GameOverEvent.class, event -> {
if(inExtraRound) return;
if(state.rules.waves){
- info("&lcGame over! Reached wave &ly@&lc with &ly@&lc players online on map &ly@&lc.", state.wave, Groups.player.size(), Strings.capitalize(state.map.name()));
+ info("Game over! Reached wave @ with @ players online on map @.", state.wave, Groups.player.size(), Strings.capitalize(state.map.name()));
}else{
- info("&lcGame over! Team &ly@&lc is victorious with &ly@&lc players online on map &ly@&lc.", event.winner.name, Groups.player.size(), Strings.capitalize(state.map.name()));
+ info("Game over! Team @ is victorious with @ players online on map @.", event.winner.name, Groups.player.size(), Strings.capitalize(state.map.name()));
}
//set next map to be played
@@ -209,11 +215,11 @@ public class ServerControl implements ApplicationListener{
String fileName = "auto_" + mapName + "_" + date + "." + saveExtension;
Fi file = saveDirectory.child(fileName);
- info("&lbAutosaving...");
+ info("Autosaving...");
try{
SaveIO.save(file);
- info("&lbAutosave completed.");
+ info("Autosave completed.");
}catch(Throwable e){
err("Autosave failed.", e);
}
@@ -241,25 +247,25 @@ public class ServerControl implements ApplicationListener{
Timer.schedule(() -> Core.settings.forceSave(), saveInterval, saveInterval);
if(!mods.list().isEmpty()){
- info("&lc@ mods loaded.", mods.list().size);
+ info("@ mods loaded.", mods.list().size);
}
toggleSocket(Config.socketInput.bool());
- info("&lcServer loaded. Type &ly'help'&lc for help.");
+ info("Server loaded. Type @ for help.", "'help'");
}
private void registerCommands(){
handler.register("help", "Displays this command list.", arg -> {
info("Commands:");
for(Command command : handler.getCommandList()){
- info(" &y" + command.text + (command.paramText.isEmpty() ? "" : " ") + command.paramText + " - &lm" + command.description);
+ info(" &b&lb " + command.text + (command.paramText.isEmpty() ? "" : " &lc&fi") + command.paramText + "&fr - &lw" + command.description);
}
});
handler.register("version", "Displays server version info.", arg -> {
- info("&lmVersion: &lyMindustry @-@ @ / build @", Version.number, Version.modifier, Version.type, Version.build + (Version.revision == 0 ? "" : "." + Version.revision));
- info("&lmJava Version: &ly@", System.getProperty("java.version"));
+ info("Version: Mindustry @-@ @ / build @", Version.number, Version.modifier, Version.type, Version.build + (Version.revision == 0 ? "" : "." + Version.revision));
+ info("Java Version: @", System.getProperty("java.version"));
});
handler.register("exit", "Exit the server application.", arg -> {
@@ -299,7 +305,7 @@ public class ServerControl implements ApplicationListener{
result = maps.all().find(map -> map.name().equalsIgnoreCase(arg[0].replace('_', ' ')) || map.name().equalsIgnoreCase(arg[0]));
if(result == null){
- err("No map with name &y'@'&lr found.", arg[0]);
+ err("No map with name '@' found.", arg[0]);
return;
}
}else{
@@ -329,21 +335,21 @@ public class ServerControl implements ApplicationListener{
if(!maps.all().isEmpty()){
info("Maps:");
for(Map map : maps.all()){
- info(" &ly@: &lb&fi@ / @x@", map.name(), map.custom ? "Custom" : "Default", map.width, map.height);
+ info(" @: &fi@ / @x@", map.name(), map.custom ? "Custom" : "Default", map.width, map.height);
}
}else{
info("No maps found.");
}
- info("&lyMap directory: &lb&fi@", customMapDirectory.file().getAbsoluteFile().toString());
+ info("Map directory: &fi@", customMapDirectory.file().getAbsoluteFile().toString());
});
handler.register("reloadmaps", "Reload all maps from disk.", arg -> {
int beforeMaps = maps.all().size;
maps.reload();
if(maps.all().size > beforeMaps){
- info("&lc@&ly new map(s) found and reloaded.", maps.all().size - beforeMaps);
+ info("@ new map(s) found and reloaded.", maps.all().size - beforeMaps);
}else{
- info("&lyMaps reloaded.");
+ info("Maps reloaded.");
}
});
@@ -352,23 +358,23 @@ public class ServerControl implements ApplicationListener{
info("Status: &rserver closed");
}else{
info("Status:");
- info(" &lyPlaying on map &fi@&fb &lb/&ly Wave @", Strings.capitalize(state.map.name()), state.wave);
+ info(" Playing on map &fi@ / Wave @", Strings.capitalize(state.map.name()), state.wave);
if(state.rules.waves){
- info("&ly @ enemies.", state.enemies);
+ info(" @ enemies.", state.enemies);
}else{
- info("&ly @ seconds until next wave.", (int)(state.wavetime / 60));
+ info(" @ seconds until next wave.", (int)(state.wavetime / 60));
}
- info(" &ly@ FPS, @ MB used.", Core.graphics.getFramesPerSecond(), Core.app.getJavaHeap() / 1024 / 1024);
+ info(" @ FPS, @ MB used.", Core.graphics.getFramesPerSecond(), Core.app.getJavaHeap() / 1024 / 1024);
if(Groups.player.size() > 0){
- info(" &lyPlayers: @", Groups.player.size());
+ info(" Players: @", Groups.player.size());
for(Player p : Groups.player){
- info(" &y@ / @", p.name(), p.uuid());
+ info(" @ / @", p.name, p.uuid());
}
}else{
- info(" &lyNo players connected.");
+ info(" No players connected.");
}
}
});
@@ -377,30 +383,30 @@ public class ServerControl implements ApplicationListener{
if(!mods.list().isEmpty()){
info("Mods:");
for(LoadedMod mod : mods.list()){
- info(" &ly@ &lcv@", mod.meta.displayName(), mod.meta.version);
+ info(" @ &fi@", mod.meta.displayName(), mod.meta.version);
}
}else{
info("No mods found.");
}
- info("&lyMod directory: &lb&fi@", modDirectory.file().getAbsoluteFile().toString());
+ info("Mod directory: &fi@", modDirectory.file().getAbsoluteFile().toString());
});
handler.register("mod", "", "Display information about a loaded plugin.", arg -> {
LoadedMod mod = mods.list().find(p -> p.meta.name.equalsIgnoreCase(arg[0]));
if(mod != null){
- info("Name: &ly@", mod.meta.displayName());
- info("Internal Name: &ly@", mod.name);
- info("Version: &ly@", mod.meta.version);
- info("Author: &ly@", mod.meta.author);
- info("Path: &ly@", mod.file.path());
- info("Description: &ly@", mod.meta.description);
+ info("Name: @", mod.meta.displayName());
+ info("Internal Name: @", mod.name);
+ info("Version: @", mod.meta.version);
+ info("Author: @", mod.meta.author);
+ info("Path: @", mod.file.path());
+ info("Description: @", mod.meta.description);
}else{
- info("No mod with name &ly'@'&lg found.");
+ info("No mod with name '@' found.");
}
});
handler.register("js", "", "Run arbitrary Javascript.", arg -> {
- info("&lc" + mods.getScripts().runConsole(arg[0]));
+ info("&fi&lw&fb" + mods.getScripts().runConsole(arg[0]));
});
handler.register("say", "", "Send a message to all players.", arg -> {
@@ -411,7 +417,7 @@ public class ServerControl implements ApplicationListener{
Call.sendMessage("[scarlet][[Server]:[] " + arg[0]);
- info("&lyServer: &lb@", arg[0]);
+ info("&fi&lcServer: &fr@", "&lw" + arg[0]);
});
@@ -426,7 +432,7 @@ public class ServerControl implements ApplicationListener{
JsonValue base = JsonIO.json().fromJson(null, rules);
if(arg.length == 0){
- Log.info("&lyRules:\n@", JsonIO.print(rules));
+ Log.info("Rules:\n@", JsonIO.print(rules));
}else if(arg.length == 1){
Log.err("Invalid usage. Specify which rule to remove or add.");
}else{
@@ -438,7 +444,7 @@ public class ServerControl implements ApplicationListener{
boolean remove = arg[0].equals("remove");
if(remove){
if(base.has(arg[1])){
- Log.info("Rule &lc'@'&lg removed.", arg[1]);
+ Log.info("Rule '@' removed.", arg[1]);
base.remove(arg[1]);
}else{
Log.err("Rule not defined, so not removed.");
@@ -462,7 +468,7 @@ public class ServerControl implements ApplicationListener{
base.remove(value.name);
}
base.addChild(arg[1], value);
- Log.info("Changed rule: &ly@", value.toString().replace("\n", " "));
+ Log.info("Changed rule: @", value.toString().replace("\n", " "));
}catch(Throwable e){
Log.err("Error parsing rule JSON: @", e.getMessage());
}
@@ -501,7 +507,7 @@ public class ServerControl implements ApplicationListener{
handler.register("playerlimit", "[off/somenumber]", "Set the server player limit.", arg -> {
if(arg.length == 0){
- info("Player limit is currently &lc@.", netServer.admins.getPlayerLimit() == 0 ? "off" : netServer.admins.getPlayerLimit());
+ info("Player limit is currently @.", netServer.admins.getPlayerLimit() == 0 ? "off" : netServer.admins.getPlayerLimit());
return;
}
if(arg[0].equals("off")){
@@ -521,11 +527,11 @@ public class ServerControl implements ApplicationListener{
handler.register("config", "[name] [value...]", "Configure server settings.", arg -> {
if(arg.length == 0){
- info("&lyAll config values:");
+ info("All config values:");
for(Config c : Config.all){
- Log.info("&ly| &lc@:&lm @", c.name(), c.get());
- Log.info("&ly| | @", c.description);
- Log.info("&ly|");
+ Log.info("&lk| @: @", c.name(), "&lc&fi" + c.get());
+ Log.info("&lk| | &lw" + c.description);
+ Log.info("&lk|");
}
return;
}
@@ -533,7 +539,7 @@ public class ServerControl implements ApplicationListener{
try{
Config c = Config.valueOf(arg[0]);
if(arg.length == 1){
- Log.info("&lc'@'&lg is currently &lc@.", c.name(), c.get());
+ Log.info("'@' is currently @.", c.name(), c.get());
}else{
if(c.isBool()){
c.set(arg[1].equals("on") || arg[1].equals("true"));
@@ -548,7 +554,7 @@ public class ServerControl implements ApplicationListener{
c.set(arg[1]);
}
- Log.info("&lc@&lg set to &lc@.", c.name(), c.get());
+ Log.info("@ set to @.", c.name(), c.get());
Core.settings.forceSave();
}
}catch(IllegalArgumentException e){
@@ -558,9 +564,9 @@ public class ServerControl implements ApplicationListener{
handler.register("subnet-ban", "[add/remove] [address]", "Ban a subnet. This simply rejects all connections with IPs starting with some string.", arg -> {
if(arg.length == 0){
- Log.info("Subnets banned: &lc@", netServer.admins.getSubnetBans().isEmpty() ? "" : "");
+ Log.info("Subnets banned: @", netServer.admins.getSubnetBans().isEmpty() ? "" : "");
for(String subnet : netServer.admins.getSubnetBans()){
- Log.info("&ly " + subnet + "");
+ Log.info("&lw " + subnet + "");
}
}else if(arg.length == 1){
err("You must provide a subnet to add or remove.");
@@ -572,7 +578,7 @@ public class ServerControl implements ApplicationListener{
}
netServer.admins.addSubnetBan(arg[1]);
- Log.info("Banned &ly@&lc**", arg[1]);
+ Log.info("Banned @**", arg[1]);
}else if(arg[0].equals("remove")){
if(!netServer.admins.getSubnetBans().contains(arg[1])){
err("That subnet isn't banned.");
@@ -580,7 +586,7 @@ public class ServerControl implements ApplicationListener{
}
netServer.admins.removeSubnetBan(arg[1]);
- Log.info("Unbanned &ly@&lc**", arg[1]);
+ Log.info("Unbanned @**", arg[1]);
}else{
err("Incorrect usage. You must provide add/remove as the second argument.");
}
@@ -589,12 +595,12 @@ public class ServerControl implements ApplicationListener{
handler.register("whitelisted", "List the entire whitelist.", arg -> {
if(netServer.admins.getWhitelisted().isEmpty()){
- info("&lyNo whitelisted players found.");
+ info("No whitelisted players found.");
return;
}
- info("&lyWhitelist:");
- netServer.admins.getWhitelisted().each(p -> Log.info("- &ly@", p.lastName));
+ info("Whitelist:");
+ netServer.admins.getWhitelisted().each(p -> info("- @", p.lastName));
});
handler.register("whitelist-add", "", "Add a player to the whitelist by ID.", arg -> {
@@ -605,7 +611,7 @@ public class ServerControl implements ApplicationListener{
}
netServer.admins.whitelist(arg[0]);
- info("Player &ly'@'&lg has been whitelisted.", info.lastName);
+ info("Player '@' has been whitelisted.", info.lastName);
});
handler.register("whitelist-remove", "", "Remove a player to the whitelist by ID.", arg -> {
@@ -616,18 +622,18 @@ public class ServerControl implements ApplicationListener{
}
netServer.admins.unwhitelist(arg[0]);
- info("Player &ly'@'&lg has been un-whitelisted.", info.lastName);
+ info("Player '@' has been un-whitelisted.", info.lastName);
});
handler.register("shuffle", "[none/all/custom/builtin]", "Set map shuffling mode.", arg -> {
if(arg.length == 0){
- info("Shuffle mode current set to &ly'@'&lg.", maps.getShuffleMode());
+ info("Shuffle mode current set to '@'.", maps.getShuffleMode());
}else{
try{
ShuffleMode mode = ShuffleMode.valueOf(arg[0]);
Core.settings.put("shufflemode", mode.name());
maps.setShuffleMode(mode);
- info("Shuffle mode set to &ly'@'&lg.", arg[0]);
+ info("Shuffle mode set to '@'.", arg[0]);
}catch(Exception e){
err("Invalid shuffle mode.");
}
@@ -638,7 +644,7 @@ public class ServerControl implements ApplicationListener{
Map res = maps.all().find(map -> map.name().equalsIgnoreCase(arg[0].replace('_', ' ')) || map.name().equalsIgnoreCase(arg[0]));
if(res != null){
nextMapOverride = res;
- Log.info("Next map set to &ly'@'.", res.name());
+ Log.info("Next map set to '@'.", res.name());
}else{
Log.err("No map '@' found.", arg[0]);
}
@@ -694,9 +700,9 @@ public class ServerControl implements ApplicationListener{
if(bans.size == 0){
info("No ID-banned players have been found.");
}else{
- info("&lyBanned players [ID]:");
+ info("Banned players [ID]:");
for(PlayerInfo info : bans){
- info(" &ly @ / Last known name: '@'", info.id, info.lastName);
+ info(" @ / Last known name: '@'", info.id, info.lastName);
}
}
@@ -705,13 +711,13 @@ public class ServerControl implements ApplicationListener{
if(ipbans.size == 0){
info("No IP-banned players have been found.");
}else{
- info("&lmBanned players [IP]:");
+ info("Banned players [IP]:");
for(String string : ipbans){
PlayerInfo info = netServer.admins.findByIP(string);
if(info != null){
- info(" &lm '@' / Last known name: '@' / ID: '@'", string, info.lastName, info.id);
+ info(" '@' / Last known name: '@' / ID: '@'", string, info.lastName, info.id);
}else{
- info(" &lm '@' (No known name or info)", string);
+ info(" '@' (No known name or info)", string);
}
}
}
@@ -765,7 +771,7 @@ public class ServerControl implements ApplicationListener{
netServer.admins.unAdminPlayer(target.id);
}
if(playert != null) playert.admin = add;
- info("Changed admin status of player: &ly@", target.lastName);
+ info("Changed admin status of player: @", target.lastName);
}else{
err("Nobody with that name or ID could be found. If adding an admin by name, make sure they're online; otherwise, use their UUID.");
}
@@ -777,7 +783,7 @@ public class ServerControl implements ApplicationListener{
if(admins.size == 0){
info("No admins have been found.");
}else{
- info("&lyAdmins:");
+ info("Admins:");
for(PlayerInfo info : admins){
info(" &lm @ / ID: '@' / IP: '@'", info.lastName, info.id, info.lastIP);
}
@@ -788,10 +794,10 @@ public class ServerControl implements ApplicationListener{
if(Groups.player.size() == 0){
info("No players are currently in the server.");
}else{
- info("&lyPlayers: @", Groups.player.size());
+ info("Players: @", Groups.player.size());
for(Player user : Groups.player){
PlayerInfo userInfo = user.getInfo();
- info(" &lm @ / ID: '@' / IP: '@' / Admin: '@'", userInfo.lastName, userInfo.id, userInfo.lastIP, userInfo.admin);
+ info(" &lm @ / ID: @ / IP: @ / Admin: @", userInfo.lastName, userInfo.id, userInfo.lastIP, userInfo.admin);
}
}
});
@@ -849,7 +855,7 @@ public class ServerControl implements ApplicationListener{
info("Save files: ");
for(Fi file : saveDirectory.list()){
if(file.extension().equals(saveExtension)){
- info("| &ly@", file.nameWithoutExtension());
+ info("| @", file.nameWithoutExtension());
}
}
});
@@ -860,7 +866,7 @@ public class ServerControl implements ApplicationListener{
return;
}
- info("&lyCore destroyed.");
+ info("Core destroyed.");
inExtraRound = false;
Events.fire(new GameOverEvent(Team.crux));
});
@@ -870,16 +876,16 @@ public class ServerControl implements ApplicationListener{
ObjectSet infos = netServer.admins.findByName(arg[0]);
if(infos.size > 0){
- info("&lgPlayers found: @", infos.size);
+ info("Players found: @", infos.size);
int i = 0;
for(PlayerInfo info : infos){
- info("&lc[@] Trace info for player '@' / UUID @", i++, info.lastName, info.id);
- info(" &lyall names used: @", info.names);
- info(" &lyIP: @", info.lastIP);
- info(" &lyall IPs used: @", info.ips);
- info(" &lytimes joined: @", info.timesJoined);
- info(" &lytimes kicked: @", info.timesKicked);
+ info("[@] Trace info for player '@' / UUID @", i++, info.lastName, info.id);
+ info(" all names used: @", info.names);
+ info(" IP: @", info.lastIP);
+ info(" all IPs used: @", info.ips);
+ info(" times joined: @", info.timesJoined);
+ info(" times kicked: @", info.timesKicked);
}
}else{
info("Nobody with that name could be found.");
@@ -891,11 +897,11 @@ public class ServerControl implements ApplicationListener{
ObjectSet infos = netServer.admins.searchNames(arg[0]);
if(infos.size > 0){
- info("&lgPlayers found: @", infos.size);
+ info("Players found: @", infos.size);
int i = 0;
for(PlayerInfo info : infos){
- info("- &lc[@] &ly'@'&lc / &lm@", i++, info.lastName, info.id);
+ info("- [@] '@' / @", i++, info.lastName, info.id);
}
}else{
info("Nobody with that name could be found.");
@@ -906,10 +912,10 @@ public class ServerControl implements ApplicationListener{
int pre = (int)(Core.app.getJavaHeap() / 1024 / 1024);
System.gc();
int post = (int)(Core.app.getJavaHeap() / 1024 / 1024);
- info("&ly@&lg MB collected. Memory usage now at &ly@&lg MB.", pre - post, post);
+ info("@ MB collected. Memory usage now at @ MB.", pre - post, post);
});
- handler.register("yes", "Run the above \"did you mean\" suggestion.", arg -> {
+ handler.register("yes", "Run the last suggested incorrect command.", arg -> {
if(yes == null){
err("There is nothing to say yes to.");
}else{
@@ -1036,7 +1042,7 @@ public class ServerControl implements ApplicationListener{
serverSocket.bind(new InetSocketAddress(Config.socketInputAddress.string(), Config.socketInputPort.num()));
while(true){
Socket client = serverSocket.accept();
- info("&lmReceived command socket connection: &lb@", serverSocket.getLocalSocketAddress());
+ info("&lkReceived command socket connection: &fi@", serverSocket.getLocalSocketAddress());
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
socketOutput = new PrintWriter(client.getOutputStream(), true);
String line;
@@ -1044,7 +1050,7 @@ public class ServerControl implements ApplicationListener{
String result = line;
Core.app.post(() -> handleCommandString(result));
}
- info("&lmLost command socket connection: &lb@", serverSocket.getLocalSocketAddress());
+ info("&lkLost command socket connection: &fi@", serverSocket.getLocalSocketAddress());
socketOutput = null;
}
}catch(BindException b){
diff --git a/server/src/mindustry/server/ServerLauncher.java b/server/src/mindustry/server/ServerLauncher.java
index 4c8a2bb8e6..ad274954ea 100644
--- a/server/src/mindustry/server/ServerLauncher.java
+++ b/server/src/mindustry/server/ServerLauncher.java
@@ -29,10 +29,10 @@ public class ServerLauncher implements ApplicationListener{
Vars.platform = new Platform(){};
Vars.net = new Net(platform.getNet());
- Log.setLogger((level, text) -> {
- String result = "[" + dateTime.format(LocalDateTime.now()) + "] " + format(tags[level.ordinal()] + " " + text + "&fr");
- System.out.println(result);
- });
+ logger = (level1, text) -> {
+ String result = "[" + dateTime.format(LocalDateTime.now()) + "] " + format(tags[level1.ordinal()] + " " + text + "&fr");
+ System.out.println(result);
+ };
new HeadlessApplication(new ServerLauncher(), null, throwable -> CrashSender.send(throwable, f -> {}));
}catch(Throwable t){
CrashSender.send(t, f -> {});
diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java
index 01cf659df2..67d30e5ff9 100644
--- a/tests/src/test/java/ApplicationTests.java
+++ b/tests/src/test/java/ApplicationTests.java
@@ -36,7 +36,7 @@ public class ApplicationTests{
try{
boolean[] begins = {false};
Throwable[] exceptionThrown = {null};
- Log.setUseColors(false);
+ Log.useColors = false;
ApplicationCore core = new ApplicationCore(){
@Override
diff --git a/tests/src/test/java/power/PowerTestFixture.java b/tests/src/test/java/power/PowerTestFixture.java
index 7bd7e821b2..ceed02b530 100644
--- a/tests/src/test/java/power/PowerTestFixture.java
+++ b/tests/src/test/java/power/PowerTestFixture.java
@@ -37,7 +37,7 @@ public class PowerTestFixture{
Vars.state = new GameState();
Vars.tree = new FileTree();
content.createBaseContent();
- Log.setUseColors(false);
+ Log.useColors = false;
Time.setDeltaProvider(() -> 0.5f);
}
diff --git a/tools/src/mindustry/tools/ImagePacker.java b/tools/src/mindustry/tools/ImagePacker.java
index 2533f99af9..1142de8a26 100644
--- a/tools/src/mindustry/tools/ImagePacker.java
+++ b/tools/src/mindustry/tools/ImagePacker.java
@@ -28,10 +28,10 @@ public class ImagePacker{
Vars.headless = true;
ArcNativesLoader.load();
- Log.setLogger(new NoopLogHandler());
+ Log.logger = new NoopLogHandler();
Vars.content = new ContentLoader();
Vars.content.createBaseContent();
- Log.setLogger(new DefaultLogHandler());
+ Log.logger = new DefaultLogHandler();
Fi.get("../../../assets-raw/sprites_out").walk(path -> {
if(!path.extEquals("png")) return;