Compare commits
67 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
520d122d82 | ||
|
|
7ab9c6fd9c | ||
|
|
4d200276d2 | ||
|
|
c335722de5 | ||
|
|
25b26be87b | ||
|
|
e714285671 | ||
|
|
dd3ce95264 | ||
|
|
564e81e734 | ||
|
|
dc63112915 | ||
|
|
bc94e24874 | ||
|
|
94fe92d67d | ||
|
|
047d39d129 | ||
|
|
b6d27c16be | ||
|
|
7c52444e3c | ||
|
|
1f85d0d24f | ||
|
|
4a53a80b21 | ||
|
|
cee09dd167 | ||
|
|
39227774e1 | ||
|
|
6cd778783e | ||
|
|
5db4c67477 | ||
|
|
0f87942b16 | ||
|
|
3dd7412ed8 | ||
|
|
43d164d54b | ||
|
|
d09695a946 | ||
|
|
5976ed6983 | ||
|
|
d739269f59 | ||
|
|
72c28f7098 | ||
|
|
f2d83f3599 | ||
|
|
b611e0f9f4 | ||
|
|
f59c439f2f | ||
|
|
e6daf63a5a | ||
|
|
00ae28847e | ||
|
|
445e147c16 | ||
|
|
410f4f69a1 | ||
|
|
9e2251028b | ||
|
|
7f6907e14f | ||
|
|
c6829c23d4 | ||
|
|
70293a4864 | ||
|
|
29855243cb | ||
|
|
16358dbd6a | ||
|
|
83d28461f0 | ||
|
|
874cba7ad3 | ||
|
|
45baeb4933 | ||
|
|
8b35b44489 | ||
|
|
1289e20990 | ||
|
|
3593803ad9 | ||
|
|
0d89654103 | ||
|
|
aa7ba6548c | ||
|
|
9b02d26856 | ||
|
|
30c773b304 | ||
|
|
738b96b94b | ||
|
|
151743021b | ||
|
|
dbbb27ec0f | ||
|
|
89e942ee35 | ||
|
|
5ec0e9dc9f | ||
|
|
b40615d9e6 | ||
|
|
307943c098 | ||
|
|
ebb40145ac | ||
|
|
ae272f079b | ||
|
|
587c8c280c | ||
|
|
7bcfaf54ef | ||
|
|
bcee2e7083 | ||
|
|
ccf85b81c8 | ||
|
|
126cca9e86 | ||
|
|
688b5b9eea | ||
|
|
0496d2108c | ||
|
|
06e63dad45 |
@@ -1,7 +1,7 @@
|
|||||||
### Adding a server to the list
|
### Adding a server to the list
|
||||||
|
|
||||||
Mindustry now has a public list of servers that everyone can see and connect to.
|
Mindustry now has a public list of servers that everyone can see and connect to.
|
||||||
This is done by letting clients `GET` a [JSON list of servers](https://github.com/Anuken/Mindustry/blob/master/servers_v6.json) in this repository.
|
This is done by letting clients `GET` a [JSON list of servers](https://github.com/Anuken/Mindustry/blob/master/servers_v7.json) in this repository.
|
||||||
|
|
||||||
You may want to add your server to this list. The steps for getting this done are as follows:
|
You may want to add your server to this list. The steps for getting this done are as follows:
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ You'll need to either hire some moderators, or make use of (currently non-existe
|
|||||||
4. **Get some good maps.** *(optional, but highly recommended)*. Add some maps to your server and set the map rotation to custom-only. You can get maps from the Steam workshop by subscribing and exporting them; using the `#maps` channel on Discord is also an option.
|
4. **Get some good maps.** *(optional, but highly recommended)*. Add some maps to your server and set the map rotation to custom-only. You can get maps from the Steam workshop by subscribing and exporting them; using the `#maps` channel on Discord is also an option.
|
||||||
5. **Check your server configuration.** *(optional)* I would recommend adding a message rate limit of 1 second (`config messageRateLimit 1`), and disabling connect/disconnect messages to reduce spam (`config showConnectMessages false`).
|
5. **Check your server configuration.** *(optional)* I would recommend adding a message rate limit of 1 second (`config messageRateLimit 1`), and disabling connect/disconnect messages to reduce spam (`config showConnectMessages false`).
|
||||||
6. Finally, **submit a pull request** to add your server's IP to the list.
|
6. Finally, **submit a pull request** to add your server's IP to the list.
|
||||||
This should be fairly straightforward: Press the edit button on the [server file](https://github.com/Anuken/Mindustry/blob/master/servers_v6.json), then add a JSON object with a single key, indicating your server address.
|
This should be fairly straightforward: Press the edit button on the [server file](https://github.com/Anuken/Mindustry/blob/master/servers_v7.json), then add a JSON object with a single key, indicating your server address.
|
||||||
For example, if your server address is `example.com:6000`, you would add a comma after the last entry and insert:
|
For example, if your server address is `example.com:6000`, you would add a comma after the last entry and insert:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 349 B After Width: | Height: | Size: 463 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 501 B After Width: | Height: | Size: 552 B |
|
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 752 B |
|
Before Width: | Height: | Size: 203 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1019 B |
BIN
core/assets-raw/sprites/blocks/turrets/salvo/salvo-side-l.png
Normal file
|
After Width: | Height: | Size: 429 B |
BIN
core/assets-raw/sprites/blocks/turrets/salvo/salvo-side-r.png
Normal file
|
After Width: | Height: | Size: 423 B |
|
Before Width: | Height: | Size: 864 B |
|
Before Width: | Height: | Size: 499 B After Width: | Height: | Size: 510 B |
|
Before Width: | Height: | Size: 779 B After Width: | Height: | Size: 817 B |
|
Before Width: | Height: | Size: 547 B After Width: | Height: | Size: 603 B |
|
Before Width: | Height: | Size: 893 B After Width: | Height: | Size: 873 B |
|
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 329 B |
|
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 324 B |
|
Before Width: | Height: | Size: 285 B After Width: | Height: | Size: 308 B |
|
Before Width: | Height: | Size: 291 B After Width: | Height: | Size: 322 B |
|
Before Width: | Height: | Size: 531 B After Width: | Height: | Size: 523 B |
@@ -1 +0,0 @@
|
|||||||
mschxœ%ŠQƒ0C]RÐÄ>v>9Ê"µˆ¶S(HÜ~)X±_dƒƒÏKŒa•YëDݹ(¼¸äS®¢øü²i©‘§¯ÆmÃ;VIÓ^e0â–s-@
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
mschxœ5<C593>Ë
|
|
||||||
!E¯Ïy-J·ý‡ù(q¤£Gú÷<C3BA>„ââä&'›„Î.<Zl.Çž®Vª{lG¸|<7C>ŸK4ÌíúÙðü{»/ùßR±ÅÒ~•^=ÝùäГkÑïG<C3AF>ç àzRPm!&ÆÌX+ ÉÓ†4©¨²¼H}E“y$9’À˜’¢XQÜÔü‰æd8ZQŠ¡†acf,Œê˜ã"
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
mschxœ5<C593>A E¿JkêÊStã<74><08>˜I
|
|
||||||
4”šx{¡ðòÿ¼¸vÐѽpq‘<71>°—”Ý›^˜Ú}æpŠ€ÆÄ…¼§#{Âã¯Ï>Å}SÆm‹tWØÏKæuÅXGÅq¤àY¬z\P?E½:<18>ÅYŽ
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
mschxœ%Žknà „ÇØIü¨äV9×È
|
|
||||||
ú;¢xS!a@€“úîMÝ%F¬¾Ñ>fz<>Æ©™p¾~:“¯¥}ŽëõbU$%MÈÆ;à
|
|
||||||
ãCeŠ’~rT:ûˆ^/6›»*ú#y’A9²’Õ7ϧà#É)%ŒÚ++5¹Ímáꘌ5Ú;™f²ì‹18Zf•<66>–S4Öb0™f™ü5áô¥2wèƒðÎO„÷ VëÕ$ÙçN+Ÿ1(åíuÞ
|
|
||||||
4
core/assets/baseparts/actuallyokrtg.msch
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
mschxœM<C593>anÂ0…MK[HÚ"Ä9rŠcÚ<63><Ô-4(MaÜ~ÏñŸ)RŸíú{vB':Ô´<C394>ý<EFBFBD>iðç¼ú^ñ'å+Ù/ç4Ýóg"jƒÿä°PõþaÉ~¿dwIStxúÌÉñoNpˆ‰ŽK>¹»Ÿ98DW&û¯DÇ<e?OëÍ<C3AB>ãüà<17>Ý•gN^Æu¾pú
|
||||||
|
ñé®0§S|p´»{Šß\ÆØe…µËñɉš‡_C&;e¾¹%®éÌXú<58>h#gƒxKT!îˆj[ªEª!Ûˆ4*Jé¬iG¨‡-<2D>’<EFBFBD>ið.<2E>ŽÉvT‰ã@åO¥Ò Ð
|
||||||
|
Þâ`É
|
||||||
|
Þ*Þ¢¥<14>‹Uá:á*”ÁwŠ£<C5A0>jÉ€w,/ÅN‹ø+³~¯6{o”7:Þèx£ã<C2A3>no”7…¯Èê-¬ÚXµéÕ¦×5zµéÕ¦×5z½Å Ü ·õ#誅”-FÅGÅG}„QñƒâÁ÷tDçF-b@tõ½ÔO¼
|
||||||
BIN
core/assets/baseparts/atrax-surprise.msch
Normal file
1
core/assets/baseparts/flar.msch
Normal file
@@ -0,0 +1 @@
|
|||||||
|
mschxœMŽÍNÃ0„'‰›æ¯^<5E>»Ÿq0‰‹,9vd»”¼{ ¬»*KÞ<4B>ogV‹'´„S³†¸XÐO:ŽÁ,Éx ¶êCÛˆòí}@oUÔANÁX‹—d’ræ:ËÑ»/½ú€“7VêïÔ˜Hžo*‘ýDc
|
||||||
BIN
core/assets/baseparts/fortress.msch
Normal file
BIN
core/assets/baseparts/impending-doom.msch
Normal file
2
core/assets/baseparts/rtgbrick1.msch
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
mschxœŒKà CͯE=
|
||||||
|
‹ž§Ê‚<EFBFBD>B%
|
||||||
5
core/assets/baseparts/rtgbrick2.msch
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
mschxś
|
||||||
|
ŚK
|
||||||
|
Ă0CĺOŇ–ĐEâMŻşpśÁ<C59B>Ně0včő;ń$!„ ł<>Żń <däMJúľ±ěÔ“”s”VĚ7â»~&<u2U’8š`é—d
|
||||||
|
ŁýHCt„Ţ.I„Wo%ś±u™°pě$a—¬ż“
|
||||||
|
Î(üÖÂŔhyłN˝ó
|
||||||
BIN
core/assets/baseparts/rtgsalvo.msch
Normal file
1
core/assets/baseparts/scorch.msch
Normal file
@@ -0,0 +1 @@
|
|||||||
|
mschxś5PŃŽ„ @ôáľÄ/şÜ<C59F>Ë’,‰ŠAÝËýýµt5!C§Ó™"FŚÝ6Ż î<>ĄĆĆg:bÍű™ËŔ-ó#-ô÷ŹĂ׾ĄkťĎ§gÍËËöNĄbŚeßSť~g˘o/WËu&jć3ÓQ®yNt`Đ> `ů®™TźŞőŚTťôş»j=Ëë>rĹw“A`€Öč%˛IĎQV*Ĺ˝6ĐË€—Ď<1D>fĄ'Ć0Đ6LZ^Âs0™3ée®™y1b$=Hz<48>Ř Ę ĘAž2đo°–6´†‰ <©ţ/_&‘
|
||||||
2
core/assets/baseparts/simplemeltdown.msch
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
mschxœ=‘벓0… å(=¾à³8þà@t¢jöôÉ<C3B4>qjqmÂq(|Ù—µ’<C2B5>â|˜ºQ㼘ñjõ¨æÛ5è¥wæêÍ<8ÙîUÛñç/5òÿ]õkç½v÷Öv²Ý¢];8c-š[ÇR«ß¼ëz?;(ãõØ.óêz<C3AA>¬Ÿ§a5jY)mý|Ó/Þøn2ëØ²üKß©º\¥ÒNó <C3B3>]šÞÝç¯v5C;š7ª”5?%¢ôš#ø¾Ný~øË‘ £ïÌÄ~à¡A!á"މüð6À_•ræ$åªF”2U#>çœyò’‹ÃIÄR. `2'ʼD´=¶çö)¿ÏíùجeÛ“ï×Åö›[¤â]Ðâ„D<E2809E>#C&ÓÝ4”HJVx˜ˆÒHj²ÓŽLZr>;XUD"%(BgÁ$QJ”'™X\åÈïµZæS2ÇÎx¯ª` B“zo:M—½©
|
||||||
|
¾Uðp$wI%àÌ“G2ïñ¨Þ¹ A#× Èò€" PHþŸLo´
|
||||||
BIN
core/assets/baseparts/solarbrick1.msch
Normal file
BIN
core/assets/baseparts/solarbrick2.msch
Normal file
BIN
core/assets/baseparts/solarbrick4.msch
Normal file
2
core/assets/baseparts/steamgobrr.msch
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
mschxœ%ÐÝrƒ àãJÔ˜fúÜõm:½@³uÌ d“æí»¸^øÁ¸ËYÄÊÕ.„f‹d—É! ½Ñ6†ùg¿¨œÈmÈ¿\^6R0ôƒ£çâm™è_p9N1ìñupv‹æfçÐïë<C3AF>¯ó/3ñ)¸Æ9ÚuÞ3úõIo®ÿôO
|
||||||
|
\ý$óþNGD=ØÈ¡o\7ïl0»’3¼šíi1›ßÃH<뎧H¯\(…Fè„E†•5›s„\(…Fèîä†YÉdÈÃ
|
||||||
BIN
core/assets/baseparts/strong_duos.msch
Normal file
@@ -1212,6 +1212,8 @@ rules.wavetimer = Wave Timer
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Waves
|
rules.waves = Waves
|
||||||
rules.attack = Attack Mode
|
rules.attack = Attack Mode
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI [red](WIP)
|
rules.rtsai = RTS AI [red](WIP)
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1187,6 +1187,8 @@ rules.wavetimer = Інтэрвал хваляў
|
|||||||
rules.wavesending = Адпраўка Хваль
|
rules.wavesending = Адпраўка Хваль
|
||||||
rules.waves = Хвалі
|
rules.waves = Хвалі
|
||||||
rules.attack = Рэжым атакі
|
rules.attack = Рэжым атакі
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Мінімальны Размер Атраду
|
rules.rtsminsquadsize = Мінімальны Размер Атраду
|
||||||
rules.rtsmaxsquadsize = Максімальны Размер Атраду
|
rules.rtsmaxsquadsize = Максімальны Размер Атраду
|
||||||
|
|||||||
@@ -1198,6 +1198,8 @@ rules.wavetimer = Таймер за Вълни
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Вълни
|
rules.waves = Вълни
|
||||||
rules.attack = Режим Атака
|
rules.attack = Режим Атака
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1202,6 +1202,8 @@ rules.wavetimer = Temporitzador d’onades
|
|||||||
rules.wavesending = Enviament d’onades
|
rules.wavesending = Enviament d’onades
|
||||||
rules.waves = Onades
|
rules.waves = Onades
|
||||||
rules.attack = Mode d’atac
|
rules.attack = Mode d’atac
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = IA avançada (RTS AI)
|
rules.rtsai = IA avançada (RTS AI)
|
||||||
rules.rtsminsquadsize = Mida mínima de l’esquadró
|
rules.rtsminsquadsize = Mida mínima de l’esquadró
|
||||||
rules.rtsmaxsquadsize = Mida màxima de l’esquadró
|
rules.rtsmaxsquadsize = Mida màxima de l’esquadró
|
||||||
|
|||||||
@@ -767,7 +767,7 @@ sector.fungalPass.description = Přechodová oblast mezi vysokými horami a spó
|
|||||||
sector.biomassFacility.description = Prapůvod všech spór. Toto je zařízení, be kterém byly spóry vynalezeny a zpočátku u vyráběny.\nVynalezni technologii, která se skrýbá uvnitř. Kultivuj spóry k výrobě paliva a plastů.\n\n[lightgray]Po vypnutí tohoto zařízení byly spóry vypuštěny. V okolním ekosystému však tomuto invazivnímu druhu nebylo nic schopné konkurovat.
|
sector.biomassFacility.description = Prapůvod všech spór. Toto je zařízení, be kterém byly spóry vynalezeny a zpočátku u vyráběny.\nVynalezni technologii, která se skrýbá uvnitř. Kultivuj spóry k výrobě paliva a plastů.\n\n[lightgray]Po vypnutí tohoto zařízení byly spóry vypuštěny. V okolním ekosystému však tomuto invazivnímu druhu nebylo nic schopné konkurovat.
|
||||||
sector.windsweptIslands.description = Vzdálen od pevniny je tento řetízek ostrovů. Záznamy ukazují, že zde kdysi byly zařízení na výrobu [accent]Plastany[].\n\nPoraž nepřátelské námořní jednotky. Vybuduj základnu na ostrově. Vynalezni továrny.
|
sector.windsweptIslands.description = Vzdálen od pevniny je tento řetízek ostrovů. Záznamy ukazují, že zde kdysi byly zařízení na výrobu [accent]Plastany[].\n\nPoraž nepřátelské námořní jednotky. Vybuduj základnu na ostrově. Vynalezni továrny.
|
||||||
sector.extractionOutpost.description = Vzdálená pevnost, postavená nepřítelem za účelem vysílání zdrojů do okolních sektorů.\n\nDoprava položek napříč sektory je nezbytná pro lapení dalších sektorů. Znič základnu. Vyzkoumej jejich Vysílací plošiny.
|
sector.extractionOutpost.description = Vzdálená pevnost, postavená nepřítelem za účelem vysílání zdrojů do okolních sektorů.\n\nDoprava položek napříč sektory je nezbytná pro lapení dalších sektorů. Znič základnu. Vyzkoumej jejich Vysílací plošiny.
|
||||||
sector.impact0078.description = Zde leží zbytky mezihvězdné lodi, která vstoupila d otohoto systému.\n\nZachraň z vraku vše, co se dá. Vyzkoumej nepoškozenou technologii.
|
sector.impact0078.description = Zde leží zbytky mezihvězdné lodi, která vstoupila do tohoto systému.\n\nZachraň z vraku vše, co se dá. Vyzkoumej nepoškozenou technologii.
|
||||||
sector.planetaryTerminal.description = Konečný cíl.\n\nTato pobřežní základna obsahuje konstrukce schopné vyslat jádra na okolní planety. Je mimořádně dobře opevněna.\n\nVyrob námořní jednotky. Odstraň nepřítele tak rychle, jak umíš. Vyzkoumej vysílací konstrukci.
|
sector.planetaryTerminal.description = Konečný cíl.\n\nTato pobřežní základna obsahuje konstrukce schopné vyslat jádra na okolní planety. Je mimořádně dobře opevněna.\n\nVyrob námořní jednotky. Odstraň nepřítele tak rychle, jak umíš. Vyzkoumej vysílací konstrukci.
|
||||||
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
|
sector.coastline.description = Remnants of naval unit technology have been detected at this location. Repel the enemy attacks, capture this sector, and acquire the technology.
|
||||||
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
|
sector.navalFortress.description = The enemy has established a base on a remote, naturally-fortified island. Destroy this outpost. Acquire their advanced naval craft technology, and research it.
|
||||||
@@ -1200,6 +1200,8 @@ rules.wavetimer = Časovač vln
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Vlny
|
rules.waves = Vlny
|
||||||
rules.attack = Režim útoku
|
rules.attack = Režim útoku
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1188,6 +1188,8 @@ rules.wavetimer = Bølge-æggeur
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Bølger
|
rules.waves = Bølger
|
||||||
rules.attack = Angrebsmode
|
rules.attack = Angrebsmode
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1211,6 +1211,8 @@ rules.wavetimer = Wellen-Timer
|
|||||||
rules.wavesending = Manuelle Wellen möglich
|
rules.wavesending = Manuelle Wellen möglich
|
||||||
rules.waves = Wellen
|
rules.waves = Wellen
|
||||||
rules.attack = Angriff-Modus
|
rules.attack = Angriff-Modus
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS KI [red](unfertig)
|
rules.rtsai = RTS KI [red](unfertig)
|
||||||
rules.rtsminsquadsize = Min. Squadgröße
|
rules.rtsminsquadsize = Min. Squadgröße
|
||||||
rules.rtsmaxsquadsize = Max. Squadgröße
|
rules.rtsmaxsquadsize = Max. Squadgröße
|
||||||
|
|||||||
@@ -1208,6 +1208,8 @@ rules.wavetimer = Temporizador de oleadas
|
|||||||
rules.wavesending = Envío de oleadas
|
rules.wavesending = Envío de oleadas
|
||||||
rules.waves = Oleadas
|
rules.waves = Oleadas
|
||||||
rules.attack = Modo de ataque
|
rules.attack = Modo de ataque
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = IA enemiga avanzada (RTS AI)
|
rules.rtsai = IA enemiga avanzada (RTS AI)
|
||||||
rules.rtsminsquadsize = Tamaño mínimo de escuadrón
|
rules.rtsminsquadsize = Tamaño mínimo de escuadrón
|
||||||
rules.rtsmaxsquadsize = Tamaño máximo de escuadrón
|
rules.rtsmaxsquadsize = Tamaño máximo de escuadrón
|
||||||
|
|||||||
@@ -1188,6 +1188,8 @@ rules.wavetimer = Kasuta taimerit
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Kasuta lahingulaineid
|
rules.waves = Kasuta lahingulaineid
|
||||||
rules.attack = Mänguviis "Rünnak"
|
rules.attack = Mänguviis "Rünnak"
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1190,6 +1190,8 @@ rules.wavetimer = Boladen denboragailua
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Boladak
|
rules.waves = Boladak
|
||||||
rules.attack = Eraso modua
|
rules.attack = Eraso modua
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1187,6 +1187,8 @@ rules.wavetimer = Tasojen aikaraja
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Tasot
|
rules.waves = Tasot
|
||||||
rules.attack = Hyökkäystila
|
rules.attack = Hyökkäystila
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min. hyökkäysjoukon koko
|
rules.rtsminsquadsize = Min. hyökkäysjoukon koko
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1187,6 +1187,8 @@ rules.wavetimer = Wave Timer
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Waves
|
rules.waves = Waves
|
||||||
rules.attack = Attack Mode
|
rules.attack = Attack Mode
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1212,6 +1212,8 @@ rules.wavetimer = Compte à rebours des vagues
|
|||||||
rules.wavesending = Déclenchement des Vagues
|
rules.wavesending = Déclenchement des Vagues
|
||||||
rules.waves = Vagues
|
rules.waves = Vagues
|
||||||
rules.attack = Mode « Attaque »
|
rules.attack = Mode « Attaque »
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = IA de RTS [red](WIP)
|
rules.rtsai = IA de RTS [red](WIP)
|
||||||
rules.rtsminsquadsize = Taille Minimale d'une Escouade
|
rules.rtsminsquadsize = Taille Minimale d'une Escouade
|
||||||
rules.rtsmaxsquadsize = Taille Maximale d'une Escouade
|
rules.rtsmaxsquadsize = Taille Maximale d'une Escouade
|
||||||
|
|||||||
@@ -1197,6 +1197,8 @@ rules.wavetimer = Hullám időzítő
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Hullámok
|
rules.waves = Hullámok
|
||||||
rules.attack = Támadás mód
|
rules.attack = Támadás mód
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1208,6 +1208,8 @@ rules.wavetimer = Pengaturan Waktu Gelombang
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Gelombang
|
rules.waves = Gelombang
|
||||||
rules.attack = Mode Penyerangan
|
rules.attack = Mode Penyerangan
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = A.I. RTS
|
rules.rtsai = A.I. RTS
|
||||||
rules.rtsminsquadsize = Ukuran Regu Minimum
|
rules.rtsminsquadsize = Ukuran Regu Minimum
|
||||||
rules.rtsmaxsquadsize = Ukuran Regu Maksimum
|
rules.rtsmaxsquadsize = Ukuran Regu Maksimum
|
||||||
|
|||||||
@@ -1194,6 +1194,8 @@ rules.wavetimer = Timer Ondate
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Ondate
|
rules.waves = Ondate
|
||||||
rules.attack = Modalità Attacco
|
rules.attack = Modalità Attacco
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Dimensione minima squadra
|
rules.rtsminsquadsize = Dimensione minima squadra
|
||||||
rules.rtsmaxsquadsize = Dimensione massima squadra
|
rules.rtsmaxsquadsize = Dimensione massima squadra
|
||||||
|
|||||||
@@ -1200,6 +1200,8 @@ rules.wavetimer = ウェーブの自動進行
|
|||||||
rules.wavesending = ウェーブスキップ
|
rules.wavesending = ウェーブスキップ
|
||||||
rules.waves = ウェーブ
|
rules.waves = ウェーブ
|
||||||
rules.attack = アタックモード
|
rules.attack = アタックモード
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = チームの最少人数
|
rules.rtsminsquadsize = チームの最少人数
|
||||||
rules.rtsmaxsquadsize = チームの最大人数
|
rules.rtsmaxsquadsize = チームの最大人数
|
||||||
|
|||||||
@@ -1200,6 +1200,8 @@ rules.wavetimer = 시간 제한이 있는 단계
|
|||||||
rules.wavesending = 단계 넘김
|
rules.wavesending = 단계 넘김
|
||||||
rules.waves = 단계
|
rules.waves = 단계
|
||||||
rules.attack = 공격 모드
|
rules.attack = 공격 모드
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = 최소 부대 규모
|
rules.rtsminsquadsize = 최소 부대 규모
|
||||||
rules.rtsmaxsquadsize = 최대 부대 규모
|
rules.rtsmaxsquadsize = 최대 부대 규모
|
||||||
|
|||||||
@@ -1188,6 +1188,8 @@ rules.wavetimer = Bangų Laikmatis
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Bangos
|
rules.waves = Bangos
|
||||||
rules.attack = Puolimo Režimas
|
rules.attack = Puolimo Režimas
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1200,6 +1200,8 @@ rules.wavetimer = Vijandelijke Golven Timer
|
|||||||
rules.wavesending = Golven Sturen
|
rules.wavesending = Golven Sturen
|
||||||
rules.waves = Golven
|
rules.waves = Golven
|
||||||
rules.attack = Aanvalmodus
|
rules.attack = Aanvalmodus
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Ploeg Grootte
|
rules.rtsminsquadsize = Min Ploeg Grootte
|
||||||
rules.rtsmaxsquadsize = Max Ploeg Grootte
|
rules.rtsmaxsquadsize = Max Ploeg Grootte
|
||||||
|
|||||||
@@ -1188,6 +1188,8 @@ rules.wavetimer = Wave Timer
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Waves
|
rules.waves = Waves
|
||||||
rules.attack = Attack Mode
|
rules.attack = Attack Mode
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1198,6 +1198,8 @@ rules.wavetimer = Zegar Fal
|
|||||||
rules.wavesending = Wysyłanie Fal
|
rules.wavesending = Wysyłanie Fal
|
||||||
rules.waves = Fale
|
rules.waves = Fale
|
||||||
rules.attack = Tryb Ataku
|
rules.attack = Tryb Ataku
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS SI
|
rules.rtsai = RTS SI
|
||||||
rules.rtsminsquadsize = Minimalny Rozmiar Składu
|
rules.rtsminsquadsize = Minimalny Rozmiar Składu
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1209,6 +1209,8 @@ rules.wavetimer = Tempo de horda
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Hordas
|
rules.waves = Hordas
|
||||||
rules.attack = Modo de ataque
|
rules.attack = Modo de ataque
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Tamanho mínimo do esquadrão
|
rules.rtsminsquadsize = Tamanho mínimo do esquadrão
|
||||||
rules.rtsmaxsquadsize = Tamanho máximo do esquadrão
|
rules.rtsmaxsquadsize = Tamanho máximo do esquadrão
|
||||||
|
|||||||
@@ -1188,6 +1188,8 @@ rules.wavetimer = Tempo de horda
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Hordas
|
rules.waves = Hordas
|
||||||
rules.attack = Modo de ataque
|
rules.attack = Modo de ataque
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1200,6 +1200,8 @@ rules.wavetimer = Valuri pe Timp
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Valuri
|
rules.waves = Valuri
|
||||||
rules.attack = Modul Atac
|
rules.attack = Modul Atac
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1200,6 +1200,8 @@ rules.wavetimer = Интервал волн
|
|||||||
rules.wavesending = Отправка волн
|
rules.wavesending = Отправка волн
|
||||||
rules.waves = Волны
|
rules.waves = Волны
|
||||||
rules.attack = Режим атаки
|
rules.attack = Режим атаки
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = ИИ в реальном времени
|
rules.rtsai = ИИ в реальном времени
|
||||||
rules.rtsminsquadsize = Минимальный размер отряда
|
rules.rtsminsquadsize = Минимальный размер отряда
|
||||||
rules.rtsmaxsquadsize = Максимальный размер отряда
|
rules.rtsmaxsquadsize = Максимальный размер отряда
|
||||||
|
|||||||
@@ -1202,6 +1202,8 @@ rules.wavetimer = Talasna Štoperica
|
|||||||
rules.wavesending = Slanje Talasa
|
rules.wavesending = Slanje Talasa
|
||||||
rules.waves = Talasi
|
rules.waves = Talasi
|
||||||
rules.attack = Mod Napada
|
rules.attack = Mod Napada
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI [red](Nedovršeno)
|
rules.rtsai = RTS AI [red](Nedovršeno)
|
||||||
rules.rtsminsquadsize = Minimalna Veličina Odreda
|
rules.rtsminsquadsize = Minimalna Veličina Odreda
|
||||||
rules.rtsmaxsquadsize = Maksimalna Veličina Odreda
|
rules.rtsmaxsquadsize = Maksimalna Veličina Odreda
|
||||||
|
|||||||
@@ -1188,6 +1188,8 @@ rules.wavetimer = Vågtimer
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Vågor
|
rules.waves = Vågor
|
||||||
rules.attack = Attack Mode
|
rules.attack = Attack Mode
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1202,6 +1202,8 @@ rules.wavetimer = นับถอยหลังการปล่อยคล
|
|||||||
rules.wavesending = การปล่อยคลื่น
|
rules.wavesending = การปล่อยคลื่น
|
||||||
rules.waves = คลื่น
|
rules.waves = คลื่น
|
||||||
rules.attack = โหมดการโจมตี
|
rules.attack = โหมดการโจมตี
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI [red](ไม่เสถียร)
|
rules.rtsai = RTS AI [red](ไม่เสถียร)
|
||||||
rules.rtsminsquadsize = ขนาดกองทัพเล็กที่สุด
|
rules.rtsminsquadsize = ขนาดกองทัพเล็กที่สุด
|
||||||
rules.rtsmaxsquadsize = ขนาดกองทัพใหญ่ที่สุด
|
rules.rtsmaxsquadsize = ขนาดกองทัพใหญ่ที่สุด
|
||||||
|
|||||||
@@ -1188,6 +1188,8 @@ rules.wavetimer = Wave Timer
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = Waves
|
rules.waves = Waves
|
||||||
rules.attack = Attack Mode
|
rules.attack = Attack Mode
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Squad Size
|
rules.rtsminsquadsize = Min Squad Size
|
||||||
rules.rtsmaxsquadsize = Max Squad Size
|
rules.rtsmaxsquadsize = Max Squad Size
|
||||||
|
|||||||
@@ -1199,6 +1199,8 @@ rules.wavetimer = Dalga Zamanlayıcısı
|
|||||||
rules.wavesending = Dalga Gönderiliyor
|
rules.wavesending = Dalga Gönderiliyor
|
||||||
rules.waves = Dalgalar
|
rules.waves = Dalgalar
|
||||||
rules.attack = Saldırı Modu
|
rules.attack = Saldırı Modu
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Min Gurup Boyutu
|
rules.rtsminsquadsize = Min Gurup Boyutu
|
||||||
rules.rtsmaxsquadsize = Maks Gurup Boyutu
|
rules.rtsmaxsquadsize = Maks Gurup Boyutu
|
||||||
|
|||||||
@@ -1210,6 +1210,8 @@ rules.wavetimer = Таймер для хвиль
|
|||||||
rules.wavesending = Ручне надсилання хвиль
|
rules.wavesending = Ручне надсилання хвиль
|
||||||
rules.waves = Хвилі
|
rules.waves = Хвилі
|
||||||
rules.attack = Режим атаки
|
rules.attack = Режим атаки
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = ШІ зі стратегій реального часу
|
rules.rtsai = ШІ зі стратегій реального часу
|
||||||
rules.rtsminsquadsize = Мінімальний розмір загону
|
rules.rtsminsquadsize = Мінімальний розмір загону
|
||||||
rules.rtsmaxsquadsize = Максимальний розмір загону
|
rules.rtsmaxsquadsize = Максимальний розмір загону
|
||||||
|
|||||||
@@ -1203,6 +1203,8 @@ rules.wavetimer = Đếm ngược đợt
|
|||||||
rules.wavesending = Gửi đợt
|
rules.wavesending = Gửi đợt
|
||||||
rules.waves = Đợt
|
rules.waves = Đợt
|
||||||
rules.attack = Chế độ tấn công
|
rules.attack = Chế độ tấn công
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = Kích thước đội hình tối thiểu
|
rules.rtsminsquadsize = Kích thước đội hình tối thiểu
|
||||||
rules.rtsmaxsquadsize = Kích thước đội hình tối đa
|
rules.rtsmaxsquadsize = Kích thước đội hình tối đa
|
||||||
|
|||||||
@@ -1211,6 +1211,8 @@ rules.wavetimer = 波次计时器
|
|||||||
rules.wavesending = 波次可跳波
|
rules.wavesending = 波次可跳波
|
||||||
rules.waves = 波次
|
rules.waves = 波次
|
||||||
rules.attack = 进攻模式
|
rules.attack = 进攻模式
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = 最小部队规模
|
rules.rtsminsquadsize = 最小部队规模
|
||||||
rules.rtsmaxsquadsize = 最大部队规模
|
rules.rtsmaxsquadsize = 最大部队规模
|
||||||
|
|||||||
@@ -1207,6 +1207,8 @@ rules.wavetimer = 波次時間
|
|||||||
rules.wavesending = Wave Sending
|
rules.wavesending = Wave Sending
|
||||||
rules.waves = 波次
|
rules.waves = 波次
|
||||||
rules.attack = 攻擊模式
|
rules.attack = 攻擊模式
|
||||||
|
rules.buildai = Base Builder AI
|
||||||
|
rules.buildaitier = Builder AI Tier
|
||||||
rules.rtsai = RTS AI
|
rules.rtsai = RTS AI
|
||||||
rules.rtsminsquadsize = 最小隊伍規模
|
rules.rtsminsquadsize = 最小隊伍規模
|
||||||
rules.rtsmaxsquadsize = 最大隊伍規模
|
rules.rtsmaxsquadsize = 最大隊伍規模
|
||||||
|
|||||||
@@ -155,3 +155,4 @@ AyuKo-o
|
|||||||
JojoFR1
|
JojoFR1
|
||||||
Xasmedy
|
Xasmedy
|
||||||
xStaBUx
|
xStaBUx
|
||||||
|
WayZer
|
||||||
|
|||||||
325
core/src/mindustry/ai/BaseBuilderAI.java
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
package mindustry.ai;
|
||||||
|
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
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.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.maps.generators.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.blocks.defense.*;
|
||||||
|
import mindustry.world.blocks.payloads.*;
|
||||||
|
import mindustry.world.blocks.production.*;
|
||||||
|
import mindustry.world.blocks.storage.*;
|
||||||
|
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
|
public class BaseBuilderAI{
|
||||||
|
private static final Vec2 axis = new Vec2(), rotator = new Vec2();
|
||||||
|
private static final int attempts = 6, coreUnitMultiplier = 2;
|
||||||
|
private static final float emptyChance = 0.01f;
|
||||||
|
private static final int timerStep = 0, timerSpawn = 1, timerRefreshPath = 2;
|
||||||
|
private static final float placeIntervalMin = 12f, placeIntervalMax = 2f;
|
||||||
|
private static final int pathStep = 50;
|
||||||
|
private static final Seq<Tile> tmpTiles = new Seq<>();
|
||||||
|
|
||||||
|
private static int correct = 0, incorrect = 0;
|
||||||
|
|
||||||
|
private int lastX, lastY, lastW, lastH;
|
||||||
|
private boolean triedWalls, foundPath;
|
||||||
|
|
||||||
|
final TeamData data;
|
||||||
|
final Interval timer = new Interval(4);
|
||||||
|
|
||||||
|
IntSet path = new IntSet();
|
||||||
|
IntSet calcPath = new IntSet();
|
||||||
|
@Nullable Tile calcTile;
|
||||||
|
boolean calculating, startedCalculating;
|
||||||
|
int calcCount = 0;
|
||||||
|
int totalCalcs = 0;
|
||||||
|
Block wallType;
|
||||||
|
|
||||||
|
public BaseBuilderAI(TeamData data){
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(){
|
||||||
|
|
||||||
|
//fill cores.
|
||||||
|
if(data.team.cores().size > 0){
|
||||||
|
var core = data.team.cores().first();
|
||||||
|
for(Item item : content.items()){
|
||||||
|
core.items.set(item, core.getMaximumAccepted(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wallType == null){
|
||||||
|
wallType = BaseGenerator.getDifficultyWall(1, data.team.rules().buildAiTier / 0.8f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data.team.rules().aiCoreSpawn && timer.get(timerSpawn, 60 * 6f) && data.hasCore()){
|
||||||
|
CoreBlock block = (CoreBlock)data.core().block;
|
||||||
|
int coreUnits = data.countType(block.unitType);
|
||||||
|
|
||||||
|
//create AI core unit(s)
|
||||||
|
if(!state.isEditor() && coreUnits < data.cores.size * coreUnitMultiplier){
|
||||||
|
Unit unit = block.unitType.create(data.team);
|
||||||
|
unit.set(data.cores.random());
|
||||||
|
unit.add();
|
||||||
|
Fx.spawn.at(unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//refresh path
|
||||||
|
if(!calculating && (timer.get(timerRefreshPath, 3f * Time.toMinutes) || !startedCalculating) && data.hasCore()){
|
||||||
|
calculating = true;
|
||||||
|
startedCalculating = true;
|
||||||
|
calcPath.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//didn't find tile in time
|
||||||
|
if(calculating && calcCount >= world.width() * world.height()){
|
||||||
|
calculating = false;
|
||||||
|
calcCount = 0;
|
||||||
|
calcPath.clear();
|
||||||
|
totalCalcs ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculate path for units so schematics are not placed on it
|
||||||
|
if(calculating){
|
||||||
|
if(calcTile == null){
|
||||||
|
Vars.spawner.eachGroundSpawn((x, y) -> calcTile = world.tile(x, y));
|
||||||
|
if(calcTile == null){
|
||||||
|
calculating = false;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
var field = pathfinder.getField(data.team, Pathfinder.costGround, Pathfinder.fieldCore);
|
||||||
|
|
||||||
|
if(field.weights != null){
|
||||||
|
int[] weights = field.weights;
|
||||||
|
for(int i = 0; i < pathStep; i++){
|
||||||
|
int minCost = Integer.MAX_VALUE;
|
||||||
|
int cx = calcTile.x, cy = calcTile.y;
|
||||||
|
boolean foundAny = false;
|
||||||
|
for(Point2 p : Geometry.d4){
|
||||||
|
int nx = cx + p.x, ny = cy + p.y, packed = world.packArray(nx, ny);
|
||||||
|
|
||||||
|
Tile other = world.tile(nx, ny);
|
||||||
|
if(other != null && weights[packed] < minCost && weights[packed] != -1){
|
||||||
|
minCost = weights[packed];
|
||||||
|
calcTile = other;
|
||||||
|
foundAny = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//didn't find anything, break out of loop, this will trigger a clear later
|
||||||
|
if(!foundAny){
|
||||||
|
calcCount = Integer.MAX_VALUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
calcPath.add(calcTile.pos());
|
||||||
|
for(Point2 p : Geometry.d8){
|
||||||
|
calcPath.add(Point2.pack(p.x + calcTile.x, p.y + calcTile.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
//found the end.
|
||||||
|
if(calcTile.build instanceof CoreBuild b && b.team != data.team){
|
||||||
|
//clean up calculations and flush results
|
||||||
|
calculating = false;
|
||||||
|
calcCount = 0;
|
||||||
|
path.clear();
|
||||||
|
path.addAll(calcPath);
|
||||||
|
calcPath.clear();
|
||||||
|
calcTile = null;
|
||||||
|
totalCalcs ++;
|
||||||
|
foundPath = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
calcCount ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//only schedule when there's something to build.
|
||||||
|
if(foundPath && data.plans.isEmpty() && timer.get(timerStep, Mathf.lerp(placeIntervalMin, placeIntervalMax, data.team.rules().buildAiTier))){
|
||||||
|
//TODO walls are silly, no walls
|
||||||
|
//if(!triedWalls){
|
||||||
|
// tryWalls();
|
||||||
|
// triedWalls = true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
for(int i = 0; i < attempts; i++){
|
||||||
|
int range = 150;
|
||||||
|
|
||||||
|
Position pos = randomPosition();
|
||||||
|
|
||||||
|
//when there are no random positions, do nothing.
|
||||||
|
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);
|
||||||
|
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<BasePart> parts = null;
|
||||||
|
|
||||||
|
//pick a completely random base part, and place it a random location
|
||||||
|
//((yes, very intelligent))
|
||||||
|
if(tile.drop() != null && Vars.bases.forResource(tile.drop()).any()){
|
||||||
|
parts = Vars.bases.forResource(tile.drop());
|
||||||
|
}else if(Mathf.chance(emptyChance)){
|
||||||
|
parts = Vars.bases.parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(parts != null){
|
||||||
|
BasePart part = parts.random();
|
||||||
|
if(tryPlace(part, tile.x, tile.y)){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return a random position from which to seed building. */
|
||||||
|
private Position randomPosition(){
|
||||||
|
if(data.hasCore()){
|
||||||
|
return data.cores.random();
|
||||||
|
}else if(data.team == state.rules.waveTeam){
|
||||||
|
return spawner.getSpawns().random();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean tryPlace(BasePart part, int x, int y){
|
||||||
|
int rotation = Mathf.range(2);
|
||||||
|
axis.set((int)(part.schematic.width / 2f), (int)(part.schematic.height / 2f));
|
||||||
|
Schematic result = Schematics.rotate(part.schematic, rotation);
|
||||||
|
int rotdeg = rotation*90;
|
||||||
|
rotator.set(part.centerX, part.centerY).rotateAround(axis, rotdeg);
|
||||||
|
//bottom left schematic corner
|
||||||
|
int cx = x - (int)rotator.x;
|
||||||
|
int cy = y - (int)rotator.y;
|
||||||
|
|
||||||
|
//check valid placeability
|
||||||
|
for(Stile tile : result.tiles){
|
||||||
|
int realX = tile.x + cx, realY = tile.y + cy;
|
||||||
|
if(!Build.validPlace(tile.block, data.team, realX, realY, tile.rotation)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Tile wtile = world.tile(realX, realY);
|
||||||
|
|
||||||
|
if(tile.block instanceof PayloadConveyor || tile.block instanceof PayloadBlock){
|
||||||
|
//near a building
|
||||||
|
for(Point2 point : Edges.getEdges(tile.block.size)){
|
||||||
|
var t = world.build(tile.x + point.x, tile.y + point.y);
|
||||||
|
if(t != null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//may intersect AI path
|
||||||
|
tmpTiles.clear();
|
||||||
|
if(tile.block.solid && wtile != null && wtile.getLinkedTilesAs(tile.block, tmpTiles).contains(t -> path.contains(t.pos()))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//make sure at least X% of resource requirements are met
|
||||||
|
correct = incorrect = 0;
|
||||||
|
boolean anyDrills = false;
|
||||||
|
|
||||||
|
if(part.required instanceof Item){
|
||||||
|
for(Stile tile : result.tiles){
|
||||||
|
if(tile.block instanceof Drill){
|
||||||
|
anyDrills = true;
|
||||||
|
|
||||||
|
tile.block.iterateTaken(tile.x + cx, tile.y + cy, (ex, ey) -> {
|
||||||
|
Tile res = world.rawTile(ex, ey);
|
||||||
|
if(res.drop() == part.required){
|
||||||
|
correct ++;
|
||||||
|
}else if(res.drop() != null){
|
||||||
|
incorrect ++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//fail if not enough fit requirements
|
||||||
|
if(anyDrills && (incorrect != 0 || correct == 0)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//queue it
|
||||||
|
for(Stile tile : result.tiles){
|
||||||
|
data.plans.add(new BlockPlan(cx + tile.x, cy + tile.y, tile.rotation, tile.block.id, tile.config));
|
||||||
|
}
|
||||||
|
|
||||||
|
lastX = cx - 1;
|
||||||
|
lastY = cy - 1;
|
||||||
|
lastW = result.width + 2;
|
||||||
|
lastH = result.height + 2;
|
||||||
|
|
||||||
|
triedWalls = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tryWalls(){
|
||||||
|
Block wall = wallType;
|
||||||
|
Building spawnt = state.rules.defaultTeam.core() != null ? state.rules.defaultTeam.core() : data.team.core();
|
||||||
|
Tile spawn = spawnt == null ? null : spawnt.tile;
|
||||||
|
|
||||||
|
if(spawn == null) return;
|
||||||
|
|
||||||
|
for(int wx = lastX; wx <= lastX + lastW; wx++){
|
||||||
|
outer:
|
||||||
|
for(int wy = lastY; wy <= lastY + lastH; wy++){
|
||||||
|
Tile tile = world.tile(wx, wy);
|
||||||
|
|
||||||
|
if(tile == null || !tile.block().alwaysReplace) continue;
|
||||||
|
|
||||||
|
boolean any = false;
|
||||||
|
|
||||||
|
for(Point2 p : Geometry.d8){
|
||||||
|
if(Angles.angleDist(Angles.angle(p.x, p.y), spawn.angleTo(tile)) > 70){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tile o = world.tile(tile.x + p.x, tile.y + p.y);
|
||||||
|
if(o != null && (o.block() instanceof PayloadBlock || o.block() instanceof PayloadConveyor || o.block() instanceof ShockMine)){
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(o != null && o.team() == data.team && !(o.block() instanceof Wall)){
|
||||||
|
any = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpTiles.clear();
|
||||||
|
if(any && Build.validPlace(wall, data.team, tile.x, tile.y, 0) && !tile.getLinkedTilesAs(wall, tmpTiles).contains(t -> path.contains(t.pos()))){
|
||||||
|
data.plans.add(new BlockPlan(tile.x, tile.y, (short)0, wall.id, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,7 +54,10 @@ public class ControlPathfinder{
|
|||||||
(PathTile.nearSolid(tile) || PathTile.solid(tile) ? 3 : 0),
|
(PathTile.nearSolid(tile) || PathTile.solid(tile) ? 3 : 0),
|
||||||
|
|
||||||
costNaval = (team, tile) ->
|
costNaval = (team, tile) ->
|
||||||
(PathTile.solid(tile) || !PathTile.liquid(tile) ? impassable : 1) +
|
//impassable same-team neutral block, or non-liquid
|
||||||
|
((PathTile.solid(tile) && ((PathTile.team(tile) == team && !PathTile.teamPassable(tile)) || PathTile.team(tile) == 0)) || !PathTile.liquid(tile) ? impassable : 1) +
|
||||||
|
//impassable synthetic enemy block
|
||||||
|
((PathTile.team(tile) != team && PathTile.team(tile) != 0) && PathTile.solid(tile) ? wallImpassableCap : 0) +
|
||||||
(PathTile.nearGround(tile) || PathTile.nearSolid(tile) ? 6 : 0);
|
(PathTile.nearGround(tile) || PathTile.nearSolid(tile) ? 6 : 0);
|
||||||
|
|
||||||
public static boolean showDebug = false;
|
public static boolean showDebug = false;
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ public class Pathfinder implements Runnable{
|
|||||||
|
|
||||||
//water
|
//water
|
||||||
(team, tile) ->
|
(team, tile) ->
|
||||||
(PathTile.solid(tile) || !PathTile.liquid(tile) ? 6000 : 1) +
|
(!PathTile.liquid(tile) ? 6000 : 1) +
|
||||||
|
PathTile.health(tile) * 5 +
|
||||||
(PathTile.nearGround(tile) || PathTile.nearSolid(tile) ? 14 : 0) +
|
(PathTile.nearGround(tile) || PathTile.nearSolid(tile) ? 14 : 0) +
|
||||||
(PathTile.deep(tile) ? 0 : 1) +
|
(PathTile.deep(tile) ? 0 : 1) +
|
||||||
(PathTile.damages(tile) ? 35 : 0)
|
(PathTile.damages(tile) ? 35 : 0)
|
||||||
@@ -527,7 +528,9 @@ public class Pathfinder implements Runnable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean passable(int pos){
|
protected boolean passable(int pos){
|
||||||
return cost.getCost(team.id, pathfinder.tiles[pos]) != impassable;
|
int amount = cost.getCost(team.id, pathfinder.tiles[pos]);
|
||||||
|
//edge case: naval reports costs of 6000+ for non-liquids, even though they are not technically passable
|
||||||
|
return amount != impassable && !(cost == costTypes.get(costNaval) && amount >= 6000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets targets to pathfind towards. This must run on the main thread. */
|
/** Gets targets to pathfind towards. This must run on the main thread. */
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ import mindustry.world.blocks.ConstructBlock.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class BuilderAI extends AIController{
|
public class BuilderAI extends AIController{
|
||||||
public static float buildRadius = 1500, retreatDst = 110f, retreatDelay = Time.toSeconds * 2f;
|
public static float buildRadius = 1500, retreatDst = 110f, retreatDelay = Time.toSeconds * 2f, defaultRebuildPeriod = 60f * 2f;
|
||||||
|
|
||||||
public @Nullable Unit assistFollowing;
|
public @Nullable Unit assistFollowing;
|
||||||
public @Nullable Unit following;
|
public @Nullable Unit following;
|
||||||
public @Nullable Teamc enemy;
|
public @Nullable Teamc enemy;
|
||||||
public @Nullable BlockPlan lastPlan;
|
public @Nullable BlockPlan lastPlan;
|
||||||
|
|
||||||
public float fleeRange = 370f, rebuildPeriod = 60f * 2f;
|
public float fleeRange = 370f, rebuildPeriod = defaultRebuildPeriod;
|
||||||
public boolean alwaysFlee;
|
public boolean alwaysFlee;
|
||||||
public boolean onlyAssist;
|
public boolean onlyAssist;
|
||||||
|
|
||||||
@@ -34,6 +34,14 @@ public class BuilderAI extends AIController{
|
|||||||
public BuilderAI(){
|
public BuilderAI(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(){
|
||||||
|
//rebuild much faster with buildAI; there are usually few builder units so this is fine
|
||||||
|
if(rebuildPeriod == defaultRebuildPeriod && unit.team.rules().buildAi){
|
||||||
|
rebuildPeriod = 10f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateMovement(){
|
public void updateMovement(){
|
||||||
|
|
||||||
|
|||||||
@@ -2548,7 +2548,6 @@ public class Blocks{
|
|||||||
researchCostMultiplier = 0.4f;
|
researchCostMultiplier = 0.4f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//TODO stats
|
|
||||||
fluxReactor = new VariableReactor("flux-reactor"){{
|
fluxReactor = new VariableReactor("flux-reactor"){{
|
||||||
requirements(Category.power, with(Items.graphite, 300, Items.carbide, 200, Items.oxide, 100, Items.silicon, 600, Items.surgeAlloy, 300));
|
requirements(Category.power, with(Items.graphite, 300, Items.carbide, 200, Items.oxide, 100, Items.silicon, 600, Items.surgeAlloy, 300));
|
||||||
powerProduction = 120f;
|
powerProduction = 120f;
|
||||||
@@ -2585,7 +2584,6 @@ public class Blocks{
|
|||||||
);
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//TODO stats
|
|
||||||
neoplasiaReactor = new HeaterGenerator("neoplasia-reactor"){{
|
neoplasiaReactor = new HeaterGenerator("neoplasia-reactor"){{
|
||||||
requirements(Category.power, with(Items.tungsten, 1000, Items.carbide, 300, Items.oxide, 150, Items.silicon, 500, Items.phaseFabric, 300, Items.surgeAlloy, 200));
|
requirements(Category.power, with(Items.tungsten, 1000, Items.carbide, 300, Items.oxide, 150, Items.silicon, 500, Items.phaseFabric, 300, Items.surgeAlloy, 200));
|
||||||
|
|
||||||
@@ -2609,7 +2607,6 @@ public class Blocks{
|
|||||||
explodeSound = Sounds.largeExplosion;
|
explodeSound = Sounds.largeExplosion;
|
||||||
|
|
||||||
powerProduction = 140f;
|
powerProduction = 140f;
|
||||||
rebuildable = false;
|
|
||||||
|
|
||||||
ambientSound = Sounds.bioLoop;
|
ambientSound = Sounds.bioLoop;
|
||||||
ambientSoundVolume = 0.2f;
|
ambientSoundVolume = 0.2f;
|
||||||
@@ -3126,8 +3123,8 @@ public class Blocks{
|
|||||||
drawer = new DrawTurret(){{
|
drawer = new DrawTurret(){{
|
||||||
parts.add(new RegionPart("-mid"){{
|
parts.add(new RegionPart("-mid"){{
|
||||||
progress = PartProgress.recoil;
|
progress = PartProgress.recoil;
|
||||||
under = true;
|
under = false;
|
||||||
moveY = -1f;
|
moveY = -1.25f;
|
||||||
}});
|
}});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -3417,14 +3414,17 @@ public class Blocks{
|
|||||||
}}
|
}}
|
||||||
);
|
);
|
||||||
|
|
||||||
shoot = new ShootAlternate(){{
|
shoot = new ShootBarrel(){{
|
||||||
|
barrels = new float[]{
|
||||||
|
-4, -1.25f, 0,
|
||||||
|
0, 0, 0,
|
||||||
|
4, -1.25f, 0
|
||||||
|
};
|
||||||
shots = 4;
|
shots = 4;
|
||||||
barrels = 3;
|
|
||||||
spread = 3.5f;
|
|
||||||
shotDelay = 5f;
|
shotDelay = 5f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
shootY = 7f;
|
shootY = 4.5f;
|
||||||
reload = 30f;
|
reload = 30f;
|
||||||
inaccuracy = 10f;
|
inaccuracy = 10f;
|
||||||
range = 240f;
|
range = 240f;
|
||||||
@@ -3489,11 +3489,16 @@ public class Blocks{
|
|||||||
);
|
);
|
||||||
|
|
||||||
drawer = new DrawTurret(){{
|
drawer = new DrawTurret(){{
|
||||||
parts.add(new RegionPart("-barrel"){{
|
parts.add(new RegionPart("-side"){{
|
||||||
progress = PartProgress.recoil.delay(0.5f); //Since recoil is 1-0, cut from the start instead of the end.
|
progress = PartProgress.warmup;
|
||||||
under = true;
|
moveX = 0.6f;
|
||||||
turretHeatLayer = Layer.turret - 0.0001f;
|
moveRot = -15f;
|
||||||
moveY = -1.5f;
|
mirror = true;
|
||||||
|
layerOffset = 0.001f;
|
||||||
|
moves.add(new PartMove(PartProgress.recoil, 0.5f, -0.5f, -8f));
|
||||||
|
}}, new RegionPart("-barrel"){{
|
||||||
|
progress = PartProgress.recoil;
|
||||||
|
moveY = -2.5f;
|
||||||
}});
|
}});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -3502,7 +3507,7 @@ public class Blocks{
|
|||||||
reload = 31f;
|
reload = 31f;
|
||||||
consumeAmmoOnce = false;
|
consumeAmmoOnce = false;
|
||||||
ammoEjectBack = 3f;
|
ammoEjectBack = 3f;
|
||||||
recoil = 2f;
|
recoil = 0f;
|
||||||
shake = 1f;
|
shake = 1f;
|
||||||
shoot.shots = 4;
|
shoot.shots = 4;
|
||||||
shoot.shotDelay = 3f;
|
shoot.shotDelay = 3f;
|
||||||
@@ -4658,7 +4663,7 @@ public class Blocks{
|
|||||||
|
|
||||||
recoil = 0.5f;
|
recoil = 0.5f;
|
||||||
|
|
||||||
fogRadiusMultiuplier = 0.4f;
|
fogRadiusMultiplier = 0.4f;
|
||||||
coolantMultiplier = 6f;
|
coolantMultiplier = 6f;
|
||||||
shootSound = Sounds.missileLaunch;
|
shootSound = Sounds.missileLaunch;
|
||||||
|
|
||||||
@@ -5814,7 +5819,7 @@ public class Blocks{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
interplanetaryAccelerator = new Accelerator("interplanetary-accelerator"){{
|
interplanetaryAccelerator = new Accelerator("interplanetary-accelerator"){{
|
||||||
requirements(Category.effect, BuildVisibility.campaignOnly, with(Items.copper, 16000, Items.silicon, 11000, Items.thorium, 13000, Items.titanium, 12000, Items.surgeAlloy, 6000, Items.phaseFabric, 5000));
|
requirements(Category.effect, BuildVisibility.hidden, with(Items.copper, 16000, Items.silicon, 11000, Items.thorium, 13000, Items.titanium, 12000, Items.surgeAlloy, 6000, Items.phaseFabric, 5000));
|
||||||
researchCostMultiplier = 0.1f;
|
researchCostMultiplier = 0.1f;
|
||||||
size = 7;
|
size = 7;
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
|
|||||||
@@ -3258,7 +3258,7 @@ public class UnitTypes{
|
|||||||
drag = 0.1f;
|
drag = 0.1f;
|
||||||
speed = 0.6f;
|
speed = 0.6f;
|
||||||
hitSize = 23f;
|
hitSize = 23f;
|
||||||
health = 6700;
|
health = 7300;
|
||||||
armor = 5f;
|
armor = 5f;
|
||||||
|
|
||||||
lockLegBase = true;
|
lockLegBase = true;
|
||||||
@@ -3271,13 +3271,14 @@ public class UnitTypes{
|
|||||||
|
|
||||||
abilities.add(new ShieldArcAbility(){{
|
abilities.add(new ShieldArcAbility(){{
|
||||||
region = "tecta-shield";
|
region = "tecta-shield";
|
||||||
radius = 34f;
|
radius = 36f;
|
||||||
angle = 82f;
|
angle = 82f;
|
||||||
regen = 0.6f;
|
regen = 0.6f;
|
||||||
cooldown = 60f * 8f;
|
cooldown = 60f * 8f;
|
||||||
max = 1500f;
|
max = 2000f;
|
||||||
y = -20f;
|
y = -20f;
|
||||||
width = 6f;
|
width = 6f;
|
||||||
|
whenShooting = false;
|
||||||
}});
|
}});
|
||||||
|
|
||||||
rotateSpeed = 2.1f;
|
rotateSpeed = 2.1f;
|
||||||
@@ -3319,14 +3320,14 @@ public class UnitTypes{
|
|||||||
velocityRnd = 0.33f;
|
velocityRnd = 0.33f;
|
||||||
heatColor = Color.red;
|
heatColor = Color.red;
|
||||||
|
|
||||||
bullet = new MissileBulletType(4.2f, 47){{
|
bullet = new MissileBulletType(4.2f, 60){{
|
||||||
homingPower = 0.2f;
|
homingPower = 0.2f;
|
||||||
weaveMag = 4;
|
weaveMag = 4;
|
||||||
weaveScale = 4;
|
weaveScale = 4;
|
||||||
lifetime = 55f;
|
lifetime = 55f;
|
||||||
shootEffect = Fx.shootBig2;
|
shootEffect = Fx.shootBig2;
|
||||||
smokeEffect = Fx.shootSmokeTitan;
|
smokeEffect = Fx.shootSmokeTitan;
|
||||||
splashDamage = 60f;
|
splashDamage = 70f;
|
||||||
splashDamageRadius = 30f;
|
splashDamageRadius = 30f;
|
||||||
frontColor = Color.white;
|
frontColor = Color.white;
|
||||||
hitSound = Sounds.none;
|
hitSound = Sounds.none;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class ContentLoader{
|
|||||||
|
|
||||||
public ContentLoader(){
|
public ContentLoader(){
|
||||||
for(ContentType type : ContentType.all){
|
for(ContentType type : ContentType.all){
|
||||||
contentMap[type.ordinal()] = new Seq<>();
|
contentMap[type.ordinal()] = new Seq<>(type.contentClass == null ? Object.class : type.contentClass);
|
||||||
contentNameMap[type.ordinal()] = new ObjectMap<>();
|
contentNameMap[type.ordinal()] = new ObjectMap<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -445,6 +445,12 @@ public class Logic implements ApplicationListener{
|
|||||||
updateWeather();
|
updateWeather();
|
||||||
|
|
||||||
for(TeamData data : state.teams.getActive()){
|
for(TeamData data : state.teams.getActive()){
|
||||||
|
//does not work on PvP so built-in attack maps can have it on by default without issues
|
||||||
|
if(data.team.rules().buildAi && !state.rules.pvp){
|
||||||
|
if(data.buildAi == null) data.buildAi = new BaseBuilderAI(data);
|
||||||
|
data.buildAi.update();
|
||||||
|
}
|
||||||
|
|
||||||
if(data.team.rules().rtsAi){
|
if(data.team.rules().rtsAi){
|
||||||
if(data.rtsAi == null) data.rtsAi = new RtsAI(data);
|
if(data.rtsAi == null) data.rtsAi = new RtsAI(data);
|
||||||
data.rtsAi.update();
|
data.rtsAi.update();
|
||||||
|
|||||||
@@ -233,6 +233,8 @@ public class NetClient implements ApplicationListener{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(message == null) return;
|
||||||
|
|
||||||
if(message.length() > maxTextLength){
|
if(message.length() > maxTextLength){
|
||||||
throw new ValidateException(player, "Player has sent a message above the text limit.");
|
throw new ValidateException(player, "Player has sent a message above the text limit.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import mindustry.type.*;
|
|||||||
import mindustry.ui.dialogs.*;
|
import mindustry.ui.dialogs.*;
|
||||||
import rhino.*;
|
import rhino.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
@@ -140,6 +141,67 @@ public interface Platform{
|
|||||||
* @param title The title of the native dialog
|
* @param title The title of the native dialog
|
||||||
*/
|
*/
|
||||||
default void showFileChooser(boolean open, String title, String extension, Cons<Fi> cons){
|
default void showFileChooser(boolean open, String title, String extension, Cons<Fi> cons){
|
||||||
|
if(OS.isLinux && !OS.isAndroid){
|
||||||
|
showZenity(open, title, new String[]{extension}, cons, () -> defaultFileDialog(open, title, extension, cons));
|
||||||
|
}else{
|
||||||
|
defaultFileDialog(open, title, extension, cons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** attempt to use the native file picker with zenity, or runs the fallback Runnable if the operation fails */
|
||||||
|
static void showZenity(boolean open, String title, String[] extensions, Cons<Fi> cons, Runnable fallback){
|
||||||
|
Threads.daemon(() -> {
|
||||||
|
try{
|
||||||
|
String formatted = (title.startsWith("@") ? Core.bundle.get(title.substring(1)) : title).replaceAll("\"", "'");
|
||||||
|
|
||||||
|
String last = FileChooser.getLastDirectory().absolutePath();
|
||||||
|
if(!last.endsWith("/")) last += "/";
|
||||||
|
|
||||||
|
//zenity doesn't support filtering by extension
|
||||||
|
Seq<String> args = Seq.with("zenity",
|
||||||
|
"--file-selection",
|
||||||
|
"--title=" + formatted,
|
||||||
|
"--filename=" + last,
|
||||||
|
"--confirm-overwrite",
|
||||||
|
"--file-filter=" + Seq.with(extensions).toString(" ", s -> "*." + s),
|
||||||
|
"--file-filter=All files | *" //allow anything if the user wants
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!open){
|
||||||
|
args.add("--save");
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = OS.exec(args.toArray(String.class));
|
||||||
|
//first line.
|
||||||
|
if(result.length() > 1 && result.contains("\n")){
|
||||||
|
result = result.split("\n")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
//cancelled selection, ignore result
|
||||||
|
if(result.isEmpty() || result.equals("\n")) return;
|
||||||
|
|
||||||
|
if(result.endsWith("\n")) result = result.substring(0, result.length() - 1);
|
||||||
|
if(result.contains("\n")) throw new IOException("invalid input: \"" + result + "\"");
|
||||||
|
|
||||||
|
Fi file = Core.files.absolute(result);
|
||||||
|
Core.app.post(() -> {
|
||||||
|
FileChooser.setLastDirectory(file.isDirectory() ? file : file.parent());
|
||||||
|
|
||||||
|
if(!open){
|
||||||
|
cons.get(file.parent().child(file.nameWithoutExtension() + "." + extensions[0]));
|
||||||
|
}else{
|
||||||
|
cons.get(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}catch(Exception e){
|
||||||
|
Log.err(e);
|
||||||
|
Log.warn("zenity not found, using non-native file dialog. Consider installing `zenity` for native file dialogs.");
|
||||||
|
Core.app.post(fallback);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void defaultFileDialog(boolean open, String title, String extension, Cons<Fi> cons){
|
||||||
new FileChooser(title, file -> file.extEquals(extension), open, file -> {
|
new FileChooser(title, file -> file.extEquals(extension), open, file -> {
|
||||||
if(!open){
|
if(!open){
|
||||||
cons.get(file.parent().child(file.nameWithoutExtension() + "." + extension));
|
cons.get(file.parent().child(file.nameWithoutExtension() + "." + extension));
|
||||||
@@ -161,11 +223,17 @@ public interface Platform{
|
|||||||
default void showMultiFileChooser(Cons<Fi> cons, String... extensions){
|
default void showMultiFileChooser(Cons<Fi> cons, String... extensions){
|
||||||
if(mobile){
|
if(mobile){
|
||||||
showFileChooser(true, extensions[0], cons);
|
showFileChooser(true, extensions[0], cons);
|
||||||
|
}else if(OS.isLinux && !OS.isAndroid){
|
||||||
|
showZenity(true, "@open", extensions, cons, () -> defaultMultiFileChooser(cons, extensions));
|
||||||
}else{
|
}else{
|
||||||
new FileChooser("@open", file -> Structs.contains(extensions, file.extension().toLowerCase()), true, cons).show();
|
defaultMultiFileChooser(cons, extensions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void defaultMultiFileChooser(Cons<Fi> cons, String... extensions){
|
||||||
|
new FileChooser("@open", file -> Structs.contains(extensions, file.extension().toLowerCase()), true, cons).show();
|
||||||
|
}
|
||||||
|
|
||||||
/** Hide the app. Android only. */
|
/** Hide the app. Android only. */
|
||||||
default void hide(){
|
default void hide(){
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,6 +85,14 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
Fonts.loadFonts();
|
Fonts.loadFonts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void loadColors(){
|
||||||
|
Colors.put("accent", Pal.accent);
|
||||||
|
Colors.put("unlaunched", Color.valueOf("8982ed"));
|
||||||
|
Colors.put("highlight", Pal.accent.cpy().lerp(Color.white, 0.3f));
|
||||||
|
Colors.put("stat", Pal.stat);
|
||||||
|
Colors.put("negstat", Pal.negativeStat);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadAsync(){
|
public void loadAsync(){
|
||||||
|
|
||||||
@@ -92,6 +100,8 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadSync(){
|
public void loadSync(){
|
||||||
|
loadColors();
|
||||||
|
|
||||||
Fonts.outline.getData().markupEnabled = true;
|
Fonts.outline.getData().markupEnabled = true;
|
||||||
Fonts.def.getData().markupEnabled = true;
|
Fonts.def.getData().markupEnabled = true;
|
||||||
Fonts.def.setOwnsTexture(false);
|
Fonts.def.setOwnsTexture(false);
|
||||||
@@ -125,12 +135,6 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
|
|
||||||
ClickListener.clicked = () -> Sounds.press.play();
|
ClickListener.clicked = () -> Sounds.press.play();
|
||||||
|
|
||||||
Colors.put("accent", Pal.accent);
|
|
||||||
Colors.put("unlaunched", Color.valueOf("8982ed"));
|
|
||||||
Colors.put("highlight", Pal.accent.cpy().lerp(Color.white, 0.3f));
|
|
||||||
Colors.put("stat", Pal.stat);
|
|
||||||
Colors.put("negstat", Pal.negativeStat);
|
|
||||||
|
|
||||||
drillCursor = Core.graphics.newCursor("drill", Fonts.cursorScale());
|
drillCursor = Core.graphics.newCursor("drill", Fonts.cursorScale());
|
||||||
unloadCursor = Core.graphics.newCursor("unload", Fonts.cursorScale());
|
unloadCursor = Core.graphics.newCursor("unload", Fonts.cursorScale());
|
||||||
targetCursor = Core.graphics.newCursor("target", Fonts.cursorScale());
|
targetCursor = Core.graphics.newCursor("target", Fonts.cursorScale());
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ public abstract class Content implements Comparable<Content>{
|
|||||||
return minfo.mod == null;
|
return minfo.mod == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return whether this content is from a mod. */
|
||||||
|
public boolean isModded(){
|
||||||
|
return !isVanilla();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Content c){
|
public int compareTo(Content c){
|
||||||
return Integer.compare(id, c.id);
|
return Integer.compare(id, c.id);
|
||||||
|
|||||||