Compare commits

..

143 Commits
v130.1 ... v131

Author SHA1 Message Date
Anuken
edbe795aa5 Merge remote-tracking branch 'origin/master' 2021-09-12 20:21:59 -04:00
Anuken
087cd2c55a Cleanup 2021-09-12 20:21:55 -04:00
fuzzbuck
ca62deaaa9 Change io event server (#5981)
(offline at this time) will used for events & seasonal modes
2021-09-12 15:09:52 -04:00
JrTRinny
d33a4f9f87 More Target varieties for energy field ability (#5828)
* more targets for energy field ability

* group booleans
2021-09-12 14:55:26 -04:00
Shockwave
f64d078f29 Update bundle_zh_CN.properties (#5938)
* Update bundle_zh_CN.properties

1. Inherited from <https://github.com/Anuken/Mindustry/pull/5661>
2. Synced latest commit from English bundle.

* Update bundle_zh_CN.properties

Synced cliff support for editor

* Update bundle_zh_CN.properties

Minor optimization

* Update bundle_zh_CN.properties

Minor fix at line 349~

* Update bundle_zh_CN.properties

Synced recent update in English bundle. (Hide All and Show All)

* Update bundle_zh_CN.properties

1. Synced hint for high threat level sector
2. Unified the term "sector"
3. Minor fix on the half-width commas

* Update bundle_zh_CN.properties

Optimized key-pressing descriptions.

* Update bundle_zh_CN.properties

Restore line 934 to half-width comma

* Update bundle_zh_CN.properties

Synced name of new sectors.
2021-09-12 12:54:32 -04:00
RebornTrack970
da465c7786 TR Translate before release (#5980) 2021-09-12 11:34:03 -04:00
NickName73
9c12125e89 Update bundle_ru.properties (#5911) 2021-09-12 11:22:17 -04:00
Sharlotte
2a6d7c5a13 Update bundle_ko.properties (#5892)
* Update bundle_ko.properties

* Update bundle_ko.properties

* Update bundle_ko.properties

* Update bundle_ko.properties
2021-09-12 11:21:53 -04:00
YellOw139
71e38862b9 [Bundle][RO] Update (#5848)
* [Bundle][RO] Update

Changelog:

- New strings/changes up to commit 254284760f
- Typo fixes & various other improvements

* Update full_description.txt

* Update full_description.txt

* killing confusion

* Update bundle_ro.properties

* deep-tainted-water

* should do for now

* sector.name
2021-09-12 11:21:17 -04:00
彭瑞暄
b58a63b200 Update bundle_zh_TW.properties (#5860)
* Update bundle_zh_TW.properties

* Update bundle_zh_TW.properties

minor correction
2021-09-12 11:21:09 -04:00
VizardAlpha
ee8b4f478d Updates bundle_fr.properties (#5931)
* Updates bundle_fr.properties

* Added rivers on Serpulo / Added deep tainted water

* Error correction

* More campaign map progress .. Added new commits

* Update bundle_fr.properties
2021-09-12 11:09:46 -04:00
JrTRinny
1941f22676 Update bundle_th.properties (#5908)
* Update bundle_th.properties

* Update bundle_th.properties

* Update bundle_th.properties

* more beautiful names

* Update bundle_th.properties
2021-09-12 11:09:40 -04:00
Anuken
35ffbef557 #5932 2021-09-12 11:07:18 -04:00
Anuken
24db94a55b No server category colors 2021-09-12 11:05:05 -04:00
Anuken
46bda97362 Merge remote-tracking branch 'origin/master' 2021-09-12 09:05:23 -04:00
Anuken
a1b9f7d1b3 Fixed #5979 2021-09-12 09:05:18 -04:00
Matthew Peng
32db058dbe Why is the smelter -top drawn between the flame circles? (#5817) 2021-09-11 18:47:30 -04:00
Anuken
2f7c5994a7 Fixed #5978 2021-09-11 15:43:24 -04:00
Anuken
2664bb84be Fixed #5974 2021-09-11 13:30:10 -04:00
Anuken
bdcfb7ab45 Merge remote-tracking branch 'origin/master' 2021-09-11 12:15:39 -04:00
Anuken
5cf47f4198 Clamp sector description in info 2021-09-11 12:15:34 -04:00
Darkness6030
515ee060d2 [RU] Sectors name translation (#5972)
С береговой линией все понятно. 
Но почему я выбрал "Прибрежная крепость"?
Все просто. "Naval" переводится как "Водяной", но "Водяная Крепость" - звучит *не очень*.
Нужен какой-то синоним. Я рассмотрел варианты "Морская", "Береговая", но в конце концов остановился на варианте "Прибрежная".

Если вы думаете иначе, предлагайте свой вариант перевода.
2021-09-11 10:20:57 -04:00
Anuken
90c2473448 Duct bridge crash fix 2021-09-11 10:07:00 -04:00
Anuken
c5a90759e5 Fixed #5971 / Fixed #5973 2021-09-11 08:45:17 -04:00
Anuken
cccce6badd Make Base AI walls correspond to tier 2021-09-10 21:11:57 -04:00
Anuken
decc570867 Slightly denser generated bases 2021-09-10 17:23:17 -04:00
Anuken
caa34c959e More campaign map progress 2021-09-10 17:07:06 -04:00
Anuken
b8fa15e546 Merge remote-tracking branch 'origin/master' 2021-09-10 16:33:30 -04:00
Anuken
47d5be679d Map progress 2021-09-10 16:33:26 -04:00
buthed010203
fc7f689ea4 Named pathfinder thread (#5969) 2021-09-10 15:56:42 -04:00
Anuken
7c028ffcb8 Experimental positional spawn support / WIP map 2021-09-10 13:56:12 -04:00
Anuken
10c3f9e44a River noise target field 2021-09-10 09:22:39 -04:00
Anuken
b2a634e5e7 Untested/WIP naval campaign map 2021-09-10 09:17:25 -04:00
Anuken
ae0a70703b Wave edit dialog cleanup 2021-09-09 22:25:08 -04:00
TranquillyUnpleasant
9076325fa1 Add a copy button to spawn groups (#5957)
* copy button

* rebuild groups on removal

* two factor sorting

* copy method for spawngroup

* implement Clonable

* revert to copy to call clone
2021-09-09 19:38:56 -04:00
Anuken
08d7390775 Merge remote-tracking branch 'origin/master' 2021-09-09 17:05:00 -04:00
Anuken
cbe188abab Map editor bugfixes / Re-added build noise 2021-09-09 17:04:55 -04:00
Matthew Peng
abbc25798d Pull trail updating out into its own method (#5964) 2021-09-09 15:47:08 -04:00
Anuken
a3ede6cf0b Merge remote-tracking branch 'origin/master' 2021-09-09 12:08:38 -04:00
Anuken
e997768a0a d 2021-09-09 12:08:33 -04:00
itcannotbe
671098cc28 Add Build Cost Multiplier to Distributor (#5967)
It just makes sense.
2021-09-09 11:16:47 -04:00
Anuken
1a686c44a1 Fixed editor crash 2021-09-09 09:59:35 -04:00
Anuken
9e737cd3fe Merge remote-tracking branch 'origin/master' 2021-09-08 20:44:31 -04:00
Anuken
deed84f9a3 Public power graph contents 2021-09-08 20:44:26 -04:00
Matthew Peng
868cd4fb0b Just because a generator doesn't have turbines doesn't mean it doesn't have liquid (#5962) 2021-09-08 20:40:56 -04:00
Anuken
a5697a7d4b Fixed mod alpha bleeding not applying correctly 2021-09-08 15:09:05 -04:00
Anuken
2222330b43 Added hint for high threat level sector 2021-09-08 11:23:37 -04:00
Anuken
cde192b59a Added Block#allowConfigInventory 2021-09-08 09:04:04 -04:00
Anuken
c98eb2edd7 Fixed #5958 2021-09-08 08:42:23 -04:00
Anuken
dd7062f0f7 ParticleEffect#sizeInterp / Log usable RAM 2021-09-07 22:32:27 -04:00
Anuken
8adefb7b72 Merge remote-tracking branch 'origin/master' 2021-09-07 17:57:17 -04:00
Anuken
5e13f71fde Minor bugfixes & compatibility fixes 2021-09-07 17:57:03 -04:00
Matthew Peng
d257adf0c1 Show All (#5954) 2021-09-07 15:20:59 -04:00
TranquillyUnpleasant
34d2a0d3a0 Hide all button for units (#5953)
* Hide all button for units

* Add bundle property
2021-09-07 13:38:43 -04:00
Matthew Peng
efae0d3b6a Anuke what is this (#5949) 2021-09-06 20:45:42 -04:00
buthed010203
a393e21326 remove redundant Core.bundle.get (#5947) 2021-09-06 15:08:22 -04:00
Anuken
5641b4901c Easier stained mountains guardian 2021-09-05 23:01:26 -04:00
Anuken
4da21ba363 Added cliff support to editor 2021-09-05 20:08:02 -04:00
Anuken
508abba2ec Merge remote-tracking branch 'origin/master' 2021-09-05 18:00:21 -04:00
Anuken
87ff876db3 Take block timeScale into account for sector damage 2021-09-05 18:00:16 -04:00
CancerGuy
4720f1b876 Add files via upload (#5943) 2021-09-05 17:06:00 -04:00
Anuken
e35d09fe62 Merge remote-tracking branch 'origin/master' 2021-09-05 12:07:20 -04:00
Anuken
fb74dfa02f Default visualElevation for ships 2021-09-05 12:07:15 -04:00
Darkness6030
461d87dbef Add HexPvp server to global V6 list (#5940) 2021-09-05 12:03:57 -04:00
TranquillyUnpleasant
cf5d172922 Wave graph y axis refactor (#5926)
* Y axis refactor

* Fix formatting inconsistencies

* Make style match xml
2021-09-05 11:21:49 -04:00
Anuken
227fb388b8 Update building consume module before main update 2021-09-05 11:18:31 -04:00
Anuken
89d495fdb1 Merge remote-tracking branch 'origin/master' 2021-09-04 23:28:20 -04:00
Anuken
82e659dd80 Planet rendering infrastructure stuff 2021-09-04 23:28:15 -04:00
SoMall-dumpling
f20b9c828c Update Blocks.java (#5939)
simplest integer ratio
2021-09-04 22:30:07 -04:00
Anuken
efe5668c5a Merge remote-tracking branch 'origin/master' 2021-09-04 20:37:31 -04:00
Anuken
0331d8c6c4 Fixed #5937 2021-09-04 20:37:26 -04:00
Volas171
15882016ca 🤦 (#5936) 2021-09-04 18:07:29 -04:00
Anuken
b4b9a44126 Merge remote-tracking branch 'origin/master' 2021-09-04 18:07:15 -04:00
Anuken
063d2ce6c0 Implemented #5905 properly 2021-09-04 18:07:08 -04:00
ZestyLemonade
3985620289 space-begone (#5935)
Co-authored-by: sample-text-here <kjdshkasjhdfkj@jashdkaj.ksdh>
2021-09-04 17:43:03 -04:00
Anuken
23d0dfe6bf Deprecated DoubleOverlayFloor 2021-09-04 16:29:14 -04:00
Anuken
0a5b1d1380 Merge remote-tracking branch 'origin/master' 2021-09-04 15:23:53 -04:00
Anuken
24b0f445b8 Added rivers on Serpulo / Added deep tainted water 2021-09-04 15:23:47 -04:00
Volas171
57cd20e2a1 update mindustry reborn v7 (#5933)
* update mindustry reborn ip

* i forgo-
2021-09-04 12:49:11 -04:00
Anuken
3f49807348 Merge branch 'master' of https://github.com/Anuken/Mindustry 2021-09-04 11:27:29 -04:00
Anuken
13ddca750a arc 2021-09-04 11:27:26 -04:00
buthed010203
c209b0bdaf add statustable name to hudfragment (#5904) 2021-09-04 11:05:06 -04:00
Matthew Peng
264052a95f Remove the slight delay in wind3.ogg (#5909)
* Remove the slight delay in `wind3.ogg`

* Don't need to export the quality that high
2021-09-04 10:26:42 -04:00
Matthew Peng
b004146015 Input liquid drawing for DrawLiquid and DrawMixer (#5906) 2021-09-04 10:18:44 -04:00
CancerGuy
3901ae1720 change (#5923) 2021-09-04 10:14:40 -04:00
RebornTrack970
bcf798c247 Moved All OmegaHub servers from all Nodes to N5 (#5917)
* Moved All OmegaHub servers from all Nodes to N5

* Update servers_v7.json

* v6 life matters!

* Update servers_v6.json

* Update servers_v7.json

Co-authored-by: Volas171 <60143910+Volas171@users.noreply.github.com>
2021-09-04 10:14:16 -04:00
buthed010203
2dffd525a3 remove useless method call (#5912)
sector.hasBase() already checks that save != null
2021-09-04 10:14:04 -04:00
QmelZ
d31389efca remove space (#5929) 2021-09-04 10:12:13 -04:00
Anuken
ee8683c734 Do not display overdrive visual for router/conduit 2021-09-04 10:07:13 -04:00
Anuken
8224cc3fce Fixed #5922 2021-09-04 10:03:40 -04:00
Anuken
94a340d3ee Merge remote-tracking branch 'origin/master' 2021-09-04 09:59:32 -04:00
Anuken
f8048be429 Fixed #5918 2021-09-04 09:59:28 -04:00
Кирилл Алдашкин
3714077fbe Fixed the display of the oil extractor efficiency (#5915) 2021-09-04 09:58:38 -04:00
Anuken
6984be2172 Merge remote-tracking branch 'origin/master' 2021-09-04 09:55:28 -04:00
Anuken
48f359ca9b Fixed #5907 2021-09-04 09:55:23 -04:00
Matthew Peng
9b28eaa3b3 Allow for SingleTypeGenerators to use only liquid. (#5900) 2021-08-30 08:23:58 -04:00
Matthew Peng
2f47f13ef7 Adjustable generateEffect randomness (#5901) 2021-08-29 22:55:52 -04:00
Anuken
80acea4708 #5897 with proper formatting 2021-08-29 16:25:26 -04:00
Anuken
cc689fd114 Fixed #5895 2021-08-29 10:26:39 -04:00
Anuken
be5d9154a7 Merge remote-tracking branch 'origin/master' 2021-08-29 09:12:08 -04:00
Anuken
bb9d7fedf7 Fixed #5894 2021-08-29 09:12:03 -04:00
Matthew Peng
71f064bda1 Shouldn't shorten() also reset the counter? (#5890) 2021-08-29 08:28:38 -04:00
Anuken
e30d7e998d Allow unit icons for sectors 2021-08-28 20:49:39 -04:00
Anuken
a3270dd908 this turned out to be pretty difficult 2021-08-28 16:29:58 -04:00
Anuken
48d568978b Merge remote-tracking branch 'origin/master'
# Conflicts:
#	core/src/mindustry/entities/Damage.java
2021-08-28 14:17:29 -04:00
Anuken
9a7324ce54 Fixed #5887 2021-08-28 14:17:01 -04:00
Darkness6030
d254d971a9 Add unitSpawnEvent (#5876) 2021-08-28 10:53:19 -04:00
SMOLKEYS.exe
800f0f4511 inconspicuous OCD goes to brazil (#5884) 2021-08-28 09:13:57 -04:00
Matthew Peng
60b2842d82 Rotator spinSpeed (#5881) 2021-08-28 08:47:11 -04:00
Matthew Peng
f8c7ff0159 Damage.damage doesn't properly convert cores (#5882)
* `Damage.damage` doesn't properly convert cores

* Well that was a complete failure
2021-08-28 08:46:08 -04:00
Anuken
4d62b0321f Fixed #5885 2021-08-28 08:44:42 -04:00
Anuken
6ca2855365 Fixed RailBulletType effect length 2021-08-27 22:33:56 -04:00
Anuken
ced97888e4 why 2021-08-27 21:51:37 -04:00
Zelaux
9f68fe520b Fixed incorrect work of TextureRegion.found() when creating icons (#5879)
* Fixed incorrect work of TextureRegion.found() when creating icons

* fixed comment text

* fixed comment text
2021-08-27 11:08:04 -04:00
Anuken
8c32acbc30 Fixed #5878 2021-08-27 09:58:08 -04:00
Anuken
bfc9b07651 Redundant cast cleanup 2021-08-27 09:31:18 -04:00
Anuken
e53b578043 Merge remote-tracking branch 'origin/master' 2021-08-27 09:17:31 -04:00
Anuken
b2ed066faa Fixed BE server not updating 2021-08-27 09:17:26 -04:00
Matthew Peng
5cc461edb0 Make hiding details optional (#5871)
* Make hiding details optional

* Sandbox blocks shouldn't have their details hidden.
2021-08-26 20:47:35 -04:00
Anuken
9b22777dfb AGP 7.0.1 2021-08-26 15:15:29 -04:00
Anuken
3bd08bb047 Merge remote-tracking branch 'origin/master' 2021-08-26 15:07:13 -04:00
Anuken
139d6cd5cc Proper #5872 2021-08-26 15:07:08 -04:00
RebornTrack970
309b0adb9e Added Rush and Expansion to Omega Hub (#5868) 2021-08-26 08:33:10 -04:00
Anuken
c25e6b586b Allow empty maps in FileMapGenerator 2021-08-25 21:57:18 -04:00
Anuken
f46b22e4a7 Merge remote-tracking branch 'origin/master' 2021-08-25 13:22:23 -04:00
Anuken
2b6856634c Fixed #5864 2021-08-25 13:22:19 -04:00
Ilya246
20305b5d36 Fix .pl BE server (#5862)
The server is currently up and running BE
2021-08-25 13:06:19 -04:00
Anuken
9e16d7385a Implemented #5853 2021-08-25 10:09:00 -04:00
Anuken
c573fd34a1 Bullet raycast clamp 2021-08-25 09:10:59 -04:00
Anuken
da7873cbd8 #5855 2021-08-25 08:49:41 -04:00
Anuken
a15f8131fa Merge remote-tracking branch 'origin/master' 2021-08-24 19:14:44 -04:00
Anuken
0d27e3afdc Fixed #5856 2021-08-24 19:14:40 -04:00
Leonid Skorospelov
bdcae408e6 Added 2v2, 3v3 ranked gamemode servers to v6 (#5854) 2021-08-24 17:45:14 -04:00
Anuken
bc4783e9cd Implemented #5851 properly 2021-08-24 12:45:28 -04:00
Anuken
8143cb7be0 Unit balancing 2021-08-24 12:10:44 -04:00
Anuken
8e90527609 Chat prefix empty message fix / Call.sound volume limit increase 2021-08-24 10:19:46 -04:00
Anuken
8949fd279e Build error fix / Anuken/Mindustry-Suggestions/issues/2897 2021-08-24 09:28:51 -04:00
Anuken
901d594768 Prevent server sound ear destruction / Particle effect rand param 2021-08-23 20:27:01 -04:00
Anuken
3964c8e826 Merge remote-tracking branch 'origin/master' 2021-08-23 17:41:02 -04:00
Anuken
044a124bc7 Fixed #5847 2021-08-23 17:40:58 -04:00
VizardAlpha
4f22db8db5 Updates bundle_fr.properties (#5663)
* Updates bundle_fr.properties

Final core launch animation / Added option to skip core animations

* Translation end

* Proper name/impl for "borderless windowed" on Windows

* Mod import progress bar

* WIP team icons

* Improved environmental block internal names

* Update core/assets/bundles/bundle_fr.properties

Co-authored-by: Lucien Perregaux <57545107+Luhrel@users.noreply.github.com>

* payload source and void descriptions

* Game stats cleanup

* Added max units field for wave editor

* Added max units

Co-authored-by: Lucien Perregaux <57545107+Luhrel@users.noreply.github.com>
Co-authored-by: Anuken <arnukren@gmail.com>
2021-08-23 16:58:31 -04:00
Anuken
80ef3cee34 Suppress gen deprecatio warning / Anuken/Mindustry-Suggestions/issues/2888 2021-08-23 15:33:28 -04:00
Anuken
254284760f Hid details of locked content 2021-08-23 15:20:56 -04:00
137 changed files with 1868 additions and 1241 deletions

View File

@@ -7,8 +7,7 @@ buildscript{
} }
dependencies{ dependencies{
//note that later versions, like alpha05, fail to work correctly classpath 'com.android.tools.build:gradle:7.0.1'
classpath 'com.android.tools.build:gradle:7.1.0-alpha02'
} }
} }

View File

@@ -101,6 +101,8 @@ public class EntityProcess extends BaseProcessor{
inter.addJavadoc("Interface for {@link $L}", component.fullName()); inter.addJavadoc("Interface for {@link $L}", component.fullName());
skipDeprecated(inter);
//implement extra interfaces these components may have, e.g. position //implement extra interfaces these components may have, e.g. position
for(Stype extraInterface : component.interfaces().select(i -> !isCompInterface(i))){ for(Stype extraInterface : component.interfaces().select(i -> !isCompInterface(i))){
//javapoet completely chokes on this if I add `addSuperInterface` or create the type name with TypeName.get //javapoet completely chokes on this if I add `addSuperInterface` or create the type name with TypeName.get
@@ -570,6 +572,8 @@ public class EntityProcess extends BaseProcessor{
.returns(tname(packageName + "." + name)) .returns(tname(packageName + "." + name))
.addStatement(ann.pooled() ? "return Pools.obtain($L.class, " +name +"::new)" : "return new $L()", name).build()); .addStatement(ann.pooled() ? "return Pools.obtain($L.class, " +name +"::new)" : "return new $L()", name).build());
skipDeprecated(builder);
definitions.add(new EntityDefinition(packageName + "." + name, builder, type, typeIsBase ? null : baseClass, components, groups, allFieldSpecs, legacy)); definitions.add(new EntityDefinition(packageName + "." + name, builder, type, typeIsBase ? null : baseClass, components, groups, allFieldSpecs, legacy));
} }
@@ -837,6 +841,8 @@ public class EntityProcess extends BaseProcessor{
TypeSpec.Builder nullBuilder = TypeSpec.classBuilder(className) TypeSpec.Builder nullBuilder = TypeSpec.classBuilder(className)
.addModifiers(Modifier.FINAL); .addModifiers(Modifier.FINAL);
skipDeprecated(nullBuilder);
nullBuilder.addSuperinterface(interf.tname()); nullBuilder.addSuperinterface(interf.tname());
if(superclass != null) nullBuilder.superclass(tname(baseName(superclass))); if(superclass != null) nullBuilder.superclass(tname(baseName(superclass)));
@@ -980,6 +986,11 @@ public class EntityProcess extends BaseProcessor{
throw new IllegalArgumentException("Missing types."); throw new IllegalArgumentException("Missing types.");
} }
void skipDeprecated(TypeSpec.Builder builder){
//deprecations are irrelevant in generated code
builder.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"deprecation\"").build());
}
class GroupDefinition{ class GroupDefinition{
final String name; final String name;
final ClassName baseType; final ClassName baseType;

View File

@@ -41,8 +41,8 @@ buildscript{
} }
plugins{ plugins{
id 'org.jetbrains.kotlin.jvm' version '1.4.32' id 'org.jetbrains.kotlin.jvm' version '1.5.21'
id "org.jetbrains.kotlin.kapt" version "1.4.32" id "org.jetbrains.kotlin.kapt" version "1.5.21"
} }
allprojects{ allprojects{
@@ -219,10 +219,16 @@ allprojects{
options.compilerArgs += ["-Xlint:deprecation"] options.compilerArgs += ["-Xlint:deprecation"]
dependsOn clearCache dependsOn clearCache
options.forkOptions.jvmArgs.addAll([ options.forkOptions.jvmArgs += [
'--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED', '--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED' '--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED',
]) '--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED',
'--add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED'
]
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 B

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

View File

@@ -169,6 +169,7 @@ launchcore = Launch Core
filename = File Name: filename = File Name:
unlocked = New content unlocked! unlocked = New content unlocked!
available = New research available! available = New research available!
unlock.incampaign = < Unlock in campaign for details >
completed = [accent]Completed completed = [accent]Completed
techtree = Tech Tree techtree = Tech Tree
research.legacy = [accent]5.0[] research data found.\nDo you want to [accent]load this data[], or [accent]discard it[] and restart research in the new campaign (recommended)? research.legacy = [accent]5.0[] research data found.\nDo you want to [accent]load this data[], or [accent]discard it[] and restart research in the new campaign (recommended)?
@@ -362,6 +363,7 @@ publish.confirm = Are you sure you want to publish this?\n\n[lightgray]Make sure
publish.error = Error publishing item: {0} publish.error = Error publishing item: {0}
steam.error = Failed to initialize Steam services.\nError: {0} steam.error = Failed to initialize Steam services.\nError: {0}
editor.cliffs = Walls To Cliffs
editor.brush = Brush editor.brush = Brush
editor.openin = Open In Editor editor.openin = Open In Editor
editor.oregen = Ore Generation editor.oregen = Ore Generation
@@ -394,6 +396,13 @@ waves.load = Load from Clipboard
waves.invalid = Invalid waves in clipboard. waves.invalid = Invalid waves in clipboard.
waves.copied = Waves copied. waves.copied = Waves copied.
waves.none = No enemies defined.\nNote that empty wave layouts will automatically be replaced with the default layout. waves.none = No enemies defined.\nNote that empty wave layouts will automatically be replaced with the default layout.
waves.sort = Sort By
waves.sort.reverse = Reverse Sort
waves.sort.begin = Begin
waves.sort.health = Health
waves.sort.type = Type
waves.units.hide = Hide All
waves.units.show = Show All
#these are intentionally in lower case #these are intentionally in lower case
wavemode.counts = counts wavemode.counts = counts
@@ -622,6 +631,8 @@ sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost sector.extractionOutpost.name = Extraction Outpost
sector.planetaryTerminal.name = Planetary Launch Terminal sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
sector.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on. sector.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on.
sector.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders. sector.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders.
@@ -649,6 +660,7 @@ status.sapped.name = Sapped
status.electrified.name = Electrified status.electrified.name = Electrified
status.spore-slowed.name = Spore Slowed status.spore-slowed.name = Spore Slowed
status.tarred.name = Tarred status.tarred.name = Tarred
status.overdrive.name = Overdrive
status.overclock.name = Overclock status.overclock.name = Overclock
status.shocked.name = Shocked status.shocked.name = Shocked
status.blasted.name = Blasted status.blasted.name = Blasted
@@ -1151,6 +1163,7 @@ block.core-nucleus.name = Core: Nucleus
block.deep-water.name = Deep Water block.deep-water.name = Deep Water
block.shallow-water.name = Water block.shallow-water.name = Water
block.tainted-water.name = Tainted Water block.tainted-water.name = Tainted Water
block.deep-tainted-water.name = Deep Tainted Water
block.darksand-tainted-water.name = Dark Sand Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water
block.tar.name = Tar block.tar.name = Tar
block.stone.name = Stone block.stone.name = Stone
@@ -1384,6 +1397,7 @@ hint.generator = \uf879 [accent]Combustion Generators[] burn coal and transmit p
hint.guardian = [accent]Guardian[] units are armored. Weak ammo such as [accent]Copper[] and [accent]Lead[] is [scarlet]not effective[].\n\nUse higher tier turrets or \uf835 [accent]Graphite[] \uf861Duo/\uf859Salvo ammunition to take Guardians down. hint.guardian = [accent]Guardian[] units are armored. Weak ammo such as [accent]Copper[] and [accent]Lead[] is [scarlet]not effective[].\n\nUse higher tier turrets or \uf835 [accent]Graphite[] \uf861Duo/\uf859Salvo ammunition to take Guardians down.
hint.coreUpgrade = Cores can be upgraded by [accent]placing higher-tier cores over them[].\n\nPlace a  [accent]Foundation[] core over the  [accent]Shard[] core. Make sure it is free from nearby obstructions. hint.coreUpgrade = Cores can be upgraded by [accent]placing higher-tier cores over them[].\n\nPlace a  [accent]Foundation[] core over the  [accent]Shard[] core. Make sure it is free from nearby obstructions.
hint.presetLaunch = Gray [accent]landing zone sectors[], such as [accent]Frozen Forest[], can be launched to from anywhere. They do not require capture of nearby territory.\n\n[accent]Numbered sectors[], such as this one, are [accent]optional[]. hint.presetLaunch = Gray [accent]landing zone sectors[], such as [accent]Frozen Forest[], can be launched to from anywhere. They do not require capture of nearby territory.\n\n[accent]Numbered sectors[], such as this one, are [accent]optional[].
hint.presetDifficulty = This sector has a [scarlet]high enemy threat level[].\nLaunching to such sectors is [accent]not recommended[] without proper technology and preparation.
hint.coreIncinerate = After the core is filled to capacity with an item, any extra items of that type it receives will be [accent]incinerated[]. hint.coreIncinerate = After the core is filled to capacity with an item, any extra items of that type it receives will be [accent]incinerated[].
hint.coopCampaign = When playing the [accent]co-op campaign[], items that are produced in the current map will also be sent [accent]to your local sectors[].\n\nAny new research done by the host also carries over. hint.coopCampaign = When playing the [accent]co-op campaign[], items that are produced in the current map will also be sent [accent]to your local sectors[].\n\nAny new research done by the host also carries over.

View File

@@ -78,13 +78,12 @@ schematic.tagexists = Ce mot-clé existe déjà.
stats = Statistiques stats = Statistiques
stat.wave = Vagues vaincues : [accent] {0} stat.wave = Vagues vaincues : [accent] {0}
stat.unitsCreated = Unités créées :[accent] {0}
stat.enemiesDestroyed = Ennemis détruits : [accent] {0} stat.enemiesDestroyed = Ennemis détruits : [accent] {0}
stat.built = Bâtiments construits : [accent] {0} stat.built = Bâtiments construits : [accent] {0}
stat.destroyed = Bâtiments détruits : [accent] {0} stat.destroyed = Bâtiments détruits : [accent] {0}
stat.deconstructed = Bâtiments déconstruits : [accent] {0} stat.deconstructed = Bâtiments déconstruits : [accent] {0}
stat.delivered = Ressources transférées :
stat.playtime = Temps de jeu : [accent] {0} stat.playtime = Temps de jeu : [accent] {0}
stat.rank = Rang Final : [accent]{0}
globalitems = [accent]Ressources globales globalitems = [accent]Ressources globales
map.delete = Êtes-vous sûr de vouloir supprimer cette carte ?"[accent]{0}[]" ? map.delete = Êtes-vous sûr de vouloir supprimer cette carte ?"[accent]{0}[]" ?
@@ -94,6 +93,7 @@ level.mode = Mode de jeu :
coreattack = [scarlet]< Le Noyau est attaqué ! > coreattack = [scarlet]< Le Noyau est attaqué ! >
nearpoint = [[ [scarlet]QUITTEZ LE POINT D'APPARITION ENNEMI IMMÉDIATEMENT[] ]\nannihilation imminente nearpoint = [[ [scarlet]QUITTEZ LE POINT D'APPARITION ENNEMI IMMÉDIATEMENT[] ]\nannihilation imminente
database = Base de données database = Base de données
database.button = Base de données
savegame = Sauvegarder la partie savegame = Sauvegarder la partie
loadgame = Charger une partie loadgame = Charger une partie
joingame = Rejoindre une partie joingame = Rejoindre une partie
@@ -169,6 +169,7 @@ launchcore = Lancer le Noyau
filename = Nom du fichier : filename = Nom du fichier :
unlocked = Nouveau contenu débloqué ! unlocked = Nouveau contenu débloqué !
available = Nouvelle recherche disponible ! available = Nouvelle recherche disponible !
unlock.incampaign = < Débloquer dans la campagne pour plus de détails >
completed = [accent]Complété completed = [accent]Complété
techtree = Arbre technologique techtree = Arbre technologique
research.legacy = Des données de recherche de la [accent]5.0[] ont été trouvées.\nVoulez-vous [accent]charger ces données[] ou [accent]les ignorer[] et recommencer la recherche dans la nouvelle campagne ? (recommandé) research.legacy = Des données de recherche de la [accent]5.0[] ont été trouvées.\nVoulez-vous [accent]charger ces données[] ou [accent]les ignorer[] et recommencer la recherche dans la nouvelle campagne ? (recommandé)
@@ -215,7 +216,7 @@ hosts.none = [lightgray]Aucune partie en LAN trouvée !
host.invalid = [scarlet]Impossible de se connecter à l'hôte. host.invalid = [scarlet]Impossible de se connecter à l'hôte.
servers.local = Serveurs locaux servers.local = Serveurs locaux
servers.local.steam = Open Games & Serveurs Locaux servers.local.steam = Jeux Libres & Serveurs Locaux
servers.remote = Serveurs distants servers.remote = Serveurs distants
servers.global = Serveurs communautaires servers.global = Serveurs communautaires
@@ -317,7 +318,7 @@ data.invalid = Ce ne sont pas des données de jeu valides.
data.import.confirm = L'importation des données externes va effacer[scarlet] toutes[] vos données de jeu actuelles.\n[accent]Ceci ne pourra pas être annulé ![]\n\nUne fois les données importées, le jeu se fermera immédiatement. data.import.confirm = L'importation des données externes va effacer[scarlet] toutes[] vos données de jeu actuelles.\n[accent]Ceci ne pourra pas être annulé ![]\n\nUne fois les données importées, le jeu se fermera immédiatement.
quit.confirm = Êtes-vous sûr de vouloir quitter ? quit.confirm = Êtes-vous sûr de vouloir quitter ?
loading = [accent]Chargement... loading = [accent]Chargement...
reloading = [accent]Rechargement des Mods... downloading = [accent]Téléchargement...
saving = [accent]Sauvegarde... saving = [accent]Sauvegarde...
respawn = [accent][[{0}][] pour réapparaître dans le Noyau respawn = [accent][[{0}][] pour réapparaître dans le Noyau
cancelbuilding = [accent][[{0}][] pour effacer le plan cancelbuilding = [accent][[{0}][] pour effacer le plan
@@ -385,6 +386,7 @@ waves.waves = vague(s)
waves.perspawn = par apparition waves.perspawn = par apparition
waves.shields = boucliers/vague waves.shields = boucliers/vague
waves.to = à waves.to = à
waves.max = Unités maximum
waves.guardian = Gardien waves.guardian = Gardien
waves.preview = Prévisualiser waves.preview = Prévisualiser
waves.edit = Modifier... waves.edit = Modifier...
@@ -393,6 +395,13 @@ waves.load = Coller depuis le presse-papiers
waves.invalid = Vagues invalides dans le presse-papiers. waves.invalid = Vagues invalides dans le presse-papiers.
waves.copied = Vagues copiées waves.copied = Vagues copiées
waves.none = Aucun ennemi défini.\nNotez que les vagues vides seront automatiquement remplacées par une vague générée par défaut. waves.none = Aucun ennemi défini.\nNotez que les vagues vides seront automatiquement remplacées par une vague générée par défaut.
waves.sort = Trier Par
waves.sort.reverse = Tri inversé
waves.sort.begin = Commence par
waves.sort.health = Santé
waves.sort.type = Type
waves.units.hide = Tout masquer
waves.units.show = Tout afficher
#these are intentionally in lower case #these are intentionally in lower case
wavemode.counts = compte wavemode.counts = compte
@@ -539,6 +548,7 @@ configure = Modifier le chargement
loadout = Chargement loadout = Chargement
resources = Ressources resources = Ressources
bannedblocks = Blocs bannis bannedblocks = Blocs bannis
bannedunits = Unités bannies
addall = Ajouter TOUT addall = Ajouter TOUT
launch.from = Décollage depuis : [accent]{0} launch.from = Décollage depuis : [accent]{0}
launch.destination = Destination: {0} launch.destination = Destination: {0}
@@ -617,6 +627,8 @@ sector.biomassFacility.name = Biomass Synthesis Facility
sector.windsweptIslands.name = Windswept Islands sector.windsweptIslands.name = Windswept Islands
sector.extractionOutpost.name = Extraction Outpost sector.extractionOutpost.name = Extraction Outpost
sector.planetaryTerminal.name = Planetary Launch Terminal sector.planetaryTerminal.name = Planetary Launch Terminal
sector.coastline.name = Coastline
sector.navalFortress.name = Naval Fortress
sector.groundZero.description = Un endroit optimal pour commencer. Avec une menace ennemie faible et le peu de ressources disponibles, rassemblez autant de cuivre et de plomb que possible pour continuer votre exploration. sector.groundZero.description = Un endroit optimal pour commencer. Avec une menace ennemie faible et le peu de ressources disponibles, rassemblez autant de cuivre et de plomb que possible pour continuer votre exploration.
sector.frozenForest.description = Même ici, près des montagnes, les spores se sont propagées. Les températures glaciales ne pourront pas les contenir indéfiniment.\n\nCommencez votre production d'énergie en construisant des générateurs à combustion et apprenez à utiliser les bâtiments de soin. sector.frozenForest.description = Même ici, près des montagnes, les spores se sont propagées. Les températures glaciales ne pourront pas les contenir indéfiniment.\n\nCommencez votre production d'énergie en construisant des générateurs à combustion et apprenez à utiliser les bâtiments de soin.
@@ -645,10 +657,12 @@ status.sapped.name = Sapé
status.electrified.name = Electrifié status.electrified.name = Electrifié
status.spore-slowed.name = Spore ralentie status.spore-slowed.name = Spore ralentie
status.tarred.name = Goudronné status.tarred.name = Goudronné
status.overdrive.name = Surmultiplié
status.overclock.name = Surcadençage status.overclock.name = Surcadençage
status.shocked.name = Étourdie status.shocked.name = Étourdie
status.blasted.name = Foudroyé status.blasted.name = Foudroyé
status.unmoving.name = Immobilisé status.unmoving.name = Immobilisé
status.boss.name = Gardien
settings.language = Langage settings.language = Langage
settings.data = Données du Jeu settings.data = Données du Jeu
@@ -838,6 +852,7 @@ category.crafting = Fabrication
category.function = Fonction category.function = Fonction
category.optional = Améliorations facultatives category.optional = Améliorations facultatives
setting.skipcoreanimation.name = Ignorer l'animation du lancement du noyau et de l'atterrissage
setting.landscape.name = Verrouiller la rotation en mode paysage setting.landscape.name = Verrouiller la rotation en mode paysage
setting.shadows.name = Ombres setting.shadows.name = Ombres
setting.blockreplace.name = Suggestion automatique des Blocs setting.blockreplace.name = Suggestion automatique des Blocs
@@ -878,6 +893,7 @@ setting.seconds = {0} secondes
setting.milliseconds = {0} millisecondes setting.milliseconds = {0} millisecondes
setting.fullscreen.name = Plein Écran setting.fullscreen.name = Plein Écran
setting.borderlesswindow.name = Fenêtré sans bordures setting.borderlesswindow.name = Fenêtré sans bordures
setting.borderlesswindow.name.windows = Plein écran sans bordure
setting.borderlesswindow.description = Un redémarrage peut être nécessaire pour appliquer les changements. setting.borderlesswindow.description = Un redémarrage peut être nécessaire pour appliquer les changements.
setting.fps.name = Afficher FPS et Ping setting.fps.name = Afficher FPS et Ping
setting.smoothcamera.name = Lissage de la Caméra setting.smoothcamera.name = Lissage de la Caméra
@@ -1111,7 +1127,6 @@ unit.reign.name = Éradicateur
unit.vela.name = Vela unit.vela.name = Vela
unit.corvus.name = Corvus unit.corvus.name = Corvus
block.resupply-point.name = Point de Rechargement
block.parallax.name = Parallax block.parallax.name = Parallax
block.cliff.name = Falaise block.cliff.name = Falaise
block.sand-boulder.name = Bloc de Sable block.sand-boulder.name = Bloc de Sable
@@ -1148,9 +1163,10 @@ block.spawn.name = Point d'Apparition Ennemi
block.core-shard.name = Noyau: Fragment block.core-shard.name = Noyau: Fragment
block.core-foundation.name = Noyau: Fondation block.core-foundation.name = Noyau: Fondation
block.core-nucleus.name = Noyau: Épicentre block.core-nucleus.name = Noyau: Épicentre
block.deep-water.name = Eau profonde block.deep-water.name = Eau Profonde
block.shallow-water.name = Eau block.shallow-water.name = Eau
block.tainted-water.name = Eau Contaminée block.tainted-water.name = Eau Contaminée
block.deep-tainted-water.name = Eau Profonde Contaminée
block.darksand-tainted-water.name = Eau Contaminée avec fond de Sable sombre block.darksand-tainted-water.name = Eau Contaminée avec fond de Sable sombre
block.tar.name = Goudron block.tar.name = Goudron
block.stone.name = Roche block.stone.name = Roche
@@ -1384,6 +1400,7 @@ hint.generator = \uf879 Les [accent]Générateurs à combustion[] brûlent du Ch
hint.guardian = Les [accent]Gardiens[] sont protégés par un bouclier. Les munitions faibles telles que le [accent]Cuivre[] et le [accent]Plomb[] ne seront [scarlet]pas efficaces[].\n\nUtilisez des tourelles de plus haut niveau, ou de meilleures munitions comme le \uf835 [accent]Graphite[] avec un \uf861Duo/\uf859Salve pour pouvoir tuer le gardien. hint.guardian = Les [accent]Gardiens[] sont protégés par un bouclier. Les munitions faibles telles que le [accent]Cuivre[] et le [accent]Plomb[] ne seront [scarlet]pas efficaces[].\n\nUtilisez des tourelles de plus haut niveau, ou de meilleures munitions comme le \uf835 [accent]Graphite[] avec un \uf861Duo/\uf859Salve pour pouvoir tuer le gardien.
hint.coreUpgrade = Les Noyaux peuvent être améliorés [accent]en plaçant un Noyau de plus haut niveau sur eux[].\n\nPlacez un  Noyau [accent]Fondation[] sur le  Noyau [accent]Fragment[]. Soyez sûrs que rien n'obstrue la construction. hint.coreUpgrade = Les Noyaux peuvent être améliorés [accent]en plaçant un Noyau de plus haut niveau sur eux[].\n\nPlacez un  Noyau [accent]Fondation[] sur le  Noyau [accent]Fragment[]. Soyez sûrs que rien n'obstrue la construction.
hint.presetLaunch = Les [accent]secteurs[] gris, tels que [accent]Frozen Forest[], peuvent être lançés de n'importe où. Ils ne requièrent pas la capture d'un secteur adjacent.\n\n[accent]Il y a beaucoup de secteurs[] comme celui-ci, qui sont [accent]optionels[]. hint.presetLaunch = Les [accent]secteurs[] gris, tels que [accent]Frozen Forest[], peuvent être lançés de n'importe où. Ils ne requièrent pas la capture d'un secteur adjacent.\n\n[accent]Il y a beaucoup de secteurs[] comme celui-ci, qui sont [accent]optionels[].
hint.presetDifficulty = Ce secteur a un niveau de menace ennemi [scarlet]élevé[].\nIl n'est [accent]pas recommandé[] de se lancer dans de tels secteurs sans la technologie et la préparation appropriées.
hint.coreIncinerate = Lorsqu'un Noyau est rempli d'une ressource en particulier, le surplus qui rentrera dans celui-ci sera [accent]incinéré[]. hint.coreIncinerate = Lorsqu'un Noyau est rempli d'une ressource en particulier, le surplus qui rentrera dans celui-ci sera [accent]incinéré[].
hint.coopCampaign = Quand vous jouez en [accent]campagne multijoueur[], les ressources produites dans le secteur dans lequel vous jouez sera aussi envoyé [accent]dans vos secteurs[].\n\nLes recherches faites par l'hôte sont aussi partagées. hint.coopCampaign = Quand vous jouez en [accent]campagne multijoueur[], les ressources produites dans le secteur dans lequel vous jouez sera aussi envoyé [accent]dans vos secteurs[].\n\nLes recherches faites par l'hôte sont aussi partagées.
@@ -1414,8 +1431,7 @@ liquid.slag.description = Différents types de métaux en fusion mélangés. Peu
liquid.oil.description = Un liquide utilisé dans la production de matériaux avancés. Peut être transformé en charbon ou pulvérisé sur les ennemis, puis enflammé. liquid.oil.description = Un liquide utilisé dans la production de matériaux avancés. Peut être transformé en charbon ou pulvérisé sur les ennemis, puis enflammé.
liquid.cryofluid.description = Un liquide inerte, non corrosif, créé à partir deau et de titane. Possède une capacité d'absorption de chaleur extrêmement élevée. Largement utilisé comme liquide de refroidissement. liquid.cryofluid.description = Un liquide inerte, non corrosif, créé à partir deau et de titane. Possède une capacité d'absorption de chaleur extrêmement élevée. Largement utilisé comme liquide de refroidissement.
block.derelict = [lightgray]Vestiges block.derelict = [lightgray]Vestiges
block.resupply-point.description = Approvisionne les unités proches en munitions. Pas compatible avec celles qui ont besoin d'énergie pour tirer.
block.illuminator.description = Une petite source lumineuse compacte et configurable. Nécessite de l'énergie pour fonctionner. block.illuminator.description = Une petite source lumineuse compacte et configurable. Nécessite de l'énergie pour fonctionner.
block.armored-conveyor.description = Déplace les objets à la même vitesse que les convoyeurs en titane, mais est plus résistant. Seulement d'autres convoyeurs peuvent faire entrer des ressources par ses côtés. block.armored-conveyor.description = Déplace les objets à la même vitesse que les convoyeurs en titane, mais est plus résistant. Seulement d'autres convoyeurs peuvent faire entrer des ressources par ses côtés.
block.message.description = Enregistre un message. Utilisé pour la communication entre alliés. Le message contenu peut être modifié par un processeur logique. block.message.description = Enregistre un message. Utilisé pour la communication entre alliés. Le message contenu peut être modifié par un processeur logique.
@@ -1441,6 +1457,8 @@ block.item-source.description = Produit des objets à l'infini. Bac à sable uni
block.item-void.description = Désintègre n'importe quel objet qui va à l'intérieur. Bac à sable uniquement. block.item-void.description = Désintègre n'importe quel objet qui va à l'intérieur. Bac à sable uniquement.
block.liquid-source.description = Source de liquide infinie. Bac à sable uniquement. block.liquid-source.description = Source de liquide infinie. Bac à sable uniquement.
block.liquid-void.description = Détruit n'importe quel liquide. Bac à sable uniquement. block.liquid-void.description = Détruit n'importe quel liquide. Bac à sable uniquement.
block.payload-source.description = Produit des charges utiles à l'infini. Bac à sable uniquement.
block.payload-void.description = Détruit toutes les charges utiles. Bac à sable uniquement.
block.copper-wall.description = Un bloc défensif à faible coût.\nUtile pour protéger la base et les tourelles lors des premières vagues. block.copper-wall.description = Un bloc défensif à faible coût.\nUtile pour protéger la base et les tourelles lors des premières vagues.
block.copper-wall-large.description = Un bloc défensif à faible coût.\nUtile pour protéger la base et les tourelles lors des premières vagues. block.copper-wall-large.description = Un bloc défensif à faible coût.\nUtile pour protéger la base et les tourelles lors des premières vagues.
block.titanium-wall.description = Un bloc défensif standard.\nProcure une protection modérée contre les attaques ennemies. block.titanium-wall.description = Un bloc défensif standard.\nProcure une protection modérée contre les attaques ennemies.

View File

@@ -93,6 +93,7 @@ level.mode = 게임 모드:
coreattack = < 코어가 공격을 받고 있습니다! > coreattack = < 코어가 공격을 받고 있습니다! >
nearpoint = [[ [scarlet]즉시 적 소환구역에서 떠나십시오[] ]\n단계가 시작하는 순간 인근 건물들과 유닛들이 파괴됩니다! nearpoint = [[ [scarlet]즉시 적 소환구역에서 떠나십시오[] ]\n단계가 시작하는 순간 인근 건물들과 유닛들이 파괴됩니다!
database = 코어 데이터베이스 database = 코어 데이터베이스
database.button = 데이터베이스
savegame = 게임 저장 savegame = 게임 저장
loadgame = 게임 불러오기 loadgame = 게임 불러오기
joingame = 게임 참여 joingame = 게임 참여
@@ -168,6 +169,7 @@ launchcore = 코어 출격
filename = 파일 이름: filename = 파일 이름:
unlocked = 새로운 콘텐츠가 해금되었습니다! unlocked = 새로운 콘텐츠가 해금되었습니다!
available = 새로운 콘텐츠 해금이 가능합니다! available = 새로운 콘텐츠 해금이 가능합니다!
unlock.incampaign = < 해금 후 상세정보 열람이 가능합니다 >
completed = [accent]완료됨 completed = [accent]완료됨
techtree = 연구 기록 techtree = 연구 기록
research.legacy = [accent]5.0[] 연구 데이터를 찾았습니다.\n[accent]이 데이터를 불러오시겠습니까?[], 아니면 이 데이터를 무시하고 캠페인을 새로 시작하시겠습니까? [accent]무시한 데이터는 삭제됩니다.[] (권장됨) research.legacy = [accent]5.0[] 연구 데이터를 찾았습니다.\n[accent]이 데이터를 불러오시겠습니까?[], 아니면 이 데이터를 무시하고 캠페인을 새로 시작하시겠습니까? [accent]무시한 데이터는 삭제됩니다.[] (권장됨)
@@ -361,6 +363,7 @@ publish.confirm = 이것을 게시하시겠습니까?[lightgray]창작마당 EUL
publish.error = 아이템 게시 오류: {0} publish.error = 아이템 게시 오류: {0}
steam.error = 스팀 서비스를 초기화하지 못했습니다.\n오류: {0} steam.error = 스팀 서비스를 초기화하지 못했습니다.\n오류: {0}
editor.cliffs = 언덕 전환
editor.brush = 브러쉬 editor.brush = 브러쉬
editor.openin = 편집기 열기 editor.openin = 편집기 열기
editor.oregen = 광물 무작위 생성 editor.oregen = 광물 무작위 생성
@@ -381,10 +384,10 @@ waves.title = 단계
waves.remove = 삭제 waves.remove = 삭제
waves.every = waves.every =
waves.waves = 단계마다 waves.waves = 단계마다
waves.perspawn = 마리씩 생성됨 waves.perspawn = 마리씩
waves.shields = 방어막 hp/단계 waves.shields = 방어막만큼 소환
waves.to = 부터 waves.to = 부터
waves.max = 최대 유닛 수 waves.max = 마리 까지
waves.guardian = 수호자 waves.guardian = 수호자
waves.preview = 미리보기 waves.preview = 미리보기
waves.edit = 편집 waves.edit = 편집
@@ -393,6 +396,13 @@ waves.load = 클립보드에서 불러오기
waves.invalid = 클립보드에 잘못된 단계 데이터가 있습니다. waves.invalid = 클립보드에 잘못된 단계 데이터가 있습니다.
waves.copied = 단계 복사됨. waves.copied = 단계 복사됨.
waves.none = 적 단계가 설정되지 않았습니다.\n비어있을 시 자동으로 기본 적 단계 데이터로 설정됩니다. waves.none = 적 단계가 설정되지 않았습니다.\n비어있을 시 자동으로 기본 적 단계 데이터로 설정됩니다.
waves.sort = 보기 정렬
waves.sort.reverse = 정렬 뒤집기
waves.sort.begin = 시작 단계순
waves.sort.health = 체력순
waves.sort.type = 유닛순
waves.units.hide = 모두 숨기기
waves.units.show = 모두 보이기
#these are intentionally in lower case #these are intentionally in lower case
wavemode.counts = 마리 wavemode.counts = 마리
@@ -409,7 +419,7 @@ editor.teams = 팀
editor.errorload = 파일을 불러오지 못했습니다. editor.errorload = 파일을 불러오지 못했습니다.
editor.errorsave = 파일을 저장하지 못했습니다. editor.errorsave = 파일을 저장하지 못했습니다.
editor.errorimage = 이것은 맵이 아니라 사진입니다. editor.errorimage = 이것은 맵이 아니라 사진입니다.
editor.errorlegacy = 이 맵은 너무 오래되어 더 이상 지원지 않는 구형 맵 형식을 사용합니다. editor.errorlegacy = 이 맵은 너무 오래되어 더 이상 지원지 않는 구형 맵 형식을 사용합니다.
editor.errornot = 맵 파일이 아닙니다. editor.errornot = 맵 파일이 아닙니다.
editor.errorheader = 이 맵 파일은 유효하지 않거나 손상되었습니다. editor.errorheader = 이 맵 파일은 유효하지 않거나 손상되었습니다.
editor.errorname = 맵에 이름이 지정되어 있지 않습니다. 저장 파일을 불러오려고 시도하는 건가요? editor.errorname = 맵에 이름이 지정되어 있지 않습니다. 저장 파일을 불러오려고 시도하는 건가요?
@@ -447,7 +457,7 @@ editor.exists = 이 이름의 맵이 이미 존재합니다.
editor.selectmap = 불러올 맵을 선택하세요: editor.selectmap = 불러올 맵을 선택하세요:
toolmode.replace = 재배치 toolmode.replace = 재배치
toolmode.replace.description = 단단한 블록에만 그립니다. toolmode.replace.description = 지형 블록에만 그립니다.
toolmode.replaceall = 모두 재배치 toolmode.replaceall = 모두 재배치
toolmode.replaceall.description = 맵에 있는 모든 블록을 재배치합니다. toolmode.replaceall.description = 맵에 있는 모든 블록을 재배치합니다.
toolmode.orthogonal = 직각 toolmode.orthogonal = 직각
@@ -648,6 +658,7 @@ status.sapped.name = 피로
status.electrified.name = 과전류 status.electrified.name = 과전류
status.spore-slowed.name = 포자감속 status.spore-slowed.name = 포자감속
status.tarred.name = 침유됨 status.tarred.name = 침유됨
status.overdrive.name = 과부하
status.overclock.name = 가속화 status.overclock.name = 가속화
status.shocked.name = 감전 status.shocked.name = 감전
status.blasted.name = 파손 status.blasted.name = 파손
@@ -1150,6 +1161,7 @@ block.core-nucleus.name = 코어: 핵심
block.deep-water.name = 깊은 물 block.deep-water.name = 깊은 물
block.shallow-water.name = block.shallow-water.name =
block.tainted-water.name = 오염된 물 block.tainted-water.name = 오염된 물
block.deep-tainted-water.name = 오염된 깊은 물
block.darksand-tainted-water.name = 오염된 젖은 검은 모래 block.darksand-tainted-water.name = 오염된 젖은 검은 모래
block.tar.name = 타르 block.tar.name = 타르
block.stone.name = 바위 block.stone.name = 바위
@@ -1316,7 +1328,7 @@ block.payload-router.name = 화물 분배기
block.duct.name = 도관 block.duct.name = 도관
block.duct-router.name = 도관 분배기 block.duct-router.name = 도관 분배기
block.duct-bridge.name = 도관 다리 block.duct-bridge.name = 도관 다리
block.payload-propulsion-tower.name = 화물 추진탑 block.payload-propulsion-tower.name = 화물 드라이버
block.payload-void.name = 화물 소멸기 block.payload-void.name = 화물 소멸기
block.payload-source.name = 화물 공급기 block.payload-source.name = 화물 공급기
block.disassembler.name = 광재 분해기 block.disassembler.name = 광재 분해기
@@ -1383,8 +1395,9 @@ hint.generator = \uf879 [accent]화력 발전기[]는 석탄을 태워서 주변
hint.guardian = [accent]수호자[] 유닛들은 방어력을 가집니다. [accent]구리[]와 [accent]납[] 같은 약한 탄약으로는 [scarlet]아무런 효과도 없습니다[].\n\n그런 수호자를 없애려면 높은 단계의 포탑 또는 \uf835 [accent]흑연[]을 탄약으로 넣은 \uf861듀오/\uf859살보를 사용하십시오. hint.guardian = [accent]수호자[] 유닛들은 방어력을 가집니다. [accent]구리[]와 [accent]납[] 같은 약한 탄약으로는 [scarlet]아무런 효과도 없습니다[].\n\n그런 수호자를 없애려면 높은 단계의 포탑 또는 \uf835 [accent]흑연[]을 탄약으로 넣은 \uf861듀오/\uf859살보를 사용하십시오.
hint.coreUpgrade = 코어는 [accent]상위 코어를 위에 설치함[]으로써 업그레이드할 수 있습니다.\n\n [accent]기반[] 코어를 [accent]조각[] 코어 위에 설치하십시오. 주변에 장애물이 없는지도 확인하십시오. hint.coreUpgrade = 코어는 [accent]상위 코어를 위에 설치함[]으로써 업그레이드할 수 있습니다.\n\n [accent]기반[] 코어를 [accent]조각[] 코어 위에 설치하십시오. 주변에 장애물이 없는지도 확인하십시오.
hint.presetLaunch = [accent]얼어붙은 숲[]과 같은 회색[accent]캠페인 지역[]은 어디에서나 출격해서 올 수 있습니다. 주변 지역을 점령하지 않아도 됩니다.\n\n이와 같은 [accent]네임드 지역[]들은 [accent]선택적[]입니다. hint.presetLaunch = [accent]얼어붙은 숲[]과 같은 회색[accent]캠페인 지역[]은 어디에서나 출격해서 올 수 있습니다. 주변 지역을 점령하지 않아도 됩니다.\n\n이와 같은 [accent]네임드 지역[]들은 [accent]선택적[]입니다.
hint.presetDifficulty = 이 지역은 [scarlet]고위험 레벨[] 지역입니다.\n적절한 기술과 준비 없이 이런 지역들로 출격하는건 [accent]비추천[]합니다.
hint.coreIncinerate = 코어가 자원으로 가득 찬 후에 받는 모든 자원들은 [accent]소각[]될 것입니다. hint.coreIncinerate = 코어가 자원으로 가득 찬 후에 받는 모든 자원들은 [accent]소각[]될 것입니다.
hint.coopCampaign = [accent]협동 캠페인[]을 할 때, 현재 맵에서 생산된 자원들은 [accent]캠페인 지역[]으로도 보내집니다.\n\n호스트가 새로 해금한 모든 들도 가져갑니다. hint.coopCampaign = [accent]협동 캠페인[]을 할 때, 현재 맵에서 생산된 자원들은 [accent]캠페인 지역[]으로도 보내집니다.\n\n호스트가 새로 해금한 모든 자원들도 가져갑니다.
item.copper.description = 가장 기본적인 건설 재료. 모든 유형의 블록에서 광범위하게 사용됩니다. item.copper.description = 가장 기본적인 건설 재료. 모든 유형의 블록에서 광범위하게 사용됩니다.
item.copper.details = 평범한 구리. 세르플로에 비정상적으로 많이 분포합니다. 별다른 보강재 없이는 구조적 문제 때문에 내구성이 비교적 약합니다. item.copper.details = 평범한 구리. 세르플로에 비정상적으로 많이 분포합니다. 별다른 보강재 없이는 구조적 문제 때문에 내구성이 비교적 약합니다.
@@ -1560,7 +1573,7 @@ block.logic-display.description = 프로세서를 이용해 그래픽을 출력
block.large-logic-display.description = 프로세서를 이용해 그래픽을 출력할 수 있습니다. block.large-logic-display.description = 프로세서를 이용해 그래픽을 출력할 수 있습니다.
block.interplanetary-accelerator.description = 거대한 전자기 레일건 타워. 코어를 행성 간 이동을 위한 탈출 속도까지 가속합니다. block.interplanetary-accelerator.description = 거대한 전자기 레일건 타워. 코어를 행성 간 이동을 위한 탈출 속도까지 가속합니다.
block.repair-turret.description = 가장 가까운 유닛을 지속적으로 수리합니다. 냉각수를 넣을 수 있습니다. block.repair-turret.description = 가장 가까운 유닛을 지속적으로 수리합니다. 냉각수를 넣을 수 있습니다.
block.payload-propulsion-tower.description = 장거리 화물 운반 구조물. 화물을 연결된 다른 화물 추진탑으로 발사합니다. block.payload-propulsion-tower.description = 장거리 화물 운반 구조물. 화물을 연결된 다른 화물 드라이버로 발사합니다.
unit.dagger.description = 주변 모든 적에게 일반적인 탄환을 발사합니다. unit.dagger.description = 주변 모든 적에게 일반적인 탄환을 발사합니다.
unit.mace.description = 주변 모든 적에게 화염 줄기를 발사합니다. unit.mace.description = 주변 모든 적에게 화염 줄기를 발사합니다.
@@ -1956,10 +1969,10 @@ unit.minke.details =
unit.bryde.details = unit.bryde.details =
unit.sei.details = [lightgray][비공식][]세이 sei! unit.sei.details = [lightgray][비공식][]세이 sei!
unit.omura.details = [lightgray][비공식][]오무라이스? unit.omura.details = [lightgray][비공식][]오무라이스?
unit.retusa.details = [lightgray][비공식][]바다를 지뢰로 뒤덮보죠. unit.retusa.details = [lightgray][비공식][]바다를 지뢰로 뒤덮보죠.
unit.oxynoe.details = unit.oxynoe.details =
unit.cyerce.details = [lightgray][비공식][]폭죽놀이다! unit.cyerce.details = [lightgray][비공식][]폭죽놀이다!
unit.aegires.details = [lightgray][비공식][]플레이어가 할 수 있는건 운전과 공사뿐... unit.aegires.details = [lightgray][비공식][]공격 컨트롤을 할 수 없습니다.
unit.navanax.details = [lightgray][비공식][]플레이어에게 잠깐의 섬광뽕을 입힙니다. unit.navanax.details = [lightgray][비공식][]플레이어에게 잠깐의 섬광뽕을 입힙니다.
unit.alpha.details = unit.alpha.details =
unit.beta.details = unit.beta.details =

View File

@@ -169,6 +169,7 @@ launchcore = Lansează Nucleu
filename = Nume Fișier: filename = Nume Fișier:
unlocked = Nou conținut deblocat! unlocked = Nou conținut deblocat!
available = Poți cerceta noi tehnologii! available = Poți cerceta noi tehnologii!
unlock.incampaign = < Deblochează în campanie pt detalii >
completed = [accent]Finalizat completed = [accent]Finalizat
techtree = Cercetează techtree = Cercetează
research.legacy = Au fost găsite date de cercetare din versiunea [accent]5.0[].\n Dorești să [accent]păstrezi aceste date[], sau [accent]să renunți la ele[] și să reîncepi cercetarea în noua campanie (recomandat)? research.legacy = Au fost găsite date de cercetare din versiunea [accent]5.0[].\n Dorești să [accent]păstrezi aceste date[], sau [accent]să renunți la ele[] și să reîncepi cercetarea în noua campanie (recomandat)?
@@ -362,6 +363,7 @@ publish.confirm = Sigur vrei să publici asta?\n\n[lightgray]Asigură-te că ai
publish.error = Eroare la publicarea itemului: {0} publish.error = Eroare la publicarea itemului: {0}
steam.error = Inițializarea serviciilor Steam a eșuat.\nEroare: {0} steam.error = Inițializarea serviciilor Steam a eșuat.\nEroare: {0}
editor.cliffs = Pereți >> Dealuri
editor.brush = Pensulă editor.brush = Pensulă
editor.openin = Deschide în Editor editor.openin = Deschide în Editor
editor.oregen = Generarea Minereurilor editor.oregen = Generarea Minereurilor
@@ -394,6 +396,13 @@ waves.load = Încarcă din Clipboard
waves.invalid = Valuri invalide în clipboard. waves.invalid = Valuri invalide în clipboard.
waves.copied = Valuri copiate. waves.copied = Valuri copiate.
waves.none = Niciun inamic definit.\nDe reținut că o listă de valuri goală va fi înlocuită automat cu lista de valuri prestabilită. waves.none = Niciun inamic definit.\nDe reținut că o listă de valuri goală va fi înlocuită automat cu lista de valuri prestabilită.
waves.sort = Sortează După
waves.sort.reverse = Inversează Sortarea
waves.sort.begin = Început
waves.sort.health = Viață
waves.sort.type = Tip
waves.units.hide = Ascunde
waves.units.show = Vezi Tot
#intenționat cu literă mică #intenționat cu literă mică
wavemode.counts = numere wavemode.counts = numere
@@ -622,6 +631,8 @@ sector.biomassFacility.name = Facilitatea de Sinteză a Biomasei
sector.windsweptIslands.name = Insulele Măturate de Vânt sector.windsweptIslands.name = Insulele Măturate de Vânt
sector.extractionOutpost.name = Avanpostul de Extracție sector.extractionOutpost.name = Avanpostul de Extracție
sector.planetaryTerminal.name = Terminalul de Lansare Planetară sector.planetaryTerminal.name = Terminalul de Lansare Planetară
sector.coastline.name = Zona de Coastă
sector.navalFortress.name = Fortăreața Navală
sector.groundZero.description = Locația optimă pt a începe încă odată. Risc de inamici scăzut. Puține resurse.\nAdună cât de mult plumb și cupru se poate.\nMergi mai departe. sector.groundZero.description = Locația optimă pt a începe încă odată. Risc de inamici scăzut. Puține resurse.\nAdună cât de mult plumb și cupru se poate.\nMergi mai departe.
sector.frozenForest.description = Chiar și aici, aproape de munți, sporii s-au împrăștiat. Temperaturile reci nu-i pot reține la infinit.\n\nÎncepe călătoria către electricitate. Construiește generatoare de combustie. Învață să folosești reparatoare. sector.frozenForest.description = Chiar și aici, aproape de munți, sporii s-au împrăștiat. Temperaturile reci nu-i pot reține la infinit.\n\nÎncepe călătoria către electricitate. Construiește generatoare de combustie. Învață să folosești reparatoare.
@@ -649,7 +660,8 @@ status.sapped.name = Slăbește
status.electrified.name = Electrificat status.electrified.name = Electrificat
status.spore-slowed.name = Încetinit de Spori status.spore-slowed.name = Încetinit de Spori
status.tarred.name = Păcurit status.tarred.name = Păcurit
status.overclock.name = Suprasolicitat status.overdrive.name = Suprasolicitat
status.overclock.name = Overclock
status.shocked.name = Electrocutat status.shocked.name = Electrocutat
status.blasted.name = Explozie status.blasted.name = Explozie
status.unmoving.name = Nemișcat status.unmoving.name = Nemișcat
@@ -766,9 +778,9 @@ stat.healing = Reparare
ability.forcefield = Câmp de Forță ability.forcefield = Câmp de Forță
ability.repairfield = Câmp de Reparare ability.repairfield = Câmp de Reparare
ability.statusfield = {0} Câmp Suprasolicitare Unități ability.statusfield = {0} Câmp de Stare
ability.unitspawn = Fabrică de {0} ability.unitspawn = Fabrică de {0}
ability.shieldregenfield = Scut Regenerabil ability.shieldregenfield = Câmp Regenerare Scut
ability.movelightning = Mișcare Fulger ability.movelightning = Mișcare Fulger
ability.energyfield = Câmp de Energie: [accent]{0}[] forță pe ~ [accent]{1}[] blocuri / [accent]{2}[] ținte ability.energyfield = Câmp de Energie: [accent]{0}[] forță pe ~ [accent]{1}[] blocuri / [accent]{2}[] ținte
@@ -873,7 +885,7 @@ setting.difficulty.name = Dificultate:
setting.screenshake.name = Agitare Ecran setting.screenshake.name = Agitare Ecran
setting.effects.name = Vezi Efectele setting.effects.name = Vezi Efectele
setting.destroyedblocks.name = Vezi Blocurile Distruse setting.destroyedblocks.name = Vezi Blocurile Distruse
setting.blockstatus.name = Vezi Statusul Blocului setting.blockstatus.name = Vezi Starea Blocului
setting.conveyorpathfinding.name = Găsirea Drumului la Plasarea Benzii setting.conveyorpathfinding.name = Găsirea Drumului la Plasarea Benzii
setting.sensitivity.name = Sensibilitatea Controlului setting.sensitivity.name = Sensibilitatea Controlului
setting.saveinterval.name = Interval de Salvare setting.saveinterval.name = Interval de Salvare
@@ -928,8 +940,8 @@ keybind.clear_building.name = Șterge Clădirea
keybind.press = Apasă o tastă... keybind.press = Apasă o tastă...
keybind.press.axis = Apasă o axă sau o tastă... keybind.press.axis = Apasă o axă sau o tastă...
keybind.screenshot.name = Captură Hartă keybind.screenshot.name = Captură Hartă
keybind.toggle_power_lines.name = Oprește/Pornește Statusul Electricelor keybind.toggle_power_lines.name = Oprește/Pornește Starea Electricelor
keybind.toggle_block_status.name = Oprește/Pornește Statusul Blocurilor keybind.toggle_block_status.name = Oprește/Pornește Starea Blocurilor
keybind.move_x.name = Mergi pe X keybind.move_x.name = Mergi pe X
keybind.move_y.name = Mergi pe Y keybind.move_y.name = Mergi pe Y
keybind.mouse_move.name = Urmărește Mouseul keybind.mouse_move.name = Urmărește Mouseul
@@ -1048,7 +1060,7 @@ content.item.name = Materiale
content.liquid.name = Lichide content.liquid.name = Lichide
content.unit.name = Unități content.unit.name = Unități
content.block.name = Blocuri content.block.name = Blocuri
content.status.name = Efecte de Status content.status.name = Efecte de Stare
content.sector.name = Sectoare content.sector.name = Sectoare
item.copper.name = Cupru item.copper.name = Cupru
@@ -1151,6 +1163,7 @@ block.core-nucleus.name = Nucleu: Core
block.deep-water.name = Apă Adâncă block.deep-water.name = Apă Adâncă
block.shallow-water.name = Apă block.shallow-water.name = Apă
block.tainted-water.name = Apă Tulbure block.tainted-water.name = Apă Tulbure
block.deep-tainted-water.name = Apă Adâncă și Tulbure
block.darksand-tainted-water.name = Apă Tulbure cu Nisip Negru block.darksand-tainted-water.name = Apă Tulbure cu Nisip Negru
block.tar.name = Păcură block.tar.name = Păcură
block.stone.name = Piatră block.stone.name = Piatră
@@ -1384,6 +1397,7 @@ hint.generator = \uf879 [accent]Generatoarele pe Combustie[] ard cărbunele și
hint.guardian = Unitățile [accent]Gardian[] au armuri puternice. Munițiile slabe precum [accent]Cuprul[] și [accent]Plumbul[] [scarlet]nu sunt eficiente[].\n\nFolosește arme mai bune sau muniție de \uf835 [accent]Grafit[] pt \uf861Duo/\uf859Salvo pt a nimici Gardianul. hint.guardian = Unitățile [accent]Gardian[] au armuri puternice. Munițiile slabe precum [accent]Cuprul[] și [accent]Plumbul[] [scarlet]nu sunt eficiente[].\n\nFolosește arme mai bune sau muniție de \uf835 [accent]Grafit[] pt \uf861Duo/\uf859Salvo pt a nimici Gardianul.
hint.coreUpgrade = Un nucleu poate pot fi îmbunătățit [accent]plasând o alt nucleu mai bun peste el[].\n\nPlasează un nucleu  [accent]Foundation[] peste nucleul  [accent]Shard[]. Nucleul nu poate fi plasat decât pe alte nuclee. Asigură-te că nu sunt alte benzi sau obstacole care să împiedice plasarea. hint.coreUpgrade = Un nucleu poate pot fi îmbunătățit [accent]plasând o alt nucleu mai bun peste el[].\n\nPlasează un nucleu  [accent]Foundation[] peste nucleul  [accent]Shard[]. Nucleul nu poate fi plasat decât pe alte nuclee. Asigură-te că nu sunt alte benzi sau obstacole care să împiedice plasarea.
hint.presetLaunch = Poți lansa de oriunde în sectoarele gri, precum [accent]Pădurea Glacială[]. Ele sunt [accent]zone[] speciale [accent]de aterizare[]. Nu ai nevoie să capturezi sectoarele învecinate pt a lansa.\n\n[accent]Sectoarele numerotate[], ca acesta, sunt [accent]opționale[]. hint.presetLaunch = Poți lansa de oriunde în sectoarele gri, precum [accent]Pădurea Glacială[]. Ele sunt [accent]zone[] speciale [accent]de aterizare[]. Nu ai nevoie să capturezi sectoarele învecinate pt a lansa.\n\n[accent]Sectoarele numerotate[], ca acesta, sunt [accent]opționale[].
hint.presetDifficulty = Acest sector are un [scarlet]nivel ridicat de amenințare inamică[].\n[accent]Nu e recomandat[] să lansezi în asemenea sectoare fără pregătiri sau tehnologie adecvată.
hint.coreIncinerate = După ce nucleul se umple până la refuz cu un tip de material, toate materialele în plus de acel tip care încearcă să între în nucleu sunt [accent]incinerate[]. hint.coreIncinerate = După ce nucleul se umple până la refuz cu un tip de material, toate materialele în plus de acel tip care încearcă să între în nucleu sunt [accent]incinerate[].
hint.coopCampaign = Când joci [accent]campania cooperând cu alți jucători[], materialele produse în sectorul curent vor fi transferate și către [accent]sectoarele tale locale[].\n\nDe asemenea, vei debloca tot ceea ce cercetează gazda. hint.coopCampaign = Când joci [accent]campania cooperând cu alți jucători[], materialele produse în sectorul curent vor fi transferate și către [accent]sectoarele tale locale[].\n\nDe asemenea, vei debloca tot ceea ce cercetează gazda.
@@ -1551,7 +1565,7 @@ block.additive-reconstructor.description = Îmbunătățește unitățile primit
block.multiplicative-reconstructor.description = Îmbunătățește unitățile primite, transformându-le în unități de nivel trei. block.multiplicative-reconstructor.description = Îmbunătățește unitățile primite, transformându-le în unități de nivel trei.
block.exponential-reconstructor.description = Îmbunătățește unitățile primite, transformându-le în unități de nivel patru. block.exponential-reconstructor.description = Îmbunătățește unitățile primite, transformându-le în unități de nivel patru.
block.tetrative-reconstructor.description = Îmbunătățește unitățile primite, transformându-le în unități de ltimă generație: nivelul cinci. block.tetrative-reconstructor.description = Îmbunătățește unitățile primite, transformându-le în unități de ltimă generație: nivelul cinci.
block.switch.description = Un întrerupător. Poate fi pornit sau oprit. Statusul său poate fi citit și controlat de procesoarele logice. block.switch.description = Un întrerupător. Poate fi pornit sau oprit. Starea sa poate fi citită și controlată de procesoarele logice.
block.micro-processor.description = Rulează într-o buclă continuă o secvență de instrucțiuni logice. Poate fi folosit pt a controla unități și diverse clădiri. block.micro-processor.description = Rulează într-o buclă continuă o secvență de instrucțiuni logice. Poate fi folosit pt a controla unități și diverse clădiri.
block.logic-processor.description = Rulează într-o buclă continuă o secvență de instrucțiuni logice. Poate fi folosit pt a controla unități și diverse clădiri. Mai rapid decât microprocesorul. block.logic-processor.description = Rulează într-o buclă continuă o secvență de instrucțiuni logice. Poate fi folosit pt a controla unități și diverse clădiri. Mai rapid decât microprocesorul.
block.hyper-processor.description = Rulează într-o buclă continuă o secvență de instrucțiuni logice. Poate fi folosit pt a controla unități și diverse clădiri. Mai rapid decât procesorul logic. block.hyper-processor.description = Rulează într-o buclă continuă o secvență de instrucțiuni logice. Poate fi folosit pt a controla unități și diverse clădiri. Mai rapid decât procesorul logic.

View File

@@ -616,6 +616,8 @@ sector.biomassFacility.name = Центр исследования биомасс
sector.windsweptIslands.name = Штормовой архипелаг sector.windsweptIslands.name = Штормовой архипелаг
sector.extractionOutpost.name = Добывающая база sector.extractionOutpost.name = Добывающая база
sector.planetaryTerminal.name = Планетарный пусковой терминал sector.planetaryTerminal.name = Планетарный пусковой терминал
sector.coastline.name = Береговая линия
sector.navalFortress.name = Прибрежная крепость
sector.groundZero.description = Оптимальная локация для повторных игр. Низкая вражеская угроза. Немного ресурсов.\nСоберите как можно больше свинца и меди.\nДвигайтесь дальше. sector.groundZero.description = Оптимальная локация для повторных игр. Низкая вражеская угроза. Немного ресурсов.\nСоберите как можно больше свинца и меди.\nДвигайтесь дальше.
sector.frozenForest.description = Даже здесь, ближе к горам, споры распространились. Холодные температуры не могут сдерживать их вечно.\n\nНачните вкладываться в энергию. Постройте генераторы внутреннего сгорания. Научитесь пользоваться регенератором. sector.frozenForest.description = Даже здесь, ближе к горам, споры распространились. Холодные температуры не могут сдерживать их вечно.\n\nНачните вкладываться в энергию. Постройте генераторы внутреннего сгорания. Научитесь пользоваться регенератором.
@@ -794,7 +796,7 @@ bullet.damage = [stat]{0}[lightgray] урона
bullet.splashdamage = [stat]{0}[lightgray] урона в радиусе ~[stat] {1}[lightgray] блоков bullet.splashdamage = [stat]{0}[lightgray] урона в радиусе ~[stat] {1}[lightgray] блоков
bullet.incendiary = [stat]зажигательный bullet.incendiary = [stat]зажигательный
bullet.homing = [stat]самонаводящийся bullet.homing = [stat]самонаводящийся
bullet.frag = [stat]осколочный bullet.frags = [stat]{0}[lightgray]x осколочный(ых) снаряд(ов):
bullet.lightning = [stat]{0}[lightgray]x молнии ~ [stat]{1}[lightgray] урона bullet.lightning = [stat]{0}[lightgray]x молнии ~ [stat]{1}[lightgray] урона
bullet.buildingdamage = [stat]{0}%[lightgray] урона по постройкам bullet.buildingdamage = [stat]{0}%[lightgray] урона по постройкам
bullet.knockback = [stat]{0}[lightgray] отбрасывания bullet.knockback = [stat]{0}[lightgray] отбрасывания
@@ -1544,6 +1546,8 @@ block.memory-bank.description = Хранит информацию для лог
block.logic-display.description = Отображает произвольную графику из логического процессора. block.logic-display.description = Отображает произвольную графику из логического процессора.
block.large-logic-display.description = Отображает произвольную графику из логического процессора. block.large-logic-display.description = Отображает произвольную графику из логического процессора.
block.interplanetary-accelerator.description = Массивная электромагнитная башня-рельсотрон. Ускоряет ядро, позволяя преодолеть гравитацию для межпланетного развёртывания. block.interplanetary-accelerator.description = Массивная электромагнитная башня-рельсотрон. Ускоряет ядро, позволяя преодолеть гравитацию для межпланетного развёртывания.
block.repair-turret.description = Непрерывно ремонтирует ближайшую поврежденную еденицу в своем радиусе. Опционально использует охлаждающую жидкость.
block.payload-propulsion-tower.description = Конструкция для транспортировки больших грузов на большое растояние. Стреляет грузом в другие грузовые катапульты.
unit.dagger.description = Стреляет стандартными пулями по всем врагам поблизости. unit.dagger.description = Стреляет стандартными пулями по всем врагам поблизости.
unit.mace.description = Стреляет потоками огня по всем врагам поблизости. unit.mace.description = Стреляет потоками огня по всем врагам поблизости.

View File

@@ -169,6 +169,7 @@ launchcore = ส่งแกนกลาง
filename = ชื่อไฟล์: filename = ชื่อไฟล์:
unlocked = เนื้อหาใหม่ปลดล็อก! unlocked = เนื้อหาใหม่ปลดล็อก!
available = มีการวิจัยใหม่พร้อมปลดล็อก! available = มีการวิจัยใหม่พร้อมปลดล็อก!
unlock.incampaign = < ปลดล็อกในแคมเปญเพื่อดูรายละเอียด >
completed = [accent]วิจัยแล้ว completed = [accent]วิจัยแล้ว
techtree = ต้นไม้แห่งเทคโนโลยี techtree = ต้นไม้แห่งเทคโนโลยี
research.legacy = พบข้อมูลการวิจัยของเวอร์ชั่น [accent]5.0[]\nคุณต้องการ[accent]โหลดข้อมูล[]หรือ[accent]ทิ้งข้อมูลไป[]และเริ่มต้นวิจัยในแคมเปญใหม่ (แนะนำ) research.legacy = พบข้อมูลการวิจัยของเวอร์ชั่น [accent]5.0[]\nคุณต้องการ[accent]โหลดข้อมูล[]หรือ[accent]ทิ้งข้อมูลไป[]และเริ่มต้นวิจัยในแคมเปญใหม่ (แนะนำ)
@@ -248,7 +249,7 @@ confirmban = คุณแน่ใจหรือว่าจะแบนผู
confirmkick = คุณแน่ใจหรือว่าจะเตะผู้เล่นนี้ออก? confirmkick = คุณแน่ใจหรือว่าจะเตะผู้เล่นนี้ออก?
confirmvotekick = คุณแน่ใจหรือว่าจะโหวตเตะผู้เล่นนี้ออก? confirmvotekick = คุณแน่ใจหรือว่าจะโหวตเตะผู้เล่นนี้ออก?
confirmunban = คุณแน่ใจหรือว่าจะเลิกแบนผู้เล่นนี้? confirmunban = คุณแน่ใจหรือว่าจะเลิกแบนผู้เล่นนี้?
confirmadmin = คุณแน่ใจหรือว่าจะเปลี่ยนผู้เล่นคนนี้เป็นแอดมิน? confirmadmin = คุณแน่ใจหรือว่าจะแต่งตั้งผู้เล่นคนนี้เป็นแอดมิน?
confirmunadmin = คุณแน่ใจหรือว่าจะลบสถานะการเป็นแอดมินของผู้เล่นนี้? confirmunadmin = คุณแน่ใจหรือว่าจะลบสถานะการเป็นแอดมินของผู้เล่นนี้?
joingame.title = เข้าร่วมเกม joingame.title = เข้าร่วมเกม
joingame.ip = ที่อยู่: joingame.ip = ที่อยู่:
@@ -362,6 +363,7 @@ publish.confirm = คุณแน่ใจหรือว่าจะเผย
publish.error = เกิดข้อผิดพลาดการเผยแพร่ไอเท็มดังต่อไปนี้: {0} publish.error = เกิดข้อผิดพลาดการเผยแพร่ไอเท็มดังต่อไปนี้: {0}
steam.error = ไม่สามารถเริ่ม Steam service ได้\nError: {0} steam.error = ไม่สามารถเริ่ม Steam service ได้\nError: {0}
editor.cliffs = เปลี่ยนกำแพงเป็นหน้าผา
editor.brush = แปรง editor.brush = แปรง
editor.openin = เปิดในตัวแก้ไข editor.openin = เปิดในตัวแก้ไข
editor.oregen = การเกิดของแร่ editor.oregen = การเกิดของแร่
@@ -394,6 +396,13 @@ waves.load = โหลดจากคลิปบอร์ด
waves.invalid = แบบคลื่นในคลิปบอร์ดไม่ถูกต้อง waves.invalid = แบบคลื่นในคลิปบอร์ดไม่ถูกต้อง
waves.copied = คัดลอกแบบคลื่นแล้ว waves.copied = คัดลอกแบบคลื่นแล้ว
waves.none = ไม่ได้กำหนดศัตรู\nแบบคลื่นเปล่าจะถูกแทนที่โดยแบบคลื่นค่าเริ่มต้นของเกม waves.none = ไม่ได้กำหนดศัตรู\nแบบคลื่นเปล่าจะถูกแทนที่โดยแบบคลื่นค่าเริ่มต้นของเกม
waves.sort = จัดเรียงตาม
waves.sort.reverse = เรียงย้อนกลับ
waves.sort.begin = เริ่มต้น
waves.sort.health = พลังชีวิต
waves.sort.type = ชนิด
waves.units.hide = ซ่อนทั้งหมด
waves.units.show = แสดงทั้งหมด
#these are intentionally in lower case #these are intentionally in lower case
wavemode.counts = จำนวน wavemode.counts = จำนวน
@@ -439,7 +448,7 @@ editor.exportimage = ส่งออกไฟล์รูปพื้นที
editor.exportimage.description = ส่งออกไฟล์รูปแมพ editor.exportimage.description = ส่งออกไฟล์รูปแมพ
editor.loadimage = นำเข้าแบบพื้นที่ editor.loadimage = นำเข้าแบบพื้นที่
editor.saveimage = ส่งออกแบบพื้นที่ editor.saveimage = ส่งออกแบบพื้นที่
editor.unsaved = [scarlet]คุณมีการเปลี่ยนแปลงที่ยังไม่ได้เซฟ![]\nคุณแน่ใจหรือว่าจะออก? editor.unsaved = คุณแน่ใจหรือว่าจะออก?\n[scarlet]การเปลี่ยนแปลงที่ยังไม่ได้เซฟจะถูกทิ้ง
editor.resizemap = เปลี่ยนขนาดของแมพ editor.resizemap = เปลี่ยนขนาดของแมพ
editor.mapname = ชื่อแมพ: editor.mapname = ชื่อแมพ:
editor.overwrite = [accent]ตำเตือน!\nแมพนี้จะเขียนทับกับแมพที่มีอยู่แล้ว editor.overwrite = [accent]ตำเตือน!\nแมพนี้จะเขียนทับกับแมพที่มีอยู่แล้ว
@@ -615,29 +624,31 @@ sector.stainedMountains.name = ภูเขาหลากสี
sector.desolateRift.name = เดโซเลต ริฟต์ sector.desolateRift.name = เดโซเลต ริฟต์
sector.nuclearComplex.name = ฐานผลิตนิวเคลียร์ sector.nuclearComplex.name = ฐานผลิตนิวเคลียร์
sector.overgrowth.name = โอเวอร์โกรว์ด sector.overgrowth.name = โอเวอร์โกรว์ด
sector.tarFields.name = ทาร์ ฟิลด์ sector.tarFields.name = ผืนแผ่นแห่งน้ำมัน
sector.saltFlats.name = ที่ราบเกลือ sector.saltFlats.name = ที่ราบเกลือ
sector.fungalPass.name = ทางผ่านฟังกัล sector.fungalPass.name = ทางผ่านฟังกัล
sector.biomassFacility.name = แหล่งสังเคราะห์ชีวมวล sector.biomassFacility.name = แหล่งสังเคราะห์ชีวมวล
sector.windsweptIslands.name = หมู่เกาะวินด์สเวปท์ sector.windsweptIslands.name = หมู่เกาะวินด์สเวปท์
sector.extractionOutpost.name = ด่านส่งทรัพยากร sector.extractionOutpost.name = ด่านส่งทรัพยากร
sector.planetaryTerminal.name = ท่าปล่อยจรวดอวกาศยาน sector.planetaryTerminal.name = ท่าปล่อยจรวดอวกาศยาน
sector.coastline.name = แนวชายฝั่ง
sector.navalFortress.name = ปราการแห่งวารี
sector.groundZero.description = ที่ที่ดีที่สุดในการเริ่มต้นอีกครั้ง ศัตรูน้อย ทรัพยากรน้อย\nเก็บ[accent]ตะกั่ว[]และ[accent]ทองแดง[]ให้ได้มากที่สุด\nแล้วลุยต่อ sector.groundZero.description = ที่ที่ดีที่สุดในการเริ่มต้นอีกครั้ง ศัตรูน้อย ทรัพยากรน้อย\nเก็บ[accent]ตะกั่ว[]และ[accent]ทองแดง[]ให้ได้มากที่สุด\nแล้วลุยต่อ
sector.frozenForest.description = แม้แต่ที่นี่ ที่ที่อยู่ใกล้ภูเขา [accent]สปอร์[]ก็ยังแพร่มาถึงที่นี่\nอากาศอันเย็นเยือกไม่สามารถหยุดยั้งพวกมันได้ตลอดไป\n\nเริ่มต้นการใช้ไฟฟ้า สร้างเครื่องกำเนิดไฟฟ้าเผาไหม้\nเรียนรู้ที่จะใช้เครื่องซ่อมแซม sector.frozenForest.description = แม้แต่ที่นี่ ที่ที่อยู่ใกล้ภูเขา [accent]สปอร์[]ก็ยังแพร่มาถึงที่นี่\nอากาศอันแสนเย็นเยือกไม่สามารถหยุดยั้งพวกมันได้ตลอดไป\n\nเริ่มต้นการใช้ไฟฟ้า สร้างเครื่องกำเนิดไฟฟ้าเผาไหม้\nเรียนรู้ที่จะใช้เครื่องซ่อมแซม
sector.saltFlats.description = ณ ขอบของทะเลทราย เป็นที่ตั้งของที่ราบเกลือ สามารถพบทรัพยากรบางอย่างได้ที่นี่\n\nศัตรูได้ตั้งฐานเก็บทรัพยากรไว้ที่นี่ ทำลายแกนกลางของพวกมัน อย่าให้มีอะไรเหลือ sector.saltFlats.description = ณ ขอบของทะเลทราย เป็นที่ตั้งของที่ราบเกลือ สามารถพบทรัพยากรบางอย่างได้ที่นี่\n\nศัตรูได้ตั้งฐานเก็บทรัพยากรไว้ที่นี่ ทำลายแกนกลางของพวกมัน อย่าให้มีอะไรเหลือ
sector.craters.description = น้ำขังอยู่ในหลุมอุกกาบาศแห่งนี้ อนุสรณ์สถานของสงครามเก่าแก่\nยึดพื้นที่นี่มา เก็บทราย เผา[accent]กระจกเมต้า[]\nปั๊มน้ำเพื่อมาหล่อเย็นป้อมปืนและเครื่องขุดเจาะ sector.craters.description = มีน้ำขังอยู่ในหลุมอุกกาบาศแห่งนี้ เป็นอนุสรณ์สถานของสงครามเก่าแก่\nยึดพื้นที่นี่มา เก็บทราย เผา[accent]กระจกเมต้า[]\nปั๊มน้ำเพื่อมาหล่อเย็นป้อมปืนและเครื่องขุดเจาะ
sector.ruinousShores.description = ถัดมาจากทะเลทราย เป็นที่ตั้งของชายฝั่ง ที่ครั้งก่อน เคยเป็นที่ตั้งของฐานป้องกันชายฝั่ง\nซึ่งทุกทำลายไปซะส่วนใหญ่แล้ว มีเหลือแค่ระบบการป้องกันพื้นฐาน\nทุกอย่างที่เหลือถูกทำลายเหลือเพียงแค่เศษเหล็ก\n\nทำการขยายการสำรวจต่อไป ค้นพบกับเทคโนโลยีอีกครั้ง sector.ruinousShores.description = ถัดมาจากทะเลทราย เป็นที่ตั้งของชายฝั่ง ที่ครั้งก่อน เคยเป็นที่ตั้งของฐานป้องกันชายฝั่ง\nซึ่งทุกทำลายไปซะส่วนใหญ่แล้ว มีเหลือแค่ระบบการป้องกันพื้นฐาน\nทุกอย่างที่เหลือถูกทำลายเหลือเพียงแค่เศษเหล็ก\n\nทำการขยายการสำรวจต่อไป ค้นพบกับเทคโนโลยีอีกครั้ง
sector.stainedMountains.description = เข้าลึกไปในพื้นที่ จะพบกับภูเขา ซึ่งยังไม่ถูกสปอร์แตะต้อง\nขุด[accent]ไทเทเนี่ยม[]ที่อุดมสมบูรณ์ในพื้นที่นี้ เรียนรู้ที่จะใช้มัน\n\nมีศัตรูปรากฏตัวมากขึ้นในบริเวณนี้ อย่าปล่อยให้พวกมันส่งยูนิตที่แข็งแกร่งที่สุดออกมา sector.stainedMountains.description = เข้าลึกไปในพื้นที่ จะพบกับภูเขา ซึ่งยังไม่ถูกสปอร์แตะต้อง\nขุด[accent]ไทเทเนี่ยม[]ที่อุดมสมบูรณ์ในพื้นที่นี้ เรียนรู้ที่จะใช้มัน\n\nมีศัตรูปรากฏตัวมากขึ้นในบริเวณนี้ อย่าปล่อยให้พวกมันส่งยูนิตที่แข็งแกร่งที่สุดออกมา
sector.overgrowth.description = พื้นที่นี้ถูกปกคลุมไปด้วยพืช เข้าใกล้กับแหล่งกำเนิดของสปอร์\nศัตรูได้ตั้งฐานเฝ้าระวังไว้ที่นี่ สร้างยูนิตเมส ทำลายฐานทิ้งซะ\nวิจัย[accent]เครื่องพัฒนารุ่นยกกำลัง[]เพื่อผลิตยูนิตขนาดที่ใหญ่ขึ้น sector.overgrowth.description = พื้นที่นี้ถูกปกคลุมไปด้วยพืช เข้าใกล้กับแหล่งกำเนิดของสปอร์\nศัตรูได้ตั้งฐานเฝ้าระวังไว้ที่นี่ สร้างยูนิตเมส ทำลายฐานทิ้งซะ\nวิจัย[accent]เครื่องพัฒนารุ่นยกกำลัง[]เพื่อผลิตยูนิตขนาดที่ใหญ่ขึ้น
sector.tarFields.description = ขอบของพื้นที่ผลิตน้ำมัน อยู่ระหว่างภูเขาและทะเลทราย หนึ่งในพื้นที่ที่มีแหล่งน้ำมันดินที่ใช้งานได้\nแม้ว่าจะถูกทิ้งร้าง พื้นที่นี้ยังคงมีฐานทัพของศัตรูอยู่ใกล้ๆ อย่าประมาทกับพวกมัน\n\n[lightgray]วิจัยเทคโนโลยีการแปรรูปน้ำมันหากเป็นไปได้ sector.tarFields.description = แนวชานขอบของแหล่งผลิตน้ำมัน อยู่ระหว่างภูเขาและทะเลทราย เป็นหนึ่งในพื้นที่ที่มีแหล่งน้ำมันดินที่ใช้งานได้\nแม้ว่าจะถูกทิ้งร้าง พื้นที่นี้ยังคงมีฐานทัพของศัตรูอยู่ใกล้ๆ อย่าประมาทกับพวกมัน\n\n[lightgray]วิจัยเทคโนโลยีการแปรรูปน้ำมันหากเป็นไปได้
sector.desolateRift.description = เป็นพื้นที่ที่อันตรายมาก ทรัพยากรมากมาย แต่พื้นที่คับแคบ\nความเสี่ยงการโดนทำลายล้างสูง ออกไปจากที่นี่ให้เร็วที่สุด\nอย่าถูกหลอกโดยระยะเวลาระหว่างการโจมตีของศัตรูที่เว้นไว้นานกว่าปกติ sector.desolateRift.description = เป็นพื้นที่ที่อันตรายมาก ทรัพยากรมากมาย แต่พื้นที่คับแคบ\nความเสี่ยงการโดนทำลายล้างสูง ออกไปจากที่นี่ให้เร็วที่สุด\nอย่าถูกหลอกโดยระยะเวลาระหว่างการโจมตีของศัตรูที่เว้นไว้นานกว่าปกติ
sector.nuclearComplex.description = สถานที่ผลิตและแปรรูปทอเรี่ยมเก่า ถูกทำลายไม่เหลือสิ้น\nวิจัยทอเรี่ยมและวิธีการใช้มัน\n\nศัตรูในบริเวณนี้มีจำนวนมาก คอยตรวจตราหาผู้บุกรุกอยู่ตลอดเวลา sector.nuclearComplex.description = สถานที่ผลิตและแปรรูปทอเรี่ยมเก่า ถูกทำลายไม่เหลือสิ้น\nวิจัยทอเรี่ยมและวิธีการใช้มัน\n\nศัตรูในบริเวณนี้มีจำนวนมาก คอยตรวจตราหาผู้บุกรุกอยู่ตลอดเวลา
sector.fungalPass.description = ทางผ่านระหว่างพื้นที่สูงและต่ำของภูเขา พื้นที่นี้เต็มไปด้วยสปอร์ ฐานลาดตระเวนขนาดเล็กของศัตรูตั้งอยู่ที่นี่\nทำลายมันซะ\nผลิตยูนิตแด็กเกอร์และครอว์เลอร์ ทำลายแกนกลางทั้งสองไม่ให้เหลือซาก sector.fungalPass.description = ทางผ่านระหว่างพื้นที่สูงและต่ำของภูเขา พื้นที่นี้เต็มไปด้วยสปอร์ ฐานลาดตระเวนขนาดเล็กของศัตรูตั้งอยู่ที่นี่\nทำลายมันซะ\nผลิตยูนิตแด็กเกอร์และครอว์เลอร์ ทำลายแกนกลางทั้งสองไม่ให้เหลือซาก
sector.biomassFacility.description = แหล่งต้นกำเนิดของสปอร์ ที่นี่คือฐานวิจัยและผลิตสปอร์เริ่มแรก\nวิจัยเทคโนโลยีที่อยู่ภายในนั้น เพาะชำ[accent]สปอร์[]เพื่อเป็นเชื้อเพลิงและใช้ในการผลิตพลาสติก\n\n[gray]เมื่อสถานที่นี้ถูกทิ้งร้าง สปอร์ก็ถูกปล่อยออกมา ไม่มีสิ่งใดในระบบนิเวศท้องถิ่นที่สามารถแข่งขันกับสิ่งมีชีวิตที่\nแพร่กระจายเช่นนี้ได้ sector.biomassFacility.description = แหล่งต้นกำเนิดของสปอร์ ที่นี่คือฐานวิจัยและผลิตสปอร์เริ่มแรก\nวิจัยเทคโนโลยีที่อยู่ภายในนั้น เพาะชำ[accent]สปอร์[]เพื่อเป็นเชื้อเพลิงและใช้ในการผลิตพลาสติก\n\n[gray]เมื่อสถานที่นี้ถูกทิ้งร้าง สปอร์ก็ถูกปล่อยออกมา ไม่มีสิ่งใดในระบบนิเวศท้องถิ่นที่สามารถแข่งขันกับสิ่งมีชีวิตที่\nแพร่กระจายเช่นนี้ได้
sector.windsweptIslands.description = เลยแนวชายฝั่งไปเป็นหมู่เกาะที่ตั้งอยู่ห่างไกล เคยมีบันทึกว่าที่นี่มีโรงงานผลิต[accent]พลาสตาเนี่ยม[]อยู่\n\nทำลายเรือศัตรู สร้างฐานทัพบนเกาะ วิจัยโรงงานพวกนี้ sector.windsweptIslands.description = เลยแนวชายฝั่งไปจะพบกับหมู่เกาะที่ตั้งอยู่ห่างไกลแห่งนี้ เคยมีบันทึกว่าที่นี่มีโรงงานผลิต[accent]พลาสตาเนี่ยม[]อยู่\n\nทำลายเรือศัตรู สร้างฐานทัพบนเกาะ วิจัยโรงงานพวกนี้
sector.extractionOutpost.description = ด่านที่อยู่ห่างไกล สร้างโดยศัตรูเพื่อใช้ในการส่งทรัพยากรไปยังฐานทัพอื่น\n\nเทคโนโลยีการส่งไอเท็มข้ามเซ็กเตอร์เป็นสิ่งจำเป็นสำหรับการพิชิตถัดๆ ไป ทำลายด่าน วิจัยฐานส่งของ sector.extractionOutpost.description = ด่านที่อยู่ห่างไกล สร้างโดยศัตรูเพื่อใช้ในการส่งทรัพยากรไปยังฐานทัพอื่น\n\nเทคโนโลยีการส่งไอเท็มข้ามเซ็กเตอร์เป็นสิ่งจำเป็นสำหรับการพิชิตถัดๆ ไป ทำลายด่าน วิจัยฐานส่งของ
sector.impact0078.description = นีคือเศษซากของเรือขนส่งระหว่างดวงดาวที่เคยเข้ามายังระบบนี้\nเศษเหล็กและหิมะปกคลุมทั่วทั้งพื้นที่\n\nกอบกู้ซากยานให้ได้มากที่สุด วิจัยเทคโนโลยีทั้งหมดที่ยังเหลือรอด\n\n\n[gray]อย่าประมาทกับฐานทัพศัตรูที่อยู่ใกล้ๆ โดยอันขาด\nศัตรูจะส่งกองกำลังมาโจมตีเรื่อยๆ จนกว่าคุณจะพ่ายแพ้ sector.impact0078.description = ณ ที่แห่งนีคือเศษซากของเรือขนส่งระหว่างดวงดาวที่เคยเข้ามายังระบบนี้\nเศษเหล็กและหิมะปกคลุมทั่วทั้งพื้นที่\n\nกอบกู้ซากยานให้ได้มากที่สุด วิจัยเทคโนโลยีทั้งหมดที่ยังเหลือรอด\n\n\n[gray]อย่าประมาทกับฐานทัพศัตรูที่อยู่ใกล้ๆ โดยอันขาด\nศัตรูจะส่งกองกำลังมาโจมตีเรื่อยๆ จนกว่าคุณจะพ่ายแพ้
sector.planetaryTerminal.description = เป้าหมายสุดท้าย\n\nฐานทัพติดชายหาดนี้มีสิ่งประดิษฐ์ที่สามารถส่งแกนกลางไปยังดาวที่อยู่ใกล้ๆ ได้ ฐานทัพมีการป้องกันที่แน่นหนามาก\n\nผลิตยูนิตเรือ กวาดล้างศัตรูให้เร็วที่สุด วิจัยสิ่งประดิษฐ์นั่น sector.planetaryTerminal.description = เป้าหมายสุดท้าย\n\nฐานทัพติดชายหาดนี้มีสิ่งประดิษฐ์ที่สามารถส่งแกนกลางไปยังดาวที่อยู่ใกล้ๆ ได้ ฐานทัพมีการป้องกันที่แน่นหนามาก\n\nผลิตยูนิตเรือ กวาดล้างศัตรูให้เร็วที่สุด วิจัยสิ่งประดิษฐ์นั่น
status.burning.name = เผาไหม้ status.burning.name = เผาไหม้
@@ -649,6 +660,7 @@ status.sapped.name = อ่อนกำลัง
status.electrified.name = ช็อตไฟฟ้า status.electrified.name = ช็อตไฟฟ้า
status.spore-slowed.name = สปอร์สโลว์ status.spore-slowed.name = สปอร์สโลว์
status.tarred.name = เปื้อนน้ำมัน status.tarred.name = เปื้อนน้ำมัน
status.overdrive.name = โอเวอร์ไดรฟ์
status.overclock.name = โอเวอร์คล็อก status.overclock.name = โอเวอร์คล็อก
status.shocked.name = ช็อก status.shocked.name = ช็อก
status.blasted.name = ระเบิด status.blasted.name = ระเบิด
@@ -665,7 +677,7 @@ settings.game = เกม
settings.sound = เสียง settings.sound = เสียง
settings.graphics = กราฟิก settings.graphics = กราฟิก
settings.cleardata = เคลียร์ข้อมูลเกม... settings.cleardata = เคลียร์ข้อมูลเกม...
settings.clear.confirm = คุณแน่ใจหรือว่าจะเคลียร์ข้อมูลเกม?\nสิ่งที่ทำไปแล้วจะไม่สามารถย้อนกลับได้! settings.clear.confirm = คุณแน่ใจหรือว่าจะเคลียร์ข้อมูลนี้?\nสิ่งที่ทำไปแล้วจะไม่สามารถย้อนกลับได้นะ!
settings.clearall.confirm = [scarlet]คำเตือน![]\nการกระทำนี้จะลบข้อมูลทั้งหมด นั้นรวมไปถึงเซฟ แมพ การวิจัยแล้วและก็ปุ่มควบคุม\nเมื่อคุณกด 'โอเค' เกมจะลบข้อมูลทุกอย่างและออกโดยอัตโนมัติ settings.clearall.confirm = [scarlet]คำเตือน![]\nการกระทำนี้จะลบข้อมูลทั้งหมด นั้นรวมไปถึงเซฟ แมพ การวิจัยแล้วและก็ปุ่มควบคุม\nเมื่อคุณกด 'โอเค' เกมจะลบข้อมูลทุกอย่างและออกโดยอัตโนมัติ
settings.clearsaves.confirm = คุณแน่ใจหรือว่าคุณต้องการเคลียร์เซฟทั้งหมด? settings.clearsaves.confirm = คุณแน่ใจหรือว่าคุณต้องการเคลียร์เซฟทั้งหมด?
settings.clearsaves = เคลียร์เซฟ settings.clearsaves = เคลียร์เซฟ
@@ -683,7 +695,7 @@ info.title = ข้อมูล
error.title = [crimson]มีบางอย่างผิดพลาดเกิดขึ้น error.title = [crimson]มีบางอย่างผิดพลาดเกิดขึ้น
error.crashtitle = มีบางอย่างผิดพลาดเกิดขึ้น error.crashtitle = มีบางอย่างผิดพลาดเกิดขึ้น
unit.nobuild = [scarlet]ยูนิตนี้ไม่สามารถสร้างได้ unit.nobuild = [scarlet]ยูนิตนี้ไม่สามารถสร้างได้
lastaccessed = [lightgray]:คนที่แตะเป็นคนสุดท้าย {0} lastaccessed = [lightgray]คนสุดท้ายที่แตะ: {0}
block.unknown = [lightgray]??? block.unknown = [lightgray]???
stat.showinmap = <โหลดแมพเพื่อแสดง> stat.showinmap = <โหลดแมพเพื่อแสดง>
@@ -1151,6 +1163,7 @@ block.core-nucleus.name = แกนกลาง: นิวเคลียส
block.deep-water.name = น้ำลึก block.deep-water.name = น้ำลึก
block.shallow-water.name = น้ำตื้น block.shallow-water.name = น้ำตื้น
block.tainted-water.name = น้ำเสีย block.tainted-water.name = น้ำเสีย
block.deep-tainted-water.name = น้ำเสียลึก
block.darksand-tainted-water.name = น้ำเสียบนทรายดำ block.darksand-tainted-water.name = น้ำเสียบนทรายดำ
block.tar.name = น้ำมันดิน block.tar.name = น้ำมันดิน
block.stone.name = หิน block.stone.name = หิน
@@ -1384,6 +1397,7 @@ hint.generator = \uf879 [accent]เครื่องกำเนิดไฟฟ
hint.guardian = หน่วย[accent]ผู้พิทักษ์[]มีเกราะป้องกันหนาแน่น กระสุนเปราะบางอย่าง[accent]ทองแดง[]และ[accent]ตะกั่ว[][scarlet]ไม่มีประสิทธิภาพ[]\n\nควรใช้ป้อมปืนที่ดีกว่านี้หรือใช้ \uf835 [accent]กราไฟท์[]ใส่ใน \uf861 ดูโอ/ \uf859 ซัลโวเป็นกระสุนเพื่อทำลายผู้พิทักษ์ hint.guardian = หน่วย[accent]ผู้พิทักษ์[]มีเกราะป้องกันหนาแน่น กระสุนเปราะบางอย่าง[accent]ทองแดง[]และ[accent]ตะกั่ว[][scarlet]ไม่มีประสิทธิภาพ[]\n\nควรใช้ป้อมปืนที่ดีกว่านี้หรือใช้ \uf835 [accent]กราไฟท์[]ใส่ใน \uf861 ดูโอ/ \uf859 ซัลโวเป็นกระสุนเพื่อทำลายผู้พิทักษ์
hint.coreUpgrade = สามารถอัปเกรดแกนกลางได้โดย[accent]วางแกนกลางที่ใหญ่กว่าทับมัน[]\n\nวาง  [accent]แกนกลาง: ฟาวน์เดชั่น[]ทับ  [accent]แกนกลาง: ชาร์ด[] ต้องแน่ใจว่ารอบข้างมีที่ว่างก่อนจะวาง hint.coreUpgrade = สามารถอัปเกรดแกนกลางได้โดย[accent]วางแกนกลางที่ใหญ่กว่าทับมัน[]\n\nวาง  [accent]แกนกลาง: ฟาวน์เดชั่น[]ทับ  [accent]แกนกลาง: ชาร์ด[] ต้องแน่ใจว่ารอบข้างมีที่ว่างก่อนจะวาง
hint.presetLaunch = [accent]เซ็กเตอร์ลงจอด[]สีเทา อย่างเช่น[accent]ป่าหนาวเหน็บ[] สามารถลงจอดจากที่ไหนที่ได้ในแผนที่ พวกนั้นไม่จำเป็นต้องยืดครองเซ็กเตอร์รอบข้างเพื่อส่งแกนกลางไป\n\n[accent]เซ็กเตอร์ที่มีเลข[] อย่างเช่นอันนี้[accent]ไม่จำเป็น[]ต้องยืดครอง hint.presetLaunch = [accent]เซ็กเตอร์ลงจอด[]สีเทา อย่างเช่น[accent]ป่าหนาวเหน็บ[] สามารถลงจอดจากที่ไหนที่ได้ในแผนที่ พวกนั้นไม่จำเป็นต้องยืดครองเซ็กเตอร์รอบข้างเพื่อส่งแกนกลางไป\n\n[accent]เซ็กเตอร์ที่มีเลข[] อย่างเช่นอันนี้[accent]ไม่จำเป็น[]ต้องยืดครอง
hint.presetDifficulty = เซ็กเตอร์นี้มี[scarlet]ระดับภัยคุกคามศัตรูสูง[]\n[accent]ไม่แนะนำ[]ให้ลงจอดไปยังเซ็กเซอร์พวกนั้นหากไม่มีการเตรียมพร้อมและเทคโนโลยี
hint.coreIncinerate = เมื่อแกนกลางมีจำนวนไอเท็มชนิดหนึ่งที่เต็ม ไอเท็มชนิดนั้นที่เข้ามาเพิ่มจะ[accent]ถูกเผา[] hint.coreIncinerate = เมื่อแกนกลางมีจำนวนไอเท็มชนิดหนึ่งที่เต็ม ไอเท็มชนิดนั้นที่เข้ามาเพิ่มจะ[accent]ถูกเผา[]
hint.coopCampaign = ตอนที่เล่น[accent]แคมเปญร่วมกัน[]กับเพื่อน ไอเท็มที่ผลิตในแมพนี้จะถูกส่ง[accent]ไปยังเซ็กเตอร์ของคุณด้วย[]\n\nการวิจัยใหม่ที่โฮสต์ได้วิจัยก็เก็บเป็นของคุณด้วย hint.coopCampaign = ตอนที่เล่น[accent]แคมเปญร่วมกัน[]กับเพื่อน ไอเท็มที่ผลิตในแมพนี้จะถูกส่ง[accent]ไปยังเซ็กเตอร์ของคุณด้วย[]\n\nการวิจัยใหม่ที่โฮสต์ได้วิจัยก็เก็บเป็นของคุณด้วย
@@ -1761,12 +1775,12 @@ lenum.target = ยิงไปที่ตำแหน่งเป้าหม
lenum.targetp = ยิงเป้าหมายโดยมีการคำนวณความเร็ว lenum.targetp = ยิงเป้าหมายโดยมีการคำนวณความเร็ว
lenum.itemdrop = ปล่อยไอเท็ม lenum.itemdrop = ปล่อยไอเท็ม
lenum.itemtake = หยิบไอเท็มจากสิ่งก่อสร้าง lenum.itemtake = หยิบไอเท็มจากสิ่งก่อสร้าง
lenum.paydrop = ปล่อยของที่บรรทุกอยู่ lenum.paydrop = ปล่อยสิ่งที่บรรทุกอยู่
lenum.paytake = หยิบของบรรทุกที่จุดที่อยู่ lenum.paytake = หยิบสิ่งบรรทุกจุดที่อยู่
lenum.flag = ปักธงยูนิตเป็นหมายเลข lenum.flag = ปักธงยูนิตเป็นหมายเลข
lenum.mine = ขุดที่ตำแหน่งเป้าหมาย lenum.mine = ขุดที่ตำแหน่งเป้าหมาย
lenum.build = สร้างสิ่งก่อสร้าง lenum.build = สร้างสิ่งก่อสร้าง
lenum.getblock = ดึงข้อมูลสิ่งก่อสร้างและประเภทสิ่งก่อสร้างที่ตำแหน่งเป้าหมาย\nหน่วยต้องอยู่ในช่วงของตำแหน่ง\nของแข็งที่ไม่ใช่สิ่งก่อสร้างจะส่งกลับเป็น [accent]@solid[] lenum.getblock = ดึงข้อมูลสิ่งก่อสร้างและประเภทสิ่งก่อสร้างที่ตำแหน่งเป้าหมาย\nหน่วยต้องอยู่ในช่วงของตำแหน่ง\nของแข็งที่ไม่ใช่สิ่งก่อสร้างจะส่งกลับเป็น [accent]@solid[]
lenum.within = ตรวจสอบว่ายูนิตอยู่ในระยะหรือไม่ lenum.within = ตรวจสอบว่ายูนิตอยู่ในระยะหรือไม่
lenum.boost = เริ่ม/หยุดการบูสต์ lenum.boost = เริ่ม/หยุดการบูสต์
#extra line: 18 => extra descriptions: 4+2 => extra details: (7+4)+1 #extra line: 16 => extra descriptions: 4 => extra details: (7+4)+1

View File

@@ -393,6 +393,13 @@ waves.load = Panodan yükle
waves.invalid = Panoda geçersiz dalga sayısı var. waves.invalid = Panoda geçersiz dalga sayısı var.
waves.copied = Dalgalar kopyalandı. waves.copied = Dalgalar kopyalandı.
waves.none = Düşman bulunamadı.\nBoş dalga düzenlerin otomatik olarak varsayılan düzenle değiştirileceğini unutmayın waves.none = Düşman bulunamadı.\nBoş dalga düzenlerin otomatik olarak varsayılan düzenle değiştirileceğini unutmayın
waves.sort = Sıralama Ölçeği:
waves.sort.reverse = Ters Sırala
waves.sort.begin = Başla
waves.sort.health = Can
waves.sort.type = Tür
waves.units.hide = Hepsini Gizle
waves.units.show = Hepsini Göster
#bunlar özellikle küçük başlıyor. #bunlar özellikle küçük başlıyor.
wavemode.counts = miktarlar wavemode.counts = miktarlar
@@ -621,6 +628,8 @@ sector.biomassFacility.name = Sentetik BioMadde Santrali
sector.windsweptIslands.name = Rüzgarlı Adalar sector.windsweptIslands.name = Rüzgarlı Adalar
sector.extractionOutpost.name = Kazı Üssü sector.extractionOutpost.name = Kazı Üssü
sector.planetaryTerminal.name = Gezegenler Arası Terminal sector.planetaryTerminal.name = Gezegenler Arası Terminal
sector.coastline.name = Kıyı Şeridi
sector.navalFortress.name = Deniz Kalesi
sector.groundZero.description = Yeniden başlamak için ideal bölge. Düşük düşman tehlikesi ve az miktarda kaynak mevcut. Mümkün olduğunca çok bakır ve kurşun topla.\nİlerle. sector.groundZero.description = Yeniden başlamak için ideal bölge. Düşük düşman tehlikesi ve az miktarda kaynak mevcut. Mümkün olduğunca çok bakır ve kurşun topla.\nİlerle.
sector.frozenForest.description = Burada, dağlara yakın bölgelerde bile sporlar etrafa yayıldı. Dondurucu soğuk onları sonsuza dek durduramaz.\n\nEnerji kullanmaya başla. Termik jeneratörler inşa et. Tamircileri kullanmayı öğren. sector.frozenForest.description = Burada, dağlara yakın bölgelerde bile sporlar etrafa yayıldı. Dondurucu soğuk onları sonsuza dek durduramaz.\n\nEnerji kullanmaya başla. Termik jeneratörler inşa et. Tamircileri kullanmayı öğren.
@@ -1382,6 +1391,7 @@ hint.generator = \uf879 [accent]Termik Jeneratör[] kömür yakarak enerji üret
hint.guardian = [accent]Gardiyan[] birimleri güçlü bir zırha sahiptir. [accent]bakır[] ve [accent]kurşun[] gibi mermilere karşı [scarlet]Dayanıklıdır[].\n\nGardiyanları öldürmek için [accent]salvo[] gibi daha güçlü taretleri ve \uf835 [accent]grafit[] gibi daha çok hasar veren mermileri kullanın. hint.guardian = [accent]Gardiyan[] birimleri güçlü bir zırha sahiptir. [accent]bakır[] ve [accent]kurşun[] gibi mermilere karşı [scarlet]Dayanıklıdır[].\n\nGardiyanları öldürmek için [accent]salvo[] gibi daha güçlü taretleri ve \uf835 [accent]grafit[] gibi daha çok hasar veren mermileri kullanın.
hint.coreUpgrade = Merkezinizi, [accent]merkezinizin üstüne daha gelişmiş bir merkez[] koyarak geliştirebilirsiniz. \n\n[accent]Parçacık[] olarak adlandırılan fakirhanenizin üstüne [accent]Temel[] olarak adlandırılan merkezinizi koyun. Merkezinizin etrafında hiçbir yapı olmamalıdır. hint.coreUpgrade = Merkezinizi, [accent]merkezinizin üstüne daha gelişmiş bir merkez[] koyarak geliştirebilirsiniz. \n\n[accent]Parçacık[] olarak adlandırılan fakirhanenizin üstüne [accent]Temel[] olarak adlandırılan merkezinizi koyun. Merkezinizin etrafında hiçbir yapı olmamalıdır.
hint.presetLaunch = [accent]Donmuş Ormanlar[] gibi [accent]ana sektörlere iniş[] herhangi bir yerden yapılabilir. Yakındaki bir sektörden fırlatma gerektirmez.\n\nBunun gibi [accent]sayı ile isimlendirilmiş[] sektörleri ele geçirmek [accent]isteğe bağlıdır.[]. hint.presetLaunch = [accent]Donmuş Ormanlar[] gibi [accent]ana sektörlere iniş[] herhangi bir yerden yapılabilir. Yakındaki bir sektörden fırlatma gerektirmez.\n\nBunun gibi [accent]sayı ile isimlendirilmiş[] sektörleri ele geçirmek [accent]isteğe bağlıdır.[].
hint.presetDifficulty = Bu sektör, [scarlet]yüksek tehlike[] barındırıyor.\nBöyle bir sektöre hazırlıksız fırlatış yapmak [accent]tavsiye edilmez[].
hint.coreIncinerate = Bir çekirdek ağzına kadar dolduktan sonra, ekstra itemler [accent]eritilir[]. hint.coreIncinerate = Bir çekirdek ağzına kadar dolduktan sonra, ekstra itemler [accent]eritilir[].
hint.coopCampaign = Arkadaşlarınla Multiplayer Campaign oynarken, her yaptığınız Araştırma ve item aktarımı, senin oyun içi Campaign ine de aktarılır. hint.coopCampaign = Arkadaşlarınla Multiplayer Campaign oynarken, her yaptığınız Araştırma ve item aktarımı, senin oyun içi Campaign ine de aktarılır.
#Yukarıdaki bağzı cümleler Anti Dragon tarafından çevirildi. #Yukarıdaki bağzı cümleler Anti Dragon tarafından çevirildi.

File diff suppressed because it is too large Load Diff

View File

@@ -78,13 +78,12 @@ schematic.tagexists = 該標籤已存在。
stats = 統計 stats = 統計
stat.wave = 打敗的波次:[accent]{0} stat.wave = 打敗的波次:[accent]{0}
stat.enemiesDestroyed = 摧毀的敵人[accent]{0} stat.unitsCreated = 建造單位數[accent] {0}
stat.enemiesDestroyed = 摧毀敵人數:[accent]{0}
stat.built = 建設的建築:[accent]{0} stat.built = 建設的建築:[accent]{0}
stat.destroyed = 摧毀的建築:[accent]{0} stat.destroyed = 摧毀的建築:[accent]{0}
stat.deconstructed = 拆除的建築:[accent]{0} stat.deconstructed = 拆除的建築:[accent]{0}
stat.delivered = 發射的核心資源:
stat.playtime = 遊玩時間:[accent] {0} stat.playtime = 遊玩時間:[accent] {0}
stat.rank = 最終排名:[accent]{0}
globalitems = [accent]全域物品 globalitems = [accent]全域物品
map.delete = 確認要刪除「[accent]{0}[]」地圖嗎? map.delete = 確認要刪除「[accent]{0}[]」地圖嗎?
@@ -93,7 +92,8 @@ level.select = 選擇關卡
level.mode = 遊戲模式: level.mode = 遊戲模式:
coreattack = 〈核心正在受到攻擊!〉 coreattack = 〈核心正在受到攻擊!〉
nearpoint = 【[scarlet]立即離開空降區[]】\n湮滅即將來臨 nearpoint = 【[scarlet]立即離開空降區[]】\n湮滅即將來臨
database = 核心數據 database = 核心資料
database.button = 資料庫
savegame = 儲存遊戲 savegame = 儲存遊戲
loadgame = 載入遊戲 loadgame = 載入遊戲
joingame = 多人連線 joingame = 多人連線
@@ -169,6 +169,7 @@ launchcore = 發射核心
filename = 檔案名稱︰ filename = 檔案名稱︰
unlocked = 已解鎖新內容! unlocked = 已解鎖新內容!
available = 可研究新科技! available = 可研究新科技!
unlock.incampaign = <在戰役中解鎖>
completed = [accent]完成 completed = [accent]完成
techtree = 科技樹 techtree = 科技樹
research.legacy = [accent]5.0[] 偵測到舊有科技資料。\n請問要[accent]載入[]資料,還是[accent]放棄[]並重置新戰役的科技樹(建議) research.legacy = [accent]5.0[] 偵測到舊有科技資料。\n請問要[accent]載入[]資料,還是[accent]放棄[]並重置新戰役的科技樹(建議)
@@ -345,9 +346,9 @@ custom = 自訂
builtin = 内建 builtin = 内建
map.delete.confirm = 確認要刪除地圖嗎?此動作無法復原! map.delete.confirm = 確認要刪除地圖嗎?此動作無法復原!
map.random = [accent]隨機地圖 map.random = [accent]隨機地圖
map.nospawn = 這個地圖沒有核心!請在編輯器中添加一個[accent]橘色[]的核心。 map.nospawn = 這個地圖沒有核心!請在編輯器中添加一個[#{0}]{1}[]的核心。
map.nospawn.pvp = 這個地圖沒有敵對核心讓玩家重生!請在編輯器中添加一個[scarlet]不是橘色[]的核心。 map.nospawn.pvp = 這個地圖沒有敵對核心讓玩家重生!請在編輯器中添加一個[scarlet]不是橘色[]的核心。
map.nospawn.attack = 這個地圖沒有敵人核心可以攻擊!請在編輯器中添加一個[scarlet]紅色[]的核心。 map.nospawn.attack = 這個地圖沒有敵人核心可以攻擊!請在編輯器中添加一個[#{0}]{1}[]的核心。
map.invalid = 地圖載入錯誤:地圖可能已經損毀。 map.invalid = 地圖載入錯誤:地圖可能已經損毀。
workshop.update = 更新項目 workshop.update = 更新項目
workshop.error = 擷取工作坊詳細資訊時出錯:{0} workshop.error = 擷取工作坊詳細資訊時出錯:{0}
@@ -385,7 +386,8 @@ waves.waves = 波次
waves.perspawn = 每次生成 waves.perspawn = 每次生成
waves.shields = 護盾/波次 waves.shields = 護盾/波次
waves.to = waves.to =
waves.guardian = 頭目 waves.max = 最大單位數
waves.guardian = 守衛者
waves.preview = 預覽 waves.preview = 預覽
waves.edit = 編輯…… waves.edit = 編輯……
waves.copy = 複製到剪貼簿 waves.copy = 複製到剪貼簿
@@ -393,6 +395,11 @@ waves.load = 從剪貼簿載入
waves.invalid = 剪貼簿中的波次無效。 waves.invalid = 剪貼簿中的波次無效。
waves.copied = 波次已複製。 waves.copied = 波次已複製。
waves.none = 無自訂敵人。\n請注意若沒有波次佈局將自動替換為預設佈局。 waves.none = 無自訂敵人。\n請注意若沒有波次佈局將自動替換為預設佈局。
waves.sort = 分類排序:
waves.sort.reverse = 反向排序
waves.sort.begin = 開始
waves.sort.health = 血量
waves.sort.type = 兵種
#校正用空行 #校正用空行
wavemode.counts = 數量 wavemode.counts = 數量
@@ -564,6 +571,8 @@ weather.sandstorm.name = 沙塵暴
weather.sporestorm.name = 孢子風暴 weather.sporestorm.name = 孢子風暴
weather.fog.name = weather.fog.name =
sectorlist = 地區
sectorlist.attacked = {0} 遭受攻擊
sectors.unexplored = [lightgray]未探索 sectors.unexplored = [lightgray]未探索
sectors.resources = 資源: sectors.resources = 資源:
sectors.production = 生產: sectors.production = 生產:
@@ -646,10 +655,12 @@ status.sapped.name = 被吸血
status.electrified.name = 觸電 status.electrified.name = 觸電
status.spore-slowed.name = 孢子緩速 status.spore-slowed.name = 孢子緩速
status.tarred.name = 焦油 status.tarred.name = 焦油
status.overdrive.name = 超載
status.overclock.name = 快轉 status.overclock.name = 快轉
status.shocked.name = 電擊 status.shocked.name = 電擊
status.blasted.name = 爆炸 status.blasted.name = 爆炸
status.unmoving.name = 立定 status.unmoving.name = 立定
status.boss.name = 守衛者
settings.language = 語言 settings.language = 語言
settings.data = 遊戲資料 settings.data = 遊戲資料
@@ -1001,6 +1012,7 @@ rules.wavetimer = 波次時間
rules.waves = 波次 rules.waves = 波次
rules.attack = 攻擊模式 rules.attack = 攻擊模式
rules.buildai = 電腦自動建築 rules.buildai = 電腦自動建築
rules.aitier = AI 等級
rules.cleanupdeadteams = 移除戰敗玩家的建築(對戰) rules.cleanupdeadteams = 移除戰敗玩家的建築(對戰)
rules.corecapture = 佔領摧毀的核心 rules.corecapture = 佔領摧毀的核心
rules.polygoncoreprotection = 核心禁築區呈多邊形 rules.polygoncoreprotection = 核心禁築區呈多邊形
@@ -1020,12 +1032,15 @@ rules.deconstructrefundmultiplier = 拆除資源返還比例
rules.waitForWaveToEnd = 等待所有敵人毀滅才開始下一波次 rules.waitForWaveToEnd = 等待所有敵人毀滅才開始下一波次
rules.dropzoneradius = 空降區半徑:[lightgray](格) rules.dropzoneradius = 空降區半徑:[lightgray](格)
rules.unitammo = 單位需要彈藥 rules.unitammo = 單位需要彈藥
rules.enemyteam = 敵方隊伍
rules.playerteam = 玩家隊伍
rules.title.waves = 波次 rules.title.waves = 波次
rules.title.resourcesbuilding = 資源與建築 rules.title.resourcesbuilding = 資源與建築
rules.title.enemy = 敵人 rules.title.enemy = 敵人
rules.title.unit = 單位 rules.title.unit = 單位
rules.title.experimental = 實驗中 rules.title.experimental = 實驗中
rules.title.environment = 環境 rules.title.environment = 環境
rules.title.teams = 分隊
rules.lighting = 光照 rules.lighting = 光照
rules.enemyLights = 敵方發光 rules.enemyLights = 敵方發光
rules.fire = rules.fire =
@@ -1432,6 +1447,8 @@ block.item-source.description = 無限輸出物品。僅限沙盒。
block.item-void.description = 不使用能量銷毀任何進入它的物品。僅限沙盒。 block.item-void.description = 不使用能量銷毀任何進入它的物品。僅限沙盒。
block.liquid-source.description = 無限輸出液體。僅限沙盒。 block.liquid-source.description = 無限輸出液體。僅限沙盒。
block.liquid-void.description = 銷毀所有輸入的液體。僅限沙盒。 block.liquid-void.description = 銷毀所有輸入的液體。僅限沙盒。
block.payload-source.description = 無限輸出原料。僅限沙盒。
block.payload-void.description = 銷毀所有進入的原料。僅限沙盒。
block.copper-wall.description = 一種便宜的防禦方塊。\n用於前幾波防衛核心和砲塔。 block.copper-wall.description = 一種便宜的防禦方塊。\n用於前幾波防衛核心和砲塔。
block.copper-wall-large.description = 一種便宜的防禦方塊。\n用於前幾波防禦核心和砲塔\n佔據多個方塊。 block.copper-wall-large.description = 一種便宜的防禦方塊。\n用於前幾波防禦核心和砲塔\n佔據多個方塊。
block.titanium-wall.description = 一個中等強度的防禦方塊。\n提供對敵人的適度保護。 block.titanium-wall.description = 一個中等強度的防禦方塊。\n提供對敵人的適度保護。

View File

@@ -127,3 +127,4 @@ WilloIzCitron
SAMBUYYA SAMBUYYA
genNAowl genNAowl
TranquillyUnpleasant TranquillyUnpleasant
Darkness6030

View File

@@ -1,6 +1,6 @@
63743=spawn|block-spawn-ui 63743=spawn|block-spawn-ui
63742=deepwater|block-deepwater-ui 63742=deepwater|block-deepwater-ui
63741=water|block-water-ui 63741=shallow-water|block-shallow-water-ui
63740=tainted-water|block-tainted-water-ui 63740=tainted-water|block-tainted-water-ui
63739=darksand-tainted-water|block-darksand-tainted-water-ui 63739=darksand-tainted-water|block-darksand-tainted-water-ui
63738=sand-water|block-sand-water-ui 63738=sand-water|block-sand-water-ui
@@ -357,6 +357,6 @@
63357=crux|team-crux 63357=crux|team-crux
63358=derelict|team-derelict 63358=derelict|team-derelict
63350=deep-water|block-deep-water-ui 63350=deep-water|block-deep-water-ui
63349=shallow-water|block-shallow-water-ui
63348=molten-slag|block-molten-slag-ui 63348=molten-slag|block-molten-slag-ui
63347=crater-stone|block-crater-stone-ui 63347=crater-stone|block-crater-stone-ui
63346=deep-tainted-water|block-deep-tainted-water-ui

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -56,6 +56,9 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
Log.info("[GL] Using @ context.", gl30 != null ? "OpenGL 3" : "OpenGL 2"); Log.info("[GL] Using @ context.", gl30 != null ? "OpenGL 3" : "OpenGL 2");
if(maxTextureSize < 4096) Log.warn("[GL] Your maximum texture size is below the recommended minimum of 4096. This will cause severe performance issues."); if(maxTextureSize < 4096) Log.warn("[GL] Your maximum texture size is below the recommended minimum of 4096. This will cause severe performance issues.");
Log.info("[JAVA] Version: @", OS.javaVersion); Log.info("[JAVA] Version: @", OS.javaVersion);
long ram = Runtime.getRuntime().maxMemory();
boolean gb = ram >= 1024 * 1024 * 1024;
Log.info("[RAM] Available: @ @", Strings.fixed(gb ? ram / 1024f / 1024 / 1024f : ram / 1024f / 1024f, 1), gb ? "GB" : "MB");
Time.setDeltaProvider(() -> { Time.setDeltaProvider(() -> {
float result = Core.graphics.getDeltaTime() * 60f; float result = Core.graphics.getDeltaTime() * 60f;
@@ -83,7 +86,7 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
Fonts.loadDefaultFont(); Fonts.loadDefaultFont();
//load fallback atlas if max texture size is below 4096 //load fallback atlas if max texture size is below 4096
assets.load(new AssetDescriptor<>(maxTextureSize >= 4096 ? "sprites/sprites.aatls" : "sprites/fallback/sprites.aatls", TextureAtlas.class)).loaded = t -> atlas = (TextureAtlas)t; assets.load(new AssetDescriptor<>(maxTextureSize >= 4096 ? "sprites/sprites.aatls" : "sprites/fallback/sprites.aatls", TextureAtlas.class)).loaded = t -> atlas = t;
assets.loadRun("maps", Map.class, () -> maps.loadPreviews()); assets.loadRun("maps", Map.class, () -> maps.loadPreviews());
Musics.load(); Musics.load();

View File

@@ -45,7 +45,7 @@ public class Vars implements Loadable{
/** Name of current Steam player. */ /** Name of current Steam player. */
public static String steamPlayerName = ""; public static String steamPlayerName = "";
/** Default accessible content types used for player-selectable icons. */ /** Default accessible content types used for player-selectable icons. */
public static final ContentType[] defaultContentIcons = {ContentType.item, ContentType.liquid, ContentType.block}; public static final ContentType[] defaultContentIcons = {ContentType.item, ContentType.liquid, ContentType.block, ContentType.unit};
/** Wall darkness radius. */ /** Wall darkness radius. */
public static final int darkRadius = 4; public static final int darkRadius = 4;
/** Maximum extra padding around deployment schematics. */ /** Maximum extra padding around deployment schematics. */

View File

@@ -12,6 +12,7 @@ import mindustry.game.*;
import mindustry.game.Schematic.*; import mindustry.game.Schematic.*;
import mindustry.game.Teams.*; import mindustry.game.Teams.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.maps.generators.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.defense.*; import mindustry.world.blocks.defense.*;
@@ -25,7 +26,6 @@ import static mindustry.Vars.*;
public class BaseAI{ public class BaseAI{
private static final Vec2 axis = new Vec2(), rotator = new Vec2(); private static final Vec2 axis = new Vec2(), rotator = new Vec2();
private static final float correctPercent = 0.5f;
private static final int attempts = 4; private static final int attempts = 4;
private static final float emptyChance = 0.01f; private static final float emptyChance = 0.01f;
private static final int timerStep = 0, timerSpawn = 1, timerRefreshPath = 2; private static final int timerStep = 0, timerSpawn = 1, timerRefreshPath = 2;
@@ -46,6 +46,7 @@ public class BaseAI{
boolean calculating, startedCalculating; boolean calculating, startedCalculating;
int calcCount = 0; int calcCount = 0;
int totalCalcs = 0; int totalCalcs = 0;
Block wallType;
public BaseAI(TeamData data){ public BaseAI(TeamData data){
this.data = data; this.data = data;
@@ -53,6 +54,10 @@ public class BaseAI{
public void update(){ public void update(){
if(wallType == null){
wallType = BaseGenerator.getDifficultyWall(1, data.team.rules().aiTier / 0.8f);
}
if(data.team.rules().aiCoreSpawn && timer.get(timerSpawn, 60 * 2.5f) && data.hasCore()){ if(data.team.rules().aiCoreSpawn && timer.get(timerSpawn, 60 * 2.5f) && data.hasCore()){
CoreBlock block = (CoreBlock)data.core().block; CoreBlock block = (CoreBlock)data.core().block;
int coreUnits = Groups.unit.count(u -> u.team == data.team && u.type == block.unitType); int coreUnits = Groups.unit.count(u -> u.team == data.team && u.type == block.unitType);
@@ -89,7 +94,7 @@ public class BaseAI{
calculating = false; calculating = false;
} }
}else{ }else{
var field = pathfinder.getField(state.rules.waveTeam, Pathfinder.costGround, Pathfinder.fieldCore); var field = pathfinder.getField(data.team, Pathfinder.costGround, Pathfinder.fieldCore);
if(field.weights != null){ if(field.weights != null){
int[][] weights = field.weights; int[][] weights = field.weights;
@@ -120,7 +125,7 @@ public class BaseAI{
} }
//found the end. //found the end.
if(calcTile.build instanceof CoreBuild b && b.team == state.rules.defaultTeam){ if(calcTile.build instanceof CoreBuild b && b.team != data.team){
//clean up calculations and flush results //clean up calculations and flush results
calculating = false; calculating = false;
calcCount = 0; calcCount = 0;
@@ -271,7 +276,7 @@ public class BaseAI{
} }
private void tryWalls(){ private void tryWalls(){
Block wall = Blocks.copperWall; Block wall = wallType;
Building spawnt = state.rules.defaultTeam.core() != null ? state.rules.defaultTeam.core() : data.team.core(); Building spawnt = state.rules.defaultTeam.core() != null ? state.rules.defaultTeam.core() : data.team.core();
Tile spawn = spawnt == null ? null : spawnt.tile; Tile spawn = spawnt == null ? null : spawnt.tile;

View File

@@ -50,10 +50,12 @@ public class BlockIndexer{
clearFlags(); clearFlags();
Events.on(TilePreChangeEvent.class, event -> { Events.on(TilePreChangeEvent.class, event -> {
if(state.isEditor()) return;
removeIndex(event.tile); removeIndex(event.tile);
}); });
Events.on(TileChangeEvent.class, event -> { Events.on(TileChangeEvent.class, event -> {
if(state.isEditor()) return;
addIndex(event.tile); addIndex(event.tile);
}); });
@@ -109,7 +111,7 @@ public class BlockIndexer{
} }
} }
//update the unit cap when building is remove //update the unit cap when building is removed
data.unitCap -= tile.block().unitCapModifier; data.unitCap -= tile.block().unitCapModifier;
//unregister building from building quadtree //unregister building from building quadtree

View File

@@ -138,7 +138,7 @@ public class Pathfinder implements Runnable{
/** Starts or restarts the pathfinding thread. */ /** Starts or restarts the pathfinding thread. */
private void start(){ private void start(){
stop(); stop();
thread = Threads.daemon(this); thread = Threads.daemon("Pathfinder", this);
} }
/** Stops the pathfinding thread. */ /** Stops the pathfinding thread. */

View File

@@ -56,7 +56,7 @@ public class WaveSpawner{
public void spawnEnemies(){ public void spawnEnemies(){
spawning = true; spawning = true;
eachGroundSpawn((spawnX, spawnY, doShockwave) -> { eachGroundSpawn(-1, (spawnX, spawnY, doShockwave) -> {
if(doShockwave){ if(doShockwave){
doShockwave(spawnX, spawnY); doShockwave(spawnX, spawnY);
} }
@@ -70,7 +70,7 @@ public class WaveSpawner{
if(group.type.flying){ if(group.type.flying){
float spread = margin / 1.5f; float spread = margin / 1.5f;
eachFlyerSpawn((spawnX, spawnY) -> { eachFlyerSpawn(group.spawn, (spawnX, spawnY) -> {
for(int i = 0; i < spawned; i++){ for(int i = 0; i < spawned; i++){
Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1); Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1);
unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread)); unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread));
@@ -80,7 +80,7 @@ public class WaveSpawner{
}else{ }else{
float spread = tilesize * 2; float spread = tilesize * 2;
eachGroundSpawn((spawnX, spawnY, doShockwave) -> { eachGroundSpawn(group.spawn, (spawnX, spawnY, doShockwave) -> {
for(int i = 0; i < spawned; i++){ for(int i = 0; i < spawned; i++){
Tmp.v1.rnd(spread); Tmp.v1.rnd(spread);
@@ -102,12 +102,14 @@ public class WaveSpawner{
} }
public void eachGroundSpawn(Intc2 cons){ public void eachGroundSpawn(Intc2 cons){
eachGroundSpawn((x, y, shock) -> cons.get(World.toTile(x), World.toTile(y))); eachGroundSpawn(-1, (x, y, shock) -> cons.get(World.toTile(x), World.toTile(y)));
} }
private void eachGroundSpawn(SpawnConsumer cons){ private void eachGroundSpawn(int filterPos, SpawnConsumer cons){
if(state.hasSpawns()){ if(state.hasSpawns()){
for(Tile spawn : spawns){ for(Tile spawn : spawns){
if(filterPos != -1 && filterPos != spawn.pos()) continue;
cons.accept(spawn.worldx(), spawn.worldy(), true); cons.accept(spawn.worldx(), spawn.worldy(), true);
} }
} }
@@ -115,6 +117,8 @@ public class WaveSpawner{
if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam) && !state.teams.playerCores().isEmpty()){ if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam) && !state.teams.playerCores().isEmpty()){
Building firstCore = state.teams.playerCores().first(); Building firstCore = state.teams.playerCores().first();
for(Building core : state.rules.waveTeam.cores()){ for(Building core : state.rules.waveTeam.cores()){
if(filterPos != -1 && filterPos != core.pos()) continue;
Tmp.v1.set(firstCore).sub(core).limit(coreMargin + core.block.size * tilesize /2f * Mathf.sqrt2); Tmp.v1.set(firstCore).sub(core).limit(coreMargin + core.block.size * tilesize /2f * Mathf.sqrt2);
boolean valid = false; boolean valid = false;
@@ -147,8 +151,10 @@ public class WaveSpawner{
} }
} }
private void eachFlyerSpawn(Floatc2 cons){ private void eachFlyerSpawn(int filterPos, Floatc2 cons){
for(Tile tile : spawns){ for(Tile tile : spawns){
if(filterPos != -1 && filterPos != tile.pos()) continue;
float angle = Angles.angle(world.width() / 2f, world.height() / 2f, tile.x, tile.y); float angle = Angles.angle(world.width() / 2f, world.height() / 2f, tile.x, tile.y);
float trns = Math.max(world.width(), world.height()) * Mathf.sqrt2 * tilesize; float trns = Math.max(world.width(), world.height()) * Mathf.sqrt2 * tilesize;
float spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(angle, trns), -margin, world.width() * tilesize + margin); float spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(angle, trns), -margin, world.width() * tilesize + margin);
@@ -158,6 +164,8 @@ public class WaveSpawner{
if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam)){ if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam)){
for(Building core : state.rules.waveTeam.data().cores){ for(Building core : state.rules.waveTeam.data().cores){
if(filterPos != -1 && filterPos != core.pos()) continue;
cons.get(core.x, core.y); cons.get(core.x, core.y);
} }
} }
@@ -171,7 +179,7 @@ public class WaveSpawner{
public int countFlyerSpawns(){ public int countFlyerSpawns(){
tmpCount = 0; tmpCount = 0;
eachFlyerSpawn((x, y) -> tmpCount ++); eachFlyerSpawn(-1, (x, y) -> tmpCount ++);
return tmpCount; return tmpCount;
} }
@@ -196,6 +204,7 @@ public class WaveSpawner{
unit.apply(StatusEffects.invincible, 60f); unit.apply(StatusEffects.invincible, 60f);
unit.add(); unit.add();
Events.fire(new UnitSpawnEvent(unit));
Call.spawnEffect(unit.x, unit.y, unit.rotation, unit.type); Call.spawnEffect(unit.x, unit.y, unit.rotation, unit.type);
} }

View File

@@ -179,7 +179,7 @@ public class SoundControl{
float avol = Core.settings.getInt("ambientvol", 100) / 100f; float avol = Core.settings.getInt("ambientvol", 100) / 100f;
sounds.each((sound, data) -> { sounds.each((sound, data) -> {
data.curVolume = Mathf.lerpDelta(data.curVolume, data.volume * avol, 0.2f); data.curVolume = Mathf.lerpDelta(data.curVolume, data.volume * avol, 0.11f);
boolean play = data.curVolume > 0.01f; boolean play = data.curVolume > 0.01f;
float pan = Mathf.zero(data.total, 0.0001f) ? 0f : sound.calcPan(data.sum.x / data.total, data.sum.y / data.total); float pan = Mathf.zero(data.total, 0.0001f) ? 0f : sound.calcPan(data.sum.x / data.total, data.sum.y / data.total);

View File

@@ -35,7 +35,7 @@ public class Blocks implements ContentList{
public static Block public static Block
//environment //environment
air, spawn, cliff, deepwater, water, taintedWater, tar, slag, stone, craters, charr, sand, darksand, dirt, mud, ice, snow, darksandTaintedWater, space, air, spawn, cliff, deepwater, water, taintedWater, deepTaintedWater, tar, slag, stone, craters, charr, sand, darksand, dirt, mud, ice, snow, darksandTaintedWater, space,
dacite, dacite,
stoneWall, dirtWall, sporeWall, iceWall, daciteWall, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster, stoneWall, dirtWall, sporeWall, iceWall, daciteWall, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster,
iceSnow, sandWater, darksandWater, duneWall, sandWall, moss, sporeMoss, shale, shaleWall, shaleBoulder, sandBoulder, daciteBoulder, boulder, snowBoulder, basaltBoulder, grass, salt, iceSnow, sandWater, darksandWater, duneWall, sandWall, moss, sporeMoss, shale, shaleWall, shaleBoulder, sandBoulder, daciteBoulder, boulder, snowBoulder, basaltBoulder, grass, salt,
@@ -142,7 +142,19 @@ public class Blocks implements ContentList{
}}; }};
taintedWater = new Floor("tainted-water"){{ taintedWater = new Floor("tainted-water"){{
speedMultiplier = 0.17f; speedMultiplier = 0.5f;
variants = 0;
status = StatusEffects.wet;
statusDuration = 90f;
liquidDrop = Liquids.water;
isLiquid = true;
cacheLayer = CacheLayer.water;
albedo = 0.5f;
attributes.set(Attribute.spores, 0.15f);
}};
deepTaintedWater = new Floor("deep-tainted-water"){{
speedMultiplier = 0.18f;
variants = 0; variants = 0;
status = StatusEffects.wet; status = StatusEffects.wet;
statusDuration = 140f; statusDuration = 140f;
@@ -313,6 +325,7 @@ public class Blocks implements ContentList{
sporeWall = new StaticWall("spore-wall"){{ sporeWall = new StaticWall("spore-wall"){{
variants = 2; variants = 2;
taintedWater.asFloor().wall = deepTaintedWater.asFloor().wall = this;
}}; }};
dirtWall = new StaticWall("dirt-wall"){{ dirtWall = new StaticWall("dirt-wall"){{
@@ -429,7 +442,7 @@ public class Blocks implements ContentList{
Seq.with(metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor4, metalFloor5, darkPanel1, darkPanel2, darkPanel3, darkPanel4, darkPanel5, darkPanel6) Seq.with(metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor4, metalFloor5, darkPanel1, darkPanel2, darkPanel3, darkPanel4, darkPanel5, darkPanel6)
.each(b -> b.asFloor().wall = darkMetal); .each(b -> b.asFloor().wall = darkMetal);
pebbles = new DoubleOverlayFloor("pebbles"); pebbles = new OverlayFloor("pebbles");
tendrils = new OverlayFloor("tendrils"); tendrils = new OverlayFloor("tendrils");
@@ -609,7 +622,7 @@ public class Blocks implements ContentList{
rotate = false; rotate = false;
solid = true; solid = true;
outputsLiquid = true; outputsLiquid = true;
drawer = new DrawMixer(); drawer = new DrawMixer(true);
consumes.power(1f); consumes.power(1f);
consumes.item(Items.titanium); consumes.item(Items.titanium);
@@ -670,10 +683,10 @@ public class Blocks implements ContentList{
disassembler = new Separator("disassembler"){{ disassembler = new Separator("disassembler"){{
requirements(Category.crafting, with(Items.plastanium, 40, Items.titanium, 100, Items.silicon, 150, Items.thorium, 80)); requirements(Category.crafting, with(Items.plastanium, 40, Items.titanium, 100, Items.silicon, 150, Items.thorium, 80));
results = with( results = with(
Items.sand, 4, Items.sand, 2,
Items.graphite, 2, Items.graphite, 1,
Items.titanium, 2, Items.titanium, 1,
Items.thorium, 2 Items.thorium, 1
); );
hasPower = true; hasPower = true;
craftTime = 15f; craftTime = 15f;
@@ -1007,6 +1020,7 @@ public class Blocks implements ContentList{
distributor = new Router("distributor"){{ distributor = new Router("distributor"){{
requirements(Category.distribution, with(Items.lead, 4, Items.copper, 4)); requirements(Category.distribution, with(Items.lead, 4, Items.copper, 4));
buildCostMultiplier = 3f;
size = 2; size = 2;
}}; }};
@@ -1158,12 +1172,14 @@ public class Blocks implements ContentList{
battery = new Battery("battery"){{ battery = new Battery("battery"){{
requirements(Category.power, with(Items.copper, 5, Items.lead, 20)); requirements(Category.power, with(Items.copper, 5, Items.lead, 20));
consumes.powerBuffered(4000f); consumes.powerBuffered(4000f);
baseExplosiveness = 1f;
}}; }};
batteryLarge = new Battery("battery-large"){{ batteryLarge = new Battery("battery-large"){{
requirements(Category.power, with(Items.titanium, 20, Items.lead, 40, Items.silicon, 20)); requirements(Category.power, with(Items.titanium, 20, Items.lead, 40, Items.silicon, 20));
size = 3; size = 3;
consumes.powerBuffered(50000f); consumes.powerBuffered(50000f);
baseExplosiveness = 5f;
}}; }};
combustionGenerator = new BurnerGenerator("combustion-generator"){{ combustionGenerator = new BurnerGenerator("combustion-generator"){{
@@ -1888,7 +1904,7 @@ public class Blocks implements ContentList{
requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 80)); requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 80));
plans = Seq.with( plans = Seq.with(
new UnitPlan(UnitTypes.dagger, 60f * 15, with(Items.silicon, 10, Items.lead, 10)), new UnitPlan(UnitTypes.dagger, 60f * 15, with(Items.silicon, 10, Items.lead, 10)),
new UnitPlan(UnitTypes.crawler, 60f * 12, with(Items.silicon, 10, Items.coal, 20)), new UnitPlan(UnitTypes.crawler, 60f * 10, with(Items.silicon, 8, Items.coal, 10)),
new UnitPlan(UnitTypes.nova, 60f * 40, with(Items.silicon, 30, Items.lead, 20, Items.titanium, 20)) new UnitPlan(UnitTypes.nova, 60f * 40, with(Items.silicon, 30, Items.lead, 20, Items.titanium, 20))
); );
size = 3; size = 3;

View File

@@ -32,7 +32,9 @@ public class Fx{
//lifetime is how many frames it takes to fade out the trail //lifetime is how many frames it takes to fade out the trail
e.lifetime = trail.length * 1.4f; e.lifetime = trail.length * 1.4f;
if(!state.isPaused()){
trail.shorten(); trail.shorten();
}
trail.drawCap(e.color, e.rotation); trail.drawCap(e.color, e.rotation);
trail.draw(e.color, e.rotation); trail.draw(e.color, e.rotation);
}), }),

View File

@@ -10,7 +10,8 @@ public class SectorPresets implements ContentList{
groundZero, groundZero,
craters, biomassFacility, frozenForest, ruinousShores, windsweptIslands, stainedMountains, tarFields, craters, biomassFacility, frozenForest, ruinousShores, windsweptIslands, stainedMountains, tarFields,
fungalPass, extractionOutpost, saltFlats, overgrowth, fungalPass, extractionOutpost, saltFlats, overgrowth,
impact0078, desolateRift, nuclearComplex, planetaryTerminal; impact0078, desolateRift, nuclearComplex, planetaryTerminal,
coastline, navalFortress;
@Override @Override
public void load(){ public void load(){
@@ -64,6 +65,15 @@ public class SectorPresets implements ContentList{
useAI = false; useAI = false;
}}; }};
coastline = new SectorPreset("coastline", serpulo, 108){{
captureWave = 30;
difficulty = 5;
}};
navalFortress = new SectorPreset("navalFortress", serpulo, 216){{
difficulty = 9;
}};
fungalPass = new SectorPreset("fungalPass", serpulo, 21){{ fungalPass = new SectorPreset("fungalPass", serpulo, 21){{
difficulty = 4; difficulty = 4;
useAI = false; useAI = false;

View File

@@ -421,11 +421,11 @@ public class TechTree implements ContentList{
}); });
}); });
node(retusa, () -> { node(retusa, Seq.with(new SectorComplete(windsweptIslands)), () -> {
node(oxynoe, () -> { node(oxynoe, Seq.with(new SectorComplete(coastline)), () -> {
node(cyerce, () -> { node(cyerce, () -> {
node(aegires, () -> { node(aegires, () -> {
node(navanax, () -> { node(navanax, Seq.with(new SectorComplete(navalFortress)), () -> {
}); });
}); });
@@ -531,10 +531,25 @@ public class TechTree implements ContentList{
new Research(airFactory), new Research(airFactory),
new Research(door) new Research(door)
), () -> { ), () -> {
node(coastline, Seq.with(
new SectorComplete(windsweptIslands),
new Research(navalFactory),
new Research(payloadConveyor)
), () -> {
node(navalFortress, Seq.with(
new SectorComplete(coastline),
new SectorComplete(extractionOutpost),
new Research(oxynoe),
new Research(minke),
new Research(cyclone),
new Research(ripple)
), () -> {
}); });
}); });
}); });
});
});
node(overgrowth, Seq.with( node(overgrowth, Seq.with(
new SectorComplete(craters), new SectorComplete(craters),

View File

@@ -152,7 +152,7 @@ public class UnitTypes implements ContentList{
}}; }};
scepter = new UnitType("scepter"){{ scepter = new UnitType("scepter"){{
speed = 0.35f; speed = 0.36f;
hitSize = 22f; hitSize = 22f;
rotateSpeed = 2.1f; rotateSpeed = 2.1f;
health = 9000; health = 9000;
@@ -180,7 +180,7 @@ public class UnitTypes implements ContentList{
inaccuracy = 3f; inaccuracy = 3f;
shotDelay = 4f; shotDelay = 4f;
bullet = new BasicBulletType(7f, 45){{ bullet = new BasicBulletType(7f, 50){{
width = 11f; width = 11f;
height = 20f; height = 20f;
lifetime = 25f; lifetime = 25f;
@@ -189,7 +189,7 @@ public class UnitTypes implements ContentList{
lightningLength = 6; lightningLength = 6;
lightningColor = Pal.surge; lightningColor = Pal.surge;
//standard bullet damage is far too much for lightning //standard bullet damage is far too much for lightning
lightningDamage = 19; lightningDamage = 20;
}}; }};
}}, }},
@@ -238,7 +238,7 @@ public class UnitTypes implements ContentList{
ejectEffect = Fx.casing4; ejectEffect = Fx.casing4;
shootSound = Sounds.bang; shootSound = Sounds.bang;
bullet = new BasicBulletType(13f, 65){{ bullet = new BasicBulletType(13f, 70){{
pierce = true; pierce = true;
pierceCap = 10; pierceCap = 10;
width = 14f; width = 14f;
@@ -413,7 +413,7 @@ public class UnitTypes implements ContentList{
vela = new UnitType("vela"){{ vela = new UnitType("vela"){{
hitSize = 24f; hitSize = 24f;
rotateSpeed = 1.7f; rotateSpeed = 1.8f;
canDrown = false; canDrown = false;
mechFrontSway = 1f; mechFrontSway = 1f;
buildSpeed = 3f; buildSpeed = 3f;
@@ -423,7 +423,7 @@ public class UnitTypes implements ContentList{
ammoType = new PowerAmmoType(2500); ammoType = new PowerAmmoType(2500);
speed = 0.44f; speed = 0.44f;
boostMultiplier = 2.2f; boostMultiplier = 2.4f;
engineOffset = 12f; engineOffset = 12f;
engineSize = 6f; engineSize = 6f;
lowAltitude = true; lowAltitude = true;
@@ -436,6 +436,7 @@ public class UnitTypes implements ContentList{
immunities = ObjectSet.with(StatusEffects.burning); immunities = ObjectSet.with(StatusEffects.burning);
commandLimit = 8; commandLimit = 8;
singleTarget = true;
weapons.add(new Weapon("vela-weapon"){{ weapons.add(new Weapon("vela-weapon"){{
mirror = false; mirror = false;
@@ -479,6 +480,18 @@ public class UnitTypes implements ContentList{
shootStatus = StatusEffects.slow; shootStatus = StatusEffects.slow;
shootStatusDuration = bullet.lifetime + firstShotDelay; shootStatusDuration = bullet.lifetime + firstShotDelay;
}}); }});
weapons.add(new RepairBeamWeapon("repair-beam-weapon-center-large"){{
x = 44 / 4f;
y = -30f / 4f;
shootY = 6f;
beamWidth = 0.8f;
repairSpeed = 1.4f;
bullet = new BulletType(){{
maxRange = 120f;
}};
}});
}}; }};
corvus = new UnitType("corvus"){{ corvus = new UnitType("corvus"){{
@@ -1056,7 +1069,7 @@ public class UnitTypes implements ContentList{
rotateSpeed = 1.9f; rotateSpeed = 1.9f;
flying = true; flying = true;
lowAltitude = true; lowAltitude = true;
health = 7000; health = 7200;
armor = 9f; armor = 9f;
engineOffset = 21; engineOffset = 21;
engineSize = 5.3f; engineSize = 5.3f;
@@ -1064,13 +1077,13 @@ public class UnitTypes implements ContentList{
targetFlags = new BlockFlag[]{BlockFlag.generator, BlockFlag.core, null}; targetFlags = new BlockFlag[]{BlockFlag.generator, BlockFlag.core, null};
ammoType = new ItemAmmoType(Items.thorium); ammoType = new ItemAmmoType(Items.thorium);
BulletType missiles = new MissileBulletType(2.7f, 14){{ BulletType missiles = new MissileBulletType(2.7f, 18){{
width = 8f; width = 8f;
height = 8f; height = 8f;
shrinkY = 0f; shrinkY = 0f;
drag = -0.01f; drag = -0.01f;
splashDamageRadius = 20f; splashDamageRadius = 20f;
splashDamage = 34f; splashDamage = 37f;
ammoMultiplier = 4f; ammoMultiplier = 4f;
lifetime = 50f; lifetime = 50f;
hitEffect = Fx.blastExplosion; hitEffect = Fx.blastExplosion;
@@ -1125,13 +1138,13 @@ public class UnitTypes implements ContentList{
}}; }};
eclipse = new UnitType("eclipse"){{ eclipse = new UnitType("eclipse"){{
speed = 0.52f; speed = 0.54f;
accel = 0.04f; accel = 0.04f;
drag = 0.04f; drag = 0.04f;
rotateSpeed = 1f; rotateSpeed = 1f;
flying = true; flying = true;
lowAltitude = true; lowAltitude = true;
health = 21000; health = 22000;
engineOffset = 38; engineOffset = 38;
engineSize = 7.3f; engineSize = 7.3f;
hitSize = 58f; hitSize = 58f;
@@ -1140,10 +1153,10 @@ public class UnitTypes implements ContentList{
targetFlags = new BlockFlag[]{BlockFlag.reactor, BlockFlag.battery, BlockFlag.core, null}; targetFlags = new BlockFlag[]{BlockFlag.reactor, BlockFlag.battery, BlockFlag.core, null};
ammoType = new ItemAmmoType(Items.thorium); ammoType = new ItemAmmoType(Items.thorium);
BulletType fragBullet = new FlakBulletType(4f, 5){{ BulletType fragBullet = new FlakBulletType(4f, 15){{
shootEffect = Fx.shootBig; shootEffect = Fx.shootBig;
ammoMultiplier = 4f; ammoMultiplier = 4f;
splashDamage = 60f; splashDamage = 65f;
splashDamageRadius = 25f; splashDamageRadius = 25f;
collidesGround = true; collidesGround = true;
lifetime = 47f; lifetime = 47f;
@@ -1166,7 +1179,7 @@ public class UnitTypes implements ContentList{
rotate = true; rotate = true;
bullet = new LaserBulletType(){{ bullet = new LaserBulletType(){{
damage = 110f; damage = 115f;
sideAngle = 20f; sideAngle = 20f;
sideWidth = 1.5f; sideWidth = 1.5f;
sideLength = 80f; sideLength = 80f;
@@ -1335,7 +1348,7 @@ public class UnitTypes implements ContentList{
quad = new UnitType("quad"){{ quad = new UnitType("quad"){{
armor = 8f; armor = 8f;
health = 6000; health = 6000;
speed = 1.3f; speed = 1.2f;
rotateSpeed = 2f; rotateSpeed = 2f;
accel = 0.05f; accel = 0.05f;
drag = 0.017f; drag = 0.017f;
@@ -1444,7 +1457,7 @@ public class UnitTypes implements ContentList{
armor = 2f; armor = 2f;
weapons.add(new Weapon("mount-weapon"){{ weapons.add(new Weapon("mount-weapon"){{
reload = 12f; reload = 13f;
x = 4f; x = 4f;
shootY = 4f; shootY = 4f;
y = 1.5f; y = 1.5f;
@@ -1455,7 +1468,7 @@ public class UnitTypes implements ContentList{
weapons.add(new Weapon("missiles-mount"){{ weapons.add(new Weapon("missiles-mount"){{
mirror = false; mirror = false;
reload = 23f; reload = 25f;
x = 0f; x = 0f;
y = -5f; y = -5f;
rotate = true; rotate = true;
@@ -1567,15 +1580,14 @@ public class UnitTypes implements ContentList{
ejectEffect = Fx.casing3; ejectEffect = Fx.casing3;
shootSound = Sounds.artillery; shootSound = Sounds.artillery;
bullet = new ArtilleryBulletType(3.2f, 12){{ bullet = new ArtilleryBulletType(3.2f, 15){{
trailMult = 0.8f; trailMult = 0.8f;
hitEffect = Fx.massiveExplosion; hitEffect = Fx.massiveExplosion;
knockback = 1.5f; knockback = 1.5f;
lifetime = 80f; lifetime = 84f;
height = 15.5f; height = 15.5f;
width = 15f; width = 15f;
collidesTiles = false; collidesTiles = false;
ammoMultiplier = 4f;
splashDamageRadius = 40f; splashDamageRadius = 40f;
splashDamage = 70f; splashDamage = 70f;
backColor = Pal.missileYellowBack; backColor = Pal.missileYellowBack;

View File

@@ -8,8 +8,9 @@ import arc.struct.*;
import arc.util.*; import arc.util.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.ctype.*; import mindustry.ctype.*;
import mindustry.game.EventType.*;
import mindustry.entities.bullet.*; import mindustry.entities.bullet.*;
import mindustry.game.EventType.*;
import mindustry.io.*;
import mindustry.mod.Mods.*; import mindustry.mod.Mods.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.*; import mindustry.world.*;
@@ -211,10 +212,16 @@ public class ContentLoader{
} }
public <T extends MappableContent> T getByName(ContentType type, String name){ public <T extends MappableContent> T getByName(ContentType type, String name){
if(contentNameMap[type.ordinal()] == null){ var map = contentNameMap[type.ordinal()];
return null;
if(map == null) return null;
//load fallbacks
if(type == ContentType.block){
name = SaveVersion.modContentNameMap.get(name, name);
} }
return (T)contentNameMap[type.ordinal()].get(name);
return (T)map.get(name);
} }
public <T extends Content> T getByID(ContentType type, int id){ public <T extends Content> T getByID(ContentType type, int id){

View File

@@ -164,14 +164,14 @@ public class NetClient implements ApplicationListener{
public static void sound(Sound sound, float volume, float pitch, float pan){ public static void sound(Sound sound, float volume, float pitch, float pan){
if(sound == null) return; if(sound == null) return;
sound.play(volume * Core.settings.getInt("sfxvol") / 100f, pitch, pan); sound.play(Mathf.clamp(volume, 0, 4f) * Core.settings.getInt("sfxvol") / 100f, pitch, pan);
} }
@Remote(variants = Variant.both, unreliable = true) @Remote(variants = Variant.both, unreliable = true)
public static void soundAt(Sound sound, float x, float y, float volume, float pitch){ public static void soundAt(Sound sound, float x, float y, float volume, float pitch){
if(sound == null) return; if(sound == null) return;
sound.at(x, y, pitch, volume); sound.at(x, y, pitch, Mathf.clamp(volume, 0, 4f));
} }
@Remote(variants = Variant.both, unreliable = true) @Remote(variants = Variant.both, unreliable = true)

View File

@@ -896,7 +896,7 @@ public class NetServer implements ApplicationListener{
} }
String fixName(String name){ String fixName(String name){
name = name.trim(); name = name.trim().replace("\n", "").replace("\t", "");
if(name.equals("[") || name.equals("]")){ if(name.equals("[") || name.equals("]")){
return ""; return "";
} }

View File

@@ -114,7 +114,7 @@ public class Renderer implements ApplicationListener{
public void update(){ public void update(){
Color.white.set(1f, 1f, 1f, 1f); Color.white.set(1f, 1f, 1f, 1f);
float dest = Mathf.round(targetscale, 0.5f); float dest = Mathf.clamp(Mathf.round(targetscale, 0.5f), minScale(), maxScale());
camerascale = Mathf.lerpDelta(camerascale, dest, 0.1f); camerascale = Mathf.lerpDelta(camerascale, dest, 0.1f);
if(Mathf.equal(camerascale, dest, 0.001f)) camerascale = dest; if(Mathf.equal(camerascale, dest, 0.001f)) camerascale = dest;
laserOpacity = settings.getInt("lasersopacity") / 100f; laserOpacity = settings.getInt("lasersopacity") / 100f;
@@ -504,6 +504,8 @@ public class Renderer implements ApplicationListener{
public void showLaunch(CoreBlock coreType){ public void showLaunch(CoreBlock coreType){
Vars.ui.hudfrag.showLaunch(); Vars.ui.hudfrag.showLaunch();
Vars.control.input.frag.config.hideConfig();
Vars.control.input.frag.inv.hide();
launchCoreType = coreType; launchCoreType = coreType;
launching = true; launching = true;
landCore = player.team().core(); landCore = player.team().core();

View File

@@ -27,6 +27,8 @@ public abstract class UnlockableContent extends MappableContent{
public boolean alwaysUnlocked = false; public boolean alwaysUnlocked = false;
/** Whether to show the description in the research dialog preview. */ /** Whether to show the description in the research dialog preview. */
public boolean inlineDescription = true; public boolean inlineDescription = true;
/** Whether details of blocks are hidden in custom games if they haven't been unlocked in campaign mode. */
public boolean hideDetails = true;
/** Special logic icon ID. */ /** Special logic icon ID. */
public int iconId = 0; public int iconId = 0;
/** Icon of the content to use in UI. */ /** Icon of the content to use in UI. */

View File

@@ -18,7 +18,7 @@ import mindustry.world.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public class MapEditor{ public class MapEditor{
public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15, 20}; public static final float[] brushSizes = {1, 1.5f, 2, 3, 4, 5, 9, 15, 20};
public StringMap tags = new StringMap(); public StringMap tags = new StringMap();
public MapRenderer renderer = new MapRenderer(); public MapRenderer renderer = new MapRenderer();
@@ -28,7 +28,7 @@ public class MapEditor{
private DrawOperation currentOp; private DrawOperation currentOp;
private boolean loading; private boolean loading;
public int brushSize = 1; public float brushSize = 1;
public int rotation; public int rotation;
public Block drawBlock = Blocks.stone; public Block drawBlock = Blocks.stone;
public Team drawTeam = Team.sharded; public Team drawTeam = Team.sharded;
@@ -227,8 +227,9 @@ public class MapEditor{
} }
public void drawCircle(int x, int y, Cons<Tile> drawer){ public void drawCircle(int x, int y, Cons<Tile> drawer){
for(int rx = -brushSize; rx <= brushSize; rx++){ int clamped = (int)brushSize;
for(int ry = -brushSize; ry <= brushSize; ry++){ for(int rx = -clamped; rx <= clamped; rx++){
for(int ry = -clamped; ry <= clamped; ry++){
if(Mathf.within(rx, ry, brushSize - 0.5f + 0.0001f)){ if(Mathf.within(rx, ry, brushSize - 0.5f + 0.0001f)){
int wx = x + rx, wy = y + ry; int wx = x + rx, wy = y + ry;
@@ -243,8 +244,9 @@ public class MapEditor{
} }
public void drawSquare(int x, int y, Cons<Tile> drawer){ public void drawSquare(int x, int y, Cons<Tile> drawer){
for(int rx = -brushSize; rx <= brushSize; rx++){ int clamped = (int)brushSize;
for(int ry = -brushSize; ry <= brushSize; ry++){ for(int rx = -clamped; rx <= clamped; rx++){
for(int ry = -clamped; ry <= clamped; ry++){
int wx = x + rx, wy = y + ry; int wx = x + rx, wy = y + ry;
if(wx < 0 || wy < 0 || wx >= width() || wy >= height()){ if(wx < 0 || wy < 0 || wx >= width() || wy >= height()){

View File

@@ -576,13 +576,11 @@ public class MapEditorDialog extends Dialog implements Disposable{
}).growX().top(); }).growX().top();
} }
if(experimental){
mid.row(); mid.row();
mid.table(t -> { mid.table(t -> {
t.button("Cliffs", Icon.terrain, Styles.cleart, editor::addCliffs).growX().margin(9f); t.button("@editor.cliffs", Icon.terrain, Styles.cleart, editor::addCliffs).growX().margin(9f);
}).growX().top(); }).growX().top();
}
}).margin(0).left().growY(); }).margin(0).left().growY();

View File

@@ -10,6 +10,7 @@ import mindustry.content.*;
import mindustry.game.*; import mindustry.game.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.environment.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
@@ -132,6 +133,11 @@ public class MapRenderer implements Disposable{
wall.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, wall.editorVariantRegions().length - 1)] : wall.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, wall.editorVariantRegions().length - 1)] :
wall.editorIcon(); wall.editorIcon();
if(wall == Blocks.cliff){
mesh.setColor(Tmp.c1.set(floor.mapColor).mul(1.6f));
region = ((Cliff)Blocks.cliff).editorCliffs[tile.data & 0xff];
}
offsetX = tilesize / 2f - region.width / 2f * Draw.scl; offsetX = tilesize / 2f - region.width / 2f * Draw.scl;
offsetY = tilesize / 2f - region.height / 2f * Draw.scl; offsetY = tilesize / 2f - region.height / 2f * Draw.scl;
}else if(wall == Blocks.air && !tile.overlay().isAir()){ }else if(wall == Blocks.air && !tile.overlay().isAir()){

View File

@@ -38,7 +38,8 @@ public class MapView extends Element implements GestureListener{
for(int i = 0; i < MapEditor.brushSizes.length; i++){ for(int i = 0; i < MapEditor.brushSizes.length; i++){
float size = MapEditor.brushSizes[i]; float size = MapEditor.brushSizes[i];
brushPolygons[i] = Geometry.pixelCircle(size, (index, x, y) -> Mathf.dst(x, y, index, index) <= index - 0.5f); float mod = size % 1f;
brushPolygons[i] = Geometry.pixelCircle(size, (index, x, y) -> Mathf.dst(x, y, index - mod, index - mod) <= size - 0.5f);
} }
Core.input.getInputProcessors().insert(0, new GestureDetector(20, 0.5f, 2, 0.15f, this)); Core.input.getInputProcessors().insert(0, new GestureDetector(20, 0.5f, 2, 0.15f, this));

View File

@@ -38,8 +38,14 @@ public class WaveGraph extends Table{
lay.setText(font, "1"); lay.setText(font, "1");
int maxY = switch(mode){
case counts -> nextStep(max);
case health -> nextStep((int)maxHealth);
case totals -> nextStep(maxTotal);
};
float fh = lay.height; float fh = lay.height;
float offsetX = Scl.scl(30f), offsetY = Scl.scl(22f) + fh + Scl.scl(5f); float offsetX = Scl.scl(lay.width * (maxY + "").length() * 2), offsetY = Scl.scl(22f) + fh + Scl.scl(5f);
float graphX = x + offsetX, graphY = y + offsetY, graphW = width - offsetX, graphH = height - offsetY; float graphX = x + offsetX, graphY = y + offsetY, graphW = width - offsetX, graphH = height - offsetY;
float spacing = graphW / (values.length - 1); float spacing = graphW / (values.length - 1);
@@ -53,7 +59,7 @@ public class WaveGraph extends Table{
for(int i = 0; i < values.length; i++){ for(int i = 0; i < values.length; i++){
int val = values[i][type.id]; int val = values[i][type.id];
float cx = graphX + i*spacing, cy = graphY + val * graphH / max; float cx = graphX + i * spacing, cy = graphY + val * graphH / maxY;
Lines.linePoint(cx, cy); Lines.linePoint(cx, cy);
} }
@@ -69,7 +75,7 @@ public class WaveGraph extends Table{
sum += values[i][type.id]; sum += values[i][type.id];
} }
float cx = graphX + i*spacing, cy = graphY + sum * graphH / maxTotal; float cx = graphX + i * spacing, cy = graphY + sum * graphH / maxY;
Lines.linePoint(cx, cy); Lines.linePoint(cx, cy);
} }
@@ -84,7 +90,7 @@ public class WaveGraph extends Table{
sum += (type.health) * values[i][type.id]; sum += (type.health) * values[i][type.id];
} }
float cx = graphX + i*spacing, cy = graphY + sum * graphH / maxHealth; float cx = graphX + i * spacing, cy = graphY + sum * graphH / maxY;
Lines.linePoint(cx, cy); Lines.linePoint(cx, cy);
} }
@@ -92,19 +98,23 @@ public class WaveGraph extends Table{
} }
//how many numbers can fit here //how many numbers can fit here
float totalMarks = (graphH - getMarginBottom() *2f) / (lay.height * 2); float totalMarks = Mathf.clamp(maxY, 1, 10);
int markSpace = Math.max(1, Mathf.ceil(max / totalMarks)); int markSpace = Math.max(1, Mathf.ceil(maxY / totalMarks));
Draw.color(Color.lightGray); Draw.color(Color.lightGray);
for(int i = 0; i < max; i += markSpace){ Draw.alpha(0.1f);
float cy = graphY + i * graphH / max, cx = graphX;
//Lines.line(cx, cy, cx + len, cy); for(int i = 0; i < maxY; i += markSpace){
float cy = graphY + i * graphH / maxY, cx = graphX;
Lines.line(cx, cy, cx + graphW, cy);
lay.setText(font, "" + i); lay.setText(font, "" + i);
font.draw("" + i, cx, cy + lay.height / 2f, Align.right); font.draw("" + i, cx, cy + lay.height / 2f, Align.right);
} }
Draw.alpha(1f);
float len = Scl.scl(4f); float len = Scl.scl(4f);
font.setColor(Color.lightGray); font.setColor(Color.lightGray);
@@ -171,6 +181,17 @@ public class WaveGraph extends Table{
colors.clear(); colors.clear();
colors.left(); colors.left();
colors.button("@waves.units.hide", Styles.cleart, () -> {
if(hidden.size == usedCopy.size){
hidden.clear();
}else{
hidden.addAll(usedCopy);
}
used.clear();
used.addAll(usedCopy);
for(UnitType o : hidden) used.remove(o);
}).update(b -> b.setText(hidden.size == usedCopy.size ? "@waves.units.show" : "@waves.units.hide")).height(32f).width(130f);
colors.pane(t -> { colors.pane(t -> {
t.left(); t.left();
for(UnitType type : used){ for(UnitType type : used){
@@ -200,6 +221,23 @@ public class WaveGraph extends Table{
return Tmp.c1.fromHsv(type.id / (float)Vars.content.units().size * 360f, 0.7f, 1f); return Tmp.c1.fromHsv(type.id / (float)Vars.content.units().size * 360f, 0.7f, 1f);
} }
int nextStep(float value){
int order = 1;
while(order < value){
if(order * 2 > value){
return order * 2;
}
if(order * 5 > value){
return order * 5;
}
if(order * 10 > value){
return order * 10;
}
order *= 10;
}
return order;
}
enum Mode{ enum Mode{
counts, totals, health; counts, totals, health;

View File

@@ -3,7 +3,9 @@ package mindustry.editor;
import arc.*; import arc.*;
import arc.graphics.*; import arc.graphics.*;
import arc.math.*; import arc.math.*;
import arc.math.geom.*;
import arc.scene.event.*; import arc.scene.event.*;
import arc.scene.style.*;
import arc.scene.ui.*; import arc.scene.ui.*;
import arc.scene.ui.TextField.*; import arc.scene.ui.TextField.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
@@ -31,6 +33,8 @@ public class WaveInfoDialog extends BaseDialog{
private Table table; private Table table;
private int start = 0; private int start = 0;
private UnitType lastType = UnitTypes.dagger; private UnitType lastType = UnitTypes.dagger;
private Sort sort = Sort.begin;
private boolean reverseSort = false;
private float updateTimer, updatePeriod = 1f; private float updateTimer, updatePeriod = 1f;
private WaveGraph graph = new WaveGraph(); private WaveGraph graph = new WaveGraph();
@@ -43,20 +47,44 @@ public class WaveInfoDialog extends BaseDialog{
addCloseListener(); addCloseListener();
onResize(this::setup); onResize(this::setup);
buttons.button(Icon.filter, () -> {
BaseDialog dialog = new BaseDialog("@waves.sort");
dialog.setFillParent(false);
dialog.cont.table(Tex.button, t -> {
for(Sort s : Sort.all){
t.button("@waves.sort." + s, Styles.clearTogglet, () -> {
sort = s;
dialog.hide();
buildGroups();
}).size(150f, 60f).checked(s == sort);
}
}).row();
dialog.cont.check("@waves.sort.reverse", b -> {
reverseSort = b;
buildGroups();
}).padTop(4).checked(reverseSort).padBottom(8f);
dialog.addCloseButton();
dialog.show();
buildGroups();
}).size(60f, 64f);
addCloseButton(); addCloseButton();
buttons.button("@waves.edit", () -> { buttons.button("@waves.edit", Icon.pencil, () -> {
BaseDialog dialog = new BaseDialog("@waves.edit"); BaseDialog dialog = new BaseDialog("@waves.edit");
dialog.addCloseButton(); dialog.addCloseButton();
dialog.setFillParent(false); dialog.setFillParent(false);
dialog.cont.defaults().size(210f, 64f); dialog.cont.table(Tex.button, t -> {
dialog.cont.button("@waves.copy", () -> { var style = Styles.cleart;
t.defaults().size(210f, 58f);
t.button("@waves.copy", Icon.copy, style, () -> {
ui.showInfoFade("@waves.copied"); ui.showInfoFade("@waves.copied");
Core.app.setClipboardText(maps.writeWaves(groups)); Core.app.setClipboardText(maps.writeWaves(groups));
dialog.hide(); dialog.hide();
}).disabled(b -> groups == null); }).disabled(b -> groups == null).marginLeft(12f).row();
dialog.cont.row();
dialog.cont.button("@waves.load", () -> { t.button("@waves.load", Icon.download, style, () -> {
try{ try{
groups = maps.readWaves(Core.app.getClipboardText()); groups = maps.readWaves(Core.app.getClipboardText());
buildGroups(); buildGroups();
@@ -65,21 +93,23 @@ public class WaveInfoDialog extends BaseDialog{
ui.showErrorMessage("@waves.invalid"); ui.showErrorMessage("@waves.invalid");
} }
dialog.hide(); dialog.hide();
}).disabled(b -> Core.app.getClipboardText() == null || Core.app.getClipboardText().isEmpty()); }).marginLeft(12f).disabled(b -> Core.app.getClipboardText() == null || Core.app.getClipboardText().isEmpty()).row();
dialog.cont.row();
dialog.cont.button("@settings.reset", () -> ui.showConfirm("@confirm", "@settings.clear.confirm", () -> { t.button("@settings.reset", Icon.upload, style, () -> ui.showConfirm("@confirm", "@settings.clear.confirm", () -> {
groups = JsonIO.copy(waves.get()); groups = JsonIO.copy(waves.get());
buildGroups(); buildGroups();
dialog.hide(); dialog.hide();
})); })).marginLeft(12f).row();
dialog.cont.row();
dialog.cont.button("@clear", () -> ui.showConfirm("@confirm", "@settings.clear.confirm", () -> { t.button("@clear", Icon.cancel, style, () -> ui.showConfirm("@confirm", "@settings.clear.confirm", () -> {
groups.clear(); groups.clear();
buildGroups(); buildGroups();
dialog.hide(); dialog.hide();
})); })).marginLeft(12f);
});
dialog.show(); dialog.show();
}).size(270f, 64f); }).size(250f, 64f);
buttons.defaults().width(60f); buttons.defaults().width(60f);
@@ -167,7 +197,8 @@ public class WaveInfoDialog extends BaseDialog{
table.margin(10f); table.margin(10f);
if(groups != null){ if(groups != null){
groups.sort(Comparator.comparing(g -> g.begin)); groups.sort(sort.sort);
if(reverseSort) groups.reverse();
for(SpawnGroup group : groups){ for(SpawnGroup group : groups){
table.table(Tex.button, t -> { table.table(Tex.button, t -> {
@@ -181,12 +212,24 @@ public class WaveInfoDialog extends BaseDialog{
b.label(() -> (group.begin + 1) + "").color(Color.lightGray).minWidth(45f).labelAlign(Align.left).left(); b.label(() -> (group.begin + 1) + "").color(Color.lightGray).minWidth(45f).labelAlign(Align.left).left();
b.button(Icon.copySmall, Styles.emptyi, () -> {
SpawnGroup newGroup = group.copy();
expandedGroup = newGroup;
groups.add(newGroup);
buildGroups();
}).pad(-6).size(46f);
b.button(group.effect != null && group.effect != StatusEffects.none ?
new TextureRegionDrawable(group.effect.uiIcon) :
Icon.logicSmall,
Styles.emptyi, () -> showEffect(group)).pad(-6).size(46f);
b.button(Icon.unitsSmall, Styles.emptyi, () -> showUpdate(group)).pad(-6).size(46f); b.button(Icon.unitsSmall, Styles.emptyi, () -> showUpdate(group)).pad(-6).size(46f);
b.button(Icon.cancel, Styles.emptyi, () -> { b.button(Icon.cancel, Styles.emptyi, () -> {
groups.remove(group); groups.remove(group);
table.getCell(t).pad(0f); table.getCell(t).pad(0f);
t.remove(); t.remove();
updateWaves(); buildGroups();
}).pad(-6).size(46f).padRight(-12f); }).pad(-6).size(46f).padRight(-12f);
}, () -> { }, () -> {
expandedGroup = expandedGroup == group ? null : group; expandedGroup = expandedGroup == group ? null : group;
@@ -271,7 +314,33 @@ public class WaveInfoDialog extends BaseDialog{
a.add("@waves.shields").padLeft(4); a.add("@waves.shields").padLeft(4);
}).row(); }).row();
t.check("@waves.guardian", b -> group.effect = (b ? StatusEffects.boss : null)).padTop(4).update(b -> b.setChecked(group.effect == StatusEffects.boss)).padBottom(8f); t.check("@waves.guardian", b -> {
group.effect = (b ? StatusEffects.boss : null);
buildGroups();
}).padTop(4).update(b -> b.setChecked(group.effect == StatusEffects.boss)).padBottom(8f).row();
//spawn positions are clunky and thus experimental for now
if(experimental){
t.table(a -> {
a.add("spawn at ");
a.field(group.spawn == -1 ? "" : Point2.x(group.spawn) + "", TextFieldFilter.digitsOnly, text -> {
if(Strings.canParsePositiveInt(text)){
group.spawn = Point2.pack(Strings.parseInt(text), Point2.y(group.spawn));
Log.info(group.spawn);
}
}).width(70f);
a.add(",");
a.field(group.spawn == -1 ? "" : Point2.y(group.spawn) + "", TextFieldFilter.digitsOnly, text -> {
if(Strings.canParsePositiveInt(text)){
group.spawn = Point2.pack(Point2.x(group.spawn), Strings.parseInt(text));
Log.info(group.spawn);
}
}).width(70f);
}).padBottom(8f).padTop(-8f).row();
}
} }
}).width(340f).pad(8); }).width(340f).pad(8);
@@ -308,6 +377,53 @@ public class WaveInfoDialog extends BaseDialog{
dialog.show(); dialog.show();
} }
void showEffect(SpawnGroup group){
BaseDialog dialog = new BaseDialog("");
dialog.setFillParent(true);
dialog.cont.pane(p -> {
int i = 0;
for(StatusEffect effect : content.statusEffects()){
if(effect != StatusEffects.none && (effect.isHidden() || effect.reactive)) continue;
p.button(t -> {
t.left();
if(effect.uiIcon != null && effect != StatusEffects.none){
t.image(effect.uiIcon).size(8 * 4).scaling(Scaling.fit).padRight(2f);
}else{
t.image(Icon.none).size(8 * 4).scaling(Scaling.fit).padRight(2f);
}
if(effect != StatusEffects.none){
t.add(effect.localizedName);
}else{
t.add("@settings.resetKey");
}
}, () -> {
group.effect = effect;
dialog.hide();
buildGroups();
}).pad(2).margin(12f).fillX();
if(++i % 3 == 0) p.row();
}
});
dialog.addCloseButton();
dialog.show();
}
enum Sort{
begin(Structs.comps(Structs.comparingFloat(g -> g.begin), Structs.comparingFloat(g -> g.type.id))),
health(Structs.comps(Structs.comparingFloat(g -> g.type.health), Structs.comparingFloat(g -> g.begin))),
type(Structs.comps(Structs.comparingFloat(g -> g.type.id), Structs.comparingFloat(g -> g.begin)));
static final Sort[] all = values();
final Comparator<SpawnGroup> sort;
Sort(Comparator<SpawnGroup> sort){
this.sort = sort;
}
}
void updateWaves(){ void updateWaves(){
graph.groups = groups; graph.groups = groups;
graph.from = start; graph.from = start;

View File

@@ -48,8 +48,8 @@ public class Damage{
public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, boolean damage, boolean fire, @Nullable Team ignoreTeam, Effect explosionFx){ public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, boolean damage, boolean fire, @Nullable Team ignoreTeam, Effect explosionFx){
if(damage){ if(damage){
for(int i = 0; i < Mathf.clamp(power / 700, 0, 8); i++){ for(int i = 0; i < Mathf.clamp(power / 700, 0, 8); i++){
int length = 5 + Mathf.clamp((int)(power / 500), 1, 20); int length = 5 + Mathf.clamp((int)(Mathf.pow(power, 0.98f) / 500), 1, 18);
Time.run(i * 0.8f + Mathf.random(4f), () -> Lightning.create(Team.derelict, Pal.power, 3, x, y, Mathf.random(360f), length + Mathf.range(2))); Time.run(i * 0.8f + Mathf.random(4f), () -> Lightning.create(Team.derelict, Pal.power, 3 + Mathf.pow(power, 0.35f), x, y, Mathf.random(360f), length + Mathf.range(2)));
} }
if(fire){ if(fire){
@@ -465,8 +465,8 @@ public class Damage{
for(int dx = -trad; dx <= trad; dx++){ for(int dx = -trad; dx <= trad; dx++){
for(int dy = -trad; dy <= trad; dy++){ for(int dy = -trad; dy <= trad; dy++){
Tile tile = world.tile(Math.round(x / tilesize) + dx, Math.round(y / tilesize) + dy); Tile tile = world.tile(Math.round(x / tilesize) + dx, Math.round(y / tilesize) + dy);
if(tile != null && tile.build != null && (team == null ||team.isEnemy(tile.team())) && Mathf.dst(dx, dy) <= trad){ if(tile != null && tile.build != null && (team == null ||team.isEnemy(tile.team())) && dx*dx + dy*dy <= trad){
tile.build.damage(damage); tile.build.damage(team, damage);
} }
} }
} }

View File

@@ -26,7 +26,7 @@ public class EnergyFieldAbility extends Ability{
public Sound shootSound = Sounds.spark; public Sound shootSound = Sounds.spark;
public float statusDuration = 60f * 6f; public float statusDuration = 60f * 6f;
public float x, y; public float x, y;
public boolean hitBuildings = true; public boolean targetGround = true, targetAir = true, hitBuildings = true, hitUnits = true;
public int maxTargets = 25; public int maxTargets = 25;
public float healPercent = 2.5f; public float healPercent = 2.5f;
@@ -99,13 +99,15 @@ public class EnergyFieldAbility extends Ability{
all.clear(); all.clear();
if(hitUnits){
Units.nearby(null, rx, ry, range, other -> { Units.nearby(null, rx, ry, range, other -> {
if(other != unit){ if(other != unit && (other.isFlying() ? targetAir : targetGround)){
all.add(other); all.add(other);
} }
}); });
}
if(hitBuildings){ if(hitBuildings && targetGround){
Units.nearbyBuildings(rx, ry, range, b -> { Units.nearbyBuildings(rx, ry, range, b -> {
if(b.team != Team.derelict || state.rules.coreCapture){ if(b.team != Team.derelict || state.rules.coreCapture){
all.add(b); all.add(b);

View File

@@ -346,13 +346,7 @@ public class BulletType extends Content implements Cloneable{
} }
public void update(Bullet b){ public void update(Bullet b){
if(!headless && trailLength > 0){ updateTrail(b);
if(b.trail == null){
b.trail = new Trail(trailLength);
}
b.trail.length = trailLength;
b.trail.update(b.x, b.y, trailInterp.apply(b.fin()));
}
if(homingPower > 0.0001f && b.time >= homingDelay){ if(homingPower > 0.0001f && b.time >= homingDelay){
Teamc target; Teamc target;
@@ -387,6 +381,16 @@ public class BulletType extends Content implements Cloneable{
} }
} }
public void updateTrail(Bullet b){
if(!headless && trailLength > 0){
if(b.trail == null){
b.trail = new Trail(trailLength);
}
b.trail.length = trailLength;
b.trail.update(b.x, b.y, trailInterp.apply(b.fin()));
}
}
@Override @Override
public void init(){ public void init(){
if(pierceCap >= 1){ if(pierceCap >= 1){

View File

@@ -7,6 +7,9 @@ import mindustry.entities.*;
import mindustry.gen.*; import mindustry.gen.*;
public class RailBulletType extends BulletType{ public class RailBulletType extends BulletType{
//for calculating the furthest point
static float furthest = 0;
public Effect pierceEffect = Fx.hitBulletSmall, updateEffect = Fx.none; public Effect pierceEffect = Fx.hitBulletSmall, updateEffect = Fx.none;
/** Multiplier of damage decreased per health pierced. */ /** Multiplier of damage decreased per health pierced. */
public float pierceDamageFactor = 1f; public float pierceDamageFactor = 1f;
@@ -47,6 +50,11 @@ public class RailBulletType extends BulletType{
//subtract health from each consecutive pierce //subtract health from each consecutive pierce
b.damage -= Math.min(b.damage, sub); b.damage -= Math.min(b.damage, sub);
//bullet was stopped, decrease furthest distance
if(b.damage <= 0f){
furthest = Math.min(furthest, b.dst(pos));
}
} }
@Override @Override
@@ -54,8 +62,9 @@ public class RailBulletType extends BulletType{
super.init(b); super.init(b);
b.fdata = length; b.fdata = length;
furthest = length;
Damage.collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), length, false, false); Damage.collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), length, false, false);
float resultLen = b.fdata; float resultLen = furthest;
Vec2 nor = Tmp.v1.trns(b.rotation(), 1f).nor(); Vec2 nor = Tmp.v1.trns(b.rotation(), 1f).nor();
for(float i = 0; i <= resultLen; i += updateEffectSeg){ for(float i = 0; i <= resultLen; i += updateEffectSeg){

View File

@@ -94,6 +94,10 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{
if(!within(tile, finalPlaceDst)) return; if(!within(tile, finalPlaceDst)) return;
if(!headless){
Vars.control.sound.loop(Sounds.build, tile, 0.51f);
}
if(!(tile.build instanceof ConstructBuild cb)){ if(!(tile.build instanceof ConstructBuild cb)){
if(!current.initialized && !current.breaking && Build.validPlace(current.block, team, current.x, current.y, current.rotation)){ if(!current.initialized && !current.breaking && Build.validPlace(current.block, team, current.x, current.y, current.rotation)){
boolean hasAll = infinite || current.isRotation(team) || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item, Math.min(Mathf.round(i.amount * state.rules.buildCostMultiplier), 1))); boolean hasAll = infinite || current.isRotation(team) || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item, Math.min(Mathf.round(i.amount * state.rules.buildCostMultiplier), 1)));

View File

@@ -1509,6 +1509,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
} }
} }
if(cons != null){
cons.update();
}
if(enabled || !block.noUpdateDisabled){ if(enabled || !block.noUpdateDisabled){
updateTile(); updateTile();
} }
@@ -1521,10 +1525,6 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
liquids.update(updateFlow); liquids.update(updateFlow);
} }
if(cons != null){
cons.update();
}
if(power != null){ if(power != null){
power.graph.update(); power.graph.update();
} }

View File

@@ -133,8 +133,9 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
int x = x0f, dx = Math.abs(x1 - x), sx = x < x1 ? 1 : -1; int x = x0f, dx = Math.abs(x1 - x), sx = x < x1 ? 1 : -1;
int y = y0f, dy = Math.abs(y1 - y), sy = y < y1 ? 1 : -1; int y = y0f, dy = Math.abs(y1 - y), sy = y < y1 ? 1 : -1;
int e2, err = dx - dy; int e2, err = dx - dy;
int ww = world.width(), wh = world.height();
while(true){ while(x >= 0 && y >= 0 && x < ww && y < wh){
Building build = world.build(x, y); Building build = world.build(x, y);
if(build != null && isAdded() && build.collide(self()) && type.testCollision(self(), build) if(build != null && isAdded() && build.collide(self()) && type.testCollision(self(), build)
&& !build.dead() && (type.collidesTeam || build.team != team) && !(type.pierceBuilding && hasCollided(build.id))){ && !build.dead() && (type.collidesTeam || build.team != team) && !(type.pierceBuilding && hasCollided(build.id))){

View File

@@ -11,7 +11,6 @@ import arc.util.*;
import mindustry.ai.*; import mindustry.ai.*;
import mindustry.ai.types.*; import mindustry.ai.types.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.core.*; import mindustry.core.*;
import mindustry.ctype.*; import mindustry.ctype.*;
import mindustry.entities.*; import mindustry.entities.*;
@@ -481,12 +480,13 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
if(!spawnedByCore){ if(!spawnedByCore){
Damage.dynamicExplosion(x, y, flammability, explosiveness, power, bounds() / 2f, state.rules.damageExplosions, item().flammability > 1, team, type.deathExplosionEffect); Damage.dynamicExplosion(x, y, flammability, explosiveness, power, bounds() / 2f, state.rules.damageExplosions, item().flammability > 1, team, type.deathExplosionEffect);
}else{
type.deathExplosionEffect.at(x, y, bounds() / 2f / 8f);
} }
float shake = hitSize / 3f; float shake = hitSize / 3f;
Effect.scorch(x, y, (int)(hitSize / 5)); Effect.scorch(x, y, (int)(hitSize / 5));
Fx.explosion.at(this);
Effect.shake(shake, shake, this); Effect.shake(shake, shake, this);
type.deathSound.at(this); type.deathSound.at(this);

View File

@@ -18,6 +18,7 @@ public class MultiEffect extends Effect{
@Override @Override
public void init(){ public void init(){
for(Effect f : effects){ for(Effect f : effects){
f.init();
clip = Math.max(clip, f.clip); clip = Math.max(clip, f.clip);
lifetime = Math.max(lifetime, f.lifetime); lifetime = Math.max(lifetime, f.lifetime);
} }

View File

@@ -4,17 +4,24 @@ import arc.*;
import arc.graphics.*; import arc.graphics.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.math.*; import arc.math.*;
import arc.math.geom.*;
import arc.util.*; import arc.util.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.graphics.*; import mindustry.graphics.*;
/** The most essential effect class. Can create particles in various shapes. */ /** The most essential effect class. Can create particles in various shapes. */
public class ParticleEffect extends Effect{ public class ParticleEffect extends Effect{
private static final Rand rand = new Rand();
private static final Vec2 rv = new Vec2();
public Color colorFrom = Color.white.cpy(), colorTo = Color.white.cpy(); public Color colorFrom = Color.white.cpy(), colorTo = Color.white.cpy();
public int particles = 6; public int particles = 6;
public boolean randLength = true;
public float cone = 180f, length = 20f, baseLength = 0f; public float cone = 180f, length = 20f, baseLength = 0f;
/** Particle size/length/radius interpolation. */ /** Particle size/length/radius interpolation. */
public Interp interp = Interp.linear; public Interp interp = Interp.linear;
/** Particle size interpolation. Null to use interp. */
public @Nullable Interp sizeInterp = null;
public float offsetX, offsetY; public float offsetX, offsetY;
public float lightScl = 2f, lightOpacity = 0.6f; public float lightScl = 2f, lightOpacity = 0.6f;
public @Nullable Color lightColor; public @Nullable Color lightColor;
@@ -39,6 +46,7 @@ public class ParticleEffect extends Effect{
@Override @Override
public void init(){ public void init(){
clip = Math.max(clip, length + Math.max(sizeFrom, sizeTo)); clip = Math.max(clip, length + Math.max(sizeFrom, sizeTo));
if(sizeInterp == null) sizeInterp = interp;
} }
@Override @Override
@@ -47,25 +55,35 @@ public class ParticleEffect extends Effect{
float rawfin = e.fin(); float rawfin = e.fin();
float fin = e.fin(interp); float fin = e.fin(interp);
float rad = interp.apply(sizeFrom, sizeTo, rawfin) * 2; float rad = sizeInterp.apply(sizeFrom, sizeTo, rawfin) * 2;
float ox = e.x + Angles.trnsx(e.rotation, offsetX, offsetY), oy = e.y + Angles.trnsy(e.rotation, offsetX, offsetY); float ox = e.x + Angles.trnsx(e.rotation, offsetX, offsetY), oy = e.y + Angles.trnsy(e.rotation, offsetX, offsetY);
Draw.color(colorFrom, colorTo, fin); Draw.color(colorFrom, colorTo, fin);
Color lightColor = this.lightColor == null ? Draw.getColor() : this.lightColor; Color lightColor = this.lightColor == null ? Draw.getColor() : this.lightColor;
if(line){ if(line){
Lines.stroke(interp.apply(strokeFrom, strokeTo, rawfin)); Lines.stroke(sizeInterp.apply(strokeFrom, strokeTo, rawfin));
float len = interp.apply(lenFrom, lenTo, rawfin); float len = sizeInterp.apply(lenFrom, lenTo, rawfin);
rand.setSeed(e.id);
for(int i = 0; i < particles; i++){
float l = length * fin + baseLength;
rv.trns(e.rotation + rand.range(cone), !randLength ? l : rand.random(l));
float x = rv.x, y = rv.y;
Angles.randLenVectors(e.id, particles, length * fin + baseLength, e.rotation, cone, (x, y) -> {
Lines.lineAngle(ox + x, oy + y, Mathf.angle(x, y), len); Lines.lineAngle(ox + x, oy + y, Mathf.angle(x, y), len);
Drawf.light(ox + x, oy + y, len * lightScl, lightColor, lightOpacity * Draw.getColor().a); Drawf.light(ox + x, oy + y, len * lightScl, lightColor, lightOpacity * Draw.getColor().a);
}); }
}else{ }else{
Angles.randLenVectors(e.id, particles, length * fin + baseLength, e.rotation, cone, (x, y) -> { rand.setSeed(e.id);
for(int i = 0; i < particles; i++){
float l = length * fin + baseLength;
rv.trns(e.rotation + rand.range(cone), !randLength ? l : rand.random(l));
float x = rv.x, y = rv.y;
Draw.rect(tex, ox + x, oy + y, rad, rad, e.rotation + offset + e.time * spin); Draw.rect(tex, ox + x, oy + y, rad, rad, e.rotation + offset + e.time * spin);
Drawf.light(ox + x, oy + y, rad * lightScl, lightColor, lightOpacity * Draw.getColor().a); Drawf.light(ox + x, oy + y, rad * lightScl, lightColor, lightOpacity * Draw.getColor().a);
}); }
} }
} }
} }

View File

@@ -428,6 +428,15 @@ public class EventType{
} }
} }
/** Called when a unit is spawned by wave. */
public static class UnitSpawnEvent{
public final Unit unit;
public UnitSpawnEvent(Unit unit) {
this.unit = unit;
}
}
/** Called when a unit is dumped from any payload block. */ /** Called when a unit is dumped from any payload block. */
public static class UnitUnloadEvent{ public static class UnitUnloadEvent{
public final Unit unit; public final Unit unit;

View File

@@ -291,16 +291,22 @@ public class Schematics implements Loadable{
/** Checks a schematic for deployment validity and adds it to the cache. */ /** Checks a schematic for deployment validity and adds it to the cache. */
private void checkLoadout(Schematic s, boolean validate){ private void checkLoadout(Schematic s, boolean validate){
Stile core = s.tiles.find(t -> t.block instanceof CoreBlock); Stile core = s.tiles.find(t -> t.block instanceof CoreBlock);
if(core == null) return;
int cores = s.tiles.count(t -> t.block instanceof CoreBlock); int cores = s.tiles.count(t -> t.block instanceof CoreBlock);
int maxSize = getMaxLaunchSize(core.block);
//make sure a core exists, and that the schematic is small enough. //make sure a core exists, and that the schematic is small enough.
if(core == null || (validate && (s.width > core.block.size + maxLoadoutSchematicPad *2 || s.height > core.block.size + maxLoadoutSchematicPad *2 if((validate && (s.width > maxSize || s.height > maxSize
|| s.tiles.contains(t -> t.block.buildVisibility == BuildVisibility.sandboxOnly || !t.block.unlocked()) || cores > 1))) return; || s.tiles.contains(t -> t.block.buildVisibility == BuildVisibility.sandboxOnly || !t.block.unlocked()) || cores > 1))) return;
//place in the cache //place in the cache
loadouts.get((CoreBlock)core.block, Seq::new).add(s); loadouts.get((CoreBlock)core.block, Seq::new).add(s);
} }
public int getMaxLaunchSize(Block block){
return block.size + maxLoadoutSchematicPad*2;
}
/** Adds a schematic to the list, also copying it into the files.*/ /** Adds a schematic to the list, also copying it into the files.*/
public void add(Schematic schematic){ public void add(Schematic schematic){
all.add(schematic); all.add(schematic);

View File

@@ -288,7 +288,7 @@ public class SectorInfo{
public void eachImport(Planet planet, Cons<Sector> cons){ public void eachImport(Planet planet, Cons<Sector> cons){
for(Sector sector : planet.sectors){ for(Sector sector : planet.sectors){
Sector dest = sector.info.getRealDestination(); Sector dest = sector.info.getRealDestination();
if(sector.hasBase() && sector.info != this && dest != null && dest.info == this){ if(sector.hasBase() && sector.info != this && dest != null && dest.info == this && sector.info.anyExports()){
cons.get(sector); cons.get(sector);
} }
} }

View File

@@ -19,7 +19,7 @@ import static mindustry.Vars.*;
* weapon equipped, ammo used, and status effects. * weapon equipped, ammo used, and status effects.
* Each spawn group can have multiple sub-groups spawned in different areas of the map. * Each spawn group can have multiple sub-groups spawned in different areas of the map.
*/ */
public class SpawnGroup implements JsonSerializable{ public class SpawnGroup implements JsonSerializable, Cloneable{
public static final int never = Integer.MAX_VALUE; public static final int never = Integer.MAX_VALUE;
/** The unit type spawned */ /** The unit type spawned */
@@ -36,10 +36,12 @@ public class SpawnGroup implements JsonSerializable{
public float unitScaling = never; public float unitScaling = never;
/** Shield points that this unit has. */ /** Shield points that this unit has. */
public float shields = 0f; public float shields = 0f;
/** How much shields get increased per wave. */ /** How much shields get increased by per wave. */
public float shieldScaling = 0f; public float shieldScaling = 0f;
/** Amount of enemies spawned initially, with no scaling */ /** Amount of enemies spawned initially, with no scaling */
public int unitAmount = 1; public int unitAmount = 1;
/** If not -1, the unit will only spawn in spawnpoints with these packed coordinates. */
public int spawn = -1;
/** Seq of payloads that this unit will spawn with. */ /** Seq of payloads that this unit will spawn with. */
public @Nullable Seq<UnitType> payloads; public @Nullable Seq<UnitType> payloads;
/** Status effect applied to the spawned unit. Null to disable. */ /** Status effect applied to the spawned unit. Null to disable. */
@@ -55,6 +57,10 @@ public class SpawnGroup implements JsonSerializable{
//serialization use only //serialization use only
} }
public boolean canSpawn(int position){
return spawn == -1 || spawn == position;
}
/** @return amount of units spawned on a specific wave. */ /** @return amount of units spawned on a specific wave. */
public int getSpawned(int wave){ public int getSpawned(int wave){
if(spacing == 0) spacing = 1; if(spacing == 0) spacing = 1;
@@ -111,6 +117,7 @@ public class SpawnGroup implements JsonSerializable{
if(shieldScaling != 0) json.writeValue("shieldScaling", shieldScaling); if(shieldScaling != 0) json.writeValue("shieldScaling", shieldScaling);
if(unitAmount != 1) json.writeValue("amount", unitAmount); if(unitAmount != 1) json.writeValue("amount", unitAmount);
if(effect != null) json.writeValue("effect", effect.name); if(effect != null) json.writeValue("effect", effect.name);
if(spawn != -1) json.writeValue("spawn", spawn);
if(payloads != null && payloads.size > 0){ if(payloads != null && payloads.size > 0){
json.writeValue("payloads", payloads.map(u -> u.name).toArray(String.class)); json.writeValue("payloads", payloads.map(u -> u.name).toArray(String.class));
} }
@@ -130,6 +137,7 @@ public class SpawnGroup implements JsonSerializable{
shields = data.getFloat("shields", 0); shields = data.getFloat("shields", 0);
shieldScaling = data.getFloat("shieldScaling", 0); shieldScaling = data.getFloat("shieldScaling", 0);
unitAmount = data.getInt("amount", 1); unitAmount = data.getInt("amount", 1);
spawn = data.getInt("spawn", -1);
if(data.has("payloads")){ if(data.has("payloads")){
payloads = Seq.with(json.readValue(String[].class, data.get("payloads"))).map(s -> content.getByName(ContentType.unit, s)); payloads = Seq.with(json.readValue(String[].class, data.get("payloads"))).map(s -> content.getByName(ContentType.unit, s));
} }
@@ -157,6 +165,14 @@ public class SpawnGroup implements JsonSerializable{
'}'; '}';
} }
public SpawnGroup copy(){
try{
return (SpawnGroup)clone();
}catch(CloneNotSupportedException how){
throw new RuntimeException("If you see this, what did you even do?", how);
}
}
@Override @Override
public boolean equals(Object o){ public boolean equals(Object o){
if(this == o) return true; if(this == o) return true;

View File

@@ -116,7 +116,7 @@ public class Waves{
spacing = 5; spacing = 5;
unitAmount = 1; unitAmount = 1;
unitScaling = 3; unitScaling = 3;
effect = StatusEffects.shielded; shields = 640f;
max = 25; max = 25;
}}, }},
@@ -350,8 +350,8 @@ public class Waves{
step += (int)(rand.random(15, 30) * Mathf.lerp(1f, 0.5f, difficulty)); step += (int)(rand.random(15, 30) * Mathf.lerp(1f, 0.5f, difficulty));
} }
int bossWave = (int)(rand.random(50, 70) * Mathf.lerp(1f, 0.7f, difficulty)); int bossWave = (int)(rand.random(50, 70) * Mathf.lerp(1f, 0.5f, difficulty));
int bossSpacing = (int)(rand.random(25, 40) * Mathf.lerp(1f, 0.6f, difficulty)); int bossSpacing = (int)(rand.random(25, 40) * Mathf.lerp(1f, 0.5f, difficulty));
int bossTier = difficulty < 0.6 ? 3 : 4; int bossTier = difficulty < 0.6 ? 3 : 4;

View File

@@ -150,7 +150,7 @@ public class BlockRenderer{
public void checkChanges(){ public void checkChanges(){
darkEvents.each(pos -> { darkEvents.each(pos -> {
var tile = world.tile(pos); var tile = world.tile(pos);
if(tile != null){ if(tile != null && tile.block().fillsTile){
tile.data = world.getWallDarkness(tile); tile.data = world.getWallDarkness(tile);
} }
}); });

View File

@@ -77,6 +77,8 @@ public class Trail{
if(points.size >= 3){ if(points.size >= 3){
points.removeRange(0, 2); points.removeRange(0, 2);
} }
counter = 0f;
} }
} }

View File

@@ -7,4 +7,7 @@ import arc.math.geom.*;
public interface HexMesher{ public interface HexMesher{
float getHeight(Vec3 position); float getHeight(Vec3 position);
Color getColor(Vec3 position); Color getColor(Vec3 position);
default boolean skip(Vec3 position){
return false;
}
} }

View File

@@ -48,6 +48,9 @@ public class MeshBuilder{
begin(grid.tiles.length * 12 * (3 + 3 + 1)); begin(grid.tiles.length * 12 * (3 + 3 + 1));
for(Ptile tile : grid.tiles){ for(Ptile tile : grid.tiles){
if(mesher.skip(tile.v)){
continue;
}
Corner[] c = tile.corners; Corner[] c = tile.corners;

View File

@@ -158,22 +158,11 @@ public class PlanetRenderer implements Disposable{
} }
if(cam.frustum.containsSphere(planet.position, planet.clipRadius) && planet.parent != null && planet.hasAtmosphere && Core.settings.getBool("atmosphere")){ if(cam.frustum.containsSphere(planet.position, planet.clipRadius) && planet.parent != null && planet.hasAtmosphere && Core.settings.getBool("atmosphere")){
Gl.depthMask(false); planet.drawAtmosphere(atmosphere, cam);
Blending.additive.apply();
Shaders.atmosphere.camera = cam;
Shaders.atmosphere.planet = planet;
Shaders.atmosphere.bind();
Shaders.atmosphere.apply();
atmosphere.render(Shaders.atmosphere, Gl.triangles);
Blending.normal.apply();
Gl.depthMask(true);
} }
planet.drawClouds(cam.combined, planet.getTransform(mat));
for(Planet child : planet.children){ for(Planet child : planet.children){
renderTransparent(child); renderTransparent(child);
} }
@@ -234,7 +223,6 @@ public class PlanetRenderer implements Disposable{
Tmp.c1.set(from).lerp(to, (f+ Time.globalTime /timeScale)%1f); Tmp.c1.set(from).lerp(to, (f+ Time.globalTime /timeScale)%1f);
batch.color(Tmp.c1); batch.color(Tmp.c1);
batch.vertex(Tmp.bz3.valueAt(Tmp.v32, f)); batch.vertex(Tmp.bz3.valueAt(Tmp.v32, f));
} }
batch.flush(Gl.lineStrip); batch.flush(Gl.lineStrip);
} }

View File

@@ -967,7 +967,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
//consume tap event if necessary //consume tap event if necessary
if(build.interactable(player.team()) && build.block.consumesTap){ if(build.interactable(player.team()) && build.block.consumesTap){
consumed = true; consumed = true;
}else if(build.interactable(player.team()) && build.block.synthetic() && !consumed){ }else if(build.interactable(player.team()) && build.block.synthetic() && (!consumed || build.block.allowConfigInventory)){
if(build.block.hasItems && build.items.total() > 0){ if(build.block.hasItems && build.items.total() > 0){
frag.inv.showFor(build); frag.inv.showFor(build);
consumed = true; consumed = true;

View File

@@ -59,6 +59,13 @@ public abstract class SaveFileReader{
"cryofluidmixer", "cryofluid-mixer" "cryofluidmixer", "cryofluid-mixer"
); );
public static final ObjectMap<String, String> modContentNameMap = ObjectMap.of(
"craters", "crater-stone",
"deepwater", "deep-water",
"water", "shallow-water",
"slag", "molten-slag"
);
protected final ReusableByteOutStream byteOutput = new ReusableByteOutStream(); protected final ReusableByteOutStream byteOutput = new ReusableByteOutStream();
protected final DataOutputStream dataBytes = new DataOutputStream(byteOutput); protected final DataOutputStream dataBytes = new DataOutputStream(byteOutput);
protected final ReusableByteOutStream byteOutputSmall = new ReusableByteOutStream(); protected final ReusableByteOutStream byteOutputSmall = new ReusableByteOutStream();

View File

@@ -715,6 +715,7 @@ public class LExecutor{
if((base instanceof Building && timer.get(30f)) || (ai != null && ai.checkTargetTimer(this))){ if((base instanceof Building && timer.get(30f)) || (ai != null && ai.checkTargetTimer(this))){
//if any of the targets involve enemies //if any of the targets involve enemies
boolean enemies = target1 == RadarTarget.enemy || target2 == RadarTarget.enemy || target3 == RadarTarget.enemy; boolean enemies = target1 == RadarTarget.enemy || target2 == RadarTarget.enemy || target3 == RadarTarget.enemy;
boolean allies = target1 == RadarTarget.ally || target2 == RadarTarget.ally || target3 == RadarTarget.ally;
best = null; best = null;
bestValue = 0; bestValue = 0;
@@ -726,6 +727,11 @@ public class LExecutor{
find(r, range, sortDir, data.items[i].team); find(r, range, sortDir, data.items[i].team);
} }
} }
}else if(!allies){
Seq<TeamData> data = state.teams.present;
for(int i = 0; i < data.size; i++){
find(r, range, sortDir, data.items[i].team);
}
}else{ }else{
find(r, range, sortDir, r.team()); find(r, range, sortDir, r.team());
} }

View File

@@ -272,16 +272,22 @@ public class SectorDamage{
float e = build.efficiency(); float e = build.efficiency();
if(e > 0.08f){ if(e > 0.08f){
if(build.team == state.rules.defaultTeam && build instanceof Ranged ranged && sparse.contains(t -> t.within(build, ranged.range() + 4*tilesize))){ if(build.team == state.rules.defaultTeam && build instanceof Ranged ranged && sparse.contains(t -> t.within(build, ranged.range() + 4*tilesize))){
//TODO make sure power turret network supports the turrets?
if(build.block instanceof Turret t && build instanceof TurretBuild b && b.hasAmmo()){ if(build.block instanceof Turret t && build instanceof TurretBuild b && b.hasAmmo()){
sumDps += t.shots / t.reloadTime * 60f * b.peekAmmo().estimateDPS() * e; sumDps += t.shots / t.reloadTime * 60f * b.peekAmmo().estimateDPS() * e * build.timeScale;
} }
if(build.block instanceof MendProjector m){ if(build.block instanceof MendProjector m){
sumRps += m.healPercent / m.reload * avgHealth * 60f / 100f * e; sumRps += m.healPercent / m.reload * avgHealth * 60f / 100f * e * build.timeScale;
}
//point defense turrets act as flat health right now
if(build.block instanceof PointDefenseTurret && build.consValid()){
sumHealth += 150f * build.timeScale;
} }
if(build.block instanceof ForceProjector f){ if(build.block instanceof ForceProjector f){
sumHealth += f.shieldHealth * e; sumHealth += f.shieldHealth * e * build.timeScale;
sumRps += e; sumRps += e;
} }
} }
@@ -315,14 +321,20 @@ public class SectorDamage{
var reg = new LinearRegression(); var reg = new LinearRegression();
SpawnGroup bossGroup = null; SpawnGroup bossGroup = null;
Seq<Vec2> waveDps = new Seq<>(), waveHealth = new Seq<>(); Seq<Vec2> waveDps = new Seq<>(), waveHealth = new Seq<>();
int groundSpawns = Math.max(spawner.countFlyerSpawns(), 1), airSpawns = Math.max(spawner.countGroundSpawns(), 1);
for(int wave = state.wave; wave < state.wave + 10; wave ++){ for(int wave = state.wave; wave < state.wave + 10; wave ++){
float sumWaveDps = 0f, sumWaveHealth = 0f; float sumWaveDps = 0f, sumWaveHealth = 0f;
for(SpawnGroup group : state.rules.spawns){ for(SpawnGroup group : state.rules.spawns){
//calculate the amount of spawn points used
//if there's a spawn position override, there is only one potential place they spawn
//assume that all overridden positions are valid, should always be true in properly designed campaign maps
int spawnCount = group.spawn != -1 ? 1 : group.type.flying ? airSpawns : groundSpawns;
float healthMult = 1f + Mathf.clamp(group.type.armor / 20f); float healthMult = 1f + Mathf.clamp(group.type.armor / 20f);
StatusEffect effect = (group.effect == null ? StatusEffects.none : group.effect); StatusEffect effect = (group.effect == null ? StatusEffects.none : group.effect);
int spawned = group.getSpawned(wave); int spawned = group.getSpawned(wave) * spawnCount;
//save the boss group //save the boss group
if(group.effect == StatusEffects.boss){ if(group.effect == StatusEffects.boss){
bossGroup = group; bossGroup = group;

View File

@@ -8,7 +8,7 @@ import static mindustry.maps.filters.FilterOption.*;
public class BlendFilter extends GenerateFilter{ public class BlendFilter extends GenerateFilter{
float radius = 2f; float radius = 2f;
Block block = Blocks.stone, floor = Blocks.ice, ignore = Blocks.air; Block block = Blocks.sand, floor = Blocks.sandWater, ignore = Blocks.air;
@Override @Override
public FilterOption[] options(){ public FilterOption[] options(){
@@ -16,7 +16,7 @@ public class BlendFilter extends GenerateFilter{
new SliderOption("radius", () -> radius, f -> radius = f, 1f, 10f), new SliderOption("radius", () -> radius, f -> radius = f, 1f, 10f),
new BlockOption("block", () -> block, b -> block = b, anyOptional), new BlockOption("block", () -> block, b -> block = b, anyOptional),
new BlockOption("floor", () -> floor, b -> floor = b, anyOptional), new BlockOption("floor", () -> floor, b -> floor = b, anyOptional),
new BlockOption("ignore", () -> ignore, b -> ignore = b, floorsOptional) new BlockOption("ignore", () -> ignore, b -> ignore = b, anyOptional)
}; };
} }

View File

@@ -27,7 +27,7 @@ public class DistortFilter extends GenerateFilter{
@Override @Override
public void apply(GenerateInput in){ public void apply(GenerateInput in){
Tile tile = in.tile(in.x + noise(in, scl, mag) - mag / 2f, in.y + noise(in, scl, mag) - mag / 2f); Tile tile = in.tile(in.x + noise(in, scl, mag) - mag / 2f, in.y + noise(1, in, scl, mag) - mag / 2f);
in.floor = tile.floor(); in.floor = tile.floor();
if(!tile.block().synthetic() && !in.block.synthetic()) in.block = tile.block(); if(!tile.block().synthetic() && !in.block.synthetic()) in.block = tile.block();

View File

@@ -99,6 +99,10 @@ public abstract class GenerateFilter{
//utility generation functions //utility generation functions
protected float noise(int seedOffset, GenerateInput in, float scl, float mag){
return Simplex.noise2d(seedOffset + seed, 1f, 0f, 1f / scl, in.x, in.y) * mag;
}
protected float noise(GenerateInput in, float scl, float mag){ protected float noise(GenerateInput in, float scl, float mag){
return Simplex.noise2d(seed, 1f, 0f, 1f / scl, in.x, in.y) * mag; return Simplex.noise2d(seed, 1f, 0f, 1f / scl, in.x, in.y) * mag;
} }

View File

@@ -8,7 +8,7 @@ import static mindustry.maps.filters.FilterOption.*;
public class RiverNoiseFilter extends GenerateFilter{ public class RiverNoiseFilter extends GenerateFilter{
float scl = 40, threshold = 0f, threshold2 = 0.1f, octaves = 1, falloff = 0.5f; float scl = 40, threshold = 0f, threshold2 = 0.1f, octaves = 1, falloff = 0.5f;
Block floor = Blocks.water, floor2 = Blocks.deepwater, block = Blocks.sandWall; Block floor = Blocks.water, floor2 = Blocks.deepwater, block = Blocks.sandWall, target = Blocks.air;
@Override @Override
public FilterOption[] options(){ public FilterOption[] options(){
@@ -18,6 +18,7 @@ public class RiverNoiseFilter extends GenerateFilter{
new SliderOption("threshold2", () -> threshold2, f -> threshold2 = f, -1f, 1f), new SliderOption("threshold2", () -> threshold2, f -> threshold2 = f, -1f, 1f),
new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f), new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f),
new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f),
new BlockOption("target", () -> target, b -> target = b, anyOptional),
new BlockOption("block", () -> block, b -> block = b, wallsOnly), new BlockOption("block", () -> block, b -> block = b, wallsOnly),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly),
new BlockOption("floor2", () -> floor2, b -> floor2 = b, floorsOnly) new BlockOption("floor2", () -> floor2, b -> floor2 = b, floorsOnly)
@@ -26,14 +27,14 @@ public class RiverNoiseFilter extends GenerateFilter{
@Override @Override
public char icon(){ public char icon(){
return Iconc.blockWater; return Iconc.blockShallowWater;
} }
@Override @Override
public void apply(GenerateInput in){ public void apply(GenerateInput in){
float noise = rnoise(in.x, in.y, (int)octaves, scl, falloff, 1f); float noise = rnoise(in.x, in.y, (int)octaves, scl, falloff, 1f);
if(noise >= threshold){ if(noise >= threshold && (target == Blocks.air || in.floor == target || in.block == target)){
in.floor = floor; in.floor = floor;
if(in.block.solid){ if(in.block.solid){

View File

@@ -30,6 +30,12 @@ public class BaseGenerator{
private Tiles tiles; private Tiles tiles;
private Seq<Tile> cores; private Seq<Tile> cores;
public static Block getDifficultyWall(int size, float difficulty){
Seq<Block> wallsSmall = content.blocks().select(b -> b instanceof Wall && b.size == size && !b.insulated && b.buildVisibility == BuildVisibility.shown && !(b instanceof Door));
wallsSmall.sort(b -> b.buildCost);
return wallsSmall.getFrac(difficulty * 0.91f);
}
public void generate(Tiles tiles, Seq<Tile> cores, Tile spawn, Team team, Sector sector, float difficulty){ public void generate(Tiles tiles, Seq<Tile> cores, Tile spawn, Team team, Sector sector, float difficulty){
this.tiles = tiles; this.tiles = tiles;
this.cores = cores; this.cores = cores;
@@ -39,22 +45,15 @@ public class BaseGenerator{
Mathf.rand.setSeed(sector.id); Mathf.rand.setSeed(sector.id);
Seq<Block> wallsSmall = content.blocks().select(b -> b instanceof Wall && b.size == 1 && !b.insulated && b.buildVisibility == BuildVisibility.shown && !(b instanceof Door)); float bracketRange = 0.17f;
Seq<Block> wallsLarge = content.blocks().select(b -> b instanceof Wall && b.size == 2 && !b.insulated && b.buildVisibility == BuildVisibility.shown && !(b instanceof Door)); float baseChance = Mathf.lerp(0.7f, 2.1f, difficulty);
//sort by cost for correct fraction
wallsSmall.sort(b -> b.buildCost);
wallsLarge.sort(b -> b.buildCost);
float bracketRange = 0.2f;
float baseChance = Mathf.lerp(0.7f, 1.9f, difficulty);
int wallAngle = 70; //180 for full coverage int wallAngle = 70; //180 for full coverage
double resourceChance = 0.5 * baseChance; double resourceChance = 0.5 * baseChance;
double nonResourceChance = 0.0005 * baseChance; double nonResourceChance = 0.0005 * baseChance;
BasePart coreschem = bases.cores.getFrac(difficulty); BasePart coreschem = bases.cores.getFrac(difficulty);
int passes = difficulty < 0.4 ? 1 : difficulty < 0.8 ? 2 : 3; int passes = difficulty < 0.4 ? 1 : difficulty < 0.8 ? 2 : 3;
Block wall = wallsSmall.getFrac(difficulty * 0.91f), wallLarge = wallsLarge.getFrac(difficulty * 0.91f); Block wall = getDifficultyWall(1, difficulty), wallLarge = getDifficultyWall(2, difficulty);
for(Tile tile : cores){ for(Tile tile : cores){
tile.clearOverlay(); tile.clearOverlay();

View File

@@ -21,6 +21,16 @@ public class FileMapGenerator implements WorldGenerator{
this.preset = preset; this.preset = preset;
} }
public FileMapGenerator(Map map, SectorPreset preset){
this.map = map;
this.preset = preset;
}
/** If you use this constructor, make sure to override generate()! */
public FileMapGenerator(SectorPreset preset){
this(emptyMap, preset);
}
@Override @Override
public void generate(Tiles tiles){ public void generate(Tiles tiles){
if(map == null) throw new RuntimeException("Generator has null map, cannot be used."); if(map == null) throw new RuntimeException("Generator has null map, cannot be used.");

View File

@@ -23,6 +23,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
BaseGenerator basegen = new BaseGenerator(); BaseGenerator basegen = new BaseGenerator();
float scl = 5f; float scl = 5f;
float waterOffset = 0.07f; float waterOffset = 0.07f;
boolean genLakes = false;
Block[][] arr = Block[][] arr =
{ {
@@ -33,11 +34,11 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
{Blocks.deepwater, Blocks.water, Blocks.sandWater, Blocks.sand, Blocks.salt, Blocks.sand, Blocks.sand, Blocks.basalt, Blocks.snow, Blocks.snow, Blocks.snow, Blocks.snow, Blocks.ice}, {Blocks.deepwater, Blocks.water, Blocks.sandWater, Blocks.sand, Blocks.salt, Blocks.sand, Blocks.sand, Blocks.basalt, Blocks.snow, Blocks.snow, Blocks.snow, Blocks.snow, Blocks.ice},
{Blocks.deepwater, Blocks.water, Blocks.sandWater, Blocks.sand, Blocks.sand, Blocks.sand, Blocks.moss, Blocks.iceSnow, Blocks.snow, Blocks.snow, Blocks.ice, Blocks.snow, Blocks.ice}, {Blocks.deepwater, Blocks.water, Blocks.sandWater, Blocks.sand, Blocks.sand, Blocks.sand, Blocks.moss, Blocks.iceSnow, Blocks.snow, Blocks.snow, Blocks.ice, Blocks.snow, Blocks.ice},
{Blocks.deepwater, Blocks.sandWater, Blocks.sand, Blocks.sand, Blocks.moss, Blocks.moss, Blocks.snow, Blocks.basalt, Blocks.basalt, Blocks.basalt, Blocks.ice, Blocks.snow, Blocks.ice}, {Blocks.deepwater, Blocks.sandWater, Blocks.sand, Blocks.sand, Blocks.moss, Blocks.moss, Blocks.snow, Blocks.basalt, Blocks.basalt, Blocks.basalt, Blocks.ice, Blocks.snow, Blocks.ice},
{Blocks.taintedWater, Blocks.darksandTaintedWater, Blocks.darksand, Blocks.darksand, Blocks.basalt, Blocks.moss, Blocks.basalt, Blocks.hotrock, Blocks.basalt, Blocks.ice, Blocks.snow, Blocks.ice, Blocks.ice}, {Blocks.deepTaintedWater, Blocks.darksandTaintedWater, Blocks.darksand, Blocks.darksand, Blocks.basalt, Blocks.moss, Blocks.basalt, Blocks.hotrock, Blocks.basalt, Blocks.ice, Blocks.snow, Blocks.ice, Blocks.ice},
{Blocks.darksandWater, Blocks.darksand, Blocks.darksand, Blocks.darksand, Blocks.moss, Blocks.sporeMoss, Blocks.snow, Blocks.basalt, Blocks.basalt, Blocks.ice, Blocks.snow, Blocks.ice, Blocks.ice}, {Blocks.darksandWater, Blocks.darksand, Blocks.darksand, Blocks.darksand, Blocks.moss, Blocks.sporeMoss, Blocks.snow, Blocks.basalt, Blocks.basalt, Blocks.ice, Blocks.snow, Blocks.ice, Blocks.ice},
{Blocks.darksandWater, Blocks.darksand, Blocks.darksand, Blocks.sporeMoss, Blocks.ice, Blocks.ice, Blocks.snow, Blocks.snow, Blocks.snow, Blocks.snow, Blocks.ice, Blocks.ice, Blocks.ice}, {Blocks.darksandWater, Blocks.darksand, Blocks.darksand, Blocks.sporeMoss, Blocks.ice, Blocks.ice, Blocks.snow, Blocks.snow, Blocks.snow, Blocks.snow, Blocks.ice, Blocks.ice, Blocks.ice},
{Blocks.taintedWater, Blocks.darksandTaintedWater, Blocks.darksand, Blocks.sporeMoss, Blocks.sporeMoss, Blocks.ice, Blocks.ice, Blocks.snow, Blocks.snow, Blocks.ice, Blocks.ice, Blocks.ice, Blocks.ice}, {Blocks.deepTaintedWater, Blocks.darksandTaintedWater, Blocks.darksand, Blocks.sporeMoss, Blocks.sporeMoss, Blocks.ice, Blocks.ice, Blocks.snow, Blocks.snow, Blocks.ice, Blocks.ice, Blocks.ice, Blocks.ice},
{Blocks.darksandTaintedWater, Blocks.darksandTaintedWater, Blocks.darksand, Blocks.sporeMoss, Blocks.moss, Blocks.sporeMoss, Blocks.iceSnow, Blocks.snow, Blocks.ice, Blocks.ice, Blocks.ice, Blocks.ice, Blocks.ice}, {Blocks.taintedWater, Blocks.darksandTaintedWater, Blocks.darksand, Blocks.sporeMoss, Blocks.moss, Blocks.sporeMoss, Blocks.iceSnow, Blocks.snow, Blocks.ice, Blocks.ice, Blocks.ice, Blocks.ice, Blocks.ice},
{Blocks.darksandWater, Blocks.darksand, Blocks.snow, Blocks.ice, Blocks.iceSnow, Blocks.snow, Blocks.snow, Blocks.snow, Blocks.ice, Blocks.ice, Blocks.ice, Blocks.ice, Blocks.ice} {Blocks.darksandWater, Blocks.darksand, Blocks.snow, Blocks.ice, Blocks.iceSnow, Blocks.snow, Blocks.snow, Blocks.snow, Blocks.ice, Blocks.ice, Blocks.ice, Blocks.ice, Blocks.ice}
}; };
@@ -255,10 +256,35 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
for(Room room : roomseq){ for(Room room : roomseq){
spawn.connect(room); spawn.connect(room);
} }
Room fspawn = spawn;
cells(1); cells(1);
distort(10f, 6f); distort(10f, 6f);
//rivers
pass((x, y) -> {
if(block.solid) return;
Vec3 v = sector.rect.project(x, y);
float rr = Simplex.noise2d(sector.id, (float)2, 0.6f, 1f / 7f, x, y) * 0.1f;
float value = Ridged.noise3d(2, v.x, v.y, v.z, 1, 1f / 53f) + rr - rawHeight(v) * 0f;
float rrscl = rr * 44 - 2;
if(value > 0.12f && !Mathf.within(x, y, fspawn.x, fspawn.y, 12 + rrscl)){
boolean deep = value > 0.12f + 0.1f && !Mathf.within(x, y, fspawn.x, fspawn.y, 15 + rrscl);
boolean spore = floor != Blocks.sand && floor != Blocks.salt;
//do not place rivers on ice, they're frozen
//ignore pre-existing liquids
if(!(floor == Blocks.ice || floor == Blocks.iceSnow || floor == Blocks.snow || floor.asFloor().isLiquid)){
floor = spore ?
(deep ? Blocks.taintedWater : Blocks.darksandTaintedWater) :
(deep ? Blocks.water :
(floor == Blocks.sand ? Blocks.sandWater : Blocks.darksandWater));
}
}
});
Seq<Block> ores = Seq.with(Blocks.oreCopper, Blocks.oreLead); Seq<Block> ores = Seq.with(Blocks.oreCopper, Blocks.oreLead);
float poles = Math.abs(sector.tile.v.y); float poles = Math.abs(sector.tile.v.y);
float nmag = 0.5f; float nmag = 0.5f;
@@ -326,7 +352,6 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
if(Math.abs(0.5f - noise(x - 40, y, 2, 0.7, 80)) > 0.25f && if(Math.abs(0.5f - noise(x - 40, y, 2, 0.7, 80)) > 0.25f &&
Math.abs(0.5f - noise(x, y + sector.id*10, 1, 1, 60)) > 0.41f && !(roomseq.contains(r -> Mathf.within(x, y, r.x, r.y, 15)))){ Math.abs(0.5f - noise(x, y + sector.id*10, 1, 1, 60)) > 0.41f && !(roomseq.contains(r -> Mathf.within(x, y, r.x, r.y, 15)))){
floor = Blocks.tar; floor = Blocks.tar;
ore = Blocks.air;
} }
} }
@@ -347,7 +372,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
floor = Blocks.magmarock; floor = Blocks.magmarock;
} }
} }
}else if(floor != Blocks.basalt && floor != Blocks.ice && floor.asFloor().hasSurface()){ }else if(genLakes && floor != Blocks.basalt && floor != Blocks.ice && floor.asFloor().hasSurface()){
float noise = noise(x + 782, y, 5, 0.75f, 260f, 1f); float noise = noise(x + 782, y, 5, 0.75f, 260f, 1f);
if(noise > 0.67f && !roomseq.contains(e -> Mathf.within(x, y, e.x, e.y, 14))){ if(noise > 0.67f && !roomseq.contains(e -> Mathf.within(x, y, e.x, e.y, 14))){
if(noise > 0.72f){ if(noise > 0.72f){
@@ -355,7 +380,6 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
}else{ }else{
floor = (floor == Blocks.sand ? floor : Blocks.darksand); floor = (floor == Blocks.sand ? floor : Blocks.darksand);
} }
ore = Blocks.air;
} }
} }
@@ -470,6 +494,13 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
} }
} }
//remove invalid ores
for(Tile tile : tiles){
if(tile.overlay().needsSurface && !tile.floor().hasSurface()){
tile.setOverlay(Blocks.air);
}
}
Schematics.placeLaunchLoadout(spawn.x, spawn.y); Schematics.placeLaunchLoadout(spawn.x, spawn.y);
for(Room espawn : enemies){ for(Room espawn : enemies){
@@ -486,7 +517,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
float waveTimeDec = 0.4f; float waveTimeDec = 0.4f;
state.rules.waveSpacing = Mathf.lerp(60 * 65 * 2, 60f * 60f * 1f, Math.max(difficulty - waveTimeDec, 0f) / 0.8f); state.rules.waveSpacing = Mathf.lerp(60 * 65 * 2, 60f * 60f * 1f, Math.max(difficulty - waveTimeDec, 0f));
state.rules.waves = sector.info.waves = true; state.rules.waves = sector.info.waves = true;
state.rules.enemyCoreBuildRadius = 600f; state.rules.enemyCoreBuildRadius = 600f;

View File

@@ -80,6 +80,8 @@ public class ContentParser{
if(data.isString()){ if(data.isString()){
StatusEffect result = locate(ContentType.status, data.asString()); StatusEffect result = locate(ContentType.status, data.asString());
if(result != null) return result; if(result != null) return result;
result = (StatusEffect)fieldOpt(StatusEffects.class, data);
if(result != null) return result;
throw new IllegalArgumentException("Unknown status effect: '" + data.asString() + "'"); throw new IllegalArgumentException("Unknown status effect: '" + data.asString() + "'");
} }
StatusEffect effect = new StatusEffect(currentMod.name + "-" + data.getString("name")); StatusEffect effect = new StatusEffect(currentMod.name + "-" + data.getString("name"));

View File

@@ -177,7 +177,7 @@ public class Mods implements Loadable{
} }
private void packSprites(Seq<Fi> sprites, LoadedMod mod, boolean prefix, Seq<AsyncResult<Runnable>> tasks){ private void packSprites(Seq<Fi> sprites, LoadedMod mod, boolean prefix, Seq<AsyncResult<Runnable>> tasks){
boolean linear = Core.settings.getBool("linear"); boolean linear = Core.settings.getBool("linear", true);
for(Fi file : sprites){ for(Fi file : sprites){
//read and bleed pixmaps in parallel //read and bleed pixmaps in parallel
@@ -186,7 +186,7 @@ public class Mods implements Loadable{
Pixmap pix = new Pixmap(file.readBytes()); Pixmap pix = new Pixmap(file.readBytes());
//only bleeds when linear filtering is on at startup //only bleeds when linear filtering is on at startup
if(linear){ if(linear){
Pixmaps.bleed(pix); Pixmaps.bleed(pix, 2);
} }
//this returns a *runnable* which actually packs the resulting pixmap; this has to be done synchronously outside the method //this returns a *runnable* which actually packs the resulting pixmap; this has to be done synchronously outside the method
return () -> { return () -> {
@@ -225,6 +225,10 @@ public class Mods implements Loadable{
var shadow = Core.atlas; var shadow = Core.atlas;
//dummy texture atlas that returns the 'shadow' regions; used for mod loading //dummy texture atlas that returns the 'shadow' regions; used for mod loading
Core.atlas = new TextureAtlas(){ Core.atlas = new TextureAtlas(){
{
//needed for the correct operation of the found() method in the TextureRegion
error = shadow.find("error");
}
@Override @Override
public AtlasRegion find(String name){ public AtlasRegion find(String name){
@@ -265,7 +269,7 @@ public class Mods implements Loadable{
} }
}; };
TextureFilter filter = Core.settings.getBool("linear") ? TextureFilter.linear : TextureFilter.nearest; TextureFilter filter = Core.settings.getBool("linear", true) ? TextureFilter.linear : TextureFilter.nearest;
Time.mark(); Time.mark();
//generate new icons //generate new icons

View File

@@ -162,8 +162,10 @@ public class ArcNetProvider implements NetProvider{
client.connect(5000, ip, port, port); client.connect(5000, ip, port, port);
success.run(); success.run();
}catch(Exception e){ }catch(Exception e){
if(netClient.isConnecting()){
net.handleException(e); net.handleException(e);
} }
}
}); });
} }

View File

@@ -39,7 +39,7 @@ public class BeControl{
public BeControl(){ public BeControl(){
if(active()){ if(active()){
Timer.schedule(() -> { Timer.schedule(() -> {
if(Vars.clientLoaded && checkUpdates && !mobile){ if((Vars.clientLoaded || headless) && checkUpdates && !mobile){
checkUpdate(t -> {}); checkUpdate(t -> {});
} }
}, updateInterval, updateInterval); }, updateInterval, updateInterval);

View File

@@ -3,6 +3,7 @@ package mindustry.type;
import arc.*; import arc.*;
import arc.func.*; import arc.func.*;
import arc.graphics.*; import arc.graphics.*;
import arc.graphics.g3d.*;
import arc.math.*; import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.struct.*; import arc.struct.*;
@@ -23,6 +24,8 @@ public class Planet extends UnlockableContent{
private static final Vec3 intersectResult = new Vec3(); private static final Vec3 intersectResult = new Vec3();
/** Mesh used for rendering. Created on load() - will be null on the server! */ /** Mesh used for rendering. Created on load() - will be null on the server! */
public @Nullable PlanetMesh mesh; public @Nullable PlanetMesh mesh;
/** Mesh used for rendering planet clouds. Null if no clouds are present. */
public @Nullable PlanetMesh cloudMesh;
/** Position in global coordinates. Will be 0,0,0 until the Universe updates it. */ /** Position in global coordinates. Will be 0,0,0 until the Universe updates it. */
public Vec3 position = new Vec3(); public Vec3 position = new Vec3();
/** Grid used for the sectors on the planet. Null if this planet can't be landed on. */ /** Grid used for the sectors on the planet. Null if this planet can't be landed on. */
@@ -74,7 +77,7 @@ public class Planet extends UnlockableContent{
/** Satellites orbiting this planet. */ /** Satellites orbiting this planet. */
public Seq<Satellite> satellites = new Seq<>(); public Seq<Satellite> satellites = new Seq<>();
/** Loads the mesh. Clientside only. Defaults to a boring sphere mesh. */ /** Loads the mesh. Clientside only. Defaults to a boring sphere mesh. */
protected Prov<PlanetMesh> meshLoader = () -> new ShaderSphereMesh(this, Shaders.unlit, 2); protected Prov<PlanetMesh> meshLoader = () -> new ShaderSphereMesh(this, Shaders.unlit, 2), cloudMeshLoader = () -> null;
public Planet(String name, Planet parent, int sectorSize, float radius){ public Planet(String name, Planet parent, int sectorSize, float radius){
super(name); super(name);
@@ -220,6 +223,7 @@ public class Planet extends UnlockableContent{
super.load(); super.load();
mesh = meshLoader.get(); mesh = meshLoader.get();
cloudMesh = cloudMeshLoader.get();
} }
@Override @Override
@@ -293,4 +297,28 @@ public class Planet extends UnlockableContent{
public void draw(Mat3D projection, Mat3D transform){ public void draw(Mat3D projection, Mat3D transform){
mesh.render(projection, transform); mesh.render(projection, transform);
} }
public void drawAtmosphere(Mesh atmosphere, Camera3D cam){
//atmosphere does not contribute to depth buffer
Gl.depthMask(false);
Blending.additive.apply();
Shaders.atmosphere.camera = cam;
Shaders.atmosphere.planet = this;
Shaders.atmosphere.bind();
Shaders.atmosphere.apply();
atmosphere.render(Shaders.atmosphere, Gl.triangles);
Blending.normal.apply();
Gl.depthMask(true);
}
public void drawClouds(Mat3D projection, Mat3D transform){
if(cloudMesh != null){
cloudMesh.render(projection, transform);
}
}
} }

View File

@@ -317,6 +317,9 @@ public class UnitType extends UnlockableContent{
canDrown = false; canDrown = false;
omniMovement = false; omniMovement = false;
immunities.add(StatusEffects.wet); immunities.add(StatusEffects.wet);
if(visualElevation < 0f){
visualElevation = 0.11f;
}
} }
if(lightRadius == -1){ if(lightRadius == -1){
@@ -445,7 +448,7 @@ public class UnitType extends UnlockableContent{
if(!packer.has(name + "-outline")){ if(!packer.has(name + "-outline")){
PixmapRegion base = Core.atlas.getPixmap(region); PixmapRegion base = Core.atlas.getPixmap(region);
var result = Pixmaps.outline(base, outlineColor, outlineRadius); var result = Pixmaps.outline(base, outlineColor, outlineRadius);
if(Core.settings.getBool("linear")){ if(Core.settings.getBool("linear", true)){
Pixmaps.bleed(result); Pixmaps.bleed(result);
} }
packer.add(PageType.main, name + "-outline", result); packer.add(PageType.main, name + "-outline", result);
@@ -607,7 +610,7 @@ public class UnitType extends UnlockableContent{
} }
public void drawControl(Unit unit){ public void drawControl(Unit unit){
Draw.z(Layer.groundUnit - 2); Draw.z(unit.isFlying() ? Layer.flyingUnitLow : Layer.groundUnit - 2);
Draw.color(Pal.accent, Color.white, Mathf.absin(4f, 0.3f)); Draw.color(Pal.accent, Color.white, Mathf.absin(4f, 0.3f));
Lines.poly(unit.x, unit.y, 4, unit.hitSize + 1.5f); Lines.poly(unit.x, unit.y, 4, unit.hitSize + 1.5f);
@@ -626,7 +629,7 @@ public class UnitType extends UnlockableContent{
Draw.color(0, 0, 0, 0.4f); Draw.color(0, 0, 0, 0.4f);
float rad = 1.6f; float rad = 1.6f;
float size = Math.max(region.width, region.height) * Draw.scl; float size = Math.max(region.width, region.height) * Draw.scl;
Draw.rect(softShadowRegion, unit, size * rad * Draw.xscl, size * rad * Draw.yscl); Draw.rect(softShadowRegion, unit, size * rad * Draw.xscl, size * rad * Draw.yscl, unit.rotation - 90);
Draw.color(); Draw.color();
} }

View File

@@ -196,12 +196,12 @@ public class Fonts{
size = 18; size = 18;
}}; }};
Core.assets.load("outline", Font.class, new FreeTypeFontLoaderParameter(mainFont, param)).loaded = t -> Fonts.outline = (Font)t; Core.assets.load("outline", Font.class, new FreeTypeFontLoaderParameter(mainFont, param)).loaded = t -> Fonts.outline = t;
Core.assets.load("tech", Font.class, new FreeTypeFontLoaderParameter("fonts/tech.ttf", new FreeTypeFontParameter(){{ Core.assets.load("tech", Font.class, new FreeTypeFontLoaderParameter("fonts/tech.ttf", new FreeTypeFontParameter(){{
size = 18; size = 18;
}})).loaded = f -> { }})).loaded = f -> {
Fonts.tech = (Font)f; Fonts.tech = f;
Fonts.tech.getData().down *= 1.5f; Fonts.tech.getData().down *= 1.5f;
}; };
} }

View File

@@ -1,10 +1,12 @@
package mindustry.ui.dialogs; package mindustry.ui.dialogs;
import arc.*;
import arc.scene.ui.*; import arc.scene.ui.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
import mindustry.ctype.*; import mindustry.ctype.*;
import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.world.meta.*; import mindustry.world.meta.*;
@@ -58,7 +60,6 @@ public class ContentInfoDialog extends BaseDialog{
if(map.size == 0) continue; if(map.size == 0) continue;
//TODO check
if(stats.useCategories){ if(stats.useCategories){
table.add("@category." + cat.name()).color(Pal.accent).fillX(); table.add("@category." + cat.name()).color(Pal.accent).fillX();
table.row(); table.row();
@@ -80,7 +81,7 @@ public class ContentInfoDialog extends BaseDialog{
} }
if(content.details != null){ if(content.details != null){
table.add("[gray]" + content.details).pad(6).padTop(20).width(400f).wrap().fillX(); table.add("[gray]" + (content.unlocked() || !content.hideDetails ? content.details : Iconc.lock + " " + Core.bundle.get("unlock.incampaign"))).pad(6).padTop(20).width(400f).wrap().fillX();
table.row(); table.row();
} }

View File

@@ -36,7 +36,7 @@ public class DatabaseDialog extends BaseDialog{
cont.table(s -> { cont.table(s -> {
s.image(Icon.zoom).padRight(8); s.image(Icon.zoom).padRight(8);
search = s.field(null, text -> rebuild()).growX().get(); search = s.field(null, text -> rebuild()).growX().get();
search.setMessageText(Core.bundle.get("players.search")); search.setMessageText("@players.search");
}).fillX().padBottom(4).row(); }).fillX().padBottom(4).row();
cont.pane(all); cont.pane(all);

View File

@@ -24,6 +24,8 @@ import mindustry.ui.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public class JoinDialog extends BaseDialog{ public class JoinDialog extends BaseDialog{
//TODO unused
Seq<Host> commmunityHosts = new Seq<>();
Seq<Server> servers = new Seq<>(); Seq<Server> servers = new Seq<>();
Dialog add; Dialog add;
Server renaming; Server renaming;
@@ -119,7 +121,7 @@ public class JoinDialog extends BaseDialog{
refreshLocal(); refreshLocal();
refreshRemote(); refreshRemote();
refreshGlobal(); refreshCommunity();
} }
void setupRemote(){ void setupRemote(){
@@ -331,7 +333,7 @@ public class JoinDialog extends BaseDialog{
if(eye){ if(eye){
name.button(Icon.eyeSmall, Styles.emptyi, () -> { name.button(Icon.eyeSmall, Styles.emptyi, () -> {
showHidden = !showHidden; showHidden = !showHidden;
refreshGlobal(); refreshCommunity();
}).update(i -> i.getStyle().imageUp = (showHidden ? Icon.eyeSmall : Icon.eyeOffSmall)) }).update(i -> i.getStyle().imageUp = (showHidden ? Icon.eyeSmall : Icon.eyeOffSmall))
.size(40f).right().padRight(3).tooltip("@servers.showhidden"); .size(40f).right().padRight(3).tooltip("@servers.showhidden");
} }
@@ -357,7 +359,8 @@ public class JoinDialog extends BaseDialog{
net.discoverServers(this::addLocalHost, this::finishLocalHosts); net.discoverServers(this::addLocalHost, this::finishLocalHosts);
} }
void refreshGlobal(){ void refreshCommunity(){
commmunityHosts.clear();
int cur = refreshes; int cur = refreshes;
global.clear(); global.clear();
@@ -378,6 +381,8 @@ public class JoinDialog extends BaseDialog{
if(refreshes != cur) return; if(refreshes != cur) return;
res.port = resport; res.port = resport;
commmunityHosts.add(res);
//add header //add header
if(groupTable[0] == null){ if(groupTable[0] == null){
global.table(t -> groupTable[0] = t).row(); global.table(t -> groupTable[0] = t).row();

View File

@@ -372,8 +372,6 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
} }
if(selectAlpha > 0.001f){ if(selectAlpha > 0.001f){
for(Sector sec : planet.sectors){ for(Sector sec : planet.sectors){
if(sec.hasBase()){ if(sec.hasBase()){
for(Sector enemy : sec.near()){ for(Sector enemy : sec.near()){
@@ -520,7 +518,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
pt.button(planet.localizedName, Styles.clearTogglet, () -> { pt.button(planet.localizedName, Styles.clearTogglet, () -> {
selected = null; selected = null;
launchSector = null; launchSector = null;
if(renderer.planets.planet != planet){
renderer.planets.planet = planet; renderer.planets.planet = planet;
rebuildList();
}
settings.put("lastplanet", planet.name); settings.put("lastplanet", planet.name);
}).width(200).height(40).growX().update(bb -> bb.setChecked(renderer.planets.planet == planet)); }).width(200).height(40).growX().update(bb -> bb.setChecked(renderer.planets.planet == planet));
pt.row(); pt.row();
@@ -749,7 +750,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
c.defaults().padBottom(5); c.defaults().padBottom(5);
if(sector.preset != null && sector.preset.description != null){ if(sector.preset != null && sector.preset.description != null){
c.add(sector.preset.displayDescription()).left().row(); c.add(sector.preset.displayDescription()).width(420f).wrap().left().row();
} }
c.add(Core.bundle.get("sectors.time") + " [accent]" + sector.save.getPlayTime()).left().row(); c.add(Core.bundle.get("sectors.time") + " [accent]" + sector.save.getPlayTime()).left().row();

View File

@@ -60,7 +60,7 @@ public class ResearchDialog extends BaseDialog{
//add global counts of each sector //add global counts of each sector
for(Planet planet : content.planets()){ for(Planet planet : content.planets()){
for(Sector sector : planet.sectors){ for(Sector sector : planet.sectors){
if(sector.hasSave() && sector.hasBase()){ if(sector.hasBase()){
ItemSeq cached = sector.items(); ItemSeq cached = sector.items();
cache.put(sector, cached); cache.put(sector, cached);
cached.each((item, amount) -> { cached.each((item, amount) -> {

View File

@@ -155,7 +155,7 @@ public class SchematicsDialog extends BaseDialog{
}); });
buttons.button(Icon.pencil, style, () -> { buttons.button(Icon.pencil, style, () -> {
new Dialog("@schematic.rename"){{ new BaseDialog("@schematic.rename"){{
setFillParent(true); setFillParent(true);
cont.margin(30); cont.margin(30);

View File

@@ -230,8 +230,12 @@ public class SettingsMenuDialog extends Dialog{
platform.shareFile(logs); platform.shareFile(logs);
}else{ }else{
platform.showFileChooser(false, "txt", file -> { platform.showFileChooser(false, "txt", file -> {
file.writeString(getLogs()); try{
file.writeBytes(getLogs().getBytes(Strings.utf8));
app.post(() -> ui.showInfo("@crash.exported")); app.post(() -> ui.showInfo("@crash.exported"));
}catch(Throwable e){
ui.showException(e);
}
}); });
} }
} }

View File

@@ -176,7 +176,8 @@ public class ChatFragment extends Table{
String message = chatfield.getText().trim(); String message = chatfield.getText().trim();
clearChatInput(); clearChatInput();
if(message.isEmpty()) return; //avoid sending prefix-empty messages
if(message.isEmpty() || (message.startsWith(mode.prefix) && message.substring(mode.prefix.length()).isEmpty())) return;
history.insert(1, message); history.insert(1, message);

View File

@@ -181,6 +181,11 @@ public class HintsFragment extends Fragment{
&& SectorPresets.frozenForest.unlocked() && SectorPresets.frozenForest.unlocked()
&& SectorPresets.frozenForest.sector.save == null, && SectorPresets.frozenForest.sector.save == null,
() -> state.isCampaign() && state.getSector().preset == SectorPresets.frozenForest), () -> state.isCampaign() && state.getSector().preset == SectorPresets.frozenForest),
presetDifficulty(() -> state.isCampaign()
&& state.getSector().preset == null
&& state.getSector().threat >= 0.5f
&& !SectorPresets.tarFields.sector.isCaptured(), //appear only when the player hasn't progressed much in the game yet
() -> state.isCampaign() && state.getSector().preset != null),
coreIncinerate(() -> state.isCampaign() && state.rules.defaultTeam.core() != null && state.rules.defaultTeam.core().items.get(Items.copper) >= state.rules.defaultTeam.core().storageCapacity - 10, () -> false), coreIncinerate(() -> state.isCampaign() && state.rules.defaultTeam.core() != null && state.rules.defaultTeam.core().items.get(Items.copper) >= state.rules.defaultTeam.core().storageCapacity - 10, () -> false),
coopCampaign(() -> net.client() && state.isCampaign() && SectorPresets.groundZero.sector.hasBase(), () -> false), coopCampaign(() -> net.client() && state.isCampaign() && SectorPresets.groundZero.sector.hasBase(), () -> false),
; ;

View File

@@ -207,7 +207,7 @@ public class HudFragment extends Fragment{
logic.skipWave(); logic.skipWave();
} }
}).growY().fillX().right().width(40f).disabled(b -> !canSkipWave()).name("skip"); }).growY().fillX().right().width(40f).disabled(b -> !canSkipWave()).name("skip");
}).width(dsize * 5 + 4f); }).width(dsize * 5 + 4f).name("statustable");
wavesMain.row(); wavesMain.row();

Some files were not shown because too many files have changed in this diff Show More