diff --git a/.gitignore b/.gitignore index b33484f175..00ff121460 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ logs/ /ios/src/io/anuke/mindustry/gen/ /core/src/io/anuke/mindustry/gen/ ios/robovm.properties +packr-out/ config/ *.gif diff --git a/.travis.yml b/.travis.yml index c0f4f1a5e8..8231bc68f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ jdk: - openjdk8 script: +- "git clone --depth=1 --branch=master https://github.com/Anuken/Arc ../Arc" - "./gradlew test" - "./gradlew desktop:dist -Pbuildversion=${TRAVIS_TAG:1}" - "./gradlew server:dist -Pbuildversion=${TRAVIS_TAG:1}" @@ -17,4 +18,4 @@ deploy: - "server/build/libs/server-release.jar" on: repo: Anuken/Mindustry - tags: true \ No newline at end of file + tags: true diff --git a/README.md b/README.md index dd13ce684b..f85d9cb702 100644 --- a/README.md +++ b/README.md @@ -13,21 +13,21 @@ _[Wiki](http://mindustry.wikia.com/wiki/Mindustry_Wiki)_ Bleeding-edge live builds are generated automatically for every commit. You can see them [here](https://jenkins.hellomouse.net/job/mindustry/). If you'd rather compile on your own, follow these instructions. -First, make sure you have Java 8 and JDK 8 installed. Open a terminal in the root directory, and run the following commands: +First, make sure you have Java 8 and JDK 8 installed. Open a terminal in the root directory, `cd` to the Mindustry folder and run the following commands: #### Windows _Running:_ `gradlew desktop:run` _Building:_ `gradlew desktop:dist` -#### Linux +#### Linux/Mac OS _Running:_ `./gradlew desktop:run` _Building:_ `./gradlew desktop:dist` -#### For Server Builds... +#### Server -Server builds are bundled with each released build (in Releases). If you'd rather compile on your own, replace 'desktop' with 'server' i.e. `gradlew server:dist`. +Server builds are bundled with each released build (in Releases). If you'd rather compile on your own, replace 'desktop' with 'server', e.g. `gradlew server:dist`. --- diff --git a/android/build.gradle b/android/build.gradle index 2c3912aeba..f218d1876a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0' + classpath 'com.android.tools.build:gradle:3.3.2' } } diff --git a/android/proguard-project.txt b/android/proguard-project.txt index b166b1e81c..1f34b8cae8 100644 --- a/android/proguard-project.txt +++ b/android/proguard-project.txt @@ -20,26 +20,10 @@ #} -verbose - --dontwarn android.support.** --dontwarn com.badlogic.gdx.backends.android.AndroidFragmentApplication --dontwarn com.badlogic.gdx.utils.GdxBuild --dontwarn com.badlogic.gdx.physics.box2d.utils.Box2DBuild --dontwarn com.badlogic.gdx.jnigen.BuildTarget* --dontwarn com.badlogic.gdx.graphics.g2d.freetype.FreetypeBuild - --keep class com.badlogic.gdx.controllers.android.AndroidControllers - --keepclassmembers class com.badlogic.gdx.backends.android.AndroidInput* { - (com.badlogic.gdx.Application, android.content.Context, java.lang.Object, com.badlogic.gdx.backends.android.AndroidApplicationConfiguration); -} - --keepclassmembers class com.badlogic.gdx.physics.box2d.World { - boolean contactFilter(long, long); - void beginContact(long); - void endContact(long); - void preSolve(long, long); - void postSolve(long, long); - boolean reportFixture(long); - float reportRayFixture(long, float, float, float, float, float); +-verbose +-ignorewarnings +-keep class io.anuke.mindustry.game.Rules +-keep class io.anuke.mindustry.desktop.DesktopLauncher +-keepclasseswithmembers public class * { + public static void main(java.lang.String[]); } diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java index 8fbb105dc4..323352d9eb 100644 --- a/android/src/io/anuke/mindustry/AndroidLauncher.java +++ b/android/src/io/anuke/mindustry/AndroidLauncher.java @@ -172,10 +172,10 @@ public class AndroidLauncher extends AndroidApplication{ SaveSlot slot = control.saves.importSave(file); ui.load.runLoadSave(slot); }catch(IOException e){ - ui.showError(Core.bundle.format("text.save.import.fail", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, false))); } }else{ - ui.showError("$text.save.import.invalid"); + ui.showError("$save.import.invalid"); } }else if(map){ //open map Core.app.post(() -> { diff --git a/annotations/src/main/java/io/anuke/annotations/Annotations.java b/annotations/src/main/java/io/anuke/annotations/Annotations.java index eae4030b44..ce7832f76d 100644 --- a/annotations/src/main/java/io/anuke/annotations/Annotations.java +++ b/annotations/src/main/java/io/anuke/annotations/Annotations.java @@ -14,6 +14,21 @@ public class Annotations{ } + /** Marks a class as a special value type struct. Class name must end in 'Struct'.*/ + @Target(ElementType.TYPE) + @Retention(RetentionPolicy.SOURCE) + public @interface Struct{ + + } + + /**Marks a field of a struct. Optional.*/ + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.SOURCE) + public @interface StructField{ + /**Size of a struct field in bits. Not valid on booleans or floating point numbers.*/ + int value(); + } + public enum PacketPriority{ /** Gets put in a queue and processed if not connected. */ normal, diff --git a/annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java b/annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java index 61382d3f24..69dbe29f8b 100644 --- a/annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java +++ b/annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java @@ -2,8 +2,6 @@ package io.anuke.annotations; import com.squareup.javapoet.*; import io.anuke.annotations.IOFinder.ClassSerializer; -import io.anuke.annotations.MethodEntry; -import io.anuke.annotations.Utils; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; @@ -52,7 +50,7 @@ public class RemoteReadGenerator{ Constructor cons = TypeName.class.getDeclaredConstructor(String.class); cons.setAccessible(true); - TypeName playerType = cons.newInstance("io.anuke.mindustry.entities.Player"); + TypeName playerType = cons.newInstance("io.anuke.mindustry.entities.type.Player"); //add player parameter readMethod.addParameter(playerType, "player"); } diff --git a/annotations/src/main/java/io/anuke/annotations/RemoteWriteGenerator.java b/annotations/src/main/java/io/anuke/annotations/RemoteWriteGenerator.java index 62cff1f25b..2f195aa896 100644 --- a/annotations/src/main/java/io/anuke/annotations/RemoteWriteGenerator.java +++ b/annotations/src/main/java/io/anuke/annotations/RemoteWriteGenerator.java @@ -80,7 +80,7 @@ public class RemoteWriteGenerator{ return; } - if(!elem.getParameters().get(0).asType().toString().equals("io.anuke.mindustry.entities.Player")){ + if(!elem.getParameters().get(0).asType().toString().equals("io.anuke.mindustry.entities.type.Player")){ Utils.messager.printMessage(Kind.ERROR, "Client invoke methods should have a first parameter of type Player.", elem); return; } diff --git a/annotations/src/main/java/io/anuke/annotations/StructAnnotationProcessor.java b/annotations/src/main/java/io/anuke/annotations/StructAnnotationProcessor.java new file mode 100644 index 0000000000..dca27b6fa1 --- /dev/null +++ b/annotations/src/main/java/io/anuke/annotations/StructAnnotationProcessor.java @@ -0,0 +1,229 @@ +package io.anuke.annotations; + +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import io.anuke.annotations.Annotations.Struct; +import io.anuke.annotations.Annotations.StructField; + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.util.ElementFilter; +import javax.tools.Diagnostic.Kind; +import java.util.List; +import java.util.Set; + +/**Generates ""value types"" classes that are packed into integer primitives of the most aproppriate size. + * It would be nice if Java didn't make crazy hacks like this necessary.*/ +@SupportedSourceVersion(SourceVersion.RELEASE_8) +@SupportedAnnotationTypes({ + "io.anuke.annotations.Annotations.Struct" +}) +public class StructAnnotationProcessor extends AbstractProcessor{ + /** Name of the base package to put all the generated classes. */ + private static final String packageName = "io.anuke.mindustry.gen"; + private int round; + + @Override + public synchronized void init(ProcessingEnvironment processingEnv){ + super.init(processingEnv); + //put all relevant utils into utils class + Utils.typeUtils = processingEnv.getTypeUtils(); + Utils.elementUtils = processingEnv.getElementUtils(); + Utils.filer = processingEnv.getFiler(); + Utils.messager = processingEnv.getMessager(); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv){ + if(round++ != 0) return false; //only process 1 round + + try{ + Set elements = ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Struct.class)); + + for(TypeElement elem : elements){ + + if(!elem.getSimpleName().toString().endsWith("Struct")){ + Utils.messager.printMessage(Kind.ERROR, "All classes annotated with @Struct must have their class names end in 'Struct'.", elem); + continue; + } + + String structName = elem.getSimpleName().toString().substring(0, elem.getSimpleName().toString().length() - "Struct".length()); + String structParam = structName.toLowerCase(); + + TypeSpec.Builder classBuilder = TypeSpec.classBuilder(structName) + .addModifiers(Modifier.FINAL, Modifier.PUBLIC); + + try{ + List variables = ElementFilter.fieldsIn(elem.getEnclosedElements()); + int structSize = variables.stream().mapToInt(StructAnnotationProcessor::varSize).sum(); + int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64); + + if(variables.size() == 0){ + Utils.messager.printMessage(Kind.ERROR, "making a struct with no fields is utterly pointles.", elem); + continue; + } + + //obtain type which will be stored + Class structType = typeForSize(structSize); + + //[constructor] get(fields...) : structType + MethodSpec.Builder constructor = MethodSpec.methodBuilder("get") + .addModifiers(Modifier.STATIC, Modifier.PUBLIC) + .returns(structType); + + StringBuilder cons = new StringBuilder(); + StringBuilder doc = new StringBuilder(); + doc.append("Bits used: ").append(structSize).append(" / ").append(structTotalSize).append("\n"); + + int offset = 0; + for(VariableElement var : variables){ + int size = varSize(var); + TypeName varType = TypeName.get(var.asType()); + String varName = var.getSimpleName().toString(); + + //add val param to constructor + constructor.addParameter(varType, varName); + + //[get] field(structType) : fieldType + MethodSpec.Builder getter = MethodSpec.methodBuilder(var.getSimpleName().toString()) + .addModifiers(Modifier.STATIC, Modifier.PUBLIC) + .returns(varType) + .addParameter(structType, structParam); + //[set] field(structType, fieldType) : structType + MethodSpec.Builder setter = MethodSpec.methodBuilder(var.getSimpleName().toString()) + .addModifiers(Modifier.STATIC, Modifier.PUBLIC) + .returns(structType) + .addParameter(structType, structParam).addParameter(varType, "value"); + + //[getter] + if(varType == TypeName.BOOLEAN){ + //bools: single bit, is simplified + getter.addStatement("return ($L & (1L << $L)) != 0", structParam, offset); + }else if(varType == TypeName.FLOAT){ + //floats: need conversion + getter.addStatement("return Float.intBitsToFloat((int)(($L >>> $L) & $L))", structParam, offset, bitString(size, structTotalSize)); + }else{ + //bytes, shorts, chars, ints + getter.addStatement("return ($T)(($L >>> $L) & $L)", varType, structParam, offset, bitString(size, structTotalSize)); + } + + //[setter] + [constructor building] + if(varType == TypeName.BOOLEAN){ + cons.append(" | (").append(varName).append(" ? ").append("1L << ").append(offset).append("L : 0)"); + + //bools: single bit, needs special case to clear things + setter.beginControlFlow("if(value)"); + setter.addStatement("return ($T)(($L & ~(1L << $LL)))", structType, structParam, offset); + setter.nextControlFlow("else"); + setter.addStatement("return ($T)(($L & ~(1L << $LL)) | (1L << $LL))", structType, structParam, offset, offset); + setter.endControlFlow(); + }else if(varType == TypeName.FLOAT){ + cons.append(" | (").append("(").append(structType).append(")").append("Float.floatToIntBits(").append(varName).append(") << ").append(offset).append("L)"); + + //floats: need conversion + setter.addStatement("return ($T)(($L & $L) | (($T)Float.floatToIntBits(value) << $LL))", structType, structParam, bitString(offset, size, structTotalSize), structType, offset); + }else{ + cons.append(" | (").append("(").append(structType).append(")").append(varName).append(" << ").append(offset).append("L)"); + + //bytes, shorts, chars, ints + setter.addStatement("return ($T)(($L & $L) | (($T)value << $LL))", structType, structParam, bitString(offset, size, structTotalSize), structType, offset); + } + + doc.append("
").append(varName).append(" [").append(offset).append("..").append(size + offset).append("]\n"); + + //add finished methods + classBuilder.addMethod(getter.build()); + classBuilder.addMethod(setter.build()); + + offset += size; + } + + classBuilder.addJavadoc(doc.toString()); + + //add constructor final statement + add to class and build + constructor.addStatement("return ($T)($L)", structType, cons.toString().substring(3)); + classBuilder.addMethod(constructor.build()); + + JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer); + }catch(IllegalArgumentException e){ + e.printStackTrace(); + Utils.messager.printMessage(Kind.ERROR, e.getMessage(), elem); + } + } + + return true; + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + static String bitString(int offset, int size, int totalSize){ + StringBuilder builder = new StringBuilder(); + for(int i = 0; i < offset; i++) builder.append('0'); + for(int i = 0; i < size; i++) builder.append('1'); + for(int i = 0; i < totalSize - size - offset; i++) builder.append('0'); + return "0b" + builder.reverse().toString() + "L"; + } + + static String bitString(int size, int totalSize){ + StringBuilder builder = new StringBuilder(); + for(int i = 0; i < size; i++) builder.append('1'); + for(int i = 0; i < totalSize - size; i++) builder.append('0'); + return "0b" + builder.reverse().toString() + "L"; + } + + static int varSize(VariableElement var) throws IllegalArgumentException{ + if(!var.asType().getKind().isPrimitive()){ + throw new IllegalArgumentException("All struct fields must be primitives: " + var); + } + + StructField an = var.getAnnotation(StructField.class); + if(var.asType().getKind() == TypeKind.BOOLEAN && an != null && an.value() != 1){ + throw new IllegalArgumentException("Booleans can only be one bit long... why would you do this?"); + } + + if(var.asType().getKind() == TypeKind.FLOAT && an != null && an.value() != 32){ + throw new IllegalArgumentException("Float size can't be changed. Very sad."); + } + + return an == null ? typeSize(var.asType().getKind()) : an.value(); + } + + static Class typeForSize(int size) throws IllegalArgumentException{ + if(size <= 8){ + return byte.class; + }else if(size <= 16){ + return short.class; + }else if(size <= 32){ + return int.class; + }else if(size <= 64){ + return long.class; + } + throw new IllegalArgumentException("Too many fields, must fit in 64 bits. Curent size: " + size); + } + + /**returns a type's element size in bits.*/ + static int typeSize(TypeKind kind) throws IllegalArgumentException{ + switch(kind){ + case BOOLEAN: + return 1; + case BYTE: + return 8; + case SHORT: + return 16; + case FLOAT: + case CHAR: + case INT: + return 32; + default: + throw new IllegalArgumentException("Invalid type kind: " + kind + ". Note that doubles and longs are not supported."); + } + } +} diff --git a/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor index a83673baa6..af76756139 100644 --- a/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ b/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -1,2 +1,3 @@ io.anuke.annotations.RemoteMethodAnnotationProcessor io.anuke.annotations.SerializeAnnotationProcessor +io.anuke.annotations.StructAnnotationProcessor diff --git a/build.gradle b/build.gradle index 249dacf7ba..74fb990a22 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,7 @@ buildscript{ dependencies{ classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.5' classpath "com.badlogicgames.gdx:gdx-tools:1.9.9" + classpath "com.badlogicgames.packr:packr:2.1-SNAPSHOT" } } @@ -20,12 +21,16 @@ allprojects{ ext{ versionNumber = '4' - versionModifier = 'alpha' + versionModifier = 'beta' if(!project.hasProperty("versionType")) versionType = 'official' appName = 'Mindustry' gdxVersion = '1.9.9' roboVMVersion = '2.3.0' arcHash = null + + debugged = { + return new File(projectDir.parent, '../debug').exists() && System.properties["release"] == null + } localArc = { return (System.properties["release"] == null || System.properties["release"] == "false") && new File(projectDir.parent, '../Arc').exists() @@ -35,7 +40,7 @@ allprojects{ //get latest commit hash from gtihub since JITPack's '-snapshot' version doesn't work correctly if(arcHash == null){ try{ - arcHash = 'git ls-remote https://github.com/Anuken/Arc.git'.execute().text.split("\t")[0]//new JsonSlurper().parse(new URL("https://api.github.com/repos/Anuken/Arc/commits/master"))["sha"] + arcHash = 'git ls-remote https://github.com/Anuken/Arc.git'.execute().text.split("\t")[0] }catch(e){ e.printStackTrace() arcHash = "-SNAPSHOT"; @@ -117,7 +122,7 @@ project(":desktop"){ compile project(":core") compile project(":net") - if(new File(projectDir.parent, '../debug').exists() && System.properties["release"] == null) compile project(":debug") + if(debugged()) compile project(":debug") compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop" @@ -194,6 +199,7 @@ project(":core"){ compile arcModule("arc-core") compile arcModule("extensions:freetype") + if(localArc() && debugged()) compile arcModule("extensions:recorder") compileOnly project(":annotations") annotationProcessor project(":annotations") diff --git a/core/assets-raw/fonts/cyrillic/Exo2-Regular.ttf b/core/assets-raw/fonts/Exo2-Regular.ttf similarity index 100% rename from core/assets-raw/fonts/cyrillic/Exo2-Regular.ttf rename to core/assets-raw/fonts/Exo2-Regular.ttf diff --git a/core/assets-raw/fonts/NanumBarunGothic.ttf b/core/assets-raw/fonts/NanumBarunGothic.ttf new file mode 100644 index 0000000000..658cd3c239 Binary files /dev/null and b/core/assets-raw/fonts/NanumBarunGothic.ttf differ diff --git a/core/assets-raw/fonts/OpenSansEmoji.ttf b/core/assets-raw/fonts/OpenSansEmoji.ttf new file mode 100644 index 0000000000..57d86a62bb Binary files /dev/null and b/core/assets-raw/fonts/OpenSansEmoji.ttf differ diff --git a/core/assets-raw/fonts/chinese/wqy-microhei.ttc b/core/assets-raw/fonts/chinese/wqy-microhei.ttc deleted file mode 100644 index 2c9bc2d4e0..0000000000 Binary files a/core/assets-raw/fonts/chinese/wqy-microhei.ttc and /dev/null differ diff --git a/core/assets-raw/fonts/font_latin.ttf b/core/assets-raw/fonts/font_latin.ttf new file mode 100644 index 0000000000..cebae09c33 Binary files /dev/null and b/core/assets-raw/fonts/font_latin.ttf differ diff --git a/core/assets-raw/fonts/korean/Sunflower-Medium.ttf b/core/assets-raw/fonts/korean/Sunflower-Medium.ttf deleted file mode 100644 index ad37058a5c..0000000000 Binary files a/core/assets-raw/fonts/korean/Sunflower-Medium.ttf and /dev/null differ diff --git a/core/assets-raw/fonts/pixel_UNEDITED.ttf b/core/assets-raw/fonts/pixel_UNEDITED.ttf deleted file mode 100644 index 3be17ee696..0000000000 Binary files a/core/assets-raw/fonts/pixel_UNEDITED.ttf and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/distribution/mass-driver-base.png b/core/assets-raw/sprites/blocks/distribution/mass-driver-base.png new file mode 100644 index 0000000000..93be68da7a Binary files /dev/null and b/core/assets-raw/sprites/blocks/distribution/mass-driver-base.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/mass-driver-turret.png b/core/assets-raw/sprites/blocks/distribution/mass-driver-turret.png deleted file mode 100644 index 4e2d5dca5f..0000000000 Binary files a/core/assets-raw/sprites/blocks/distribution/mass-driver-turret.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/distribution/mass-driver.png b/core/assets-raw/sprites/blocks/distribution/mass-driver.png index 93be68da7a..4e2d5dca5f 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/mass-driver.png and b/core/assets-raw/sprites/blocks/distribution/mass-driver.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/warp-gate-top.png b/core/assets-raw/sprites/blocks/distribution/warp-gate-top.png deleted file mode 100644 index 57ec334c4e..0000000000 Binary files a/core/assets-raw/sprites/blocks/distribution/warp-gate-top.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/distribution/warp-gate.png b/core/assets-raw/sprites/blocks/distribution/warp-gate.png deleted file mode 100644 index 6ccfb3b703..0000000000 Binary files a/core/assets-raw/sprites/blocks/distribution/warp-gate.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/drills/blast-drill-rim.png b/core/assets-raw/sprites/blocks/drills/blast-drill-rim.png index 611d85060b..05b5f843a1 100644 Binary files a/core/assets-raw/sprites/blocks/drills/blast-drill-rim.png and b/core/assets-raw/sprites/blocks/drills/blast-drill-rim.png differ diff --git a/core/assets-raw/sprites/blocks/drills/blast-drill-rotator.png b/core/assets-raw/sprites/blocks/drills/blast-drill-rotator.png index fe87720d61..f216e3f0b3 100644 Binary files a/core/assets-raw/sprites/blocks/drills/blast-drill-rotator.png and b/core/assets-raw/sprites/blocks/drills/blast-drill-rotator.png differ diff --git a/core/assets-raw/sprites/blocks/drills/blast-drill-top.png b/core/assets-raw/sprites/blocks/drills/blast-drill-top.png index 106df26337..45c3aff97f 100644 Binary files a/core/assets-raw/sprites/blocks/drills/blast-drill-top.png and b/core/assets-raw/sprites/blocks/drills/blast-drill-top.png differ diff --git a/core/assets-raw/sprites/blocks/drills/blast-drill.png b/core/assets-raw/sprites/blocks/drills/blast-drill.png index 703d4bf7de..22ffe595a5 100644 Binary files a/core/assets-raw/sprites/blocks/drills/blast-drill.png and b/core/assets-raw/sprites/blocks/drills/blast-drill.png differ diff --git a/core/assets-raw/sprites/blocks/drills/laser-drill-rim.png b/core/assets-raw/sprites/blocks/drills/laser-drill-rim.png new file mode 100644 index 0000000000..611d85060b Binary files /dev/null and b/core/assets-raw/sprites/blocks/drills/laser-drill-rim.png differ diff --git a/core/assets-raw/sprites/blocks/drills/laser-drill-rotator.png b/core/assets-raw/sprites/blocks/drills/laser-drill-rotator.png index b28c8f43b0..f58528f84f 100644 Binary files a/core/assets-raw/sprites/blocks/drills/laser-drill-rotator.png and b/core/assets-raw/sprites/blocks/drills/laser-drill-rotator.png differ diff --git a/core/assets-raw/sprites/blocks/drills/laser-drill-top.png b/core/assets-raw/sprites/blocks/drills/laser-drill-top.png index 5239a1a5fe..46d9519881 100644 Binary files a/core/assets-raw/sprites/blocks/drills/laser-drill-top.png and b/core/assets-raw/sprites/blocks/drills/laser-drill-top.png differ diff --git a/core/assets-raw/sprites/blocks/drills/laser-drill.png b/core/assets-raw/sprites/blocks/drills/laser-drill.png index eb94d28b65..97e620dfb3 100644 Binary files a/core/assets-raw/sprites/blocks/drills/laser-drill.png and b/core/assets-raw/sprites/blocks/drills/laser-drill.png differ diff --git a/core/assets-raw/sprites/blocks/drills/oil-extractor-top.png b/core/assets-raw/sprites/blocks/drills/oil-extractor-top.png index 37bebd60c1..ba07cbb184 100644 Binary files a/core/assets-raw/sprites/blocks/drills/oil-extractor-top.png and b/core/assets-raw/sprites/blocks/drills/oil-extractor-top.png differ diff --git a/core/assets-raw/sprites/blocks/drills/oil-extractor.png b/core/assets-raw/sprites/blocks/drills/oil-extractor.png index e137d2e773..8d363c44cb 100644 Binary files a/core/assets-raw/sprites/blocks/drills/oil-extractor.png and b/core/assets-raw/sprites/blocks/drills/oil-extractor.png differ diff --git a/core/assets-raw/sprites/blocks/drills/plasma-drill-rim.png b/core/assets-raw/sprites/blocks/drills/plasma-drill-rim.png deleted file mode 100644 index 05b5f843a1..0000000000 Binary files a/core/assets-raw/sprites/blocks/drills/plasma-drill-rim.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/drills/plasma-drill-rotator.png b/core/assets-raw/sprites/blocks/drills/plasma-drill-rotator.png deleted file mode 100644 index f216e3f0b3..0000000000 Binary files a/core/assets-raw/sprites/blocks/drills/plasma-drill-rotator.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/drills/plasma-drill-top.png b/core/assets-raw/sprites/blocks/drills/plasma-drill-top.png deleted file mode 100644 index 45c3aff97f..0000000000 Binary files a/core/assets-raw/sprites/blocks/drills/plasma-drill-top.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/drills/plasma-drill.png b/core/assets-raw/sprites/blocks/drills/plasma-drill.png deleted file mode 100644 index 1ca3ea1903..0000000000 Binary files a/core/assets-raw/sprites/blocks/drills/plasma-drill.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/blackrock1.png b/core/assets-raw/sprites/blocks/environment/blackrock1.png deleted file mode 100644 index 4a43dbe023..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/blackrock1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/blackstone1.png b/core/assets-raw/sprites/blocks/environment/blackstone1.png deleted file mode 100644 index 5bc819ae4e..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/blackstone1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/blackstone2.png b/core/assets-raw/sprites/blocks/environment/blackstone2.png deleted file mode 100644 index 458d40c265..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/blackstone2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/blackstone3.png b/core/assets-raw/sprites/blocks/environment/blackstone3.png deleted file mode 100644 index cd064a04cd..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/blackstone3.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/blackstoneedge.png b/core/assets-raw/sprites/blocks/environment/blackstoneedge.png deleted file mode 100644 index 0bd91906aa..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/blackstoneedge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/char1.png b/core/assets-raw/sprites/blocks/environment/char1.png new file mode 100644 index 0000000000..47203a89c7 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/char1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/char2.png b/core/assets-raw/sprites/blocks/environment/char2.png new file mode 100644 index 0000000000..7ded27b4fd Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/char2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/char3.png b/core/assets-raw/sprites/blocks/environment/char3.png new file mode 100644 index 0000000000..482ecb48ab Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/char3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/cliffs1.png b/core/assets-raw/sprites/blocks/environment/cliffs1.png new file mode 100644 index 0000000000..f07190276d Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/cliffs1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/craters1.png b/core/assets-raw/sprites/blocks/environment/craters1.png index b2aa5461bc..e819484335 100644 Binary files a/core/assets-raw/sprites/blocks/environment/craters1.png and b/core/assets-raw/sprites/blocks/environment/craters1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/craters2.png b/core/assets-raw/sprites/blocks/environment/craters2.png index 6286436fd2..f33ee31d60 100644 Binary files a/core/assets-raw/sprites/blocks/environment/craters2.png and b/core/assets-raw/sprites/blocks/environment/craters2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/craters3.png b/core/assets-raw/sprites/blocks/environment/craters3.png index 4b1dc35be7..36a73ab5a5 100644 Binary files a/core/assets-raw/sprites/blocks/environment/craters3.png and b/core/assets-raw/sprites/blocks/environment/craters3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/craters4.png b/core/assets-raw/sprites/blocks/environment/craters4.png new file mode 100644 index 0000000000..57c362e366 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/craters4.png differ diff --git a/core/assets-raw/sprites/blocks/environment/craters5.png b/core/assets-raw/sprites/blocks/environment/craters5.png new file mode 100644 index 0000000000..684ebd3e2b Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/craters5.png differ diff --git a/core/assets-raw/sprites/blocks/environment/craters6.png b/core/assets-raw/sprites/blocks/environment/craters6.png new file mode 100644 index 0000000000..2ee1c2dfd1 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/craters6.png differ diff --git a/core/assets-raw/sprites/blocks/environment/deepwater.png b/core/assets-raw/sprites/blocks/environment/deepwater.png index bc4f5312d3..869752084b 100644 Binary files a/core/assets-raw/sprites/blocks/environment/deepwater.png and b/core/assets-raw/sprites/blocks/environment/deepwater.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dirt1.png b/core/assets-raw/sprites/blocks/environment/dirt1.png deleted file mode 100644 index 8738655fe7..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/dirt1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/dirt2.png b/core/assets-raw/sprites/blocks/environment/dirt2.png deleted file mode 100644 index 9e04571b90..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/dirt2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/dirt3.png b/core/assets-raw/sprites/blocks/environment/dirt3.png deleted file mode 100644 index c62c7dcc36..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/dirt3.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/dirtedge.png b/core/assets-raw/sprites/blocks/environment/dirtedge.png deleted file mode 100644 index 9e2a03cd15..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/dirtedge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/dunerocks-large.png b/core/assets-raw/sprites/blocks/environment/dunerocks-large.png new file mode 100644 index 0000000000..44f6a2f372 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/dunerocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dunerocks1.png b/core/assets-raw/sprites/blocks/environment/dunerocks1.png new file mode 100644 index 0000000000..384904fa48 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/dunerocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dunerocks2.png b/core/assets-raw/sprites/blocks/environment/dunerocks2.png new file mode 100644 index 0000000000..0409649b3f Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/dunerocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/edge-stencil-blocky.png b/core/assets-raw/sprites/blocks/environment/edge-stencil-blocky.png new file mode 100644 index 0000000000..e9e15f64bb Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/edge-stencil-blocky.png differ diff --git a/core/assets-raw/sprites/blocks/environment/edge-stencil-smooth.png b/core/assets-raw/sprites/blocks/environment/edge-stencil-smooth.png new file mode 100644 index 0000000000..ae245b60c4 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/edge-stencil-smooth.png differ diff --git a/core/assets-raw/sprites/blocks/environment/generic-cliff-edge-1.png b/core/assets-raw/sprites/blocks/environment/generic-cliff-edge-1.png deleted file mode 100644 index eccc9e20a5..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/generic-cliff-edge-1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/generic-cliff-edge-2.png b/core/assets-raw/sprites/blocks/environment/generic-cliff-edge-2.png deleted file mode 100644 index d88235bed9..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/generic-cliff-edge-2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/generic-cliff-edge.png b/core/assets-raw/sprites/blocks/environment/generic-cliff-edge.png deleted file mode 100644 index e93dd6f1ac..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/generic-cliff-edge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/generic-cliff-side.png b/core/assets-raw/sprites/blocks/environment/generic-cliff-side.png deleted file mode 100644 index 33bc3ca031..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/generic-cliff-side.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/grass1.png b/core/assets-raw/sprites/blocks/environment/grass1.png index 1e600d144d..abc7231016 100644 Binary files a/core/assets-raw/sprites/blocks/environment/grass1.png and b/core/assets-raw/sprites/blocks/environment/grass1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/grass2.png b/core/assets-raw/sprites/blocks/environment/grass2.png index 5bdfe6cc8e..33d2cef85f 100644 Binary files a/core/assets-raw/sprites/blocks/environment/grass2.png and b/core/assets-raw/sprites/blocks/environment/grass2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/grass3.png b/core/assets-raw/sprites/blocks/environment/grass3.png index 6ce88c3d74..a0e5014795 100644 Binary files a/core/assets-raw/sprites/blocks/environment/grass3.png and b/core/assets-raw/sprites/blocks/environment/grass3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/grassedge.png b/core/assets-raw/sprites/blocks/environment/grassedge.png deleted file mode 100644 index f4e2a53254..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/grassedge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/holostone1.png b/core/assets-raw/sprites/blocks/environment/holostone1.png new file mode 100644 index 0000000000..7e9ea228b2 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/holostone1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/holostone2.png b/core/assets-raw/sprites/blocks/environment/holostone2.png new file mode 100644 index 0000000000..1c0c94d197 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/holostone2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/holostone3.png b/core/assets-raw/sprites/blocks/environment/holostone3.png new file mode 100644 index 0000000000..928118bee8 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/holostone3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/hotrock1.png b/core/assets-raw/sprites/blocks/environment/hotrock1.png new file mode 100644 index 0000000000..f7c566bf06 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/hotrock1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/hotrock2.png b/core/assets-raw/sprites/blocks/environment/hotrock2.png new file mode 100644 index 0000000000..41586d523b Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/hotrock2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/hotrock3.png b/core/assets-raw/sprites/blocks/environment/hotrock3.png new file mode 100644 index 0000000000..cc72227234 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/hotrock3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ice-edge.png b/core/assets-raw/sprites/blocks/environment/ice-edge.png new file mode 100644 index 0000000000..0355b50f3a Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/ice-edge.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ice-snow1.png b/core/assets-raw/sprites/blocks/environment/ice-snow1.png new file mode 100644 index 0000000000..23764ff1cc Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/ice-snow1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ice-snow2.png b/core/assets-raw/sprites/blocks/environment/ice-snow2.png new file mode 100644 index 0000000000..538943b64c Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/ice-snow2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ice-snow3.png b/core/assets-raw/sprites/blocks/environment/ice-snow3.png new file mode 100644 index 0000000000..2e56e2e7e7 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/ice-snow3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ice1.png b/core/assets-raw/sprites/blocks/environment/ice1.png index dd7af2fd0d..f27c916fa2 100644 Binary files a/core/assets-raw/sprites/blocks/environment/ice1.png and b/core/assets-raw/sprites/blocks/environment/ice1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ice2.png b/core/assets-raw/sprites/blocks/environment/ice2.png index fa8e08f161..463317a9d2 100644 Binary files a/core/assets-raw/sprites/blocks/environment/ice2.png and b/core/assets-raw/sprites/blocks/environment/ice2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ice3.png b/core/assets-raw/sprites/blocks/environment/ice3.png index 73908890a1..21e0023570 100644 Binary files a/core/assets-raw/sprites/blocks/environment/ice3.png and b/core/assets-raw/sprites/blocks/environment/ice3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/iceedge.png b/core/assets-raw/sprites/blocks/environment/iceedge.png deleted file mode 100644 index 7065c36213..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/iceedge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/icerock1.png b/core/assets-raw/sprites/blocks/environment/icerock1.png deleted file mode 100644 index d81cdfcc84..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/icerock1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/icerock2.png b/core/assets-raw/sprites/blocks/environment/icerock2.png deleted file mode 100644 index e5adab47a2..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/icerock2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/icerocks-large.png b/core/assets-raw/sprites/blocks/environment/icerocks-large.png new file mode 100644 index 0000000000..79671701fa Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/icerocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/icerocks1.png b/core/assets-raw/sprites/blocks/environment/icerocks1.png new file mode 100644 index 0000000000..ca5db6fedf Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/icerocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/icerocks2.png b/core/assets-raw/sprites/blocks/environment/icerocks2.png new file mode 100644 index 0000000000..b2dd1a0cee Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/icerocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ignarock1.png b/core/assets-raw/sprites/blocks/environment/ignarock1.png new file mode 100644 index 0000000000..c329cb2f15 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/ignarock1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ignarock2.png b/core/assets-raw/sprites/blocks/environment/ignarock2.png new file mode 100644 index 0000000000..08834e87af Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/ignarock2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ignarock3.png b/core/assets-raw/sprites/blocks/environment/ignarock3.png new file mode 100644 index 0000000000..eb0af3a572 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/ignarock3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/lava.png b/core/assets-raw/sprites/blocks/environment/lava.png deleted file mode 100644 index 4f1f9cfe10..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/lava.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/lavaedge.png b/core/assets-raw/sprites/blocks/environment/lavaedge.png deleted file mode 100644 index fc8a770308..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/lavaedge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/magmarock1.png b/core/assets-raw/sprites/blocks/environment/magmarock1.png new file mode 100644 index 0000000000..05d62c8859 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/magmarock1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/magmarock2.png b/core/assets-raw/sprites/blocks/environment/magmarock2.png new file mode 100644 index 0000000000..65640ff22c Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/magmarock2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/magmarock3.png b/core/assets-raw/sprites/blocks/environment/magmarock3.png new file mode 100644 index 0000000000..07dbf8366d Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/magmarock3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-2.png b/core/assets-raw/sprites/blocks/environment/metal-floor-2.png new file mode 100644 index 0000000000..8d3b818096 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/metal-floor-2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-3.png b/core/assets-raw/sprites/blocks/environment/metal-floor-3.png new file mode 100644 index 0000000000..eb6b15d03b Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/metal-floor-3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-5.png b/core/assets-raw/sprites/blocks/environment/metal-floor-5.png new file mode 100644 index 0000000000..e9d39b3db2 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/metal-floor-5.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged1.png b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged1.png new file mode 100644 index 0000000000..e4220e9adc Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged2.png b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged2.png new file mode 100644 index 0000000000..a74ac3897d Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged3.png b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged3.png new file mode 100644 index 0000000000..2f07315bc5 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged4.png b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged4.png new file mode 100644 index 0000000000..64027a66f1 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged4.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged5.png b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged5.png new file mode 100644 index 0000000000..9c9b48708b Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged5.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor-damaged6.png b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged6.png new file mode 100644 index 0000000000..f2b7f15be5 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/metal-floor-damaged6.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metal-floor.png b/core/assets-raw/sprites/blocks/environment/metal-floor.png new file mode 100644 index 0000000000..049e13a3ae Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/metal-floor.png differ diff --git a/core/assets-raw/sprites/blocks/environment/metalfloor1.png b/core/assets-raw/sprites/blocks/environment/metalfloor1.png deleted file mode 100644 index 2c625b7a77..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/metalfloor1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/metalfloor2.png b/core/assets-raw/sprites/blocks/environment/metalfloor2.png deleted file mode 100644 index 74c443f2f1..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/metalfloor2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/metalfloor3.png b/core/assets-raw/sprites/blocks/environment/metalfloor3.png deleted file mode 100644 index 1215611d66..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/metalfloor3.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/metalfloor4.png b/core/assets-raw/sprites/blocks/environment/metalfloor4.png deleted file mode 100644 index 937133c441..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/metalfloor4.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/metalfloor5.png b/core/assets-raw/sprites/blocks/environment/metalfloor5.png deleted file mode 100644 index 1d5e775c80..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/metalfloor5.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/metalfloor6.png b/core/assets-raw/sprites/blocks/environment/metalfloor6.png deleted file mode 100644 index a14136822c..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/metalfloor6.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/metalflooredge.png b/core/assets-raw/sprites/blocks/environment/metalflooredge.png deleted file mode 100644 index b8089a6c63..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/metalflooredge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/moss1.png b/core/assets-raw/sprites/blocks/environment/moss1.png new file mode 100644 index 0000000000..8344698387 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/moss1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/moss2.png b/core/assets-raw/sprites/blocks/environment/moss2.png new file mode 100644 index 0000000000..ed1a8981fb Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/moss2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/moss3.png b/core/assets-raw/sprites/blocks/environment/moss3.png new file mode 100644 index 0000000000..ea5072a8dd Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/moss3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/pack.json b/core/assets-raw/sprites/blocks/environment/pack.json new file mode 100644 index 0000000000..91480ffa76 --- /dev/null +++ b/core/assets-raw/sprites/blocks/environment/pack.json @@ -0,0 +1,8 @@ +{ + duplicatePadding: true, + combineSubdirectories: true, + flattenPaths: true, + maxWidth: 2048, + maxHeight: 2048, + fast: true, +} diff --git a/core/assets-raw/sprites/blocks/environment/pine.png b/core/assets-raw/sprites/blocks/environment/pine.png new file mode 100644 index 0000000000..13eee73aaa Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/pine.png differ diff --git a/core/assets-raw/sprites/blocks/environment/rock1.png b/core/assets-raw/sprites/blocks/environment/rock1.png index d1e645a279..034b6b2fb6 100644 Binary files a/core/assets-raw/sprites/blocks/environment/rock1.png and b/core/assets-raw/sprites/blocks/environment/rock1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/rock2.png b/core/assets-raw/sprites/blocks/environment/rock2.png index f696f51f77..9f29ee1517 100644 Binary files a/core/assets-raw/sprites/blocks/environment/rock2.png and b/core/assets-raw/sprites/blocks/environment/rock2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/rocks-large.png b/core/assets-raw/sprites/blocks/environment/rocks-large.png new file mode 100644 index 0000000000..391ce2f941 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/rocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/rocks1.png b/core/assets-raw/sprites/blocks/environment/rocks1.png index 01d5f670b5..907519e3a9 100644 Binary files a/core/assets-raw/sprites/blocks/environment/rocks1.png and b/core/assets-raw/sprites/blocks/environment/rocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/rocks2.png b/core/assets-raw/sprites/blocks/environment/rocks2.png index 44c4928519..e9b0151176 100644 Binary files a/core/assets-raw/sprites/blocks/environment/rocks2.png and b/core/assets-raw/sprites/blocks/environment/rocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand1.png b/core/assets-raw/sprites/blocks/environment/sand1.png index 6ef1e28bc0..73e2c6d635 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sand1.png and b/core/assets-raw/sprites/blocks/environment/sand1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand2.png b/core/assets-raw/sprites/blocks/environment/sand2.png index 05bedd0bc3..4429bb584b 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sand2.png and b/core/assets-raw/sprites/blocks/environment/sand2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand3.png b/core/assets-raw/sprites/blocks/environment/sand3.png index 69b1dd2ec7..c358be019b 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sand3.png and b/core/assets-raw/sprites/blocks/environment/sand3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sandedge.png b/core/assets-raw/sprites/blocks/environment/sandedge.png deleted file mode 100644 index 51b4c9f290..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/sandedge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/sandrocks-large.png b/core/assets-raw/sprites/blocks/environment/sandrocks-large.png new file mode 100644 index 0000000000..d91729fb22 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/sandrocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sandrocks1.png b/core/assets-raw/sprites/blocks/environment/sandrocks1.png new file mode 100644 index 0000000000..5df0ef7fe1 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/sandrocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sandrocks2.png b/core/assets-raw/sprites/blocks/environment/sandrocks2.png new file mode 100644 index 0000000000..70a4cea724 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/sandrocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/scrap1.png b/core/assets-raw/sprites/blocks/environment/scrap1.png index c509773e5b..2a72eb2a06 100644 Binary files a/core/assets-raw/sprites/blocks/environment/scrap1.png and b/core/assets-raw/sprites/blocks/environment/scrap1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/scrap2.png b/core/assets-raw/sprites/blocks/environment/scrap2.png index 567a887bf7..dd2503dfce 100644 Binary files a/core/assets-raw/sprites/blocks/environment/scrap2.png and b/core/assets-raw/sprites/blocks/environment/scrap2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/scrap3.png b/core/assets-raw/sprites/blocks/environment/scrap3.png index f491b722e8..39c65cc1b0 100644 Binary files a/core/assets-raw/sprites/blocks/environment/scrap3.png and b/core/assets-raw/sprites/blocks/environment/scrap3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/shrub.png b/core/assets-raw/sprites/blocks/environment/shrub.png deleted file mode 100644 index 74335d79cd..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/shrub.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/snow1.png b/core/assets-raw/sprites/blocks/environment/snow1.png index 87ffafe61c..25042c14c5 100644 Binary files a/core/assets-raw/sprites/blocks/environment/snow1.png and b/core/assets-raw/sprites/blocks/environment/snow1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/snow2.png b/core/assets-raw/sprites/blocks/environment/snow2.png index 96c0889c85..2ef4c13aca 100644 Binary files a/core/assets-raw/sprites/blocks/environment/snow2.png and b/core/assets-raw/sprites/blocks/environment/snow2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/snow3.png b/core/assets-raw/sprites/blocks/environment/snow3.png index 7695fa4265..79c9b36ab7 100644 Binary files a/core/assets-raw/sprites/blocks/environment/snow3.png and b/core/assets-raw/sprites/blocks/environment/snow3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/snowedge.png b/core/assets-raw/sprites/blocks/environment/snowedge.png deleted file mode 100644 index b3d088df1f..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/snowedge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/snowrocks-large.png b/core/assets-raw/sprites/blocks/environment/snowrocks-large.png new file mode 100644 index 0000000000..75017dbee1 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/snowrocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/snowrocks1.png b/core/assets-raw/sprites/blocks/environment/snowrocks1.png new file mode 100644 index 0000000000..5a18216caa Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/snowrocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/snowrocks2.png b/core/assets-raw/sprites/blocks/environment/snowrocks2.png new file mode 100644 index 0000000000..d3f14dc536 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/snowrocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/space.png b/core/assets-raw/sprites/blocks/environment/space.png deleted file mode 100644 index 9d8e9aade9..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/space.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/spaceedge.png b/core/assets-raw/sprites/blocks/environment/spaceedge.png deleted file mode 100644 index 20f01523c5..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/spaceedge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/spore-cluster1.png b/core/assets-raw/sprites/blocks/environment/spore-cluster1.png new file mode 100644 index 0000000000..89a95e4f5f Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/spore-cluster1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/spore-cluster2.png b/core/assets-raw/sprites/blocks/environment/spore-cluster2.png new file mode 100644 index 0000000000..c8975c0472 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/spore-cluster2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/spore-cluster3.png b/core/assets-raw/sprites/blocks/environment/spore-cluster3.png new file mode 100644 index 0000000000..c1a4749033 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/spore-cluster3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-boulder1.png b/core/assets-raw/sprites/blocks/environment/stained-boulder1.png new file mode 100644 index 0000000000..66f88b2a06 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-boulder1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-boulder2.png b/core/assets-raw/sprites/blocks/environment/stained-boulder2.png new file mode 100644 index 0000000000..4b45697887 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-boulder2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-large.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-large.png new file mode 100644 index 0000000000..ec311cc1fc Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-rocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-red-large.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-red-large.png new file mode 100644 index 0000000000..1697abb808 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-rocks-red-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-red1.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-red1.png new file mode 100644 index 0000000000..e646fcbba3 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-rocks-red1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-red2.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-red2.png new file mode 100644 index 0000000000..f85c1882bc Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-rocks-red2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow-large.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow-large.png new file mode 100644 index 0000000000..055bd4cc44 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow1.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow1.png new file mode 100644 index 0000000000..9e59a807c8 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow2.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow2.png new file mode 100644 index 0000000000..4788cb582a Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks1.png b/core/assets-raw/sprites/blocks/environment/stained-rocks1.png new file mode 100644 index 0000000000..e0aa379812 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-rocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks2.png b/core/assets-raw/sprites/blocks/environment/stained-rocks2.png new file mode 100644 index 0000000000..7b6eabb5d1 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-rocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone-red1.png b/core/assets-raw/sprites/blocks/environment/stained-stone-red1.png new file mode 100644 index 0000000000..78250c48d9 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-stone-red1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone-red2.png b/core/assets-raw/sprites/blocks/environment/stained-stone-red2.png new file mode 100644 index 0000000000..baae667241 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-stone-red2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone-red3.png b/core/assets-raw/sprites/blocks/environment/stained-stone-red3.png new file mode 100644 index 0000000000..f069c248ae Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-stone-red3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone-yellow1.png b/core/assets-raw/sprites/blocks/environment/stained-stone-yellow1.png new file mode 100644 index 0000000000..874ba9b380 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-stone-yellow1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone-yellow2.png b/core/assets-raw/sprites/blocks/environment/stained-stone-yellow2.png new file mode 100644 index 0000000000..20b285b768 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-stone-yellow2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone-yellow3.png b/core/assets-raw/sprites/blocks/environment/stained-stone-yellow3.png new file mode 100644 index 0000000000..2a92d862be Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-stone-yellow3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stainedrocks-large.png b/core/assets-raw/sprites/blocks/environment/stainedrocks-large.png new file mode 100644 index 0000000000..46c60a3be4 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stainedrocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stainedrocks1.png b/core/assets-raw/sprites/blocks/environment/stainedrocks1.png new file mode 100644 index 0000000000..d8af4693e9 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stainedrocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stainedrocks2.png b/core/assets-raw/sprites/blocks/environment/stainedrocks2.png new file mode 100644 index 0000000000..7a8d8b178b Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stainedrocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stone-cliff-edge-1.png b/core/assets-raw/sprites/blocks/environment/stone-cliff-edge-1.png deleted file mode 100644 index d86f0adfea..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stone-cliff-edge-1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stone-cliff-edge-2.png b/core/assets-raw/sprites/blocks/environment/stone-cliff-edge-2.png deleted file mode 100644 index f0f94d1d3a..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stone-cliff-edge-2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stone-cliff-edge.png b/core/assets-raw/sprites/blocks/environment/stone-cliff-edge.png deleted file mode 100644 index bc3492afc5..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stone-cliff-edge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stone-cliff-side.png b/core/assets-raw/sprites/blocks/environment/stone-cliff-side.png deleted file mode 100644 index d6bd37c898..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stone-cliff-side.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stone1.png b/core/assets-raw/sprites/blocks/environment/stone1.png index 8664e25bbc..684ebd3e2b 100644 Binary files a/core/assets-raw/sprites/blocks/environment/stone1.png and b/core/assets-raw/sprites/blocks/environment/stone1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stone2.png b/core/assets-raw/sprites/blocks/environment/stone2.png index f938a042f5..2ee1c2dfd1 100644 Binary files a/core/assets-raw/sprites/blocks/environment/stone2.png and b/core/assets-raw/sprites/blocks/environment/stone2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stone3.png b/core/assets-raw/sprites/blocks/environment/stone3.png index ad8c8c1501..baf4ec6835 100644 Binary files a/core/assets-raw/sprites/blocks/environment/stone3.png and b/core/assets-raw/sprites/blocks/environment/stone3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stoneedge.png b/core/assets-raw/sprites/blocks/environment/stoneedge.png deleted file mode 100644 index 0a8b5cc987..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stoneedge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/taredge.png b/core/assets-raw/sprites/blocks/environment/taredge.png deleted file mode 100644 index e7f2a2182d..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/taredge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/titanium1.png b/core/assets-raw/sprites/blocks/environment/titanium1.png index 2496e3bc4c..95bc34dd60 100644 Binary files a/core/assets-raw/sprites/blocks/environment/titanium1.png and b/core/assets-raw/sprites/blocks/environment/titanium1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/titanium2.png b/core/assets-raw/sprites/blocks/environment/titanium2.png index edf8b6db31..68d021abe7 100644 Binary files a/core/assets-raw/sprites/blocks/environment/titanium2.png and b/core/assets-raw/sprites/blocks/environment/titanium2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/titanium3.png b/core/assets-raw/sprites/blocks/environment/titanium3.png index bdb5d318fb..e4bb5b45dd 100644 Binary files a/core/assets-raw/sprites/blocks/environment/titanium3.png and b/core/assets-raw/sprites/blocks/environment/titanium3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/water-cliff-edge-1.png b/core/assets-raw/sprites/blocks/environment/water-cliff-edge-1.png deleted file mode 100644 index d9dc5602b8..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/water-cliff-edge-1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/water-cliff-edge-2.png b/core/assets-raw/sprites/blocks/environment/water-cliff-edge-2.png deleted file mode 100644 index 9bc0ee1962..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/water-cliff-edge-2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/water-cliff-edge.png b/core/assets-raw/sprites/blocks/environment/water-cliff-edge.png deleted file mode 100644 index 460663e57d..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/water-cliff-edge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/water-cliff-side.png b/core/assets-raw/sprites/blocks/environment/water-cliff-side.png deleted file mode 100644 index 7e0402fa97..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/water-cliff-side.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/water.png b/core/assets-raw/sprites/blocks/environment/water.png deleted file mode 100644 index b923481473..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/water.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/wateredge.png b/core/assets-raw/sprites/blocks/environment/wateredge.png deleted file mode 100644 index 5dcc17b20e..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/wateredge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/white-tree-dead.png b/core/assets-raw/sprites/blocks/environment/white-tree-dead.png new file mode 100644 index 0000000000..adc18507bb Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/white-tree-dead.png differ diff --git a/core/assets-raw/sprites/blocks/environment/white-tree.png b/core/assets-raw/sprites/blocks/environment/white-tree.png new file mode 100644 index 0000000000..a6e26a8ede Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/white-tree.png differ diff --git a/core/assets-raw/sprites/blocks/extra/block-border.png b/core/assets-raw/sprites/blocks/extra/block-border.png index 84969075fb..f28df6c095 100644 Binary files a/core/assets-raw/sprites/blocks/extra/block-border.png and b/core/assets-raw/sprites/blocks/extra/block-border.png differ diff --git a/core/assets-raw/sprites/blocks/extra/place-arrow.png b/core/assets-raw/sprites/blocks/extra/place-arrow.png index 3e0ca09fa2..e9a33f74c1 100644 Binary files a/core/assets-raw/sprites/blocks/extra/place-arrow.png and b/core/assets-raw/sprites/blocks/extra/place-arrow.png differ diff --git a/core/assets-raw/sprites/blocks/extra/rubble-4-0.png b/core/assets-raw/sprites/blocks/extra/rubble-4-0.png new file mode 100644 index 0000000000..0a23d121b1 Binary files /dev/null and b/core/assets-raw/sprites/blocks/extra/rubble-4-0.png differ diff --git a/core/assets-raw/sprites/blocks/extra/rubble-4-1.png b/core/assets-raw/sprites/blocks/extra/rubble-4-1.png new file mode 100644 index 0000000000..0bc32c92a7 Binary files /dev/null and b/core/assets-raw/sprites/blocks/extra/rubble-4-1.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/liquid-router-bottom.png b/core/assets-raw/sprites/blocks/liquid/liquid-router-bottom.png index f5b9f85edc..248aa61266 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/liquid-router-bottom.png and b/core/assets-raw/sprites/blocks/liquid/liquid-router-bottom.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/liquid-tank-bottom.png b/core/assets-raw/sprites/blocks/liquid/liquid-tank-bottom.png index 61791af364..b3d4a432a9 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/liquid-tank-bottom.png and b/core/assets-raw/sprites/blocks/liquid/liquid-tank-bottom.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/mechanical-pump.png b/core/assets-raw/sprites/blocks/liquid/mechanical-pump.png index 9900f26875..b92420f1c3 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/mechanical-pump.png and b/core/assets-raw/sprites/blocks/liquid/mechanical-pump.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/thermal-pump.png b/core/assets-raw/sprites/blocks/liquid/thermal-pump.png index 47d5349d23..c89ff8890d 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/thermal-pump.png and b/core/assets-raw/sprites/blocks/liquid/thermal-pump.png differ diff --git a/core/assets-raw/sprites/blocks/mechs/alpha-mech-pad.png b/core/assets-raw/sprites/blocks/mechs/alpha-dart-mech-pad.png similarity index 100% rename from core/assets-raw/sprites/blocks/mechs/alpha-mech-pad.png rename to core/assets-raw/sprites/blocks/mechs/alpha-dart-mech-pad.png diff --git a/core/assets-raw/sprites/blocks/mechs/dart-ship-pad.png b/core/assets-raw/sprites/blocks/mechs/dart-ship-pad.png deleted file mode 100644 index 112c9e6ebd..0000000000 Binary files a/core/assets-raw/sprites/blocks/mechs/dart-ship-pad.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/power/battery-large.png b/core/assets-raw/sprites/blocks/power/battery-large.png index e140bf1bd0..fb5c37bf18 100644 Binary files a/core/assets-raw/sprites/blocks/power/battery-large.png and b/core/assets-raw/sprites/blocks/power/battery-large.png differ diff --git a/core/assets-raw/sprites/blocks/power/battery.png b/core/assets-raw/sprites/blocks/power/battery.png index 902ab6a6c3..527ab35d5a 100644 Binary files a/core/assets-raw/sprites/blocks/power/battery.png and b/core/assets-raw/sprites/blocks/power/battery.png differ diff --git a/core/assets-raw/sprites/blocks/power/combustion-generator.png b/core/assets-raw/sprites/blocks/power/combustion-generator.png index 2c10d22506..bc22c6fc55 100644 Binary files a/core/assets-raw/sprites/blocks/power/combustion-generator.png and b/core/assets-raw/sprites/blocks/power/combustion-generator.png differ diff --git a/core/assets-raw/sprites/blocks/power/differential-generator-top.png b/core/assets-raw/sprites/blocks/power/differential-generator-top.png new file mode 100644 index 0000000000..a540f2b93c Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/differential-generator-top.png differ diff --git a/core/assets-raw/sprites/blocks/power/differential-generator.png b/core/assets-raw/sprites/blocks/power/differential-generator.png new file mode 100644 index 0000000000..adf332a1e9 Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/differential-generator.png differ diff --git a/core/assets-raw/sprites/blocks/power/fusion-reactor-bottom.png b/core/assets-raw/sprites/blocks/power/fusion-reactor-bottom.png deleted file mode 100644 index 3960ab07af..0000000000 Binary files a/core/assets-raw/sprites/blocks/power/fusion-reactor-bottom.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/power/fusion-reactor-top.png b/core/assets-raw/sprites/blocks/power/fusion-reactor-top.png deleted file mode 100644 index baa449e990..0000000000 Binary files a/core/assets-raw/sprites/blocks/power/fusion-reactor-top.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/power/impact-reactor-bottom.png b/core/assets-raw/sprites/blocks/power/impact-reactor-bottom.png new file mode 100644 index 0000000000..e43c25e404 Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/impact-reactor-bottom.png differ diff --git a/core/assets-raw/sprites/blocks/power/fusion-reactor-light.png b/core/assets-raw/sprites/blocks/power/impact-reactor-light.png similarity index 100% rename from core/assets-raw/sprites/blocks/power/fusion-reactor-light.png rename to core/assets-raw/sprites/blocks/power/impact-reactor-light.png diff --git a/core/assets-raw/sprites/blocks/power/fusion-reactor-plasma-0.png b/core/assets-raw/sprites/blocks/power/impact-reactor-plasma-0.png similarity index 100% rename from core/assets-raw/sprites/blocks/power/fusion-reactor-plasma-0.png rename to core/assets-raw/sprites/blocks/power/impact-reactor-plasma-0.png diff --git a/core/assets-raw/sprites/blocks/power/fusion-reactor-plasma-1.png b/core/assets-raw/sprites/blocks/power/impact-reactor-plasma-1.png similarity index 100% rename from core/assets-raw/sprites/blocks/power/fusion-reactor-plasma-1.png rename to core/assets-raw/sprites/blocks/power/impact-reactor-plasma-1.png diff --git a/core/assets-raw/sprites/blocks/power/fusion-reactor-plasma-2.png b/core/assets-raw/sprites/blocks/power/impact-reactor-plasma-2.png similarity index 100% rename from core/assets-raw/sprites/blocks/power/fusion-reactor-plasma-2.png rename to core/assets-raw/sprites/blocks/power/impact-reactor-plasma-2.png diff --git a/core/assets-raw/sprites/blocks/power/fusion-reactor-plasma-3.png b/core/assets-raw/sprites/blocks/power/impact-reactor-plasma-3.png similarity index 100% rename from core/assets-raw/sprites/blocks/power/fusion-reactor-plasma-3.png rename to core/assets-raw/sprites/blocks/power/impact-reactor-plasma-3.png diff --git a/core/assets-raw/sprites/blocks/power/impact-reactor-top.png b/core/assets-raw/sprites/blocks/power/impact-reactor-top.png new file mode 100644 index 0000000000..b564994c56 Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/impact-reactor-top.png differ diff --git a/core/assets-raw/sprites/blocks/power/fusion-reactor.png b/core/assets-raw/sprites/blocks/power/impact-reactor.png similarity index 100% rename from core/assets-raw/sprites/blocks/power/fusion-reactor.png rename to core/assets-raw/sprites/blocks/power/impact-reactor.png diff --git a/core/assets-raw/sprites/blocks/power/power-node-large.png b/core/assets-raw/sprites/blocks/power/power-node-large.png index 7af50508f5..95d43bb0b2 100644 Binary files a/core/assets-raw/sprites/blocks/power/power-node-large.png and b/core/assets-raw/sprites/blocks/power/power-node-large.png differ diff --git a/core/assets-raw/sprites/blocks/power/power-node.png b/core/assets-raw/sprites/blocks/power/power-node.png index 3e3a043d2d..2081207f2a 100644 Binary files a/core/assets-raw/sprites/blocks/power/power-node.png and b/core/assets-raw/sprites/blocks/power/power-node.png differ diff --git a/core/assets-raw/sprites/blocks/power/power-source.png b/core/assets-raw/sprites/blocks/power/power-source.png index 5a14712e46..079397e307 100644 Binary files a/core/assets-raw/sprites/blocks/power/power-source.png and b/core/assets-raw/sprites/blocks/power/power-source.png differ diff --git a/core/assets-raw/sprites/blocks/power/power-void.png b/core/assets-raw/sprites/blocks/power/power-void.png index 5634353f59..4506ce2f99 100644 Binary files a/core/assets-raw/sprites/blocks/power/power-void.png and b/core/assets-raw/sprites/blocks/power/power-void.png differ diff --git a/core/assets-raw/sprites/blocks/power/solar-panel-large.png b/core/assets-raw/sprites/blocks/power/solar-panel-large.png index 6dfa4d7c59..d226e9f8b8 100644 Binary files a/core/assets-raw/sprites/blocks/power/solar-panel-large.png and b/core/assets-raw/sprites/blocks/power/solar-panel-large.png differ diff --git a/core/assets-raw/sprites/blocks/power/surge-tower.png b/core/assets-raw/sprites/blocks/power/surge-tower.png new file mode 100644 index 0000000000..50ad5a1852 Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/surge-tower.png differ diff --git a/core/assets-raw/sprites/blocks/power/turbine-generator.png b/core/assets-raw/sprites/blocks/power/turbine-generator.png index 566b38a505..246f90efe9 100644 Binary files a/core/assets-raw/sprites/blocks/power/turbine-generator.png and b/core/assets-raw/sprites/blocks/power/turbine-generator.png differ diff --git a/core/assets-raw/sprites/blocks/production/alloy-smelter-top.png b/core/assets-raw/sprites/blocks/production/alloy-smelter-top.png index 04220393c4..52616bf864 100644 Binary files a/core/assets-raw/sprites/blocks/production/alloy-smelter-top.png and b/core/assets-raw/sprites/blocks/production/alloy-smelter-top.png differ diff --git a/core/assets-raw/sprites/blocks/production/alloy-smelter.png b/core/assets-raw/sprites/blocks/production/alloy-smelter.png index a80b7e0727..3226e4efb9 100644 Binary files a/core/assets-raw/sprites/blocks/production/alloy-smelter.png and b/core/assets-raw/sprites/blocks/production/alloy-smelter.png differ diff --git a/core/assets-raw/sprites/blocks/production/biomattercompressor-frame0.png b/core/assets-raw/sprites/blocks/production/biomattercompressor-frame0.png deleted file mode 100644 index 1e46dc766e..0000000000 Binary files a/core/assets-raw/sprites/blocks/production/biomattercompressor-frame0.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/production/biomattercompressor-frame1.png b/core/assets-raw/sprites/blocks/production/biomattercompressor-frame1.png deleted file mode 100644 index a4675cb48f..0000000000 Binary files a/core/assets-raw/sprites/blocks/production/biomattercompressor-frame1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/production/biomattercompressor-frame2.png b/core/assets-raw/sprites/blocks/production/biomattercompressor-frame2.png deleted file mode 100644 index 26c5cf37c3..0000000000 Binary files a/core/assets-raw/sprites/blocks/production/biomattercompressor-frame2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/production/biomattercompressor.png b/core/assets-raw/sprites/blocks/production/biomattercompressor.png deleted file mode 100644 index 5af8cffe15..0000000000 Binary files a/core/assets-raw/sprites/blocks/production/biomattercompressor.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/production/centrifuge-liquid.png b/core/assets-raw/sprites/blocks/production/centrifuge-liquid.png deleted file mode 100644 index 9c215f6166..0000000000 Binary files a/core/assets-raw/sprites/blocks/production/centrifuge-liquid.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/production/centrifuge.png b/core/assets-raw/sprites/blocks/production/centrifuge.png deleted file mode 100644 index 281fb35a9d..0000000000 Binary files a/core/assets-raw/sprites/blocks/production/centrifuge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/production/cultivator-top.png b/core/assets-raw/sprites/blocks/production/cultivator-top.png index 7aacfdb839..c665608609 100644 Binary files a/core/assets-raw/sprites/blocks/production/cultivator-top.png and b/core/assets-raw/sprites/blocks/production/cultivator-top.png differ diff --git a/core/assets-raw/sprites/blocks/production/graphite-press.png b/core/assets-raw/sprites/blocks/production/graphite-press.png new file mode 100644 index 0000000000..57d5c43969 Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/graphite-press.png differ diff --git a/core/assets-raw/sprites/blocks/production/item-void.png b/core/assets-raw/sprites/blocks/production/item-void.png index 1b0af09978..ebd286c3ac 100644 Binary files a/core/assets-raw/sprites/blocks/production/item-void.png and b/core/assets-raw/sprites/blocks/production/item-void.png differ diff --git a/core/assets-raw/sprites/blocks/production/arc-smelter-top.png b/core/assets-raw/sprites/blocks/production/kiln-top.png similarity index 100% rename from core/assets-raw/sprites/blocks/production/arc-smelter-top.png rename to core/assets-raw/sprites/blocks/production/kiln-top.png diff --git a/core/assets-raw/sprites/blocks/production/arc-smelter.png b/core/assets-raw/sprites/blocks/production/kiln.png similarity index 100% rename from core/assets-raw/sprites/blocks/production/arc-smelter.png rename to core/assets-raw/sprites/blocks/production/kiln.png diff --git a/core/assets-raw/sprites/blocks/production/multi-press.png b/core/assets-raw/sprites/blocks/production/multi-press.png new file mode 100644 index 0000000000..3adb9c84f1 Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/multi-press.png differ diff --git a/core/assets-raw/sprites/blocks/production/oilrefinery.png b/core/assets-raw/sprites/blocks/production/oilrefinery.png deleted file mode 100644 index b6fdea3228..0000000000 Binary files a/core/assets-raw/sprites/blocks/production/oilrefinery.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/production/plastanium-compressor.png b/core/assets-raw/sprites/blocks/production/plastanium-compressor.png index 4bd9a0098f..8bcbc2c911 100644 Binary files a/core/assets-raw/sprites/blocks/production/plastanium-compressor.png and b/core/assets-raw/sprites/blocks/production/plastanium-compressor.png differ diff --git a/core/assets-raw/sprites/blocks/production/pulverizer.png b/core/assets-raw/sprites/blocks/production/pulverizer.png index 670f682ff9..0a215af405 100644 Binary files a/core/assets-raw/sprites/blocks/production/pulverizer.png and b/core/assets-raw/sprites/blocks/production/pulverizer.png differ diff --git a/core/assets-raw/sprites/blocks/production/separator-liquid.png b/core/assets-raw/sprites/blocks/production/separator-liquid.png index 8b06086201..18897e6b0f 100644 Binary files a/core/assets-raw/sprites/blocks/production/separator-liquid.png and b/core/assets-raw/sprites/blocks/production/separator-liquid.png differ diff --git a/core/assets-raw/sprites/blocks/production/separator.png b/core/assets-raw/sprites/blocks/production/separator.png index a7896abda7..623bc76bba 100644 Binary files a/core/assets-raw/sprites/blocks/production/separator.png and b/core/assets-raw/sprites/blocks/production/separator.png differ diff --git a/core/assets-raw/sprites/blocks/production/silicon-smelter.png b/core/assets-raw/sprites/blocks/production/silicon-smelter.png index 8bfea1e265..a1e7a82e89 100644 Binary files a/core/assets-raw/sprites/blocks/production/silicon-smelter.png and b/core/assets-raw/sprites/blocks/production/silicon-smelter.png differ diff --git a/core/assets-raw/sprites/blocks/production/solidifer.png b/core/assets-raw/sprites/blocks/production/solidifer.png deleted file mode 100644 index e84862dc9a..0000000000 Binary files a/core/assets-raw/sprites/blocks/production/solidifer.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/production/spore-press-frame0.png b/core/assets-raw/sprites/blocks/production/spore-press-frame0.png new file mode 100644 index 0000000000..58a7284a74 Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/spore-press-frame0.png differ diff --git a/core/assets-raw/sprites/blocks/production/spore-press-frame1.png b/core/assets-raw/sprites/blocks/production/spore-press-frame1.png new file mode 100644 index 0000000000..9d6b5fba03 Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/spore-press-frame1.png differ diff --git a/core/assets-raw/sprites/blocks/production/spore-press-frame2.png b/core/assets-raw/sprites/blocks/production/spore-press-frame2.png new file mode 100644 index 0000000000..8899a23501 Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/spore-press-frame2.png differ diff --git a/core/assets-raw/sprites/blocks/production/biomattercompressor-liquid.png b/core/assets-raw/sprites/blocks/production/spore-press-liquid.png similarity index 100% rename from core/assets-raw/sprites/blocks/production/biomattercompressor-liquid.png rename to core/assets-raw/sprites/blocks/production/spore-press-liquid.png diff --git a/core/assets-raw/sprites/blocks/production/biomattercompressor-top.png b/core/assets-raw/sprites/blocks/production/spore-press-top.png similarity index 100% rename from core/assets-raw/sprites/blocks/production/biomattercompressor-top.png rename to core/assets-raw/sprites/blocks/production/spore-press-top.png diff --git a/core/assets-raw/sprites/blocks/production/spore-press.png b/core/assets-raw/sprites/blocks/production/spore-press.png new file mode 100644 index 0000000000..def84f6512 Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/spore-press.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-foundation.png b/core/assets-raw/sprites/blocks/storage/core-foundation.png new file mode 100644 index 0000000000..83e3b25c9f Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-foundation.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-nucleus.png b/core/assets-raw/sprites/blocks/storage/core-nucleus.png new file mode 100644 index 0000000000..9619e83c9d Binary files /dev/null and b/core/assets-raw/sprites/blocks/storage/core-nucleus.png differ diff --git a/core/assets-raw/sprites/blocks/storage/core-open.png b/core/assets-raw/sprites/blocks/storage/core-open.png deleted file mode 100644 index 627a4bce64..0000000000 Binary files a/core/assets-raw/sprites/blocks/storage/core-open.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/storage/core-top.png b/core/assets-raw/sprites/blocks/storage/core-shard-top.png similarity index 100% rename from core/assets-raw/sprites/blocks/storage/core-top.png rename to core/assets-raw/sprites/blocks/storage/core-shard-top.png diff --git a/core/assets-raw/sprites/blocks/storage/core.png b/core/assets-raw/sprites/blocks/storage/core-shard.png similarity index 100% rename from core/assets-raw/sprites/blocks/storage/core.png rename to core/assets-raw/sprites/blocks/storage/core-shard.png diff --git a/core/assets-raw/sprites/blocks/storage/launch-pad.png b/core/assets-raw/sprites/blocks/storage/launch-pad.png index b74d9f00e2..cc192f5edb 100644 Binary files a/core/assets-raw/sprites/blocks/storage/launch-pad.png and b/core/assets-raw/sprites/blocks/storage/launch-pad.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/arc-heat.png b/core/assets-raw/sprites/blocks/turrets/arc-heat.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/arc-heat.png rename to core/assets-raw/sprites/blocks/turrets/arc-heat.png diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/arc.png b/core/assets-raw/sprites/blocks/turrets/arc.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/arc.png rename to core/assets-raw/sprites/blocks/turrets/arc.png diff --git a/core/assets-raw/sprites/blocks/turrets/bases/block-1-top.png b/core/assets-raw/sprites/blocks/turrets/bases/block-1-top.png deleted file mode 100644 index 3df51ef476..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/bases/block-1-top.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/bases/block-2-top.png b/core/assets-raw/sprites/blocks/turrets/bases/block-2-top.png deleted file mode 100644 index 0662ec043d..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/bases/block-2-top.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/bases/block-2.png b/core/assets-raw/sprites/blocks/turrets/bases/block-2.png index 63f2f93057..2a1522f8fb 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/bases/block-2.png and b/core/assets-raw/sprites/blocks/turrets/bases/block-2.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/bases/block-3-top.png b/core/assets-raw/sprites/blocks/turrets/bases/block-3-top.png deleted file mode 100644 index 01fea4f5ab..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/bases/block-3-top.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/bases/block-3.png b/core/assets-raw/sprites/blocks/turrets/bases/block-3.png index ec95108038..019c25f183 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/bases/block-3.png and b/core/assets-raw/sprites/blocks/turrets/bases/block-3.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/bases/block-4-top.png b/core/assets-raw/sprites/blocks/turrets/bases/block-4-top.png deleted file mode 100644 index 527f3abd7e..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/bases/block-4-top.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/cyclone.png b/core/assets-raw/sprites/blocks/turrets/cyclone.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/cyclone.png rename to core/assets-raw/sprites/blocks/turrets/cyclone.png diff --git a/core/assets-raw/sprites/blocks/turrets/duo.png b/core/assets-raw/sprites/blocks/turrets/duo.png new file mode 100644 index 0000000000..40d21d0fb0 Binary files /dev/null and b/core/assets-raw/sprites/blocks/turrets/duo.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/fuse.png b/core/assets-raw/sprites/blocks/turrets/fuse.png new file mode 100644 index 0000000000..c03bad9cba Binary files /dev/null and b/core/assets-raw/sprites/blocks/turrets/fuse.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/hail-heat.png b/core/assets-raw/sprites/blocks/turrets/hail-heat.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/hail-heat.png rename to core/assets-raw/sprites/blocks/turrets/hail-heat.png diff --git a/core/assets-raw/sprites/blocks/turrets/hail.png b/core/assets-raw/sprites/blocks/turrets/hail.png new file mode 100644 index 0000000000..f54b439dbc Binary files /dev/null and b/core/assets-raw/sprites/blocks/turrets/hail.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/lancer-heat.png b/core/assets-raw/sprites/blocks/turrets/lancer-heat.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/lancer-heat.png rename to core/assets-raw/sprites/blocks/turrets/lancer-heat.png diff --git a/core/assets-raw/sprites/blocks/turrets/lancer.png b/core/assets-raw/sprites/blocks/turrets/lancer.png new file mode 100644 index 0000000000..9864ac6ad9 Binary files /dev/null and b/core/assets-raw/sprites/blocks/turrets/lancer.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/meltdown-heat.png b/core/assets-raw/sprites/blocks/turrets/meltdown-heat.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/meltdown-heat.png rename to core/assets-raw/sprites/blocks/turrets/meltdown-heat.png diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/meltdown.png b/core/assets-raw/sprites/blocks/turrets/meltdown.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/meltdown.png rename to core/assets-raw/sprites/blocks/turrets/meltdown.png diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/ripple-heat.png b/core/assets-raw/sprites/blocks/turrets/ripple-heat.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/ripple-heat.png rename to core/assets-raw/sprites/blocks/turrets/ripple-heat.png diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/ripple.png b/core/assets-raw/sprites/blocks/turrets/ripple.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/ripple.png rename to core/assets-raw/sprites/blocks/turrets/ripple.png diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/salvo-heat.png b/core/assets-raw/sprites/blocks/turrets/salvo-heat.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/salvo-heat.png rename to core/assets-raw/sprites/blocks/turrets/salvo-heat.png diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/salvo-panel-left.png b/core/assets-raw/sprites/blocks/turrets/salvo-panel-left.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/salvo-panel-left.png rename to core/assets-raw/sprites/blocks/turrets/salvo-panel-left.png diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/salvo-panel-right.png b/core/assets-raw/sprites/blocks/turrets/salvo-panel-right.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/salvo-panel-right.png rename to core/assets-raw/sprites/blocks/turrets/salvo-panel-right.png diff --git a/core/assets-raw/sprites/blocks/turrets/salvo.png b/core/assets-raw/sprites/blocks/turrets/salvo.png new file mode 100644 index 0000000000..bfa377509f Binary files /dev/null and b/core/assets-raw/sprites/blocks/turrets/salvo.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/spectre.png b/core/assets-raw/sprites/blocks/turrets/spectre.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/spectre.png rename to core/assets-raw/sprites/blocks/turrets/spectre.png diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/swarmer.png b/core/assets-raw/sprites/blocks/turrets/swarmer.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/swarmer.png rename to core/assets-raw/sprites/blocks/turrets/swarmer.png diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/duo.png b/core/assets-raw/sprites/blocks/turrets/turrets/duo.png deleted file mode 100644 index c14c3eec09..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/duo.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/fuse.png b/core/assets-raw/sprites/blocks/turrets/turrets/fuse.png deleted file mode 100644 index 32218df362..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/fuse.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/hail.png b/core/assets-raw/sprites/blocks/turrets/turrets/hail.png deleted file mode 100644 index 32de585540..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/hail.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/lancer.png b/core/assets-raw/sprites/blocks/turrets/turrets/lancer.png deleted file mode 100644 index 7b6c522ae8..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/lancer.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/salvo.png b/core/assets-raw/sprites/blocks/turrets/turrets/salvo.png deleted file mode 100644 index 35692ef373..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/salvo.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/scatter.png b/core/assets-raw/sprites/blocks/turrets/turrets/scatter.png deleted file mode 100644 index 5e64bd36e4..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/scatter.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/scorch-shoot.png b/core/assets-raw/sprites/blocks/turrets/turrets/scorch-shoot.png deleted file mode 100644 index cc73e4bd33..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/scorch-shoot.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/scorch.png b/core/assets-raw/sprites/blocks/turrets/turrets/scorch.png deleted file mode 100644 index 875047c7fd..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/scorch.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/wave.png b/core/assets-raw/sprites/blocks/turrets/turrets/wave.png deleted file mode 100644 index 2019a6e2a2..0000000000 Binary files a/core/assets-raw/sprites/blocks/turrets/turrets/wave.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/turrets/turrets/wave-liquid.png b/core/assets-raw/sprites/blocks/turrets/wave-liquid.png similarity index 100% rename from core/assets-raw/sprites/blocks/turrets/turrets/wave-liquid.png rename to core/assets-raw/sprites/blocks/turrets/wave-liquid.png diff --git a/core/assets-raw/sprites/blocks/turrets/wave.png b/core/assets-raw/sprites/blocks/turrets/wave.png new file mode 100644 index 0000000000..ff132fbd74 Binary files /dev/null and b/core/assets-raw/sprites/blocks/turrets/wave.png differ diff --git a/core/assets-raw/sprites/blocks/units/command-center.png b/core/assets-raw/sprites/blocks/units/command-center.png deleted file mode 100644 index 16d5d7f4ad..0000000000 Binary files a/core/assets-raw/sprites/blocks/units/command-center.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/units/crawler-factory-top-open.png b/core/assets-raw/sprites/blocks/units/crawler-factory-top-open.png new file mode 100644 index 0000000000..290db9d373 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/crawler-factory-top-open.png differ diff --git a/core/assets-raw/sprites/blocks/units/crawler-factory-top.png b/core/assets-raw/sprites/blocks/units/crawler-factory-top.png new file mode 100644 index 0000000000..f7cad4dbf6 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/crawler-factory-top.png differ diff --git a/core/assets-raw/sprites/blocks/units/reconstructor.png b/core/assets-raw/sprites/blocks/units/crawler-factory.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/reconstructor.png rename to core/assets-raw/sprites/blocks/units/crawler-factory.png diff --git a/core/assets-raw/sprites/blocks/units/fortress-factory.png b/core/assets-raw/sprites/blocks/units/fortress-factory.png index 79572e2bdd..716fd0a9cf 100644 Binary files a/core/assets-raw/sprites/blocks/units/fortress-factory.png and b/core/assets-raw/sprites/blocks/units/fortress-factory.png differ diff --git a/core/assets-raw/sprites/blocks/units/reconstructor-open.png b/core/assets-raw/sprites/blocks/units/reconstructor-open.png deleted file mode 100644 index 92a6e51ac3..0000000000 Binary files a/core/assets-raw/sprites/blocks/units/reconstructor-open.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/units/repair-point-base.png b/core/assets-raw/sprites/blocks/units/repair-point-base.png new file mode 100644 index 0000000000..cbddf2f48a Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/repair-point-base.png differ diff --git a/core/assets-raw/sprites/blocks/units/repair-point-turret.png b/core/assets-raw/sprites/blocks/units/repair-point-turret.png deleted file mode 100644 index b01b4bde05..0000000000 Binary files a/core/assets-raw/sprites/blocks/units/repair-point-turret.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/units/repair-point.png b/core/assets-raw/sprites/blocks/units/repair-point.png index 41c5134409..b01b4bde05 100644 Binary files a/core/assets-raw/sprites/blocks/units/repair-point.png and b/core/assets-raw/sprites/blocks/units/repair-point.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-gigantic.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-gigantic.png new file mode 100644 index 0000000000..ffdc63ffcc Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall-gigantic.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-huge1.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-huge1.png new file mode 100644 index 0000000000..c03322d55d Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall-huge1.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-huge2.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-huge2.png new file mode 100644 index 0000000000..bdf6d1344c Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall-huge2.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-huge3.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-huge3.png new file mode 100644 index 0000000000..fa12bc5e02 Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall-huge3.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-large1.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-large1.png new file mode 100644 index 0000000000..7b420a30d3 Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall-large1.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-large2.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-large2.png new file mode 100644 index 0000000000..804d7749e4 Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall-large2.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-large3.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-large3.png new file mode 100644 index 0000000000..d7279d6b32 Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall-large3.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall-large4.png b/core/assets-raw/sprites/blocks/walls/scrap-wall-large4.png new file mode 100644 index 0000000000..3ea4802427 Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall-large4.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall1.png b/core/assets-raw/sprites/blocks/walls/scrap-wall1.png new file mode 100644 index 0000000000..736757a9d1 Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall1.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall2.png b/core/assets-raw/sprites/blocks/walls/scrap-wall2.png new file mode 100644 index 0000000000..ed6229481c Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall2.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall3.png b/core/assets-raw/sprites/blocks/walls/scrap-wall3.png new file mode 100644 index 0000000000..59dab303a3 Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall3.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall4.png b/core/assets-raw/sprites/blocks/walls/scrap-wall4.png new file mode 100644 index 0000000000..df86f16cc2 Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall4.png differ diff --git a/core/assets-raw/sprites/blocks/walls/scrap-wall5.png b/core/assets-raw/sprites/blocks/walls/scrap-wall5.png new file mode 100644 index 0000000000..1f75829f3a Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/scrap-wall5.png differ diff --git a/core/assets-raw/sprites/blocks/walls/thruster.png b/core/assets-raw/sprites/blocks/walls/thruster.png new file mode 100644 index 0000000000..82ec7622f6 Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/thruster.png differ diff --git a/core/assets-raw/sprites/blocks/walls/titanium-wall-large.png b/core/assets-raw/sprites/blocks/walls/titanium-wall-large.png index 996af7f52d..d6f6fc4644 100644 Binary files a/core/assets-raw/sprites/blocks/walls/titanium-wall-large.png and b/core/assets-raw/sprites/blocks/walls/titanium-wall-large.png differ diff --git a/core/assets-raw/sprites/blocks/walls/titanium-wall.png b/core/assets-raw/sprites/blocks/walls/titanium-wall.png index f778c11fdb..effbf52069 100644 Binary files a/core/assets-raw/sprites/blocks/walls/titanium-wall.png and b/core/assets-raw/sprites/blocks/walls/titanium-wall.png differ diff --git a/core/assets-raw/sprites/effects/beam-end.png b/core/assets-raw/sprites/effects/beam-end.png deleted file mode 100644 index d0674d380d..0000000000 Binary files a/core/assets-raw/sprites/effects/beam-end.png and /dev/null differ diff --git a/core/assets-raw/sprites/effects/beam.png b/core/assets-raw/sprites/effects/beam.png deleted file mode 100644 index 327fd4b7f6..0000000000 Binary files a/core/assets-raw/sprites/effects/beam.png and /dev/null differ diff --git a/core/assets-raw/sprites/effects/command-attack.png b/core/assets-raw/sprites/effects/command-attack.png deleted file mode 100644 index 655f819338..0000000000 Binary files a/core/assets-raw/sprites/effects/command-attack.png and /dev/null differ diff --git a/core/assets-raw/sprites/effects/command-idle.png b/core/assets-raw/sprites/effects/command-idle.png deleted file mode 100644 index 4271a5a321..0000000000 Binary files a/core/assets-raw/sprites/effects/command-idle.png and /dev/null differ diff --git a/core/assets-raw/sprites/effects/command-patrol.png b/core/assets-raw/sprites/effects/command-patrol.png deleted file mode 100644 index acf89f181a..0000000000 Binary files a/core/assets-raw/sprites/effects/command-patrol.png and /dev/null differ diff --git a/core/assets-raw/sprites/effects/command-retreat.png b/core/assets-raw/sprites/effects/command-retreat.png deleted file mode 100644 index f40dcfe5cf..0000000000 Binary files a/core/assets-raw/sprites/effects/command-retreat.png and /dev/null differ diff --git a/core/assets-raw/sprites/effects/enemyarrow.png b/core/assets-raw/sprites/effects/enemyarrow.png deleted file mode 100644 index d31e365701..0000000000 Binary files a/core/assets-raw/sprites/effects/enemyarrow.png and /dev/null differ diff --git a/core/assets-raw/sprites/effects/error.png b/core/assets-raw/sprites/effects/error.png deleted file mode 100644 index 1f7efdb692..0000000000 Binary files a/core/assets-raw/sprites/effects/error.png and /dev/null differ diff --git a/core/assets-raw/sprites/effects/laser-end.png b/core/assets-raw/sprites/effects/laser-end.png deleted file mode 100644 index 7c109d16dd..0000000000 Binary files a/core/assets-raw/sprites/effects/laser-end.png and /dev/null differ diff --git a/core/assets-raw/sprites/effects/laser.png b/core/assets-raw/sprites/effects/laser.png deleted file mode 100644 index eba798c01e..0000000000 Binary files a/core/assets-raw/sprites/effects/laser.png and /dev/null differ diff --git a/core/assets-raw/sprites/effects/laserfull.png b/core/assets-raw/sprites/effects/laserfull.png deleted file mode 100644 index fab831c1c4..0000000000 Binary files a/core/assets-raw/sprites/effects/laserfull.png and /dev/null differ diff --git a/core/assets-raw/sprites/effects/minelaser-end.png b/core/assets-raw/sprites/effects/minelaser-end.png deleted file mode 100644 index 8a04ee1a6d..0000000000 Binary files a/core/assets-raw/sprites/effects/minelaser-end.png and /dev/null differ diff --git a/core/assets-raw/sprites/effects/minelaser.png b/core/assets-raw/sprites/effects/minelaser.png deleted file mode 100644 index 956e4d2311..0000000000 Binary files a/core/assets-raw/sprites/effects/minelaser.png and /dev/null differ diff --git a/core/assets-raw/sprites/items/item-coal.png b/core/assets-raw/sprites/items/item-coal.png index 0c094a7436..399e28f7d5 100644 Binary files a/core/assets-raw/sprites/items/item-coal.png and b/core/assets-raw/sprites/items/item-coal.png differ diff --git a/core/assets-raw/sprites/items/item-graphite.png b/core/assets-raw/sprites/items/item-graphite.png index 36857e49a2..bacdf52b8a 100644 Binary files a/core/assets-raw/sprites/items/item-graphite.png and b/core/assets-raw/sprites/items/item-graphite.png differ diff --git a/core/assets-raw/sprites/items/item-metaglass.png b/core/assets-raw/sprites/items/item-metaglass.png index 538acab631..3ccccbf1ca 100644 Binary files a/core/assets-raw/sprites/items/item-metaglass.png and b/core/assets-raw/sprites/items/item-metaglass.png differ diff --git a/core/assets-raw/sprites/items/item-scrap.png b/core/assets-raw/sprites/items/item-scrap.png index a19374afad..d39570505b 100644 Binary files a/core/assets-raw/sprites/items/item-scrap.png and b/core/assets-raw/sprites/items/item-scrap.png differ diff --git a/core/assets-raw/sprites/items/item-stone.png b/core/assets-raw/sprites/items/item-stone.png deleted file mode 100644 index 20fcd1b4c7..0000000000 Binary files a/core/assets-raw/sprites/items/item-stone.png and /dev/null differ diff --git a/core/assets-raw/sprites/items/liquid-cryofluid.png b/core/assets-raw/sprites/items/liquid-cryofluid.png index abf14496c8..8fb5c04279 100644 Binary files a/core/assets-raw/sprites/items/liquid-cryofluid.png and b/core/assets-raw/sprites/items/liquid-cryofluid.png differ diff --git a/core/assets-raw/sprites/items/liquid-oil.png b/core/assets-raw/sprites/items/liquid-oil.png index a35b2248ed..897050ec04 100644 Binary files a/core/assets-raw/sprites/items/liquid-oil.png and b/core/assets-raw/sprites/items/liquid-oil.png differ diff --git a/core/assets-raw/sprites/items/liquid-slag.png b/core/assets-raw/sprites/items/liquid-slag.png index af8efaf9ef..e3387f557a 100644 Binary files a/core/assets-raw/sprites/items/liquid-slag.png and b/core/assets-raw/sprites/items/liquid-slag.png differ diff --git a/core/assets-raw/sprites/items/liquid-water.png b/core/assets-raw/sprites/items/liquid-water.png index dc11153408..c51264d09b 100644 Binary files a/core/assets-raw/sprites/items/liquid-water.png and b/core/assets-raw/sprites/items/liquid-water.png differ diff --git a/core/assets-raw/sprites/mechs/mechs/omega-mech-armor.png b/core/assets-raw/sprites/mechs/mechs/omega-mech-armor.png index 051c4f4791..943895deab 100644 Binary files a/core/assets-raw/sprites/mechs/mechs/omega-mech-armor.png and b/core/assets-raw/sprites/mechs/mechs/omega-mech-armor.png differ diff --git a/core/assets-raw/sprites/ui/bar.9.png b/core/assets-raw/sprites/ui/bar.9.png index 1bf63c7bdf..5e9ab3f2a0 100644 Binary files a/core/assets-raw/sprites/ui/bar.9.png and b/core/assets-raw/sprites/ui/bar.9.png differ diff --git a/core/assets-raw/sprites/ui/button-disabled.9.png b/core/assets-raw/sprites/ui/button-disabled.9.png new file mode 100644 index 0000000000..2f57455034 Binary files /dev/null and b/core/assets-raw/sprites/ui/button-disabled.9.png differ diff --git a/core/assets-raw/sprites/ui/button-down.9.png b/core/assets-raw/sprites/ui/button-down.9.png index 3e8c108d52..b26d54d0a1 100644 Binary files a/core/assets-raw/sprites/ui/button-down.9.png and b/core/assets-raw/sprites/ui/button-down.9.png differ diff --git a/core/assets-raw/sprites/ui/button-edge-1.9.png b/core/assets-raw/sprites/ui/button-edge-1.9.png index 2502858baa..b91afee83a 100644 Binary files a/core/assets-raw/sprites/ui/button-edge-1.9.png and b/core/assets-raw/sprites/ui/button-edge-1.9.png differ diff --git a/core/assets-raw/sprites/ui/button-edge-2.9.png b/core/assets-raw/sprites/ui/button-edge-2.9.png index c6ee4208e1..063dfa6c69 100644 Binary files a/core/assets-raw/sprites/ui/button-edge-2.9.png and b/core/assets-raw/sprites/ui/button-edge-2.9.png differ diff --git a/core/assets-raw/sprites/ui/button-edge-3.9.png b/core/assets-raw/sprites/ui/button-edge-3.9.png index 349c5b2fe8..a182e728a6 100644 Binary files a/core/assets-raw/sprites/ui/button-edge-3.9.png and b/core/assets-raw/sprites/ui/button-edge-3.9.png differ diff --git a/core/assets-raw/sprites/ui/button-edge-4.9.png b/core/assets-raw/sprites/ui/button-edge-4.9.png index b8d4abb820..c8e554c5e3 100644 Binary files a/core/assets-raw/sprites/ui/button-edge-4.9.png and b/core/assets-raw/sprites/ui/button-edge-4.9.png differ diff --git a/core/assets-raw/sprites/ui/button-over.9.png b/core/assets-raw/sprites/ui/button-over.9.png index da58085c33..fe5f260ce5 100644 Binary files a/core/assets-raw/sprites/ui/button-over.9.png and b/core/assets-raw/sprites/ui/button-over.9.png differ diff --git a/core/assets-raw/sprites/ui/button-right-down.9.png b/core/assets-raw/sprites/ui/button-right-down.9.png index dea5fa0eac..475f255934 100644 Binary files a/core/assets-raw/sprites/ui/button-right-down.9.png and b/core/assets-raw/sprites/ui/button-right-down.9.png differ diff --git a/core/assets-raw/sprites/ui/button-right-over.9.png b/core/assets-raw/sprites/ui/button-right-over.9.png index aeb5860006..c764c18dab 100644 Binary files a/core/assets-raw/sprites/ui/button-right-over.9.png and b/core/assets-raw/sprites/ui/button-right-over.9.png differ diff --git a/core/assets-raw/sprites/ui/button-right.9.png b/core/assets-raw/sprites/ui/button-right.9.png index 0cbe0e8288..2c8c4bb1e0 100644 Binary files a/core/assets-raw/sprites/ui/button-right.9.png and b/core/assets-raw/sprites/ui/button-right.9.png differ diff --git a/core/assets-raw/sprites/ui/button-select.9.png b/core/assets-raw/sprites/ui/button-select.9.png index a636259c96..73c217fc2b 100644 Binary files a/core/assets-raw/sprites/ui/button-select.9.png and b/core/assets-raw/sprites/ui/button-select.9.png differ diff --git a/core/assets-raw/sprites/ui/button.9.png b/core/assets-raw/sprites/ui/button.9.png index 84d9576166..b88439e267 100644 Binary files a/core/assets-raw/sprites/ui/button.9.png and b/core/assets-raw/sprites/ui/button.9.png differ diff --git a/core/assets-raw/sprites/ui/content-background-locked.9.png b/core/assets-raw/sprites/ui/content-background-locked.9.png index 8b3ac94f48..60e1941d4f 100644 Binary files a/core/assets-raw/sprites/ui/content-background-locked.9.png and b/core/assets-raw/sprites/ui/content-background-locked.9.png differ diff --git a/core/assets-raw/sprites/ui/content-background-over.9.png b/core/assets-raw/sprites/ui/content-background-over.9.png index 8993b24afa..7e1a6e6c2d 100644 Binary files a/core/assets-raw/sprites/ui/content-background-over.9.png and b/core/assets-raw/sprites/ui/content-background-over.9.png differ diff --git a/core/assets-raw/sprites/ui/content-background.9.png b/core/assets-raw/sprites/ui/content-background.9.png index 4f2012fce3..cdd8df0abc 100644 Binary files a/core/assets-raw/sprites/ui/content-background.9.png and b/core/assets-raw/sprites/ui/content-background.9.png differ diff --git a/core/assets-raw/sprites/ui/discord-banner.png b/core/assets-raw/sprites/ui/discord-banner.png index abcfa2d7b1..ac4d3b1ec9 100644 Binary files a/core/assets-raw/sprites/ui/discord-banner.png and b/core/assets-raw/sprites/ui/discord-banner.png differ diff --git a/core/assets-raw/sprites/ui/empty-sector.png b/core/assets-raw/sprites/ui/empty-sector.png index 347b3bfc8d..a0bad794cd 100644 Binary files a/core/assets-raw/sprites/ui/empty-sector.png and b/core/assets-raw/sprites/ui/empty-sector.png differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-crafting.png b/core/assets-raw/sprites/ui/icons-category/icon-crafting.png index 80447efca8..9a5fd055e6 100644 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-crafting.png and b/core/assets-raw/sprites/ui/icons-category/icon-crafting.png differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-defense.png b/core/assets-raw/sprites/ui/icons-category/icon-defense.png index f0b4cabdad..150f611402 100644 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-defense.png and b/core/assets-raw/sprites/ui/icons-category/icon-defense.png differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-distribution.png b/core/assets-raw/sprites/ui/icons-category/icon-distribution.png index 18233d41c0..52a07aac9f 100644 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-distribution.png and b/core/assets-raw/sprites/ui/icons-category/icon-distribution.png differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-effect.png b/core/assets-raw/sprites/ui/icons-category/icon-effect.png index 5da7498a1f..d0613ec868 100644 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-effect.png and b/core/assets-raw/sprites/ui/icons-category/icon-effect.png differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-liquid.png b/core/assets-raw/sprites/ui/icons-category/icon-liquid.png index 4d4142213b..050ea2ef38 100644 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-liquid.png and b/core/assets-raw/sprites/ui/icons-category/icon-liquid.png differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-power.png b/core/assets-raw/sprites/ui/icons-category/icon-power.png index 5df68ce22b..27d9fa885d 100644 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-power.png and b/core/assets-raw/sprites/ui/icons-category/icon-power.png differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-production.png b/core/assets-raw/sprites/ui/icons-category/icon-production.png index 0735582732..8d037a43a2 100644 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-production.png and b/core/assets-raw/sprites/ui/icons-category/icon-production.png differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-turret.png b/core/assets-raw/sprites/ui/icons-category/icon-turret.png index 3ed23cf8b8..60cce4fa14 100644 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-turret.png and b/core/assets-raw/sprites/ui/icons-category/icon-turret.png differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-units.png b/core/assets-raw/sprites/ui/icons-category/icon-units.png index b907051a23..d76063e640 100644 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-units.png and b/core/assets-raw/sprites/ui/icons-category/icon-units.png differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-upgrade.png b/core/assets-raw/sprites/ui/icons-category/icon-upgrade.png index 6f054ad8d0..af4b3f4576 100644 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-upgrade.png and b/core/assets-raw/sprites/ui/icons-category/icon-upgrade.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-add.png b/core/assets-raw/sprites/ui/icons/icon-add.png index 2cee82e07d..50c7a2c330 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-add.png and b/core/assets-raw/sprites/ui/icons/icon-add.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-cancel-2.png b/core/assets-raw/sprites/ui/icons/icon-cancel-2.png index c653c00af4..5b14e4c468 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-cancel-2.png and b/core/assets-raw/sprites/ui/icons/icon-cancel-2.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-check-2.png b/core/assets-raw/sprites/ui/icons/icon-check-2.png index e123e30478..ec0bb3cb8e 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-check-2.png and b/core/assets-raw/sprites/ui/icons/icon-check-2.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-copy.png b/core/assets-raw/sprites/ui/icons/icon-copy.png index b1a8d0a607..0f03ee5d04 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-copy.png and b/core/assets-raw/sprites/ui/icons/icon-copy.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-database-small.png b/core/assets-raw/sprites/ui/icons/icon-database-small.png new file mode 100644 index 0000000000..dc105e3f67 Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-database-small.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-database.png b/core/assets-raw/sprites/ui/icons/icon-database.png new file mode 100644 index 0000000000..f5bc48c80d Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-database.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-file-image.png b/core/assets-raw/sprites/ui/icons/icon-file-image.png index 254ea95f3d..5b0d2adbe5 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-file-image.png and b/core/assets-raw/sprites/ui/icons/icon-file-image.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-fill.png b/core/assets-raw/sprites/ui/icons/icon-fill.png index 79bc8b2c39..25d439a830 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-fill.png and b/core/assets-raw/sprites/ui/icons/icon-fill.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-info.png b/core/assets-raw/sprites/ui/icons/icon-info.png index ac482f4194..e3461da338 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-info.png and b/core/assets-raw/sprites/ui/icons/icon-info.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-paste.png b/core/assets-raw/sprites/ui/icons/icon-paste.png index 1ddee0eb9b..606165ed34 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-paste.png and b/core/assets-raw/sprites/ui/icons/icon-paste.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-play-custom.png b/core/assets-raw/sprites/ui/icons/icon-play-custom.png new file mode 100644 index 0000000000..78716a2fb0 Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-play-custom.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-power-requirement.png b/core/assets-raw/sprites/ui/icons/icon-power-requirement.png new file mode 100644 index 0000000000..dc82f5942e Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-power-requirement.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-spray.png b/core/assets-raw/sprites/ui/icons/icon-spray.png index 9370d5751b..17198d657b 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-spray.png and b/core/assets-raw/sprites/ui/icons/icon-spray.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-tree-locked.png b/core/assets-raw/sprites/ui/icons/icon-tree-locked.png index d6a6462d1c..5c9678c8a9 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-tree-locked.png and b/core/assets-raw/sprites/ui/icons/icon-tree-locked.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-tree.png b/core/assets-raw/sprites/ui/icons/icon-tree.png index 6e28a70c13..0731f6a7e5 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-tree.png and b/core/assets-raw/sprites/ui/icons/icon-tree.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-zone-locked.png b/core/assets-raw/sprites/ui/icons/icon-zone-locked.png index 207c41c463..b0b184918c 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-zone-locked.png and b/core/assets-raw/sprites/ui/icons/icon-zone-locked.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-zone.png b/core/assets-raw/sprites/ui/icons/icon-zone.png index af66d61ea6..2496b1bc79 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-zone.png and b/core/assets-raw/sprites/ui/icons/icon-zone.png differ diff --git a/core/assets-raw/sprites/ui/info-banner.png b/core/assets-raw/sprites/ui/info-banner.png index 8e5c3cbf99..3568944de5 100644 Binary files a/core/assets-raw/sprites/ui/info-banner.png and b/core/assets-raw/sprites/ui/info-banner.png differ diff --git a/core/assets-raw/sprites/ui/logotext.png b/core/assets-raw/sprites/ui/logotext.png index fbe5a07d36..4305683321 100644 Binary files a/core/assets-raw/sprites/ui/logotext.png and b/core/assets-raw/sprites/ui/logotext.png differ diff --git a/core/assets-raw/sprites/ui/pane-2.9.png b/core/assets-raw/sprites/ui/pane-2.9.png index b83c929833..e2fe497574 100644 Binary files a/core/assets-raw/sprites/ui/pane-2.9.png and b/core/assets-raw/sprites/ui/pane-2.9.png differ diff --git a/core/assets-raw/sprites/ui/pane.9.png b/core/assets-raw/sprites/ui/pane.9.png index eb07b24fa0..a21c4607aa 100644 Binary files a/core/assets-raw/sprites/ui/pane.9.png and b/core/assets-raw/sprites/ui/pane.9.png differ diff --git a/core/assets-raw/sprites/ui/scroll-horizontal.9.png b/core/assets-raw/sprites/ui/scroll-horizontal.9.png index eea4d3f872..72c4cda25f 100644 Binary files a/core/assets-raw/sprites/ui/scroll-horizontal.9.png and b/core/assets-raw/sprites/ui/scroll-horizontal.9.png differ diff --git a/core/assets-raw/sprites/ui/scroll-knob-horizontal-black.9.png b/core/assets-raw/sprites/ui/scroll-knob-horizontal-black.9.png index d6227471aa..7f5dd4137f 100644 Binary files a/core/assets-raw/sprites/ui/scroll-knob-horizontal-black.9.png and b/core/assets-raw/sprites/ui/scroll-knob-horizontal-black.9.png differ diff --git a/core/assets-raw/sprites/ui/scroll-knob-vertical-black.9.png b/core/assets-raw/sprites/ui/scroll-knob-vertical-black.9.png index acd97cdd79..1b5c9d39d8 100644 Binary files a/core/assets-raw/sprites/ui/scroll-knob-vertical-black.9.png and b/core/assets-raw/sprites/ui/scroll-knob-vertical-black.9.png differ diff --git a/core/assets-raw/sprites/ui/scroll.9.png b/core/assets-raw/sprites/ui/scroll.9.png index afcdf783b9..4c92865fcb 100644 Binary files a/core/assets-raw/sprites/ui/scroll.9.png and b/core/assets-raw/sprites/ui/scroll.9.png differ diff --git a/core/assets-raw/sprites/ui/sector-edge.png b/core/assets-raw/sprites/ui/sector-edge.png deleted file mode 100644 index 293d9bee79..0000000000 Binary files a/core/assets-raw/sprites/ui/sector-edge.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/slider-knob-down.png b/core/assets-raw/sprites/ui/slider-knob-down.png index 1c44f1497d..2822be93af 100644 Binary files a/core/assets-raw/sprites/ui/slider-knob-down.png and b/core/assets-raw/sprites/ui/slider-knob-down.png differ diff --git a/core/assets-raw/sprites/ui/slider-knob-over.png b/core/assets-raw/sprites/ui/slider-knob-over.png index f32d6c3975..2822be93af 100644 Binary files a/core/assets-raw/sprites/ui/slider-knob-over.png and b/core/assets-raw/sprites/ui/slider-knob-over.png differ diff --git a/core/assets-raw/sprites/ui/slider-knob.png b/core/assets-raw/sprites/ui/slider-knob.png index b9059692ca..4d98387c78 100644 Binary files a/core/assets-raw/sprites/ui/slider-knob.png and b/core/assets-raw/sprites/ui/slider-knob.png differ diff --git a/core/assets-raw/sprites/ui/slider.png b/core/assets-raw/sprites/ui/slider.png index 904b8f2001..278674e9a0 100644 Binary files a/core/assets-raw/sprites/ui/slider.png and b/core/assets-raw/sprites/ui/slider.png differ diff --git a/core/assets-raw/sprites/ui/underline-2.9.png b/core/assets-raw/sprites/ui/underline-2.9.png index bd2c4fbf18..f703111db2 100644 Binary files a/core/assets-raw/sprites/ui/underline-2.9.png and b/core/assets-raw/sprites/ui/underline-2.9.png differ diff --git a/core/assets-raw/sprites/ui/underline.9.png b/core/assets-raw/sprites/ui/underline.9.png index 2c764bd6b5..e42d29c78f 100644 Binary files a/core/assets-raw/sprites/ui/underline.9.png and b/core/assets-raw/sprites/ui/underline.9.png differ diff --git a/core/assets-raw/sprites/units/alpha-drone.png b/core/assets-raw/sprites/units/alpha-drone.png deleted file mode 100644 index 8cd435aed6..0000000000 Binary files a/core/assets-raw/sprites/units/alpha-drone.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/chaos-array-base.png b/core/assets-raw/sprites/units/chaos-array-base.png new file mode 100644 index 0000000000..b1174913d6 Binary files /dev/null and b/core/assets-raw/sprites/units/chaos-array-base.png differ diff --git a/core/assets-raw/sprites/units/chaos-array-leg.png b/core/assets-raw/sprites/units/chaos-array-leg.png new file mode 100644 index 0000000000..7269601fcf Binary files /dev/null and b/core/assets-raw/sprites/units/chaos-array-leg.png differ diff --git a/core/assets-raw/sprites/units/chaos-array.png b/core/assets-raw/sprites/units/chaos-array.png new file mode 100644 index 0000000000..afd96f43dc Binary files /dev/null and b/core/assets-raw/sprites/units/chaos-array.png differ diff --git a/core/assets-raw/sprites/units/crawler-base.png b/core/assets-raw/sprites/units/crawler-base.png new file mode 100644 index 0000000000..dd62bbf01e Binary files /dev/null and b/core/assets-raw/sprites/units/crawler-base.png differ diff --git a/core/assets-raw/sprites/units/crawler-leg.png b/core/assets-raw/sprites/units/crawler-leg.png new file mode 100644 index 0000000000..40d363b816 Binary files /dev/null and b/core/assets-raw/sprites/units/crawler-leg.png differ diff --git a/core/assets-raw/sprites/units/crawler.png b/core/assets-raw/sprites/units/crawler.png new file mode 100644 index 0000000000..42456d8681 Binary files /dev/null and b/core/assets-raw/sprites/units/crawler.png differ diff --git a/core/assets-raw/sprites/units/dagger-base.png b/core/assets-raw/sprites/units/dagger-base.png index 16d639ad6b..ef06fe6820 100644 Binary files a/core/assets-raw/sprites/units/dagger-base.png and b/core/assets-raw/sprites/units/dagger-base.png differ diff --git a/core/assets-raw/sprites/units/dagger-leg.png b/core/assets-raw/sprites/units/dagger-leg.png index 9049d99666..2804fc72d3 100644 Binary files a/core/assets-raw/sprites/units/dagger-leg.png and b/core/assets-raw/sprites/units/dagger-leg.png differ diff --git a/core/assets-raw/sprites/units/eradicator-base.png b/core/assets-raw/sprites/units/eradicator-base.png new file mode 100644 index 0000000000..24b5cdb446 Binary files /dev/null and b/core/assets-raw/sprites/units/eradicator-base.png differ diff --git a/core/assets-raw/sprites/units/eradicator-leg.png b/core/assets-raw/sprites/units/eradicator-leg.png new file mode 100644 index 0000000000..3a503a2e6a Binary files /dev/null and b/core/assets-raw/sprites/units/eradicator-leg.png differ diff --git a/core/assets-raw/sprites/units/eradicator.png b/core/assets-raw/sprites/units/eradicator.png new file mode 100644 index 0000000000..c620aa3d0f Binary files /dev/null and b/core/assets-raw/sprites/units/eradicator.png differ diff --git a/core/assets-raw/sprites/units/eruptor-base.png b/core/assets-raw/sprites/units/eruptor-base.png new file mode 100644 index 0000000000..0b1e55dbb9 Binary files /dev/null and b/core/assets-raw/sprites/units/eruptor-base.png differ diff --git a/core/assets-raw/sprites/units/eruptor-leg.png b/core/assets-raw/sprites/units/eruptor-leg.png new file mode 100644 index 0000000000..c3d622340a Binary files /dev/null and b/core/assets-raw/sprites/units/eruptor-leg.png differ diff --git a/core/assets-raw/sprites/units/eruptor.png b/core/assets-raw/sprites/units/eruptor.png new file mode 100644 index 0000000000..992fc9ea2d Binary files /dev/null and b/core/assets-raw/sprites/units/eruptor.png differ diff --git a/core/assets-raw/sprites/units/fortress-base.png b/core/assets-raw/sprites/units/fortress-base.png index 8d01aeb29a..27d0869faa 100644 Binary files a/core/assets-raw/sprites/units/fortress-base.png and b/core/assets-raw/sprites/units/fortress-base.png differ diff --git a/core/assets-raw/sprites/units/fortress-leg.png b/core/assets-raw/sprites/units/fortress-leg.png index 3e94dd7bed..f6154b625a 100644 Binary files a/core/assets-raw/sprites/units/fortress-leg.png and b/core/assets-raw/sprites/units/fortress-leg.png differ diff --git a/core/assets-raw/sprites/units/lich.png b/core/assets-raw/sprites/units/lich.png new file mode 100644 index 0000000000..9f34958af8 Binary files /dev/null and b/core/assets-raw/sprites/units/lich.png differ diff --git a/core/assets-raw/sprites/units/reaper.png b/core/assets-raw/sprites/units/reaper.png new file mode 100644 index 0000000000..2d70f5d179 Binary files /dev/null and b/core/assets-raw/sprites/units/reaper.png differ diff --git a/core/assets-raw/sprites/units/revenant.png b/core/assets-raw/sprites/units/revenant.png index 6054faf101..2c9616b93e 100644 Binary files a/core/assets-raw/sprites/units/revenant.png and b/core/assets-raw/sprites/units/revenant.png differ diff --git a/core/assets-raw/sprites/units/titan-base.png b/core/assets-raw/sprites/units/titan-base.png index 8d01aeb29a..27d0869faa 100644 Binary files a/core/assets-raw/sprites/units/titan-base.png and b/core/assets-raw/sprites/units/titan-base.png differ diff --git a/core/assets-raw/sprites/units/titan-leg.png b/core/assets-raw/sprites/units/titan-leg.png index 8f79a7c274..a7f07eccef 100644 Binary files a/core/assets-raw/sprites/units/titan-leg.png and b/core/assets-raw/sprites/units/titan-leg.png differ diff --git a/core/assets-raw/sprites/weapons/artillery-equip.png b/core/assets-raw/sprites/weapons/artillery-equip.png index 2f18a8de59..843da3adbc 100644 Binary files a/core/assets-raw/sprites/weapons/artillery-equip.png and b/core/assets-raw/sprites/weapons/artillery-equip.png differ diff --git a/core/assets-raw/sprites/weapons/chain-blaster-equip.png b/core/assets-raw/sprites/weapons/chain-blaster-equip.png index 6591a21135..d2bc4331f4 100644 Binary files a/core/assets-raw/sprites/weapons/chain-blaster-equip.png and b/core/assets-raw/sprites/weapons/chain-blaster-equip.png differ diff --git a/core/assets-raw/sprites/weapons/chaos-equip.png b/core/assets-raw/sprites/weapons/chaos-equip.png new file mode 100644 index 0000000000..0a83fcc8a1 Binary files /dev/null and b/core/assets-raw/sprites/weapons/chaos-equip.png differ diff --git a/core/assets-raw/sprites/weapons/eradication-equip.png b/core/assets-raw/sprites/weapons/eradication-equip.png new file mode 100644 index 0000000000..16befb33e1 Binary files /dev/null and b/core/assets-raw/sprites/weapons/eradication-equip.png differ diff --git a/core/assets-raw/sprites/weapons/eruption-equip.png b/core/assets-raw/sprites/weapons/eruption-equip.png new file mode 100644 index 0000000000..7758d622a5 Binary files /dev/null and b/core/assets-raw/sprites/weapons/eruption-equip.png differ diff --git a/core/assets-raw/sprites/weapons/flamethrower-equip.png b/core/assets-raw/sprites/weapons/flamethrower-equip.png index 1d4462bd42..40b085ac43 100644 Binary files a/core/assets-raw/sprites/weapons/flamethrower-equip.png and b/core/assets-raw/sprites/weapons/flamethrower-equip.png differ diff --git a/core/assets-raw/sprites/weapons/lich-missiles-equip.png b/core/assets-raw/sprites/weapons/lich-missiles-equip.png new file mode 100644 index 0000000000..8deeb5416a Binary files /dev/null and b/core/assets-raw/sprites/weapons/lich-missiles-equip.png differ diff --git a/core/assets-raw/sprites/weapons/reaper-gun-equip.png b/core/assets-raw/sprites/weapons/reaper-gun-equip.png new file mode 100644 index 0000000000..1eb3cb64ba Binary files /dev/null and b/core/assets-raw/sprites/weapons/reaper-gun-equip.png differ diff --git a/core/assets-raw/sprites/weapons/revenant-missiles-equip.png b/core/assets-raw/sprites/weapons/revenant-missiles-equip.png new file mode 100644 index 0000000000..e8ebc4be08 Binary files /dev/null and b/core/assets-raw/sprites/weapons/revenant-missiles-equip.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/bridge-conveyor-end.png b/core/assets-raw/sprites_replacement/blocks/distribution/bridge-conveyor-end.png new file mode 100644 index 0000000000..b553fc29a7 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/distribution/bridge-conveyor-end.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-0.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-0.png index 2e55ce429a..2e0a43ea3b 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-0.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-0.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-1.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-1.png index 34a281b719..24048d1a43 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-1.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-2.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-2.png index 0b7db4da5c..73b23fc35b 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-2.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-3.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-3.png index a85cfdad60..6306aa871a 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-3.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-0-3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-0.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-0.png index 18736adf66..5227b0a105 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-0.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-0.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-1.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-1.png index 807b2bf17d..d7807ed213 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-1.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-2.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-2.png index faf67a8736..809e73f91e 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-2.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-3.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-3.png index edbb81841f..cbbcc06765 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-3.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-1-3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-0.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-0.png index ffd0e24f58..7d83503a4c 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-0.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-0.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-1.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-1.png index f249623779..7c096f931d 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-1.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-2.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-2.png index 3c04427e1a..8f3bc82e43 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-2.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-3.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-3.png index 439afb9c4b..2ae54594cb 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-3.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-2-3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-0.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-0.png index 2485ac23b6..4ab7a2b834 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-0.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-0.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-1.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-1.png index c7997843d0..078385b52e 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-1.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-2.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-2.png index 22e6868cce..353aed8146 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-2.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-3.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-3.png index 7a94546637..b0ca93a9ef 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-3.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-3-3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-0.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-0.png index 3563503f6f..7cf6b7a50c 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-0.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-0.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-1.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-1.png index 83c49920b4..20edd79d73 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-1.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-2.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-2.png index c89f011734..d2857c3270 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-2.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-3.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-3.png index acfe7e8136..2533da2648 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-3.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/conveyor-4-3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-0.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-0.png index 29af97eb5c..8b950f97f8 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-0.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-0.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-1.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-1.png index ecd054afa6..3254dc8756 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-1.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-2.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-2.png index 7dc49bd440..7f69cf0669 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-2.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-3.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-3.png index 97e31e5722..8675cc94d0 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-3.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-0-3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-0.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-0.png index 7e7bb86c62..1329d5537d 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-0.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-0.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-1.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-1.png index ffbafc5cdf..ee5360c7fe 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-1.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-2.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-2.png index f9dd561d6d..92c8101998 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-2.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-3.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-3.png index 5377953723..427ffeacd3 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-3.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-1-3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-0.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-0.png index 2f53cd53fd..9a3d6926f6 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-0.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-0.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-1.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-1.png index 29727566b0..9961efb201 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-1.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-2.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-2.png index 464a7d4cf8..14ba76c0fa 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-2.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-3.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-3.png index 53c6124f64..c9f72835e5 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-3.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-2-3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-0.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-0.png index aee4b266b2..2707bc9288 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-0.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-0.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-1.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-1.png index a547a7790f..352665be11 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-1.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-2.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-2.png index 0dafebb699..4ce88b7534 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-2.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-3.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-3.png index ae7bad0c38..a555b6b661 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-3.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-3-3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-0.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-0.png index e001d5f945..da3dafa312 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-0.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-0.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-1.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-1.png index 992e544fc7..9e040e9590 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-1.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-2.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-2.png index 9c26ceef47..a2b0ee6665 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-2.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-3.png b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-3.png index 09db7b8269..6a96832452 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-3.png and b/core/assets-raw/sprites_replacement/blocks/distribution/conveyors/titanium-conveyor-4-3.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/deepwater.png b/core/assets-raw/sprites_replacement/blocks/environment/deepwater.png new file mode 100644 index 0000000000..2389c5985d Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/deepwater.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-smooth.png b/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-smooth.png new file mode 100644 index 0000000000..55f4b9fb03 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-smooth.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/pine.png b/core/assets-raw/sprites_replacement/blocks/environment/pine.png new file mode 100644 index 0000000000..661c4caeb7 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/pine.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/salt.png b/core/assets-raw/sprites_replacement/blocks/environment/salt.png new file mode 100644 index 0000000000..df9fd72915 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/salt.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/sand-water.png b/core/assets-raw/sprites_replacement/blocks/environment/sand-water.png new file mode 100644 index 0000000000..4ac2222ed3 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/sand-water.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/water.png b/core/assets-raw/sprites_replacement/blocks/environment/water.png new file mode 100644 index 0000000000..631f99201a Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/water.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/white-tree-dead.png b/core/assets-raw/sprites_replacement/blocks/environment/white-tree-dead.png new file mode 100644 index 0000000000..4831e1879e Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/white-tree-dead.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/white-tree.png b/core/assets-raw/sprites_replacement/blocks/environment/white-tree.png new file mode 100644 index 0000000000..af2b61c5ca Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/white-tree.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/extra/block-border.png b/core/assets-raw/sprites_replacement/blocks/extra/block-border.png new file mode 100644 index 0000000000..415c5a6849 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/extra/block-border.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/extra/block-select.png b/core/assets-raw/sprites_replacement/blocks/extra/block-select.png new file mode 100644 index 0000000000..f2c77caa2b Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/extra/block-select.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/extra/place-arrow.png b/core/assets-raw/sprites_replacement/blocks/extra/place-arrow.png new file mode 100644 index 0000000000..5ae905b23f Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/extra/place-arrow.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/turrets/duo.png b/core/assets-raw/sprites_replacement/blocks/turrets/duo.png new file mode 100644 index 0000000000..efcdb60832 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/turrets/duo.png differ diff --git a/core/assets-raw/sprites_replacement/editor/block-border-editor.png b/core/assets-raw/sprites_replacement/editor/block-border-editor.png new file mode 100644 index 0000000000..415c5a6849 Binary files /dev/null and b/core/assets-raw/sprites_replacement/editor/block-border-editor.png differ diff --git a/core/assets-raw/sprites_replacement/editor/clear-editor.png b/core/assets-raw/sprites_replacement/editor/clear-editor.png new file mode 100644 index 0000000000..a804d435b6 Binary files /dev/null and b/core/assets-raw/sprites_replacement/editor/clear-editor.png differ diff --git a/core/assets-raw/sprites_replacement/editor/pack.json b/core/assets-raw/sprites_replacement/editor/pack.json new file mode 100644 index 0000000000..91480ffa76 --- /dev/null +++ b/core/assets-raw/sprites_replacement/editor/pack.json @@ -0,0 +1,8 @@ +{ + duplicatePadding: true, + combineSubdirectories: true, + flattenPaths: true, + maxWidth: 2048, + maxHeight: 2048, + fast: true, +} diff --git a/core/assets-raw/sprites_replacement/effects/error.png b/core/assets-raw/sprites_replacement/effects/error.png new file mode 100644 index 0000000000..f784bec923 Binary files /dev/null and b/core/assets-raw/sprites_replacement/effects/error.png differ diff --git a/core/assets-raw/sprites_replacement/effects/laser-end.png b/core/assets-raw/sprites_replacement/effects/laser-end.png new file mode 100644 index 0000000000..dc90d3620b Binary files /dev/null and b/core/assets-raw/sprites_replacement/effects/laser-end.png differ diff --git a/core/assets-raw/sprites_replacement/effects/laser.png b/core/assets-raw/sprites_replacement/effects/laser.png new file mode 100644 index 0000000000..0072419acc Binary files /dev/null and b/core/assets-raw/sprites_replacement/effects/laser.png differ diff --git a/core/assets-raw/sprites_replacement/effects/minelaser-end.png b/core/assets-raw/sprites_replacement/effects/minelaser-end.png new file mode 100644 index 0000000000..46ab615894 Binary files /dev/null and b/core/assets-raw/sprites_replacement/effects/minelaser-end.png differ diff --git a/core/assets-raw/sprites_replacement/effects/minelaser.png b/core/assets-raw/sprites_replacement/effects/minelaser.png new file mode 100644 index 0000000000..21acfa15d4 Binary files /dev/null and b/core/assets-raw/sprites_replacement/effects/minelaser.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-blast-compound.png b/core/assets-raw/sprites_replacement/items/item-blast-compound.png new file mode 100644 index 0000000000..c14eb34b11 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-blast-compound.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-coal.png b/core/assets-raw/sprites_replacement/items/item-coal.png new file mode 100644 index 0000000000..13727cd802 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-coal.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-copper.png b/core/assets-raw/sprites_replacement/items/item-copper.png new file mode 100644 index 0000000000..50742d5643 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-copper.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-graphite.png b/core/assets-raw/sprites_replacement/items/item-graphite.png new file mode 100644 index 0000000000..68b074bdc7 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-graphite.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-lead.png b/core/assets-raw/sprites_replacement/items/item-lead.png new file mode 100644 index 0000000000..040918a394 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-lead.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-metaglass.png b/core/assets-raw/sprites_replacement/items/item-metaglass.png new file mode 100644 index 0000000000..3c45a8873f Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-metaglass.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-phase-fabric.png b/core/assets-raw/sprites_replacement/items/item-phase-fabric.png new file mode 100644 index 0000000000..6f226c7a97 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-phase-fabric.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-plastanium.png b/core/assets-raw/sprites_replacement/items/item-plastanium.png new file mode 100644 index 0000000000..454afb274a Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-plastanium.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-pyratite.png b/core/assets-raw/sprites_replacement/items/item-pyratite.png new file mode 100644 index 0000000000..eec30df17d Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-pyratite.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-sand.png b/core/assets-raw/sprites_replacement/items/item-sand.png new file mode 100644 index 0000000000..ec9c497fd3 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-sand.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-scrap.png b/core/assets-raw/sprites_replacement/items/item-scrap.png new file mode 100644 index 0000000000..e0a70317e0 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-scrap.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-silicon.png b/core/assets-raw/sprites_replacement/items/item-silicon.png new file mode 100644 index 0000000000..5d4cfab004 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-silicon.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-spore-pod.png b/core/assets-raw/sprites_replacement/items/item-spore-pod.png new file mode 100644 index 0000000000..aa69408ee7 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-spore-pod.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-surge-alloy.png b/core/assets-raw/sprites_replacement/items/item-surge-alloy.png new file mode 100644 index 0000000000..9fc6aa4561 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-surge-alloy.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-thorium.png b/core/assets-raw/sprites_replacement/items/item-thorium.png new file mode 100644 index 0000000000..80bd29633c Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-thorium.png differ diff --git a/core/assets-raw/sprites_replacement/items/item-titanium.png b/core/assets-raw/sprites_replacement/items/item-titanium.png new file mode 100644 index 0000000000..3e15e1e7c7 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-titanium.png differ diff --git a/core/assets-raw/sprites_replacement/items/liquid-cryofluid.png b/core/assets-raw/sprites_replacement/items/liquid-cryofluid.png new file mode 100644 index 0000000000..198c21ad17 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/liquid-cryofluid.png differ diff --git a/core/assets-raw/sprites_replacement/items/liquid-oil.png b/core/assets-raw/sprites_replacement/items/liquid-oil.png new file mode 100644 index 0000000000..e0fbc07cf2 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/liquid-oil.png differ diff --git a/core/assets-raw/sprites_replacement/items/liquid-slag.png b/core/assets-raw/sprites_replacement/items/liquid-slag.png new file mode 100644 index 0000000000..87c2a41d07 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/liquid-slag.png differ diff --git a/core/assets-raw/sprites_replacement/items/liquid-water.png b/core/assets-raw/sprites_replacement/items/liquid-water.png new file mode 100644 index 0000000000..025c812967 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/liquid-water.png differ diff --git a/core/assets-raw/sprites_replacement/shapes/circle.png b/core/assets-raw/sprites_replacement/shapes/circle.png index 459e48082a..e2e6c0b2ec 100644 Binary files a/core/assets-raw/sprites_replacement/shapes/circle.png and b/core/assets-raw/sprites_replacement/shapes/circle.png differ diff --git a/core/assets-raw/sprites_replacement/shapes/shape-3.png b/core/assets-raw/sprites_replacement/shapes/shape-3.png index 358facf7db..5e98717513 100644 Binary files a/core/assets-raw/sprites_replacement/shapes/shape-3.png and b/core/assets-raw/sprites_replacement/shapes/shape-3.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 05e2b4525b..81b71ebf88 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -21,6 +21,7 @@ stat.built = Buildings Built:[accent] {0} stat.destroyed = Buildings Destroyed:[accent] {0} stat.deconstructed = Buildings Deconstructed:[accent] {0} stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = Are you sure you want to delete the map "[accent]{0}[]"? level.highscore = High Score: [accent]{0} @@ -33,12 +34,15 @@ deconstruction.title = Block Deconstruction Guide deconstruction = You've just selected [accent]block deconstruction mode[].\n\nTo begin breaking, simply tap a block near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin de-constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Remove blocks in an area[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel deconstruction or selection[] by pressing the X at the bottom left. showagain = Don't show again next session coreattack = < Core is under attack! > +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} database = Core Database savegame = Save Game loadgame = Load Game joingame = Join Game addplayers = Add/Remove Players customgame = Custom Game +newgame = New Game none = close = Close quit = Quit @@ -184,7 +188,6 @@ map.nospawn = This map does not have any cores for the player to spawn in! Add a map.nospawn.pvp = This map does not have any enemy cores for player to spawn into! Add[SCARLET] red[] cores to this map in the editor. map.invalid = Error loading map: corrupted or invalid map file. editor.brush = Brush -editor.slope = \\ editor.openin = Open In Editor editor.oregen = Ore Generation editor.oregen.info = Ore Generation: @@ -245,10 +248,21 @@ abandon.text = This zone and all its resources will be lost to the enemy. locked = Locked complete = [LIGHT_GRAY]Complete: resume = Resume Zone:\n[LIGHT_GRAY]{0} -bestwave = [LIGHT_GRAY]Best: {0} -launch = Launch +bestwave = [LIGHT_GRAY]Best Wave: {0} +launch = < LAUNCH > launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] {0} Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Unlock configuring loadout:\nWave {0}. zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Wave {0} reached:\nNew zone requirements met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson]Failed to connect to server:\n\n[accent]{0} error.unreachable = Server unreachable.\nIs the address spelled correctly? @@ -264,14 +278,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Language settings.reset = Reset to Defaults @@ -291,12 +300,15 @@ no = No info.title = Info error.title = [crimson]An error has occured error.crashtitle = An error has occured -blocks.unknown=[LIGHT_GRAY]??? +blocks.outputspeed = Drill Speed: {0}/s +blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Block Info +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = Power Capacity blocks.powershot = Power/Shot blocks.targetsair = Targets Air -blocks.itemspeed = Units Moved +blocks.itemsmoved = Move Speed blocks.shootrange = Range blocks.size = Size blocks.liquidcapacity = Liquid Capacity @@ -317,16 +329,23 @@ blocks.inputitems = Input Items blocks.outputitem = Output Item blocks.drilltier = Drillables blocks.drillspeed = Base Drill Speed +blocks.maxunits = Max Active Units blocks.liquidoutput = Liquid Output blocks.liquidoutputspeed = Liquid Output Speed blocks.liquiduse = Liquid Use blocks.coolant = Coolant +blocks.liquid = Liquid blocks.coolantuse = Coolant Use blocks.inputliquidfuel = Fuel Liquid blocks.liquidfueluse = Liquid Fuel Use blocks.boostitem = Boost Item blocks.boostliquid = Boost Liquid blocks.health = Health +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Inaccuracy blocks.shots = Shots blocks.reload = Shots/Second @@ -334,11 +353,11 @@ blocks.inputfuel = Fuel blocks.fuelburntime = Fuel Burn Time blocks.inputcapacity = Input capacity blocks.outputcapacity = Output capacity +blocks.ammo = Ammo unit.blocks = blocks unit.powersecond = power units/second unit.liquidsecond = liquid units/second unit.itemssecond = items/second -unit.pixelssecond = pixels/second unit.liquidunits = liquid units unit.powerunits = power units unit.degrees = degrees @@ -351,6 +370,7 @@ category.items = Items category.crafting = Crafting category.shooting = Shooting category.optional = Optional Enhancements +setting.animatedwater.name = Animated Water setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS @@ -392,7 +412,8 @@ keybind.screenshot.name = Map Screenshot keybind.move_x.name = Move x keybind.move_y.name = Move y keybind.select.name = Select/Shoot -keybind.break.name = Break +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = Deselect keybind.shoot.name = Shoot keybind.zoom_hold.name = Zoom Hold @@ -411,8 +432,8 @@ keybind.chat_scroll.name = Chat scroll keybind.drop_unit.name = Drop Unit keybind.zoom_minimap.name = Zoom minimap mode.help.title = Description of modes -mode.waves.name = Waves -mode.waves.description = The normal mode. Limited resources and automatic incoming waves. +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. mode.sandbox.name = Sandbox mode.sandbox.description = Infinite resources and no timer for waves. mode.freebuild.name = Freebuild @@ -420,7 +441,7 @@ mode.freebuild.description = Limited resources and no timer for waves. mode.pvp.name = PvP mode.pvp.description = Fight against other players locally. mode.attack.name = Attack -mode.attack.descrption = No waves, with the goal to destroy the enemy base. +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = Items content.liquid.name = Liquids content.unit.name = Units @@ -445,8 +466,8 @@ item.phase-fabric.name = Phase Fabric item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. item.surge-alloy.name = Surge Alloy item.surge-alloy.description = An advanced alloy with unique electrical properties. -item.biomatter.name = Biomatter -item.biomatter.description = A clump of organic mush; used for conversion into oil or as a basic fuel. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = Sand item.sand.description = A common material that is used extensively in smelting, both in alloying and as a flux. item.blast-compound.name = Blast Compound @@ -458,7 +479,7 @@ item.metaglass.description = A super-tough glass compound. Extensively used for item.scrap.name = Scrap item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = Water -liquid.lava.name = Lava +liquid.slag.name = Slag liquid.oil.name = Oil liquid.cryofluid.name = Cryofluid mech.alpha-mech.name = Alpha @@ -493,11 +514,10 @@ mech.glaive-ship.weapon = Flame Repeater item.explosiveness = [LIGHT_GRAY]Explosiveness: {0}% item.flammability = [LIGHT_GRAY]Flammability: {0}% item.radioactivity = [LIGHT_GRAY]Radioactivity: {0}% -item.fluxiness = [LIGHT_GRAY]Flux Power: {0}% unit.health = [LIGHT_GRAY]Health: {0} unit.speed = [LIGHT_GRAY]Speed: {0} mech.weapon = [LIGHT_GRAY]Weapon: {0} -mech.armor = [LIGHT_GRAY]Armor: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]Item Capacity: {0} mech.minespeed = [LIGHT_GRAY]Mining Speed: {0} mech.minepower = [LIGHT_GRAY]Mining Power: {0} @@ -505,25 +525,56 @@ mech.ability = [LIGHT_GRAY]Ability: {0} liquid.heatcapacity = [LIGHT_GRAY]Heat Capacity: {0} liquid.viscosity = [LIGHT_GRAY]Viscosity: {0} liquid.temperature = [LIGHT_GRAY]Temperature: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0} [LIGHT_GRAY](Constructing) block.spawn.name = Enemy Spawn -block.core.name = Core -block.metalfloor.name = Metal Floor -block.deepwater.name = deepwater -block.water.name = water -block.lava.name = lava +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus +block.deepwater.name = Deep Water +block.water.name = Water block.tar.name = Tar -block.blackstone.name = Black Stone block.stone.name = Stone -block.dirt.name = Dirt -block.sand.name = Sand +block.sand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.grass.name = Grass -block.shrub.name = Shrub -block.rock.name = Rock -block.blackrock.name = Black Rock -block.icerock.name = icerock +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulder +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = Copper Wall block.copper-wall-large.name = Large Copper Wall block.titanium-wall.name = Titanium Wall @@ -535,7 +586,6 @@ block.thorium-wall-large.name = Large Thorium Wall block.door.name = Door block.door-large.name = Large Door block.duo.name = Duo -block.scorch.name = Scorch block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = Conveyor @@ -547,30 +597,29 @@ block.sorter.name = Sorter block.sorter.description = Sorts items. If an item matches the selection, it is allowed to pass. Otherwise, the item is outputted to the left and right. block.overflow-gate.name = Overflow Gate block.overflow-gate.description = A combination splitter and router that only outputs to the left and right if the front path is blocked. -block.smelter.name = Smelter -block.arc-smelter.name = Arc Smelter block.silicon-smelter.name = Silicon Smelter block.phase-weaver.name = Phase Weaver block.pulverizer.name = Pulverizer block.cryofluidmixer.name = Cryofluid Mixer block.melter.name = Melter block.incinerator.name = Incinerator -block.biomattercompressor.name = Biomatter Compressor +block.spore-press.name = Spore Press block.separator.name = Separator -block.centrifuge.name = Centrifuge block.power-node.name = Power Node block.power-node-large.name = Large Power Node +block.surge-tower.name = Surge Tower block.battery.name = Battery block.battery-large.name = Large Battery block.combustion-generator.name = Combustion Generator block.turbine-generator.name = Turbine Generator +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = Mechanical Drill block.pneumatic-drill.name = Pneumatic Drill block.laser-drill.name = Laser Drill block.water-extractor.name = Water Extractor block.cultivator.name = Cultivator -block.alpha-mech-pad.name = Alpha Mech Pad -block.dart-ship-pad.name = Dart Ship Pad +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = Delta Mech Pad block.javelin-ship-pad.name = Javelin Ship Pad block.trident-ship-pad.name = Trident Ship Pad @@ -595,7 +644,6 @@ block.bridge-conveyor.name = Bridge Conveyor block.plastanium-compressor.name = Plastanium Compressor block.pyratite-mixer.name = Pyratite Mixer block.blast-mixer.name = Blast Mixer -block.solidifer.name = Solidifer block.solar-panel.name = Solar Panel block.solar-panel-large.name = Large Solar Panel block.oil-extractor.name = Oil Extractor @@ -604,6 +652,7 @@ block.phantom-factory.name = Phantom Drone Factory block.wraith-factory.name = Wraith Fighter Factory block.ghoul-factory.name = Ghoul Bomber Factory block.dagger-factory.name = Dagger Mech Factory +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Titan Mech Factory block.fortress-factory.name = Fortress Mech Factory block.revenant-factory.name = Revenant Fighter Factory @@ -616,7 +665,6 @@ block.liquid-junction.name = Liquid Junction block.bridge-conduit.name = Bridge Conduit block.rotary-pump.name = Rotary Pump block.thorium-reactor.name = Thorium Reactor -block.command-center.name = Command Center block.mass-driver.name = Mass Driver block.blast-drill.name = Airblast Drill block.thermal-pump.name = Thermal Pump @@ -635,21 +683,21 @@ block.rtg-generator.name = RTG Generator block.spectre.name = Spectre block.meltdown.name = Meltdown block.container.name = Container -block.core.description = The most important building in the game. block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = blue team.red.name = red team.orange.name = orange team.none.name = gray team.green.name = green team.purple.name = purple -unit.alpha-drone.name = Alpha Drone unit.spirit.name = Spirit Drone unit.spirit.description = The starter drone unit. Spawns in the core by default. Automatically mines ores and repairs blocks. unit.phantom.name = Phantom Drone unit.phantom.description = An advanced drone unit. Automatically mines ores and repairs blocks. Significantly more effective than a spirit drone. unit.dagger.name = Dagger unit.dagger.description = A basic ground unit. Useful in swarms. +unit.crawler.name = Crawler unit.titan.name = Titan unit.titan.description = An advanced, armored ground unit. Attacks both ground and air targets. unit.ghoul.name = Ghoul Bomber @@ -659,7 +707,11 @@ unit.wraith.description = A fast, hit-and-run interceptor unit. unit.fortress.name = Fortress unit.fortress.description = A heavy artillery ground unit. unit.revenant.name = Revenant -unit.revenant.description = A heavy laser platform. +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = Your mission here is to eradicate the[LIGHT_GRAY] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this. tutorial.drill = Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein. tutorial.conveyor = [accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core. @@ -683,8 +735,6 @@ tutorial.dagger = Link power nodes to the factory.\nOnce requirements are met, a tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. block.copper-wall.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves. block.copper-wall-large.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves.\nSpans multiple tiles. -block.dense-alloy-wall.description = A standard defensive block.\nAdequate protection from enemies. -block.dense-alloy-wall-large.description = A standard defensive block.\nAdequate protection from enemies.\nSpans multiple tiles. block.thorium-wall.description = A strong defensive block.\nGood protection from enemies. block.thorium-wall-large.description = A strong defensive block.\nGood protection from enemies.\nSpans multiple tiles. block.phase-wall.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful. @@ -714,9 +764,7 @@ block.titanium-conveyor.description = Advanced item transport block. Moves items block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles. block.junction.description = Acts as a bridge for two crossing conveyor belts. Useful in situations with two different conveyors carrying different materials to different locations. block.mass-driver.description = Ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. -block.smelter.description = Burns coal for smelting copper and lead into dense alloy. -block.arc-smelter.description = Smelts copper and lead into dense alloy by using an external power source. -block.silicon-smelter.description = Reduces sand with highly pure coke in order to produce silicon. +block.silicon-smelter.description = Reduces sand with highly pure coal in order to produce silicon. block.plastanium-compressor.description = Produces plastanium from oil and titanium. block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. block.alloy-smelter.description = Produces surge alloy from titanium, lead, silicon and copper. @@ -724,34 +772,31 @@ block.pulverizer.description = Crushes stone into sand. Useful when there is a l block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. block.blast-mixer.description = Uses oil for transforming pyratite into the less flammable but more explosive blast compound. block.cryofluidmixer.description = Combines water and titanium into cryofluid which is much more efficient for cooling. -block.solidifer.description = Cools lava to stone at a fast pace. -block.melter.description = Heats up stone to very high temperatures to obtain lava. +block.melter.description = Melts down scrap into slag for further processing or usage in turrets. block.incinerator.description = Gets rid of any excess item or liquid. -block.biomattercompressor.description = Compresses biomatter in order to retrieve oil. -block.separator.description = Exposes stone to water pressure in order to obtain various minerals contained in the stone. -block.centrifuge.description = More efficient than the separator, but also more expensive to build and requires power. +block.spore-press.description = Compresses spore pods into oil. +block.separator.description = Extracts useful minerals from slag. block.power-node.description = Transmits power to connected nodes. Up to four power sources, sinks or nodes can be connected. The node will receive power from or supply power to any adjacent blocks. block.power-node-large.description = Has a larger radius than the power node and connects to up to six power sources, sinks or nodes. block.battery.description = Stores power whenever there is an abundance and provides power whenever there is a shortage, as long as there is capacity left. block.battery-large.description = Stores much more power than a regular battery. block.combustion-generator.description = Generates power by burning oil or flammable materials. block.turbine-generator.description = More efficient than a combustion generator, but requires additional water. -block.thermal-generator.description = Generates a large amount of power from lava. +block.thermal-generator.description = Generates power when placed in hot locations. block.solar-panel.description = Provides a small amount of power from the sun. block.solar-panel-large.description = Provides much better power supply than a standard solar panel, but is also much more expensive to build. -block.thorium-reactor.description = Generates huge amounts of power from highly radioactive thorium. Requires constant cooling. Will explode violently if insufficient amounts of coolant are supplied. Power output depends on fullness, with base power generated at half capacity. +block.thorium-reactor.description = Generates huge amounts of power from highly radioactive thorium. Requires constant cooling. Will explode violently if insufficient amounts of coolant are supplied. Power output depends on fullness, with base power generated at full capacity. block.rtg-generator.description = A radioisotope thermoelectric generator which does not require cooling but provides less power than a thorium reactor. block.unloader.description = Unloads items from a container, vault or core onto a conveyor or directly into an adjacent block. The type of item to be unloaded can be changed by tapping on the unloader. -block.container.description = Stores a small amount of items of each type. Adjacent containers, vaults and cores will be treated as a single storage unit. An[LIGHT_GRAY] unloader[] can be used to retrieve items from the container. -block.vault.description = Stores a large amount of items of each type. Adjacent containers, vaults and cores will be treated as a single storage unit. An[LIGHT_GRAY] unloader[] can be used to retrieve items from the vault. +block.container.description = Stores a small amount of items of each type. An[LIGHT_GRAY] unloader[] can be used to retrieve items from the container. +block.vault.description = Stores a large amount of items of each type. An[LIGHT_GRAY] unloader[] can be used to retrieve items from the vault. block.mechanical-drill.description = A cheap drill. When placed on appropriate tiles, outputs items at a slow pace indefinitely. block.pneumatic-drill.description = An improved drill which is faster and able to process harder materials by making use of air pressure. block.laser-drill.description = Allows drilling even faster through laser technology, but requires power. Additionally, radioactive thorium can be retrieved with this drill. block.blast-drill.description = The ultimate drill. Requires large amounts of power. block.water-extractor.description = Extracts water from the ground. Use it when there is no lake nearby. -block.cultivator.description = Cultivates the soil with water in order to obtain biomatter. +block.cultivator.description = Cultivates tiny concentrations of spores into industry-ready pods. block.oil-extractor.description = Uses large amounts of power in order to extract oil from sand. Use it when there is no direct source of oil nearby. -block.dart-ship-pad.description = Leave your current vessel and change into a basic fighter aircraft.\nUse the pad by double tapping while standing on it. block.trident-ship-pad.description = Leave your current vessel and change into a reasonably well armored heavy bomber.\nUse the pad by double tapping while standing on it. block.javelin-ship-pad.description = Leave your current vessel and change into a strong and fast interceptor with lightning weapons.\nUse the pad by double tapping while standing on it. block.glaive-ship-pad.description = Leave your current vessel and change into a large, well-armored gunship.\nUse the pad by double tapping while standing on it. @@ -764,10 +809,10 @@ block.wraith-factory.description = Produces fast, hit-and-run interceptor units. block.ghoul-factory.description = Produces heavy carpet bombers. block.dagger-factory.description = Produces basic ground units. block.titan-factory.description = Produces advanced, armored ground units. + block.fortress-factory.description = Produces heavy artillery ground units. block.revenant-factory.description = Produces heavy laser air units. block.repair-point.description = Continuously heals the closest damaged unit in its vicinity. -block.command-center.description = Allows changing friendly AI behavior. Currently, attack, retreat and patrol commands are supported. block.conduit.description = Basic liquid transport block. Works like a conveyor, but with liquids. Best used with extractors, pumps or other conduits. block.pulse-conduit.description = Advanced liquid transport block. Transports liquids faster and stores more than standard conduits. block.phase-conduit.description = Advanced liquid transport block. Uses power to teleport liquids to a connected phase conduit over several tiles. @@ -777,17 +822,15 @@ block.liquid-junction.description = Acts as a bridge for two crossing conduits. block.bridge-conduit.description = Advanced liquid transport block. Allows transporting liquids over up to 3 tiles of any terrain or building. block.mechanical-pump.description = A cheap pump with slow output, but no power consumption. block.rotary-pump.description = An advanced pump which doubles up speed by using power. -block.thermal-pump.description = The ultimate pump. Three times as fast as a mechanical pump and the only pump which is able to retrieve lava. +block.thermal-pump.description = The ultimate pump. block.router.description = Accepts items from one direction and outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets. block.distributor.description = An advanced router which splits items to up to 7 other directions equally. block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building. -block.alpha-mech-pad.description = When given enough power, rebuilds your ship into the[accent] Alpha[] mech. block.item-source.description = Infinitely outputs items. Sandbox only. block.liquid-source.description = Infinitely outputs liquids. Sandbox only. block.item-void.description = Destroys any items which go into it without using power. Sandbox only. block.power-source.description = Infinitely outputs power. Sandbox only. block.power-void.description = Voids all power inputted into it. Sandbox only. liquid.water.description = Commonly used for cooling machines and waste processing. -liquid.lava.description = Can be transformed into[LIGHT_GRAY] stone[], used for generating power or used as ammo for certain turrets. liquid.oil.description = Can be burnt, exploded or used as a coolant. liquid.cryofluid.description = The most efficient liquid for cooling things down. diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties index 466827c14f..9c665955be 100644 --- a/core/assets/bundles/bundle_cs.properties +++ b/core/assets/bundles/bundle_cs.properties @@ -13,13 +13,16 @@ linkfail = Nepodařilo se otevřít odkaz!\nURL byla zkopírována do schránky. screenshot = Snímek obrazovky uložen {0} gameover = Konec hry gameover.pvp = [accent] {0}[] Tým Vyhrál! -sector.gameover = Tento sektor byl ztracen. Znovu obsadit? -sector.retry = Znovu highscore = [accent]Nový Rekord! -wave.lasted = Vydržel jsi do vlny [accent]{0}[]. -level.highscore = Nejvyšší skóre: [accent]{0} -level.delete.title = Potvrdit smazání +stat.wave = Waves Defeated:[accent] {0} +stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} +stat.built = Buildings Built:[accent] {0} +stat.destroyed = Buildings Destroyed:[accent] {0} +stat.deconstructed = Buildings Deconstructed:[accent] {0} +stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = Jsi si jistý že chceš smazat mapu "[accent]{0}[]"? +level.highscore = Nejvyšší skóre: [accent]{0} level.select = Výběr levelu level.mode = Herní mód: construction.desktop = K odznačení bloku nebo k zastavení stavby, [accent]stiskni mezerník[]. @@ -29,61 +32,36 @@ deconstruction.title = Návod k dekonstrukci bloků. deconstruction = Právě jsi vybral [accent]Mód dekonstrukce bloků[].\n\nK boření staveb, jednoduše vyber blok poblíž tvé lodi.\nJakmile jsis vybral nějaké bloky, stiskni pole potvrzení, a tvoje loď je začne sama dekonstruovat.\n\n- [accent]Odstranění bloků[] z tvého výběru kliknutím na ně.\n- [accent]Odstranění bloků v oblasti[] provedeš stisknutím prázdného pole a přetažením do jakéhokoliv směru.\n- [accent]Zrušení dekonstrukce nebo výběru[] stisknutím X v levém dolním rohu. showagain = Znovu neukazovat ! coreattack = < Jádro je pod útokem! > -unlocks = Odemykatelné +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = Uložit hru loadgame = Načíst hru joingame = Připojit se ke hře addplayers = Přidat/Odebrat hráče customgame = Vlastní hra -sectors = Sektory -sector = Sektor: [LIGHT_GRAY]{0} -sector.time = Čas: [LIGHT_GRAY]{0} -sector.deploy = Výsadek -sector.abandon = Opustit -sector.abandon.confirm = Jsi si jistý že chceš opustit veškerý postup v tomto sektoru?\nTento krok je nevratný! -sector.resume = Pokračovat -sector.locked = [scarlet][[Incomplete] -sector.unexplored = [accent][[Unexplored] -missions = Mise:[LIGHT_GRAY] {0} -mission = Mise:[LIGHT_GRAY] {0} -mission.main = Hlavní mise:[LIGHT_GRAY] {0} -mission.info = Informace o misi -mission.complete = Mise splněna! -mission.complete.body = Sektor {0},{1} Byl dobyt. -mission.wave = Udrž se[accent] {0}/{1} []Vln\nVlna za {2} -mission.wave.enemies = Udrž se[accent] {0}/{1} []vln\n{2} Nepřátel -mission.wave.enemy = Udrž se[accent] {0}/{1} []vln\n{2} Nepřátel -mission.wave.menu = Udrž se[accent] {0}[] vln -mission.battle = Znič nepřátelské jádro -mission.resource.menu = Získej {0} x{1} -mission.resource = Získej {0}:\n[accent]{1}/{2}[] -mission.block = Vytvoř {0} -mission.unit = Vytvoř {0} Jednotek -mission.command = Pošli rozkaz {0} jednotkám -mission.linknode = Propoj energetický uzel -mission.display = [accent]Mise:\n[LIGHT_GRAY]{0} -mission.mech = Změň na Mecha[accent] {0}[] -mission.create = Vytvoř[accent] {0}[] +newgame = New Game none = close = Zavřít quit = Ukončit maps = Mapy continue = Pokračovat -nextmission = Další Mise maps.none = [LIGHT_GRAY]Žádné mapy nebyly nalezeny! about.button = O hře name = Name: noname = Nejdřív si vyber[accent] herní jméno[]. filename = Jméno složky: unlocked = Nový blok odemknut! -unlocked.plural = Nové bloky odemknuty! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. players = {0} hráčů online players.single = {0} hráč online server.closing = [accent]Zavírám server... server.kicked.kick = Byl jsi vykopnut ze serveru! server.kicked.serverClose = Server je zavřený. -server.kicked.sectorComplete = Sektor Dokončen. -server.kicked.sectorComplete.text = Tvá mise je dokončena.\nServer teď bude pokračovat v dalším sektoru. server.kicked.clientOutdated = Zastaralý klient hry! Aktualizuj si hru! server.kicked.serverOutdated = Zastaralý server! Řekni hostiteli o aktualizaci! server.kicked.banned = Jsi zabanován na tomto serveru. @@ -92,6 +70,7 @@ server.kicked.nameInUse = Někdo se stejným jménem\nje aktuálně na serveru. server.kicked.nameEmpty = Tvé jméno je neplatné. server.kicked.idInUse = Již jsi na tomhle serveru připojen! Připojování se dvěma účty není povoleno. server.kicked.customClient = Tento server nepodporuje vlastní verze hry. Stáhni si oficiální verzi. +server.kicked.gameover = Game over! host.info = [accent]hostitel[] hostuje server na portu [scarlet]6567[]. \nKdokoliv na stejné [LIGHT_GRAY]wifi nebo místní síti[] by měl vidět server ve svém listu serverů.\n\nJestli chcete aby se uživatelé připojovali odkudkoliv pomocí IP, [accent]přesměrování portů[] je nutné.\n\n[LIGHT_GRAY]Poznámka: Jestli někdo má problém s připojením ke své LAN hře, ujistěte se že má Mindustry povolený přístup k místní síti v nastavení Firewallu. join.info = Tady můžeš vložit [accent]IP serveru[] ke kterému se chceš připojit, nebo objevit [accent]Servery Místní sítě[] ke kterým se chceš připojit.\nLAN i Multiplayer jsou podporovány.\n\n[LIGHT_GRAY]Poznámka: Není žádný globální seznam serverů; Pokud se budeš chtít připojit k někomu pomocí IP, budeš jí muset znát od hostitele. hostserver = Hostovat hru @@ -162,7 +141,6 @@ save.rename.text = Nové jméno: selectslot = Vyber uložení. slot = [accent]Slot {0} save.corrupted = [accent]Uložení je poškozené nebo neplatné\nPokud jsi právě aktualizoval svou hru, je to možná změnou formátu pro ukládání a [scarlet]NE[] chyba hry. -sector.corrupted = [accent]Byla nalezena uložená pozice pro tentosektor, ale načtení se nezdařilo.\nNová pozice byla vytvořena. empty = on = On off = Off @@ -172,6 +150,7 @@ save.wave = Vlna {0} save.difficulty = Obtížnost: {0} save.date = Naposledy uloženo: {0} save.playtime = Herní čas: {0} +warning = Warning. confirm = Potvrdit delete = Smazat ok = OK @@ -207,7 +186,6 @@ map.nospawn = Tato mapa nemá žádná jádra pro hráče ke spawnutí! přidej[ map.nospawn.pvp = Tato mapa nemá žádné nepřátelské jádra pro hráče ke spawnutí! přidej[SCARLET] red[] jádro na tuto mapu v editoru. map.invalid = Chyba v načítání mapy: poškozený nebo neplatný soubor mapy. editor.brush = Štětec -editor.slope = \\ editor.openin = Otevřít v editoru. editor.oregen = Generovat nerostné zdroje. editor.oregen.info = Generování nerostných zdrojů: @@ -262,7 +240,26 @@ tutorial = Tutoriál editor = Editor mapeditor = Editor map donate = Darovat - +abandon = Abandon +abandon.text = This zone and all its resources will be lost to the enemy. +locked = Locked +complete = [LIGHT_GRAY]Complete: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Best: {0} +launch = Launch +launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson]Nepovedlo se připojení k serveru:\n\n[accent]{0} error.unreachable = Server je nedostupný.\nJe adresa napsaná správně? error.invalidaddress = Neplatná adresa. @@ -270,8 +267,20 @@ error.timedout = Čas vypršel!\nUjisti se že hostitel má nastavené přesměr error.mismatch = Chyba Packetu:\nKlient/Verze serveru se neshodují.\nUjisti se že máš nejnovější verzi Mindustry! error.alreadyconnected = Již připojeno. error.mapnotfound = Soubor mapy nebyl nalezen! +error.io = Network I/O error. error.any = neznámá chyba sítě. - +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = Jazyk settings.reset = nastavit výchozí settings.rebind = Přenastavit @@ -282,7 +291,6 @@ settings.graphics = Zobrazení settings.cleardata = Resetovat data hry... settings.clear.confirm = Jsi si jistý že chceš resetovat obsah hry?\nTento krok je nevratný! settings.clearall.confirm = [scarlet]Varování![]\nToto vyresetuje všechna data, včetně uložení, map, odemykatelných a nastavení ovládání.\nJakmile stiskneš 'ok' data se vymažou a hra se automaticky ukončí. -settings.clearsectors = Vymazaní sektorů settings.clearunlocks = Vymazání odemykatelných settings.clearall = Vymazat všechno paused = [accent]< Pauza > @@ -291,12 +299,15 @@ no = Ne info.title = Informace error.title = [crimson]Objevila se chyba error.crashtitle = Objevila se chyba -blocks.unknown=[LIGHT_GRAY]??? +blocks.outputspeed = Drill Speed: {0}/s +blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Informace o bloku +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = Kapacita energie blocks.powershot = Energie na výstřel blocks.targetsair = Zaměřuje vzdušné jednotky -blocks.itemspeed = Zpracování +blocks.itemsmoved = Move Speed blocks.shootrange = Dostřel blocks.size = velikost blocks.liquidcapacity = Kapacita tekutin @@ -317,16 +328,23 @@ blocks.inputitems = Vstupní předměty blocks.outputitem = Výstupní předmět blocks.drilltier = Vrtatelné blocks.drillspeed = Základní rychlost vrtu +blocks.maxunits = Max Active Units blocks.liquidoutput = Výstup tekutin blocks.liquidoutputspeed = Rychlost výstupu tekutin blocks.liquiduse = Spotřebuje tekutin blocks.coolant = Chlazení +blocks.liquid = Liquid blocks.coolantuse = Spotřeba chlazení blocks.inputliquidfuel = Palivo-tekutina blocks.liquidfueluse = Spotřeba Paliva-tekutiny blocks.boostitem = Předmět pro zrychlení blocks.boostliquid = Tekutina pro zrychlení blocks.health = Životy +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Nepřesnost/výchylka blocks.shots = Střely blocks.reload = Střely za sekundu @@ -334,11 +352,11 @@ blocks.inputfuel = Palivo blocks.fuelburntime = Čas spalování paliva blocks.inputcapacity = Vstupní kapacita blocks.outputcapacity = Výstupní kapacita +blocks.ammo = Ammo unit.blocks = Bloky unit.powersecond = jednotek energie/sekunda unit.liquidsecond = jednotek tekutin/sekundu unit.itemssecond = předmětů/sekundu -unit.pixelssecond = pixelů/sekundu unit.liquidunits = jednotek tekutin unit.powerunits = jednotek energie unit.degrees = úhly @@ -392,7 +410,8 @@ keybind.screenshot.name = Sníměk mapy keybind.move_x.name = Pohyb na X keybind.move_y.name = Pohyb na Y keybind.select.name = Vybrat/Střílet -keybind.break.name = Ničit +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = Odznačit keybind.shoot.name = Střílet keybind.zoom_hold.name = Přiblížení-podržení @@ -411,8 +430,8 @@ keybind.chat_scroll.name = Chat posun keybind.drop_unit.name = Zahodit jednotku keybind.zoom_minimap.name = Přiblížit minimapu mode.help.title = Popis módů -mode.waves.name = Vlny -mode.waves.description = Normální mód. Limitované zdroje a automaticky přicházející Vlny nepřátel. +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. mode.sandbox.name = Sandbox mode.sandbox.description = Nekonečné zdroje a žádný čas pro vlny nepřátel. mode.freebuild.name = Freebuild @@ -420,22 +439,19 @@ mode.freebuild.description = Limitované zdroje a žádný čas pro vlny nepřá mode.pvp.name = PvP mode.pvp.description = Bojuj proti ostatním hráčům v lokální síti. mode.attack.name = Útok -mode.attack.descrption = Žádné vlny, cílem je zničit nepřátelskou základnu. +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = Předměty content.liquid.name = Tekutiny content.unit.name = jednotky -content.recipe.name = Bloky +content.block.name = Blocks content.mech.name = Mechy -item.stone.name = Kámen -item.stone.description = Běžný, nespracovaný materiál ,Používá se k separaci a přečišťování do jiných materiáů na roztavení na lávu. item.copper.name = Měď item.copper.description = Užitečný strukturální materiál. Používá se rozsáhle v ostatních typech bloků. item.lead.name = Olovo item.lead.description = Základní počáteční materiál. Požívá se rozsáhle v elektronice a v blocích pro transport tekutin. item.coal.name = Uhlí item.coal.description = Běžné a snadno dostupné palivo, pochází z Ostravy. -item.dense-alloy.name = Hustá Slitina -item.dense-alloy.description = Těžká slitina z Olova a Mědi. Používá se v pokročilých transportních blocích a ve vyšší třídě vrtů. +item.graphite.name = Graphite item.titanium.name = Titánium item.titanium.description = Vzácný, velice lehký kov, používá se rozsáhle v trasportu tekutin, vrtech a letounech. item.thorium.name = Thorium @@ -448,16 +464,20 @@ item.phase-fabric.name = Fázová tkanina item.phase-fabric.description = Skoro beztížná substance používaná v pokročilé elektronice a v sebeopravné technologii. item.surge-alloy.name = Impulzní slitina item.surge-alloy.description = Pokročilá slitina s unikátními elektronickými vlastnostmi. -item.biomatter.name = BioHmota -item.biomatter.description = Shluk organické kaše; Používá se k přeměně na ropu nebo jako jednoduché palivo. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = Písek item.sand.description = Běžný materiál rozšířeně používaný v spalování slitin. item.blast-compound.name = Výbušná směs item.blast-compound.description = Těkavá směs používaná v bombácha a výbušninách. Dá se spalovat ale jako palivo se nedoporučuje. item.pyratite.name = Pyratite item.pyratite.description = Extrémně vznětlivá substance, používá ve vznětovém střelivu. +item.metaglass.name = Metaglass +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = Voda -liquid.lava.name = Láva +liquid.slag.name = Slag liquid.oil.name = Ropa liquid.cryofluid.name = Cryofluid mech.alpha-mech.name = Alfa @@ -492,11 +512,10 @@ mech.glaive-ship.weapon = Plamenný Opakovač item.explosiveness = [LIGHT_GRAY]Výbušnost: {0}% item.flammability = [LIGHT_GRAY]Zápalnost: {0}% item.radioactivity = [LIGHT_GRAY]Radioaktivita: {0}% -item.fluxiness = [LIGHT_GRAY]Tok energie: {0}% unit.health = [LIGHT_GRAY]Životy: {0} unit.speed = [LIGHT_GRAY]Rychlost: {0} mech.weapon = [LIGHT_GRAY]Zbraň: {0} -mech.armor = [LIGHT_GRAY]Brnění: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]Kapacita předmětů: {0} mech.minespeed = [LIGHT_GRAY]Rychlost těžení: {0} mech.minepower = [LIGHT_GRAY]Síla těžení: {0} @@ -504,29 +523,60 @@ mech.ability = [LIGHT_GRAY]Schopnost: {0} liquid.heatcapacity = [LIGHT_GRAY]Kapacita teploty: {0} liquid.viscosity = [LIGHT_GRAY]Viskozita: {0} liquid.temperature = [LIGHT_GRAY]Teplota: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0} [LIGHT_GRAY](Constructing) block.spawn.name = Nepřátelský Spawn -block.core.name = Jádro -block.metalfloor.name = Kovová podlaha +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = Hluboká voda block.water.name = Voda -block.lava.name = Láva block.tar.name = Tar -block.blackstone.name = Černý kámen block.stone.name = Kámen -block.dirt.name = Hlína block.sand.name = Písek block.ice.name = Led block.snow.name = Sníh -block.grass.name = Tráva -block.shrub.name = Keř -block.rock.name = Kámen -block.blackrock.name = Černý kámen -block.icerock.name = Ledový kámen +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = Měděná zeď block.copper-wall-large.name = Velká měděná zeď -block.dense-alloy-wall.name = Zeď husté slitiny -block.dense-alloy-wall-large.name = Velká zeď husté slitiny +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = Fázová stěna block.phase-wall-large.name = Velká fázová stěna block.thorium-wall.name = Thoriová stěna @@ -534,7 +584,6 @@ block.thorium-wall-large.name = Velká thoriová stěna block.door.name = Dveře block.door-large.name = Velké dveře block.duo.name = Duo -block.scorch.name = Scorch block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = Dopravník @@ -546,30 +595,29 @@ block.sorter.name = Dělička block.sorter.description = Třídí předměty. Jestli je předmět shodný s výběrem, je mu dovoleno projít. Naopak neshodné předměty jsou vypuštěny do prava nebo do leva. block.overflow-gate.name = Brána přetečení block.overflow-gate.description = Kombinace distributoru a děličky která má výstup do leva nebo do prava jen pokud je přední strana zablokovaná. -block.smelter.name = Pec -block.arc-smelter.name = Oblouková Pec block.silicon-smelter.name = Silicon Smelter block.phase-weaver.name = Tkalcovna pro fázovou tkaninu block.pulverizer.name = Rozmělňovač block.cryofluidmixer.name = Cryofluid mixér block.melter.name = Tavírna block.incinerator.name = Spalovna -block.biomattercompressor.name = Kompresor na Biohmotu +block.spore-press.name = Spore Press block.separator.name = Separátor -block.centrifuge.name = Centrifuga block.power-node.name = Energetický uzel block.power-node-large.name = Velký energetický uzel +block.surge-tower.name = Surge Tower block.battery.name = Baterie block.battery-large.name = Velká baterie block.combustion-generator.name = Spalovací generátor block.turbine-generator.name = Turbínový generátor +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = Mechanický vrt block.pneumatic-drill.name = Pneumatický vrt block.laser-drill.name = Laserový vrt block.water-extractor.name = Vodní extraktor block.cultivator.name = Kultivátor -block.alpha-mech-pad.name = Plošina pro Alfa Mech -block.dart-ship-pad.name = Plošina pro Šipka Mech +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = Plošina pro Delta Mech block.javelin-ship-pad.name = Plošina pro Oštěp Mech block.trident-ship-pad.name = Plošina pro loď Trojzubec @@ -594,7 +642,6 @@ block.bridge-conveyor.name = Mostový přepravník block.plastanium-compressor.name = Kompresor na Plastanium block.pyratite-mixer.name = Pyratit mixér block.blast-mixer.name = Výbušninový mixér -block.solidifer.name = Krystalizér block.solar-panel.name = Solární panel block.solar-panel-large.name = Velký solární panel block.oil-extractor.name = Ropný Extraktor @@ -615,7 +662,6 @@ block.liquid-junction.name = Křižovatka tekutin block.bridge-conduit.name = Mostové potrubí block.rotary-pump.name = Rotační pumpa block.thorium-reactor.name = Thoriový Reaktor -block.command-center.name = Příkazové centrum block.mass-driver.name = Hromadný Distributor block.blast-drill.name = Tlakovzdušný vrt block.thermal-pump.name = Termální pumpa @@ -634,20 +680,21 @@ block.rtg-generator.name = RTG Generátor block.spectre.name = Spektr block.meltdown.name = Meltdown block.container.name = Kontejnér -block.core.description = Ta nejdůležitější stavba ve hře. +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = modrá team.red.name = červená team.orange.name = oranžová team.none.name = šedá team.green.name = zelená team.purple.name = fialová -unit.alpha-drone.name = Alfa Dron unit.spirit.name = Spirit Dron unit.spirit.description = Startovní dron. Standartně se objevuje u jádra. Automaticky těží rudy a opravuje stavby. unit.phantom.name = Fantom Dron unit.phantom.description = Pokročilý dron. Automaticky těží rudy a opravuje stavby. Podstatně víc efektivní než Spirit dron. unit.dagger.name = Dagger unit.dagger.description = Základní pozemní jednotka. Efektivní ve velkém počtu. +unit.crawler.name = Crawler unit.titan.name = Titán unit.titan.description = Pokročilá, obrněná pozemní jednotka. Útočí jak na pozemní tak vzdušné nepřátelské jednotky. unit.ghoul.name = Ghůl Bombardér @@ -657,7 +704,11 @@ unit.wraith.description = Rychlý, udeř a uteč stíhací letoun. unit.fortress.name = Pevnost unit.fortress.description = Težká, pozemní artilérní jednotka. unit.revenant.name = Revenant -unit.revenant.description = Težká laserová plošina. +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = Tvá mise tady je vyhladit [LIGHT_GRAY] nepřítele[].\n\nZačneš tím že[accent] budeš těžit měd[]. Klikni na měděnou rudu poblíž tvého jádra pro těžbu. tutorial.drill = Manuální zěžba je neefektivní.\n[accent]Vrty []budou těžit automaticky.\npolož jeden na měděnou rudu. tutorial.conveyor = [accent]Dopravníky[] jsou zapotřebí k dopravě materiálu k jádru.\nVytvoř řadu dopravníku od vrtu až k jádru. @@ -681,8 +732,6 @@ tutorial.dagger = Propoj energetické uzly s továrnou.\nJakmile jsou požadavky tutorial.battle = [LIGHT_GRAY] Nepřítel[] prozradil lokaci svého jádra.\nZnič ho svými bojovými jednotkami. block.copper-wall.description = Levný defenzivní blok.\nUžitečný k obraně tvého jádra a střílen v prvotních vlnách nepřátel. block.copper-wall-large.description = Levný defenzivní blok.\nUžitečný k obraně tvého jádra a střílen v prvotních vlnách nepřátel.\nZabírá více polí. -block.dense-alloy-wall.description = Standartní defenzivní blok.\nAdekvátní obrana vůči nepřátelům. -block.dense-alloy-wall-large.description = Standartní defenzivní blok.\nAdekvátní obrana vůči nepřátelům.\nZabírá více polí. block.thorium-wall.description = Sílný defenzivní blok.\nDobrá obrana vůči nepřátelům. block.thorium-wall-large.description = Sílný defenzivní blok.\nDobrá obrana vůči nepřátelům..\nZabírá více polí. block.phase-wall.description = Né tak silná jako zeď Thoria ale odráží nepřátelské projektily dokud nejsou moc silné. @@ -712,8 +761,6 @@ block.titanium-conveyor.description = Pokročilý blok přepravy předmětů. Ne block.phase-conveyor.description = Pokročilý blok přepravy předmětů. Využívá energii k přepravě od jednoho bodu k druhému po velice dlouhé vzdálenosti. block.junction.description = Chová se jako most pro dva křížící se pásy dopravníků. Užitečný při situaci kdy dva rozdílné dopravníky dopravují dva rozdílné materiálny na rozdílné místa. block.mass-driver.description = Ultimátní blok přepravy předmětů. Sbírá několik druhů předmětů a vystřelí je k dalšímu hromadnému distributoru přes veliké vzdálenosti. -block.smelter.description = Spaluje uhlí, měd a olovo pro vytvoření husté slitiny. -block.arc-smelter.description = Spaluje měd a olovo za pomocí externího energetického zdroje. block.silicon-smelter.description = Redukuje písek s vysoce čistým koksem za účelem výroby křemíku. block.plastanium-compressor.description = Produkuje plastánium za pomocí titánia a ropy. block.phase-weaver.description = Produkuje fázovou tkaninu z radioaktivního thoria a velkého množství písku. @@ -722,12 +769,10 @@ block.pulverizer.description = Drtí kámen na písek. Užitečné když se v ob block.pyratite-mixer.description = Míchá uhlí, olovo a písek do velice hořlavého pyratitu. block.blast-mixer.description = Používá ropu k přeměně pyratitu do méně hořlavé ale více explozivní těkavé směsi. block.cryofluidmixer.description = Kombinuje vodu a titánium do cryofluid, která je více efektivní pro chlazení. -block.solidifer.description = Velice rychle chladí lávu na kámen. block.melter.description = Taví kámen při velice vysokých teplotách na lávu. block.incinerator.description = Zbaví tě přebytku předmětů. -block.biomattercompressor.description = Stlačuje biohmotu k získání ropy. +block.spore-press.description = Compresses spore pods into oil. block.separator.description = Vystaví kámen velkému tlaku vody k získání různých materiálů obsažené v kameni. -block.centrifuge.description = Více efektivní než separátor. Za to více nákladný na provoz ke které vyžaduje energii. block.power-node.description = Vysílá energii mezi propojenými uzly. Dokáže se propojit až se čtyřmi uzly či stavbami najednou. Uzel bude dostávat zásobu energie a bude ji distribuovat mezi připojené bloky. block.power-node-large.description = Má větší dosah než standartní energetický uzel and a dokáže propojit až 6 staveb nebo uzly. block.battery.description = Ukládá energii kdykoliv kdy je nadbytek ,poskytuje energii kdykolik když je pokles energie v síti, tak dlouho doku zbývá kapacita. @@ -749,7 +794,6 @@ block.blast-drill.description = Ultimátní vrt, vyžaduje velké množství ene block.water-extractor.description = Extrahuje vodu ze země. Vhodný k použití když se v oblasti nenachází zdroj vody. block.cultivator.description = Kultivuje půdu vodou za účelem získání biohmoty. block.oil-extractor.description = Vyžaduje velké množství energie na extrakci ropy z písku. Použíj ho když se v oblasti nenachází žádný zdroj ropy. -block.dart-ship-pad.description = Zanech zde své aktuální plavidlo a žměn ho na klasický bojový letoun.\nPoužíj ho poklikáním když se nacházíš nad ním. block.trident-ship-pad.description = Zanech zde své aktuální plavidlo a změň ho do docela dobře obrněného těžkého bombardéru.\nPoužíj ho poklikáním když se nacházíš nad ním. block.javelin-ship-pad.description = Zanech zde své aktuální plavidlo a změn ho na silný a rychlý stíhač s bleskovými zbraněmi.\nPoužíj ho poklikáním když se nacházíš nad ním. block.glaive-ship-pad.description = Zanech zde své aktuální plavidlo a změn ho na velkou, dobře obrněnou střeleckou loď.\nPoužíj ho poklikáním když se nacházíš nad ním. @@ -765,7 +809,6 @@ block.titan-factory.description = Produkuje pokročilé, orněné pozemní jedno block.fortress-factory.description = Produkuje těžké artilérní, pozmení jednotky. block.revenant-factory.description = Produkuje vzdušné, težké laserové stíhače.. block.repair-point.description = Kontinuálně léčí nejbližší budovy a jednotky. -block.command-center.description = Dovoluje měnit umělou inteligenci spojeneckých jednotek. Aktuálně, útok, ztáhnout se a hlídkuj příkazy jsou podporovány. block.conduit.description = Základní blok přepravy tekutin. Funguje jako dopravník, ale na tekutiny, chápeš ne ? Užívá se s extraktory, pumpami nebo jiným potrubím. block.pulse-conduit.description = Pokročilý blok přepravy tekutin. Přepravuje tekutiny rychleji a více než standartní potrubí. block.phase-conduit.description = Pokročilý blok přepravy tekutin. Používá energii k teleportu tekutin do druhého bodu přez několik polí. @@ -779,13 +822,11 @@ block.thermal-pump.description = Ultimátní pumpa. Trojnásobně rychlejší ne block.router.description = Příijmá předměty z jednoho směru a posílá je rovnoměrně do zbylých tří směrů. Užitečný při rozdělení jednoho zdroje směřující do různých cílů. block.distributor.description = Pokročilý směrovač, který z libovolného počtu vstupů vytvoří libovolný počet výstupu a rozdělí přísun předmětů rovnoměrně do každého z nich, obdoba Multiplexeru a Demultiplexeru. block.bridge-conveyor.description = Pokročilý blok přepravy předmětů. Dovoluje transport předmětů až přez tři pole jakéhokoliv terénu nebo budovy. -block.alpha-mech-pad.description = Když je dodán dostatek energie, Přestaví tvoji loď na[accent] Alfa[] mecha. block.item-source.description = Nekonečný zdroj předmětů. Jen pro Sandbox. block.liquid-source.description = Nekonečný zdroj tekutin. Jen pro Sandbox. block.item-void.description = Likviduje jakéhokoliv vstupní předmět bež použití energie. Jen pro Sandbox. block.power-source.description = Nekonečný zdroj energie. Jen pro Sandbox. block.power-void.description = Prázdnota pro veškerou energii vstupující do něj. Jen pro Sandbox. liquid.water.description = Nejčastěji se používá ke chlazení a zpracování odpadu. -liquid.lava.description = Může být transformován na[LIGHT_GRAY] kámen[], nebo pro generátor energie nebo jako střelivo pro určitý druh střílen. liquid.oil.description = Může být spálen, vybouchnout nebo použit jako chlazení. liquid.cryofluid.description = Nejefektivnější tekutina pro chlazení. diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index cd1e17809c..2c9e710f68 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -1,5 +1,6 @@ credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet!) credits = Danksagungen +contributors = Translators and Contributors discord = Trete dem Mindustry Discord bei! link.discord.description = Der offizielle Mindustry Discord Chatroom link.github.description = Quellcode des Spiels @@ -9,15 +10,19 @@ link.itch.io.description = itch.io Seite mit Downloads und der Web-Version des S link.google-play.description = Google Play Store Seite link.wiki.description = Offizelles Mindustry Wiki linkfail = Fehler beim Öffnen des Links!\nDie URL wurde in die Zwischenablage kopiert. +screenshot = Screenshot saved to {0} gameover = Der Kern wurde zerstört. gameover.pvp = Das[accent] {0}[] Team ist siegreich! -sector.gameover = Du hast diesen Sektor verloren. Erneuter Einsatz? -sector.retry = Erneut versuchen highscore = [YELLOW] Neuer Highscore! -wave.lasted = Du hast es bis Welle [accent]{0}[] ausgehalten. -level.highscore = High Score: [accent]{0} -level.delete.title = Löschen bestätigen +stat.wave = Waves Defeated:[accent] {0} +stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} +stat.built = Buildings Built:[accent] {0} +stat.destroyed = Buildings Destroyed:[accent] {0} +stat.deconstructed = Buildings Deconstructed:[accent] {0} +stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = Bist du sicher, dass du die Karte "[accent]{0}[]" löschen möchtest? +level.highscore = High Score: [accent]{0} level.select = Level Auswahl level.mode = Spielmodus: construction.desktop = Um einen Block zu deselektieren oder den Bau abzubrechen, [accent]verwende die Leertaste[]. @@ -27,60 +32,36 @@ deconstruction.title = Abbruchanleitung für Blöcke deconstruction = Du hast soeben den [accent]Abbruchmodus für Blöcke[] aktiviert.\n\nUm mit dem Abriss zu beginnen, tippe einfach auf einen Block in der Nähe deines Schiffs.\nSobald du einige Blöcke ausgewählt hast, drücke zum Bestätigen auf den Haken, und dein Schiff wird mit dem Abriss beginnen.\n\n- [accent]Entferne einen Block[] von deiner Selektion, indem du darauf tippst.\n- [accent]Reiße Blöcke in einem Gebiet ab[], indem du einen leeren Platz gedrückt hältst, und in eine Richtung ziehst.\n- [accent]Breche den Abriss or die Selektion ab[], indem du das X links unten drückst. showagain = Nächstes mal nicht mehr anzeigen coreattack = < Die Basis wird angegriffen! > -unlocks = Freigeschaltet +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = Spiel speichern loadgame = Spiel laden joingame = Spiel beitreten addplayers = Hinzufügen/Entfernen von Spielern customgame = Benutzerdefiniertes Spiel -sectors = Sektoren -sector = Sektor: [LIGHT_GRAY]{0} -sector.time = Zeit: [LIGHT_GRAY]{0} -sector.deploy = Einsatz -sector.abandon = Aufgeben -sector.abandon.confirm = Bist du sicher, dass du den gesamten Fortschritt in diesem Sektor aufgeben willst?\n Diese Aktion kann nicht rückgängig gemacht werden! -sector.resume = Fortsetzen -sector.locked = [scarlet][[Unvollständig] -sector.unexplored = [accent][[Unerforscht] -missions = Missionen:[LIGHT_GRAY] {0} -mission = Mission:[LIGHT_GRAY] {0} -mission.main = Hauptmission:[LIGHT_GRAY] {0} -mission.info = Missionsbeschreibung -mission.complete = Mission erfolgreich! -mission.complete.body = Sektor {0},{1} wurde erobert. -mission.wave = Überlebe [accent]{0}/{1}[] Wellen\nWelle in {2} -mission.wave.enemies = Überlebe[accent] {0}/{1} []Wellen\n{2} Gegner -mission.wave.enemy = Überlebe[accent] {0}/{1} []Wellen\n{2} Gegner -mission.wave.menu = Überlebe[accent] {0} []Wellen -mission.battle = Zerstöre die gegnerische Basis. -mission.resource.menu = Erlange {0} x{1} -mission.resource = Sammele {0}:\n[accent]{1}/{2}[] -mission.block = Erstelle {0} -mission.unit = Erstelle {0} Einheiten -mission.command = Sende {0}-Kommando an Einheiten -mission.linknode = Verbinde Stromknoten -mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -mission.mech = Wechsle zum [accent] {0}[]-Mech -mission.create = Platziere[accent] {0}[] +newgame = New Game none = close = Schließen quit = Verlassen maps = Karten continue = Weiter -nextmission = Nächste Mission maps.none = [LIGHT_GRAY]Keine Karten gefunden! about.button = Info name = Name: +noname = Pick a[accent] player name[] first. filename = File Name: unlocked = Neuen Block freigeschaltet! -unlocked.plural = Neue Blöcke freigeschaltet! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. players = {0} Spieler online players.single = {0} Spieler online server.closing = [accent]Schließe den Server... server.kicked.kick = Du wurdest vom Server gekickt! server.kicked.serverClose = Server geschlossen. -server.kicked.sectorComplete = Sektor abgeschlossen. -server.kicked.sectorComplete.text = Deine Mission ist abgeschlossen.\nDer Server wird nun in einen neuen Sektor wechseln. server.kicked.clientOutdated = Veralteter Client! Aktualisiere dein Spiel! server.kicked.serverOutdated = Veralteter Server! Bitte den Host um ein Update! server.kicked.banned = Du wurdest vom Server verbannt. @@ -89,6 +70,7 @@ server.kicked.nameInUse = Es ist bereits ein Spieler \nmit diesem Namen auf dem server.kicked.nameEmpty = Dein Name muss zumindest einen Buchstaben oder eine Zahl enthalten. server.kicked.idInUse = Du bist bereits auf dem Server! Anmeldungen mit zwei Accounts sind nicht gestattet. server.kicked.customClient = Der Server akzeptiert keine Custom Builds von Mindustry. Lade dir die offizielle Version herunter. +server.kicked.gameover = Game over! host.info = Der [accent]host[] Knopf startet einen Server auf den Ports [scarlet]6567[] und [scarlet]6568.[]\nJeder im gleichen [LIGHT_GRAY]W-Lan oder lokalem Netzwerk[] sollte deinen Server in seiner Server Liste sehen können.\n\nWenn du Leuten die Verbindung über IP ermöglichen willst, benötigst du [accent]Port-Forwarding[].\n\n[LIGHT_GRAY]Hinweis: Falls es Probleme mit der Verbindung im Netzwerk gibt, stell sicher, dass Mindustry in deinen Firewall Einstellungen Zugriff auf das lokale Netzwerk hat. join.info = Hier kannst du eine [accent]Server IP[] eingeben um dich zu verbinden oder Server im [accent]lokalem Netzwerk[] entdecken und dich mit ihnen verbinden.\nSowohl Spielen über das lokale Netzwerk als auch Spielen über das Internet werden unterstützt.\n\n[LIGHT_GRAY]Hinweis: Es gibt keine globale Server Liste; Wenn du dich mit jemand per IP verbinden willst musst du den Host nach seiner IP fragen. hostserver = Server hosten @@ -159,7 +141,6 @@ save.rename.text = Neuer Name selectslot = Wähle einen Spielstand slot = [accent] Platz {0} save.corrupted = [accent] Datei beschädigt oder ungültig! -sector.corrupted = [accent]Ein Spielstand für diesen Sektor wurde nicht gefunden.\nEin neuer Spielstand wurde erstellt. empty = on = An off = Aus @@ -169,6 +150,7 @@ save.wave = Welle: {0} save.difficulty = Schwierigkeitsgrad: {0} save.date = Zuletzt gespeichert: {0} save.playtime = Spielzeit: {0} +warning = Warning. confirm = Bestätigen delete = Löschen ok = OK @@ -204,7 +186,6 @@ map.nospawn = Diese Karte hat keine Kerne in denen die Spieler beginnen können! map.nospawn.pvp = Diese Karte hat keine gegnerischen Kerne wo Gegner starten könnten! Füge über den Editor [SCARLET] rote[] Kerne zu dieser Karte hinzu. map.invalid = Fehler beim Laden der Karte: Beschädigtes oder invalide Karten Datei. editor.brush = Pinsel -editor.slope = \\ editor.openin = Öffne im Editor editor.oregen = Erze generieren editor.oregen.info = Erze generiert: @@ -259,6 +240,26 @@ tutorial = Tutorial editor = Editor mapeditor = Karten Editor donate = Spenden +abandon = Abandon +abandon.text = This zone and all its resources will be lost to the enemy. +locked = Locked +complete = [LIGHT_GRAY]Complete: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Best: {0} +launch = Launch +launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson] Verbindung zum Server konnte nicht hergestellt werden: [accent]{0} error.unreachable = Server nicht erreichbar. error.invalidaddress = Ungültige Adresse. @@ -266,7 +267,20 @@ error.timedout = Zeitüberschreitung!\nStelle sicher, dass die Portweiterleitung error.mismatch = Paketfehler:\nClient und Server passen möglicherweise nicht zusammen.\nStelle sicher, dass du und der Host jeweils die neueste Version von Mindustry haben! error.alreadyconnected = Bereits verbunden. error.mapnotfound = Map file not found! +error.io = Network I/O error. error.any = Unbekannter Netzwerkfehler. +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = Sprache settings.reset = Auf Standard zurücksetzen settings.rebind = Zuweisen @@ -277,7 +291,6 @@ settings.graphics = Grafiken settings.cleardata = Spieldaten zurücksetzen... settings.clear.confirm = Bist du sicher, dass du die Spieldaten zurücksetzen willst?\n Diese Aktion kann nicht rückgänig gemacht werden! settings.clearall.confirm = [scarlet]Warnung![]\nDas wird jegliche Spieldaten zurücksetzen inklusive Speicherstände, Karten, Freischaltungen und Tastenbelegungen.\n Nachdem du 'OK' drückst wird alles zurückgesetzt und das Spiel schließt sich automatisch. -settings.clearsectors = Sektoren zurücksetzen settings.clearunlocks = Freischaltungen zurücksetzen settings.clearall = Alles zurücksetzen paused = Pausiert @@ -286,12 +299,15 @@ no = Nein info.title = [accent]Info error.title = [crimson] Ein Fehler ist aufgetreten error.crashtitle = Ein Fehler ist aufgetreten! +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Blockinfo: +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = Kapazität blocks.powershot = Stromverbrauch/Schuss blocks.targetsair = Visiert Luft Einheiten an -blocks.itemspeed = Beförderte Materialien +blocks.itemsmoved = Move Speed blocks.shootrange = Reichweite blocks.size = Größe blocks.liquidcapacity = Flüssigkeitskapazität @@ -312,16 +328,23 @@ blocks.inputitems = Akzeptierte Materialien blocks.outputitem = Erzeugtes Material blocks.drilltier = Abbaubare Erze blocks.drillspeed = Bohrgeschwindigkeit +blocks.maxunits = Max Active Units blocks.liquidoutput = Erzeugte Flüssigkeit blocks.liquidoutputspeed = Ausgabegeschwindigkeit blocks.liquiduse = Flüssigkeitsverbrauch blocks.coolant = Kühlmittel +blocks.liquid = Liquid blocks.coolantuse = Kühlmittelverbrauch blocks.inputliquidfuel = Kraftstoff blocks.liquidfueluse = Kraftstoffverbrauch blocks.boostitem = Boost Item blocks.boostliquid = Boost Liquid blocks.health = Lebenspunkte +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Ungenauigkeit blocks.shots = Schüsse blocks.reload = Schüsse/Sekunde @@ -329,11 +352,11 @@ blocks.inputfuel = Kraftstoff blocks.fuelburntime = Kraftstoff Verbrennungs-Zeit blocks.inputcapacity = Annahmekapazität blocks.outputcapacity = Ausgabekapazität +blocks.ammo = Ammo unit.blocks = Blöcke unit.powersecond = Stromeinheiten/Sekunde unit.liquidsecond = Flüssigkeitseinheiten/Sekunde unit.itemssecond = Materialeinheiten/Sekunde -unit.pixelssecond = Pixel/Sekunde unit.liquidunits = Flüssigkeitseinheiten unit.powerunits = Stromeinheiten unit.degrees = Grad @@ -346,6 +369,7 @@ category.items = Materialien category.crafting = Erzeugung category.shooting = Schießen category.optional = Optional Enhancements +setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Zielauswahl setting.fpscap.name = Max FPS setting.fpscap.none = kein @@ -378,12 +402,16 @@ category.multiplayer.name = Mehrspieler command.attack = Angreifen command.retreat = Rückzug command.patrol = Patrouillieren +keybind.gridMode.name = Block Select +keybind.gridModeShift.name = Category Select keybind.press = Drücke eine Taste... keybind.press.axis = Drücke eine Taste oder bewege eine Achse... +keybind.screenshot.name = Map Screenshot keybind.move_x.name = X-Achse keybind.move_y.name = Y-Achse keybind.select.name = Auswählen/Schießen -keybind.break.name = Abreißen +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = Auswahl aufheben keybind.shoot.name = Schießen keybind.zoom_hold.name = Zoom halten @@ -402,29 +430,28 @@ keybind.chat_scroll.name = Chat scrollen keybind.drop_unit.name = Einheit absetzen keybind.zoom_minimap.name = Minimap-Zoom mode.help.title = Beschreibung der Modi -mode.waves.name = Wellen -mode.waves.description = Der normale Modus. Begrenzte Ressourcen und automatische Wellen. +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. mode.sandbox.name = Sandkasten mode.sandbox.description = Unendliche Ressourcen und kein Timer für Wellen. mode.freebuild.name = Freier Bau mode.freebuild.description = Begrenzte Ressourcen und kein Timer für Wellen. mode.pvp.name = PvP mode.pvp.description = Kämpfe gegen andere Spieler local. +mode.attack.name = Attack +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = Materialien content.liquid.name = Flüssigkeiten content.unit.name = Einheiten -content.recipe.name = Blöcke +content.block.name = Blocks content.mech.name = Mechs -item.stone.name = Stein -item.stone.description = Ein gängiger Rohstoff ,der für die Zerteilung und Verfeinerung in andere Materialien oder geschmolzen als Lava verwendet wird. item.copper.name = Kupfer item.copper.description = Ein nützliches Material. Wird in allen Arten von Blöcken verwendet. item.lead.name = Blei item.lead.description = Ein grundliegendes Material. Häufig in Elektronik und Flüssigkeits-Transport-Blöcken verwendet. item.coal.name = Kohle item.coal.description = Ein sehr häufiger vorkommender Kraftstoff. -item.dense-alloy.name = Dichte Legierung -item.dense-alloy.description = Eine robuste Legierung aus Blei und Kupfer. Findet Verwendung in fortgeschrittenen Transport-Blöcken und höherwertigen Bohrern. +item.graphite.name = Graphite item.titanium.name = Titan item.titanium.description = Ein seltenes, sehr leichtes Metall. Häufig in Flüssigkeits-Transport-Blöcken, Abbauanlagen und Flugzeugen verwendet. item.thorium.name = Uran @@ -437,16 +464,20 @@ item.phase-fabric.name = Phasengewebe item.phase-fabric.description = Eine nahezu gewichtslose Substanz, die in fortgeschrittener Elektronik und in selbstreparierender Technologie verwendet wird. item.surge-alloy.name = Spannungsstoß-Legierung item.surge-alloy.description = Eine fortgeschrittene Legierung mit einzigartigen elektrischen Eigenschaften. -item.biomatter.name = Biomasse -item.biomatter.description = Ein Klumpen organischer Brei. Wird für die Umwandlung in Öl oder als grundliegender Kraftstoff verwendet. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = Sand item.sand.description = Ein gängiges Material, welches häufig in geschmolzener Form, flüssig oder als Legierung verwendet wird. item.blast-compound.name = Explosive Mischung item.blast-compound.description = Eine flüchtige Mischung, die in Bomben und Sprengstoffen Verwendung findet. Es besteht die Möglichkeit, es als Treibstoff zu verwenden, aber dies ist nicht empfehlenswert. item.pyratite.name = Pyratit item.pyratite.description = Eine extrem leicht entflammbare Substanz. Findet Verwendeung in Brandwaffen. +item.metaglass.name = Metaglass +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = Wasser -liquid.lava.name = Lava +liquid.slag.name = Slag liquid.oil.name = Öl liquid.cryofluid.name = Kryoflüssigkeit mech.alpha-mech.name = Alpha @@ -481,11 +512,10 @@ mech.glaive-ship.weapon = Flammen-Mehrlader item.explosiveness = [LIGHT_GRAY]Explosivität: {0} item.flammability = [LIGHT_GRAY]Entflammbarkeit: {0} item.radioactivity = [LIGHT_GRAY]Radioaktivität: {0} -item.fluxiness = [LIGHT_GRAY]Strömungskraft: {0} unit.health = [LIGHT_GRAY]Lebenskraft: {0} unit.speed = [LIGHT_GRAY]Geschwindigkeit: {0} mech.weapon = [LIGHT_GRAY]Waffe: {0} -mech.armor = [LIGHT_GRAY]Rüstung: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]Materialkapazität: {0} mech.minespeed = [LIGHT_GRAY]Erzabbaugeschwindigkeit: {0} mech.minepower = [LIGHT_GRAY]Erzabbaukraft: {0} @@ -493,29 +523,60 @@ mech.ability = [LIGHT_GRAY]Fähigkeit: {0} liquid.heatcapacity = [LIGHT_GRAY]Wärmekapazität: {0} liquid.viscosity = [LIGHT_GRAY]Viskosität: {0} liquid.temperature = [LIGHT_GRAY]Temperatur: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](Constructing) block.spawn.name = Gegnerischer Startpunkt -block.core.name = Basis -block.metalfloor.name = Metallboden +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = Tiefes Wasser block.water.name = Wasser -block.lava.name = Lava block.tar.name = Teer -block.blackstone.name = Schwarzer Stein block.stone.name = Stein -block.dirt.name = Dreck block.sand.name = Sand block.ice.name = Eis block.snow.name = Schnee -block.grass.name = Gras -block.shrub.name = Busch -block.rock.name = Fels -block.blackrock.name = Schwarzer Fels -block.icerock.name = Eisfels +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = Kupfermauer block.copper-wall-large.name = Große Kupfermauer -block.dense-alloy-wall.name = Dichte Legierungsmauer -block.dense-alloy-wall-large.name = Große dichte Legierungsmauer +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = Phasenmauer block.phase-wall-large.name = Große Phasenmauer block.thorium-wall.name = Thorium-Mauer @@ -523,7 +584,6 @@ block.thorium-wall-large.name = Große Thorium-Mauer block.door.name = Tür block.door-large.name = Große Tür block.duo.name = Duo -block.scorch.name = Scorch block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = Förderband @@ -535,30 +595,29 @@ block.sorter.name = Sortierer block.sorter.description = Sortiert Materialien. Wenn ein Gegenstand der Auswahl entspricht, darf er vorbei. Andernfalls wird er links oder rechts ausgegeben. block.overflow-gate.name = Überlauftor block.overflow-gate.description = Ein Verteiler, der nur Materialien nach links oder rechts ausgibt, falls der Weg gerade aus blockiert ist. -block.smelter.name = Schmelzer -block.arc-smelter.name = Lichtbogen-Schmelzer block.silicon-smelter.name = Silizium-Schmelzer block.phase-weaver.name = Phasenweber block.pulverizer.name = Pulverisierer block.cryofluidmixer.name = Kryoflüssigkeitsmixer block.melter.name = Schmelzer block.incinerator.name = Verbrennungsanlage -block.biomattercompressor.name = Biomassenverdichter +block.spore-press.name = Spore Press block.separator.name = Separierer -block.centrifuge.name = Zentrifuge block.power-node.name = Stromknoten block.power-node-large.name = Großer Stromknoten +block.surge-tower.name = Surge Tower block.battery.name = Batterie block.battery-large.name = Große Batterie block.combustion-generator.name = Verbrennungsgenerator block.turbine-generator.name = Turbinengenerator +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = Mechanischer Bohrer block.pneumatic-drill.name = Pneumatischer Bohrer block.laser-drill.name = Laser-Bohrer block.water-extractor.name = Wasser-Extraktor block.cultivator.name = Kultivierer -block.alpha-mech-pad.name = Alpha Mech Pad -block.dart-ship-pad.name = Dart Ship Pad +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = Delta Mech Pad block.javelin-ship-pad.name = Javelin Ship Pad block.trident-ship-pad.name = Trident Ship Pad @@ -583,7 +642,6 @@ block.bridge-conveyor.name = Brücken-Transportband block.plastanium-compressor.name = Plastanium-Verdichter block.pyratite-mixer.name = Pyratit-Mixer block.blast-mixer.name = Sprengmixer -block.solidifer.name = Verhärter block.solar-panel.name = Solar Panel block.solar-panel-large.name = Großes Solar Panel block.oil-extractor.name = Oil Extraktor @@ -604,7 +662,6 @@ block.liquid-junction.name = Flüssigkeits-Kreuzung block.bridge-conduit.name = Kanalbrücke block.rotary-pump.name = Rotierende Pumpe block.thorium-reactor.name = Thorium-Reaktor -block.command-center.name = Kommandozentrum block.mass-driver.name = Massenbeschleuniger block.blast-drill.name = Sprengbohrer block.thermal-pump.name = Thermische Pumpe @@ -623,20 +680,21 @@ block.rtg-generator.name = RTG Generator block.spectre.name = Spectre block.meltdown.name = Meltdown block.container.name = Container -block.core.description = Das wichtigste Gebäude im Spiel +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = Blau team.red.name = Rot team.orange.name = Orange team.none.name = Grau team.green.name = Grün team.purple.name = Lila -unit.alpha-drone.name = Alpha Drohne unit.spirit.name = Spirit Drohne unit.spirit.description = Die anfängliche Drohne. Sie wird gewöhnlich in der Basis Erz ab, sammelt Materialien und repariert Blöcke. unit.phantom.name = Phantom Drohne unit.phantom.description = Eine fortgeschrittene Drohne. Baut automatisch Erz ab, sammelt Materialien und repariert Blöcke. Deutlich effizienter als die Drohne. unit.dagger.name = Dagger unit.dagger.description = Eine Standard-Bodeneinheit. Nützlich in Schwärmen. +unit.crawler.name = Crawler unit.titan.name = Titan unit.titan.description = Eine fortgeschrittene gepanzerte Bodeneinheit. Greift sowohl Boden- als auch Luftziele an. unit.ghoul.name = Ghoul Bomber @@ -646,7 +704,11 @@ unit.wraith.description = Eine schneller Abfangjäger. unit.fortress.name = Fortress unit.fortress.description = Eine schwere Artillerie-Bodeneinheit. unit.revenant.name = Revenant -unit.revenant.description = Eine schwere Laser-Platform. +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = Deine Mission ist es den [LIGHT_GRAY]Gegner[] auszurotten.\n\n Beginne damit [accent] Kupfer abzubauen[]. Beginne in dem du auf ein Kupfer Vorkommen nahe deines Kerns klickst. tutorial.drill = Manuelles Abbauen von Ressourcen ist ineffizient.\n[accent]Bohrer[] können automatisch abbauen.\n Platziere einen auf einem Kupfer Vorkommen. tutorial.conveyor = [accent]Transportbänder[] werden dazu benutzt Materialien zum Kern zu transportieren.\n Erstelle eine Reihe von Transportbändern zum Kern. @@ -670,8 +732,6 @@ tutorial.dagger = Verbinde die Fabrik mit einem Stromknoten. Wenn alle Vorausset tutorial.battle = Der[LIGHT_GRAY] Gegner[] hat seinen Kern offenbart.\nZerstöre ihn mit deiner Einheit und den Dagger Mechs. block.copper-wall.description = Ein günstiger Verteidigungsblock.\nNützlich, um die Basis und Türme in den ersten Wellen zu beschützen. block.copper-wall-large.description = Ein günstiger Verteidigungsblock.\nNützlich, um die Basis und Türme in den ersten Wellen zu beschützen.\nBenötigt mehrere Kacheln. -block.dense-alloy-wall.description = Ein Standard-Verteidigungsblock.\nAngemessener Schutz vor Feinden. -block.dense-alloy-wall-large.description = Ein Standard-Verteidigungsblock.\nAngemessener Schutz vor Feinden.\nBenötigt mehrere Kacheln. block.thorium-wall.description = Ein starker Verteidigungsblock.\nGuter Schutz vor Feinden. block.thorium-wall-large.description = Ein starker Verteidigungsblock.\nGuter Schutz vor Feinden.\nBenötigt mehrere Kacheln. block.phase-wall.description = Nicht so stark wie eine Thorium-Mauer, aber reflektiert Schüsse bis zu einer gewissen Stärke. @@ -701,8 +761,6 @@ block.titanium-conveyor.description = Verbesserter Transportblock. Bewegt Materi block.phase-conveyor.description = Verbesserter Transportblock. Verwendet Strom, um Materialien zu einem verbundenen Phasen-Förderband über mehrere Kacheln zu teleportieren. block.junction.description = Fungiert als Brücke zwischen zwei kreuzenden Förderbändern. Nützlich, wenn zwei verschiedene Förderbänder sich kreuzen, aber unterschiedliche Materialien verwenden. block.mass-driver.description = Ultimativer Transportblock. Sammelt mehrere Materialien und schießt sie zu einem verbundenen Massenbeschleuniger über eine große Reichweite. -block.smelter.description = Verbrennt Kohle, um Kupfer und Blei zu einer dichten Legierung zu verschmelzen. -block.arc-smelter.description = Verschmilzt Kupfer und Blei zu einer dichten Legierung, indem es eine externe Stromquelle benutzt. block.silicon-smelter.description = Reduziert Sand mit hochreinem Kohlenstoff, um Silizium zu produzieren. block.plastanium-compressor.description = Produziert Plastanium aus Öl und Titan. block.phase-weaver.description = Produziert Phasengewebe aus radioaktivem Thorium und großen Mengen an Sand. @@ -711,12 +769,10 @@ block.pulverizer.description = Zertrümmert Stein zu Sand. Nützlich, wenn kein block.pyratite-mixer.description = Vermischt Kohle, Blei und Sand zu hochentzündlichem Pyratit. block.blast-mixer.description = Verwendet Öl, um Pyratit in eine weniger enzündliche aber explosivee Mischung umzuwandeln. block.cryofluidmixer.description = Verarbeitet Wasser mit Titan zu einer Kryoflüssigkeit, die viel effizienter kühlt. -block.solidifer.description = Kühlt Lava zu großen Mengen Stein. block.melter.description = Erhitzt Stein auf extrem hohe Temperaturen, um Lava zu erhalten. block.incinerator.description = Vernichtet beliebige überschüssige Materialien oder Flüssigkeiten. -block.biomattercompressor.description = Komprimiert Biomasse, um Öl zu erhalten. +block.spore-press.description = Compresses spore pods into oil. block.separator.description = Setzt Stein Wasserdruck aus, um verschiedene Mineralien im Stein freizulegen. -block.centrifuge.description = Effizienter als der Separierer, aber auch teurer zum Bauen und benötigt Strom. block.power-node.description = Überträgt Strom zu verbundenen Knoten. Bis zu vier Stromquellen, -verbraucher oder -knoten können verbunden werden. Der Knoten erhält Strom von benachbarten Knoten und gibt Strom benachbarte Blöcke weiter. block.power-node-large.description = Hat einen größeren Radius als der normale Stromknoten und verbindet bis zu sechs Stromquellen, -verbraucher oder -knoten. block.battery.description = Speichert Strom, solange ein Überschuss besteht, und gibt ihn bei Knappheit ab, solange Kapazität vorhanden ist. @@ -738,7 +794,6 @@ block.blast-drill.description = Der ultimative Bohrer. Benötigt große Mengen a block.water-extractor.description = Extrahiert Wasser aus dem Boden. Verwende ihn, wenn es keinen See in der Nähe gibt. block.cultivator.description = Kultiviert den Boden mit Wasser, um Biomasse zu erzeugen. block.oil-extractor.description = Verwendet große Mengen an Strom, um Öl aus Sand zu extrahieren. Verwende ihn, wenn es keine direkte Ölquelle gibt. -block.dart-ship-pad.description = Wechsle in einen Standard-Jäger.\nVerwende das Pad, indem du doppelt darauf tippst, während du darauf bist. block.trident-ship-pad.description = Wechsle in einen massiv gepanzerten schweren Bomber.\nVerwende das Pad, indem du doppelt darauf tippst, während du darauf bist. block.javelin-ship-pad.description = Wechsle in einen starken und schnellen Abfangjäger mit Blitz-Waffen.\nVerwende das Pad, indem du doppelt darauf tippst, während du darauf bist. block.glaive-ship-pad.description = Wechsle in ein großes, gut gepanzertes Kampfflugzeug.\nVerwende das Pad, indem du doppelt darauf tippst, während du darauf bist. @@ -754,7 +809,6 @@ block.titan-factory.description = Produziert fortgeschrittene, gepanzerte Bodene block.fortress-factory.description = Produziert schwere Artillerie-Bodeneinheiten. block.revenant-factory.description = Produziert schwere Laser-Bodeneinheiten. block.repair-point.description = Heilt durchgehend die nächste befreundete, beschädigte Einheit in der Umgebung. -block.command-center.description = Erlaubt es, die KI der eigenen Einheiten zu ändern. Momentan sind Angriff, Rückzug und Patroulle unterstützt. block.conduit.description = Standard Flüssigkeits-Transportblock. Funktioniert wie ein Förderband, nur für Flüssigkeiten. Wird am Besten mit Extraktoren, Pumpen oder anderen Kanälen benutzt. block.pulse-conduit.description = Verbesserter Flüssigkeits-Transportblock. Transportiert Flüssigkeiten schneller und speichert mehr als Standard Kanäle. block.phase-conduit.description = Verbesserter Flüssigkeits-Transportblock. Verwendet Strom, um Flüssigkeiten zu einem verbundenen Phasenkanal zu teleportieren. @@ -768,13 +822,11 @@ block.thermal-pump.description = Die ultimative Pumpe, dreimal so schnell wie ei block.router.description = Akzeptiert Materialien aus einer Richtung und leitet sie gleichmäßig in bis zu drei andere Richtungen weiter. Nützlich, wenn die Materialien aus einer Richtung an mehrere Empfänger verteilt werden sollen. block.distributor.description = Ein weiterentwickelter Router, der Materialien in bis zu sieben Richtungen gleichmäßig verteilt. block.bridge-conveyor.description = Verbesserter Transportblock. Erlaubt es, Materialien über bis zu 3 Kacheln beliebigen Terrains oder Inhalts zu transportieren. -block.alpha-mech-pad.description = Sofern genügend Strom zur Verfügung steht, baut dieses Pad deinen Schiff in einen [accent]Alpha[] mech zurück. block.item-source.description = Produziert unendlich items. Nur im Sandkasten verfügbar. block.liquid-source.description = Produziert unendlich Flüssigkeiten. Nur im Sandkasten verfügbar. block.item-void.description = Zerstört Materialien, die hereingegeben werden, ohne Strom zu verbrauchen. Nur im Sandkasten verfügbar. block.power-source.description = Erzeugt unendlich viel Strom. Nur im Sandkasten verfügbar. block.power-void.description = Verschlingt den kompletten übrigen Strom. Nur im Sandkasten verfügbar. liquid.water.description = Wird überlicherweise zum Kühlen von Maschinen und zur Müllverarbeitung verwendet. -liquid.lava.description = Kann zu [LIGHT_GRAY] Stein[] verarbeitet werden, zur Stromerzeugung verwendet werden oder als Munition für bestimmte Geschütztürme verwendet werden. liquid.oil.description = Kann verbrannt, zum explodieren gebracht, oder als Kühlung verwendet werden. liquid.cryofluid.description = Die effizienteste Flüssigkeit, um Dinge herunter zu kühlen. diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index c9886889eb..84a6d51bc5 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -1,5 +1,6 @@ credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet!) credits = Créditos +contributors = Translators and Contributors discord = ¡Únete al Discord de Mindustry! link.discord.description = La sala oficial del Discord de Mindustry link.github.description = Código fuente del juego @@ -9,15 +10,19 @@ link.itch.io.description = itch.io es la página donde podes descargar las versi link.google-play.description = Ficha en la Google Play Store link.wiki.description = Wiki oficial de Mindustry linkfail = ¡Error al abrir el enlace!\nLa URL ha sido copiada a su portapapeles. +screenshot = Screenshot saved to {0} gameover = Tu núcleo ha sido destruido. gameover.pvp = ¡El equipo[accent] {0}[] ha ganado! -sector.gameover = Este sector ha sido perdido. ¿Re-desplegar? -sector.retry = Reintentar highscore = [accent]¡Nueva mejor puntuación! -wave.lasted = Duraste hasta la ronda [accent]{0}[]. -level.highscore = Puntuación más alta: [accent]{0} -level.delete.title = Confirmar Eliminación +stat.wave = Waves Defeated:[accent] {0} +stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} +stat.built = Buildings Built:[accent] {0} +stat.destroyed = Buildings Destroyed:[accent] {0} +stat.deconstructed = Buildings Deconstructed:[accent] {0} +stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = ¿Estás seguro que quieres borrar el mapa "[accent]{0}[]"? +level.highscore = Puntuación más alta: [accent]{0} level.select = Selección de nivel level.mode = Modo de juego: construction.desktop = Los controles de la versión de escritorio han cambiado.\nPara deseleccionar un bloque o dejar de construir, [accent]usa la space tab[]. @@ -27,60 +32,36 @@ deconstruction.title = Guía de Deconstrucción de Bloques deconstruction = Acaba de seleccionar el [accent]modo de deconstrucción de blocks[].\n\nPara empezar a destruir, simplemente presione en un bloque cercano a su nave.\nCuando haya terminado de seleccionar algunos bloques, presiona la casilla para confirmar, y su nave empezara a de-construirlos.\n\n- [accent]Remueve bloques[] de tu selección presionando en ellos.\n- [accent]Remueve bloques en un area[] presionando y manteniendo en un espacio vacío, y arrastrando hacia cualquier dirección.\n- [accent]Cancela la deconstrucción o selección[] presionando la X abajo a la izquierda. showagain = No mostrar otra vez en la próxima sesión coreattack = < ¡El núcleo está bajo ataque! > -unlocks = Desbloqueos +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = Guardar Partida loadgame = Cargar Partida joingame = Unirse a la Partida addplayers = Agregar/Quitar Jugadores customgame = Partida personalizada -sectors = Sectores -sector = Sector: [LIGHT_GRAY]{0} -sector.time = Tiempo: [LIGHT_GRAY]{0} -sector.deploy = Desplegar -sector.abandon = Abandonar -sector.abandon.confirm = ¿Realmente quieres abandonar todo el progreso hecho en este sector?\n¡Esto no se puede deshacer! -sector.resume = Continuar -sector.locked = [scarlet][[Incompleto] -sector.unexplored = [accent][[No explorado] -missions = Misiones:[LIGHT_GRAY] {0} -mission = Misión:[LIGHT_GRAY] {0} -mission.main = Misión Principal:[LIGHT_GRAY] {0} -mission.info = Información de la Misión -mission.complete = ¡Misión completada! -mission.complete.body = El Sector {0},{1} ha sido conquistado. -mission.wave = Sobrevive [accent]{0}/{1}[] hordas\nHordas en {2} -mission.wave.enemies = Sobrevive[accent] {0}/{1} []hordas\n{2} Enemigas -mission.wave.enemy = Sobrevive[accent] {0}/{1} []hordas\n{2} Enemigas -mission.wave.menu = Sobrevive[accent] {0} []hordas -mission.battle = Destruye la base enemiga. -mission.resource.menu = Obtener {0} x{1} -mission.resource = Obtén {0} x{1} -mission.block = Crear {0} -mission.unit = Crear {0} -mission.command = Envía Comando {0} a las unidades -mission.linknode = Conecta nodo de energía -mission.display = [accent]Misión:\n[LIGHT_GRAY]{0} -mission.mech = Cambiar a mecanoide[accent] {0}[] -mission.create = Crear[accent] {0}[] +newgame = New Game none = close = Cerrar quit = Salir maps = Mapas continue = Continuar -nextmission = Próxima Misión maps.none = [LIGHT_GRAY]¡No se han encontrado mapas! about.button = Acerca de name = Nombre: +noname = Pick a[accent] player name[] first. filename = Nombre del archivo: unlocked = ¡Nuevo Bloque Desbloqueado! -unlocked.plural = ¡Nuevos Bloques Desbloqueados! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. players = {0} jugadores online players.single = {0} jugador online server.closing = [accent]Cerrando servidor... server.kicked.kick = ¡Has sido expulsado del servidor! server.kicked.serverClose = El servidor ha cerrado. -server.kicked.sectorComplete = Sector completado. -server.kicked.sectorComplete.text = Tu misión ha sido completada.\nEl servidor ahora continuará con el próximo sector. server.kicked.clientOutdated = ¡Cliente desactualizado! ¡Actualiza tu juego! server.kicked.serverOutdated = ¡Servidor desactualizado! ¡Pídele al anfitrión que lo actualice! server.kicked.banned = Has sido baneado del servidor. @@ -89,6 +70,7 @@ server.kicked.nameInUse = Ya hay alguien con ese\nnombre en el servidor. server.kicked.nameEmpty = Tu nombre debe por lo menos contener un carácter o número. server.kicked.idInUse = ¡Ya estás en el servidor! Conectarse con dos cuentas no está permitido. server.kicked.customClient = Este servidor no soporta versiones personalizadas. Descarga una versión oficial. +server.kicked.gameover = Game over! host.info = El botón [accent]host[] hostea un servidor en el puerto [scarlet]6567[]. \nCualquier persona en la misma [LIGHT_GRAY]wifi o red local[] debería poder ver tu servidor en la lista de servidores.\n\nSi quieres que cualquier persona se pueda conectar de cualquier lugar por IP, la [accent]asignación de puertos[] es requerida.\n\n[LIGHT_GRAY]Nota: Si alguien experimenta problemas conectándose a tu partida LAN, asegúrate de permitir a Mindustry acceso a tu red local mediante la configuración de tu firewall. join.info = Aquí, puedes escribir la [accent]IP de un server[] para conectarte, o descubrir servidores de [accent]red local[] para conectarte.\nLAN y WAN es soportado para jugar en multijugador.\n\n[LIGHT_GRAY]Nota: No hay una lista automática global de servidores; si quieres conectarte por IP, tendrás que preguntarle al anfitrión por la IP. hostserver = Hostear Servidor @@ -159,7 +141,6 @@ save.rename.text = Nuevo nombre: selectslot = Selecciona un Punto de Guardado. slot = [accent]Casilla {0} save.corrupted = [accent]¡El punto de guardado está corrupto o es inválido!\nSi acabas de actualizar el juego, esto debe ser probablemente un cambio en el formato de guardado y[scarlet] no[] un error. -sector.corrupted = [accent]El punto de guardado de este sector fue encontrado, pero su carga ha fallado.\nUn nuevo punto ha sido creado. empty = on = Encendido off = Apagado @@ -169,6 +150,7 @@ save.wave = Horda {0} save.difficulty = Dificultad: {0} save.date = Última vez guardado: {0} save.playtime = Tiempo de juego: {0} +warning = Warning. confirm = Confirmar delete = Borrar ok = OK @@ -204,7 +186,6 @@ map.nospawn = ¡Este mapa no tiene ningún núcleo en el cual pueda aparecer el map.nospawn.pvp = ¡Este mapa no tiene ningún núcleo enemigo para que aparezca el jugador! Añade un núcleo[SCARLET] red[] a este mapa en el editor. map.invalid = Error cargando el mapa: archivo corrupto o inválido. editor.brush = Pincel -editor.slope = \\ editor.openin = Abrir en el Editor editor.oregen = Generación de Minerales editor.oregen.info = Generación de Minerales: @@ -259,6 +240,26 @@ tutorial = Tutorial editor = Editor mapeditor = Editor de Mapa donate = Donar +abandon = Abandon +abandon.text = This zone and all its resources will be lost to the enemy. +locked = Locked +complete = [LIGHT_GRAY]Complete: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Best: {0} +launch = Launch +launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson]Ha fallado la conexión con el servidor: [accent]{0} error.unreachable = Servidor inaccesible. error.invalidaddress = Dirección inválida. @@ -266,7 +267,20 @@ error.timedout = ¡Se acabó el tiempo!\n¡Asegúrate que el host ha hecho el po error.mismatch = Error de paquete:\nposible versión no válida del servidor/cliente.\nAsegúrate de que tú y el host tenéis la última versión de Mindustry. error.alreadyconnected = Ya estás conectado. error.mapnotfound = ¡Archivo de mapa no encontrado! +error.io = Network I/O error. error.any = Error de red desconocido. +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = Lenguaje settings.reset = Reiniciar por los de defecto settings.rebind = Reasignar @@ -277,7 +291,6 @@ settings.graphics = Gráficos settings.cleardata = Limpiar Datos del Juego... settings.clear.confirm = ¿Estas seguro de querer limpiar estos datos?\n¡Esta acción no puede deshacerse! settings.clearall.confirm = [scarlet]ADVERTENCIA![]\nEsto va a eliminar todos tus datos, incluyendo guardados, mapas, desbloqueos y keybinds.\nUna vez presiones 'ok', el juego va a borrrar todos tus datos y saldrá del juego automáticamente. -settings.clearsectors = Eliminar Sectores settings.clearunlocks = Eliminar Desbloqueos settings.clearall = Eliminar Todo paused = Pausado @@ -286,12 +299,15 @@ no = No info.title = [accent]Información error.title = [crimson]Un error ha ocurrido. error.crashtitle = Un error ha ocurrido. +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Información del Bloque +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = Capacidad de Energía blocks.powershot = Energía/Disparo blocks.targetsair = Apunta al Aire -blocks.itemspeed = Unidades Movidas +blocks.itemsmoved = Move Speed blocks.shootrange = Rango blocks.size = Tamaño blocks.liquidcapacity = Capacidad de Líquidos @@ -312,16 +328,23 @@ blocks.inputitems = Objetos de Entrada blocks.outputitem = Objeto de Salida blocks.drilltier = Taladrables blocks.drillspeed = Velocidad Base del Taladro +blocks.maxunits = Max Active Units blocks.liquidoutput = Líquido de Salida blocks.liquidoutputspeed = Velocidad de Salida del Líquido blocks.liquiduse = Uso de Líquido blocks.coolant = Refrigerante +blocks.liquid = Liquid blocks.coolantuse = Uso del Refrigerante blocks.inputliquidfuel = Combustible Líquido blocks.liquidfueluse = Uso del Combustible Líquido blocks.boostitem = Boost Item blocks.boostliquid = Boost Liquid blocks.health = Vida +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Imprecisión blocks.shots = Disparos blocks.reload = Recarga @@ -329,11 +352,11 @@ blocks.inputfuel = Combustible blocks.fuelburntime = Tiempo de Quemado del Combustible blocks.inputcapacity = Capacidad de entrada blocks.outputcapacity = Capacidad de salida +blocks.ammo = Ammo unit.blocks = bloques unit.powersecond = unidades de energía/segundo unit.liquidsecond = unidades de líquido/segundo unit.itemssecond = objetos/segundo -unit.pixelssecond = píxeles/segundo unit.liquidunits = unidades de líquido unit.powerunits = unidades de energía unit.degrees = grados @@ -346,6 +369,7 @@ category.items = Objetos category.crafting = Fabricación category.shooting = Disparo category.optional = Mejoras Opcionales +setting.indicators.name = Ally Indicators setting.autotarget.name = Auto apuntado setting.fpscap.name = Máx FPS setting.fpscap.none = Nada @@ -378,12 +402,16 @@ category.multiplayer.name = Multijugador command.attack = Atacar command.retreat = Retirarse command.patrol = Patrullar +keybind.gridMode.name = Block Select +keybind.gridModeShift.name = Category Select keybind.press = Presiona una tecla... keybind.press.axis = Pulsa un eje o botón... +keybind.screenshot.name = Map Screenshot keybind.move_x.name = Mover x keybind.move_y.name = Mover y keybind.select.name = Seleccionar -keybind.break.name = Romper +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = Deseleccionar keybind.shoot.name = Disparar keybind.zoom_hold.name = Mantener Zoom @@ -402,29 +430,28 @@ keybind.chat_scroll.name = Chat scroll keybind.drop_unit.name = drop unit keybind.zoom_minimap.name = Zoom minimapa mode.help.title = Descripción de modos -mode.waves.name = hordas -mode.waves.description = El modo normal. con recursos limitados y entrada de hordas automática. +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. mode.sandbox.name = sandbox mode.sandbox.description = Recursos ilimitados y sin temporizador para las hordas. mode.freebuild.name = construcción libre mode.freebuild.description = recursos limitados y no hay temporizador para las hordas. mode.pvp.name = PvP mode.pvp.description = Pelea contra otros jugadores localmente. +mode.attack.name = Attack +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = Objetos content.liquid.name = Líquidos content.unit.name = Unidades -content.recipe.name = Bloques +content.block.name = Blocks content.mech.name = Mecanoides -item.stone.name = Piedra -item.stone.description = Un material muy común. Usado para separar y para refinarse a otros objetos, y también derretir en lava. item.copper.name = Cobre item.copper.description = Un útil material estructural. Usado extensivamente en todo tipo de bloques. item.lead.name = Plomo item.lead.description = Un material básico. Usado extensivamente en electrónicos y bloques de transferencia de líquidos. item.coal.name = Carbón item.coal.description = Un combustible común y preparado para ser quemado. -item.dense-alloy.name = Aleación Densa -item.dense-alloy.description = Una dura aleación fabricada con plomo y cobre. Usado en bloques de transporte avanzados y taladros de alto nivel. +item.graphite.name = Graphite item.titanium.name = Titanio item.titanium.description = Un metal raro super ligero usado extensivamente en transportación de liquidos, taladros y aeronaves. item.thorium.name = Torio @@ -437,16 +464,20 @@ item.phase-fabric.name = Tejido de fase item.phase-fabric.description = Una sustancia casi sin peso usada en electrónica avanzada y en tecnología autoreparadora. item.surge-alloy.name = Surge Alloy item.surge-alloy.description = Una aleación avanzada con propiedades eléctricas únicas. -item.biomatter.name = Biomateria -item.biomatter.description = Una bola de restos orgánicos; usado para convertirlo a petróleo o combustible básico. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = Arena item.sand.description = Un material común que es usado extensivamente en la fundición, para alear y como fundente. item.blast-compound.name = Compuesto Explosivo item.blast-compound.description = Un compuesto volatil usado en bombas y explosivos. Aunque se puede quemar como combustible, esto no es recomendable. item.pyratite.name = Pirotita item.pyratite.description = Una sustancia extremadamente inflamable usada en armas incendiarias. +item.metaglass.name = Metaglass +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = Agua -liquid.lava.name = Lava +liquid.slag.name = Slag liquid.oil.name = Petróleo liquid.cryofluid.name = Criogénico mech.alpha-mech.name = Alpha @@ -481,11 +512,10 @@ mech.glaive-ship.weapon = Flame Repeater item.explosiveness = [LIGHT_GRAY]Explosividad: {0} item.flammability = [LIGHT_GRAY]Inflamabilidad: {0} item.radioactivity = [LIGHT_GRAY]Radioactividad: {0} -item.fluxiness = [LIGHT_GRAY]Poder como Fundente: {0} unit.health = [LIGHT_GRAY]Vida: {0} unit.speed = [LIGHT_GRAY]Velocidad: {0} mech.weapon = [LIGHT_GRAY]Arma: {0} -mech.armor = [LIGHT_GRAY]Armadura: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]Capacidad de objetos: {0} mech.minespeed = [LIGHT_GRAY]Velocidad de minado: {0} mech.minepower = [LIGHT_GRAY]Potencia de minado: {0} @@ -493,29 +523,60 @@ mech.ability = [LIGHT_GRAY]Hablidad: {0} liquid.heatcapacity = [LIGHT_GRAY]Capacidad Térmica: {0} liquid.viscosity = [LIGHT_GRAY]Viscosidad: {0} liquid.temperature = [LIGHT_GRAY]Temperatura: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](Construyendo) block.spawn.name = Punto de generación -block.core.name = Núcleo -block.metalfloor.name = Suelo de Metal +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = Aguas profundas block.water.name = Agua -block.lava.name = Lava block.tar.name = Alquitrán -block.blackstone.name = Piedra negra block.stone.name = Piedra -block.dirt.name = Tierra block.sand.name = Arena block.ice.name = Hielo block.snow.name = Nieve -block.grass.name = Pasto -block.shrub.name = Arbusto -block.rock.name = Roca -block.blackrock.name = Roca negra -block.icerock.name = Roca de hielo +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = Muro de cobre block.copper-wall-large.name = Muro de cobre grande -block.dense-alloy-wall.name = Muro de aleación densa -block.dense-alloy-wall-large.name = Muro de aleación densa grande +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = Muro de Fase grande block.phase-wall-large.name = Muro de Fase grande block.thorium-wall.name = Pared de Torio @@ -523,7 +584,6 @@ block.thorium-wall-large.name = Pared de Torio grande block.door.name = Puerta block.door-large.name = Puerta Larga block.duo.name = Dúo -block.scorch.name = Lanzallamas block.hail.name = Granizo block.lancer.name = Lancero block.conveyor.name = Cinta Transportadora @@ -535,30 +595,29 @@ block.sorter.name = Clasificador block.sorter.description = Clasifica objetos. Si un objeto es igual al seleccionado, pasará al frente. Si no, el objeto saldrá por la izquierda y la derecha. block.overflow-gate.name = Compuerta de Desborde block.overflow-gate.description = Un enrutador que solo saca por la izquierda y la derecha si la cinta del frente está llena. -block.smelter.name = Horno de Fundición -block.arc-smelter.name = Horno de Arco Eléctrico block.silicon-smelter.name = Horno para Silicona block.phase-weaver.name = Tejedor de Fase block.pulverizer.name = Pulverizador block.cryofluidmixer.name = Mezclador de Criogénicos block.melter.name = Fundidor block.incinerator.name = Incinerador -block.biomattercompressor.name = Compresor de Biomateria +block.spore-press.name = Spore Press block.separator.name = Separador -block.centrifuge.name = Centrifugadora block.power-node.name = Nodo de Energía block.power-node-large.name = Nodo de Energía Grande +block.surge-tower.name = Surge Tower block.battery.name = Batería block.battery-large.name = Batería Grande block.combustion-generator.name = Generador de Combustión block.turbine-generator.name = Turbina +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = Taladro mecánico block.pneumatic-drill.name = Taladro neumático block.laser-drill.name = Taladro Laser block.water-extractor.name = Extractor de Agua block.cultivator.name = Cultivador -block.alpha-mech-pad.name = Pad de mecanoide Alpha -block.dart-ship-pad.name = Pad de nave de dardos +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = Pad de mecanoide Delta block.javelin-ship-pad.name = Pad de nave Jabalina block.trident-ship-pad.name = Pad de nave Tridente @@ -583,7 +642,6 @@ block.bridge-conveyor.name = Cinta Transportadora Puente block.plastanium-compressor.name = Compresor de Plastanio block.pyratite-mixer.name = Mezclador de Pirotita block.blast-mixer.name = Mezclador de Explosivos -block.solidifer.name = Solidificador block.solar-panel.name = Panel Solar block.solar-panel-large.name = Panel Solar Grande block.oil-extractor.name = Extractor de Petróleo @@ -604,7 +662,6 @@ block.liquid-junction.name = Cruce de Líquidos block.bridge-conduit.name = Conducto Puente block.rotary-pump.name = Bomba Rotatoria block.thorium-reactor.name = Reactor de Torio -block.command-center.name = Centro de Comando block.mass-driver.name = Teletransportador de Masa block.blast-drill.name = Taladro de explosión block.thermal-pump.name = Bomba Térmica @@ -623,20 +680,21 @@ block.rtg-generator.name = Generador RTG block.spectre.name = Espectro block.meltdown.name = Meltdown block.container.name = Contenedor -block.core.description = The most important building in the game. +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = Azul team.red.name = Rojo team.orange.name = Naranja team.none.name = Gris team.green.name = Verde team.purple.name = Púrpura -unit.alpha-drone.name = Dron Alpha unit.spirit.name = Dron Espíritu unit.spirit.description = El dron del comienzo. Aparece en el núcleo por defecto. Mina automáticamente minerales, recoge objetos y repara bloques. unit.phantom.name = Dron Fantasmal unit.phantom.description = Un dron avanzado. Mina automáticamente minerales, recoge objetos y repra bloques. Bastante más efectivo que un dron normal. unit.dagger.name = Daga unit.dagger.description = Una unidad de terreno. Útil con enjambres. +unit.crawler.name = Crawler unit.titan.name = Titán unit.titan.description = Una unidad blindada de terreno, avanzada. Ataca blancos de aire y de terreno. unit.ghoul.name = Ghoul Bomber @@ -646,7 +704,11 @@ unit.wraith.description = Una unidad interceptora rápida. unit.fortress.name = Fortress unit.fortress.description = Una unidad terrestre pesada de artillería. unit.revenant.name = Revenant -unit.revenant.description = Una plataforma láser pesada. +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = Tu objetivo aquí es erradicar el[LIGHT_GRAY] enemy[].\n\nComienza[accent]minando copper[]. Toca una veta de cobre cerca de tu núcleo para hacer esto. tutorial.drill = Minar manualmente es ineficiente.\nLos [accent]taladros pueden minar automáticamente.\nColoca uno en una veta de cobre. tutorial.conveyor = Los [accent]Conveyors[] se usan para transportar objetos al núcleo.\nConstruye una línea de transportadores del taladro al núcleo. @@ -670,8 +732,6 @@ tutorial.dagger = Conecta nodos de energía a la fábrica.\nUna vez las necesida tutorial.battle = El[LIGHT_GRAY] enemy[] ha revelado su núcleo.\nDestrúyelo con tu nave y tus unidades de combate. block.copper-wall.description = Un bloque defensivo barato.\nÚtil para defneder e núcleo y las torres en las primeras hordas. block.copper-wall-large.description = Un bloque defensivo barato.\nÚtil para defneder e núcleo y las torres en las primeras hordas.\nOcupa múltiples casillas. -block.dense-alloy-wall.description = Un bloque de defensa estándar.\nProtección adecuada contra enemigos. -block.dense-alloy-wall-large.description = Un bloque de defensa estándar.\nProtección adecuada contra enemigos.\nOcupa múltiples casillas. block.thorium-wall.description = Un bloque defensivo fuerte.\nBuena protección contra enemigos. block.thorium-wall-large.description = Un bloque defensivo fuerte.\nBuena protección contra enemigos.\nOcupa múltiples casillas. block.phase-wall.description = No es tan fuerte como un muro de torio pero rebota balas al enemigo si no son demasiado fuertes. @@ -701,8 +761,6 @@ block.titanium-conveyor.description = Bloque de transporte avanzado. Mueve objet block.phase-conveyor.description = Bloque de transporte avanzado. Usa energía para transportar objetos a otro transportador de fase conectado por varias casillas. block.junction.description = Actúa como puente para dos transportadores que se cruzan. Útil en situaciones con dos diferentes transportadores transportando diferentes materiales a diferentes lugares. block.mass-driver.description = El mejor bloque de transorte. Recoge varios objetos y los dispara a otro conductor de masa en un largo rango. -block.smelter.description = Quema carbón para fundir cobre y plomo, produciendo así aleación densa. -block.arc-smelter.description = Funde cobre y plomo en aleación densa usando una fuented de energía externa. block.silicon-smelter.description = Reduce arena con coque de alta pureza para producir silicona. block.plastanium-compressor.description = Produce plastanio con aceite y titanio. block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. @@ -711,12 +769,10 @@ block.pulverizer.description = Despedaza la piedra en arena. Útil cuando no hay block.pyratite-mixer.description = Mezcla carbón, plomo y arena en pirotita altamente inflamable. block.blast-mixer.description = Usa aceite para transformar pirotita en un objeto menos inflamable pero más explosivo: compuesto explosivo. block.cryofluidmixer.description = Combina agua y titanio en líquido criogénico que es mucho más eficiente para enfriar. -block.solidifer.description = Enfría la lava a piedra a una gran velocidad. block.melter.description = Calienta piedra a temperaturas muy altas para obtener lava. block.incinerator.description = Se deshace de cualquier líquido u objeto excesivo. -block.biomattercompressor.description = Comprime biomateria para extraer aceite. +block.spore-press.description = Compresses spore pods into oil. block.separator.description = Expone piedra a la presión del agua para obtener diversos minerales contenidos en la piedra. -block.centrifuge.description = Más eficiente que un separador, pero es más caro de construir y requiere energía. block.power-node.description = Transmite energía a nodos conectados, conecta hasta cuatro fuentes de energía, edificios que usan energía o nodos. El nodo obtendrá o transmitirá energía de cualquier bloque adyacente. block.power-node-large.description = Tiene un radio más amplio que el nodo de energía y conecta hasta seis fuentes de energía, edificios que usan energía o nodos. block.battery.description = Guarda energía cuando hay abundancia y proporciona energía cuando hay escasez de energía mientras la batería tenga energía. @@ -738,7 +794,6 @@ block.blast-drill.description = El mejor taladro. Requiere grandes cantidades de block.water-extractor.description = Extrae agua de la tierra. Úsalo cuando no haya lagos cercanos. block.cultivator.description = Cultiva la tierra para obtener biomateria. block.oil-extractor.description = Usa grandes cantidades de energía para extraer aceite de la arena. Úsalo cuando no hay fuentes directas de aceite cerca. -block.dart-ship-pad.description = Deja tu nave actual y transfórmate en una unidad aérea básica.\nUsa el pad tocándolo dos veces mientras estás en él. block.trident-ship-pad.description = Deja tu nave actual y transfórmate en una unidad aérea bombardera pesada.\nUsa el pad tocándolo dos veces mientras estás en él. block.javelin-ship-pad.description = Deja tu nave actual y transfórmate en una unidad aérea fuerte y rápida interceptora con arma eléctrica.\nUsa el pad tocándolo dos veces mientras estás en él. block.glaive-ship-pad.description = Deja tu nave actual y transfórmate en una unidad aérea grande y bien armada nave pistolera.\nUsa el pad tocándolo dos veces mientras estás en él. @@ -754,7 +809,6 @@ block.titan-factory.description = Produce unidades terrestres avanzadas. block.fortress-factory.description = Produce unidades terrestres de artillería pesada. block.revenant-factory.description = Produce unidades terrestres láser pesadas. block.repair-point.description = Repara la unidad dañada más cercana a su alrededor. -block.command-center.description = Permite cambiar el comportamiento de la IA aliada. Actualmente, atacar, retirarse y patrullar son los comandos soportados. block.conduit.description = Bloque de transporte de líquidos básico. Funciona como un transportador, pero con líquidos. Usado con bombas, extractores u otros conductos. block.pulse-conduit.description = Bloque de transporte de líquidos avanzado. Transporta líquidos más rápidamente y almacena más que los conductos estándar. block.phase-conduit.description = Bloque de transporte de líquidos avanzado. Usa energía para transportar líquidos a otro conducto de fase conectado por varias casillas. @@ -768,13 +822,11 @@ block.thermal-pump.description = La mejor bomba. Tres veces más rápido que la block.router.description = Acepta objetos de una dirección y deja objetos equitativamente en hasta 3 direcciones diferentes. Útil para dividir los materiales de una fuente de recursos a múltiples objetivos. block.distributor.description = Un enrutador avanzado que distribuye objetos equitativamente en hasta otras 7 direcciones. block.bridge-conveyor.description = Bloque avanado de transporte. Puede transportar objetos por encima hasta 3 casillas de cualquier terreno o construcción. -block.alpha-mech-pad.description = Cuando se le da suficiente energía, reconstruye tu nave en el mecanoide[accent] Alpha[]. block.item-source.description = Da objetos infinitos. Solo en sandbox. block.liquid-source.description = Da líquido infinito. Solo en sandbox. block.item-void.description = Destruye cuanquier objeto que va a él sin necesitar energía. Solo en sandbox. block.power-source.description = Da energía infinita. Solo en sandbox. block.power-void.description = Elimina toda la energía que se le da. Solo en sandbox. liquid.water.description = Usado comúnmente para enfriar máquinas y para procesar residuos. -liquid.lava.description = Puede usarse para ser transformado en[LIGHT_GRAY] stone[], para generar energía o para munición de ciertas torres. liquid.oil.description = Puede ser quemado, explotado o como un enfriador. liquid.cryofluid.description = El líquido más eficiente pra enfriar las cosas. diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index e92454f302..c836a7610b 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -1,5 +1,6 @@ credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet!) credits = Crédits +contributors = Translators and Contributors discord = Rejoignez le discord de Mindustry link.discord.description = Le discord officiel de mindustry link.github.description = Code source du jeu @@ -9,15 +10,19 @@ link.itch.io.description = Page itch.io avec le lien du téléchargement pour PC link.google-play.description = Listing par le Google Play Store link.wiki.description = Wiki officiel de mindustry . linkfail = Erreur lors de l'ouverture du lien !\nL'URL a été copié avec succès. +screenshot = Screenshot saved to {0} gameover = Partie terminée. gameover.pvp = L'équipe [accent] {0}[] a gagnée ! -sector.gameover = Ce secteur a été perdu. Réessayer? -sector.retry = Réessayer highscore = [YELLOW]Nouveau meilleur score! -wave.lasted = Vous avez survécu jusqu'à la vague [accent]{0}[]. -level.highscore = Meilleur score: [accent]{0} -level.delete.title = Confirmer +stat.wave = Waves Defeated:[accent] {0} +stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} +stat.built = Buildings Built:[accent] {0} +stat.destroyed = Buildings Destroyed:[accent] {0} +stat.deconstructed = Buildings Deconstructed:[accent] {0} +stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = Êtes-vous sûr de supprimer cette carte"[accent]{0}[]"? +level.highscore = Meilleur score: [accent]{0} level.select = Sélection de niveau level.mode = Mode de jeu : construction.desktop = Pour désélectionner un bloc ou arrêter de construire, appuyer sur [accent]espace[]. @@ -27,60 +32,36 @@ deconstruction.title = Guide de destruction de blocs deconstruction = Vous venez de sélectionner le mode [accent]destruction de blocs[].\n\nPour commencez à détruire des blocs, appuyez simplement sur un bloc proche de votre vaisseau.\nUne fois que vous avez sélectionné quelques blocs, Appuyez sur le bouton valider pour confirmer, et votre vaisseau commencera à détruire.\n\n- [accent]Enlevez des blocs[] de votre sélection en appuyant dessus.\n- [accent]Déplacez la sélection[] en restant appuyé puis en déplaçant n'importe quel bloc de la sélection.\n- [accent]Placez les blocs en ligne[] En restant appuyé sur un espace vide, puis en étirant dans une direction.\n- [accent]Annulez la construction ou la sélection[] en appuyant sur le X en bas à droite. showagain = Ne pas montrer la prochaine fois coreattack = [scarlet] -unlocks = Débloqué +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = Sauvegarder la partie loadgame = Charger la partie joingame = Rejoindre une partie addplayers = Ajouter/Enlever des joueurs customgame = Partie personnalisée -sectors = Secteurs -sector = Secteur: [LIGHT_GRAY]{0} -sector.time = Temps: [LIGHT_GRAY]{0} -sector.deploy = Se déployer -sector.abandon = Abandonner -sector.abandon.confirm = Êtes-vous sûr d'abandonner ce secteur ?\nCe choix ne peut être annulé! -sector.resume = Reprendre -sector.locked = [scarlet][[Incomplet] -sector.unexplored = [accent][[Inexploré] -missions = Missions:[LIGHT_GRAY] {0} -mission = Mission:[LIGHT_GRAY] {0} -mission.main = Main Mission:[LIGHT_GRAY] {0} -mission.info = Infos sur la Mission -mission.complete = Mission terminée! -mission.complete.body = Le secteur {0},{1} a été conquis. -mission.wave = Survivez à[accent] {0}/{1} []vague\nLa vague commence dans {2} -mission.wave.enemies = Survivez à[accent] {0}/{1} []vagues\n{2} ennemis -mission.wave.enemy = Survivez à[accent] {0}/{1} []vagues\n{2} ennemi -mission.wave.menu = Survivez à[accent] {0} []vagues -mission.battle = Détruisez la base ennemie -mission.resource.menu = Obtenez {0} x{1} -mission.resource = Obtenez {0}:\n[accent]{1}/{2}[] -mission.block = Créez {0} -mission.unit = Créez {0} unités -mission.command = Envoyer une commande à {0} unités -mission.linknode = Reliez un transmetteur -mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -mission.mech = Équiper ce mécha[accent] {0}[] -mission.create = Créez[accent] {0}[] +newgame = New Game none = close = Fermer quit = Quitter maps = Cartes continue = Continuer -nextmission = Prochaine mission maps.none = [LIGHT_GRAY]Aucune carte trouvée! about.button = À propos name = Nom: +noname = Pick a[accent] player name[] first. filename = Nom du fichier: unlocked = Nouveau bloc débloqué! -unlocked.plural = Nouveaux blocs débloqués! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. players = {0} joueurs en ligne players.single = {0} joueur en ligne server.closing = [accent]Fermeture du serveur... server.kicked.kick = Vous avez été expulsé du serveur! server.kicked.serverClose = Serveur fermé. -server.kicked.sectorComplete = Secteur terminé. -server.kicked.sectorComplete.text = Votre mission est complète .\nLe serveur va maintenant aller au prochain secteur . server.kicked.clientOutdated = Client dépassé! Mettez à jour votre jeu! server.kicked.serverOutdated = Serveur dépassé! Demandez à l'hôte de le mettre à jour! server.kicked.banned = Vous avez été banni sur ce serveur. @@ -89,6 +70,7 @@ server.kicked.nameInUse = Il y a déjà quelqu'un avec ce nom\nsur ce serveur. server.kicked.nameEmpty = Votre nom doit contenir au moins une lettre ou un chiffre. server.kicked.idInUse = Vous êtes déjà sur ce serveur ! Se connecter avec deux comptes n'est pas permis ! server.kicked.customClient = Ce serveur ne supporte pas les versions personnalisées (Custom builds). Téléchargez une version officielle. +server.kicked.gameover = Game over! host.info = Le bouton [accent]Héberger[] héberge un serveur sur le port [scarlet]6567[]. \nN'importe qui sur le même [LIGHT_GRAY]wifi ou réseau local []devrait voir votre serveur sur leur liste des serveurs.\n\nSi vous voulez que les gens puissent s'y connecter de partout à l'aide de votre IP, [accent]le transfert de port (port forwarding)[] est demandé.\n\n[LIGHT_GRAY]Note: Si quelqu'un a des problèmes de connexion à votre partie LAN, vérifiez que vous avez autorisé l'accès à Mindustry sur votre réseau local dans les paramètres de votre pare-feu. join.info = Ici vous pouvez entrez [accent]l'IP d'un serveur []pour s'y connecter, ou découvrir un serveur en [accent]réseau local[].\nLe multijoueur en LAN ainsi qu'en WAN est supporté.\n\n[LIGHT_GRAY]Note: Il n'y a pas de liste de serveurs globaux automatiques; Si vous voulez vous connectez à quelqu'un par IP, il faudra d'abord demander à l'hébergeur leur IP. hostserver = Héberger une partie @@ -159,7 +141,6 @@ save.rename.text = Nouveau nom: selectslot = Sélectionner une sauvegarde. slot = [accent]Emplacement {0} save.corrupted = [accent]Fichier de sauvegarde corrompu ou invalide!\nSi vous venez de mettre à jour votre jeu, c'est probablement dû à un changement du format de sauvegarde et [scarlet]non[] un bug. -sector.corrupted = [accent]Une sauvegarde pour ce secteur a été trouvé, mais son chargement a raté.\nUne nouvelle sauvegarde a été créé. empty = on = On off = Off @@ -169,6 +150,7 @@ save.wave = Vague {0} save.difficulty = Difficulté: {0} save.date = Dernière sauvegarde: {0} save.playtime = Temps de jeu: {0} +warning = Warning. confirm = Confirmer delete = Supprimer ok = OK @@ -204,7 +186,6 @@ map.nospawn = Cette carte n'a pas de base pour que le joueur y apparaisse! Ajout map.nospawn.pvp = Cette carte n'a pas de base ennemies pour qu'un joueur ennemi y apparaisse! Ajouter au moins une [SCARLET]Base rouge[] sur cette carte dans l'éditeur. map.invalid = Erreur lors du chargement de la carte: carte corrompue ou invalide. editor.brush = Pinceau -editor.slope = \\ editor.openin = Ouvrir dans l'éditeur editor.oregen = Génération de minerais editor.oregen.info = Génération de minerais: @@ -259,6 +240,26 @@ tutorial = Tutoriel editor = Éditeur mapeditor = Éditeur de carte donate = Faire un\ndon +abandon = Abandon +abandon.text = This zone and all its resources will be lost to the enemy. +locked = Locked +complete = [LIGHT_GRAY]Complete: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Best: {0} +launch = Launch +launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson]Échec de la connexion au serveur : [accent]{0} error.unreachable = Server injoignable. error.invalidaddress = Adresse invalide. @@ -266,7 +267,20 @@ error.timedout = Délai de connexion dépassé!\nAssurez-vous que l'hôte a auto error.mismatch = Erreur de paquet:\nPossible différence de verison entre le client et le serveur .\nVérifiez que vous et l'hôte avez la plus récente version de Mindustry ! error.alreadyconnected = Déjà connecté. error.mapnotfound = Fichier de la carte introuvable! +error.io = Network I/O error. error.any = Erreur réseau inconnue. +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = Langage settings.reset = Valeur par défaut. settings.rebind = Réatttribuer @@ -277,7 +291,6 @@ settings.graphics = Graphiques settings.cleardata = Effacer les données du jeu... settings.clear.confirm = Êtes-vous sûr d'effacer ces données ?\nCe qui est fait ne peut être défait ! settings.clearall.confirm = [scarlet]ATTENTION![]\nCet action effacera toutes les données , incluant les sauvegarges, les cartes, les déblocages et la configuration des touches.\nUne fois que vous aurez pressé 'ok' le jeu effacera toutes les données et se fermera. -settings.clearsectors = Effacer les données des secteurs settings.clearunlocks = Effacer les déblocages settings.clearall = Tout effacer paused = En pause @@ -286,12 +299,15 @@ no = Non info.title = Info error.title = [crimson]Une erreur s'est produite error.crashtitle = Une erreur s'est produite +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Info sur le bloc +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = capacité d'énergie blocks.powershot = Énergie/Tir blocks.targetsair = Cible les unités aériennes -blocks.itemspeed = Objets déplacés +blocks.itemsmoved = Move Speed blocks.shootrange = Portée blocks.size = Taille blocks.liquidcapacity = Capacité en liquide @@ -312,16 +328,23 @@ blocks.inputitems = Objets utilisés blocks.outputitem = Objet produit blocks.drilltier = Forable blocks.drillspeed = Vitesse de forage de base +blocks.maxunits = Max Active Units blocks.liquidoutput = Liquide en sortie blocks.liquidoutputspeed = Vitesse de production de liquide blocks.liquiduse = Quantité de liquide utilisée blocks.coolant = Liquide de refroidissement +blocks.liquid = Liquid blocks.coolantuse = Quantité de liquide de refroidissement utilisée blocks.inputliquidfuel = Carburant liquide blocks.liquidfueluse = Quantité de carburant liquide utilisé blocks.boostitem = Boost Item blocks.boostliquid = Boost Liquid blocks.health = Santé +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Précision blocks.shots = Tir blocks.reload = Tirs/Seconde @@ -329,11 +352,11 @@ blocks.inputfuel = Carburant blocks.fuelburntime = Durée du carburant blocks.inputcapacity = Capacité d'entrée blocks.outputcapacity = Capacité de production +blocks.ammo = Ammo unit.blocks = blocs unit.powersecond = Énergie/seconde unit.liquidsecond = Liquides/seconde unit.itemssecond = Objets/seconde -unit.pixelssecond = Pixels/seconde unit.liquidunits = Unité de liquide unit.powerunits = Unité d'énergie unit.degrees = degrés @@ -346,6 +369,7 @@ category.items = Objets category.crafting = Fabrication category.shooting = Défense category.optional = Optional Enhancements +setting.indicators.name = Ally Indicators setting.autotarget.name = Visée automatique setting.fpscap.name = Max FPS setting.fpscap.none = None @@ -378,12 +402,16 @@ category.multiplayer.name = Multijoueur command.attack = Attaque command.retreat = Retraite command.patrol = Patrouille +keybind.gridMode.name = Block Select +keybind.gridModeShift.name = Category Select keybind.press = Appuyer sur une touche... keybind.press.axis = Appuyer sur un axe ou une touche... +keybind.screenshot.name = Map Screenshot keybind.move_x.name = mouvement x keybind.move_y.name = mouvement y keybind.select.name = sélectionner -keybind.break.name = Pause +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = Déselectionner keybind.shoot.name = tirer keybind.zoom_hold.name = tenir le zoom @@ -402,29 +430,28 @@ keybind.chat_scroll.name = Chat scroll keybind.drop_unit.name = drop unit keybind.zoom_minimap.name = Zoom minimap mode.help.title = Description des modes de jeu -mode.waves.name = Vagues -mode.waves.description = Le mode de jeu normal. Ressources limitées et vagues d'ennemis. +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. mode.sandbox.name = bac à sable mode.sandbox.description = Ressources infinies et pas de timer pour les vagues. mode.freebuild.name = construction libre mode.freebuild.description = Ressources limitées et pas de timer pour les vagues. mode.pvp.name = JcJ mode.pvp.description = Battez-vous contre d'autres joueurs en local. +mode.attack.name = Attack +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = Objets content.liquid.name = Liquides content.unit.name = Unités -content.recipe.name = Blocs +content.block.name = Blocks content.mech.name = Méchas -item.stone.name = Pierre -item.stone.description = Un matériau brut commun. Peut être séparé et raffiné en d'autres matériaux, ou fondu en lave. item.copper.name = Cuivre item.copper.description = Un matériau de construction utile. Utilisé intensivement dans tout les blocs. item.lead.name = Plomb item.lead.description = Un matériau de départ. Utilisé intensivement en électronique et pour le transport de blocs. item.coal.name = Charbon item.coal.description = Un carburant commun et facile à obtenir. -item.dense-alloy.name = Alliage lourd -item.dense-alloy.description = Un alliage résistant fait de plomb et de cuivre. Utilisé dans les blocs de transports avancés et dans les foreuses de haut niveau. +item.graphite.name = Graphite item.titanium.name = Titane item.titanium.description = Un métal rare super-léger largement utilisé dans le transport de liquides et d'objets ainsi que dans les foreuses de haut-niveau et l'aviation. item.thorium.name = Thorium @@ -437,16 +464,20 @@ item.phase-fabric.name = Tissu phasé item.phase-fabric.description = Une substance au poids quasiment inexistant utilisé pour l'électronique avancé et la technologie auto-réparatrice. item.surge-alloy.name = Alliage superchargé item.surge-alloy.description = Un alliage avancé avec des propriétés électriques avancées. -item.biomatter.name = Biomasse -item.biomatter.description = Un mélange de matières organiques; utilisé pour la transformation en huile ou en tant que carburant de base. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = Sable item.sand.description = Un matériau commun utilisé largement dans la fonte, à la fois dans l'alliage et comme un flux. item.blast-compound.name = Mélange explosif item.blast-compound.description = Un composé volatile utilisé dans les bombes et les explosifs. Bien qu'il puisse être utilisé comme carburant, ce n'est pas conseillé. item.pyratite.name = Pyratite item.pyratite.description = Une substance extrêmement inflammable utilisée dans les armes incendiaires. +item.metaglass.name = Metaglass +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = Eau -liquid.lava.name = Lave +liquid.slag.name = Slag liquid.oil.name = Pétrole liquid.cryofluid.name = Liquide cryogénique mech.alpha-mech.name = Alpha @@ -481,11 +512,10 @@ mech.glaive-ship.weapon = Fusil automatique incendiaire item.explosiveness = [LIGHT_GRAY]Explosivité: {0} item.flammability = [LIGHT_GRAY]Inflammabilité: {0} item.radioactivity = [LIGHT_GRAY]Radioactivité: {0} -item.fluxiness = [LIGHT_GRAY]Flux de Puissance: {0} unit.health = [LIGHT_GRAY]Santé: {0} unit.speed = [LIGHT_GRAY]Rapidité: {0} mech.weapon = [LIGHT_GRAY]Arme: {0} -mech.armor = [LIGHT_GRAY]Armure: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]Capacité de stockage: {0} mech.minespeed = [LIGHT_GRAY]Vitesse de minage: {0} mech.minepower = [LIGHT_GRAY]Puissance du minage: {0} @@ -493,29 +523,60 @@ mech.ability = [LIGHT_GRAY]Compétence: {0} liquid.heatcapacity = [LIGHT_GRAY]Capacité Thermique: {0} liquid.viscosity = [LIGHT_GRAY]Viscosité: {0} liquid.temperature = [LIGHT_GRAY]Température: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](En Construction) block.spawn.name = Générateur d'ennemis -block.core.name = Base -block.metalfloor.name = Sol en métal +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = Eau profonde block.water.name = Eau -block.lava.name = Lave block.tar.name = Pétrole -block.blackstone.name = Roche sombre block.stone.name = Roche -block.dirt.name = Terre block.sand.name = Sable block.ice.name = glace block.snow.name = Neige -block.grass.name = Herbe -block.shrub.name = Buisson -block.rock.name = Pierre -block.blackrock.name = Pierre sombre -block.icerock.name = Pierre gelée +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = Mur de cuivre block.copper-wall-large.name = Grand mur de cuivre -block.dense-alloy-wall.name = Mur en alliage lourd -block.dense-alloy-wall-large.name = Grand mur en alliage lourd +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = Mur phasé block.phase-wall-large.name = Grand mur phasé block.thorium-wall.name = Mur en Thorium @@ -523,7 +584,6 @@ block.thorium-wall-large.name = Mur en Thorium large block.door.name = Porte block.door-large.name = Grande porte block.duo.name = Duo -block.scorch.name = Scorch block.hail.name = Hail block.lancer.name = Lancier block.conveyor.name = Convoyeur @@ -535,30 +595,29 @@ block.sorter.name = Sorteur block.sorter.description = Trie les articles. Si un article rcorrespond à la sélection, il peut passer. Autrement, l'article est distribué vers la gauche ou la droite. block.overflow-gate.name = Barrière de Débordement block.overflow-gate.description = C'est la combinaison entre un Routeur et un Diviseur qui peut seulement distribuer à gauche et à droite si le chemin de devant est bloqué. -block.smelter.name = Fonderie d'alliage lourd -block.arc-smelter.name = Fonderie d'alliage lourd électrique block.silicon-smelter.name = Fonderie de Silicone block.phase-weaver.name = Tisseur à Phase block.pulverizer.name = Pulvérisateur block.cryofluidmixer.name = Refroidisseur block.melter.name = Four à Fusion block.incinerator.name = Incinérateur -block.biomattercompressor.name = Compresseur de Biomasse +block.spore-press.name = Spore Press block.separator.name = Séparateur -block.centrifuge.name = Centrifugeuse block.power-node.name = Transmetteur énergétique block.power-node-large.name = Gros transmetteur énergétique +block.surge-tower.name = Surge Tower block.battery.name = Batterie block.battery-large.name = Batterie large block.combustion-generator.name = Générateur à combustion block.turbine-generator.name = Générateur à Turbine +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = Foreuse mécanique block.pneumatic-drill.name = Foreuse à vérin block.laser-drill.name = Foreuse Laser block.water-extractor.name = Extracteur d'eau block.cultivator.name = Cultivateur -block.alpha-mech-pad.name = Reconstructeur de mécha "Alpha" -block.dart-ship-pad.name = Reconstructeur de vaisseau "Dard" +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = Reconstructeur de mécha "Delta" block.javelin-ship-pad.name = Reconstructeur de vaisseau "Javelin" block.trident-ship-pad.name = Reconstructeur de vaisseau "Trident" @@ -583,7 +642,6 @@ block.bridge-conveyor.name = Pont block.plastanium-compressor.name = Compresseur de Plastanium block.pyratite-mixer.name = Mixeur à Pyratite block.blast-mixer.name = Mixeur à Explosion -block.solidifer.name = Solidifieur block.solar-panel.name = Panneau Solaire block.solar-panel-large.name = Grand Panneau Solaire block.oil-extractor.name = Extracteur d'huile @@ -604,7 +662,6 @@ block.liquid-junction.name = Jonction à Liquide block.bridge-conduit.name = Pont à liquide block.rotary-pump.name = Pompe Rotative block.thorium-reactor.name = Réacteur à Thorium -block.command-center.name = Centre de commandement block.mass-driver.name = Transporteur de masse block.blast-drill.name = Foreuse à explosion block.thermal-pump.name = Pompe thermique @@ -623,20 +680,21 @@ block.rtg-generator.name = G.T.R. block.spectre.name = Spectre block.meltdown.name = Meltdown block.container.name = Conteneur -block.core.description = Le batiment le plus important du jeu. +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = Bleu team.red.name = Rouge team.orange.name = Orange team.none.name = Gris team.green.name = Vert team.purple.name = Violet -unit.alpha-drone.name = Alpha Drone unit.spirit.name = Drone sppirituel unit.spirit.description = L'unité de soutien de départ. Apparaît dans la base par défaut. Mine automatiquement les minerais, récupère les objets au sol et répare les blocs. unit.phantom.name = Drone Fantôme unit.phantom.description = Une unité de soutien avancée. Mine automatiquement les minerais, récupère les objets au sol et répare les blocs. Bien plus efficace qu'un drone spirituel. unit.dagger.name = Poignard unit.dagger.description = Une unité terrestre basiquee. Utile en armée. +unit.crawler.name = Crawler unit.titan.name = Titan unit.titan.description = Une unité terrestre cuirassée avancée. Attaque les unités terrestres comme aériennes. unit.ghoul.name = Bombardier goule @@ -646,7 +704,11 @@ unit.wraith.description = Une unité volante rapide harcelant les ennemis .Utili unit.fortress.name = Forteresse unit.fortress.description = Une unité terrestre d'artillerie lourde . unit.revenant.name = Revenant -unit.revenant.description = Une plateforme laser lourde. +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = Votre mission, si vous l'acceptez est de détruire [LIGHT_GRAY]l'ennemi[].\n\nCommencez par [accent] miner du cuivre[]. Appuyer sur un filon de cuivre proche de votre base pour faire ceci. tutorial.drill = Le minage manuel est inefficace.\n[accent]Des foreuses[]peuvent miner automatiquement.\nPlacez-en une sur un filon de cuivre. tutorial.conveyor = [accent]Les Tapis roulants[] sont utilisés pour transporter des objets jusqu'à la base.\nFaites une ligne de tapis roulants de la foreuse à la base . @@ -670,8 +732,6 @@ tutorial.dagger = Reliez des transmetteurs énergétiques à l'usine.\nUne fois tutorial.battle = [LIGHT_GRAY]L'Ennemi[] a révélé sa base .\nDétruisez la avec votre unité et des méchas "Poignard". block.copper-wall.description = Un bloc défensif à faible coût.\nUtile pour protéger la base et les tourelles dans les premières 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 dans les premières lors des premières vagues.\nFait du 2 sur 2. -block.dense-alloy-wall.description = Un bloc défensif standard .\nProcure une bonne protection contre les ennemis. -block.dense-alloy-wall-large.description = Un bloc défensif standard .\nProcure une bonne protection contre les ennemis.\nFait du 2 sur 2. block.thorium-wall.description = Un bloc défensif puissant.\nProcure une très bonne protection contre les ennemis. block.thorium-wall-large.description = Un bloc défensif puissant.\nProcure une très bonne protection contre les ennemis.\nFait du 2 sur 2. block.phase-wall.description = Moins puissant qu'un mur en Thorium mais déviera les balles sauf si elles sont trop puissantes. @@ -701,8 +761,6 @@ block.titanium-conveyor.description = Convoyeur avancé . Déplace les objets pl block.phase-conveyor.description = convoyeur très avancé . Utilise de l'énergie pour téléporter des objets à un convoyeur phasé connecté jusqu'à une longue distance . block.junction.description = Agit comme un pont pour deux ligne de convoyeurs se croisant. Utile lorsque deux différents convoyeurs déplacent différents matériaux à différents endroits. block.mass-driver.description = Batiment de transport d'objet [accent]ultime[]. Collecte un grand nombre d'objets puis les tire à un autre transporteur de masse sur une très longue distance. -block.smelter.description = Brûle du charbon pour fondre du cuivre et du plomb en un alliage lourd. -block.arc-smelter.description = Fait fondre du cuivre et du plomb en un alliage lourd en utilisant une source d'énergie extérieure . block.silicon-smelter.description = Utilise du sable, du charbon et de l'énergie afin de produire du silicone. block.plastanium-compressor.description = Produit du plastanium à partir de pétrole et de titane. block.phase-weaver.description = Produit du tissu phasé à partir de thorium et de grandes quantités de sable. @@ -711,12 +769,10 @@ block.pulverizer.description = Écrase la pierre pour en faire du sable. Utile q block.pyratite-mixer.description = Mélange charbon, plomb et sable en l'hautement inflammable pyratite. block.blast-mixer.description = Utilise du pétrole pour transformer la pyratite en un mélange explosif moins inflammable mais plus explosif que la pyratite. block.cryofluidmixer.description = Combine de l'eau et du titane en un liquide cryogénique bien plus efficace pour refroidir. -block.solidifer.description = Refroidit de la lave en pierre très rapidement. block.melter.description = chauffe de la pierre à de très hautes températures pour obtenir de la lave. block.incinerator.description = Permet de se débarasser de n'importe quel objet ou liquide en exces . -block.biomattercompressor.description = Compresse de la biomasse pour en récupérer le pétrole. +block.spore-press.description = Compresses spore pods into oil. block.separator.description = Expose la pierre à de l'eau sous pression afin d'obtenir différents minéraux contenus dansla pierre. -block.centrifuge.description = Plus efficace qu'un séparateur mais aussi plus cher à construire et demande plus d'énergie. block.power-node.description = Transmet l'énergie aux transmetteurs énergétiques connectés . Jusqu'à quatre sources d'énergie, consommateurs ou transmetteurs peuvent être connectés. Le transmetteur recevra de l'énergie ou le transmettra à n'importe quel batiment adjacent. block.power-node-large.description = A un plus grand rayon que le transmetteur énergétique standard et jusqu'à six sources d'énergie, consommateurs ou transmetteurs peuvent être connectés. block.battery.description = Stocke l'énergie quand elle est en abondance et le distribue si il y a trop peu d'énergie tant qu'il lui reste de l'énergie. @@ -738,7 +794,6 @@ block.blast-drill.description = La Foreuse ultime . Demande une grande quantité block.water-extractor.description = Extrait l'eau des nappes phréatiques. Utile quand il n'y a pas d'eau à proximité. block.cultivator.description = Cultive le sol avec de l'eau afin d'obtenir de la biomasse. block.oil-extractor.description = Utilise une grande quantité d'énergie afin d'extraire du pétrole du sable . Utile quand il n'y a pas de lacs de pétrole à proximité. -block.dart-ship-pad.description = Quitte ton mécha ou ton vaisseau actuel pour un avion de combat basique .\nUtilisez le reconstructeur en double cliquant dessus lorsque vous êtes dessus. block.trident-ship-pad.description = Quitte ton mécha ou ton vaisseau actuel pour un bombardier lourd raisonnablement cuirassé .\nUtilisez le reconstructeur en double cliquant dessus lorsque vous êtes dessus. block.javelin-ship-pad.description = Quitte ton mécha ou ton vaisseau actuel pour un intercepteur rapide et puissant avec des armes électriques.\nUtilisez le reconstructeur en double cliquant dessus lorsque vous êtes dessus. block.glaive-ship-pad.description = Quitte ton mécha ou ton vaisseau actuel pour un large vaisseau cuirassé .\nUtilisez le reconstructeur en double cliquant dessus lorsque vous êtes dessus. @@ -754,7 +809,6 @@ block.titan-factory.description = Produit des unités terrestres avancées et cu block.fortress-factory.description = Produit des unités terrestres d'artillerie lourde . block.revenant-factory.description = Produit des unités terrestres lourdes avec des lasers. block.repair-point.description = Soigne en continu l'unité blessée la plus proche tant qu'elle est à sa portée. -block.command-center.description = Permet de changer le comportement des IA alliées. Pour le moment, l'attaque, la retraite et les patrouilles sont supportées. block.conduit.description = tuyau basique permettant le transport de liquide . Marche comme un convoyeur mais avec les liquides. Utile si utilisé avec des extracteurs, des pompes ou d'autres conduits. block.pulse-conduit.description = tuyau avancé permettant le transport de liquide . Transporte les liquides plus rapidement et en stocke plus que les tuyaux standards. block.phase-conduit.description = tuyau très avancé permettant le transport de liquide. Utilise de l'énergie pour téléporter les liquides à un autre tuyau phasé sur une longue distance. @@ -768,13 +822,11 @@ block.thermal-pump.description = La pompe ultime . Trois fois plus rapide qu'une block.router.description = Accepte les objets depuis une ou plus directions et le renvoie dans n'importe quelle direction. Utile pour séparer une chaîne de convoyeurs en plusieurs.[accent]Le seul et l'Unique[] block.distributor.description = Un routeur avancé qui sépare les objets jusqu'à 7 autres directions équitablement. block.bridge-conveyor.description = bloc de transport avancé permettant de traverser jusqu'à 3 blocs de n'importe quel terrain ou batiment. -block.alpha-mech-pad.description = Avec assez d'énergie, reconstruit votre vaisseau en un mécha [accent] Alpha[]. block.item-source.description = Produit des objets à l'infini. Bac à sable uniquement . block.liquid-source.description = Source de liquide infinie . Bac à sable uniquement. block.item-void.description = Désintègre n'importe quel objet qui va à l'intérieur sans utiliser d'énergie. Bac à sable uniquement. block.power-source.description = Produit de l'énergie à l'infini. Bac à sable uniquement. block.power-void.description = Supprime toute l'énergie allant à l'intérieur.Bac à sable uniquement liquid.water.description = Couramment utilisé pour le refroidissement et le traitement des déchets. -liquid.lava.description = Peut être transformé en [LIGHT_GRAY]pierre[], utilisé pour produire de l'énergie ou utilisé comme munition par certaines tourelles. liquid.oil.description = Peut être brûlé, utilisé comme explosif ou comme liquide de refroidissement. liquid.cryofluid.description = Le liquide de refroidissement le plus efficace. diff --git a/core/assets/bundles/bundle_fr_BE.properties b/core/assets/bundles/bundle_fr_BE.properties index 79788734dc..ee3b8fe759 100644 --- a/core/assets/bundles/bundle_fr_BE.properties +++ b/core/assets/bundles/bundle_fr_BE.properties @@ -13,13 +13,16 @@ linkfail = L'ouverture du lien a échoué!\nL'URL a été copiée dans votre pre screenshot = Capture d'écran enregistrée sur {0} gameover = Le base a été détruit. gameover.pvp = L'équipe[accent] {0}[] a gagnée ! -sector.gameover = Ce secteur a été perdu. Réessayer ? -sector.retry = Réessayer highscore = [accent]Nouveau meilleur score ! -wave.lasted = Tu as survécu jusqu'à la vagues [accent]{0}[]. -level.highscore = Meilleur score: [accent]{0} -level.delete.title = Confirmer +stat.wave = Waves Defeated:[accent] {0} +stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} +stat.built = Buildings Built:[accent] {0} +stat.destroyed = Buildings Destroyed:[accent] {0} +stat.deconstructed = Buildings Deconstructed:[accent] {0} +stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = Êtes-vous sûr de vouloir supprimer cette carte ?"[accent]{0}[]"? +level.highscore = Meilleur score: [accent]{0} level.select = Sélection de niveau level.mode = Mode de jeu: construction.desktop = Désélectionner un bloc ou arrêter la construction, [accent]utiliser la touche espace[]. @@ -29,61 +32,36 @@ deconstruction.title = Guide de déconstruction de blocs deconstruction = Vous venez de sélectionner le [accent]mode de destruction de blocs[].\n\nPour détruire, tapez simplement un bloc près de votre vaisseau (vous).\nUne fois que vous avez sélectionné des blocs, appuyez sur le "check" pour confirmer, et votre vaisseau commencera à les détruire.\n\n- [accent]Retirez les blocs[] de votre sélection en les touchant.\n- [accent]Détruisez les blocs dans une aire[] en sélectionnant et en maintenant un emplacement vide, ensuite glissez votre doigt dans une direction.\n- [accent]Annulez une destruction ou une sélection[] en appuyant sur "X" dans le coin en bas à gauche. showagain = Ne plus montrer la prochaine fois. coreattack = -unlocks = Débloqués +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = Sauvegarder la partie loadgame = Charger la partie joingame = Rejoindre la partie addplayers = Ajouter/Enlever des joueurs customgame = Partie personnalisée -sectors = Secteurs -sector = Secteur sélectionné: [LIGHT_GRAY]{0} -sector.time = Temps: [LIGHT_GRAY]{0} -sector.deploy = Déployer -sector.abandon = Abandonner -sector.abandon.confirm = Êtes-vous sûr de vouloir abandonner tout progrès dans ce secteur?\nCette action ne peut être annulée! -sector.resume = Reprendre -sector.locked = [scarlet][[Incomplet] -sector.unexplored = [accent][[Inexploré] -missions = Missions:[LIGHT_GRAY] {0} -mission = Mission:[LIGHT_GRAY] {0} -mission.main = Mission principale:[LIGHT_GRAY] {0} -mission.info = Mission info -mission.complete = Mission terminée ! -mission.complete.body = Le secteur {0},{1} a été conquis. -mission.wave = Survivez[accent] {0}/{1} []vagues\nProchaine vague dans {2} -mission.wave.enemies = Survivez[accent] {0}/{1} []vagues\n{2} Ennemis -mission.wave.enemy = Survivez[accent] {0}/{1} []vagues\n{2} Ennemi -mission.wave.menu = Survivez[accent] {0} []vagues -mission.battle = Détruire la base ennemie. -mission.resource.menu = Obtenez {0} x{1} -mission.resource = Obtenez {0}:\n[accent]{1}/{2}[] -mission.block = Créez {0} -mission.unit = Créez {0} unité -mission.command = Envoyer une commande à {0} unités -mission.linknode = Reliez le transmetteur énergétique -mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -mission.mech = Changer de mécha[accent] {0}[] -mission.create = Créez[accent] {0}[] +newgame = New Game none = close = Fermer quit = Quitter maps = Cartes continue = Continue -nextmission = Prochaine Mission maps.none = [LIGHT_GRAY]Aucune carte trouvée! about.button = À propos name = Nom: noname = Choisissez d'abord [accent]un pseudo[]. filename = Nom du fichier: unlocked = Nouveau bloc debloqué! -unlocked.plural = Nouveaux blocs débloqués! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. players = {0} joueurs en ligne players.single = {0} joueur en ligne server.closing = [accent]Fermeture du serveur ... server.kicked.kick = Vous avez été expulsé du serveur ! server.kicked.serverClose = Serveur fermé. -server.kicked.sectorComplete = Secteur terminée. -server.kicked.sectorComplete.text = Votre mission est complète.\nLe serveur va maintenant passer au prochain secteur. server.kicked.clientOutdated = Client dépassé! Mettez à jour votre jeu ! server.kicked.serverOutdated = Serveur dépassé! Demandez à l'hôte de le mettre à jour ! server.kicked.banned = Vous êtes banni de ce serveur. @@ -163,7 +141,6 @@ save.rename.text = Nouveau nom: selectslot = Sélectionnez une sauvegarde. slot = [accent]Emplacement {0} save.corrupted = [accent]Fichier de sauvegarde corrompu ou invalide!\nSi vous venez de mettre à jour votre jeu, c'est probablement dû à un changement du format de sauvegarde et [scarlet]non[] un bug. -sector.corrupted = [accent]Une sauvegarde pour ce secteur a été trouvé, mais son chargement a raté.\nUne nouvelle sauvegarde a été créé. empty = on = Allumer off = Éteint @@ -173,6 +150,7 @@ save.wave = Vague {0} save.difficulty = Difficulté: {0} save.date = Dernière sauvegarde: {0} save.playtime = Temps de jeu: {0} +warning = Warning. confirm = Confirmer delete = Supprimer ok = OK @@ -208,7 +186,6 @@ map.nospawn = Cette carte ne possède pas de base pour que le joueur puisse appa map.nospawn.pvp = Cette carte ne contient aucune base ennemi dans lequel le joueur apparaît!\nAjoutez des bases[SCARLET] rouge[] à cette carte dans l'éditeur. map.invalid = Erreur lors du chargement de la carte: carte corrompue ou invalide. editor.brush = Pinceau -editor.slope = Pente editor.openin = Ouvrir dans l'éditeur editor.oregen = Génération des minerais editor.oregen.info = Génération de minerais: @@ -263,6 +240,26 @@ tutorial = Tutoriel editor = Éditeur mapeditor = Éditeur de carte donate = Faire un\ndon +abandon = Abandon +abandon.text = This zone and all its resources will be lost to the enemy. +locked = Locked +complete = [LIGHT_GRAY]Complete: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Best: {0} +launch = Launch +launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson]Échec de la connexion au serveur: [accent]{0} error.unreachable = Serveur inaccessible. error.invalidaddress = Adresse invalide. @@ -270,8 +267,20 @@ error.timedout = Expiration du délai !\nAssurez-vous que la redirection de port error.mismatch = Erreur de paquet:\nPossible d'incompatibilité de version client/serveur.\nAssurez-vous que l'hôte et vous disposez de la dernière version de Mindustry ! error.alreadyconnected = Déjà connecté. error.mapnotfound = Fichier de carte introuvable ! -text.error.io = Erreur réseau IO. +error.io = Network I/O error. error.any = Erreur réseau inconnue. +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = Langage settings.reset = Valeur par défaut. settings.rebind = Réatttribuer @@ -282,7 +291,6 @@ settings.graphics = Graphiques settings.cleardata = Effacer les données du jeu... settings.clear.confirm = Êtes-vous sûr d'effacer ces données ?\n[scarlet]Ceci est irréversible settings.clearall.confirm = [scarlet]ATTENTION![]\nCet action effacera toutes les données , incluant les sauvegarges, les cartes, les déblocages et la configuration des touches.\nUne fois que vous aurez pressé 'Ok' le jeu effacera toutes les données et se fermera. -settings.clearsectors = Éffacer les données des secteurs settings.clearunlocks = Éffacer les déblocages settings.clearall = Tout effacer paused = En pause @@ -291,12 +299,15 @@ no = Non info.title = Info error.title = [crimson]Une erreur s'est produite error.crashtitle = Une erreur s'est produite +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Info sur le bloc +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = Capacité d'énergie blocks.powershot = Énergie/Tir blocks.targetsair = Cible les unités aériennes -blocks.itemspeed = Objets déplacés +blocks.itemsmoved = Move Speed blocks.shootrange = Portée blocks.size = Taille blocks.liquidcapacity = Capacité en liquide @@ -317,16 +328,23 @@ blocks.inputitems = Objets utilisés blocks.outputitem = Objet produit blocks.drilltier = Forable blocks.drillspeed = Vitesse de forage de base +blocks.maxunits = Max Active Units blocks.liquidoutput = Liquide en sortie blocks.liquidoutputspeed = Vitesse de sortie du liquide blocks.liquiduse = Quantité de liquide utilisé blocks.coolant = Liquide de refroidissement +blocks.liquid = Liquid blocks.coolantuse = Quantité de liquide de refroidissement utilisé blocks.inputliquidfuel = Carburant liquide blocks.liquidfueluse = Quantité de carburant liquide utilisé blocks.boostitem = Objet boostant la production blocks.boostliquid = Liquide boostant la production blocks.health = Santé +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Précision blocks.shots = Tirs blocks.reload = Tirs/Seconde @@ -334,11 +352,11 @@ blocks.inputfuel = Carburant blocks.fuelburntime = Durée du carburant blocks.inputcapacity = Capacité d'entrée blocks.outputcapacity = Capacité de sortie +blocks.ammo = Ammo unit.blocks = Blocs unit.powersecond = Énergie/seconde unit.liquidsecond = Liquides/seconde unit.itemssecond = Objets/seconde -unit.pixelssecond = Pixels/seconde unit.liquidunits = Unité de liquide unit.powerunits = Unité d'énergie unit.degrees = degrés @@ -388,10 +406,12 @@ keybind.gridMode.name = Sélectionnez le bloc keybind.gridModeShift.name = Sélection de la catégorie keybind.press = Appuyez sur une touche ... keybind.press.axis = Appuyez sur un axe ou une touche... +keybind.screenshot.name = Map Screenshot keybind.move_x.name = Mouvement X keybind.move_y.name = Mouvement Y keybind.select.name = Sélectionner/Tirer -keybind.break.name = Pause +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = Déselectionner keybind.shoot.name = Tirer keybind.zoom_hold.name = Tenir le zoom @@ -410,8 +430,8 @@ keybind.chat_scroll.name = Faire défiler le tchat keybind.drop_unit.name = Larguer une unité keybind.zoom_minimap.name = Zoomer la minimap mode.help.title = Description des modes de jeu -mode.waves.name = Vagues -mode.waves.description = Le mode normal. Ressources limitées et vagues déclenchées automatiquement. +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. mode.sandbox.name = Bac à sable mode.sandbox.description = Ressources infinies et pas de compte à rebours pour les vagues. mode.freebuild.name = Construction libre @@ -419,22 +439,19 @@ mode.freebuild.description = Ressources limitées et pas de compte à rebours po mode.pvp.name = PvP mode.pvp.description = Lutter contre d'autres joueurs pour gagner ! mode.attack.name = Attaque -mode.attack.descrption = Pas de vagues, le but est de détruire la base ennemie. +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = Objets content.liquid.name = Liquides content.unit.name = Unités -content.recipe.name = Bloc +content.block.name = Blocks content.mech.name = Mécha -item.stone.name = Pierre -item.stone.description = Un matériau brut commun. Peut-être séparé et raffiné en d'autres matériaux, ou fondus en lave. item.copper.name = Cuivre item.copper.description = Un matériau de construction utile. Utilisé intensivement dans tout les blocs. item.lead.name = Plomb item.lead.description = Un matériau de départ. Utilisé intensivement en électronique et pour le transport de blocs. item.coal.name = Charbon item.coal.description = Un carburant commun et facile à obtenir. -item.dense-alloy.name = Alliage lourd -item.dense-alloy.description = Un alliage résistant fait de plomb et de cuivre. Utilisé dans les blocs de transports avancés et les foreuses de haut niveau. +item.graphite.name = Graphite item.titanium.name = Titane item.titanium.description = Un métal rare super-léger largement utilisé dans le transport de liquides et d'objets ainsi que dans les foreuses de haut-niveau et l'aviation item.thorium.name = Thorium @@ -447,16 +464,20 @@ item.phase-fabric.name = Phase Fabric item.phase-fabric.description = Une substance presque en apesanteur utilisée dans l'électronique de pointe et la technologie autoréparable. item.surge-alloy.name = Alliage superchargé item.surge-alloy.description = Un alliage avancé aux propriétés électriques uniques. -item.biomatter.name = Biomasse -item.biomatter.description = Un mélange de matières organiques; utilisé pour la transformation en pétrole ou en tant que carburant de base. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = Sable item.sand.description = Un matériau commun utilisé largement dans la fonte, à la fois dans l'alliage et comme un flux. item.blast-compound.name = Mélange explosif item.blast-compound.description = Un composé volatile utilisé dans les bombes et les explosifs. Bien qu'il puisse être utilisé comme carburant, ce n'est pas conseillé. item.pyratite.name = Pyratite item.pyratite.description = Une substance extrêmement inflammable utilisée dans les armes incendiaires. +item.metaglass.name = Metaglass +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = Eau -liquid.lava.name = Lave +liquid.slag.name = Slag liquid.oil.name = Pétrole liquid.cryofluid.name = Liquide Cryogénique mech.alpha-mech.name = Alpha @@ -491,11 +512,10 @@ mech.glaive-ship.weapon = Fusil automatique incendiaire item.explosiveness = [LIGHT_GRAY]Explosivité: {0} item.flammability = [LIGHT_GRAY]Inflammabilité: {0} item.radioactivity = [LIGHT_GRAY]Radioactivité: {0} -item.fluxiness = [LIGHT_GRAY]Flux de Puissance: {0} unit.health = [LIGHT_GRAY]Santé: {0} unit.speed = [LIGHT_GRAY]Vitesse: {0} mech.weapon = [LIGHT_GRAY]Arme: {0} -mech.armor = [LIGHT_GRAY]Armure: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]Capacité de stockage: {0} mech.minespeed = [LIGHT_GRAY]Vitesse de minage: {0} mech.minepower = [LIGHT_GRAY]Puissance du minage: {0} @@ -503,29 +523,60 @@ mech.ability = [LIGHT_GRAY]Compétence: {0} liquid.heatcapacity = [LIGHT_GRAY]Capacité Thermique {0} liquid.viscosity = [LIGHT_GRAY]Viscosité: {0} liquid.temperature = [LIGHT_GRAY]Température: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](En construction) block.spawn.name = Générateur d'ennemi -block.core.name = Base -block.metalfloor.name = Sol en métal +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = Eau profonde block.water.name = Eau -block.lava.name = Lave block.tar.name = Pétrole -block.blackstone.name = Roche sombre block.stone.name = Roche -block.dirt.name = Terre block.sand.name = Sable block.ice.name = Glace block.snow.name = Neige -block.grass.name = Herbe -block.shrub.name = Buisson -block.rock.name = Pierre -block.blackrock.name = Pierre sombre -block.icerock.name = Pierre gelée +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = Mur de cuivre block.copper-wall-large.name = Grand mur de cuivre -block.dense-alloy-wall.name = Mur en alliage lourd -block.dense-alloy-wall-large.name = Grand mur en alliage lourd +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = Mur phasé block.phase-wall-large.name = Grand mur phasé block.thorium-wall.name = Mur en Thorium @@ -533,7 +584,6 @@ block.thorium-wall-large.name = Mur en Thorium large block.door.name = Porte block.door-large.name = Grande porte block.duo.name = Duo -block.scorch.name = Scorch block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = Transporteur @@ -545,30 +595,29 @@ block.sorter.name = Trieur block.sorter.description = Trie les articles. Si un article correspond à la sélection, il peut passer. Autrement, l'article est distribué vers la gauche ou la droite. block.overflow-gate.name = Barrière de Débordement block.overflow-gate.description = C'est la combinaison entre un Routeur et un Diviseur qui peut seulement distribuer à gauche et à droite si le chemin de devant est bloqué. -block.smelter.name = Fonderie d'alliage lourd -block.arc-smelter.name = Fonderie d'alliage lourd électrique block.silicon-smelter.name = Fonderie de Silicone block.phase-weaver.name = Tisseur à phase block.pulverizer.name = Pulvérisateur block.cryofluidmixer.name = Refroidisseur block.melter.name = Four à Fusion block.incinerator.name = Incinérateur -block.biomattercompressor.name = Compresseur de Biomasse +block.spore-press.name = Spore Press block.separator.name = Séparateur -block.centrifuge.name = Centrifugeuse block.power-node.name = Transmetteur énergétique block.power-node-large.name = Grand transmetteur énergétique +block.surge-tower.name = Surge Tower block.battery.name = Batterie block.battery-large.name = Batterie large block.combustion-generator.name = Générateur à combustion block.turbine-generator.name = Générateur à Turbine +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = Foreuse mécanique block.pneumatic-drill.name = Foreuse à vérin block.laser-drill.name = Foreuse Laser block.water-extractor.name = Extracteur d'eau block.cultivator.name = Cultivateur -block.alpha-mech-pad.name = Alpha Mech Pad -block.dart-ship-pad.name = Dart Ship Pad +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = Delta Mech Pad block.javelin-ship-pad.name = Javelin Ship Pad block.trident-ship-pad.name = Trident Ship Pad @@ -593,7 +642,6 @@ block.bridge-conveyor.name = Pont transporteur block.plastanium-compressor.name = Compresseur de plastanium block.pyratite-mixer.name = Mixeur à pyratite block.blast-mixer.name = Mixeur à explosion -block.solidifer.name = Solidifieur block.solar-panel.name = Panneau solaire block.solar-panel-large.name = Grand panneau solaire block.oil-extractor.name = Extracteur de pétrol @@ -614,7 +662,6 @@ block.liquid-junction.name = Jonction à Liquide block.bridge-conduit.name = Pont à liquide block.rotary-pump.name = Pompe Rotative block.thorium-reactor.name = Réacteur à Thorium -block.command-center.name = Centre de commandement block.mass-driver.name = Transporteur de masse block.blast-drill.name = Foreuse à explosion block.thermal-pump.name = Pompe thermique @@ -633,20 +680,21 @@ block.rtg-generator.name = G.T.R. block.spectre.name = Spectre block.meltdown.name = Meltdown block.container.name = Conteneur -block.core.description = Sert de point de base pour le/les joueur(s). Ce bâtiment est le plus [scarlet]important[] du jeu ! +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = Bleu team.red.name = Rouge team.orange.name = Orange team.none.name = Gris team.green.name = Vert team.purple.name = Violet -unit.alpha-drone.name = Drone alpha unit.spirit.name = Drone spirituel unit.spirit.description = L'unité de soutien de départ. Apparaît dans la base par défaut. Mine automatiquement les minerais, récupère les objets au sol et répare les blocs. unit.phantom.name = Drone Fantôme unit.phantom.description = Une unité de soutien avancée. Mine automatiquement les minerais, récupère les objets au sol et répare les blocs. Bien plus efficace qu'un drone spirituel. unit.dagger.name = Poignard unit.dagger.description = Une unité terrestre de base. Utile en essaims. +unit.crawler.name = Crawler unit.titan.name = Titan unit.titan.description = Une unité terrestre cuirassée avancée. Utilise de l'alliage lourd pour munition. Attaque les unités aérinnes comme terrestres. unit.ghoul.name = Bombardier goule @@ -656,7 +704,11 @@ unit.wraith.description = Une unité volante rapide harcelant les ennemis. Utili unit.fortress.name = Forteresse unit.fortress.description = Une unité terrestre d'artillerie lourde. unit.revenant.name = Revenant -unit.revenant.description = Une plateforme de laser lourd. +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = Votre mission, si vous l'acceptez est de détruire [LIGHT_GRAY]l'ennemi[].\n\nCommencez par [accent] miner du cuivre[]. Appuyer sur un filon de cuivre proche de votre base pour faire ceci. tutorial.drill = Le minage manuel est inefficace.\n[accent]Des foreuses[]peuvent miner automatiquement.\nPlacez-en une sur un filon de cuivre. tutorial.conveyor = [accent]Les Tapis roulants[] sont utilisés pour transporter des objets jusqu'à la base.\nFaites une ligne de tapis roulants de la foreuse à la base . @@ -680,8 +732,6 @@ tutorial.dagger = Reliez des transmetteurs énergétiques à l'usine.\nUne fois tutorial.battle = [LIGHT_GRAY]L'Ennemi[] a révélé sa base.\nDétruisez la avec votre unité et des méchas "Poignard". block.copper-wall.description = Un bloc défensif bon marché.\nUtile pour protéger le noyau et les tourelles lors des premières vagues. block.copper-wall-large.description = Un bloc défensif bon marché.\nUtile pour protéger le noyau et les tourelles lors des premières vagues.\nS'étend sur plusieurs tuiles. -block.dense-alloy-wall.description = Un bloc défensif standard.\nUne protection adéquate contre les ennemis. -block.dense-alloy-wall-large.description = Un bloc défensif standard.\nUne protection adéquate contre les ennemis.\nS'étend sur plusieurs tuiles. block.thorium-wall.description = Un puissant bloc défensif.\nBonne protection contre les ennemis. block.thorium-wall-large.description = Un puissant bloc défensif.\nBonne protection contre les ennemis.\nS'étend sur plusieurs tuiles. block.phase-wall.description = Pas aussi fort qu'un mur de thorium, mais détournera les balles à moins qu'elles ne soient trop puissantes. @@ -711,8 +761,6 @@ block.titanium-conveyor.description = Bloc de transport d'articles avancé.\nDé block.phase-conveyor.description = Bloc de transport d'articles avancé.\nUtilise le pouvoir de téléporter des articles vers un convoyeur de phase connecté sur plusieurs carreaux. block.junction.description = Agit comme un pont pour deux bandes transporteuses qui se croisent.\nUtile dans les situations avec deux convoyeurs différents transportant des matériaux différents à des endroits différents. block.mass-driver.description = Bloc de transport d'articles ultime.\nRecueille plusieurs objets et les envoie ensuite à un autre pilote de masse sur une longue distance. -block.smelter.description = Brûle le charbon pour fondre le cuivre et le plomb en un alliage dense. -block.arc-smelter.description = Fait fondre le cuivre et le plomb en un alliage dense en utilisant une source d'alimentation externe. block.silicon-smelter.description = Réduit le sable avec du coke* très pur afin de produire du silicium. (*Coke produit à partir de charbon:REF) block.plastanium-compressor.description = Produit du plastanium à partir de pétrole et de titane. block.phase-weaver.description = Produit un tissu de phase à partir de thorium radioactif et de grandes quantités de sable. @@ -721,12 +769,10 @@ block.pulverizer.description = Brise la pierre en sable. Utile en cas de manque block.pyratite-mixer.description = Mélange le charbon, le plomb et le sable en pyratite hautement inflammable. block.blast-mixer.description = Utilise du pétrole pour transformer la pyratite en un composé explosif moins inflammable mais plus explosif. block.cryofluidmixer.description = L'eau et le titane combinés forment un fluide cryo beaucoup plus efficace pour le refroidissement. -block.solidifer.description = Refroidit la lave en pierre à un rythme rapide. block.melter.description = Chauffe la pierre à des températures très élevées pour obtenir de la lave. block.incinerator.description = Se débarrasse de tout article ou liquide en excès. -block.biomattercompressor.description = Compresse biomatter afin de récupérer du pétrole. +block.spore-press.description = Compresses spore pods into oil. block.separator.description = Exposer la pierre à la pression de l'eau afin d'obtenir différents minéraux contenus dans la pierre. -block.centrifuge.description = Plus efficace que le séparateur, mais aussi plus coûteux à construire et à alimenter. block.power-node.description = Transmet la puissance à des noeuds connectés. Il est possible de connecter jusqu'à quatre sources d'alimentation, puits ou nœuds.\nLe nœud recevra de l’alimentation ou fournira l’alimentation à tous les blocs adjacents. block.power-node-large.description = Son rayon d'action est supérieur à celui du nœud d'alimentation et peut être connecté à six sources d'alimentation, puits ou nœuds au maximum. block.battery.description = Stocke l’énergie chaque fois qu’il ya abondance et en cas de pénurie, tant qu’il reste de la capacité. @@ -748,7 +794,6 @@ block.blast-drill.description = L'extracteur ultime. Nécessite de grandes quant block.water-extractor.description = Extrait l'eau du sol. Utilisez-le quand il n'y a pas de lac à proximité. block.cultivator.description = Cultiver le sol avec de l'eau afin d'obtenir du biomatter. block.oil-extractor.description = Utilise de grandes quantités d'énergie pour extraire le pétrole du sable. Utilisez-le lorsqu'il n'y a pas de source directe de pétrole à proximité. -block.dart-ship-pad.description = Quittez votre vaisseau actuel et changez-vous en avion de combat de base.\nUtilisez la plate-forme en tapotant deux fois dessus. block.trident-ship-pad.description = Quittez votre vaisseau actuel et changez-vous en un bombardier lourd raisonnablement bien blindé.\nUtilisez la plate-forme en tapotant deux fois dessus. block.javelin-ship-pad.description = Quittez votre vaisseau actuel et changez-vous en un intercepteur puissant et rapide doté d’armes légères.\nUtilisez la plate-forme en tapotant deux fois dessus. block.glaive-ship-pad.description = Quittez votre vaisseau actuel et changez-vous en un grand vaisseau de combat bien blindé.\nUtilisez la plate-forme en tapotant deux fois dessus. @@ -764,7 +809,6 @@ block.titan-factory.description = Produit des unités terrestres avancées et bl block.fortress-factory.description = Produit des unités terrestres d'artillerie lourde. block.revenant-factory.description = Produit des unités terrestres laser lourdes. block.repair-point.description = Soigne en permanence l'unité endommagée la plus proche à proximité. -block.command-center.description = Permet de changer le comportement amical de l'IA. Actuellement, les commandes d'attaque, de retraite et de patrouille sont prises en charge. block.conduit.description = Bloc de transport liquide de base. Fonctionne comme un convoyeur, mais avec des liquides. Utilisation optimale avec des extracteurs, des pompes ou d’autres conduits. block.pulse-conduit.description = Bloc de transport de liquide avancé. Transporte les liquides plus rapidement et stocke plus que des conduits standard. block.phase-conduit.description = Bloc de transport de liquide avancé. Utilise le pouvoir de téléporter des liquides vers un conduit de phase connecté sur plusieurs carreaux. @@ -778,13 +822,11 @@ block.thermal-pump.description = La pompe ultime. Trois fois plus rapide qu'une block.router.description = Accepte les éléments d'une direction et les envoie dans 3 autres directions de manière égale. Utile pour séparer les matériaux d'une source en plusieurs cibles. block.distributor.description = Un routeur avancé qui divise les articles en 7 autres directions de manière égale. [scarlet]Seule et unique ![] block.bridge-conveyor.description = Bloc de transport d'articles avancé. Permet de transporter des objets sur plus de 3 tuiles de n'importe quel terrain ou bâtiment. -block.alpha-mech-pad.description = Lorsque vous avez assez de puissance, reconstruisez votre vaisseau dans le [accent]Alpha[] mech. block.item-source.description = Sort infiniment les articles. Bac à sable seulement. block.liquid-source.description = Débit infini de liquides. Bac à sable seulement. block.item-void.description = Détruit tous les objets qui y entrent sans utiliser d'énergie. Bac à sable seulement. block.power-source.description = Débit infini d'énergie. Bac à sable seulement. block.power-void.description = Annule toute l'énergie qui y est introduite. Bac à sable seulement. liquid.water.description = Couramment utilisé pour les machines de refroidissement et le traitement des déchets. -liquid.lava.description = Peut être transformé en [LIGHT_GRAY]pierre[], utilisé pour générer de l'énergie ou utilisé comme munition pour certaines tourelles. liquid.oil.description = Peut être brûlé, explosé ou utilisé comme liquide de refroidissement. liquid.cryofluid.description = Le liquide de refroidissement le plus efficace. diff --git a/core/assets/bundles/bundle_in_ID.properties b/core/assets/bundles/bundle_in_ID.properties index 392c57acf6..d591dce885 100644 --- a/core/assets/bundles/bundle_in_ID.properties +++ b/core/assets/bundles/bundle_in_ID.properties @@ -1,5 +1,6 @@ credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet!) credits = Kredit +contributors = Translators and Contributors discord = Mari bergabung di Discord Mindustry! link.discord.description = grup Discord Mindustry resmi link.github.description = Source code permainan @@ -9,15 +10,19 @@ link.itch.io.description = Halaman itch.io dengan unduhan PC dan versi web link.google-play.description = Google Play store link.wiki.description = wiki resmi Mindustry linkfail = Gagal membuka link!\nURL telah disalin ke papan salin. +screenshot = Screenshot saved to {0} gameover = Intinya hancur. gameover.pvp = Tim [accent] {0}[] menang! -sector.gameover = Sektor ini telah hancur. Ulangi? -sector.retry = Ulangi highscore = [YELLOW]Rekor baru! -wave.lasted = Kamu bertahan sampai gelombang ke [accent]{0}[]. -level.highscore = Skor Tinggi: [accent]{0} -level.delete.title = Konfirmasi Hapus +stat.wave = Waves Defeated:[accent] {0} +stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} +stat.built = Buildings Built:[accent] {0} +stat.destroyed = Buildings Destroyed:[accent] {0} +stat.deconstructed = Buildings Deconstructed:[accent] {0} +stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = Apakah kamu yakin ingin menghapus peta "[orange]{0}[]"? +level.highscore = Skor Tinggi: [accent]{0} level.select = Pilih Level level.mode = Modus permainan: construction.desktop = Kontrol desktop telah berubah.\nUntuk membatalkan blok atau menghentikan pembangunan, [accent]gunakan spasi[]. @@ -27,60 +32,36 @@ deconstruction.title = Block Deconstruction Guide deconstruction = You've just selected [accent]block deconstruction mode[].\n\nTo begin breaking, simply tap a block near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin de-constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Remove blocks in an area[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel deconstruction or selection[] by pressing the X at the bottom left. showagain = Jangan tampilkan lagi di sesi berikutnya coreattack = < Intinya sedang diserang! > -unlocks = Pencapaian +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = Simpan Permainan loadgame = Lanjutkan joingame = Bermain Bersama addplayers = Tambah/Hapus Pemain customgame = Game Bebas -sectors = Sektor -sector = Sektor Dipilih: [LIGHT_GRAY]{0} -sector.time = Waktu: [LIGHT_GRAY]{0} -sector.deploy = Pasang -sector.abandon = Batalkan -sector.abandon.confirm = Apakah kamu yakin ingin membatalkan all progress at this sector?\nIni tidak dapat diubah kembali! -sector.resume = Lanjutkan -sector.locked = [scarlet][[Belum Selesai] -sector.unexplored = [accent][[Belum Ditelusuri] -missions = Misi:[LIGHT_GRAY] {0} -mission = Misi:[LIGHT_GRAY] {0} -mission.main = Misi Utama:[LIGHT_GRAY] {0} -mission.info = Info Misi -mission.complete = Misi selesai! -mission.complete.body = Sektor {0},{1} telah dikuasai. -mission.wave = Bertahanlah selama [accent]{0}[] gelombang. -mission.wave.enemies = Bertahanlah selama[accent] {0}/{1} []gelombang\n{2} Musuh -mission.wave.enemy = Bertahanlah selama[accent] {0}/{1} []gelombang\n{2} Musuh -mission.wave.menu = Bertahanlah selama[accent] {0} []gelombang -mission.battle = Hancurkan markas musuh. -mission.resource.menu = Dapatkan {0} x{1} -mission.resource = Dapatkan {0}:\n[accent]{1}/{2}[] -mission.block = Buat {0} -mission.unit = Buat {0} Pasukan -mission.command = Beri Perintah {0} Ke Pasukan -mission.linknode = Gabungkan Power Node -mission.display = [accent]Misi:\n[LIGHT_GRAY]{0} -mission.mech = Ganti ke robot[accent] {0}[] -mission.create = Buat[accent] {0}[] +newgame = New Game none = close = Tutup quit = Keluar maps = Peta continue = Lanjutkan -nextmission = Tugas Berikut maps.none = [LIGHT_GRAY]Peta tidak ditemukan! about.button = Tentang name = Nama: +noname = Pick a[accent] player name[] first. filename = Nama file: unlocked = Blok Baru Terbuka! -unlocked.plural = Blok Baru Terbuka! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. players = {0} pemain online players.single = {0} pemain online server.closing = [accent]Menutup server... server.kicked.kick = Anda telah dikeluarkan dari server! server.kicked.serverClose = Server ditutup. -server.kicked.sectorComplete = Sektor selesai. -server.kicked.sectorComplete.text = Misi Anda telah selesai.\nServer akan melanjutkan ke sektor selanjutnya. server.kicked.clientOutdated = Client versi lama! Update game Anda! server.kicked.serverOutdated = Server versi lama! Tanyakan host untuk memperbaharuinya! server.kicked.banned = Anda telah di-ban dari server ini. @@ -89,6 +70,7 @@ server.kicked.nameInUse = Ada seseorang dengan nama\nitu di server ini. server.kicked.nameEmpty = Nama Anda harus mengandung setidaknya satu karakter atau angka. server.kicked.idInUse = Kamu sudah ada di server ini! Menghubungkan dengan dua akun tidak diizinkan. server.kicked.customClient = Server ini tidak mendukung bentukan khusus. Unduh versi resmi. +server.kicked.gameover = Game over! host.info = Tombol [accent]host[] akan membuat server dengan port [scarlet]6567[] dan [scarlet]6568.[]\nSiapa saja yang terhubung ke [LIGHT_GRAY]WiFi atau jaringan lokal[] dapat melihat server Anda di daftar server.\n\nJika Anda ingin orang-orang agar dapat terhubung dari mana saja melalui IP, diperlukan [accent]port forwarding[].\n\n[LIGHT_GRAY]Catatan: Jika seseorang mengalami kesulitan untuk bergabung, pastikan bahwa Anda telah mengizinkan akses Mindustry ke jaringan lokal Anda di pengaturan firewall. join.info = Di sini, Anda dapat memasukan [accent]IP server[] yang akan dihubungkan, atau menemukan server di [accent]jaringan lokal[] untuk dihubungkan.\nKedua jaringan LAN dan WAN didukung.\n\n[LIGHT_GRAY]Catatan: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP. hostserver = Host Server @@ -159,7 +141,6 @@ save.rename.text = Nama baru: selectslot = Pilih simpanan. slot = [accent]Slot{0} save.corrupted = [accent]Simpanan rusak atau tidak valid! -sector.corrupted = [accent]A save file for this sector was found, but loading failed.\nA new one has been created. empty = on = Hidup off = Mati @@ -169,6 +150,7 @@ save.wave = Gelombang {0} save.difficulty = Difficulty: {0} save.date = Terakhir Disimpan: {0} save.playtime = Playtime: {0} +warning = Warning. confirm = Konfirmasi delete = Hapus ok = OK @@ -204,7 +186,6 @@ map.nospawn = This map does not have any cores for the player to spawn in! Add a map.nospawn.pvp = This map does not have any enemy cores for player to spawn into! Add[SCARLET] red[] cores to this map in the editor. map.invalid = Error loading map: corrupted or invalid map file. editor.brush = Brush -editor.slope = \\ editor.openin = Open In Editor editor.oregen = Ore Generation editor.oregen.info = Ore Generation: @@ -259,6 +240,26 @@ tutorial = Tutorial editor = Pengedit mapeditor = Pengedit Peta donate = Sumbangkan +abandon = Abandon +abandon.text = This zone and all its resources will be lost to the enemy. +locked = Locked +complete = [LIGHT_GRAY]Complete: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Best: {0} +launch = Launch +launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson]Gagal terhubung ke server: [accent]{0} error.unreachable = Server unreachable. error.invalidaddress = Invalid address. @@ -266,7 +267,20 @@ error.timedout = Timed out!\nMake sure the host has port forwarding set up, and error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! error.alreadyconnected = Already connected. error.mapnotfound = Map file not found! +error.io = Network I/O error. error.any = Unkown network error. +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = Bahasa settings.reset = Atur ulang ke Default settings.rebind = Rebind @@ -277,7 +291,6 @@ settings.graphics = Grafis settings.cleardata = Clear Game Data... settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! settings.clearall.confirm = [scarlet]WARNING![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit. -settings.clearsectors = Clear Sectors settings.clearunlocks = Clear Unlocks settings.clearall = Clear All paused = Jeda @@ -286,12 +299,15 @@ no = No info.title = [accent]Info error.title = [crimson]Telah terjadi kesalahan error.crashtitle = Telah terjadi kesalahan +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Info Blok +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = Kapasitas Tenaga blocks.powershot = Tenaga/tembakan blocks.targetsair = Targets Air -blocks.itemspeed = Units Moved +blocks.itemsmoved = Move Speed blocks.shootrange = Range blocks.size = Ukuran blocks.liquidcapacity = Kapasitas cairan @@ -312,16 +328,23 @@ blocks.inputitems = Input Items blocks.outputitem = Output Item blocks.drilltier = Drillables blocks.drillspeed = Base Drill Speed +blocks.maxunits = Max Active Units blocks.liquidoutput = Liquid Output blocks.liquidoutputspeed = Liquid Output Speed blocks.liquiduse = Liquid Use blocks.coolant = Coolant +blocks.liquid = Liquid blocks.coolantuse = Coolant Use blocks.inputliquidfuel = Fuel Liquid blocks.liquidfueluse = Liquid Fuel Use blocks.boostitem = Boost Item blocks.boostliquid = Boost Liquid blocks.health = Darah +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Ketidaktelitian blocks.shots = Tembakan blocks.reload = Reload @@ -329,11 +352,11 @@ blocks.inputfuel = Fuel blocks.fuelburntime = Fuel Burn Time blocks.inputcapacity = Kapasitas masuk blocks.outputcapacity = Kapasitas keluar +blocks.ammo = Ammo unit.blocks = blocks unit.powersecond = power units/second unit.liquidsecond = liquid units/second unit.itemssecond = items/second -unit.pixelssecond = pixels/second unit.liquidunits = liquid units unit.powerunits = power units unit.degrees = degrees @@ -346,6 +369,7 @@ category.items = Items category.crafting = Crafting category.shooting = Shooting category.optional = Optional Enhancements +setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS setting.fpscap.none = None @@ -378,12 +402,16 @@ category.multiplayer.name = Multiplayer command.attack = Attack command.retreat = Retreat command.patrol = Patrol +keybind.gridMode.name = Block Select +keybind.gridModeShift.name = Category Select keybind.press = Press a key... keybind.press.axis = Press an axis or key... +keybind.screenshot.name = Map Screenshot keybind.move_x.name = gerak_x keybind.move_y.name = gerak_y keybind.select.name = pilih -keybind.break.name = hapus +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = Deselect keybind.shoot.name = tembak keybind.zoom_hold.name = perbesar_tahan @@ -402,29 +430,28 @@ keybind.chat_scroll.name = Chat scroll keybind.drop_unit.name = drop unit keybind.zoom_minimap.name = Zoom minimap mode.help.title = Description of modes -mode.waves.name = gelombang -mode.waves.description = the normal mode. limited resources and automatic incoming waves. +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. mode.sandbox.name = sandbox mode.sandbox.description = infinite resources and no timer for waves. mode.freebuild.name = freebuild mode.freebuild.description = limited resources and no timer for waves. mode.pvp.name = PvP mode.pvp.description = fight against other players locally. +mode.attack.name = Attack +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = Items content.liquid.name = Liquids content.unit.name = Units -content.recipe.name = Blocks +content.block.name = Blocks content.mech.name = Mechs -item.stone.name = batu -item.stone.description = A common raw material. Used for separating and refining into other materials, or melting into lava. item.copper.name = Copper item.copper.description = A useful structure material. Used extensively in all types of blocks. item.lead.name = Lead item.lead.description = A basic starter material. Used extensively in electronics and liquid transportation blocks. item.coal.name = batu bara item.coal.description = A common and readily available fuel. -item.dense-alloy.name = Dense Alloy -item.dense-alloy.description = A tough alloy made with lead and copper. Used in advanced transportation blocks and high-tier drills. +item.graphite.name = Graphite item.titanium.name = titanium item.titanium.description = A rare super-light metal used extensively in liquid transportation, drills and aircraft. item.thorium.name = thorium @@ -437,16 +464,20 @@ item.phase-fabric.name = Phase Fabric item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. item.surge-alloy.name = Surge Alloy item.surge-alloy.description = An advanced alloy with unique electrical properties. -item.biomatter.name = Biomatter -item.biomatter.description = A clump of organic mush; used for conversion into oil or as a basic fuel. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = pasir item.sand.description = A common material that is used extensively in smelting, both in alloying and as a flux. item.blast-compound.name = Blast Compound item.blast-compound.description = A volatile compound used in bombs and explosives. While it can burned as fuel, this is not advised. item.pyratite.name = Pyratite item.pyratite.description = An extremely flammable substance used in incendiary weapons. +item.metaglass.name = Metaglass +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = air -liquid.lava.name = lahar +liquid.slag.name = Slag liquid.oil.name = minyak liquid.cryofluid.name = Cryofluid mech.alpha-mech.name = Alpha @@ -481,11 +512,10 @@ mech.glaive-ship.weapon = Flame Repeater item.explosiveness = [LIGHT_GRAY]Explosiveness: {0} item.flammability = [LIGHT_GRAY]Flammability: {0} item.radioactivity = [LIGHT_GRAY]Radioactivity: {0} -item.fluxiness = [LIGHT_GRAY]Flux Power: {0} unit.health = [LIGHT_GRAY]Health: {0} unit.speed = [LIGHT_GRAY]Speed: {0} mech.weapon = [LIGHT_GRAY]Weapon: {0} -mech.armor = [LIGHT_GRAY]Armor: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]Item Capacity: {0} mech.minespeed = [LIGHT_GRAY]Mining Speed: {0} mech.minepower = [LIGHT_GRAY]Mining Power: {0} @@ -493,29 +523,60 @@ mech.ability = [LIGHT_GRAY]Ability: {0} liquid.heatcapacity = [LIGHT_GRAY]Heat Capacity: {0} liquid.viscosity = [LIGHT_GRAY]Viscosity: {0} liquid.temperature = [LIGHT_GRAY]Temperature: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](Constructing) block.spawn.name = Enemy Spawn -block.core.name = Core -block.metalfloor.name = Metal Floor +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = deepwater block.water.name = water -block.lava.name = lava block.tar.name = Tar -block.blackstone.name = blackstone block.stone.name = stone -block.dirt.name = dirt block.sand.name = sand block.ice.name = ice block.snow.name = snow -block.grass.name = grass -block.shrub.name = shrub -block.rock.name = rock -block.blackrock.name = blackrock -block.icerock.name = icerock +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = Copper Wall block.copper-wall-large.name = Large Copper Wall -block.dense-alloy-wall.name = Dense Alloy Wall -block.dense-alloy-wall-large.name = Large Dense Alloy Wall +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = Phase Wall block.phase-wall-large.name = Large Phase Wall block.thorium-wall.name = Thorium Wall @@ -523,7 +584,6 @@ block.thorium-wall-large.name = Large Thorium Wall block.door.name = pintu block.door-large.name = pintu besar block.duo.name = Duo -block.scorch.name = Scorch block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = konveyor @@ -535,30 +595,29 @@ block.sorter.name = penyortir block.sorter.description = Sorts items. If an item matches the selection, it is allowed to pass. Otherwise, the item is outputted to the left and right. block.overflow-gate.name = Overflow Gate block.overflow-gate.description = A combination splitter and router that only outputs to the left and right if the front path is blocked. -block.smelter.name = peleburan -block.arc-smelter.name = Arc Smelter block.silicon-smelter.name = Silicon Smelter block.phase-weaver.name = Phase Weaver block.pulverizer.name = Pulverizer block.cryofluidmixer.name = Cryofluid Mixer block.melter.name = Melter block.incinerator.name = Incinerator -block.biomattercompressor.name = Biomatter Compressor +block.spore-press.name = Spore Press block.separator.name = Separator -block.centrifuge.name = Centrifuge block.power-node.name = Power Node block.power-node-large.name = Large Power Node +block.surge-tower.name = Surge Tower block.battery.name = Battery block.battery-large.name = Large Battery block.combustion-generator.name = Combustion Generator block.turbine-generator.name = Turbine Generator +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = Mechanical Drill block.pneumatic-drill.name = Pneumatic Drill block.laser-drill.name = Laser Drill block.water-extractor.name = Water Extractor block.cultivator.name = Cultivator -block.alpha-mech-pad.name = Alpha Mech Pad -block.dart-ship-pad.name = Dart Ship Pad +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = Delta Mech Pad block.javelin-ship-pad.name = Javelin Ship Pad block.trident-ship-pad.name = Trident Ship Pad @@ -583,7 +642,6 @@ block.bridge-conveyor.name = Bridge Conveyor block.plastanium-compressor.name = Plastanium Compressor block.pyratite-mixer.name = Pyratite Mixer block.blast-mixer.name = Blast Mixer -block.solidifer.name = Solidifer block.solar-panel.name = Solar Panel block.solar-panel-large.name = Large Solar Panel block.oil-extractor.name = Oil Extractor @@ -604,7 +662,6 @@ block.liquid-junction.name = Liquid Junction block.bridge-conduit.name = Bridge Conduit block.rotary-pump.name = Rotary Pump block.thorium-reactor.name = Thorium Reactor -block.command-center.name = Command Center block.mass-driver.name = Mass Driver block.blast-drill.name = Blast Drill block.thermal-pump.name = Thermal Pump @@ -623,20 +680,21 @@ block.rtg-generator.name = RTG Generator block.spectre.name = Spectre block.meltdown.name = Meltdown block.container.name = Container -block.core.description = The most important building in the game. +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = blue team.red.name = red team.orange.name = orange team.none.name = gray team.green.name = green team.purple.name = purple -unit.alpha-drone.name = Alpha Drone unit.spirit.name = Spirit Drone unit.spirit.description = The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. unit.phantom.name = Phantom Drone unit.phantom.description = An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. unit.dagger.name = Dagger unit.dagger.description = A basic ground unit. Useful in swarms. +unit.crawler.name = Crawler unit.titan.name = Titan unit.titan.description = An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. unit.ghoul.name = Ghoul Bomber @@ -646,7 +704,11 @@ unit.wraith.description = A fast, hit-and-run interceptor unit. unit.fortress.name = Fortress unit.fortress.description = A heavy artillery ground unit. unit.revenant.name = Revenant -unit.revenant.description = A heavy laser platform. +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = Your mission here is to eradicate the[LIGHT_GRAY] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this. tutorial.drill = Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein. tutorial.conveyor = [accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core. @@ -670,8 +732,6 @@ tutorial.dagger = Link power nodes to the factory.\nOnce requirements are met, a tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. block.copper-wall.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves. block.copper-wall-large.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves.\nSpans multiple tiles. -block.dense-alloy-wall.description = A standard defensive block.\nAdequate protection from enemies. -block.dense-alloy-wall-large.description = A standard defensive block.\nAdequate protection from enemies.\nSpans multiple tiles. block.thorium-wall.description = A strong defensive block.\nGood protection from enemies. block.thorium-wall-large.description = A strong defensive block.\nGood protection from enemies.\nSpans multiple tiles. block.phase-wall.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful. @@ -701,8 +761,6 @@ block.titanium-conveyor.description = Advanced item transport block. Moves items block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles. block.junction.description = Acts as a bridge for two crossing conveyor belts. Useful in situations with two different conveyors carrying different materials to different locations. block.mass-driver.description = Ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. -block.smelter.description = Burns coal for smelting copper and lead into dense alloy. -block.arc-smelter.description = Smelts copper and lead into dense alloy by using an external power source. block.silicon-smelter.description = Reduces sand with highly pure coke in order to produce silicon. block.plastanium-compressor.description = Produces plastanium from oil and titanium. block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. @@ -711,12 +769,10 @@ block.pulverizer.description = Crushes stone into sand. Useful when there is a l block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. block.blast-mixer.description = Uses oil for transforming pyratite into the less flammable but more explosive blast compound. block.cryofluidmixer.description = Combines water and titanium into cryofluid which is much more efficient for cooling. -block.solidifer.description = Cools lava to stone at a fast pace. block.melter.description = Heats up stone to very high temperatures to obtain lava. block.incinerator.description = Gets rid of any excess item or liquid. -block.biomattercompressor.description = Compresses biomatter in order to retrieve oil. +block.spore-press.description = Compresses spore pods into oil. block.separator.description = Exposes stone to water pressure in order to obtain various minerals contained in the stone. -block.centrifuge.description = More efficient than the separator, but also more expensive to build and requires power. block.power-node.description = Transmits power to connected nodes. Up to four power sources, sinks or nodes can be connected. The node will receive power from or supply power to any adjacent blocks. block.power-node-large.description = Has a larger radius than the power node and connects to up to six power sources, sinks or nodes. block.battery.description = Stores power whenever there is an abundance and provides power whenever there is a shortage, as long as there is capacity left. @@ -738,7 +794,6 @@ block.blast-drill.description = The ultimate drill. Requires large amounts of po block.water-extractor.description = Extracts water from the ground. Use it when there is no lake nearby. block.cultivator.description = Cultivates the soil with water in order to obtain biomatter. block.oil-extractor.description = Uses large amounts of power in order to extract oil from sand. Use it when there is no direct source of oil nearby. -block.dart-ship-pad.description = Leave your current vessel and change into a basic fighter aircraft.\nUse the pad by double tapping while standing on it. block.trident-ship-pad.description = Leave your current vessel and change into a reasonably well armored heavy bomber.\nUse the pad by double tapping while standing on it. block.javelin-ship-pad.description = Leave your current vessel and change into a strong and fast interceptor with lightning weapons.\nUse the pad by double tapping while standing on it. block.glaive-ship-pad.description = Leave your current vessel and change into a large, well-armored gunship.\nUse the pad by double tapping while standing on it. @@ -754,7 +809,6 @@ block.titan-factory.description = Produces advanced, armored ground units. block.fortress-factory.description = Produces heavy artillery ground units. block.revenant-factory.description = Produces heavy laser ground units. block.repair-point.description = Continuously heals the closest damaged unit in its vicinity. -block.command-center.description = Allows changing friendly AI behavior. Currently, attack, retreat and patrol commands are supported. block.conduit.description = Basic liquid transport block. Works like a conveyor, but with liquids. Best used with extractors, pumps or other conduits. block.pulse-conduit.description = Advanced liquid transport block. Transports liquids faster and stores more than standard conduits. block.phase-conduit.description = Advanced liquid transport block. Uses power to teleport liquids to a connected phase conduit over several tiles. @@ -768,13 +822,11 @@ block.thermal-pump.description = The ultimate pump. Three times as fast as a mec block.router.description = Accepts items from one direction and outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets. block.distributor.description = An advanced router which splits items to up to 7 other directions equally. block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building. -block.alpha-mech-pad.description = When given enough power, rebuilds your ship into the[accent] Alpha[] mech. block.item-source.description = Infinitely outputs items. Sandbox only. block.liquid-source.description = Infinitely outputs liquids. Sandbox only. block.item-void.description = Destroys any items which go into it without using power. Sandbox only. block.power-source.description = Infinitely outputs power. Sandbox only. block.power-void.description = Voids all power inputted into it. Sandbox only. liquid.water.description = Commonly used for cooling machines and waste processing. -liquid.lava.description = Can be transformed into[LIGHT_GRAY] stone[], used for generating power or used as ammo for certain turrets. liquid.oil.description = Can be burnt, exploded or used as a coolant. liquid.cryofluid.description = The most efficient liquid for cooling things down. diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties index fd8af06514..54539615aa 100644 --- a/core/assets/bundles/bundle_it.properties +++ b/core/assets/bundles/bundle_it.properties @@ -1,5 +1,6 @@ credits.text = Creato da [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](Nel caso non te ne sia accorto, la traduzione del gioco non è completa.\n Chi di dovere sta lavorando più velocemente possibile per completarla!) credits = Crediti +contributors = Translators and Contributors discord = Unisciti sul server discord di mindustry! link.discord.description = la chatroom ufficiale del server discord di Mindustry link.github.description = Codice sorgente del gioco @@ -9,15 +10,19 @@ link.itch.io.description = pagina di itch.io con download per PC e versione web link.google-play.description = Elenco di Google Play Store link.wiki.description = wiki ufficiale di Mindustry linkfail = Impossibile aprire il link! L'URL è stato copiato nella tua bacheca. +screenshot = Screenshot saved to {0} gameover = Il nucleo è stato distrutto. gameover.pvp = The[accent] {0}[] team is victorious! -sector.gameover = Hai perso questo settore. Attaccare di nuovo? -sector.retry = Riprova highscore = [YELLOW]Nuovo record! -wave.lasted = Sei sopravvissuto fino all'onda [accent]{0}[]. -level.highscore = Miglior punteggio: [accent]{0} -level.delete.title = Conferma Eliminazione +stat.wave = Waves Defeated:[accent] {0} +stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} +stat.built = Buildings Built:[accent] {0} +stat.destroyed = Buildings Destroyed:[accent] {0} +stat.deconstructed = Buildings Deconstructed:[accent] {0} +stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = Sei sicuro di voler eliminare questa mappa"[accent]{0}[]"? +level.highscore = Miglior punteggio: [accent]{0} level.select = Selezione del livello level.mode = Modalità di gioco: construction.desktop = Desktop controls have been changed.\nTo deselect a block or stop building, [accent]use space[]. @@ -27,60 +32,36 @@ deconstruction.title = Guida distruzione blocchi deconstruction = Hai appena selezionato la [accent]modalità di distruzione [].\n\nPer iniziare a distruggere, premi sui blocchi interessati.\n Poi premi conferma(✔), e la tua navicella inizierà A INIZIARE\n\n- [accent]Rimuovi i blocchi[] dalla tua selezione cliccandoci sopra.\n- [accent]Per rimuovere più blocchi in un area[] tieni premuto in un punto, poi trascina in modo da selexionare ciò che ti interessa.\n- [accent]Cancella la distruzione[] premendo la X in basso a sinistra. showagain = non mostrare più coreattack = < Il nucleo è sotto attacco! > -unlocks = Sblocchi +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = Salva loadgame = Carica joingame = Unisciti al gioco addplayers = Aggiungi/rimuovi giocatori customgame = Gioco personalizzato -sectors = Settori -sector = Settori Selezionati: [LIGHT_GRAY]{0} -sector.time = Tempo: [LIGHT_GRAY]{0} -sector.deploy = Schiera -sector.abandon = Abandon -sector.abandon.confirm = Are you sure you want to abandon all progress at this sector?\nThis cannot be undone! -sector.resume = Riprendi -sector.locked = [scarlet][[Incomplete] -sector.unexplored = [accent][[Unexplored] -missions = Missions:[LIGHT_GRAY] {0} -mission = Mission:[LIGHT_GRAY] {0} -mission.main = Main Mission:[LIGHT_GRAY] {0} -mission.info = Mission Info -mission.complete = Missione completata! -mission.complete.body = Il settore {0},{1} è stato conquistato. -mission.wave = Sopravvivi a [accent]{0}/{1][] onda/e.Onda in {2} -mission.wave.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies -mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy -mission.wave.menu = Survive[accent] {0} []waves -mission.battle = Distruggi la base del nemico. -mission.resource.menu = Obtain {0} x{1} -mission.resource = Ottieni {0} x{1} -mission.block = Create {0} -mission.unit = Create {0} Unit -mission.command = Send Command {0} To Units -mission.linknode = Link Power Node -mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -mission.mech = Switch to mech[accent] {0}[] -mission.create = Create[accent] {0}[] +newgame = New Game none = close = Chiuso quit = Esci maps = Mappe continue = Continua -nextmission = Missione successiva maps.none = [LIGHT_GRAY]Nessuna mappa trovata! about.button = Info name = Nome: +noname = Pick a[accent] player name[] first. filename = File Name: unlocked = Nuovo blocco scoperto! -unlocked.plural = Nuovi blocchi scoperti! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. players = {0} giocatori online players.single = {0} giocatori online server.closing = [accent]Chiusura server ... server.kicked.kick = Sei stato cacciato dal server! server.kicked.serverClose = Server chiuso. -server.kicked.sectorComplete = Settore completato. -server.kicked.sectorComplete.text = La tua misione è completata.\nOra il server continuerà al settore successivo. server.kicked.clientOutdated = Versione del client obsoleta! Aggiorna il tuo gioco! server.kicked.serverOutdated = Server obsoleto! Chiedi all'host di aggiornare! server.kicked.banned = Sei bannato da questo server. @@ -89,6 +70,7 @@ server.kicked.nameInUse = C'è già qualcuno con il tuo nome\nsu questo server. server.kicked.nameEmpty = Il tuo nome deve contenere almeno un carattere. server.kicked.idInUse = Sei già su questo server! Non è permesso connettersi con due account. server.kicked.customClient = Questo server non supporta le build personalizzate. Scarica la versione ufficiale dal sito. +server.kicked.gameover = Game over! host.info = Il pulsante [accent]hos [] ospita un server sulle porte [scarlet]6567[] e [scarlet]656.[] Chiunque sulla stessa [LIGHT_GRAY]connessione wifi o rete locale[] dovrebbe essere in grado di vedere il proprio server nel proprio elenco server.\n\n Se vuoi che le persone siano in grado di connettersi ovunque tramite IP, è richiesto il [accent]port forwarding[]. \n\n[LIGHT_GRAY]Nota: se qualcuno sta riscontrando problemi durante la connessione al gioco LAN, assicurati di aver consentito a Mindustry di accedere alla rete locale nelle impostazioni del firewall. join.info = Qui è possibile inserire un [accent]IP del server[] a cui connettersi, o scoprire [accento]un server sulla rete locale[] disponibile.\n Sono supportati sia il multiplayer LAN che WAN. \n\n[LIGHT_GRAY]Nota: non esiste un elenco di server globali automatici; se si desidera connettersi a qualcuno tramite IP, è necessario chiedere all'host il proprio IP. hostserver = Host Server @@ -159,7 +141,6 @@ save.rename.text = Nuovo nome: selectslot = Seleziona un salvataggio. slot = [accent]Slot {0} save.corrupted = [orang]Salvataggio corrotto o non valido! -sector.corrupted = [accent]Un file per questo settore è stato trovato, ma è fallito il caricamnto.\nQuindi ne è stato creato uno nuovo. empty = on = On off = Off @@ -169,6 +150,7 @@ save.wave = Ondata: {0} save.difficulty = Difficoltà: {0} save.date = Ultimo salvataggio: {0} save.playtime = Tempo di gioco: {0} +warning = Warning. confirm = Conferma delete = Elimina ok = OK @@ -204,7 +186,6 @@ map.nospawn = Questa mappa non possiede un nucleo dove spawnare! Aggiungine uno map.nospawn.pvp = This map does not have any enemy cores for player to spawn into! Add[SCARLET] red[] cores to this map in the editor. map.invalid = Errore nel caricamento della mappa: file mappa corrotto o non valido. editor.brush = Pennello -editor.slope = \\ editor.openin = Apri nell'editor editor.oregen = Generazione dei minerali editor.oregen.info = Generazione dei minerali: @@ -259,6 +240,26 @@ tutorial = Tutorial editor = Editor mapeditor = Editor Mappe donate = Dona +abandon = Abandon +abandon.text = This zone and all its resources will be lost to the enemy. +locked = Locked +complete = [LIGHT_GRAY]Complete: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Best: {0} +launch = Launch +launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson] Impossibile connettersi al server: [accent] {0} error.unreachable = Server unreachable. error.invalidaddress = Invalid address. @@ -266,7 +267,20 @@ error.timedout = Timed out!\nMake sure the host has port forwarding set up, and error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! error.alreadyconnected = Already connected. error.mapnotfound = Map file not found! +error.io = Network I/O error. error.any = Unkown network error. +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = Lingua settings.reset = Resetta Alle Impostazioni Predefinite settings.rebind = Reinposta @@ -277,7 +291,6 @@ settings.graphics = Grafica settings.cleardata = Clear Game Data... settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! settings.clearall.confirm = [scarlet]WARNING![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit. -settings.clearsectors = Clear Sectors settings.clearunlocks = Clear Unlocks settings.clearall = Clear All paused = In pausa @@ -286,12 +299,15 @@ no = No info.title = [accent] Info error.title = [crimson]Si è verificato un errore error.crashtitle = Si è verificato un errore +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = info sul blocco +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = Capacità Energetica blocks.powershot = Danno/Colpo blocks.targetsair = Attacca nemici aerei -blocks.itemspeed = Unità spostate +blocks.itemsmoved = Move Speed blocks.shootrange = Raggio blocks.size = Grandezza blocks.liquidcapacity = Capacità del liquido @@ -312,16 +328,23 @@ blocks.inputitems = Oggetti in entrata blocks.outputitem = Oggetti in uscita blocks.drilltier = Scavabili blocks.drillspeed = Velocità scavo stbile +blocks.maxunits = Max Active Units blocks.liquidoutput = Uscita liquidi blocks.liquidoutputspeed = Liquid Output Speed blocks.liquiduse = Uso liquidi blocks.coolant = Refrigerante +blocks.liquid = Liquid blocks.coolantuse = uso refrigerante blocks.inputliquidfuel = carburante liquido blocks.liquidfueluse = Utilizzo carburante liquido blocks.boostitem = Boost Item blocks.boostliquid = Boost Liquid blocks.health = Salute +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Inaccuratezza blocks.shots = Colpi blocks.reload = Ricarica @@ -329,11 +352,11 @@ blocks.inputfuel = Carburante blocks.fuelburntime = Tempo combustione carburante blocks.inputcapacity = Capacità di ingresso blocks.outputcapacity = Capacità di uscita +blocks.ammo = Ammo unit.blocks = blocchi unit.powersecond = unità energia/secondo unit.liquidsecond = unità liquide/secondo unit.itemssecond = oggetti/secondo -unit.pixelssecond = pixel/secondo unit.liquidunits = unità liquidi unit.powerunits = unità energia unit.degrees = gradi @@ -346,6 +369,7 @@ category.items = Oggetti category.crafting = Produzione category.shooting = Potenza di fuoco category.optional = Optional Enhancements +setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Limite FPS setting.fpscap.none = Niente @@ -378,12 +402,16 @@ category.multiplayer.name = Multigiocatore command.attack = Attack command.retreat = Retreat command.patrol = Patrol +keybind.gridMode.name = Block Select +keybind.gridModeShift.name = Category Select keybind.press = Press a key... keybind.press.axis = Press an axis or key... +keybind.screenshot.name = Map Screenshot keybind.move_x.name = Sposta_x keybind.move_y.name = Sposta_y keybind.select.name = seleziona -keybind.break.name = rompi +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = Deselect keybind.shoot.name = spara keybind.zoom_hold.name = zoom_hold @@ -402,29 +430,28 @@ keybind.chat_scroll.name = Scorri chat keybind.drop_unit.name = droppa materiali keybind.zoom_minimap.name = Zomma minimappa mode.help.title = Descrizione delle modalità -mode.waves.name = ondate -mode.waves.description = modalità normale. risorse limitate e ondate automatiche. +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. mode.sandbox.name = Sandbox mode.sandbox.description = risorse infinite e nessun timer per le ondate. mode.freebuild.name = freebuild mode.freebuild.description = risorse limitate e nessun timer per le ondate. mode.pvp.name = PvP mode.pvp.description = fight against other players locally. +mode.attack.name = Attack +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = Oggetti content.liquid.name = Liquidi content.unit.name = Units -content.recipe.name = Blocchi +content.block.name = Blocks content.mech.name = Mech -item.stone.name = pietra -item.stone.description = UN materiale grezzo molto comune, che solitamente viene rifinito per ottenerne degli altri. item.copper.name = Rame item.copper.description = Una utile materiale styrutturale. Molto usato in tutti i blocchi. item.lead.name = Piombo item.lead.description = Un materiale base, molto usato nei blocchi di trasporto. item.coal.name = carbone item.coal.description = Un carburante comune e facilmente ottenibile. -item.dense-alloy.name = LEga ad alta densità -item.dense-alloy.description = Una lega molto pesante composta da piombo e rame. utilizzato in blocchi di trasporto e trapani avanzati. +item.graphite.name = Graphite item.titanium.name = titanio item.titanium.description = Un raro metallo super leggero usato ampiamente nel trasporto di liquidi, trapani e navi. item.thorium.name = Torio @@ -437,16 +464,20 @@ item.phase-fabric.name = Phase Fabric item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. item.surge-alloy.name = Surge Alloy item.surge-alloy.description = An advanced alloy with unique electrical properties. -item.biomatter.name = Biomateria -item.biomatter.description = Materiale organico; Utilizzato per essere convertito in petrolio o carburante. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = sabbia item.sand.description = Un materiale base che viene altamente usato nei processi di fusione, Sia come lega che come lubrificante. item.blast-compound.name = Polvere esplosiva item.blast-compound.description = Un composto altamente volatile, utilizzato nella produzione di bombe ed esplosivi. Può essere utilizzato come combustibile anche se non è consigliato. item.pyratite.name = Pirite item.pyratite.description = Una sostanza molto infiammabile che viene utilizzata nelle armi a fuoco. +item.metaglass.name = Metaglass +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = acqua -liquid.lava.name = lava +liquid.slag.name = Slag liquid.oil.name = petrolio liquid.cryofluid.name = criogenium mech.alpha-mech.name = Alpha @@ -481,11 +512,10 @@ mech.glaive-ship.weapon = Ripetitore di fiamma item.explosiveness = [LIGHT_GRAY]Esplosività: {0} item.flammability = [LIGHT_GRAY]Infiammabilità: {0} item.radioactivity = [LIGHT_GRAY]Radioattività: {0} -item.fluxiness = [LIGHT_GRAY]Portata: {0} unit.health = [LIGHT_GRAY]Vita: {0} unit.speed = [LIGHT_GRAY]Velocità: {0} mech.weapon = [LIGHT_GRAY]Armi: {0} -mech.armor = [LIGHT_GRAY]Protezione: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]Capacità oggetti: {0} mech.minespeed = [LIGHT_GRAY]Velocità di scavo: {0} mech.minepower = [LIGHT_GRAY]Potenza di scavo: {0} @@ -493,29 +523,60 @@ mech.ability = [LIGHT_GRAY]Abilità: {0} liquid.heatcapacity = [LIGHT_GRAY]Capacità calorifica: {0} liquid.viscosity = [LIGHT_GRAY]Viscosità: {0} liquid.temperature = [LIGHT_GRAY]Temperatura: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](Constructing) block.spawn.name = Enemy Spawn -block.core.name = Nucleo -block.metalfloor.name = Pavimento di ferro +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = acqua profonda block.water.name = acqua -block.lava.name = lava block.tar.name = Tar -block.blackstone.name = pietra nera block.stone.name = pietra -block.dirt.name = terra block.sand.name = sabbia block.ice.name = ghiaccio block.snow.name = neve -block.grass.name = erba -block.shrub.name = arbusto -block.rock.name = roccia -block.blackrock.name = roccia nera -block.icerock.name = roccia di ghiaccio +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = Muro di rame block.copper-wall-large.name = Muro grande di rame -block.dense-alloy-wall.name = Dense Alloy Wall -block.dense-alloy-wall-large.name = Large Dense Alloy Wall +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = Muro di fase block.phase-wall-large.name = Muro grande di fase block.thorium-wall.name = Muro di torio @@ -523,7 +584,6 @@ block.thorium-wall-large.name = Muro grande di torio block.door.name = porta block.door-large.name = Porta grande block.duo.name = Duo -block.scorch.name = Scorch block.hail.name = Bombardiere block.lancer.name = Idrogetto block.conveyor.name = trasportatore @@ -535,30 +595,29 @@ block.sorter.name = Filtro block.sorter.description = Divide gli oggetti. Se l'oggetto corrisponde a quello selezionato, Può passare. Altrimenti viene espulso sui lati. block.overflow-gate.name = splitter per eccesso block.overflow-gate.description = Una combinazione di un divisore e di un router , che distribuisce sui suoi lati se la via centrale è bloccata. -block.smelter.name = fonderia -block.arc-smelter.name = Fonderia ad arco block.silicon-smelter.name = Fonderia per silicio block.phase-weaver.name = Tessitore di fase block.pulverizer.name = Polverizzatore block.cryofluidmixer.name = Mixer liqidi block.melter.name = Fonditore block.incinerator.name = Inceneritore -block.biomattercompressor.name = Compostore +block.spore-press.name = Spore Press block.separator.name = Separatore -block.centrifuge.name = Centrifugatore block.power-node.name = Snodo energetico block.power-node-large.name = Snodo energetico grande +block.surge-tower.name = Surge Tower block.battery.name = Batteria block.battery-large.name = Batteria grossa block.combustion-generator.name = generatore a carbone block.turbine-generator.name = Turbina +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = Trapano meccanico block.pneumatic-drill.name = Trapano pneumatico block.laser-drill.name = Estrattore laser block.water-extractor.name = Estrattore d'acqua block.cultivator.name = Coltivatore -block.alpha-mech-pad.name = Alpha Mech Pad -block.dart-ship-pad.name = Dart Ship Pad +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = Delta Mech Pad block.javelin-ship-pad.name = Javelin Ship Pad block.trident-ship-pad.name = Trident Ship Pad @@ -583,7 +642,6 @@ block.bridge-conveyor.name = Nastro trasportatore sopraelevato block.plastanium-compressor.name = Compressore al plastanio block.pyratite-mixer.name = Mixer pirite block.blast-mixer.name = Mixer poleri -block.solidifer.name = Solidificatore block.solar-panel.name = Pannello solare block.solar-panel-large.name = Pannrllo solare 3x3 block.oil-extractor.name = Estrattore petrolio @@ -604,7 +662,6 @@ block.liquid-junction.name = Giunzione liquida block.bridge-conduit.name = Condotta sopraelevata block.rotary-pump.name = Pompa a turbina block.thorium-reactor.name = Reattore al torio -block.command-center.name = Centro di comando block.mass-driver.name = Lancia materiali block.blast-drill.name = Blast Drill block.thermal-pump.name = Pompa termica @@ -623,20 +680,21 @@ block.rtg-generator.name = RTG Generator block.spectre.name = Spectre block.meltdown.name = Meltdown block.container.name = Container -block.core.description = The most important building in the game. +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = blue team.red.name = red team.orange.name = orange team.none.name = gray team.green.name = green team.purple.name = purple -unit.alpha-drone.name = Drone Alpha unit.spirit.name = Spirit Drone unit.spirit.description = The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. unit.phantom.name = Phantom Drone unit.phantom.description = An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. unit.dagger.name = Pericolo unit.dagger.description = Un unità terrena base, molto più efficiente se in branco. +unit.crawler.name = Crawler unit.titan.name = Titano unit.titan.description = Un'unità di terra corazzata avanzata. Utilizza carburo come munizione. Attacca sia bersagli terrestri che aerei. unit.ghoul.name = Ghoul Bomber @@ -646,7 +704,11 @@ unit.wraith.description = A fast, hit-and-run interceptor unit. unit.fortress.name = Fortress unit.fortress.description = A heavy artillery ground unit. unit.revenant.name = Revenant -unit.revenant.description = A heavy laser platform. +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = Your mission here is to eradicate the[LIGHT_GRAY] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this. tutorial.drill = Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein. tutorial.conveyor = [accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core. @@ -670,8 +732,6 @@ tutorial.dagger = Link power nodes to the factory.\nOnce requirements are met, a tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. block.copper-wall.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves. block.copper-wall-large.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves.\nSpans multiple tiles. -block.dense-alloy-wall.description = A standard defensive block.\nAdequate protection from enemies. -block.dense-alloy-wall-large.description = A standard defensive block.\nAdequate protection from enemies.\nSpans multiple tiles. block.thorium-wall.description = A strong defensive block.\nGood protection from enemies. block.thorium-wall-large.description = A strong defensive block.\nGood protection from enemies.\nSpans multiple tiles. block.phase-wall.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful. @@ -701,8 +761,6 @@ block.titanium-conveyor.description = Advanced item transport block. Moves items block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles. block.junction.description = Acts as a bridge for two crossing conveyor belts. Useful in situations with two different conveyors carrying different materials to different locations. block.mass-driver.description = Ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. -block.smelter.description = Burns coal for smelting copper and lead into dense alloy. -block.arc-smelter.description = Smelts copper and lead into dense alloy by using an external power source. block.silicon-smelter.description = Reduces sand with highly pure coke in order to produce silicon. block.plastanium-compressor.description = Produces plastanium from oil and titanium. block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. @@ -711,12 +769,10 @@ block.pulverizer.description = Crushes stone into sand. Useful when there is a l block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. block.blast-mixer.description = Uses oil for transforming pyratite into the less flammable but more explosive blast compound. block.cryofluidmixer.description = Combines water and titanium into cryofluid which is much more efficient for cooling. -block.solidifer.description = Cools lava to stone at a fast pace. block.melter.description = Heats up stone to very high temperatures to obtain lava. block.incinerator.description = Gets rid of any excess item or liquid. -block.biomattercompressor.description = Compresses biomatter in order to retrieve oil. +block.spore-press.description = Compresses spore pods into oil. block.separator.description = Exposes stone to water pressure in order to obtain various minerals contained in the stone. -block.centrifuge.description = More efficient than the separator, but also more expensive to build and requires power. block.power-node.description = Transmits power to connected nodes. Up to four power sources, sinks or nodes can be connected. The node will receive power from or supply power to any adjacent blocks. block.power-node-large.description = Has a larger radius than the power node and connects to up to six power sources, sinks or nodes. block.battery.description = Stores power whenever there is an abundance and provides power whenever there is a shortage, as long as there is capacity left. @@ -738,7 +794,6 @@ block.blast-drill.description = The ultimate drill. Requires large amounts of po block.water-extractor.description = Extracts water from the ground. Use it when there is no lake nearby. block.cultivator.description = Cultivates the soil with water in order to obtain biomatter. block.oil-extractor.description = Uses large amounts of power in order to extract oil from sand. Use it when there is no direct source of oil nearby. -block.dart-ship-pad.description = Leave your current vessel and change into a basic fighter aircraft.\nUse the pad by double tapping while standing on it. block.trident-ship-pad.description = Leave your current vessel and change into a reasonably well armored heavy bomber.\nUse the pad by double tapping while standing on it. block.javelin-ship-pad.description = Leave your current vessel and change into a strong and fast interceptor with lightning weapons.\nUse the pad by double tapping while standing on it. block.glaive-ship-pad.description = Leave your current vessel and change into a large, well-armored gunship.\nUse the pad by double tapping while standing on it. @@ -754,7 +809,6 @@ block.titan-factory.description = Produces advanced, armored ground units. block.fortress-factory.description = Produces heavy artillery ground units. block.revenant-factory.description = Produces heavy laser ground units. block.repair-point.description = Continuously heals the closest damaged unit in its vicinity. -block.command-center.description = Allows changing friendly AI behavior. Currently, attack, retreat and patrol commands are supported. block.conduit.description = Basic liquid transport block. Works like a conveyor, but with liquids. Best used with extractors, pumps or other conduits. block.pulse-conduit.description = Advanced liquid transport block. Transports liquids faster and stores more than standard conduits. block.phase-conduit.description = Advanced liquid transport block. Uses power to teleport liquids to a connected phase conduit over several tiles. @@ -768,13 +822,11 @@ block.thermal-pump.description = The ultimate pump. Three times as fast as a mec block.router.description = Accepts items from one direction and outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets. block.distributor.description = An advanced router which splits items to up to 7 other directions equally. block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building. -block.alpha-mech-pad.description = When given enough power, rebuilds your ship into the[accent] Alpha[] mech. block.item-source.description = Infinitely outputs items. Sandbox only. block.liquid-source.description = Infinitely outputs liquids. Sandbox only. block.item-void.description = Destroys any items which go into it without using power. Sandbox only. block.power-source.description = Infinitely outputs power. Sandbox only. block.power-void.description = Voids all power inputted into it. Sandbox only. liquid.water.description = Commonly used for cooling machines and waste processing. -liquid.lava.description = Can be transformed into[LIGHT_GRAY] stone[], used for generating power or used as ammo for certain turrets. liquid.oil.description = Can be burnt, exploded or used as a coolant. liquid.cryofluid.description = The most efficient liquid for cooling things down. diff --git a/core/assets/bundles/bundle_ja.properties b/core/assets/bundles/bundle_ja.properties index 194daffbf4..01781da711 100644 --- a/core/assets/bundles/bundle_ja.properties +++ b/core/assets/bundles/bundle_ja.properties @@ -13,13 +13,16 @@ linkfail = リンクを開けませんでした!\nURLをクリップボードに screenshot = スクリーンショットを {0} に保存しました。 gameover = ゲームオーバー gameover.pvp = [accent] {0}[] チームの勝利! -sector.gameover = この区域は敗北しました。 再配備しますか? -sector.retry = リトライ highscore = [accent]ハイスコアを記録! -wave.lasted = あなたはウェーブ[accent]{0}[]まで続きました。 -level.highscore = ハイスコア: [accent]{0} -level.delete.title = 削除の確認 +stat.wave = Waves Defeated:[accent] {0} +stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} +stat.built = Buildings Built:[accent] {0} +stat.destroyed = Buildings Destroyed:[accent] {0} +stat.deconstructed = Buildings Deconstructed:[accent] {0} +stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = マップ "[accent]{0}[]" を削除してもよろしいですか? +level.highscore = ハイスコア: [accent]{0} level.select = レベル選択 level.mode = ゲームモード: construction.desktop = ブロックの選択や建設を止めるには、[accent]スペースを使用[]してください。 @@ -29,61 +32,36 @@ deconstruction.title = ブロック撤去ガイド deconstruction = [accent]ブロック撤去モード[]になりました。\n\nブロックを撤去するには、機体の近くのブロックをタップしてください。\nブロックを選択した状態で、チェックボタンを押して確認すると、機体がブロックの撤去を始めます。\n\n- [accent]ブロックを撤去[]するには、タップして範囲を選択してください。\n- [accent]範囲を選択してブロックを撤去[]するには、 タップで空いている場所を長押しして、伸ばしたい方向にドラッグしてください\n- [accent]撤去や範囲選択をキャンセル[]するには、左下の X ボタンを押してください。 showagain = 次回以降表示しない coreattack = < コアが攻撃を受けています! > -unlocks = アンロック +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = ゲームを保存 loadgame = ゲームを読み込む joingame = ゲームに参加 addplayers = プレイヤーを追加/削除 customgame = カスタムゲーム -sectors = 区域 -sector = 区域: [LIGHT_GRAY]{0} -sector.time = 時間: [LIGHT_GRAY]{0} -sector.deploy = 配備 -sector.abandon = 撤退 -sector.abandon.confirm = 区域のすべての進行を撤退します。\nこれは元に戻すことはできません! -sector.resume = 再開 -sector.locked = [scarlet][[不完全] -sector.unexplored = [accent][[未調査] -missions = ミッション:[LIGHT_GRAY] {0} -mission = ミッション:[LIGHT_GRAY] {0} -mission.main = メインミッション:[LIGHT_GRAY] {0} -mission.info = ミッション情報 -mission.complete = ミッション完了! -mission.complete.body = 区域 {0},{1} を征服しました。 -mission.wave = 残り[accent] {0}/{1} []ウェーブ\n次のウェーブまで {2} -mission.wave.enemies = 残り[accent] {0}/{1} []ウェーブ\n敵の残り {2} 体 -mission.wave.enemy = 残り[accent] {0}/{1} []ウェーブ\n敵の残り {2} 体 -mission.wave.menu = 残り[accent] {0}[] ウェーブ -mission.battle = 敵のコアを破壊する -mission.resource.menu = {0} を{1}個を入手する -mission.resource = {0} を入手する :\n[accent]{1}/{2}[] -mission.block = {0} を作る -mission.unit = ユニット {0} を作る -mission.command = ユニットに {0} を命令する -mission.linknode = 電源ノードを接続する -mission.display = [accent]ミッション:\n[LIGHT_GRAY]{0} -mission.mech = 機体を[accent]{0}[]に乗り換える -mission.create = [accent]{0}[] を作る +newgame = New Game none = <なし> close = 閉じる quit = 終了 maps = マップ continue = 続ける -nextmission = 次のミッションへ maps.none = [LIGHT_GRAY]マップが存在しません! about.button = About name = 名前: noname = 先に[accent]プレイヤー名[]を決めてください。 filename = ファイル名: unlocked = 新しいブロックをアンロック! -unlocked.plural = 新しいブロックをアンロック! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. players = {0} 人がオンライン players.single = {0} 人がオンライン server.closing = [accent]サーバーを閉じています... server.kicked.kick = サーバからキックされました! server.kicked.serverClose = サーバーが閉じました。 -server.kicked.sectorComplete = 区域を制覇しました。 -server.kicked.sectorComplete.text = ミッションが完了しました。\nサーバーは次の区域に移ります。 server.kicked.clientOutdated = 古いクライアントです! ゲームをアップデートしてください! server.kicked.serverOutdated = 古いサーバーです! ホストに更新してもらってください! server.kicked.banned = サーバーからBanされています。 @@ -92,6 +70,7 @@ server.kicked.nameInUse = このサーバーでは、\nその名前はすでに server.kicked.nameEmpty = 無効な名前です。 server.kicked.idInUse = すでにサーバーに参加しています。! 二つのアカウントでの接続は許可されていません。 server.kicked.customClient = このサーバーはカスタムビルドをサポートしていません。公式版をダウンロードしてください。 +server.kicked.gameover = Game over! host.info = [accent]ホスト[]ボタンを押すと、ポート[scarlet]6567[]でサーバーが開かれます。同じ[LIGHT_GRAY]Wifi や ローカルネットワーク[]からはサーバーリストで見ることができます。\n\nIPアドレスからどこからでもアクセスできるようにするには、[accent]ポート開放[]する必要があります。\n\n[LIGHT_GRAY]注意:: LAN上のゲームで接続できない場合、Mindustryがファイアウォールの設定でローカルネットワークに接続が許可されているか確認してください。 join.info = ここでは、[accent]サーバーのIPアドレス[]から接続したり、[accent]ローカルネットワーク[]のサーバーを探すことができます。\nLANとWANの両方のマルチプレイに対応しています。\n\n[LIGHT_GRAY]注意:グローバルサーバーリストはありません。誰かのサーバーにIPで接続したい場合、ホストにIPをお尋ねください。 hostserver = ゲームをホスト @@ -162,7 +141,6 @@ save.rename.text = 新しい名前: selectslot = セーブデータを選択 slot = [accent]スロット {0} save.corrupted = [accent]セーブファイルが無効、または破損しました!\nゲームのアップデート直後の場合、恐らくセーブデータのフォーマットの変更によるもので、バグではありません。 -sector.corrupted = [accent]区域のセーブファイルが見つかりましたが、読み込みに失敗しました。\n新しく区域がが作成されます。 empty = <空> on = オン off = オフ @@ -172,6 +150,7 @@ save.wave = ウェーブ {0} save.difficulty = 難易度: {0} save.date = 最終保存: {0} save.playtime = プレイ時間: {0} +warning = Warning. confirm = 確認 delete = 削除 ok = OK @@ -207,7 +186,6 @@ map.nospawn = このマップにはスポーンするためのプレイヤーの map.nospawn.pvp = このマップには敵がスポーンするためのプレイヤーのコアがありません! [SCARLET]赤い[]コアをエディターでマップに追加してください。 map.invalid = マップの読み込みエラー: ファイルが無効、または破損しています。 editor.brush = ブラシ -editor.slope = \\ editor.openin = エディターで開く editor.oregen = 鉱石の生成 editor.oregen.info = 鉱石の生成: @@ -262,6 +240,26 @@ tutorial = チュートリアル editor = エディター mapeditor = マップエディター donate = 寄附 +abandon = Abandon +abandon.text = This zone and all its resources will be lost to the enemy. +locked = Locked +complete = [LIGHT_GRAY]Complete: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Best: {0} +launch = Launch +launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson]サーバーへの接続できませんでした:\n\n[accent]{0} error.unreachable = サーバーに到達できません。\nアドレスは正しいですか? error.invalidaddress = 無効なアドレスです。 @@ -269,7 +267,20 @@ error.timedout = タイムアウトしました!\nホストがポート開放さ error.mismatch = パケットエラー:\nクライアント/サーバーのバージョンが一致しません。\nゲームとホストが最新のMindustryか確認してください! error.alreadyconnected = すでに接続されています。 error.mapnotfound = マップファイルが見つかりません! +error.io = Network I/O error. error.any = 不明なネットワークエラーです。 +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = 言語 settings.reset = デフォルトにリセット settings.rebind = 再設定 @@ -280,7 +291,6 @@ settings.graphics = グラフィック settings.cleardata = データを削除... settings.clear.confirm = データを削除してもよろしいですか?\n元に戻すことはできません! settings.clearall.confirm = [scarlet]警告![]\nこれはすべてのデータが削除されます。これにはセーブデータ、マップ、アンロック、キーバインドが含まれます。\n「ok」 を押すと、すべてのデータが削除され、自動的に終了します。 -settings.clearsectors = 区域を削除 settings.clearunlocks = アンロックを削除 settings.clearall = すべてを削除 paused = [accent]< ポーズ > @@ -289,12 +299,15 @@ no = いいえ info.title = 情報 error.title = [crimson]エラーが発生しました error.crashtitle = エラーが発生しました +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = ブロック情報 +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = 電力容量 blocks.powershot = 電力/ショット blocks.targetsair = 対空攻撃 -blocks.itemspeed = 輸送速度 +blocks.itemsmoved = Move Speed blocks.shootrange = 範囲 blocks.size = 大きさ blocks.liquidcapacity = 液体容量 @@ -315,16 +328,23 @@ blocks.inputitems = 必要なアイテム blocks.outputitem = 搬出アイテム blocks.drilltier = ドリル blocks.drillspeed = 基本採掘速度 +blocks.maxunits = Max Active Units blocks.liquidoutput = 搬出液体 blocks.liquidoutputspeed = 液体搬出速度 blocks.liquiduse = 液体使用量 blocks.coolant = 冷却 +blocks.liquid = Liquid blocks.coolantuse = 冷却使用量 blocks.inputliquidfuel = 液体燃料 blocks.liquidfueluse = 液体燃料使用量 blocks.boostitem = 加速アイテム blocks.boostliquid = 加速液体 blocks.health = 耐久値 +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = 精度のずれ blocks.shots = ショット blocks.reload = ショット/秒 @@ -332,11 +352,11 @@ blocks.inputfuel = 燃料 blocks.fuelburntime = 燃焼時間 blocks.inputcapacity = 搬入容量 blocks.outputcapacity = 搬出容量 +blocks.ammo = Ammo unit.blocks = ブロック unit.powersecond = 電力/秒 unit.liquidsecond = 液体/秒 unit.itemssecond = アイテム/秒 -unit.pixelssecond = ピクセル/秒 unit.liquidunits = 液体 unit.powerunits = 電力 unit.degrees = 度 @@ -390,7 +410,8 @@ keybind.screenshot.name = スクリーンショット keybind.move_x.name = 左右移動 keybind.move_y.name = 上下移動 keybind.select.name = 選択/ショット -keybind.break.name = 破壊 +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = 選択解除 keybind.shoot.name = ショット keybind.zoom_hold.name = ズーム長押し @@ -409,8 +430,8 @@ keybind.chat_scroll.name = チャットスクロール keybind.drop_unit.name = ドロップユニット keybind.zoom_minimap.name = ミニマップのズーム mode.help.title = モード説明 -mode.waves.name = ウェーブ -mode.waves.description = 通常モードです。限られた資源の中でウェーブが自動的に進行します。 +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. mode.sandbox.name = サンドボックス mode.sandbox.description = 無限の資源でウェーブを自由に進行できます。 mode.freebuild.name = フリービルド @@ -418,22 +439,19 @@ mode.freebuild.description = 限られた資源の中でウェーブを自由に mode.pvp.name = PvP mode.pvp.description = ローカル内で他のプレイヤーと戦います。 mode.attack.name = アタック -mode.attack.descrption = ウェーブはなく、敵基地の破壊を目指します。 +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = アイテム content.liquid.name = 液体 content.unit.name = ユニット -content.recipe.name = ブロック +content.block.name = Blocks content.mech.name = 機体 -item.stone.name = 石 -item.stone.description = 基本的な原材料です。他の材料を分離したり、精製や溶岩を溶かしたりするのに使用します。 item.copper.name = 銅 item.copper.description = 便利な鉱石です。様々なブロックの材料として幅広く使われています。 item.lead.name = 鉛 item.lead.description = 一般的で手軽な鉱石です。機械や液体輸送ブロックなどに使われます。 item.coal.name = 石炭 item.coal.description = 一般的で有用な燃料です。 -item.dense-alloy.name = 高密度合金 -item.dense-alloy.description = 銅と鉛でできた丈夫な合金です。高性能な輸送ブロックやドリルに使われます。 +item.graphite.name = Graphite item.titanium.name = チタン item.titanium.description = 希少で非常に軽量な金属です。液体輸送やドリル、航空機などで使われます。 item.thorium.name = トリウム @@ -446,16 +464,20 @@ item.phase-fabric.name = フェーズファイバー item.phase-fabric.description = 極めて軽量な素材です。高度な機械や自己修復技術に使用されます。 item.surge-alloy.name = サージ合金 item.surge-alloy.description = 電気的特性を持った特殊な合金です。 -item.biomatter.name = バイオメター -item.biomatter.description = 有機物を含んだ塊です。石油への転換や燃料として使われます。 +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = 砂 item.sand.description = 合金や融剤など広く使用されている一般的な材料です。 item.blast-compound.name = 爆発性化合物 item.blast-compound.description = 爆弾や爆発物に使われる揮発性の化合物です。燃料として燃やすこともできますが、お勧めしません。 item.pyratite.name = ピラタイト item.pyratite.description = 兵器などに使われる非常に燃えやすい物質です。 +item.metaglass.name = Metaglass +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = 水 -liquid.lava.name = 溶岩 +liquid.slag.name = Slag liquid.oil.name = 石油 liquid.cryofluid.name = 冷却水 mech.alpha-mech.name = アルファ @@ -490,11 +512,10 @@ mech.glaive-ship.weapon = 焼夷弾 item.explosiveness = [LIGHT_GRAY]爆発性: {0}% item.flammability = [LIGHT_GRAY]可燃性: {0}% item.radioactivity = [LIGHT_GRAY]放射能: {0}% -item.fluxiness = [LIGHT_GRAY]流動性: {0}% unit.health = [LIGHT_GRAY]耐久値: {0} unit.speed = [LIGHT_GRAY]速度: {0} mech.weapon = [LIGHT_GRAY]武器: {0} -mech.armor = [LIGHT_GRAY]装備: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]アイテム容量: {0} mech.minespeed = [LIGHT_GRAY]採掘速度: {0} mech.minepower = [LIGHT_GRAY]採掘力: {0} @@ -502,29 +523,60 @@ mech.ability = [LIGHT_GRAY]能力: {0} liquid.heatcapacity = [LIGHT_GRAY]熱容量: {0} liquid.viscosity = [LIGHT_GRAY]粘度: {0} liquid.temperature = [LIGHT_GRAY]温度: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](建設中) block.spawn.name = エネミースポーン -block.core.name = コア -block.metalfloor.name = 金属製の床 +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = 深層水 block.water.name = 水 -block.lava.name = 溶岩 block.tar.name = タール -block.blackstone.name = 黒い石 block.stone.name = 石 -block.dirt.name = 土 block.sand.name = 砂 block.ice.name = 氷 block.snow.name = 雪 -block.grass.name = 草 -block.shrub.name = 低木 -block.rock.name = 岩 -block.blackrock.name = 黒い岩 -block.icerock.name = 氷岩 +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = 銅の壁 block.copper-wall-large.name = 大きな銅の壁 -block.dense-alloy-wall.name = 高密度合金の壁 -block.dense-alloy-wall-large.name = 大きな高密度合金の壁 +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = フェーズファイバーの壁 block.phase-wall-large.name = 大きなフェーズファイバーの壁 block.thorium-wall.name = トリウムの壁 @@ -532,7 +584,6 @@ block.thorium-wall-large.name = 大きなトリウムの壁 block.door.name = ドア block.door-large.name = 大きなドア block.duo.name = デュオ -block.scorch.name = スコッチ block.hail.name = ヘイル block.lancer.name = ランサー block.conveyor.name = コンベアー @@ -544,30 +595,29 @@ block.sorter.name = ソーター block.sorter.description = アイテムを分別して搬出します。設定されたアイテムは通過させ、異なるアイテムの場合、左右に搬出します。 block.overflow-gate.name = オーバーフローゲート block.overflow-gate.description = 搬出先がいっぱいの場合に左右にアイテムを搬出します。 -block.smelter.name = 溶鉱炉 -block.arc-smelter.name = 電気式溶鉱炉 block.silicon-smelter.name = シリコン溶鉱炉 block.phase-weaver.name = フェーズ織機 block.pulverizer.name = 粉砕機 block.cryofluidmixer.name = 冷却ミキサー block.melter.name = 融合機 block.incinerator.name = 焼却炉 -block.biomattercompressor.name = バイオメター圧縮機 +block.spore-press.name = Spore Press block.separator.name = 分離機 -block.centrifuge.name = 遠心分離機 block.power-node.name = 電源ノード block.power-node-large.name = 大型電源ノード +block.surge-tower.name = Surge Tower block.battery.name = バッテリー block.battery-large.name = 大型バッテリー block.combustion-generator.name = 火力発電機 block.turbine-generator.name = タービン発電機 +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = 機械ドリル block.pneumatic-drill.name = 空気圧ドリル block.laser-drill.name = レーザードリル block.water-extractor.name = ウォーターポンプ block.cultivator.name = 耕作機 -block.alpha-mech-pad.name = アルファパッド -block.dart-ship-pad.name = ダーツパッド +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = デルタパッド block.javelin-ship-pad.name = ジャベリンパッド block.trident-ship-pad.name = トライデントパッド @@ -592,7 +642,6 @@ block.bridge-conveyor.name = ブリッジコンベアー block.plastanium-compressor.name = プラスタニウム圧縮機 block.pyratite-mixer.name = ピラタイトミキサー block.blast-mixer.name = 化合物ミキサー -block.solidifer.name = 冷却機 block.solar-panel.name = ソーラーパネル block.solar-panel-large.name = 大型ソーラーパネル block.oil-extractor.name = 石油抽出機 @@ -613,7 +662,6 @@ block.liquid-junction.name = 液体ジャンクション block.bridge-conduit.name = ブリッジパイプ block.rotary-pump.name = ロータリーポンプ block.thorium-reactor.name = トリウムリアクター -block.command-center.name = コマンドセンター block.mass-driver.name = マスドライバー block.blast-drill.name = エアブラストドリル block.thermal-pump.name = サーマルポンプ @@ -632,20 +680,21 @@ block.rtg-generator.name = RTG発電機 block.spectre.name = スペクター block.meltdown.name = メルトダウン block.container.name = コンテナー -block.core.description = ゲームで最も重要な建物です。 +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = ブルー team.red.name = レッド team.orange.name = オレンジ team.none.name = グレー team.green.name = グリーン team.purple.name = パープル -unit.alpha-drone.name = アルファドローン unit.spirit.name = スピリットドローン unit.spirit.description = 初期のユニットです。デフォルトでコアからスポーンします。自動で鉱石の採掘やブロックの修理をします。 unit.phantom.name = ファントムドローン unit.phantom.description = 強化されたユニットです。自動で鉱石の採掘やブロックの修理をします。スピリットドローンよりも効率的に行います。 unit.dagger.name = ダガー unit.dagger.description = 一般的な地上ユニットです。集団になると便利です。 +unit.crawler.name = Crawler unit.titan.name = タイタン unit.titan.description = 強化された地上戦闘ユニットです。地上と空の敵の両方に攻撃します。 unit.ghoul.name = グール爆撃機 @@ -655,7 +704,11 @@ unit.wraith.description = 高速な攻撃機ユニットです。 unit.fortress.name = フォートレス unit.fortress.description = 砲撃地上ユニットです。 unit.revenant.name = レベナント -unit.revenant.description = レーザープラットフォームです。 +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = ここでのミッションは[LIGHT_GRAY]敵[]を倒すことです。\n\nまずは、[accent]銅の採掘[]から始めましょう。コアの近くの銅鉱石の鉱脈をタップしましょう。 tutorial.drill = 手動で採掘するのは非効率的です。\n[accent]ドリル[]を使えば自動で採掘できます。\n銅鉱石の鉱脈の上に1つ置いてみましょう。 tutorial.conveyor = [accent]コンベアー[]はコアにアイテムを輸送することができます。\nドリルからコアまでコンベアー作りましょう。 @@ -679,8 +732,6 @@ tutorial.dagger = 電源ノードを生産機に接続しましょう。\n要件 tutorial.battle = [LIGHT_GRAY]敵[]のコアが見つかりました。\nユニットやダガー機で敵の基地を破壊しましょう。 block.copper-wall.description = 安価な防壁ブロックです。\n最初のウェーブでコアやターレットを保護するのに便利です。 block.copper-wall-large.description = 安価な大型防壁ブロックです。\n最初のウェーブでコアやターレットを保護するのに便利です。 -block.dense-alloy-wall.description = 標準的な防壁ブロックです。\n敵からの保護に最適です。 -block.dense-alloy-wall-large.description = 標準的な大型防壁ブロックです。\n敵からの保護に最適です。 block.thorium-wall.description = 強化された防壁ブロックです。\n敵からの保護により強固です。 block.thorium-wall-large.description = 強化された大型防壁ブロックです。\n敵からの保護により強固です。 block.phase-wall.description = トリウムの壁ほど強固ではないが、強力な弾でなければ弾き返すことができます。 @@ -710,8 +761,6 @@ block.titanium-conveyor.description = 改良されたアイテム輸送ブロッ block.phase-conveyor.description = 改良されたアイテム転送ブロックです。電力を使用して、離れた場所にあるフェーズコンベアーにアイテムを転送することができます。 block.junction.description = 十字に交差したコンベアーをそれぞれ前方に搬出します。コンベアーで複雑な構造を組み立てるときに便利です。 block.mass-driver.description = 長距離の輸送が可能なアイテム上位輸送ブロックです。離れた別のマスドライバーにアイテムを発射します。 -block.smelter.description = 石炭を燃やして、銅と鉛から高密度合金を製錬します。 -block.arc-smelter.description = 電力を使用して銅と鉛から高密度合金を製錬します。 block.silicon-smelter.description = 石炭と砂からシリコンを製造します。 block.plastanium-compressor.description = オイルとチタンからプラスタニウムを製造します。 block.phase-weaver.description = 放射性トリウムと多量の砂からフェーズファイバーを作り出します。 @@ -720,12 +769,10 @@ block.pulverizer.description = 石を砕いて砂にします。自然の砂が block.pyratite-mixer.description = 石炭、鉛、砂から燃えやすいピラタイトを製造します。 block.blast-mixer.description = 可燃性のピラタイトを石油を使用してさらに爆発性化合物にします。 block.cryofluidmixer.description = 水とチタンから冷却に効率的な冷却水を製造します。 -block.solidifer.description = 溶岩を急速に冷却し、石を生成します。 block.melter.description = 石を熱で溶かして溶岩を生成します。 block.incinerator.description = 不要なアイテムや液体を焼却します。 -block.biomattercompressor.description = バイオメターを圧縮して、石油を回収します。 +block.spore-press.description = Compresses spore pods into oil. block.separator.description = 石を水圧で砕き、石に含まれる様々な鉱石を回収します。 -block.centrifuge.description = 建設費が高価で電力も必要ですが、分離機よりも効率的に回収できます。 block.power-node.description = 電力ノード間で電力の送電を行います。最大で4つの電力源やノードなどに接続できます。隣接するブロックから電力の送電や供給を行います。 block.power-node-large.description = 巨大な電力ノードです。最大で6つの電力源やノードに接続できます。 block.battery.description = 余分な電力の充電して、貯めておくことができます。必要があれば、溜まった電力を供給します。 @@ -747,7 +794,6 @@ block.blast-drill.description = 高級ドリルです。大量の電力が必要 block.water-extractor.description = 地面から水を汲み上げます。近くに湖がない場合に便利です。 block.cultivator.description = 水で土壌を耕して、バイオメターを回収します。 block.oil-extractor.description = 大量の電力を使用して、砂から石油を回収します。近くに油田がない場合に便利です。 -block.dart-ship-pad.description =  今使っている機体から一般的な戦闘機に乗り換えます。\nパッドに乗って、パッドをダブルタップすることで使用できます。 block.trident-ship-pad.description = 今使っている機体から武装した爆撃機に乗り換えます。\nパッドに乗って、パッドをダブルタップすることで使用できます。 block.javelin-ship-pad.description = 今使っている機体から速くて強い電撃を放つ要撃機に乗り換えます。\nパッドに乗って、パッドをダブルタップすることで使用できます。 block.glaive-ship-pad.description = 今使っている機体から大きく、重武装された攻撃機に乗り換えます。\nパッドに乗って、パッドをダブルタップすることで使用できます。 @@ -763,7 +809,6 @@ block.titan-factory.description = 強化され武装した地上ユニットを block.fortress-factory.description = 地上砲撃ユニットを製造します。 block.revenant-factory.description = 航空レーザーユニットを製造します。 block.repair-point.description = 近くの負傷したユニットを修復します。 -block.command-center.description = 味方のAIの動作を変更できるようにします。現在は攻撃、撤退、巡回に対応しています。 block.conduit.description = 一般的な液体輸送ブロックです。液体版のコンベアーです。ポンプや他のパイプに使うことができます。 block.pulse-conduit.description = 改良された液体輸送ブロックです。通常のパイプより速く、たくさんのアイテムを輸送することができます。 block.phase-conduit.description = 改良された液体転送ブロックです。電力を使用して、液体を他の離れたフューズコンベアーに転送することができます。 @@ -777,13 +822,11 @@ block.thermal-pump.description = 高級ポンプです。機械ポンプより3 block.router.description = 一つの方向から受け取ったアイテムを他の3方向に搬出します。一つの資源から複数に分ける際に便利です。 block.distributor.description = 高度なルーターです。アイテムを7方向に均等に分けて搬出します。 block.bridge-conveyor.description = 高度な輸送ブロックです。地形や建物を超えて、3ブロック離れた場所にアイテムを輸送することができます。 -block.alpha-mech-pad.description = 電力を使用して、機体を[accent]アルファ[]機体に作り替えます。 block.item-source.description = アイテムを無限に搬出します。サンドボックスのみ。 block.liquid-source.description = 液体を無限に搬出します。サンドボックスのみ。 block.item-void.description = 電力なしでアイテムを廃棄します。サンドボックスのみ。 block.power-source.description = 無限に電力を搬出します。サンドボックスのみ。 block.power-void.description = 入力されたすべての電力を破棄します。サンドボックスのみ。 liquid.water.description = 一般的に機械の冷却や廃棄物の処理などに使用されます。 -liquid.lava.description = 冷却して石にしたり、発電や一部ターレットの弾薬として使用することができます。 liquid.oil.description = 燃焼させたり、爆発させたり、冷却水としても使われます。 liquid.cryofluid.description = 冷却させるのに最も効率的な液体です。 diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 535cd8481f..540d31c23d 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -1,96 +1,79 @@ -credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet!) +credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[] credits = 제작자 -discord = Mindustry Discord 에 참여하세요! -link.discord.description = 공식 Mindustry Discord 채팅방 +contributors = 번역 및 기여자들 +discord = mindustry discord 에 참여 해 보세요! +link.discord.description = 공식 mindustry discrod 채팅방 link.github.description = 게임 소스코드 -link.dev-builds.description = 개발중인 빌드 -link.trello.description = 다음 출시될 기능들을 게시한 공식 Trello 보드 +link.dev-builds.description = 불안정한 개발 빌드들 +link.trello.description = 다음 출시될 기능들을 게시판 공식 Trello 보드 link.itch.io.description = PC 버전 다운로드와 HTML5 버전이 있는 itch.io 사이트 link.google-play.description = Google Play 스토어 정보 -link.wiki.description = 공식 Mindustry 위키 (영어) -linkfail = 링크를 여는데 실패했습니다! URL이 기기의 클립보드에 복사되었습니다. -gameover = 코어가 터졌습니다. 게임 오버! +link.wiki.description = 공식 Mindustry 위키 +linkfail = 링크를 여는데 실패했습니다!\nURL이 기기의 클립보드에 복사되었습니다. +screenshot = 화면 캡쳐가 {0} 경로에 저장되었습니다. +gameover = 게임 오버 gameover.pvp = [accent]{0}[] 팀이 승리했습니다! -sector.gameover = 이 지역을 공략하는데 실패했습니다. 다시 시도하시겠습니까? -sector.retry = 아니오 -highscore = [YELLOW]최고점수 달성! -wave.lasted = [accent]{0}[] 까지 버티셨습니다. -level.highscore = 최고 점수 : [accent]{0} -level.delete.title = 삭제 확인 -map.delete = 정말로 "[accent]{0}[]" 맵을 삭제하시겠습니까? +highscore = [accent]최고점수 달성! + +stat.wave = 웨이브 성공:[accent]{0} +stat.enemiesDestroyed = 파괴한 적 수:[accent]{0} +stat.built = 건설한 건물 수:[accent]{0} +stat.destroyed = 파괴된 건물 수:[accent]{0} +stat.deconstructed = 해체한 건물 수:[accent]{0} +stat.delivered = 획득한 자원: +stat.rank = 최종 기록: [accent]{0} + +map.delete = 정말로 "[accent]{0}[]" 맵을 삭제하시겠습니까?\n +level.highscore = 최고 점수: [accent]{0} level.select = 맵 선택 -level.mode = 게임모드 : -construction.desktop = PC 에서의 조작 방법이 변경되었습니다.\n블록 선택을 해제하거나 건설을 중지하려면 [accent]스페이스 바[]를 누르세요. -construction.title = 블록 배치 안내서 +level.mode = 게임 모드 : +construction.desktop = PC 에서의 조작 방법이 변경되었습니다.\n블록 선택을 해제하거나 건설을 중지하려면 [accent]스페이스 바[]를 누르세요.\n +construction.title = PC 에서의 조작 방법이 변경되었습니다. construction = [accent]블록 배치 모드[]를 선택하셨습니다.\n\n블록을 설치하고 싶으면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 배치 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요. \n- [accent]블록을 넓게 배치[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록을 한줄로 배치[]하고 싶다면 배치하고 싶은 시작 영역을 한번 탭 하고 길게 누르면서 드래그 하면 됩니다. \n- [accent]블록 배치 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. -deconstruction.title = 블록 삭제 안내서 -deconstruction = [accent]블록 삭제 모드[]를 선택하셨습니다\n\n블록을 삭제하고 싶다면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 파괴 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요\n- [accent]블록을 넓은 범위로 삭제[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록 삭제 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. +deconstruction.title = 블록 해체 안내서 +deconstruction = [accent]블록 해체 모드[]를 선택하셨습니다\n\n블록을 삭제하고 싶다면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 파괴 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요\n- [accent]블록을 넓은 범위로 삭제[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록 삭제 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. showagain = 다음 세션에서 이 메세지를 표시하지 않습니다 coreattack = < 코어가 공격받고 있습니다! > -unlocks = 아이템들 +nearpoint = [[ [scarlet]드롭 지점에서 나가세요[] ]\n모든 유닛 및 건물 파괴 임박 +outofbounds = [[ 출입 금지 구역 ]\n[]{0}초후 건물이 해체됩니다. +database = 코어 데이터베이스 savegame = 게임 저장 loadgame = 게임 불러오기 joingame = 멀티플레이 addplayers = 플레이어 추가/제거 customgame = 커스텀 게임 -sectors = 지역 플레이 -sector = 지역 : [LIGHT_GRAY]{0} -sector.time = 시간 : [LIGHT_GRAY]{0} -sector.deploy = 시작 -sector.abandon = 초기화 -sector.abandon.confirm = 정말로 이 지역의 모든 진행상황을 초기화 하겠습니까?\n이 작업은 되돌릴 수 없습니다! -sector.resume = 계속하기 -sector.locked = [scarlet][[완료안됨] -sector.unexplored = [accent][[탐색안됨] -missions = 목표 : [LIGHT_GRAY] {0} -mission = 목표 : [LIGHT_GRAY] {0} -mission.main = 주요 목표 : [LIGHT_GRAY]{0} -mission.info = 미션 정보 -mission.complete = 미션 성공! -mission.complete.body = 지역 {0},{1} 클리어. -mission.wave = [accent]{0}/{1}[] 단계 생존\n{2}초 남음 -mission.wave.enemies = [accent]{0}/{1} []단계 생존\n{2}마리 남음 -mission.wave.enemy = [accent]{0}/{1} []단계 생존\n{2}마리 남음 -mission.wave.menu = [accent]{0}[] 단계 -mission.battle = 적 코어를 파괴하세요 -mission.resource.menu = {0} {1}개 수집 -mission.resource = {0} 을(를) 수집하세요\n[accent]{1}/{2} -mission.block = {0} 를 만드세요 -mission.unit = {0} 유닛을 만드세요 -mission.command = 유닛에게 {0} 명령을 보내세요 -mission.linknode = 전력 노드를 연결하세요 -mission.display = [accent]목표 : [LIGHT_GRAY]{0} -mission.mech = [accent]{0}[] 기체로 바꾸세요 -mission.create = [accent]{0}[] 을(를)설치하세요. +newgame = 새 게임 none = <없음> close = 닫기 quit = 나가기 maps = 맵 continue = 계속하기 -nextmission = 다음 임무 maps.none = [LIGHT_GRAY]맵을 찾을 수 없습니다! about.button = 정보 -name = 이름 : -filename = 파일 이름 : +name = 이름 : +noname = 먼저 [accent] 플레이어 이름[] 을 설정하세요. +filename = 파일 이름 : unlocked = 새 블록 잠금 해제됨 -unlocked.plural = 잠금 해제 +completed = [accent]연구됨 +techtree = 기술 트리 +research.list = [LIGHT_GRAY]연구: +research = 연구 +researched = [LIGHT_GRAY]{0}연구됨. players = 현재 {0}명 접속중 players.single = 현재 {0}명만 있음. server.closing = [accent]서버 닫는중... server.kicked.kick = 서버에서 추방되었습니다! server.kicked.serverClose = 서버 종료됨. -server.kicked.sectorComplete = 지역 클리어. -server.kicked.sectorComplete.text = 임무 성공.\n서버가 다음지역 맵으로 이동되었습니다. server.kicked.clientOutdated = 오래된 버전의 클라이언트 입니다! 게임을 업데이트 하세요! server.kicked.serverOutdated = 오래된 버전의 서버입니다! 서버 호스트 관리자에게 문의하세요! -server.kicked.banned = 뭘 하셨는지는 모르겠지만, 이제 영원히 서버에 접속할 수 없습니다. -server.kicked.recentKick = 방금 추방처리 되었습니다.\n잠시 기다린 후에 접속 해 주세요.\n참고 : [accent]계속해서 접속을 시도하면 강퇴 시간이 길어집니다. +server.kicked.banned = 서버 규칙 위반으로 인해, 이제 당신은 영원히 이 서버를 플레이 하실 수 없습니다. +server.kicked.recentKick = 방금 추방처리 되었습니다.\n잠시 기다린 후에 접속 해 주세요. server.kicked.nameInUse = 이 닉네임이 이미 서버에서 사용중입니다. server.kicked.nameEmpty = 닉네임에는 반드시 영어 또는 숫자가 있어야 합니다. server.kicked.idInUse = 이미 서버에 접속중입니다! 다중 계정은 허용되지 않습니다. server.kicked.customClient = 이 서버는 직접 빌드한 버전을 지원하지 않습니다. 공식 버전을 사용하세요. -server.kicked.gameover = 게임 오버로 인해 서버에서 추방되었습니다. -host.info = [accent]호스트[] 버튼은 현재 네트워크의 [scarlet]6567[] 포트를 사용합니다.\n[LIGHY_GRAY]같은 Wi-Fi 또는 로컬 네트워크[] 에서 서버 목록을 볼 수 있습니다.\n\n만약 플레이어들이 이 IP를 통해 어디에서나 연결할 수 있게 하고 싶다면, 공유기 설정에서 [accent]포트 포워딩[]을 해야 합니다.\n\n[LIGHT_GRAY]참고 : LAN 게임 연결에 문제가 있는 사람이 있다면, 방화벽 설정에서 Mindustry 가 로컬 네트워크에 액세스하도록 허용했는지 확인 해 주세요. +server.kicked.gameover = 게임 오버! +host.info = [accent]호스트[] 버튼은 현재 네트워크의 [scarlet]6567[] 포트를 사용합니다.\n[LIGHT_GRAY]같은 Wi-Fi 또는 로컬 네트워크[] 에서 서버 목록을 볼 수 있습니다.\n\n만약 플레이어들이 이 IP를 통해 어디에서나 연결할 수 있게 하고 싶다면, 공유기 설정에서 [accent]포트 포워딩[]을 해야 합니다.\n\n[LIGHT_GRAY]참고: LAN 게임 연결에 문제가 있는 사람이 있다면, 방화벽 설정에서 Mindustry 가 로컬 네트워크에 액세스하도록 허용했는지 확인 해 주세요. join.info = 여기서 [accent]서버 IP[]를 입력하여 다른 서버에 접속할 수 있습니다.\n또는 [accent]로컬 네트워크(LAN)[] 서버를 검색하여 접속할 수 있습니다.\nLAN 및 WAN 멀티 플레이어 모두 지원됩니다.\n\n[LIGHT_GRAY]참고:여기에서는 자동으로 글로벌 서버를 추가하지 않습니다. IP로 다른 사람의 서버에 접속할려면 서버장에게 IP를 요청해야 합니다. hostserver = 서버 열기 hostserver.mobile = 서버\n열기 @@ -102,28 +85,28 @@ server.refreshing = 서버 목록 새로고치는중... hosts.none = [lightgray]LAN 게임을 찾을 수 없습니다! host.invalid = [scarlet]서버에 연결할 수 없습니다! trace = 플레이어 정보 보기 -trace.playername = 이름 : [accent]{0} -trace.ip = IP : [accent]{0} -trace.id = 고유 ID : [accent]{0} -trace.android = Android 클라이언트 : [accent]{0} -trace.modclient = 수정된 클라이언트 : [accent]{0} -trace.totalblocksbroken = 총 블록 파괴 개수 : [accent]{0} -trace.structureblocksbroken = 구조 블록 파괴 수 : [accent]{0} -trace.lastblockbroken = 마지막으로 파괴한 블록 : [accent]{0} -trace.totalblocksplaced = 총 설치한 블록 개수 : [accent]{0} -trace.lastblockplaced = 마지막으로 설치한 블록 : [accent]{0} -invalidid = 잘못된 클라이언트 ID 입니다! 공식 Mindustry Discord 으로 버그 보고서를 제출 해 주세요. +trace.playername = 이름: [accent]{0} +trace.ip = IP: [accent]{0}{0} +trace.id = 고유 ID: [accent]{0} +trace.android = Android 클라이언트: [accent]{0} +trace.modclient = 수정된 클라이언트: [accent]{0} +trace.totalblocksbroken = 총 블록 파괴 개수: [accent]{0} +trace.structureblocksbroken = 구조 블록 파괴 수: [accent]{0} +trace.lastblockbroken = 마지막으로 파괴한 블록: [accent]{0} +trace.totalblocksplaced = 총 설치한 블록 개수: [accent]{0} +trace.lastblockplaced = 마지막으로 설치한 블록: [accent]{0} +invalidid = 잘못된 클라이언트 ID 입니다! 버그 보고서를 제출 해 주세요. server.bans = 차단된 유저 server.bans.none = 차단된 플레이어가 없습니다. server.admins = 관리자 server.admins.none = 관리자가 없습니다! server.add = 서버 추가 server.delete = 이 서버를 삭제 하시겠습니까? -server.hostname = 호스트 : {0} +server.hostname = 호스트: {0} server.edit = 서버 수정 server.outdated = [crimson]서버 버전이 낮습니다![] -server.outdated.client = [Crimson]클라이언트 버전이 낮습니다![] -server.version = [lightgray]서버 버전 : {0} +server.outdated.client = [crimson]클라이언트 버전이 낮습니다![] +server.version = [lightgray]서버 버전: {0} {1} server.custombuild = [yellow]커스텀 서버 confirmban = 이 플레이어를 차단하시겠습니까? confirmkick = 정말로 이 플레이어를 추방시키겠습니까? @@ -131,15 +114,15 @@ confirmunban = 이 플레이어를 차단해제 하시겠습니까? confirmadmin = 이 플레이어를 관리자로 만들겠습니까? confirmunadmin = 이 플레이어를 일반 유저로 만들겠습니까? joingame.title = 게임 참가 -joingame.ip = IP : +joingame.ip = 주소: disconnect = 서버와 연결이 해제되었습니다. -disconnect.data = 맵 데이터를 받아오는데 실패했습니다. +disconnect.data = 맵 데이터를 받아오는데 실패했습니다! connecting = [accent]연결중... connecting.data = [accent]맵 데이터 다운로드중... -server.port = 포트 : +server.port = 포트: server.addressinuse = 이 주소는 이미 사용중입니다! server.invalidport = 포트 번호가 잘못되었습니다. -server.error = [crimson]{0}[accent]서버를 여는데 오류가 발생했습니다.[] +server.error = [accent]{0}[crimson]서버를 여는데 오류가 발생했습니다. save.old = 이 저장파일은 이전 버전의 게임용이며, 지금은 사용할 수 없습니다. \n\n[LIGHT_GRAY]4.0 정식때 이전 게임버전에서 만든 저장파일과 호환됩니다. save.new = 새로 저장 save.overwrite = 이 저장 슬롯을 덮어씌우겠습니까? @@ -151,28 +134,28 @@ save.delete.confirm = 이 저장파일을 삭제 하시겠습니까? save.delete = 삭제 save.export = 저장파일 내보내기 save.import.invalid = [accent]파일이 잘못되었습니다! -save.import.fail = [crimson]저장파일을 불러오지 못함 : [accent]{0} -save.export.fail = [crimson]저장파일을 내보내지 못함 : [accent]{0} +save.import.fail = [crimson]저장파일을 불러오지 못함: [accent]{0} +save.export.fail = [crimson]저장파일을 내보내지 못함: [accent]{0} save.import = 저장파일 불러오기 -save.newslot = 저장 파일이름 : +save.newslot = 저장 파일이름: save.rename = 이름 변경 -save.rename.text = 새 이름 : +save.rename.text = 새 이름: selectslot = 저장슬롯을 선택하십시오. slot = [accent]{0}번째 슬롯 save.corrupted = [accent]세이브 파일이 손상되었거나 잘못된 파일입니다! 만약 게임을 업데이트 했다면 이것은 아마 저장 형식 변경일 것이고, 이것은 버그가 [scarlet]아닙니다[]. -sector.corrupted = [accent]저장 파일에서 지역을 발견했으나 불러오지 못했습니다.\n새로 생성되었습니다. empty = <비어있음> on = 켜기 off = 끄기 -save.autosave = 자동저장 : {0} -save.map = 맵 : {0} -save.wave = {0}단계[] -save.difficulty = 난이도 : {0} -save.date = 마지막 저장날짜 : {0} -save.playtime = 플레이시간 : {0} +save.autosave = 자동저장: {0} +save.map = 맵: {0} +save.wave = 웨이브 {0} +save.difficulty = 난이도: {0} +save.date = 마지막 저장날짜: {0} +save.playtime = 플레이시간: {0} +warning = 경고. confirm = 확인 delete = 삭제 -ok = 확인 +ok = OK open = 열기 cancel = 취소 openlink = 링크 열기 @@ -183,13 +166,13 @@ changelog.title = 변경사항 changelog.loading = 변경사항 가져오는중... changelog.error.android = [accent]게임 변경사항은 가끔 Android 4.4 이하에서 작동하지 않습니다. 이것은 내부 Android 버그 때문입니다. changelog.error.ios = [accent]현재 iOS에서는 변경 사항을 지원하지 않습니다. -changelog.error = [scarlet]게임 변경사항을 가져오는 중 오류가 발생했습니다![]\n인터넷 연결을 확인하십시오. -changelog.current = [accent][[현재 버전] +changelog.error = [scarlet]게임 변경사항을 가져오는 중 오류가 발생했습니다!\n인터넷 연결을 확인하십시오. +changelog.current = [yellow][[현재 버전] changelog.latest = [accent][[최신 버전] loading = [accent]불러오는중... saving = [accent]저장중... -wave = [accent]{0}단계 -wave.waiting = 남은 시간 : [green]{0}초[] +wave = [accent]웨이브 {0} +wave.waiting = [green]{0}초[]후 웨이브 시작 waiting = [LIGHT_GRAY]대기중... waiting.players = 다른 플레이어를 기다리는 중.. wave.enemies = [LIGHT_GRAY]{0} 마리 남았음 @@ -202,17 +185,16 @@ builtin = 기본맵 map.delete.confirm = 이 맵을 삭제하시겠습니까? 이 명령은 취소할 수 없습니다! map.random = [accent]랜덤 맵 map.nospawn = 이 맵에 플레이어가 스폰 할 코어가 없습니다! 맵 편집기에서 [ROYAL]파란색[]코어를 맵에 추가하세요. -map.nospawn.pvp = 이 맵에는 적팀 코어가 없습니다! 에디터에서 [scarlet]빨간팀[] 코어를 추가하세요. +map.nospawn.pvp = 이 맵에는 적팀 코어가 없습니다! 에디터에서 [SCARLET]빨간팀[] 코어를 추가하세요. map.invalid = 파일이 잘못되었거나 손상되어 맵을 열 수 없습니다. editor.brush = 브러쉬 -editor.slope = \\ editor.openin = 편집기 열기 editor.oregen = 광물 무작위 생성 -editor.oregen.info = 광물 무작위 생성 : +editor.oregen.info = 광물 무작위 생성: editor.mapinfo = 맵 정보 -editor.author = 만든이 : -editor.description = 설명 : -editor.name = 이름 : +editor.author = 만든이: +editor.description = 설명: +editor.name = 이름: editor.teams = 팀 editor.elevation = 지형 높이 editor.errorimageload = [accent]{0}[] 파일을 불러오는데 오류가 발생했습니다. @@ -224,7 +206,7 @@ editor.savemap = 맵 저장 editor.saved = 저장됨! editor.save.noname = 지도에 이름이 없습니다! 메뉴 -> '맵 정보' 에서 설정하세요. editor.save.overwrite = 이 맵의 이름은 기존에 있던 맵을 덮어씁니다! '맵 정보' 메뉴에서 다른 이름을 선택하세요. -editor.import.exists = [scarlet]맵을 불러올 수 없음 : [] 기존에 있던 '{0}' 맵이 이미 존재합니다! +editor.import.exists = [scarlet]맵을 불러올 수 없음: [] 기존에 있던 '{0}' 맵이 이미 존재합니다! editor.import = 가져오기 editor.importmap = 맵 가져오기 editor.importmap.description = 이미 존재하는 맵 가져오기 @@ -241,33 +223,70 @@ editor.loadimage = 지형 가져오기 editor.saveimage = 지형 내보내기 editor.unsaved = [scarlet]변경사항을 저장하지 않았습니다![]\n정말로 나가시겠습니까? editor.resizemap = 맵 크기 조정 -editor.mapname = 맵 이름 : +editor.mapname = 맵 이름: editor.overwrite = [accept]경고!이 명령은 기존 맵을 덮어씌우게 됩니다. editor.overwrite.confirm = [scarlet]경고![] 이 이름을 가진 맵이 이미 있습니다. 덮어 쓰시겠습니까? -editor.selectmap = 불러올 맵 선택 : -width = 넓이 : -height = 높이 : +editor.selectmap = 불러올 맵 선택: +width = 넓이: +height = 높이: menu = 메뉴 play = 플레이 load = 불러오기 save = 저장 -fps = {0}FPS -tps = {0}TPS -ping = ping : {0}ms +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0}ms language.restart = 언어를 변경하려면 게임을 다시시작 해 주세요. settings = 설정 tutorial = 게임 방법 editor = 편집기 mapeditor = 맵 편집기 donate = 기부 + +abandon = 버리기 +abandon.text = 이 구역과 모든 자원이 적에게 빼앗길 것입니다. +locked = 잠김 +complete = [LIGHT_GRAY]완료: +resume = 지역 계속 플레이:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]최고 점수: {0} +launch = < 출격 > +launch.title = 출격 성공 +launch.next = [LIGHT_GRAY]다음 출격기회는 {0} 단계에서 나타납니다. +launch.unable = [scarlet]출격할 수 없습니다.[] {0}마리 남음. +launch.confirm = 출격하게 되면 모든 자원이 코어로 들어갑니다.\n또한 성공하기 전까지 기지로 돌아갈 수 없습니다. +uncover = 털어넣기 +configure = 로드아웃 설정 +configure.locked = {0} 단계에서 로드아웃을 설정할 수 있음. +zone.unlocked = [LIGHT_GRAY] 잠금 해제됨. +zone.complete = 지역 조건이 충족됨. +zone.config.complete = 웨이브 {0} 달성:\n로드아웃 설정 잠금 해제됨. +zone.resources = 자원 감지됨: +add = 추가... +boss.health = 보스 체력 + connectfail = [crimson]{0}[accent] 서버에 연결하지 못했습니다.[] -error.unreachable = 서버에 연결하지 못했습니다. +error.unreachable = 서버에 연결하지 못했습니다.\n서버 주소가 정확히 입력되었나요? error.invalidaddress = 잘못된 주소입니다. error.timedout = 시간 초과!\n서버에 포트 포워딩이 설정되어 있고 주소가 올바른지 확인하십시오. error.mismatch = 패킷 오류:\n클라이언트/서버 버전이 일치하지 않습니다.\n접속할려는 서버가 최신 버전의 Mindustry 인지 확인하세요! error.alreadyconnected = 이미 접속중입니다. error.mapnotfound = 맵 파일을 찾을 수 없습니다! +error.io = 네트워크 I/O 오류. error.any = 알 수 없는 네트워크 오류. + +zone.groundZero.name = 그라운드 제로 +zone.craters.name = 분화구 +zone.frozenForest.name = 얼어붙은 숲 +zone.ruinousShores.name = 파멸의 기슭 +zone.crags.name = 바위산 +zone.stainedMountains.name = 얼룩진 산맥 +zone.impact0079.name = 임팩트 0079 +zone.desolateRift.name = 황량한 강 +zone.arcticDesert.name = 북극 사막 +zone.dryWastes.name = 건조한 폐허 +zone.nuclearComplex.name = 핵 생산 단지 +zone.moltenFault.name = 녹은 결점 + settings.language = 언어 settings.reset = 설정 초기화 settings.rebind = 키 재설정 @@ -278,7 +297,6 @@ settings.graphics = 그래픽 settings.cleardata = 게임 데이터 초기화... settings.clear.confirm = 정말로 초기화 하겠습니까?\n이 작업을 되돌릴 수 없습니다! settings.clearall.confirm = [scarlet]경고![]\n이 작업은 저장된 맵, 맵파일, 잠금 해제된 목록과 키 매핑, 그리고 모든 데이터를 삭제합니다.\n확인 버튼을 다시 눌러 모든 데이터를 삭제하고 게임에서 나갑니다. -settings.clearsectors = 지역 초기화 settings.clearunlocks = 잠금 해제 초기화 settings.clearall = 모두 초기화 paused = 일시 정지 @@ -287,54 +305,64 @@ no = 아니오 info.title = [accent]정보 error.title = [crimson]오류가 발생했습니다. error.crashtitle = 오류가 발생했습니다. +blocks.outputspeed = 채광 속도: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = 블록 정보 -blocks.powercapacity = 최대 전력 용량 -blocks.powershot = 1발당 전력 소모량 -blocks.targetsair = 공중공격 가능 -blocks.itemspeed = 유닛 이동 속도 -blocks.shootrange = 사거리 -blocks.size = 블록 크기 -blocks.liquidcapacity = 최대 액체 용량 -blocks.maxitemssecond = 최대 아이템 보관량 -blocks.powerrange = 전력 범위 -blocks.poweruse = 전력 사용 -blocks.powerdamage = 전력/데미지 -blocks.inputitemcapacity = 입력 아이템 용량 -blocks.outputitemcapacity = 출력 아이템 용량 -blocks.itemcapacity = 저장 용량 -blocks.basepowergeneration = 기지 전력 생성기 -blocks.powertransferspeed = 전력 전송량 -blocks.craftspeed = 생산 속도 -blocks.inputliquid = 사용되는 액체 -blocks.inputliquidaux = 보조 액체 -blocks.inputitem = 사용되는 아이템 -blocks.inputitems = 사용되는 아이템들 -blocks.outputitem = 출력 아이템 -blocks.drilltier = 드릴 -blocks.drillspeed = 기본 드릴 속도 -blocks.liquidoutput = 액체 출력 -blocks.liquidoutputspeed = 액체 출력속도 -blocks.liquiduse = 액체 사용량 -blocks.coolant = 냉각제 -blocks.coolantuse = 냉각수 사용 -blocks.inputliquidfuel = 연료 액 -blocks.liquidfueluse = 액체 연료 사용 +blocks.powerbalance = 전력: {0} +blocks.poweroutput = 전력 출력: {0} +blocks.powercapacity = 전력 용량 +blocks.powershot = 1발당 전력 소모량 +blocks.targetsair = 공중공격 가능 +blocks.itemsmoved = 이동 속도 +blocks.shootrange = 사거리 +blocks.size = 크기 +blocks.liquidcapacity = 액체 용량 +blocks.maxitemssecond = 아이템 보관량 +blocks.powerrange = 전력 범위 +blocks.poweruse = 전력 사용 +blocks.powerdamage = 전력/데미지 +blocks.inputitemcapacity = 입력 아이템 용량 +blocks.outputitemcapacity = 출력 아이템 용량 +blocks.itemcapacity = 저장 용량 +blocks.basepowergeneration = 기지 전력 생성기 +blocks.powertransferspeed = 전력 전송량 +blocks.craftspeed = 생산 속도 +blocks.inputliquid = 사용되는 액체 +blocks.inputliquidaux = 보조 액체 +blocks.inputitem = 사용되는 아이템 +blocks.inputitems = 사용되는 아이템들 +blocks.outputitem = 출력 아이템 +blocks.drilltier = 드릴 +blocks.drillspeed = 기본 드릴 속도 +blocks.maxunits = 최대 활성유닛 +blocks.liquidoutput = 액체 출력 +blocks.liquidoutputspeed = 액체 출력속도 +blocks.liquiduse = 액체 사용량 +blocks.coolant = 냉각제 +blocks.liquid = 액체 +blocks.coolantuse = 냉각제 사용 +blocks.inputliquidfuel = 연료 액 +blocks.liquidfueluse = 액체 연료 사용 blocks.boostitem = 가속 아이템 blocks.boostliquid = 가속 액체 -blocks.health = 체력 -blocks.inaccuracy = 오차각 -blocks.shots = 발포 횟수 -blocks.reload = 재장전 -blocks.inputfuel = 연료 -blocks.fuelburntime = 연료 연소 시간 -blocks.inputcapacity = 입력 용량 -blocks.outputcapacity = 출력 용량 +blocks.health = 체력 +blocks.heat = 발열 +blocks.power = 전력 +blocks.progress = 건설 진행 +blocks.spawned = 유닛: {0}/{1} +blocks.power.satisfaction = 전력 만족도 +blocks.inaccuracy = 오차각 +blocks.shots = 발포 횟수 +blocks.reload = 재장전 +blocks.inputfuel = 연료 +blocks.fuelburntime = 연료 연소 시간 +blocks.inputcapacity = 입력 용량 +blocks.outputcapacity = 출력 용량 +blocks.ammo = 탄약 unit.blocks = 블록 unit.powersecond = 전력/초 unit.liquidsecond = 액체/초 unit.itemssecond = 개/초 -unit.pixelssecond = 초당 픽셀 unit.liquidunits = 액체 unit.powerunits = 전력 unit.degrees = 도 @@ -346,22 +374,24 @@ category.liquids = 액체 category.items = 아이템 category.crafting = 제작 category.shooting = 사격 -category.optional = 선택적 가속 +category.optional = 보조 아이템 +setting.animatedwater.name = 움직이는 물 +setting.indicators.name = 인디게이터 표시 setting.autotarget.name = 자동 조준 setting.fpscap.name = 최대 FPS setting.fpscap.none = 없음 -setting.fpscap.text = {0} FPS +setting.fpscap.text = FPS setting.difficulty.training = 훈련 setting.difficulty.easy = 쉬움 setting.difficulty.normal = 보통 setting.difficulty.hard = 어려움 -setting.difficulty.insane = [#00ff00]멀[#2efe2e]티[#58fa58]플[#81f781]레[#a9f5a9]이 [#81f781]전[#58fa58]용[] -setting.difficulty.name = 난이도 : -setting.screenshake.name = 화면 흔들기 강도 +setting.difficulty.insane = 매우 어려움 +setting.difficulty.name = 난이도: +setting.screenshake.name = 화면 흔들기 setting.effects.name = 화면 효과 setting.sensitivity.name = 컨트롤러 감도 -setting.saveinterval.name = 자동저장 간격 -setting.seconds = {0}초 +setting.saveinterval.name = 자동저장 간격 +setting.seconds = 초 setting.fullscreen.name = 전체 화면 setting.fps.name = FPS 표시 setting.vsync.name = VSync 활성화 @@ -383,13 +413,15 @@ keybind.gridMode.name = 블록 선택 keybind.gridModeShift.name = 카테고리 선택 keybind.press = 키를 누르세요... keybind.press.axis = 축 또는 키를 누르세요... +keybind.screenshot.name = 맵 스크린샷 keybind.move_x.name = 오른쪽/왼쪽 이동 -keybind.move_y.name = 위쪽/아래쪽 이동 +keybind.move_y.name = 위 / 아래 중간 keybind.select.name = 선택 -keybind.break.name = 파괴 +keybind.pick.name = 블록 선택 +keybind.break_block.name = 블록 파괴 keybind.deselect.name = 선택해제 keybind.shoot.name = 사격 -keybind.zoom_hold.name = 길게눌러 확대 +keybind.zoom_hold.name = 길게 확대 keybind.zoom.name = 확대 keybind.menu.name = 메뉴 keybind.pause.name = 일시중지 @@ -404,54 +436,57 @@ keybind.chat_history_next.name = 다음 채팅기록 keybind.chat_scroll.name = 채팅 스크롤 keybind.drop_unit.name = 유닛 드롭 keybind.zoom_minimap.name = 미니맵 확대 -mode.help.title = 도움말 -mode.waves.name = 단계 -mode.waves.description = 이것은 일반 모드입니다. 제한된 자원과 자동으로 다음 단계가 시작됩니다. +mode.help.title = 모드 도움말 +mode.survival.name = 생존 +mode.survival.description = 이것은 일반 모드입니다. 제한된 자원을 가지고 자동으로 다음 단계가 시작됩니다. mode.sandbox.name = 샌드박스 -mode.sandbox.description = 무한한 자원과 다음단계 시작을 위한 타이머가 없습니다. +mode.sandbox.description = 무한한 자원을 가지고 자유롭게 다음 단계를 시작할 수 있습니다. mode.freebuild.name = 자유 건축 -mode.freebuild.description = 제한된 자원과 다음단계 시작을 위한 타이머가 없습니다. +mode.freebuild.description = 제한된 자원을 가지고 다음 단계를 시작할 수 있습니다. mode.pvp.name = PvP -mode.pvp.description = 몹이 아닌 실제 플레이어와 PvP를 합니다. +mode.pvp.description = 실제 플레이어와 PvP를 합니다. +mode.attack.name = 공격 +mode.attack.description = 일정 시간마다 적이 오는 단계가 없으며, 적의 기지를 파괴하는 것을 목표로 합니다. content.item.name = 아이템 content.liquid.name = 액체 content.unit.name = 유닛 -content.recipe.name = 블록 +content.block.name = 블록 content.mech.name = 기체 -item.stone.name = 돌 -item.stone.description = 주로 용암을 사용하여 얻을 수 있는 자원입니다. item.copper.name = 구리 item.copper.description = 모든 종류의 블록에서 광범위하게 사용되는 자원입니다. item.lead.name = 납 item.lead.description = 쉽게 구할 수 있으며, 전자 및 액체 수송 블록에서 광범위하게 사용되는 자원입니다. item.coal.name = 석탄 -item.coal.description = 쉽게 구할 수 있으며, 주로 제련소 등에서 연료로 사용됩니다. -item.dense-alloy.name = 고밀도 합금 -item.dense-alloy.description = 납과 구리로 만든 튼튼한 고밀도 합금.\n고급 수송 블록이나 상위 티어 블록을 건설하는데 사용됩니다. +item.coal.description = 흔하고 쉽게 구할 수 있는 연료. +item.graphite.name = 흑연 item.titanium.name = 티타늄 item.titanium.description = 파이프 재료나 고급 드릴, 비행기/기체 등에서 재료로 사용되는 자원입니다. item.thorium.name = 토륨 -item.thorium.description = 건물의 재료, 포탑의 탄약 또는 핵연료로 사용되는 방사성 금속입니다. +item.thorium.description = 건물의 재료, 터렛의 탄약 또는 핵연료로 사용되는 방사성 금속입니다. item.silicon.name = 실리콘 item.silicon.description = 매우 유용한 반도체로, 기체를 만들거나 태양 전지판 등 전자 건물에 사용할 수 있습니다. item.plastanium.name = 플라스터늄 item.plastanium.description = 고급 항공기 및 분열 탄약에 사용되는 가벼운 연성 재료. -item.phase-fabric.name = 메타 +item.phase-fabric.name = 위상 패브릭 item.phase-fabric.description = 최첨단 전자 제품과 자기수리 기술에 사용되는 거의 무중력에 가까운 물질입니다. -item.surge-alloy.name = 설금 +item.surge-alloy.name = 서지 합금 item.surge-alloy.description = 독특한 전기 특성을 가진 고급 합금입니다. -item.biomatter.name = 바이오메터 -item.biomatter.description = 이것은 유기농 덤불입니다!\n압축기에 넣어 석유로 바꿀 수 있습니다. +item.spore-pod.name = 포자 포드 +item.spore-pod.description = 석유, 폭발물 및 연료로 전환하는데 사용됩니다. item.sand.name = 모래 item.sand.description = 고밀도 합금 제작이나 제련시 이 광물을 사용하여 소모 재료를 줄이는 등 광범위하게 사용되는 일반적인 재료입니다. -item.blast-compound.name = 폭발물 -item.blast-compound.description = 포탑 및 건설의 재료로 사용되는 휘발성 폭발물.\n연료로도 사용할 수 있지만, 별로 추천하지는 않습니다. -item.pyratite.name = 피라테 -item.pyratite.description = 폭발성을 가진 재료로, 주로 포탑의 탄약으로 사용됩니다. +item.blast-compound.name = 폭발 화합물 +item.blast-compound.description = 터렛 및 건설의 재료로 사용되는 휘발성 폭발물.\n연료로도 사용할 수 있지만, 별로 추천하지는 않습니다. +item.pyratite.name = 피라타이트 +item.pyratite.description = 폭발성을 가진 재료로, 주로 터렛의 탄약으로 사용됩니다. +item.metaglass.name = 메타유리 +item.metaglass.description = 초강력 유리 화합물. 액체 분배 및 저장에 광범위하게 사용됩니다. +item.scrap.name = 조각 +item.scrap.description = 오래된 건물과 유닛의 남은 잔해. 미량의 많은 금속이 포함되어 있습니다. liquid.water.name = 물 -liquid.lava.name = 용암 +liquid.slag.name = 광재 liquid.oil.name = 석유 -liquid.cryofluid.name = 냉각수 +liquid.cryofluid.name = 냉각유체 mech.alpha-mech.name = 알파 mech.alpha-mech.weapon = 중무장 소총 mech.alpha-mech.ability = 드론 소환 @@ -471,7 +506,7 @@ mech.omega-mech.description = 지상 기체 최종판이자 건물 파괴용으 mech.dart-ship.name = 다트 mech.dart-ship.weapon = 소총 mech.dart-ship.description = 표준 비행선.\n빠르고 가볍지만 공격력이 거의 없고 채광 속도가 느립니다. -mech.javelin-ship.name = 자비린 +mech.javelin-ship.name = 재블린 mech.javelin-ship.description = 치고 빠지는 공격을 위한 비행선.\n처음에는 느리지만, 가속도가 붙어 엄청난 속도로 미사일 피해를 입힐 수 있으며, 전격 능력을 사용할 수 있습니다. mech.javelin-ship.weapon = 유도 미사일 mech.javelin-ship.ability = 가속 전격 생성기 @@ -481,52 +516,81 @@ mech.trident-ship.weapon = 폭탄 저장고 mech.glaive-ship.name = 글레브 mech.glaive-ship.description = 크고 잘 무장된 총을 가진 비행선.\n방화용 리피터가 장착되어 있으며, 가속도와 최대속도가 높습니다. mech.glaive-ship.weapon = 방화총 -item.explosiveness = [LIGHT_GRAY]폭발성 : {0} -item.flammability = [LIGHT_GRAY]인화성 : {0} -item.radioactivity = [LIGHT_GRAY]방사능 : {0} -item.fluxiness = [LIGHT_GRAY]유동성 : {0} -unit.health = [LIGHT_GRAY]체력 : {0} -unit.speed = [LIGHT_GRAY]속도 : {0} -mech.weapon = [LIGHT_GRAY]무기 : {0} -mech.armor = [LIGHT_GRAY]방어력 : {0} -mech.itemcapacity = [LIGHT_GRAY]아이템 수용 용량 : {0} -mech.minespeed = [LIGHT_GRAY]채광 속도 : {0} -mech.minepower = [LIGHT_GRAY]채광 레벨 : {0} -mech.ability = [LIGHT_GRAY]능력 : {0} -liquid.heatcapacity = [LIGHT_GRAY]발열량 : {0} -liquid.viscosity = [LIGHT_GRAY]점도 : {0} -liquid.temperature = [LIGHT_GRAY]온도 : {0} -block.constructing = {0}[LIGHT_GRAY](만드는중) +item.explosiveness = [LIGHT_GRAY]폭발성: {0} +item.flammability = [LIGHT_GRAY]인화성: {0} +item.radioactivity = [LIGHT_GRAY]방사능: {0} +unit.health = [LIGHT_GRAY]체력: {0} +unit.speed = [LIGHT_GRAY]속도: {0} +mech.weapon = [LIGHT_GRAY]무기: {0} +mech.health = [LIGHT_GRAY]체력: {0} +mech.itemcapacity = [LIGHT_GRAY]아이템 수용 용량: {0} +mech.minespeed = [LIGHT_GRAY]채광 속도: {0} +mech.minepower = [LIGHT_GRAY]채광 레벨: {0} +mech.ability = [LIGHT_GRAY]능력: {0} +liquid.heatcapacity = [LIGHT_GRAY]발열 용량: {0} +liquid.viscosity = [LIGHT_GRAY]점도: {0} +liquid.temperature = [LIGHT_GRAY]온도: {0} +block.scrap-wall.name = 조각벽 +block.scrap-wall-large.name = 큰 조각벽 +block.scrap-wall-huge.name = 거대한 조각 벽 +block.scrap-wall-gigantic.name = 엄청나게 큰 조각 벽 +block.thruster.name = 트릭스터 +block.kiln.name = 가마 +block.kiln.description = 모래를 녹여서 메타유리로 만듭니다. 소량의 전력이 필요합니다. +block.graphite-press.name = 흑연 압축기 +block.multi-press.name = 다중 압축기 +block.constructing = {0} [LIGHT_GRAY](만드는중) block.spawn.name = 적 스폰지점 -block.core.name = 코어 -block.metalfloor.name = 철판 +block.core-shard.name = 코어: 공유 +block.core-foundation.name = 코어: 기초 +block.core-nucleus.name = 코어: 핵 block.deepwater.name = 깊은물 block.water.name = 물 -block.lava.name = 용암 block.tar.name = 타르 -block.blackstone.name = 검은돌 block.stone.name = 돌 -block.dirt.name = 흙 block.sand.name = 모래 block.ice.name = 얼음 block.snow.name = 눈 -block.grass.name = 잔디 -block.shrub.name = 관목 -block.rock.name = 바위 -block.blackrock.name = 검은바위 -block.icerock.name = 얼음바위 +block.craters.name = 크레이터 +block.sand-water.name = 젖은모래 +block.char.name = 숯 +block.holostone.name = 홀로스톤 +block.ice-snow.name = 얼음눈 +block.rocks.name = 돌 +block.icerocks.name = 얼음바위 +block.snowrocks.name = 눈바위 +block.dunerocks.name = 모래돌 +block.pine.name = 소나무 +block.white-tree-dead.name = 죽은 하얀나무 +block.white-tree.name = 하얀 나무 +block.spore-cluster.name = 포자낭 +block.stained-rocks.name = 얼룩진 바위 +block.stained-stone.name = 얼룩진 돌 +block.stained-rocks-red.name = 얼룩진 빨간 바위 +block.stained-stone-red.name = 얼룩진 빨간 돌 +block.stained-rocks-yellow.name = 얼룩진 노란 바위 +block.stained-stone-yellow.name = 얼룩진 노란 돌 +block.stained-boulder.name = 얼룩진 둥근 돌 +block.metal-floor.name = 메탈 바닥 +block.metal-floor-2.name = 메탈 바닥 2 +block.metal-floor-3.name = 메탈 바닥 3 +block.metal-floor-5.name = 메탈 바닥 5 +block.metal-floor-damaged.name = 손상된 메탈 바닥 +block.ignarock.name = 얼은 바위 +block.hotrock.name = 뜨거운 바위 +block.magmarock.name = 마그마 바위 +block.cliffs.name = 절벽 block.copper-wall.name = 구리벽 block.copper-wall-large.name = 큰 구리벽 -block.dense-alloy-wall.name = 합금 벽 -block.dense-alloy-wall-large.name = 큰 합금 벽 -block.phase-wall.name = 메타벽 -block.phase-wall-large.name = 큰 메타벽 +block.titanium-wall.name = 티타늄 벽 +block.titanium-wall-large.name = 대형 티타늄 벽 +block.phase-wall.name = 상직물벽 +block.phase-wall-large.name = 큰 상직물벽 block.thorium-wall.name = 토륨벽 block.thorium-wall-large.name = 대형 토륨벽 block.door.name = 문 block.door-large.name = 대형문 block.duo.name = 듀오 -block.scorch.name = 스코치 block.hail.name = 헤일 block.lancer.name = 랜서 block.conveyor.name = 컨베이어 @@ -538,32 +602,31 @@ block.sorter.name = 필터 block.sorter.description = 아이템을 넣어서 필터에 설정된 아이템일 경우 바로 앞으로 통과하며, 그렇지 않을 경우 옆으로 통과합니다. block.overflow-gate.name = 오버플로 게이트 block.overflow-gate.description = 정면으로 가는 자원이 막히면 옆으로 출력하고, 그렇지 않으면 계속 정면으로 출력합니다. -block.smelter.name = 제련소 -block.arc-smelter.name = 대형 제련소 block.silicon-smelter.name = 실리콘 제련소 -block.phase-weaver.name = 메타 합성기 +block.phase-weaver.name = 상직물 합성기 block.pulverizer.name = 분쇄기 block.cryofluidmixer.name = 냉각수 제조기 block.melter.name = 융해기 block.incinerator.name = 소각로 -block.biomattercompressor.name = 바이오메터 압축기 +block.spore-press.name = 포자 압축기 block.separator.name = 셉터 -block.centrifuge.name = 원심 분리기 -block.power-node.name = 전력 송신기 -block.power-node-large.name = 대형 전력 송신기 +block.power-node.name = 전력 노드 +block.power-node-large.name = 대형 전력 노드 +block.surge-tower.name = 서지 합금 타워 block.battery.name = 배터리 block.battery-large.name = 대형 배터리 -block.combustion-generator.name = 석탄 발전기 +block.combustion-generator.name = 화력 발전기 block.turbine-generator.name = 터빈 발전기 -block.mechanical-drill.name = 기계식 드릴 +block.differential-generator.name = 차동 발전기 +block.impact-reactor.name = 충격 반응기 +block.mechanical-drill.name = 기계 드릴 block.pneumatic-drill.name = 강철 드릴 block.laser-drill.name = 레이저 드릴 block.water-extractor.name = 물 추출기 block.cultivator.name = 온실 -block.alpha-mech-pad.name = 알파 기체 패드 -block.dart-ship-pad.name = 다트 비행선 패드 +block.alpha-dart-mech-pad.name = 알파-다트 기체 패드 block.delta-mech-pad.name = 델타 기체 패드 -block.javelin-ship-pad.name = 자비린 비행선 패드 +block.javelin-ship-pad.name = 재블린 비행선 패드 block.trident-ship-pad.name = 삼지창 비행선 패드 block.glaive-ship-pad.name = 글레브 비행선 패드 block.omega-mech-pad.name = 오메가 기체 패드 @@ -581,12 +644,11 @@ block.wave.name = 파도 block.swarmer.name = 스웜 block.salvo.name = 살보 block.ripple.name = 립플 -block.phase-conveyor.name = 메타 컨베이어 -block.bridge-conveyor.name = 터널 +block.phase-conveyor.name = 위상 컨베이어 +block.bridge-conveyor.name = 터널 컨베이어 block.plastanium-compressor.name = 플라스터늄 압축기 -block.pyratite-mixer.name = 피라테 제조기 -block.blast-mixer.name = 폭발물 제조기 -block.solidifer.name = 고체 +block.pyratite-mixer.name = 피라타이트 혼합기 +block.blast-mixer.name = 폭발물 혼합기 block.solar-panel.name = 태양 전지판 block.solar-panel-large.name = 대형 태양 전지판 block.oil-extractor.name = 석유 추출기 @@ -598,47 +660,48 @@ block.dagger-factory.name = 디거 기체 공장 block.titan-factory.name = 타이탄 기체 공장 block.fortress-factory.name = 포트리스 기체 공장 block.revenant-factory.name = 레비던트 전투기 공장 -block.repair-point.name = 정비소 +block.repair-point.name = 수리 지점 block.pulse-conduit.name = 퓨즈 파이프 -block.phase-conduit.name = 메타 파이프 +block.phase-conduit.name = 상직물 파이프 block.liquid-router.name = 액체 분배기 block.liquid-tank.name = 물탱크 block.liquid-junction.name = 액체 교차기 block.bridge-conduit.name = 다리 파이프 block.rotary-pump.name = 동력 펌프 block.thorium-reactor.name = 토륨 원자로 -block.command-center.name = 명령 본부 -block.mass-driver.name = 자원 발사기 -block.blast-drill.name = 고속 발열 드릴 +block.mass-driver.name = 매스 드라이버 +block.blast-drill.name = 압축 공기분사 드릴 block.thermal-pump.name = 화력 펌프 block.thermal-generator.name = 열발전기 -block.alloy-smelter.name = 설금 제련소 +block.alloy-smelter.name = 서지 합금 제련소 block.mend-projector.name = 수리 프로젝터 -block.surge-wall.name = 설금벽 -block.surge-wall-large.name = 큰 설금벽 +block.surge-wall.name = 서지 합금벽 +block.surge-wall-large.name = 큰 서지 합금벽 block.cyclone.name = 사이클론 block.fuse.name = 퓨즈 block.shock-mine.name = 전격 지뢰 block.overdrive-projector.name = 오버드라이브 프로젝터 block.force-projector.name = 보호막 프로젝터 block.arc.name = 아크 -block.rtg-generator.name = 토륨 발전소 +block.rtg-generator.name = RTG 발전기 block.spectre.name = 스펙터 block.meltdown.name = 멜트다운 block.container.name = 컨테이너 +block.launch-pad.name = 발사대 +block.launch-pad.description = 출격할 필요 없이 아이템을 수송시킵시다. 미완성. team.blue.name = 블루팀 team.red.name = 레드팀 team.orange.name = 오렌지팀 team.none.name = 공기팀 team.green.name = 그린팀 team.purple.name = 보라색팀 -unit.alpha-drone.name = 알파 드론 unit.spirit.name = 스피릿 드론 unit.spirit.description = 기본 드론 유닛. 기본적으로 코어에서 1개가 스폰됩니다.\n자동으로 채광하며 아이템을 수집하고, 블록을 수리합니다. unit.phantom.name = 팬텀 드론 unit.phantom.description = 첨단 드론 유닛.\n광석을 자동으로 채광하며, 아이템을 수집하고 블록을 수리합니다. 일반 드론보다 훨씬 효과적입니다. unit.dagger.name = 디거 unit.dagger.description = 기본 지상 유닛입니다.\n플레이어 기체처럼 드론을 소환하지는 않습니다. +unit.crawler.name = 크롤러 unit.titan.name = 타이탄 unit.titan.description = 고급 지상 유닛입니다.\n원거리 총 대신에 근접 화염 방사기를 가지고 있으며, 지상과 공중 둘다 공격할 수 있습니다. unit.ghoul.name = 구울 폭격기 @@ -648,7 +711,11 @@ unit.wraith.description = 적 핵심 건물 및 유닛을 집중적으로 공격 unit.fortress.name = 포트리스 unit.fortress.description = 중포 지상 유닛.\n높은 공격력을 가진 총과 높은 체력을 가지고 있습니다. unit.revenant.name = 레비던트 -unit.revenant.description = 튼튼하고 강력한 대형 레이저를 발사하는 공중 유닛입니다. +unit.eruptor.name = 이어럽터 +unit.chaos-array.name = 카오스 배열 +unit.eradicator.name = 박멸 +unit.lich.name = 리치 +unit.reaper.name = 사신 tutorial.begin = 플레이어의 주요 목표는 [LIGHT_GRAY]적군[]을 제거하는 것입니다.\n\n이 게임은 [accent]구리를 채광[]하는 것으로 시작합니다.\n이것을 하기 위해 플레이어의 중심부 근처에 있는 구리 광맥을 누르세요. tutorial.drill = 수동으로 채광하는 것은 효율이 낮습니다.\n[accent]드릴[]은 자동으로 채광 작업을 합니다.\n구리 광맥에 표시된 영역에 드릴을 하나를 놓으세요. tutorial.conveyor = [accent]컨베이어[]를 사용하여 아이템을 코어로 운반합니다.\n드릴에서 코어까지 컨베이어 라인을 만드세요. @@ -663,123 +730,110 @@ tutorial.siliconsmelter = 이제 이코어는 채굴과 수리하기 위한[acce tutorial.silicondrill = 실리콘을 제작하려면[accent] 석탄[] 과[accent] 모래[]가 필요합니다.\n드릴을 먼저 건설해보는건 어떤가요? tutorial.generator = 이 건물은 [LIGHT_YELLOW]전력[]이 필요합니다.\n[accent] 석탄 발전기[]를 건설하세요. tutorial.generatordrill = [accent] 석탄 발전기[]는 연료가 필요합니다.\n[accent] 석탄[]을 드릴로 채굴해서 연료를 체워주세요. -tutorial.node = 전력은 송신해줄 송신기가 필요합니다.\n[accent] 전력 송신기[]를 석탄 등등 발전기 옆에 설치해서 생산된 전기를 다른곳으로 송신합시다. -tutorial.nodelink = 전력은 전력 블록과 발전기에 연결하거나, 연결된 전력 송신기를 통해 전송이 가능합니다. \n\n전력 송신기를 누르고 발전기와 실리콘 제련기를 선택하여 전원을 연결합시다. +tutorial.node = 전력은 송신해줄 노드가 필요합니다.\n[accent] 전력 노드[]를 석탄 등등 발전기 옆에 설치해서 생산된 전기를 다른곳으로 송신합시다. +tutorial.nodelink = 전력은 전력 블록과 발전기에 연결하거나, 연결된 전력 노드를 통해 전송이 가능합니다. \n\n전력 노드를 누르고 발전기와 실리콘 제련기를 선택하여 전원을 연결합시다. tutorial.silicon = 실리콘이 생산되고 있습니다.\n\n생산 시스템의 개선을 권고 드립니다. tutorial.daggerfactory = 이[accent] 디거 기체 공장[]은\n\n공격하는 기체를 생산하기 위해 사용됩니다. tutorial.router = 공장을 작동시키기 위해 자원이 필요합니다.\n컨베이어에 운반되고 있는 자원을 분할할 분배기를 만드세요. tutorial.dagger = 전력 노드를 공장에 연결하세요.\n일단 요구 사항이 충족되면 기체 생산을 시작합니다.\n\n필요에 따라 드릴 및 발전기, 컨베이어를 더 많이 만들 수 있습니다. tutorial.battle = [LIGHT_GRAY]적[]의 코어가 드러났습니다.\n당신의 부대와 디거를 사용하여 파괴하세요. -block.core.description = 게임에서 가장 중요한 건물.\n코어가 1개밖에 없을때 파괴되면 게임에서 패배합니다. -block.copper-wall.description = 구리로 만든 방어벽.\n가장 약한 방어벽입니다. -block.copper-wall-large.description = 구리로 만든 큰 방어벽.\n일반 구리벽의 4개를 합쳐놓은 벽이며, 가장 약한 방어벽입니다. -block.dense-alloy-wall.description = 고밀도 합금으로 만든 방어벽.\n구리벽보다 체력이 높습니다. -block.dense-alloy-wall-large.description = 고밀도 합금으로 만든 큰 방어벽.\n일반 고밀도 합금 벽을 4개 합쳐놓은 벽이며, 내구성이 좋습니다. -block.thorium-wall.description = 토륨으로 만든 방어벽.\n아무 기능이 없는 튼튼한 방어벽입니다. -block.thorium-wall-large.description = 토륨으로 만든 큰 방어벽.\n토륨벽을 4개 합쳐놓은 벽이며, 내구성이 뛰어납니다. -block.phase-wall.description = 메타로 제작하는 방어벽.날라오는 모든 총알을 튕겨내고 데미지를 입는 특수한 벽입니다. -block.phase-wall-large.description = 메타로 제작한 큰 방어벽.\n날라오는 총알을 모두 튕겨냅니다. -block.surge-wall.description = 데미지를 입으면 번개를 일으켜 대상에게 피해를 입히는 특수한 벽입니다. -block.surge-wall-large.description = 설금을 재료로 한 큰 방어벽.\n데미지를 입으면 번개를 일으켜 대상에게 피해를 입힙니다. -block.door.description = 유닛이 지나갈 수 있도록 만든 문.\n클릭하면 열고 닫습니다. -block.door-large.description = 유닛이 자나갈 수 있도록 만든 큰 문.\n클릭하면 열고 닫습니다. -block.mend-projector.description = 주위 건물을 넓은 범위로 치료하는 건물입니다. -block.overdrive-projector.description = 범위 내 모든 행동의 속도를 2배 높여주는 보조형 건물입니다. -block.force-projector.description = 보호막을 생성하는 건물.\n기본적으로 전력만 있으면 작동하지만, 메타를 넣어 보호막의 범위를 크게 확장시킬 수 있습니다. -block.shock-mine.description = 적이 이 블록을 지나가면 전격 공격을 하는 함정형 방어 건물입니다. -block.duo.description = 범용성을 가진 터렛.\n지상 및 공중공격을 하며, 초반에 유용합니다. -block.arc.description = 목표 방향으로 전격 공격을 하는 포탑입니다. -block.hail.description = 장거리 지상 공격을 하는 터렛입니다.\n적이 공격하기 전에 쓸어버릴 수 있습니다. -block.lancer.description = 중거리 레이져 포탑입니다.\n적을 관통하기 때문에 뭉쳐있는 적들에게 매우 효과적입니다. -block.wave.description = 적이 있는 자리에 액체를 뿌립니다.\n이 포탑을 활용하여 액체를 뿌린 곳에 불을 붙이거나 적을 느리게 할 수 있습니다. -block.salvo.description = 명중률이 높고, 3발씩 끊어 발사하는 포탑입니다. -block.swarmer.description = 4발씩 끊어서 유도체를 발사하는 포탑입니다 -block.ripple.description = 4개의 탄약으로 나눠 발사하여 명중률이 낮지만, 사거리가 매우 긴 포탑입니다. -block.cyclone.description = 낮은 명중률과 높은 RPM 을 가진 포탑입니다.\n사격하는데 쿨타임이 거의 없습니다. -block.fuse.description = 단거리에서 범위형 레이저를 발사하는 포탑입니다. -block.spectre.description = 높은 명중률과 RPM 을 가진 포탑입니다.\n탄약이 남아있는 한 멈추지 않고 계속 연사합니다. -block.meltdown.description = 목표를 따라 초대형 레이져를 발사하는 포탑입니다.\n조준 시간이 길어 공중에는 적합하지 않지만 뭉쳐있는 몹에게 매우 효과가 좋습니다. -block.conveyor.description = 느린 속도로 자원을 수송할 수 있는 컨베이어. -block.titanium-conveyor.description = 빠른 속도로 자원을 수송할 수 있는 컨베이어. -block.phase-conveyor.description = 자원을 지정된 방향으로 바로 이동시켜 주는 컨베이어 입니다. -block.junction.description = 컨베이어를 교차시켜 자원을 수송할 때 사용할 수 있는 블록입니다. -block.mass-driver.description = 자원을 받아서 다른 물질 이동기로 전달할 수 있는 블록입니다.\n엄청난 사거리를 가지고 있으며, 주로 컨베이어가 접근할 수 없는 곳에 유용하게 사용됩니다. -block.smelter.description = 고밀도 합금을 제작할 수 있는 건물입니다. -block.arc-smelter.description = 고밀도 합금을 제작할 수 있는 건물이지만, 이 건물은 석탄이 필요 없고 좀더 빠른 속도로 합금을 생산해낼 수 있습니다. -block.silicon-smelter.description = 실리콘을 제작할 수 있는 건물입니다. -block.plastanium-compressor.description = 플라스터늄을 제조할 수 있는 건물입니다. -block.phase-weaver.description = 메타를 제작할 수 있는 건물입니다. -block.alloy-smelter.description = 설금을 제작할 수 있는 건물입니다. -block.pulverizer.description = 돌을 갈아서 모래로 만들 수 있는 건물입니다. -block.pyratite-mixer.description = 피라테를 제조할 수 있는 건물입니다. -block.blast-mixer.description = 폭발물을 제조할 수 있는 건물입니다. -block.cryofluidmixer.description = 냉각수를 제작할 수 있는 건물입니다. -block.solidifer.description = 용암을 돌로 만들 수 있는 건물입니다. -block.melter.description = 돌로 용암을 만들 수 있는 건물입니다. +block.copper-wall.description = 싸구려 방어블록.\n처음에 몇번 웨이브에서 건물과 터렛을 보호하는 데 유용함. +block.copper-wall-large.description = 싸구려 방어블록.\n처음에 몇번 웨이브에서 건물과 터렛을 보호하는 데 유용함.\n4개를 합친 블록입니다. +block.thorium-wall.description = 강력한 방어블록.\n적 공격으로부터 좋은 보호를 할 수 있습니다. +block.thorium-wall-large.description = 강력한 방어블록.\n적 공격으로부터 좋은 보호를 할 수 있습니다.\n4개를 합친 블록입니다. +block.phase-wall.description = 토륨 벽만큼 강하지 않지만 벽을 향해 날아오는 총알이 너무 강력하지 않으면 총알을 튕겨냅니다. +block.phase-wall-large.description = 토륨 벽만큼 강하지 않지만 벽을 향해 날아오는 총알이 너무 강력하지 않으면 총알을 튕겨냅니다.\n4개를 합친 블록입니다. +block.surge-wall.description = 최강 방어블록.\n공격을 받으면 낮은 확률로 공격자에게 전격 공격을 합니다. +block.surge-wall-large.description = 최강 방어블록.\n공격을 받으면 낮은 확률로 공격자에게 전격 공격을 합니다.\n4개를 합친 블록입니다. +block.door.description = 눌러서 열고 닫을 수 있는 작은 문.\n만약 문이 열리면, 적들은 총을 쏘며 문을 통과할 수 있습니다. +block.door-large.description = 누르는 것으로 여닫을 수 있는 큰 문.\n만약 문이 열리면, 적들은 총을 쏘며 문을 통과할 수 있습니다.\n4개를 합친 블록입니다. +block.mend-projector.description = 주변 건물을 주기적으로 치료합니다. +block.overdrive-projector.description = 드릴과 컨베이어와 같은 인근 건물의 속도를 높여줍니다. +block.force-projector.description = 총알에게서 내부의 건물과 유닛을 보호하면서 그 주위에 육각형 보호막을 만듭니다. +block.shock-mine.description = 지뢰를 밟는 적에게 피해를 줍니다. 적에게는 거의 보이지 않습니다. +block.duo.description = 작고 싼 터렛. +block.arc.description = 적을 향해 무작위 각도로 전기를 쏘는 작은 터렛. +block.hail.description = 작은 포병 터렛. +block.lancer.description = 충전된 전기빔을 쏘는 중형 터렛. +block.wave.description = 액체를 뿜는 중간 크기의 속화 터렛. +block.salvo.description = 살보에서 사격을 하는 중형 터렛. +block.swarmer.description = 유도 미사일을 발사하는 중형 터렛. +block.ripple.description = 여러 발의 사격을 동시에 하는 대형 포대. +block.cyclone.description = 대형 초고속 사격 터렛. +block.fuse.description = 강력한 단거리 빔을 쏘는 대형 터렛. +block.spectre.description = 한 번에 두 발의 강력한 총알을 쏘는 대형 터렛. +block.meltdown.description = 강력한 장거리 빔을 쏘는 대형 터렛. +block.conveyor.description = 기본 아이템 수송 블록. 아이템을 앞으로 이동시켜 자동으로 터렛이나 건물에 넣어줍니다. 회전식. +block.titanium-conveyor.description = 고급 아이템 운송 블록. 표준 컨베이어보다 아이템을 더 빨리 이동시킨다. +block.phase-conveyor.description = 고급품 수송 블록. 여러 타일을 통해 아이템을 연결된 위상 컨베이어로 텔레포트하기 위해 전력을 사용합니다. +block.junction.description = 2개의 컨베이어 벨트를 교차시키는 다리 역할을 합니다. 서로 다른 재료를 다른 장소로 운반하는 두 개의 다른 컨베이어의 상황에서 유용합니다. +block.mass-driver.description = 최강 아이템 수송 블록. 몇 가지 아이템을 모아 장거리에서 또 다른 매스 드라이버에게 발사합니다. +block.silicon-smelter.description = 고순도 석탄으로 모래를 줄여 실리콘을 생산합니다. +block.plastanium-compressor.description = 석유와 티타늄으로 플라스타늄을 생산합니다. +block.phase-weaver.description = 방사능 토륨과 많은 량의 모래에서 상직물을 생산합니다. +block.alloy-smelter.description = 티타늄, 납, 실리콘, 구리로부터 서지 합금을 생산합니다. +block.pulverizer.description = 모래로 돌을 부숩니다. 천연 모래가 부족할 때 유용합니다. +block.pyratite-mixer.description = 석탄, 납, 모래를 가연성이 높은 피라타이트로 만듭니다. +block.blast-mixer.description = 기름을 사용하여 피라타이트를 인화성은 떨어지지만 폭발성은 높은 폭발성 화합물로 변환시킵니다. +block.cryofluidmixer.description = 물과 티타늄을 냉각에 훨씬 더 효과적인 냉동액으로 결합시킵니다. +block.melter.description = 고철을 녹여 더 많은 처리나 터렛의 사용을 위해 광재에 녹입니다. block.incinerator.description = 불필요한 아이템을 소각시켜 줄 수 있는 건물입니다. -block.biomattercompressor.description = 잔디밭에서 바이오메터를 추출할 수 있는 건물입니다. +block.spore-press.description = 포자 포드를 석유로 바꿔줍니다. block.separator.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물입니다. -block.centrifuge.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물이지만, 이 건물은 좀 더 다양한 자원을 얻을 수 있게 해 줍니다. -block.power-node.description = 생성된 전력를 다른 건물로 전달하기 위한 전력 노드입니다. +block.power-node.description = 전원을 연결된 노드로 전송합니다. 최대 4개의 동력원, 싱크 또는 노드를 연결할 수 있습니다. 노드는 인접한 블록으로부터 전원을 공급하거나 공급받을 수 있습니다. block.power-node-large.description = 생성된 전력를 다른 건물로 전달하기 위한 건물이며, 일반 노드보다 더 많은 전력을 이동시킬 수 있습니다. -block.battery.description = 흔히 아는 충전식 배터리입니다.\n전력을 사용하는 건물에 전력이 떨어질경우, 이 배터리를 전력 노드에 연결하면 이 배터리에 저장된 전력을 소모하여 지속적으로 공급할 수 있습니다. -block.battery-large.description = 일반 배터리보다 용량이 매우 커진 커진 배터리. -block.combustion-generator.description = 석탄을 연료로 전력를 생산해내는 발전소 입니다. -block.turbine-generator.description = 석탄 발전기보다 더 많은량의 전력를 생산하는 발전기입니다. -block.thermal-generator.description = 용암을 원료로 전력을 생산할 수 있는 발전소입니다. -block.solar-panel.description = 태양열을 받아 자기 스스로 전력을 생산하는 건물입니다. -block.solar-panel-large.description = 태양열을 받아 자기 스스로 전력을 생산하지만, 이 블록은 더 빨리 전력을 생산할 수 있습니다. -block.thorium-reactor.description = 토륨을 원료로 하는 토륨 원자로 입니다.\n많은 전력을 생산하지만 엄청난 열을 발생시키기 때문에, 많은 량의 물 또는 냉각수가 있어야 터지지 않고 작동합니다. -block.rtg-generator.description = 냉각은 필요 없지만 토륨 원자로보다 적은량의 전력을 생산하는 방사선 동위원소 열전자 발전기. -block.unloader.description = 해당 창고 및 코어에서 자원을 빼내는데 사용됩니다. -block.container.description = 아이템을 저장할 수 있는 소형 창고입니다. -block.vault.description = 아이템을 저장할 수 있는 대형 창고입니다. -block.mechanical-drill.description = 구리로 제작할 수 있는 기본 드릴입니다. -block.pneumatic-drill.description = 돌, 티타늄을 채광할 수 있는 고급 드릴입니다. -block.laser-drill.description = 토륨을 채광할 수 있는 최고급 드릴입니다.\n전력과 물을 공급하여 빠른 속도로 채광할 수 있습니다. -block.blast-drill.description = 최상위 드릴입니다.\n엄청난 양의 전력과 물을 소모하는 대신, 매우 빠른 속도로 채광합니다. -block.water-extractor.description = 바닥에서 물을 추출하여 건물에 공급할 수 있는 건물입니다. -block.cultivator.description = 잔디에서 바이오메터를 추출할 수 있는 건물입니다. -block.oil-extractor.description = 석유를 추출 해 주는 건물입니다. -block.dart-ship-pad.description = 다트 비행선으로 바꿀 수 있는 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.trident-ship-pad.description = 대형 폭격기 역할을 하는 삼지창 비행선으로 바꿀 수 있는 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.javelin-ship-pad.description = 처음에는 느리지만 가속도가 붙어 다른 비행선보다 5배 이상 빠르게 움직일 수 있으며, 적에게 부딛쳐서 공격할 수 있는 자비린 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.glaive-ship-pad.description = 글레브 비행선으로 바꿀 수 있는 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.tau-mech-pad.description = 주위 건물이나 기체를 치료하는 타우 기체로 바꿀 수 있는 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.delta-mech-pad.description = 전방에 전격 공격을 하는 델타 기체로 바꿀 수 있는 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.omega-mech-pad.description = 건물 파괴용 기체의 끝판왕이며, 공격시 방어모드로 전환되어 최대 90% 피해를 줄일 수 있는 오메가 기체로 바꿀 수 있는 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.spirit-factory.description = 코어에 기본적으로 스폰되는 드론인 스피릿 유닛을 생산하는 공장입니다. -block.phantom-factory.description = 일반 드론보다 좀 더 효율적이며 빠른 새 드론인 팬텀을 생산하는 공장입니다. -block.wraith-factory.description = 지상 및 공중을 공격할 수 있으며, 공격후 빠지고 다시 공격하는 방식을 사용하는 유령 전투기를 소환하는 공장입니다. -block.ghoul-factory.description = 지상만 공격할 수 있으며, 건물을 집중 폭격하는데 목적이 있는 구울 비행선 유닛을 생산하는 공장입니다. -block.dagger-factory.description = 지상 및 공중을 공격할 수 있으며, 플레이어 기본 기체인 디거를 생산하는 공장입니다. -block.titan-factory.description = 지상 및 공중을 공격할 수 있으며, 총알 대신 근접 화염 방사기를 가진 타이탄 유닛을 생산할 수 있는 공장입니다. -block.fortress-factory.description = 지상 유닛의 최종판이며, 강력한 총을 가진 포트리스를 생산하는 공장입니다. -block.revenant-factory.description = 공중 유닛의 최종판이며, 강력한 레이저 총을 가진 레비던트 유닛을 생산할 수 있는 공장입니다. -block.repair-point.description = 근처 유닛들을 수리하는 건물입니다.\n커맨드 센터에서 후퇴 명령시 공중 유닛이 이 건물로 이동하여 수리를 받습니다. -block.command-center.description = 생산된 유닛들을 제어할 수 있는 건물.\n첫번째 버튼은 적 기지로 공격하며, 두번째는 대기 상태, 세번째는 기지 근처를 돌며 정찰합니다. +block.battery.description = 전력 생산량에 여유가 있을경우, 생산된 잉여 전력을 여기에 저장합니다. +block.battery-large.description = 일반 배터리보다 훨씬 많은 량의 전력을 저장합니다. +block.combustion-generator.description = 기름이나 인화성 물질을 태워 전력을 발생시킵니다. +block.turbine-generator.description = 연소 발생기보다 효율적이지만, 추가 액체가 필요합니다. +block.thermal-generator.description = 뜨거운 위치에 건설하면 전력을 생산합니다. +block.solar-panel.description = 태양으로부터 소량의 전력을 공급합니다. +block.solar-panel-large.description = 일반 태양 전지판보다 훨씬 나은 전력을 공급하지만, 건축비도 훨씬 비쌉니다. +block.thorium-reactor.description = 고방사능 토륨으로부터 막대한 양의 전력을 발생시킵니다. 지속적인 냉각이 필요하며 냉각제의 양이 부족하면 크게 폭발합니다. 전력 출력은 최대 용량에서 기본 전력을 발생시키는 완전성에 따라 결정됩니다. +block.rtg-generator.description = 냉각은 필요 없지만 토륨 원자로에 비해 전력을 적게 공급하는 방사성 동위원소 열전 발생기. +block.unloader.description = 컨테이너, 금고 또는 코어에서 인접한 블록으로 아이템을 출하합니다. 출하시킬 아이템의 종류는 언로더를 눌러 지정할 수 있습니다. +block.container.description = 각종 소량의 자원을 저장할 수 있습니다.[LIGHT_GRAY언로더[]를 사용하여 컨테이너에서 물건을 회수할 수 있습니다. +block.vault.description = 각종 대량의 자원을 저장할 수 있습니다.[LIGHT_GRAY]언로더[]를 사용하여 금고에서 물건을 회수할 수 있습니다. +block.mechanical-drill.description = 싸구려 드릴. 적절한 타일 위에 놓였을때 매우 느린 속도로 계속 출력합니다. +block.pneumatic-drill.description = 기압을 이용하여 보다 빠르고 단단한 물질을 채광할 수 있는 향상된 드릴. +block.laser-drill.description = 토륨을 채광할 수 있는 최고급 드릴입니다. 전력과 물을 공급하여 빠른 속도로 채광할 수 있습니다. +block.blast-drill.description = 최상위 드릴입니다. 많은량의 전력이 필요합니다. +block.water-extractor.description = 땅에서 물을 추출합니다. 근처에 호수가 없을 때 사용하세요. +block.cultivator.description = 소량의 포자를 산업용으로 준비된 포자로 배양하는 건물입니다. +block.oil-extractor.description = 모래에서 기름을 추출하기 위해 대량을 전력을 사용합니다. 근처에 직접적인 석유 공급원이 없을때 사용하세요. +block.trident-ship-pad.description = 지금 타고있는 배를 떠나 잘 무장된 중폭격기로 갈아타세요.\n누르거나 클릭하여 이 기체로 바꿉니다. +block.javelin-ship-pad.description = 지금 타고있는 배를 떠나 전격 무기와 강력하고 빠른 요격체로 변신합니다.\n누르거나 클릭하여 이 기체로 바꿉니다. +block.glaive-ship-pad.description = 지금 타고있는 배를 떠나 크고 잘 무장된 기체로 갈아타세요.\n누르거나 클릭하여 이 기체로 바꿉니다. +block.tau-mech-pad.description = 지금 타고있는 배를 떠나 아군 건물이나 유닛을 치료할 수 있는 지원형 기체로 갈아타세요.\n누르거나 클릭하여 이 기체로 바꿉니다. +block.delta-mech-pad.description = 지금 타고있는 배를 떠나 뺑소니 공격을 위해 만들어진 빠르고 가벼운 기체로 갈아타세요.\n누르거나 클릭하여 이 기체로 바꿉니다. +block.omega-mech-pad.description = 지금 타고있는 배를 떠나 최전방 공격을 위해 만든 부피가 크고 잘 무장된 기체로 갈아타세요.\n누르거나 클릭하여 이 기체로 바꿉니다. +block.spirit-factory.description = 광석을 채굴하고 블록을 수리하는 경량 드론을 생산합니다. +block.phantom-factory.description = 스피릿 드론보다 훨씬 효과적인 첨단 드론 유닛을 생산합니다. +block.wraith-factory.description = 빠른 뺑소니 요격기 유닛을 생산합니다. +block.ghoul-factory.description = 중탄두 폭격기를 생산합니다. +block.dagger-factory.description = 기본 지상 유닛을 생산합니다. +block.titan-factory.description = 첨단 장갑 지상부대를 생산합니다. +block.fortress-factory.description = 중대포 지상부대를 생산합니다. +block.revenant-factory.description = 중량의 레이저 포대를 가진 공중부대를 생산합니다. +block.repair-point.description = 주변에서 가장 가까운 손상된 유닛을 지속적으로 치료합니다. block.conduit.description = 일반 파이프.\n액체가 지나갈 수 있도록 해 줍니다. -block.pulse-conduit.description = 티타늄으로 만들어 졌으며, 일반 파이프보다 액체 수용량이 높습니다. -block.phase-conduit.description = 물을 먼거리로 순간이동 시켜 주는 장치입니다. +block.pulse-conduit.description = 고급 액체 수송블록. 일반 파이프보다 액체 운송 속도가 빠릅니다. +block.phase-conduit.description = 고급 액체 수송블록. 물을 먼거리로 순간이동 시켜 주는 장치입니다. block.liquid-router.description = 물펌프를 다른 방향으로 분배할 수 있게 하는 블럭입니다. block.liquid-tank.description = 액체 종류를 저장할 수 있는 물탱크 입니다. block.liquid-junction.description = 물펌프와 다른 물펌프를 서로 교차시키게 할 수 있는 블럭입니다. block.bridge-conduit.description = 다리와 다리 사이를 연결하여 액체가 지나갈 수 있게 해 줍니다.\n주로 다리 사이에 지나갈 수 없는 장애물이 있을 때 사용합니다. -block.mechanical-pump.description = 구리로 제작할 수 있는 기계식 물펌프입니다. +block.mechanical-pump.description = 느린 속도로 물을 퍼올리는 펌프입니다. 대신 전력이 필요없습니다. block.rotary-pump.description = 일반 물 펌프보다 더 빠른 속도로 물을 끌어올릴 수 있는 펌프입니다. -block.thermal-pump.description = 기계식 펌프보다 3배 빠른 속도로 액체를 퍼올릴 수 있는 펌프이며, 용암도 퍼올릴 수 있는 유일한 펌프입니다. -block.router.description = 한 방향에서 아이템을 받은 후 최대 3개의 다른 방향으로 동일하게 출력합니다.\n재료를 한곳에서 여러 대상으로 분할하여 운반하는데 유용합니다. +block.thermal-pump.description = 최고의 펌프. +block.router.description = 한 방향에서 아이템을 널은 후 최대 3개의 다른 방향으로 균등하게 출력합니다. 재료를 한곳에서 여러 개의 목표로 분할하는 데 유용합니다. block.distributor.description = 아이템을 최대 7개의 다른 방향으로 똑같이 분할하는 고급 분배기. block.bridge-conveyor.description = 고급 자원 수송 블록.\n지형이나 건물을 넘어 최대 3개 타일을 건너뛰고 자원을 운송할 수 있습니다. -block.alpha-mech-pad.description = 알파 기체로 바꿀 수 있는 패드입니다. -block.item-source.description = 자원을 선택하면 그 자원이 무한하게 생성되는 블록입니다. -block.liquid-source.description = 무한한 액체를 출력해냅니다. -block.item-void.description = 아이템을 사라지게 만듭니다. -block.power-source.description = 무한한 전력을 공급해주는 블록입니다. +block.item-source.description = 자원을 선택하면 그 자원이 무한하게 생성되는 블록입니다. 샌드박스 전용. +block.liquid-source.description = 무한한 액체를 출력해냅니다. 샌드박스 전용. +block.item-void.description = 아이템을 사라지게 만듭니다. 샌드박스 전용. +block.power-source.description = 무한한 전력을 공급해주는 블록입니다. 샌드박스 전용. block.power-void.description = 설정된 아이템을 계속해서 출력하는 블록입니다. -liquid.water.description = 지상 유닛이 이 위를 지나가면 이동속도가 느려지고, 깊은 물에 빠지면 죽습니다. -liquid.lava.description = 지상 유닛이 이 위를 지나가면 이동속도가 매우 느려지고, 지속적으로 데미지를 입습니다. -liquid.oil.description = 일부 조합 블록에서 사용되는 자원입니다. -liquid.cryofluid.description = 포탑 및 토륨 원자로에서 사용되는 자원입니다. - -setting.indicators.name = 인디게이터 표시 +liquid.water.description = 일반적으로 냉각기와 폐기물 처리에 사용된다. +liquid.oil.description = 연소, 폭발 또는 냉각제로 사용될 수 있다. +liquid.cryofluid.description = 건물을 냉각시키는데 가장 효과적인 액체. diff --git a/core/assets/bundles/bundle_nl.properties b/core/assets/bundles/bundle_nl.properties new file mode 100644 index 0000000000..627ed142be --- /dev/null +++ b/core/assets/bundles/bundle_nl.properties @@ -0,0 +1,832 @@ +credits.text = Gemaakt door [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[] +credits = Credits +contributors = Vertalers en Medewerkers +discord = Word lid van de Mindustry Discord! +link.discord.description = De officiële Mindustry discord chatroom +link.github.description = Game broncode +link.dev-builds.description = Onstabiele ontwikkeling builds +link.trello.description = Officiële trello-bord voor geplande functies +link.itch.io.description = itch.io pagina met pc-downloads en webversie +link.google-play.description = Google Play store vermelding +link.wiki.description = Officiële Mindustry wiki +linkfail = Kan link niet openen!\nDe URL is gekopieerd naar je klembord +screenshot = Schermafbeeling opgeslagen in {0} +gameover = Game Over +gameover.pvp = het[accent] {0}[] team heeft gewonnen! +highscore = [accent]Nieuw topscore! +stat.wave = Waves Verslagen:[accent] {0} +stat.enemiesDestroyed = Vijanden Vernietigd:[accent] {0} +stat.built = Gebouwen Gebouwd:[accent] {0} +stat.destroyed = Gebouwen Vernietigd:[accent] {0} +stat.deconstructed = Gebouwen Gesloopt:[accent] {0} +stat.delivered = Middelen Gelanceerd: +stat.rank = Eindrang: [accent]{0} +map.delete = Weet je zeker dat je de map wilt verwijderen? "[accent]{0}[]"? +level.highscore = Topscore: [accent]{0} +level.select = Selecteer Level +level.mode = Spelmodus: +construction.desktop = Om een blok te deselecteren of te stoppen met bouwen, [accent]gebruik spatiebalk[]. +construction.title = Blok Bouwhandleiding +construction = You've just selected [accent]block construction mode[].\n\nTo begin placing, simply tap a valid location near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Shift the selection[] by holding and dragging any block in the selection.\n- [accent]Place blocks in a line[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel construction or selection[] by pressing the X at the bottom left. +deconstruction.title = Block Deconstruction Guide +deconstruction = You've just selected [accent]block deconstruction mode[].\n\nTo begin breaking, simply tap a block near your ship.\nOnce you have selected some blocks, press the checkbox to confirm, and your ship will begin de-constructing them.\n\n- [accent]Remove blocks[] from your selection by tapping them.\n- [accent]Remove blocks in an area[] by tapping and holding an empty spot, then dragging in a direction.\n- [accent]Cancel deconstruction or selection[] by pressing the X at the bottom left. +showagain = Don't show again next session +coreattack = < Core is under attack! > +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database +savegame = Save Game +loadgame = Load Game +joingame = Join Game +addplayers = Add/Remove Players +customgame = Custom Game +newgame = New Game +none = +close = Close +quit = Quit +maps = Maps +continue = Continue +maps.none = [LIGHT_GRAY]No maps found! +about.button = About +name = Name: +noname = Pick a[accent] player name[] first. +filename = File Name: +unlocked = New content unlocked! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. +players = {0} players online +players.single = {0} player online +server.closing = [accent]Closing server... +server.kicked.kick = You have been kicked from the server! +server.kicked.serverClose = Server closed. +server.kicked.clientOutdated = Outdated client! Update your game! +server.kicked.serverOutdated = Outdated server! Ask the host to update! +server.kicked.banned = You are banned on this server. +server.kicked.recentKick = You have been kicked recently.\nWait before connecting again. +server.kicked.nameInUse = There is someone with that name\nalready on this server. +server.kicked.nameEmpty = Your chosen name is invalid. +server.kicked.idInUse = You are already on this server! Connecting with two accounts is not permitted. +server.kicked.customClient = This server does not support custom builds. Download an official version. +server.kicked.gameover = Game over! +host.info = The [accent]host[] button hosts a server on port [scarlet]6567[]. \nAnybody on the same [LIGHT_GRAY]wifi or local network[] should be able to see your server in their server list.\n\nIf you want people to be able to connect from anywhere by IP, [accent]port forwarding[] is required.\n\n[LIGHT_GRAY]Note: If someone is experiencing trouble connecting to your LAN game, make sure you have allowed Mindustry access to your local network in your firewall settings. +join.info = Here, you can enter a [accent]server IP[] to connect to, or discover [accent]local network[] servers to connect to.\nBoth LAN and WAN multiplayer is supported.\n\n[LIGHT_GRAY]Note: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP. +hostserver = Host Game +hostserver.mobile = Host\nGame +host = Host +hosting = [accent]Opening server... +hosts.refresh = Refresh +hosts.discovering = Discovering LAN games +server.refreshing = Refreshing server +hosts.none = [lightgray]No local games found! +host.invalid = [scarlet]Can't connect to host. +trace = Trace Player +trace.playername = Player name: [accent]{0} +trace.ip = IP: [accent]{0} +trace.id = Unique ID: [accent]{0} +trace.android = Android Client: [accent]{0} +trace.modclient = Custom Client: [accent]{0} +trace.totalblocksbroken = Total blocks broken: [accent]{0} +trace.structureblocksbroken = Structure blocks broken: [accent]{0} +trace.lastblockbroken = Last block broken: [accent]{0} +trace.totalblocksplaced = Total blocks placed: [accent]{0} +trace.lastblockplaced = Last block placed: [accent]{0} +invalidid = Invalid client ID! Submit a bug report. +server.bans = Bans +server.bans.none = No banned players found! +server.admins = Admins +server.admins.none = No admins found! +server.add = Add Server +server.delete = Are you sure you want to delete this server? +server.hostname = Host: {0} +server.edit = Edit Server +server.outdated = [crimson]Outdated Server![] +server.outdated.client = [crimson]Outdated Client![] +server.version = [lightgray]Version: {0} {1} +server.custombuild = [yellow]Custom Build +confirmban = Are you sure you want to ban this player? +confirmkick = Are you sure you want to kick this player? +confirmunban = Are you sure you want to unban this player? +confirmadmin = Are you sure you want to make this player an admin? +confirmunadmin = Are you sure you want to remove admin status from this player? +joingame.title = Join Game +joingame.ip = Address: +disconnect = Disconnected. +disconnect.data = Failed to load world data! +connecting = [accent]Connecting... +connecting.data = [accent]Loading world data... +server.port = Port: +server.addressinuse = Address already in use! +server.invalidport = Invalid port number! +server.error = [crimson]Error hosting server: [accent]{0} +save.old = This save is for an older version of the game, and can no longer be used.\n\n[LIGHT_GRAY]Save backwards compatibility will be implemented in the full 4.0 release. +save.new = New Save +save.overwrite = Are you sure you want to overwrite\nthis save slot? +overwrite = Overwrite +save.none = No saves found! +saveload = [accent]Saving... +savefail = Failed to save game! +save.delete.confirm = Are you sure you want to delete this save? +save.delete = Delete +save.export = Export Save +save.import.invalid = [accent]This save is invalid! +save.import.fail = [crimson]Failed to import save: [accent]{0} +save.export.fail = [crimson]Failed to export save: [accent]{0} +save.import = Import Save +save.newslot = Save name: +save.rename = Rename +save.rename.text = New name: +selectslot = Select a save. +slot = [accent]Slot {0} +save.corrupted = [accent]Save file corrupted or invalid!\nIf you have just updated your game, this is probably a change in the save format and [scarlet]not[] a bug. +empty = +on = On +off = Off +save.autosave = Autosave: {0} +save.map = Map: {0} +save.wave = Wave {0} +save.difficulty = Difficulty: {0} +save.date = Last Saved: {0} +save.playtime = Playtime: {0} +warning = Warning. +confirm = Confirm +delete = Delete +ok = OK +open = Open +cancel = Cancel +openlink = Open Link +copylink = Copy Link +back = Back +quit.confirm = Are you sure you want to quit? +changelog.title = Changelog +changelog.loading = Getting changelog... +changelog.error.android = [accent]Note that the changelog sometimes does not work on Android 4.4 and below!\nThis is due to an internal Android bug. +changelog.error.ios = [accent]The changelog is currently not supported in iOS. +changelog.error = [scarlet]Error getting changelog!\nCheck your internet connection. +changelog.current = [yellow][[Current version] +changelog.latest = [accent][[Latest version] +loading = [accent]Loading... +saving = [accent]Saving... +wave = [accent]Wave {0} +wave.waiting = [LIGHT_GRAY]Wave in {0} +waiting = [LIGHT_GRAY]Waiting... +waiting.players = Waiting for players... +wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining +wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining +loadimage = Load Image +saveimage = Save Image +unknown = Unknown +custom = Custom +builtin = Built-In +map.delete.confirm = Are you sure you want to delete this map? This action cannot be undone! +map.random = [accent]Random Map +map.nospawn = This map does not have any cores for the player to spawn in! Add a[ROYAL] blue[] core to this map in the editor. +map.nospawn.pvp = This map does not have any enemy cores for player to spawn into! Add[SCARLET] red[] cores to this map in the editor. +map.invalid = Error loading map: corrupted or invalid map file. +editor.brush = Brush +editor.openin = Open In Editor +editor.oregen = Ore Generation +editor.oregen.info = Ore Generation: +editor.mapinfo = Map Info +editor.author = Author: +editor.description = Description: +editor.name = Name: +editor.teams = Teams +editor.elevation = Elevation +editor.errorimageload = Error loading file:\n[accent]{0} +editor.errorimagesave = Error saving file:\n[accent]{0} +editor.generate = Generate +editor.resize = Resize +editor.loadmap = Load Map +editor.savemap = Save Map +editor.saved = Saved! +editor.save.noname = Your map does not have a name! Set one in the 'map info' menu. +editor.save.overwrite = Your map overwrites a built-in map! Pick a different name in the 'map info' menu. +editor.import.exists = [scarlet]Unable to import:[] a built-in map named '{0}' already exists! +editor.import = Import... +editor.importmap = Import Map +editor.importmap.description = Import an already existing map +editor.importfile = Import File +editor.importfile.description = Import an external map file +editor.importimage = Import Legacy Image +editor.importimage.description = Import an external map image file +editor.export = Export... +editor.exportfile = Export File +editor.exportfile.description = Export a map file +editor.exportimage = Export Terrain Image +editor.exportimage.description = Export a map image file +editor.loadimage = Import Terrain +editor.saveimage = Export Terrain +editor.unsaved = [scarlet]You have unsaved changes![]\nAre you sure you want to exit? +editor.resizemap = Resize Map +editor.mapname = Map Name: +editor.overwrite = [accent]Warning!\nThis overwrites an existing map. +editor.overwrite.confirm = [scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? +editor.selectmap = Select a map to load: +width = Width: +height = Height: +menu = Menu +play = Play +load = Load +save = Save +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0}ms +language.restart = Please restart your game for the language settings to take effect. +settings = Settings +tutorial = Tutorial +editor = Editor +mapeditor = Map Editor +donate = Donate +abandon = Abandon +abandon.text = This zone and all its resources will be lost to the enemy. +locked = Locked +complete = [LIGHT_GRAY]Complete: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Best Wave: {0} +launch = < LAUNCH > +launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] {0} Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Unlock configuring loadout:\nWave {0}. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Wave {0} reached:\nNew zone requirements met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health +connectfail = [crimson]Failed to connect to server:\n\n[accent]{0} +error.unreachable = Server unreachable.\nIs the address spelled correctly? +error.invalidaddress = Invalid address. +error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! +error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! +error.alreadyconnected = Already connected. +error.mapnotfound = Map file not found! +error.io = Network I/O error. +error.any = Unknown network error. +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault +settings.language = Language +settings.reset = Reset to Defaults +settings.rebind = Rebind +settings.controls = Controls +settings.game = Game +settings.sound = Sound +settings.graphics = Graphics +settings.cleardata = Clear Game Data... +settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! +settings.clearall.confirm = [scarlet]WARNING![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit. +settings.clearunlocks = Clear Unlocks +settings.clearall = Clear All +paused = [accent]< Paused > +yes = Yes +no = No +info.title = Info +error.title = [crimson]An error has occured +error.crashtitle = An error has occured +blocks.outputspeed = Drill Speed: {0}/s +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Block Info +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} +blocks.powercapacity = Power Capacity +blocks.powershot = Power/Shot +blocks.targetsair = Targets Air +blocks.itemsmoved = Move Speed +blocks.shootrange = Range +blocks.size = Size +blocks.liquidcapacity = Liquid Capacity +blocks.maxitemssecond = Max Items +blocks.powerrange = Power Range +blocks.poweruse = Power Use +blocks.powerdamage = Power/Damage +blocks.inputitemcapacity = Input Item Capacity +blocks.outputitemcapacity = Output Item Capacity +blocks.itemcapacity = Item Capacity +blocks.basepowergeneration = Base Power Generation +blocks.powertransferspeed = Power Transfer +blocks.craftspeed = Production Speed +blocks.inputliquid = Input Liquid +blocks.inputliquidaux = Aux Liquid +blocks.inputitem = Input Item +blocks.inputitems = Input Items +blocks.outputitem = Output Item +blocks.drilltier = Drillables +blocks.drillspeed = Base Drill Speed +blocks.maxunits = Max Active Units +blocks.liquidoutput = Liquid Output +blocks.liquidoutputspeed = Liquid Output Speed +blocks.liquiduse = Liquid Use +blocks.coolant = Coolant +blocks.liquid = Liquid +blocks.coolantuse = Coolant Use +blocks.inputliquidfuel = Fuel Liquid +blocks.liquidfueluse = Liquid Fuel Use +blocks.boostitem = Boost Item +blocks.boostliquid = Boost Liquid +blocks.health = Health +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = Inaccuracy +blocks.shots = Shots +blocks.reload = Shots/Second +blocks.inputfuel = Fuel +blocks.fuelburntime = Fuel Burn Time +blocks.inputcapacity = Input capacity +blocks.outputcapacity = Output capacity +blocks.ammo = Ammo +unit.blocks = blocks +unit.powersecond = power units/second +unit.liquidsecond = liquid units/second +unit.itemssecond = items/second +unit.liquidunits = liquid units +unit.powerunits = power units +unit.degrees = degrees +unit.seconds = seconds +unit.items = items +category.general = General +category.power = Power +category.liquids = Liquids +category.items = Items +category.crafting = Crafting +category.shooting = Shooting +category.optional = Optional Enhancements +setting.indicators.name = Ally Indicators +setting.autotarget.name = Auto-Target +setting.fpscap.name = Max FPS +setting.fpscap.none = None +setting.fpscap.text = {0} FPS +setting.difficulty.training = training +setting.difficulty.easy = easy +setting.difficulty.normal = normal +setting.difficulty.hard = hard +setting.difficulty.insane = insane +setting.difficulty.name = Difficulty: +setting.screenshake.name = Screen Shake +setting.effects.name = Display Effects +setting.sensitivity.name = Controller Sensitivity +setting.saveinterval.name = Autosave Interval +setting.seconds = {0} Seconds +setting.fullscreen.name = Fullscreen +setting.fps.name = Show FPS +setting.vsync.name = VSync +setting.lasers.name = Show Power Lasers +setting.minimap.name = Show Minimap +setting.musicvol.name = Music Volume +setting.mutemusic.name = Mute Music +setting.sfxvol.name = SFX Volume +setting.mutesound.name = Mute Sound +setting.crashreport.name = Send Anonymous Crash Reports +keybind.title = Rebind Keys +category.general.name = General +category.view.name = View +category.multiplayer.name = Multiplayer +command.attack = Attack +command.retreat = Retreat +command.patrol = Patrol +keybind.gridMode.name = Block Select +keybind.gridModeShift.name = Category Select +keybind.press = Press a key... +keybind.press.axis = Press an axis or key... +keybind.screenshot.name = Map Screenshot +keybind.move_x.name = Move x +keybind.move_y.name = Move y +keybind.select.name = Select/Shoot +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block +keybind.deselect.name = Deselect +keybind.shoot.name = Shoot +keybind.zoom_hold.name = Zoom Hold +keybind.zoom.name = Zoom +keybind.menu.name = Menu +keybind.pause.name = Pause +keybind.dash.name = Dash +keybind.chat.name = Chat +keybind.player_list.name = Player list +keybind.console.name = Console +keybind.rotate.name = Rotate +keybind.toggle_menus.name = Toggle menus +keybind.chat_history_prev.name = Chat history prev +keybind.chat_history_next.name = Chat history next +keybind.chat_scroll.name = Chat scroll +keybind.drop_unit.name = Drop Unit +keybind.zoom_minimap.name = Zoom minimap +mode.help.title = Description of modes +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. +mode.sandbox.name = Sandbox +mode.sandbox.description = Infinite resources and no timer for waves. +mode.freebuild.name = Freebuild +mode.freebuild.description = Limited resources and no timer for waves. +mode.pvp.name = PvP +mode.pvp.description = Fight against other players locally. +mode.attack.name = Attack +mode.attack.description = No waves, with the goal to destroy the enemy base. +content.item.name = Items +content.liquid.name = Liquids +content.unit.name = Units +content.block.name = Blocks +content.mech.name = Mechs +item.copper.name = Copper +item.copper.description = A useful structure material. Used extensively in all types of blocks. +item.lead.name = Lead +item.lead.description = A basic starter material. Used extensively in electronics and liquid transportation blocks. +item.coal.name = Coal +item.coal.description = A common and readily available fuel. +item.graphite.name = Graphite +item.titanium.name = Titanium +item.titanium.description = A rare super-light metal used extensively in liquid transportation, drills and aircraft. +item.thorium.name = Thorium +item.thorium.description = A dense, radioactive metal used as structural support and nuclear fuel. +item.silicon.name = Silicon +item.silicon.description = An extremely useful semiconductor, with applications in solar panels and many complex electronics. +item.plastanium.name = Plastanium +item.plastanium.description = A light, ductile material used in advanced aircraft and fragmentation ammunition. +item.phase-fabric.name = Phase Fabric +item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. +item.surge-alloy.name = Surge Alloy +item.surge-alloy.description = An advanced alloy with unique electrical properties. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. +item.sand.name = Sand +item.sand.description = A common material that is used extensively in smelting, both in alloying and as a flux. +item.blast-compound.name = Blast Compound +item.blast-compound.description = A volatile compound used in bombs and explosives. While it can burned as fuel, this is not advised. +item.pyratite.name = Pyratite +item.pyratite.description = An extremely flammable substance used in incendiary weapons. +item.metaglass.name = Metaglass +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. +liquid.water.name = Water +liquid.slag.name = Slag +liquid.oil.name = Oil +liquid.cryofluid.name = Cryofluid +mech.alpha-mech.name = Alpha +mech.alpha-mech.weapon = Heavy Repeater +mech.alpha-mech.ability = Drone Swarm +mech.alpha-mech.description = The standard mech. Has decent speed and damage output; can create up to 3 drones for increased offensive capability. +mech.delta-mech.name = Delta +mech.delta-mech.weapon = Arc Generator +mech.delta-mech.ability = Discharge +mech.delta-mech.description = A fast, lightly-armored mech made for hit-and-run attacks. Does little damage against structures, but can kill large groups of enemy units very quickly with its arc lightning weapons. +mech.tau-mech.name = Tau +mech.tau-mech.weapon = Restruct Laser +mech.tau-mech.ability = Repair Burst +mech.tau-mech.description = The support mech. Heals allied blocks by shooting at them. Can heal allies in a radius with its repair ability. +mech.omega-mech.name = Omega +mech.omega-mech.weapon = Swarm Missiles +mech.omega-mech.ability = Armored Configuration +mech.omega-mech.description = A bulky and well-armored mech, made for front-line assaults. Its armor ability can block up to 90% of incoming damage. +mech.dart-ship.name = Dart +mech.dart-ship.weapon = Repeater +mech.dart-ship.description = The standard ship. Reasonably fast and light, but has little offensive capability and low mining speed. +mech.javelin-ship.name = Javelin +mech.javelin-ship.description = A hit-and-run strike ship. While initially slow, it can accelerate to great speeds and fly by enemy outposts, dealing large amounts of damage with its lightning ability and missiles. +mech.javelin-ship.weapon = Burst Missiles +mech.javelin-ship.ability = Discharge Booster +mech.trident-ship.name = Trident +mech.trident-ship.description = A heavy bomber. Reasonably well armored. +mech.trident-ship.weapon = Bomb Bay +mech.glaive-ship.name = Glaive +mech.glaive-ship.description = A large, well-armored gunship. Equipped with an incendiary repeater. Good acceleration and maximum speed. +mech.glaive-ship.weapon = Flame Repeater +item.explosiveness = [LIGHT_GRAY]Explosiveness: {0}% +item.flammability = [LIGHT_GRAY]Flammability: {0}% +item.radioactivity = [LIGHT_GRAY]Radioactivity: {0}% +unit.health = [LIGHT_GRAY]Health: {0} +unit.speed = [LIGHT_GRAY]Speed: {0} +mech.weapon = [LIGHT_GRAY]Weapon: {0} +mech.health = [LIGHT_GRAY]Health: {0} +mech.itemcapacity = [LIGHT_GRAY]Item Capacity: {0} +mech.minespeed = [LIGHT_GRAY]Mining Speed: {0} +mech.minepower = [LIGHT_GRAY]Mining Power: {0} +mech.ability = [LIGHT_GRAY]Ability: {0} +liquid.heatcapacity = [LIGHT_GRAY]Heat Capacity: {0} +liquid.viscosity = [LIGHT_GRAY]Viscosity: {0} +liquid.temperature = [LIGHT_GRAY]Temperature: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press +block.constructing = {0} [LIGHT_GRAY](Constructing) +block.spawn.name = Enemy Spawn +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus +block.deepwater.name = Deep Water +block.water.name = Water +block.tar.name = Tar +block.stone.name = Stone +block.sand.name = Dark Sand +block.ice.name = Ice +block.snow.name = Snow +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulder +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs +block.copper-wall.name = Copper Wall +block.copper-wall-large.name = Large Copper Wall +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall +block.phase-wall.name = Phase Wall +block.phase-wall-large.name = Large Phase Wall +block.thorium-wall.name = Thorium Wall +block.thorium-wall-large.name = Large Thorium Wall +block.door.name = Door +block.door-large.name = Large Door +block.duo.name = Duo +block.hail.name = Hail +block.lancer.name = Lancer +block.conveyor.name = Conveyor +block.titanium-conveyor.name = Titanium Conveyor +block.junction.name = Junction +block.router.name = Router +block.distributor.name = Distributor +block.sorter.name = Sorter +block.sorter.description = Sorts items. If an item matches the selection, it is allowed to pass. Otherwise, the item is outputted to the left and right. +block.overflow-gate.name = Overflow Gate +block.overflow-gate.description = A combination splitter and router that only outputs to the left and right if the front path is blocked. +block.silicon-smelter.name = Silicon Smelter +block.phase-weaver.name = Phase Weaver +block.pulverizer.name = Pulverizer +block.cryofluidmixer.name = Cryofluid Mixer +block.melter.name = Melter +block.incinerator.name = Incinerator +block.spore-press.name = Spore Press +block.separator.name = Separator +block.power-node.name = Power Node +block.power-node-large.name = Large Power Node +block.surge-tower.name = Surge Tower +block.battery.name = Battery +block.battery-large.name = Large Battery +block.combustion-generator.name = Combustion Generator +block.turbine-generator.name = Turbine Generator +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor +block.mechanical-drill.name = Mechanical Drill +block.pneumatic-drill.name = Pneumatic Drill +block.laser-drill.name = Laser Drill +block.water-extractor.name = Water Extractor +block.cultivator.name = Cultivator +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad +block.delta-mech-pad.name = Delta Mech Pad +block.javelin-ship-pad.name = Javelin Ship Pad +block.trident-ship-pad.name = Trident Ship Pad +block.glaive-ship-pad.name = Glaive Ship Pad +block.omega-mech-pad.name = Omega Mech Pad +block.tau-mech-pad.name = Tau Mech Pad +block.conduit.name = Conduit +block.mechanical-pump.name = Mechanical Pump +block.item-source.name = Item Source +block.item-void.name = Item Void +block.liquid-source.name = Liquid Source +block.power-void.name = Power Void +block.power-source.name = Power Infinite +block.unloader.name = Unloader +block.vault.name = Vault +block.wave.name = Wave +block.swarmer.name = Swarmer +block.salvo.name = Salvo +block.ripple.name = Ripple +block.phase-conveyor.name = Phase Conveyor +block.bridge-conveyor.name = Bridge Conveyor +block.plastanium-compressor.name = Plastanium Compressor +block.pyratite-mixer.name = Pyratite Mixer +block.blast-mixer.name = Blast Mixer +block.solar-panel.name = Solar Panel +block.solar-panel-large.name = Large Solar Panel +block.oil-extractor.name = Oil Extractor +block.spirit-factory.name = Spirit Drone Factory +block.phantom-factory.name = Phantom Drone Factory +block.wraith-factory.name = Wraith Fighter Factory +block.ghoul-factory.name = Ghoul Bomber Factory +block.dagger-factory.name = Dagger Mech Factory +block.titan-factory.name = Titan Mech Factory +block.fortress-factory.name = Fortress Mech Factory +block.revenant-factory.name = Revenant Fighter Factory +block.repair-point.name = Repair Point +block.pulse-conduit.name = Pulse Conduit +block.phase-conduit.name = Phase Conduit +block.liquid-router.name = Liquid Router +block.liquid-tank.name = Liquid Tank +block.liquid-junction.name = Liquid Junction +block.bridge-conduit.name = Bridge Conduit +block.rotary-pump.name = Rotary Pump +block.thorium-reactor.name = Thorium Reactor +block.mass-driver.name = Mass Driver +block.blast-drill.name = Airblast Drill +block.thermal-pump.name = Thermal Pump +block.thermal-generator.name = Thermal Generator +block.alloy-smelter.name = Alloy Smelter +block.mend-projector.name = Mend Projector +block.surge-wall.name = Surge Wall +block.surge-wall-large.name = Large Surge Wall +block.cyclone.name = Cyclone +block.fuse.name = Fuse +block.shock-mine.name = Shock Mine +block.overdrive-projector.name = Overdrive Projector +block.force-projector.name = Force Projector +block.arc.name = Arc +block.rtg-generator.name = RTG Generator +block.spectre.name = Spectre +block.meltdown.name = Meltdown +block.container.name = Container +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. +team.blue.name = blue +team.red.name = red +team.orange.name = orange +team.none.name = gray +team.green.name = green +team.purple.name = purple +unit.spirit.name = Spirit Drone +unit.spirit.description = The starter drone unit. Spawns in the core by default. Automatically mines ores and repairs blocks. +unit.phantom.name = Phantom Drone +unit.phantom.description = An advanced drone unit. Automatically mines ores and repairs blocks. Significantly more effective than a spirit drone. +unit.dagger.name = Dagger +unit.dagger.description = A basic ground unit. Useful in swarms. +unit.crawler.name = Crawler +unit.titan.name = Titan +unit.titan.description = An advanced, armored ground unit. Attacks both ground and air targets. +unit.ghoul.name = Ghoul Bomber +unit.ghoul.description = A heavy carpet bomber. +unit.wraith.name = Wraith Fighter +unit.wraith.description = A fast, hit-and-run interceptor unit. +unit.fortress.name = Fortress +unit.fortress.description = A heavy artillery ground unit. +unit.revenant.name = Revenant +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper +tutorial.begin = Your mission here is to eradicate the[LIGHT_GRAY] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this. +tutorial.drill = Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein. +tutorial.conveyor = [accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core. +tutorial.morecopper = More copper is required.\n\nEither mine it manually, or place more drills. +tutorial.turret = Defensive structures must be built to repel the[LIGHT_GRAY] enemy[].\nBuild a duo turret near your base. +tutorial.drillturret = Duo turrets require[accent] copper ammo []to shoot.\nPlace a drill next to the turret to supply it with mined copper. +tutorial.waves = The[LIGHT_GRAY] enemy[] approaches.\n\nDefend your core for 2 waves. Build more turrets. +tutorial.lead = More ores are available. Explore and mine[accent] lead[].\n\nDrag from your unit to the core to transfer resources. +tutorial.smelter = Copper and lead are weak metals.\nSuperior[accent] Dense Alloy[] can be created in a smelter.\n\nBuild one. +tutorial.densealloy = The smelter will now produce alloy.\nGet some.\nImprove the production if necessary. +tutorial.siliconsmelter = The core will now create a[accent] spirit drone[] for mining and repairing blocks.\n\nFactories for other units can be created with [accent] silicon.\nMake a silicon smelter. +tutorial.silicondrill = Silicon requires[accent] coal[] and[accent] sand[].\nStart by making drills. +tutorial.generator = This technology requires power.\nCreate a[accent] combustion generator[] for it. +tutorial.generatordrill = Combustion generators need fuel.\nFuel it with coal from a drill. +tutorial.node = Power requires transport.\nCreate a[accent] power node[] next to your combustion generator to transfer its power. +tutorial.nodelink = Power can be transferred through contacting power blocks and generators, or by linked power nodes.\n\nLink power by tapping the node and selecting the generator and silicon smelter. +tutorial.silicon = Silicon is being produced. Get some.\n\nImproving the production system is advised. +tutorial.daggerfactory = Construct a[accent] dagger mech factory.[]\n\nThis will be used to create attack mechs. +tutorial.router = Factories need resources to function.\nCreate a router to split conveyor resources. +tutorial.dagger = Link power nodes to the factory.\nOnce requirements are met, a mech will be created.\n\nCreate more drills, generators and conveyors as necessary. +tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. +block.copper-wall.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves. +block.copper-wall-large.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves.\nSpans multiple tiles. +block.thorium-wall.description = A strong defensive block.\nGood protection from enemies. +block.thorium-wall-large.description = A strong defensive block.\nGood protection from enemies.\nSpans multiple tiles. +block.phase-wall.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful. +block.phase-wall-large.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful.\nSpans multiple tiles. +block.surge-wall.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker. +block.surge-wall-large.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker.\nSpans multiple tiles. +block.door.description = A small door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through. +block.door-large.description = A large door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through.\nSpans multiple tiles. +block.mend-projector.description = Periodically heals blocks in its vicinity. +block.overdrive-projector.description = Increases the speed of nearby buildings like drills and conveyors. +block.force-projector.description = Creates a hexagonal force field around itself, protecting buildings and units inside from damage through bullets. +block.shock-mine.description = Damages enemies stepping on the mine. Nearly invisible to the enemy. +block.duo.description = A small, cheap turret. +block.arc.description = A small turret which shoots electricity in a random arc towards the enemy. +block.hail.description = A small artillery turret. +block.lancer.description = A medium-sized turret which shoots charged electricity beams. +block.wave.description = A medium-sized rapid-fire turret which shoots liquid bubbles. +block.salvo.description = A medium-sized turret which fires shots in salvos. +block.swarmer.description = A medium-sized turret which shoots burst missiles. +block.ripple.description = A large artillery turret which fires several shots simultaneously. +block.cyclone.description = A large rapid fire turret. +block.fuse.description = A large turret which shoots powerful short-range beams. +block.spectre.description = A large turret which shoots two powerful bullets at once. +block.meltdown.description = A large turret which shoots powerful long-range beams. +block.conveyor.description = Basic item transport block. Moves items forward and automatically deposits them into turrets or crafters. Rotatable. +block.titanium-conveyor.description = Advanced item transport block. Moves items faster than standard conveyors. +block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles. +block.junction.description = Acts as a bridge for two crossing conveyor belts. Useful in situations with two different conveyors carrying different materials to different locations. +block.mass-driver.description = Ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. +block.silicon-smelter.description = Reduces sand with highly pure coal in order to produce silicon. +block.plastanium-compressor.description = Produces plastanium from oil and titanium. +block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. +block.alloy-smelter.description = Produces surge alloy from titanium, lead, silicon and copper. +block.pulverizer.description = Crushes stone into sand. Useful when there is a lack of natural sand. +block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. +block.blast-mixer.description = Uses oil for transforming pyratite into the less flammable but more explosive blast compound. +block.cryofluidmixer.description = Combines water and titanium into cryofluid which is much more efficient for cooling. +block.melter.description = Melts down scrap into slag for further processing or usage in turrets. +block.incinerator.description = Gets rid of any excess item or liquid. +block.spore-press.description = Compresses spore pods into oil. +block.separator.description = Extracts useful minerals from slag. +block.power-node.description = Transmits power to connected nodes. Up to four power sources, sinks or nodes can be connected. The node will receive power from or supply power to any adjacent blocks. +block.power-node-large.description = Has a larger radius than the power node and connects to up to six power sources, sinks or nodes. +block.battery.description = Stores power whenever there is an abundance and provides power whenever there is a shortage, as long as there is capacity left. +block.battery-large.description = Stores much more power than a regular battery. +block.combustion-generator.description = Generates power by burning oil or flammable materials. +block.turbine-generator.description = More efficient than a combustion generator, but requires additional water. +block.thermal-generator.description = Generates power when placed in hot locations. +block.solar-panel.description = Provides a small amount of power from the sun. +block.solar-panel-large.description = Provides much better power supply than a standard solar panel, but is also much more expensive to build. +block.thorium-reactor.description = Generates huge amounts of power from highly radioactive thorium. Requires constant cooling. Will explode violently if insufficient amounts of coolant are supplied. Power output depends on fullness, with base power generated at half capacity. +block.rtg-generator.description = A radioisotope thermoelectric generator which does not require cooling but provides less power than a thorium reactor. +block.unloader.description = Unloads items from a container, vault or core onto a conveyor or directly into an adjacent block. The type of item to be unloaded can be changed by tapping on the unloader. +block.container.description = Stores a small amount of items of each type. Adjacent containers, vaults and cores will be treated as a single storage unit. An[LIGHT_GRAY] unloader[] can be used to retrieve items from the container. +block.vault.description = Stores a large amount of items of each type. Adjacent containers, vaults and cores will be treated as a single storage unit. An[LIGHT_GRAY] unloader[] can be used to retrieve items from the vault. +block.mechanical-drill.description = A cheap drill. When placed on appropriate tiles, outputs items at a slow pace indefinitely. +block.pneumatic-drill.description = An improved drill which is faster and able to process harder materials by making use of air pressure. +block.laser-drill.description = Allows drilling even faster through laser technology, but requires power. Additionally, radioactive thorium can be retrieved with this drill. +block.blast-drill.description = The ultimate drill. Requires large amounts of power. +block.water-extractor.description = Extracts water from the ground. Use it when there is no lake nearby. +block.cultivator.description = Cultivates spores with water in order to obtain biomatter. +block.oil-extractor.description = Uses large amounts of power in order to extract oil from sand. Use it when there is no direct source of oil nearby. +block.trident-ship-pad.description = Leave your current vessel and change into a reasonably well armored heavy bomber.\nUse the pad by double tapping while standing on it. +block.javelin-ship-pad.description = Leave your current vessel and change into a strong and fast interceptor with lightning weapons.\nUse the pad by double tapping while standing on it. +block.glaive-ship-pad.description = Leave your current vessel and change into a large, well-armored gunship.\nUse the pad by double tapping while standing on it. +block.tau-mech-pad.description = Leave your current vessel and change into a support mech which can heal friendly buildings and units.\nUse the pad by double tapping while standing on it. +block.delta-mech-pad.description = Leave your current vessel and change into a fast, lightly-armored mech made for hit-and-run attacks.\nUse the pad by double tapping while standing on it. +block.omega-mech-pad.description = Leave your current vessel and change into a bulky and well-armored mech, made for front-line assaults.\nUse the pad by double tapping while standing on it. +block.spirit-factory.description = Produces light drones which mine ore and repair blocks. +block.phantom-factory.description = Produces advanced drone units which are significantly more effective than a spirit drone. +block.wraith-factory.description = Produces fast, hit-and-run interceptor units. +block.ghoul-factory.description = Produces heavy carpet bombers. +block.dagger-factory.description = Produces basic ground units. +block.titan-factory.description = Produces advanced, armored ground units. +block.fortress-factory.description = Produces heavy artillery ground units. +block.revenant-factory.description = Produces heavy laser air units. +block.repair-point.description = Continuously heals the closest damaged unit in its vicinity. +block.conduit.description = Basic liquid transport block. Works like a conveyor, but with liquids. Best used with extractors, pumps or other conduits. +block.pulse-conduit.description = Advanced liquid transport block. Transports liquids faster and stores more than standard conduits. +block.phase-conduit.description = Advanced liquid transport block. Uses power to teleport liquids to a connected phase conduit over several tiles. +block.liquid-router.description = Accepts liquids from one direction and outputs them to up to 3 other directions equally. Can also store a certain amount of liquid. Useful for splitting the liquids from one source to multiple targets. +block.liquid-tank.description = Stores a large amount of liquids. Use it for creating buffers when there is a non-constant demand of materials or as a safeguard for cooling vital blocks. +block.liquid-junction.description = Acts as a bridge for two crossing conduits. Useful in situations with two different conduits carrying different liquids to different locations. +block.bridge-conduit.description = Advanced liquid transport block. Allows transporting liquids over up to 3 tiles of any terrain or building. +block.mechanical-pump.description = A cheap pump with slow output, but no power consumption. +block.rotary-pump.description = An advanced pump which doubles up speed by using power. +block.thermal-pump.description = The ultimate pump. Three times as fast as a mechanical pump and the only pump which is able to retrieve lava. +block.router.description = Accepts items from one direction and outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets. +block.distributor.description = An advanced router which splits items to up to 7 other directions equally. +block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building. +block.item-source.description = Infinitely outputs items. Sandbox only. +block.liquid-source.description = Infinitely outputs liquids. Sandbox only. +block.item-void.description = Destroys any items which go into it without using power. Sandbox only. +block.power-source.description = Infinitely outputs power. Sandbox only. +block.power-void.description = Voids all power inputted into it. Sandbox only. +liquid.water.description = Commonly used for cooling machines and waste processing. +liquid.oil.description = Can be burnt, exploded or used as a coolant. +liquid.cryofluid.description = The most efficient liquid for cooling things down. diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index 683468ca01..bab1016b6a 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -1,23 +1,28 @@ credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet!) credits = Zasłużeni +contributors = Tłumacze i pomocnicy discord = Odwiedź nasz serwer Discord! link.discord.description = Oficjalny serwer Discord Mindustry link.github.description = Kod Gry link.dev-builds.description = Niestabilne wersje gry link.trello.description = Oficjalna tablica Trello z planowanym funkcjami link.itch.io.description = Strona itch.io z oficjanymi wersjami do pobrania -link.google-play.description = Google Play store listing +link.google-play.description = Strona na sklepie Google Play link.wiki.description = Oficjana Wiki Mindustry linkfail = Nie udało się otworzyć linku!\nURL został skopiowany. +screenshot = Zapisano zdjęcie do {0} gameover = Rdzeń został zniszczony. -gameover.pvp = The[accent] {0}[] team is victorious! -sector.gameover = This sector has been lost. Re-deploy? -sector.retry = Spróbuj ponownie +gameover.pvp = Zwyciężyła drużyna [accent]{0}[]! highscore = [YELLOW] Nowy rekord! -wave.lasted = Wytrwałeś do [accent]{0}[] fali. -level.highscore = Rekord: [accent]{0} -level.delete.title = Potwierdź usuwanie +stat.wave = Fale powstrzymane:[accent] {0} +stat.enemiesDestroyed = Przeciwnicy zniszczeni:[accent] {0} +stat.built = Budynki zbudowane:[accent] {0} +stat.destroyed = Budynki zniszczone:[accent] {0} +stat.deconstructed = Budynki zrekonstruowane:[accent] {0} +stat.delivered = Surowce wystrzelone: +stat.rank = Final Rank: [accent]{0} map.delete = Jesteś pewny, że chcesz usunąć "[accent]{0}[]"? +level.highscore = Rekord: [accent]{0} level.select = Wybrany poziom level.mode = Tryb gry: construction.desktop = Desktop controls have been changed.\nTo deselect a block or stop building, [accent]use space[]. @@ -27,60 +32,36 @@ deconstruction.title = Poradnik niszczenia bloków deconstruction = Wybrałeś [accent]tryb niszczenia bloków[].\n\nAby zacząć niszczenie, po prostu kliknij na blok obok twojego statku.\nKiedy wybrałeś kilka bloków, kliknij ptaszek i twój statek zacznie niszczyć bloki.\n\n- [accent]Anuluj bloki[] z twojej kolekcji przez klikanie ich(?)\n- [accent]Usuwaj bloki na obszrze[] przez zaznacznie ich.\n- [accent]Anuluj niszcznie [] przez kliknięcie X w lewym dolnym rogu. showagain = Nie pokazuj tego więcej coreattack = < Rdzeń jest atakowany! > -unlocks = Lista przedmiotów +nearpoint = [[ [scarlet]OPUŚĆ PUNKT ZRZUTU NATYCHMIAST[] ]\n unicestwienie nadchodzi +outofbounds = [[ POZA GRANICAMI ]\n[] samozniszcenie za {0} sekund +database = Centralna baza danych savegame = Zapisz Grę loadgame = Wczytaj grę joingame = Gra wieloosobowa addplayers = Dodaj/Usuń graczy customgame = Własna Gra -sectors = Sektory -sector = Wybrany Sektor: [LIGHT_GRAY]{0} -sector.time = Czas: [LIGHT_GRAY]{0} -sector.deploy = Wejdź -sector.abandon = Opuść -sector.abandon.confirm = Czy jesteś pewien, że chcesz porzucić cały postęp w tym sektorze?\nProces jest nieodwracalny! -sector.resume = Wznów -sector.locked = [scarlet][[Niegotowy] -sector.unexplored = [accent][[Nieodkryty] -missions = Misje:[LIGHT_GRAY] {0} -mission = Misja:[LIGHT_GRAY] {0} -mission.main = Główna misja:[LIGHT_GRAY] {0} -mission.info = Informacje o misji -mission.complete = Misja zakończona sukcesem! -mission.complete.body = Sektor {0},{1} został podbity. -mission.wave = Przetrwaj[accent] {0}/{1} []fal\nNastępna fala w {2} -mission.wave.enemies = Przetrwaj[accent] {0}/{1} []fal\nPozostało {2} przeciwników -mission.wave.enemy = Przetrwaj[accent] {0}/{1} []fal\nPozostał{2} przeciwnik -mission.wave.menu = Przetrwaj[accent] {0} []fal -mission.battle = Zniszcz bazę przeciwnika -mission.resource.menu = Wydobądź {0} x{1} -mission.resource = Wydobądź {0}:\n[accent]{1}/{2}[] -mission.block = Stwórz {0} -mission.unit = Utwórz {0} jednostkę -mission.command = Wyślij komendę {0} do Jednostek -mission.linknode = Połącz Węzeł prądu -mission.display = [accent]Misja:\n[LIGHT_GRAY]{0} -mission.mech = Switch to mech[accent] {0}[] -mission.create = Utwórz[accent] {0}[] -none = +newgame = Nowa Gra +none = <żadne> close = Zamknij quit = Wyjdź maps = Mapy continue = Kontynuuj -nextmission = Następna misja maps.none = [LIGHT_GRAY]Nie znaleziono żadnych map! about.button = O grze name = Nazwa: -filename = File Name: +noname = Najpierw wybierz [accent]nazwę gracza[] +filename = Nazwa Pliku: unlocked = Odblokowano nowy blok! -unlocked.plural = Odblokowano nowe bloki! +completed = [accent]Ukończony +techtree = Drzewo Technologiczne +research.list = [LIGHT_GRAY]Badania: +research = Badaj +researched = [LIGHT_GRAY]{0} zbadane. players = {0} graczy online players.single = {0} gracz online server.closing = [accent] Zamykanie serwera... server.kicked.kick = Zostałeś wyrzucony z serwera! server.kicked.serverClose = Serwer został zamknięty. -server.kicked.sectorComplete = Sektor ukończony. -server.kicked.sectorComplete.text = Twoja misja została ukończona.\nSerwer kontynuuje w następnym sektorze. server.kicked.clientOutdated = Nieaktualna gra! Zaktualizują ją! server.kicked.serverOutdated = Nieaktualny serwer! server.kicked.banned = Zostałeś zbanowany na tym serwerze. @@ -89,11 +70,12 @@ server.kicked.nameInUse = Ta nazwa jest już zajęta na tym serwerze. server.kicked.nameEmpty = Nazwa musi zawierać przynajmniej 1 literę lub cyfrę. server.kicked.idInUse = Jesteś już na serwerze! Używanie tego samego konta na 2 urządzeniach jest zabronione. server.kicked.customClient = Ten serwer nie wspomaga wersji deweloperskich. Pobierz oryginalną wersję. +server.kicked.gameover = Koniec gry! host.info = Przycisk [accent]host[] hostuje serwer na porcie [scarlet]6567[] i [scarlet]6568.[]\nKtokolwiek z tym samym [LIGHT_GRAY]wifi lub hotspotem[] powinien zobaczyć twój serwer.\n\nJeśli chcesz, aby każdy z twoim IP mógł dołączyć, [accent]przekierowywanie portów[] jest potrzebne.\n\n[LIGHT_GRAY]Notka:Jeśli ktokolwiek ma problem z dołączeniem do gry, upewnij się, że udostępniłeś Mindustry dostęp do sieci. join.info = Tutaj możesz wpisać [accent]IP serwera[], aby dołączyć lub wyszukaj [accent]serwery wifi[], do których chcesz dołączyć .\nGra wieloosobowa na LAN i WAN jest wspomagana.\n\n[LIGHT_GRAY]Notka: Nie ma automatycznej listy wszystkich serwerów; jeśli chcesz dołączyć przez IP, musisz zapytać się hosta o IP. hostserver = Stwórz Serwer hostserver.mobile = Hostuj\ngrę -host = Host +host = Hostuj hosting = [accent] Otwieranie serwera... hosts.refresh = Odśwież hosts.discovering = Wyszukiwanie gier w sieci LAN @@ -159,7 +141,6 @@ save.rename.text = Zmień nazwę selectslot = Wybierz zapis. slot = [accent]Slot {0} save.corrupted = [accent]Zapis gry jest uszkodzony lub nieprawidłowy! -sector.corrupted = [accent]Zapis sektora został znaleziony, ale nie można go otworzyć.\nNowy sektor został utworzony. empty = on = Włączone off = Wyłączone @@ -169,6 +150,7 @@ save.wave = Fala: {0} save.difficulty = Poziom trudności: {0} save.date = Ostatnio zapisano: {0} save.playtime = Czas gry: {0} +warning = Uwaga. confirm = Potwierdź delete = Usuń ok = Ok @@ -182,7 +164,7 @@ changelog.title = Lista Zmian changelog.loading = Pobieranie listy zmian... changelog.error.android = [accent]Notka: lista zmian czasami nie działa na Androidzie 4.4 i w dół!\nJest to spowodowane przez błąd Androida. changelog.error.ios = [accent]Lista zmian nie wspiera IOS. -changelog.error = [scarlet]Bład w pobieraniu listy zmian!\nSprawdź połączenie z internetem. +changelog.error = [scarlet]Błąd podczas pobierania listy zmian!\nSprawdź połączenie z internetem. changelog.current = [yellow][[Twoja wersja] changelog.latest = [accent][[Najnowsza wersja] loading = [accent]Ładowanie... @@ -204,7 +186,6 @@ map.nospawn = Ta mapa nie zawiera żadnego rdzenia! Musisz dodać [ROYAL]niebies map.nospawn.pvp = Ta mapa nie ma żadnego rdzenia przeciwnika, aby mogli się zrespić przeciwnicy! Dodaj[SCARLET] czerwony[] rdzeń do mapy w edytorze. map.invalid = Error podczas ładowania mapy: uszkodzony lub niepoprawny plik mapy. editor.brush = Pędzel -editor.slope = \\ editor.openin = Otwórz w edytorze editor.oregen = Generacja złóż editor.oregen.info = Generacja złóż: @@ -259,6 +240,26 @@ tutorial = Poradnik editor = Edytor mapeditor = Edytor map donate = Wspomóż nas +abandon = Opuść +abandon.text = Ta strefa i wszystkie jej surowce będą przejęte przez przeciwników. +locked = Zablokowane +complete = [LIGHT_GRAY]Ukończone: +resume = Kontynuuj Strefę:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Najwyższa fala: {0} +launch = Wystrzel +launch.title = Wystrzelenie Udane +launch.next = [LIGHT_GRAY]Następna okazja przy fali {0} +launch.unable = [scarlet] Wystrzelenie niedozwolone![] Wykryto przeciwników. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY] Strefa {0} odblokowana! +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson]Nie można połączyć się z serwerem: [accent] {0} error.unreachable = Serwer niedostępny. error.invalidaddress = Niepoprawny adres. @@ -266,7 +267,20 @@ error.timedout = Przekroczono limit czasu!/nUpewnij się, że host ma ustawione error.mismatch = Błąd pakietu:\nprawdopodobne niedopasowanie klienta/serwera.\nUpewnij się, że ty i host macie najnowszą wersję Mindustry! error.alreadyconnected = Jesteś już połączony. error.mapnotfound = Plik mapy nie został znaleziony! +error.io = Błąd siecowy I/O. error.any = Nieznany błąd sieci. +zone.groundZero.name = Wybuch Lądowy +zone.craters.name = Kratery +zone.frozenForest.name = Zamrożony Las +zone.ruinousShores.name = Zniszczone Przybrzerza +zone.crags.name = Urwiska +zone.stainedMountains.name = Zabarwione Góry +zone.impact0079.name = Uderzenie 0079 +zone.desolateRift.name = Ponura Szczelina +zone.arcticDesert.name = Lodowa Pustynia +zone.dryWastes.name = Suche Pustki +zone.nuclearComplex.name = Centrum Wyrobu Jądrowego +zone.moltenFault.name = Stopiony Uskok settings.language = Język settings.reset = Przywróć domyślne settings.rebind = Zmień przyciski @@ -275,27 +289,29 @@ settings.game = Gra settings.sound = Dźwięk settings.graphics = Grafika settings.cleardata = Wyczyść dane gry... -settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! -settings.clearall.confirm = [scarlet]WARNING![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit. -settings.clearsectors = Wyczyść sektory +settings.clear.confirm = Czy jesteś pewien że chcesz usunąć te dane?\nPo tym nie ma powrotu! +settings.clearall.confirm = [scarlet]UWAGA![]\nTo wykasuje wszystkie dane, włącznie z zapisanymi grami i mapami, ustawienami, i znanych technologiami.\nKiedy naciśniesz 'ok', gra się zamknie i wszystko przepadnie. settings.clearunlocks = Wyczyść listę przedmiotów settings.clearall = Wyczyść wszystko -paused = Wstrzymano +paused = [accent]< Wstrzymano > yes = Jasne! no = Nie ma mowy! info.title = [accent]Informacje error.title = [crimson]Wystąpił błąd error.crashtitle = Wystąpił błąd +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Informacje o bloku +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = Pojemność mocy -blocks.powershot = moc / strzał +blocks.powershot = moc/strzał blocks.targetsair = Może namierzać wrogów powietrznych -blocks.itemspeed = Szybkość Transporterów +blocks.itemsmoved = Move Speed blocks.shootrange = Zasięg blocks.size = Rozmiar blocks.liquidcapacity = Pojemność cieczy -blocks.maxitemssecond = Maksymalna liczba przedmiotów / Sekunda +blocks.maxitemssecond = Maksymalna liczba przedmiotów/sekundę blocks.powerrange = Zakres mocy blocks.poweruse = Zużycie prądu blocks.powerdamage = Moc/Zniszczenia @@ -312,16 +328,23 @@ blocks.inputitems = Materiały do produkcji blocks.outputitem = Produkty blocks.drilltier = Co może wykopać blocks.drillspeed = Postawowa szybkość kopania +blocks.maxunits = Max Active Units blocks.liquidoutput = Wyprodukowany płyn blocks.liquidoutputspeed = Prędkość odpływu cieczy blocks.liquiduse = Zużycie płynów blocks.coolant = Płyn chłodzący +blocks.liquid = Płyn blocks.coolantuse = Zużycie płynu chłodzącego blocks.inputliquidfuel = Paliwo blocks.liquidfueluse = Zużycie paliwa blocks.boostitem = Boost Item blocks.boostliquid = Boost Liquid blocks.health = Zdrowie +blocks.heat = Heat +blocks.power = Prąd +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Zapotrzebowanie Prądu blocks.inaccuracy = Niedokładność blocks.shots = Strzały blocks.reload = Przeładowanie @@ -329,13 +352,13 @@ blocks.inputfuel = Paliwo blocks.fuelburntime = Płonięcie paliwa blocks.inputcapacity = Pojemność wejściowa blocks.outputcapacity = Wydajność wyjściowa -unit.blocks = bloki +blocks.ammo = Ammo +unit.blocks = Klocki unit.powersecond = jednostek prądu na sekundę unit.liquidsecond = jednostek płynów na sekundę unit.itemssecond = przedmiotów na sekundę -unit.pixelssecond = pikseli na sekundę unit.liquidunits = jednostek płynów -unit.powerunits = jednostek paliwa +unit.powerunits = jednostek prądu unit.degrees = stopnie unit.seconds = sekundy unit.items = Przedmioty @@ -345,10 +368,11 @@ category.liquids = Płyny category.items = Przedmioty category.crafting = Przetwórstwo category.shooting = Strzelanie -category.optional = Optional Enhancements -setting.autotarget.name = Auto-Target -setting.fpscap.name = Max FPS -setting.fpscap.none = None +category.optional = Ulepszenia Nieobowiąskowe +setting.indicators.name = Wskaźniki Przyjaciół +setting.autotarget.name = Automatyczne Celowanie +setting.fpscap.name = Maksymalny FPS +setting.fpscap.none = Nieograniczone setting.fpscap.text = {0} FPS setting.difficulty.training = trening setting.difficulty.easy = łatwy @@ -372,19 +396,23 @@ setting.sfxvol.name = Głośność dźwięków setting.mutesound.name = Wycisz dźwięki setting.crashreport.name = Wysyłaj anonimowo dane o crashu gry keybind.title = Zmień ustawienia przycisków -category.general.name = General +category.general.name = Ogólne category.view.name = Wyświetl category.multiplayer.name = Multiplayer command.attack = Atakuj command.retreat = Wycofaj command.patrol = Patrol +keybind.gridMode.name = Wybieranie Bloku +keybind.gridModeShift.name = Wybieranie Kategorii keybind.press = Naciśnij wybrany klawisz... keybind.press.axis = Naciśnij oś lub klawisz... +keybind.screenshot.name = Zrzut ekranu mapy keybind.move_x.name = Poruszanie w poziomie keybind.move_y.name = Poruszanie w pionie -keybind.select.name = Wybieranie -keybind.break.name = Niszczenie -keybind.deselect.name = Deselect +keybind.select.name = Zaznacz +keybind.pick.name = Wybierz Blok +keybind.break_block.name = Break Block +keybind.deselect.name = Odznacz keybind.shoot.name = Strzelanie keybind.zoom_hold.name = Inicjator przybliżania keybind.zoom.name = Przybliżanie @@ -395,36 +423,35 @@ keybind.chat.name = Chat keybind.player_list.name = Lista graczy keybind.console.name = Konsola keybind.rotate.name = Obracanie (2) -keybind.toggle_menus.name = Toggle menus -keybind.chat_history_prev.name = Chat history prev -keybind.chat_history_next.name = Chat history next -keybind.chat_scroll.name = Chat scroll +keybind.toggle_menus.name = Zmień Widoczność Menu +keybind.chat_history_prev.name = Przewiń wiadomości w górę +keybind.chat_history_next.name = Przewiń wiadomości w dół +keybind.chat_scroll.name = Przewijaj Wiadomości keybind.drop_unit.name = Wyrzuć przedmiot keybind.zoom_minimap.name = Powiększenie mapy mode.help.title = Opis trybów -mode.waves.name = Fale -mode.waves.description = Normalny tryb. Normalne surowce i fale. -mode.sandbox.name = Sandbox +mode.survival.name = Przeżycie +mode.survival.description = Zwykły tryb. Limitowane surowce i fale przeciwników. +mode.sandbox.name = Piaskownica mode.sandbox.description = Nieskończone surowce i fale bez odliczania. Dla przedszkolaków! mode.freebuild.name = Budowanie mode.freebuild.description = Normalne surowce i fale bez odliczania. mode.pvp.name = PvP -mode.pvp.description = Walcz lokalnie przeciwko innym graczom. +mode.pvp.description = Walcz przeciwko innym graczom. +mode.attack.name = Atak +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = Przedmioty content.liquid.name = Płyny content.unit.name = Jednostki -content.recipe.name = Bloki +content.block.name = Klocki content.mech.name = Mechs -item.stone.name = Kamień -item.stone.description = Zwkły surowy materiał. Używany do separacji i zamiany w inne surowce lub lawę. Już jaskiniowcy go używali. -item.copper.name = Copper -item.copper.description = A useful structure material. Used extensively in all types of blocks. +item.copper.name = Miedź +item.copper.description = Przydatny materiał budowlany. Szeroko używany w prawie każdej konstrukcji. item.lead.name = Ołów item.lead.description = Podstawowy matriał. Używany w przesyle przemiotów i płynów. Nie jest on przypadkiem szkodliwy? item.coal.name = Węgiel item.coal.description = Zwykły i łatwo dostępny materiał energetyczny. -item.dense-alloy.name = Dense Alloy -item.dense-alloy.description = A tough alloy made with lead and copper. Used in advanced transportation blocks and high-tier drills. +item.graphite.name = Graphite item.titanium.name = Tytan item.titanium.description = Rzadki i bardzo lekki materiał. Używany w bardzo zaawansowanym przewodnictwie, wiertłach i samolotach. Poczuj się jak Tytan! item.thorium.name = Uran @@ -432,60 +459,63 @@ item.thorium.description = Zwarty i radioaktywny materiał używany w struktucra item.silicon.name = Krzem item.silicon.description = Niesamowicie przydatny półprzewodnk uźywany w panelach słonecznych i skomplikowanej elektronice. Nie, w Dolinie Krzemowej już nie ma krzemu. item.plastanium.name = Plastan -item.plastanium.description = Lekki i plastyczny materiał używany w amunicji odłamkowej i samolotach. Używany też w w klockach LEGO (Dlatego są niezniszczalne) -item.phase-fabric.name = Phase Fabric -item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. -item.surge-alloy.name = Niezwykły Stop -item.surge-alloy.description = An advanced alloy with unique electrical properties. -item.biomatter.name = Biomateria -item.biomatter.description = Zbita organiczna papka używana jako materiał do ropy lub jako podstawowy materiał energetyczny. Wegańska! +item.plastanium.description = Lekki i plastyczny materiał używany w amunicji odłamkowej i samolotach. Używany też w klockach LEGO (Dlatego są niezniszczalne) +item.phase-fabric.name = Włókno Fazowe +item.phase-fabric.description = Niewiarygodnie lekkie włókno używane w zaawansowanej elektronice i technologii samo-naprawiającej się. +item.surge-alloy.name = Energetyczny Stop +item.surge-alloy.description = Zaawansowany materiał z niesłychanymi wartościami energetycznymi. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = Piasek item.sand.description = Zwykły materiał używany pospolicie w przepalaniu, stopach i jako topnik. Dostanie piaskiem po oczach nie jest przyjemne. item.blast-compound.name = Wybuchowy związek item.blast-compound.description = Lotny związek używany w pirotechnice. Może być używany jako materiał energetyczny, ale nie polecam. BOOOM! item.pyratite.name = Piratian item.pyratite.description = Niesamowicie palny związek używany w zbrojeniu. Nielegalny w 9 państwach. -liquid.water.name = woda -liquid.lava.name = lawa -liquid.oil.name = ropa -liquid.cryofluid.name = Cryofluid +item.metaglass.name = Metaszkło +item.metaglass.description = Niesamowite silne szkło. Szeroko używane w transporcie i przechowywaniu płynów. +item.scrap.name = Resztki +item.scrap.description = Pozostałości starych budynków i jednostek. Składa się z małej ilości wszystkiego. +liquid.water.name = Woda +liquid.slag.name = Slag +liquid.oil.name = Ropa +liquid.cryofluid.name = Lodociecz mech.alpha-mech.name = Alpha -mech.alpha-mech.weapon = Heavy Repeater -mech.alpha-mech.ability = Drone Swarm -mech.alpha-mech.description = The standard mech. Has decent speed and damage output; can create up to 3 drones for increased offensive capability. +mech.alpha-mech.weapon = Ciężki Karabin +mech.alpha-mech.ability = Chmara Dronòw +mech.alpha-mech.description = Standardowy mech. Średnia broń i prędkość, leć potrafi stworzyć trzy małe drony do walki. mech.delta-mech.name = Delta -mech.delta-mech.weapon = Arc Generator -mech.delta-mech.ability = Discharge -mech.delta-mech.description = A fast, lightly-armored mech made for hit-and-run attacks. Does little damage against structures, but can kill large groups of enemy units very quickly with its arc lightning weapons. +mech.delta-mech.weapon = Generator Piorunów +mech.delta-mech.ability = Rozładunek +mech.delta-mech.description = Szybki i wrażliwy mech stworzony do szybkih ataków i ucieczki. Budynką robi prawie nic, leć jest wstanie szybko rozwalić grupę wrogich jednostek piorunami. mech.tau-mech.name = Tau -mech.tau-mech.weapon = Restruct Laser -mech.tau-mech.ability = Repair Burst -mech.tau-mech.description = The support mech. Heals allied blocks by shooting at them. Can extinguish fires and heal allies in a radius with its repair ability. +mech.tau-mech.weapon = Laser Odbudowy +mech.tau-mech.ability = Wybuch Naprawy +mech.tau-mech.description = Mech pomocny. Naprawia budynki drużyny strzelając wnie. Potrafi wygasić niedalekie pożary i uleczyć bliskich przyjaciół. mech.omega-mech.name = Omega -mech.omega-mech.weapon = Swarm Missiles -mech.omega-mech.ability = Armored Configuration -mech.omega-mech.description = A bulky and well-armored mech, made for front-line assaults. Its armor ability can block up to 90% of incoming damage. -mech.dart-ship.name = Dart -mech.dart-ship.weapon = Repeater -mech.dart-ship.description = The standard ship. Reasonably fast and light, but has little offensive capability and low mining speed. +mech.omega-mech.weapon = Rakiety Chmarowe +mech.omega-mech.ability = Układ Obronny +mech.omega-mech.description = Duży i silny mech, zaprojektowany na ataki. Jego zdolność pozwala mu na zablokowane do 90% zagrożen. +mech.dart-ship.name = Strzałka +mech.dart-ship.weapon = Karabin +mech.dart-ship.description = Standardowy statek. Lekki i szybki, ale jest kiepski jak chodzi o walkę i kopanie. mech.javelin-ship.name = Javelin -mech.javelin-ship.description = A hit-and-run strike ship. While initially slow, it can accelerate to great speeds and fly by enemy outposts, dealing large amounts of damage with its lightning ability and missiles. -mech.javelin-ship.weapon = Burst Missiles -mech.javelin-ship.ability = Discharge Booster -mech.trident-ship.name = Trident -mech.trident-ship.description = A heavy bomber. Reasonably well armored. -mech.trident-ship.weapon = Bomb Bay -mech.glaive-ship.name = Glaive -mech.glaive-ship.description = A large, well-armored gunship. Equipped with an incendiary repeater. Good acceleration and maximum speed. -mech.glaive-ship.weapon = Flame Repeater +mech.javelin-ship.description = Statek do ataku i szybkiej ucieczki. Zaczyna powoli, ale przyspiesza do wielkiej prędkości. Przy tej prędkości, może przelecieć koło wrogiej bazy i atakować piorunami czy rakietami. +mech.javelin-ship.weapon = Seria Rakiet +mech.javelin-ship.ability = Dopalacze Prądowe +mech.trident-ship.name = Trójząb +mech.trident-ship.description = Ciężki bombowiec. Dobrze uzbrojony. +mech.trident-ship.weapon = Wnęka bombowa +mech.glaive-ship.name = Glewia +mech.glaive-ship.description = Duży, uzbrojony statek. Dobra prędkość i przyspieszenie. Ma ognisty karabin. +mech.glaive-ship.weapon = Zapalający Karabin item.explosiveness = [LIGHT_GRAY]Wybuchowość: {0} item.flammability = [LIGHT_GRAY]Palność: {0} item.radioactivity = [LIGHT_GRAY]Promieniotwórczość: {0} -item.fluxiness = [LIGHT_GRAY]Moc topnika: {0} unit.health = [LIGHT_GRAY]Zdrowie: {0} unit.speed = [LIGHT_GRAY]Prędkość: {0} mech.weapon = [LIGHT_GRAY]Broń: {0} -mech.armor = [LIGHT_GRAY]Uzbrojenie: {0} +mech.health = [LIGHT_GRAY]Zdrowie: {0} mech.itemcapacity = [LIGHT_GRAY]Pojemność przedmiotów: {0} mech.minespeed = [LIGHT_GRAY]Prędkość kopania: {0} mech.minepower = [LIGHT_GRAY]Moc kopania: {0} @@ -493,37 +523,67 @@ mech.ability = [LIGHT_GRAY]Umiejętność: {0} liquid.heatcapacity = [LIGHT_GRAY]Wytrzymałość na przegrzewanie: {0} liquid.viscosity = [LIGHT_GRAY]Lepkość: {0} liquid.temperature = [LIGHT_GRAY]Temperatura: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Piec Ceglany +block.kiln.description = Stapia ołów i piasek na metaszkło. Wymaga małą ilość energii. +block.graphite-press.name = Grafitowa Prasa +block.multi-press.name = Multi-Prasa block.constructing = {0}\n[LIGHT_GRAY](Budowa) block.spawn.name = Spawn wrogów -block.core.name = Rdzeń -block.metalfloor.name = Podłoga metalowa -block.deepwater.name = Głęboka woda +block.core-shard.name = Rdzeń: Ułamek +block.core-foundation.name = Rdzeń: Podstawa +block.core-nucleus.name = Core: Nucleus +block.deepwater.name = Głęboka Woda block.water.name = Woda -block.lava.name = Lawa block.tar.name = Smoła -block.blackstone.name = Czarny kamień block.stone.name = Kamień -block.dirt.name = Ziemia block.sand.name = Piasek block.ice.name = Lód block.snow.name = Śnieg -block.grass.name = Trawa -block.shrub.name = Krzak -block.rock.name = Skała -block.blackrock.name = Czarna skała -block.icerock.name = Lodowa skała -block.copper-wall.name = Miedziana ściana +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs +block.copper-wall.name = Miedziana Ściana block.copper-wall-large.name = Duża miedziana ściana -block.dense-alloy-wall.name = Dense Alloy Wall -block.dense-alloy-wall-large.name = Large Dense Alloy Wall -block.phase-wall.name = Phase Wall -block.phase-wall-large.name = Large Phase Wall +block.titanium-wall.name = Tytanowa Ściana +block.titanium-wall-large.name = Duża Tytanowa Ściana +block.phase-wall.name = Fazowa Ściana +block.phase-wall-large.name = Duża Fazowa Ściana block.thorium-wall.name = Torowa Ściana block.thorium-wall-large.name = Duża Torowa Ściana block.door.name = Drzwi block.door-large.name = Duże drzwi block.duo.name = Podwójne działko -block.scorch.name = Ogniste działko block.hail.name = Święte działko block.lancer.name = Lancer block.conveyor.name = Przenośnik @@ -535,36 +595,35 @@ block.sorter.name = Sortownik block.sorter.description = Sortuje przedmioty. Jeśli przedmiot pasuje to przechodzi dalej, jeśli nie - to przechodzi na boki. block.overflow-gate.name = Brama Przeciwprzepełnieniowa block.overflow-gate.description = Rozdzielacz, który przerzuca przedmioty, kiedy główna droga jest przepełniona -block.smelter.name = Huta -block.arc-smelter.name = Duża Huta block.silicon-smelter.name = Huta Krzemu block.phase-weaver.name = Fazowa Fabryka block.pulverizer.name = Rozkruszacz block.cryofluidmixer.name = Mieszacz Cryofluidu block.melter.name = Przetapiacz block.incinerator.name = Spalacz -block.biomattercompressor.name = Kompresor Biomaterii -block.separator.name = Separator -block.centrifuge.name = Wirnik +block.spore-press.name = Spore Press +block.separator.name = Rozdzielacz block.power-node.name = Węzeł Prądu block.power-node-large.name = Duży Węzeł Prądu +block.surge-tower.name = Wieża Energetyczna block.battery.name = Bateria block.battery-large.name = Duża Bateria block.combustion-generator.name = Generator Spalinowy block.turbine-generator.name = Generator Turbinowy +block.differential-generator.name = Generator Różnicowy +block.impact-reactor.name = Reaktor Uderzeniowy block.mechanical-drill.name = Wiertło Mechaniczne block.pneumatic-drill.name = Wiertło Pneumatyczne block.laser-drill.name = Wiertło Laserowe block.water-extractor.name = Ekstraktor Wody block.cultivator.name = Spluchniacz -block.alpha-mech-pad.name = Alpha Mech Pad -block.dart-ship-pad.name = Dart Ship Pad -block.delta-mech-pad.name = Delta Mech Pad -block.javelin-ship-pad.name = Javelin Ship Pad -block.trident-ship-pad.name = Trident Ship Pad -block.glaive-ship-pad.name = Glaive Ship Pad -block.omega-mech-pad.name = Omega Mech Pad -block.tau-mech-pad.name = Tau Mech Pad +block.alpha-dart-mech-pad.name = Lądowisko Alpha-Strzałka +block.delta-mech-pad.name = Lądowisko Mecha Delta +block.javelin-ship-pad.name = Lądowisko Statku Oszczep +block.trident-ship-pad.name = Lądowisko Statku Trójząb +block.glaive-ship-pad.name = Lądowisko Statku Glewia +block.omega-mech-pad.name = Lądowisko Mecha Omega +block.tau-mech-pad.name = Lądowisko Mecha Tau block.conduit.name = Rura block.mechanical-pump.name = Mechaniczna Pompa block.item-source.name = Źródło przedmiotów @@ -583,18 +642,17 @@ block.bridge-conveyor.name = Most Transportowy block.plastanium-compressor.name = Kompresor Plastanu block.pyratite-mixer.name = Mieszacz Piratianu block.blast-mixer.name = Wybuchowy Mieszacz -block.solidifer.name = Utwardzacz block.solar-panel.name = Panel Słoneczny block.solar-panel-large.name = Duży Panel Słoneczny block.oil-extractor.name = Ekstraktor Ropy -block.spirit-factory.name = Spirit Drone Factory -block.phantom-factory.name = Phantom Drone Factory -block.wraith-factory.name = Wraith Fighter Factory -block.ghoul-factory.name = Ghoul Bomber Factory -block.dagger-factory.name = Dagger Mech Factory -block.titan-factory.name = Titan Mech Factory -block.fortress-factory.name = Fortress Mech Factory -block.revenant-factory.name = Revenant Fighter Factory +block.spirit-factory.name = Fabryka Dronów Duch +block.phantom-factory.name = Fabryka Dronów Widmo +block.wraith-factory.name = Fabryka Wojowników Zjawa +block.ghoul-factory.name = Fabryka Bombowców Upiór +block.dagger-factory.name = Fabryka Mechów Nóż +block.titan-factory.name = Fabryka Mechów Tytan +block.fortress-factory.name = Fabryka Mechów Fortreca +block.revenant-factory.name = Fabryka Wojowników Potwór block.repair-point.name = Punkt Napraw block.pulse-conduit.name = Rura Pulsacyjna block.phase-conduit.name = Rura Fazowa @@ -604,49 +662,53 @@ block.liquid-junction.name = Łącznik Płynów block.bridge-conduit.name = Most Płynów block.rotary-pump.name = Wirowa Pompa block.thorium-reactor.name = Reaktor Torowy -block.command-center.name = Centrum dowodzenia -block.mass-driver.name = Mass Driver -block.blast-drill.name = Blast Drill +block.mass-driver.name = Katapulta Masy +block.blast-drill.name = Wiertło Wybuchowe block.thermal-pump.name = Pompa Termalna block.thermal-generator.name = Generator Termalny -block.alloy-smelter.name = Alloy Smtler -block.mend-projector.name = Mend Projector -block.surge-wall.name = Surge Wall -block.surge-wall-large.name = Large Surge Wall -block.cyclone.name = Cyclone -block.fuse.name = Fuse +block.alloy-smelter.name = Piec Mieszający +block.mend-projector.name = Projektor Napraw +block.surge-wall.name = Ściana Stopu Energetycznego +block.surge-wall-large.name = Duża Ściana Stopu Energetycznego +block.cyclone.name = Cyklon +block.fuse.name = Lont block.shock-mine.name = Mina -block.overdrive-projector.name = Overdrive Projector -block.force-projector.name = Force Projector -block.arc.name = Arc +block.overdrive-projector.name = Projektor Nad-prędkości +block.force-projector.name = Projektor Pola Siłowego +block.arc.name = Piorun block.rtg-generator.name = Generator RTG block.spectre.name = Spectre block.meltdown.name = Meltdown -block.container.name = Container -block.core.description = Najważniejszy budynek w grze. +block.container.name = Kontener +block.launch-pad.name = Skocznia +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = niebieski team.red.name = czerwony team.orange.name = pomarańczowy team.none.name = szary team.green.name = zielony team.purple.name = fioletowy -unit.alpha-drone.name = Alpha Drone -unit.spirit.name = Spirit Drone -unit.spirit.description = The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. -unit.phantom.name = Phantom Drone -unit.phantom.description = An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. -unit.dagger.name = Dagger -unit.dagger.description = A basic ground unit. Useful in swarms. -unit.titan.name = Titan -unit.titan.description = An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. -unit.ghoul.name = Ghoul Bomber -unit.ghoul.description = A heavy carpet bomber. Uses blast compound or pyratite as ammo. -unit.wraith.name = Wraith Fighter -unit.wraith.description = A fast, hit-and-run interceptor unit. -unit.fortress.name = Fortress -unit.fortress.description = A heavy artillery ground unit. -unit.revenant.name = Revenant -unit.revenant.description = A heavy laser platform. +unit.spirit.name = Duch +unit.spirit.description = Początkowy dron. Rdzeń zawsze tworzy jeden. Wydobywa surowce, naprawia budynki oraz pomaga przy budowie. +unit.phantom.name = Widmo +unit.phantom.description = Zaawansowany dron. Wydobywa surowce, naprawia budynki oraz pomaga przy budowie szybciej niż dron Duch. +unit.dagger.name = Nóż +unit.dagger.description = Podstawowy mech lądowy. Sam jest słaby, lecz przydatny w dużych ilościach. +unit.crawler.name = Pełzak +unit.titan.name = Tytan +unit.titan.description = Bardziej zaawansowany mech lądowy. Atakuje cele lądowe i niebne. +unit.ghoul.name = Upiór +unit.ghoul.description = Ciężki bombowiec. +unit.wraith.name = Zjawa +unit.wraith.description = Szybka jednostka do ataku i ucieczki. +unit.fortress.name = Fortreca +unit.fortress.description = Wielka jednostka artyleryjna lądowa. +unit.revenant.name = Potwór +unit.eruptor.name = Wysadzać +unit.chaos-array.name = Kolejka Chaosu +unit.eradicator.name = Niszczyciel +unit.lich.name = Obudzony +unit.reaper.name = Żeniec tutorial.begin = Your mission here is to eradicate the[LIGHT_GRAY] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this. tutorial.drill = Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein. tutorial.conveyor = [accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core. @@ -670,8 +732,6 @@ tutorial.dagger = Link power nodes to the factory.\nOnce requirements are met, a tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. block.copper-wall.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves. block.copper-wall-large.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves.\nSpans multiple tiles. -block.dense-alloy-wall.description = A standard defensive block.\nAdequate protection from enemies. -block.dense-alloy-wall-large.description = A standard defensive block.\nAdequate protection from enemies.\nSpans multiple tiles. block.thorium-wall.description = A strong defensive block.\nGood protection from enemies. block.thorium-wall-large.description = A strong defensive block.\nGood protection from enemies.\nSpans multiple tiles. block.phase-wall.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful. @@ -701,8 +761,6 @@ block.titanium-conveyor.description = Advanced item transport block. Moves items block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles. block.junction.description = Acts as a bridge for two crossing conveyor belts. Useful in situations with two different conveyors carrying different materials to different locations. block.mass-driver.description = Ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. -block.smelter.description = Burns coal for smelting copper and lead into dense alloy. -block.arc-smelter.description = Smelts copper and lead into dense alloy by using an external power source. block.silicon-smelter.description = Reduces sand with highly pure coke in order to produce silicon. block.plastanium-compressor.description = Produces plastanium from oil and titanium. block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. @@ -711,12 +769,10 @@ block.pulverizer.description = Crushes stone into sand. Useful when there is a l block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. block.blast-mixer.description = Uses oil for transforming pyratite into the less flammable but more explosive blast compound. block.cryofluidmixer.description = Combines water and titanium into cryofluid which is much more efficient for cooling. -block.solidifer.description = Cools lava to stone at a fast pace. block.melter.description = Heats up stone to very high temperatures to obtain lava. block.incinerator.description = Gets rid of any excess item or liquid. -block.biomattercompressor.description = Compresses biomatter in order to retrieve oil. +block.spore-press.description = Compresses spore pods into oil. block.separator.description = Exposes stone to water pressure in order to obtain various minerals contained in the stone. -block.centrifuge.description = More efficient than the separator, but also more expensive to build and requires power. block.power-node.description = Transmits power to connected nodes. Up to four power sources, sinks or nodes can be connected. The node will receive power from or supply power to any adjacent blocks. block.power-node-large.description = Has a larger radius than the power node and connects to up to six power sources, sinks or nodes. block.battery.description = Stores power whenever there is an abundance and provides power whenever there is a shortage, as long as there is capacity left. @@ -738,7 +794,6 @@ block.blast-drill.description = The ultimate drill. Requires large amounts of po block.water-extractor.description = Extracts water from the ground. Use it when there is no lake nearby. block.cultivator.description = Cultivates the soil with water in order to obtain biomatter. block.oil-extractor.description = Uses large amounts of power in order to extract oil from sand. Use it when there is no direct source of oil nearby. -block.dart-ship-pad.description = Leave your current vessel and change into a basic fighter aircraft.\nUse the pad by double tapping while standing on it. block.trident-ship-pad.description = Leave your current vessel and change into a reasonably well armored heavy bomber.\nUse the pad by double tapping while standing on it. block.javelin-ship-pad.description = Leave your current vessel and change into a strong and fast interceptor with lightning weapons.\nUse the pad by double tapping while standing on it. block.glaive-ship-pad.description = Leave your current vessel and change into a large, well-armored gunship.\nUse the pad by double tapping while standing on it. @@ -754,7 +809,6 @@ block.titan-factory.description = Produces advanced, armored ground units. block.fortress-factory.description = Produces heavy artillery ground units. block.revenant-factory.description = Produces heavy laser ground units. block.repair-point.description = Continuously heals the closest damaged unit in its vicinity. -block.command-center.description = Allows changing friendly AI behavior. Currently, attack, retreat and patrol commands are supported. block.conduit.description = Basic liquid transport block. Works like a conveyor, but with liquids. Best used with extractors, pumps or other conduits. block.pulse-conduit.description = Zaawansowany blok do przenoszenia cieczy. Transports liquids faster and stores more than standard conduits. block.phase-conduit.description = Zaawansowany blok do przenoszenia cieczy. Używa prądu, aby przenieść ciecz do połączonego phase conduit przez kilka bloków. @@ -768,13 +822,11 @@ block.thermal-pump.description = The ultimate pump. Three times as fast as a mec block.router.description = Akceptuje przedmioty z jednego miejsca i rozdziela je do trzech innych kierunków. Przydatne w rozdzielaniu materiałów z jednego źródła do wielu celów. block.distributor.description = Zaawansowany rozdzielacz, rozdzielający przedmioty do 7 innych kierunków. block.bridge-conveyor.description = Zaawansowany blok transportujący. Pozwala na przenoszenie przedmiotów nawet do 3 bloków na każdym terenie, przez każdy budynek. -block.alpha-mech-pad.description = When given enough power, rebuilds your ship into the[accent] Alpha[] mech. block.item-source.description = Wydziela przedmioty w nieskończoność. Dostępny tylko w trybie sandbox. block.liquid-source.description = Wydziela ciecz w nieskończoność. Dostępny tylko w trybie sandbox. block.item-void.description = Niszczy wszystkie przedmioty, które idą do tego bloku, który nie wymaga prądu. Dostępny tylko w trybie sandbox. block.power-source.description = Wydziela prąd w nieskończoność. Dostępny tylko w trybie sandbox. block.power-void.description = Niszczy całą energię wprowadzoną do tego bloku. Dostępny tylko w trybie sandbox. liquid.water.description = Powszechnie używana do schładzania budowli i przetwarzania odpadów. -liquid.lava.description = Może być przekształcona w [LIGHT_GRAY] kamień[]; używana do generowania prądu lub używana jako amunicja dla niektórych działek. liquid.oil.description = Może się palić, eksplodować lub być używana do schładzania. liquid.cryofluid.description = Najefektywniejsza ciecz do schładzania budowli. diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties index a08ef30ff6..02e46340da 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -1,5 +1,6 @@ credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet!) credits = Creditos +contributors = Translators and Contributors discord = Junte-se ao Discord do Mindustry! (Lá nós falamos em inglês) link.discord.description = O discord oficial do Mindustry link.github.description = Codigo fonte do jogo. @@ -9,78 +10,58 @@ link.itch.io.description = Pagina da Itch.io com os Downloads link.google-play.description = Listamento do google play store link.wiki.description = Wiki oficial do Mindustry linkfail = Falha ao abrir o link\nO Url foi copiado +screenshot = Screenshot saved to {0} gameover = O núcleo foi destruído. gameover.pvp = O time[accent] {0}[] É vitorioso! -sector.gameover = Esse setor foi perdido! Soltar Novamente? -sector.retry = Tentar novamente? highscore = [YELLOW]Novo recorde! -wave.lasted = Você sobreviveu até a onda [accent]{0}[]. -level.highscore = Melhor\npontuação: [accent] {0} -level.delete.title = Confirmar exclusão +stat.wave = Waves Defeated:[accent] {0} +stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} +stat.built = Buildings Built:[accent] {0} +stat.destroyed = Buildings Destroyed:[accent] {0} +stat.deconstructed = Buildings Deconstructed:[accent] {0} +stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = Certeza que quer deletar o mapa "[accent]{0}[]"? +level.highscore = Melhor\npontuação: [accent] {0} level.select = Seleção de Fase level.mode = Modo de Jogo: construction.desktop = Os controles do Desktop foram Mudados.\nPara descelecionar um bloco ou parar de construir, [accent]Use espaço.[]. construction.title = Guia de contrução de blocos -construction =Você selecionou [accent]Modo de construção de blocos[].\n\nPara começar a colocar, Simplesmente clique um lugar valido perto de sua nave.\nUma vez que você selecionou alguns blocos, Clique na caixa para confirmar, E sua nave vai começar a construi-los.\n\n- [accent]Remova blocos[] De sua seleção clicando neles.\n- [accent]Mude a seleção[] Segurando e arrastando qualquer bloco na seleção.\n- [accent]Coloque os blocos em linha[] Clicando e segurando em um lugar vazio e arrastando em uma direção.\n- [accent]Cancele a construção ou seleção[] Pressionando X no canto esquerdo. +construction = Você selecionou [accent]Modo de construção de blocos[].\n\nPara começar a colocar, Simplesmente clique um lugar valido perto de sua nave.\nUma vez que você selecionou alguns blocos, Clique na caixa para confirmar, E sua nave vai começar a construi-los.\n\n- [accent]Remova blocos[] De sua seleção clicando neles.\n- [accent]Mude a seleção[] Segurando e arrastando qualquer bloco na seleção.\n- [accent]Coloque os blocos em linha[] Clicando e segurando em um lugar vazio e arrastando em uma direção.\n- [accent]Cancele a construção ou seleção[] Pressionando X no canto esquerdo. deconstruction.title = Block Deconstruction Guide deconstruction = Você selecionou [accent]O modo de destruição de blocos[].\n\nPara Começar a quebrar, Simplesmente clique num bloco perto da nave.\nQuando tiver selecionados alguns blocos, Aperte a caixa para confirmar, E sua nave vai começar a construir.\n\n- [accent]Remova blocos[] De sua seleção clicando neles.\n- [accent]Remova blocos em uma area[] Clicando e Apertando um lugar vazio então arraste numa direção.\n- [accent]Cancele a construção ou Seleção[] Apertando X no canto Esquerdo. showagain = Não mostrar na proxima sessão -coreattack = < A base está sobre ataque! > -unlocks = Desbloqueados +coreattack = < O núcleo está sobre ataque! > +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = Salvar Jogo loadgame = Carregar Jogo joingame = Entrar no Jogo addplayers = Adicionar/Remover Jogador customgame = Jogo Customizado -sectors = Setores -sector = Setor Selecionado: [LIGHT_GRAY]{0} -sector.time = Tempo: [LIGHT_GRAY]{0} -sector.deploy = Soltar -sector.abandon = Abandonar -sector.abandon.confirm = Certeza que quer abandonar seu progresso nesse setor?\nThis cannot be undone! -sector.resume = Voltar -sector.locked = [scarlet][[Não liberado] -sector.unexplored = [accent][[Inexplorado] -missions = Missões:[LIGHT_GRAY] {0} -mission = Missão:[LIGHT_GRAY] {0} -mission.main = Missão principal:[LIGHT_GRAY] {0} -mission.info = Info da missão -mission.complete = Missão completa! -mission.complete.body = Setor {0},{1} Foi conquistado. -mission.wave = Sobrevive [accent]{0}/{1}[] Onda\nOnda em {2} -mission.wave.enemies = Sobreviva[accent] {0}/{1} []ondas\n{2} inimigos -mission.wave.enemy = Sobreviva[accent] {0}/{1} []Ondas\n{2} Inimigos -mission.wave.menu = Sobreviva[accent] {0} []Ondas -mission.battle = Destrua a base inimiga. -mission.resource.menu = Obtenha {0} x{1} -mission.resource = Obtenha {0}:\n[accent]{1}/{2}[] -mission.block = Criar {0} -mission.unit = Criar {0} Unidade -mission.command = Enviar comando {0} As unidades -mission.linknode = Ligar nodo de energia -mission.display = [accent]Missão:\n[LIGHT_GRAY]{0} -mission.mech = Trocar para Meca[accent] {0}[] -mission.create = Criar[accent] {0}[] +newgame = Novo Jogo none = close = Fechar quit = Sair maps = Mapas continue = Continue -nextmission = Próxima Missão maps.none = [LIGHT_GRAY]Nenhum Mapa Encontrado! about.button = Sobre name = Nome: +noname = Pick a[accent] player name[] first. filename = Nome do arquivo: unlocked = Novo bloco Desbloqueado! -unlocked.plural = Novos Blocos desbloqueados! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. players = {0} Jogadores Ativos players.single = {0} Jogador Ativo server.closing = [accent]Fechando servidor... server.kicked.kick = Voce foi expulso do servidor! server.kicked.serverClose = Servidor Fechado. -server.kicked.sectorComplete = Setor completo. -server.kicked.sectorComplete.text = Sua missão esta completa.\nO servidor vai continuar no proximo setor. server.kicked.clientOutdated = Cliente desatualizado! Atualize seu jogo! server.kicked.serverOutdated = Servidor desatualiado! Peca ao dono para atualizar! server.kicked.banned = Voce foi banido do servidor. @@ -89,6 +70,7 @@ server.kicked.nameInUse = Este nome ja esta sendo usado\nneste servidor. server.kicked.nameEmpty = Voce deve ter pelo menos uma letra ou numero. server.kicked.idInUse = Voce ja esta neste servidor! Conectar com duas contas não é permitido. server.kicked.customClient = Este servidor não suporta construções customizadas. Baixe a versão original. +server.kicked.gameover = Game over! host.info = The [accent]Hospedar[]Botão Hopeda um servidor no Host[scarlet]6567[] e [scarlet]6568.[]\nQualquer um no [LIGHT_GRAY]Wi-fi Ou Internet local[] Pode ver este servidor na lista de servidores.\n\nSe voce quer poder entrar em qualquer servidor em seu ip, [accent]port forwarding[] é requerido.\n\n[LIGHT_GRAY]Note: Se alguem esta com problemas em conectar no seu servidor lan, Tenha certeza que deixou mindustry Acessar sua internet local nas configurações de firewall join.info = Aqui, Você pode entar em um [accent]IP De servidor[] Para conectar, Ou descobrir [accent]Servidores[] Da rede local.\nAmbos os servidores LAN e WAN São suportados.\n\n[LIGHT_GRAY]Note: Não tem uma lista de servidores automaticos; Se você quer conectar ao IP de alguem, Você precisa pedir o IP Ao Rosteador. hostserver = Hospedar servidor @@ -104,7 +86,7 @@ trace = Traçar jogador trace.playername = Nome do jogador: [accent]{0} trace.ip = IP: [accent]{0} trace.id = ID unico: [accent]{0} -trace.android = Cliente Androide: [accent]{0} +trace.android = Cliente Android: [accent]{0} trace.modclient = Cliente Customizado: [accent]{0} trace.totalblocksbroken = Blocos totais quebrados: [accent]{0} trace.structureblocksbroken = Blocos de estrutura quebrados: [accent]{0} @@ -125,7 +107,7 @@ server.outdated.client = [crimson]Cliente desatualizado![] server.version = [lightgray]Versão: {0} server.custombuild = [yellow]Construção customizada confirmban = Certeza que quer banir este jogador? -confirmkick = Certeza que quer kickar o jogador? +confirmkick = Certeza que quer expulsar o jogador? confirmunban = Certeza que quer desbanir este jogador? confirmadmin = Certeza que quer fazer este jogador um administrador? confirmunadmin = Certeza que quer remover o estatus de adminstrador deste jogador? @@ -159,7 +141,6 @@ save.rename.text = Novo jogo: selectslot = Selecione um slot para salvar. slot = [accent]Slot {0} save.corrupted = [accent]Arquivo corrompido ou inválido! -sector.corrupted = [accent]Um arquivo de save Foi encontrado neste setor, Mas o login falhou.\nUm novo foi criado. empty = on = Ligado off = Desligado @@ -169,6 +150,7 @@ save.wave = Horda {0} save.difficulty = Dificuldade: {0} save.date = Último salvamento: {0} save.playtime = Playtime: {0} +warning = Aviso. confirm = Confirmar delete = Excluir ok = OK @@ -200,11 +182,10 @@ custom = Customizado builtin = Built-In map.delete.confirm = Certeza que quer deletar este mapa? Isto não pode ser desfeito! map.random = [accent]Mapa aleatório -map.nospawn = Esse mapa não contém um [yellow]core[] para o jogador Nascer! [ROYAL]blue[] Coloque um [yellow]core[] no editor de mapa. -map.nospawn.pvp = Esse mapa não tem cores inimigos para os jogadores nascerem! Adicione[SCARLET] Cores vermelhos[] no mapa no editor. +map.nospawn = Esse mapa não contém um [yellow]núcleo[] para o jogador Nascer! [ROYAL]blue[] Coloque um [yellow]núcleo[] no editor de mapa. +map.nospawn.pvp = Esse mapa não tem núcleos inimigos para os jogadores nascerem! Adicione[SCARLET] Núcleos vermelhos[] no mapa no editor. map.invalid = Erro ao carregar o mapa: Arquivo de mapa invalido ou corrupto. editor.brush = Pincel -editor.slope = \\ editor.openin = Abrir no Editor editor.oregen = Geração de minério editor.oregen.info = Geração de minério: @@ -259,6 +240,26 @@ tutorial = Tutorial editor = Editor mapeditor = Editor de mapa donate = Doar +abandon = Abandonar +abandon.text = This zone and all its resources will be lost to the enemy. +locked = Trancado +complete = [LIGHT_GRAY]Complete: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Best: {0} +launch = Launch +launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson]Falha ao entrar no servidor: [accent]{0} error.unreachable = Servidor inalcançavel. error.invalidaddress = Endereço invalido. @@ -266,7 +267,20 @@ error.timedout = Desconectado!\nTenha certeza que o Rosteador tenha feito Port f error.mismatch = Erro de pacote:\nPossivel versão do cliente/Servidor incompatibilidade.\nTenha certeza que você e o host tenham a ultima versão! error.alreadyconnected = Já conectado. error.mapnotfound = Arquivo de mapa não encontrado! +error.io = Network I/O error. error.any = Erro de rede desconhecido. +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = Linguagem settings.reset = Restaurar Padrões settings.rebind = Religar @@ -277,7 +291,6 @@ settings.graphics = Gráficos settings.cleardata = Data do jogo limpa... settings.clear.confirm = Certeza que quer limpar a data?\nOque é feito não pode ser desfeito! settings.clearall.confirm = [scarlet]Aviso![]\nIsso vai limpar toda a data, Incluindo saves, mapas, Keybinds e desbloqueados.\nQuando apertar 'ok' Vai apagar toda a data e sair automaticamente. -settings.clearsectors = Limpar setores settings.clearunlocks = Limpar liberados settings.clearall = Limpar tudo paused = Pausado @@ -286,12 +299,15 @@ no = Não info.title = [accent]Informação error.title = [crimson]Ocorreu um Erro. error.crashtitle = Ocorreu um Erro +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Informação do Bloco +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = Capacidade de Energia blocks.powershot = Energia/tiro blocks.targetsair = Mirar no ar -blocks.itemspeed = Unidades mobilizadas +blocks.itemsmoved = Move Speed blocks.shootrange = Alcance blocks.size = Tamanho blocks.liquidcapacity = Capacidade de Líquido @@ -312,16 +328,23 @@ blocks.inputitems = Itens de entrada blocks.outputitem = Itens de saida blocks.drilltier = Furaveis blocks.drillspeed = Velocidade da furadeira base +blocks.maxunits = Max Active Units blocks.liquidoutput = Saida de liquido blocks.liquidoutputspeed = Velocidade da saida de líquido blocks.liquiduse = Uso de liquido blocks.coolant = Esfriador +blocks.liquid = Liquid blocks.coolantuse = Uso do esfriador blocks.inputliquidfuel = Liquido de combustivel blocks.liquidfueluse = Uso do liquido de combustivel blocks.boostitem = Acelerar item blocks.boostliquid = Acelerar líquido blocks.health = Saúde +blocks.heat = Heat +blocks.power = Poder +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = Imprecisão blocks.shots = Tiros blocks.reload = Recarregar @@ -329,11 +352,11 @@ blocks.inputfuel = Combustivel blocks.fuelburntime = Tempo de queima de combustivel blocks.inputcapacity = Capacidade de entrada blocks.outputcapacity = Capacidade de saída +blocks.ammo = Ammo unit.blocks = blocos unit.powersecond = Unidades de energia/segundo unit.liquidsecond = Unidades de líquido/segundo unit.itemssecond = itens/segundo -unit.pixelssecond = pixeis/segundo unit.liquidunits = Unidades de liquido unit.powerunits = Unidades de energia unit.degrees = Graus @@ -346,6 +369,7 @@ category.items = Itens category.crafting = Construindo category.shooting = Atirando category.optional = Melhoras opcionais +setting.indicators.name = Ally Indicators setting.autotarget.name = Alvo automatico setting.fpscap.name = FPS Maximo setting.fpscap.none = Nenhum @@ -378,23 +402,27 @@ category.multiplayer.name = Multijogador command.attack = Atacar command.retreat = Recuar command.patrol = Patrulha +keybind.gridMode.name = Block Select +keybind.gridModeShift.name = Category Select keybind.press = Pressione uma tecla... keybind.press.axis = Pressione uma Axis ou tecla... +keybind.screenshot.name = Map Screenshot keybind.move_x.name = mover_x keybind.move_y.name = mover_y keybind.select.name = selecionar -keybind.break.name = quebrar +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = Deselecionar keybind.shoot.name = Atirar keybind.zoom_hold.name = segurar_zoom -keybind.zoom.name = zoom -keybind.menu.name = menu -keybind.pause.name = pausar +keybind.zoom.name = Zoom +keybind.menu.name = Menu +keybind.pause.name = Pausar keybind.dash.name = Correr keybind.chat.name = Conversa keybind.player_list.name = Lista_de_jogadores keybind.console.name = console -keybind.rotate.name = girar +keybind.rotate.name = Girar keybind.toggle_menus.name = Toggle menus keybind.chat_history_prev.name = Historico do chat anterior keybind.chat_history_next.name = Historico do proximo chat @@ -402,29 +430,28 @@ keybind.chat_scroll.name = Rolar chat keybind.drop_unit.name = Soltar unidade keybind.zoom_minimap.name = Zoom minimap mode.help.title = Descrição dos modos -mode.waves.name = hordas -mode.waves.description = O modo normal. Recursos limitados E os ataques vem automaticamente. -mode.sandbox.name = Caixa de areia +mode.survival.name = Sobrevivencia +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. +mode.sandbox.name = Sandbox mode.sandbox.description = Recursos infinitos E sem tempo para Ataques. mode.freebuild.name = construção \nlivre mode.freebuild.description = recursos limitados e Sem tempo para Ataques. mode.pvp.name = PvP mode.pvp.description = Lutar contra outros jogadores locais. +mode.attack.name = Ataque +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = Itens content.liquid.name = Liquidos content.unit.name = Units -content.recipe.name = Blocos +content.block.name = Blocks content.mech.name = Mecas -item.stone.name = Pedra -item.stone.description = Um Material Incomum Cru. Usado para separar e refinar Em outros materiais,Ou Derreter em Lava. item.copper.name = Cobre item.copper.description = Um material de estrutura util. Usado extensivamente em Maioria dos blocos. item.lead.name = Chumbo item.lead.description = Material de comeco basico. usado intensivamente em Blocos de transporte de liquidos e eletronicos. item.coal.name = Carvão item.coal.description = Combustivel pronto. -item.dense-alloy.name = Liga densa -item.dense-alloy.description = Uma liga densa de chumbo e cobre. Usado na transportação de blocos e mineradoras de alto nivel. +item.graphite.name = Graphite item.titanium.name = Titânio item.titanium.description = Um Material raro super leve, metal usado intensivamente na transportação de líquidos, Brocas e Aeronaves. item.thorium.name = Urânio @@ -437,16 +464,20 @@ item.phase-fabric.name = Fabrica fase item.phase-fabric.description = Uma substancia quase sem peso Usado em eletronica avançada E tecnologia de auto-reparo. item.surge-alloy.name = Liga de surto item.surge-alloy.description = Uma liga com propriedades unicas eletricas. -item.biomatter.name = Biomateria -item.biomatter.description = Um monte de materia organica; Usado na conversão de oleo Ou como oleo basico. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = Areia item.sand.description = Um material comum Que é usado intensivamente em derretimento, Tanto em ligas como fluxo. item.blast-compound.name = Composto de explosão item.blast-compound.description = Um composto volatil usado em bombas em bombas em explosivos. Enquanto pode ser queimado como combustivel, Isso não é recomendado. item.pyratite.name = piratita item.pyratite.description = Substancia extremamente inflamavel usado em armas incendiarias. +item.metaglass.name = Metaglass +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = Água -liquid.lava.name = Lava +liquid.slag.name = Slag liquid.oil.name = Petróleo liquid.cryofluid.name = Crio Fluido mech.alpha-mech.name = Alfa @@ -481,11 +512,10 @@ mech.glaive-ship.weapon = Repetidor de fogo item.explosiveness = [LIGHT_GRAY]Explosividade: {0} item.flammability = [LIGHT_GRAY]Inflamabilidade: {0} item.radioactivity = [LIGHT_GRAY]RadioAtividade: {0} -item.fluxiness = [LIGHT_GRAY]Poder do fluxo: {0} unit.health = [LIGHT_GRAY]Vida: {0} unit.speed = [LIGHT_GRAY]Velocidade: {0} mech.weapon = [LIGHT_GRAY]Arma: {0} -mech.armor = [LIGHT_GRAY]Armadura: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]Capacidade de itens: {0} mech.minespeed = [LIGHT_GRAY]Velocidade de mineração: {0} mech.minepower = [LIGHT_GRAY]Poder de mineração: {0} @@ -493,29 +523,60 @@ mech.ability = [LIGHT_GRAY]Habilidade: {0} liquid.heatcapacity = [LIGHT_GRAY]Capacidade de aquecimento: {0} liquid.viscosity = [LIGHT_GRAY]Viscosidade: {0} liquid.temperature = [LIGHT_GRAY]Temperatura: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](Construindo) block.spawn.name = Spawn dos inimigos -block.core.name = Core -block.metalfloor.name = Chão de metal +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = água funda -block.water.name = água -block.lava.name = lava +block.water.name = Água block.tar.name = Tar -block.blackstone.name = pedra negra -block.stone.name = pedra -block.dirt.name = terra -block.sand.name = areia -block.ice.name = gelo -block.snow.name = neve -block.grass.name = grama -block.shrub.name = Arbusto -block.rock.name = rocha -block.blackrock.name = rocha negra -block.icerock.name = rocha de gelo +block.stone.name = Pedra +block.sand.name = Areia +block.ice.name = Gelo +block.snow.name = Neve +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = Parede de Cobre block.copper-wall-large.name = Parede de Cobre Grande -block.dense-alloy-wall.name = Parede de liga densa -block.dense-alloy-wall-large.name = Parede de liga densa grande +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = Parede de fase block.phase-wall-large.name = Parde de fase grande block.thorium-wall.name = Parede de tório @@ -523,7 +584,6 @@ block.thorium-wall-large.name = Parede larga de tório block.door.name = Porta block.door-large.name = Porta Grande block.duo.name = Dupla -block.scorch.name = Queimar block.hail.name = Hail block.lancer.name = Lancador block.conveyor.name = Esteira @@ -535,46 +595,45 @@ block.sorter.name = Ordenador block.sorter.description = [interact]Aperte no bloco para configurar[] block.overflow-gate.name = Portão Sobrecarregado block.overflow-gate.description = Uma combinação de roteador e divisor Que apenas manda para a esquerda e Direita se a frente estiver bloqueada. -block.smelter.name = Fornalha -block.arc-smelter.name = Fundidora Arc block.silicon-smelter.name = Fundidora de silicio block.phase-weaver.name = Palheta de fase block.pulverizer.name = Pulverizador block.cryofluidmixer.name = Misturador de Crio Fluido block.melter.name = Aparelho de fusão block.incinerator.name = Incinerador -block.biomattercompressor.name = Compressor de bio-matéria +block.spore-press.name = Spore Press block.separator.name = Separador -block.centrifuge.name = Centrifuga block.power-node.name = Célula de energia block.power-node-large.name = Célula de energia Grande +block.surge-tower.name = Surge Tower block.battery.name = Bateria block.battery-large.name = Bateria Grande block.combustion-generator.name = Gerador de combustão block.turbine-generator.name = Gerador de Turbina +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Reator De Impacto block.mechanical-drill.name = Furadera Mecânica block.pneumatic-drill.name = Mineradora Pneumatica block.laser-drill.name = Broca a Laser block.water-extractor.name = Extrator de Agua block.cultivator.name = Cultivador -block.alpha-mech-pad.name = Controle do meca Alfa -block.dart-ship-pad.name = Controle do meca Dart -block.delta-mech-pad.name = Controle do meca Delta -block.javelin-ship-pad.name = Controle do meca Javelin -block.trident-ship-pad.name = Controle do meca Tridente -block.glaive-ship-pad.name = Controle do meca Glaive -block.omega-mech-pad.name = Controle do meca Omega -block.tau-mech-pad.name = Controle do meca Tau +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad +block.delta-mech-pad.name = Controle do mech Delta +block.javelin-ship-pad.name = Controle do mech Javelin +block.trident-ship-pad.name = Controle do mech Tridente +block.glaive-ship-pad.name = Controle do mech Glaive +block.omega-mech-pad.name = Controle do mech Omega +block.tau-mech-pad.name = Controle do mech Tau block.conduit.name = Cano block.mechanical-pump.name = Bomba Mecanica block.item-source.name = Fonte do item block.item-void.name = Item Void block.liquid-source.name = Liquid Source -block.power-void.name = Power Void -block.power-source.name = Power Infinite -block.unloader.name = Unloader +block.power-void.name = Poder Void +block.power-source.name = Poder Infinito +block.unloader.name = Descarregador block.vault.name = Cofre -block.wave.name = Wave +block.wave.name = Onda block.swarmer.name = Swarmer block.salvo.name = Salvo block.ripple.name = Ripple @@ -583,17 +642,16 @@ block.bridge-conveyor.name = Esteira-Ponte block.plastanium-compressor.name = Compressor de Plastanio block.pyratite-mixer.name = Misturador de Piratita block.blast-mixer.name = Misturador de Explosão -block.solidifer.name = Solidificador block.solar-panel.name = Painel Solar block.solar-panel-large.name = Painel Solar Grande -block.oil-extractor.name = Extrator de Oleo +block.oil-extractor.name = Extrator de Óleo block.spirit-factory.name = Fabrica de Drone Spirit block.phantom-factory.name = Fabrica de Drone Phantom block.wraith-factory.name = Fabrica de Drone Wraith block.ghoul-factory.name = Fabrica de Bombardeiro Ghoul -block.dagger-factory.name = Fabrica de meca Dagger -block.titan-factory.name = Fabrica de meca titan -block.fortress-factory.name = Fabrica de meca Fortress +block.dagger-factory.name = Fabrica de mech Dagger +block.titan-factory.name = Fabrica de mech titan +block.fortress-factory.name = Fabrica de mech Fortress block.revenant-factory.name = Fabrica de lutadores Revenant block.repair-point.name = Ponto de Reparo block.pulse-conduit.name = Conduto de Pulso @@ -604,7 +662,6 @@ block.liquid-junction.name = Junção de Líquido block.bridge-conduit.name = Conduto-Ponte block.rotary-pump.name = Bomba Rotatoria block.thorium-reactor.name = Reator Torio -block.command-center.name = Centro De Comando block.mass-driver.name = Drive de Massa block.blast-drill.name = Mineradora de Explosão block.thermal-pump.name = Cano termico @@ -612,7 +669,7 @@ block.thermal-generator.name = Gerador Térmico block.alloy-smelter.name = Fundidora de Liga block.mend-projector.name = Projetor Mend block.surge-wall.name = Parede de Surge -block.surge-wall-large.name = Parede de surge grande +block.surge-wall-large.name = Parede de Surge grande block.cyclone.name = Ciclone block.fuse.name = Fundir block.shock-mine.name = Mina de Choque @@ -623,20 +680,21 @@ block.rtg-generator.name = Gerador RTG block.spectre.name = Espectra block.meltdown.name = Derreter block.container.name = Container -block.core.description = A mais importante construção do jogo. +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = Azul team.red.name = Vermelho team.orange.name = Laranja team.none.name = Cinza team.green.name = Verde team.purple.name = Roxo -unit.alpha-drone.name = Drone alfa unit.spirit.name = Drone Spirit unit.spirit.description = A unidade de drone inicial. Ele nasce no core por padrão. Minera minérios automaticamente, Coleta itens e repara blocos. unit.phantom.name = Drone Phantom unit.phantom.description = Uma unidade de drone avançada. Minera minérios automaticamente, Coleta itens e repara blocos automaticamente. Significantemente mais efetiva. unit.dagger.name = Dagger unit.dagger.description = Unidade terrestre basica, Forte em grupos. +unit.crawler.name = Crawler unit.titan.name = Titan unit.titan.description = Uma unidade armadurada terreste avancada. Usa carbide como munição. Ataca ambas as unidades de Aereas e terrestres. unit.ghoul.name = Bombardeiro Ghoul @@ -646,7 +704,11 @@ unit.wraith.description = Uma unidade rapida, Interceptadora de bater e correr. unit.fortress.name = Fortaleza unit.fortress.description = Uma unidade pesada de artilharia terrestre. unit.revenant.name = Revenant -unit.revenant.description = Uma plataforma de laser pesada. +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = Sua missão aqui é de erradicar[LIGHT_GRAY] Inimigo[].\n\nComeçe por[accent] Minerar cobre[]. Clique numa veia de cobre perto de seu core para fazer isso. tutorial.drill = Minerar manualmente é ineficiente.\n[accent]Mineradoras []podem minerar automaticamente.\nColoque uma numa veia de cobre. tutorial.conveyor = [accent]Esteiras[] São usadas para transportar itens até o core.\nFaça uma linha de Esteiras da mineradora até o core. @@ -670,8 +732,6 @@ tutorial.dagger = Ligue os nodos de energia a fabrica.\nQuando os requerimentos tutorial.battle = O[LIGHT_GRAY] Inimigo[] revelou seu core.\nDestrua com sua unidade e Dagger's. block.copper-wall.description = Um bloco defensivo e barato.\nUtil para proteger o core e torres no começo. block.copper-wall-large.description = Um bloco defensivo e barato.\nUtil para proteger o core e torres no começo.\nOcupa multiplos espaços. -block.dense-alloy-wall.description = Um bloco defensivo padrão.\nProteção adequada contra inimigos. -block.dense-alloy-wall-large.description = Um bloco defensivo padrão.\nProteção adequada contra inimigos.\nOcupa multiplos espaços. block.thorium-wall.description = A strong defensive block.\nBoa proteção contra inimigos. block.thorium-wall-large.description = Um bloco grande e defensivo.\nBoa proteção contra inimigos.\nOcupa multiplos espaços. block.phase-wall.description = Não tão forte quanto a parede de torio Mas vai defletir balas a menos que seja muito forte. @@ -701,8 +761,6 @@ block.titanium-conveyor.description = Bloco de transporte de item avancado. Move block.phase-conveyor.description = Bloco de transporte de item avançado. Usa energia para teleportar itens a uma esteira de fase sobre uma severa distancia. block.junction.description = Funciona como uma ponte Para duas esteiras que estejam se cruzando. Util em situações que tenha duas esteiras diferentes carregando materiais diferentes para lugares diferentes. block.mass-driver.description = Bloco de transporte de itens supremo. Coleta itens severos e atira eles em outro mass driver de uma longa distancia. -block.smelter.description = Queima carvão para derreter cobre e chumbo em liga densa. -block.arc-smelter.description = Derrete Cobre e chumbo em liga densa usando energia exterior. block.silicon-smelter.description = Reduz areia a coque altamente puro Para fazer silicio. block.plastanium-compressor.description = Produz plastanio para usando oleo e titanio. block.phase-weaver.description = Produz tecido de fase de torio radioativo e grandes quantidades de areia. @@ -711,12 +769,10 @@ block.pulverizer.description = Esmaga pedra em areia. Util quando esta em falta block.pyratite-mixer.description = Mistura carvão, Cobre e areia em piratite altamente inflamavel block.blast-mixer.description = Usa oleo em Transformar piratite em composto de explosão menos inflamavel mas mais explosivo block.cryofluidmixer.description = Combina agua e titanio em cryo fluido que é mais eficiente em esfriar. -block.solidifer.description = Esfria lava em pedra em um ritmo rapido. block.melter.description = Aquece pedra em altas temperaturas para fazer lava. block.incinerator.description = Se livra de itens em excesso ou liquidos. -block.biomattercompressor.description = Compressa Biomassa para recuperar oleo. +block.spore-press.description = Compresses spore pods into oil. block.separator.description = Expos pedra em agua em pressão para ter varios mineiras contendo na pedra. -block.centrifuge.description = Mais eficiente que o separador, Mas mais caro e precisa de energia. block.power-node.description = Transmite poder em nodos. Maximo de 4 fontes de energia, sinks ou nodos podem ser conectados. Os nodos vão receber energia de ou dar energia para qualquer bloco adjacente. block.power-node-large.description = Tem um raio maior que o nodo de energia e pode conectar até 6 fontes de energia, sinks ou nodos. block.battery.description = Guarda energia sempre que tiver em abundancia e da energia sempre que precisar enquanto tiver capacidade. @@ -738,7 +794,6 @@ block.blast-drill.description = A melhor mineradora. Requer muita energia. block.water-extractor.description = Extrai agua do chão. Use quando não tive nenhum lago proximo block.cultivator.description = Cultiva o solo com agua para pegar bio materia. block.oil-extractor.description = Usa altas quantidades de energia Para extrair oleo da areia. Use quando não tiver fontes de oleo por perto -block.dart-ship-pad.description = Deixe sua atual embarcação e mude para uma aeronave lutadora basica.\nUse o pad clicando duas vezes em cima enquando fica em cima dele. block.trident-ship-pad.description = Deixe sua atual embarcação e mude para um bombardeiro resionavelmente bem armadurado.\nUse o pad clicando duas vezes em cima enquando fica em cima dele. block.javelin-ship-pad.description = Deixe sua atual embarcação e mude para um interceptador forte e rapido com armas de raio.\nUse o pad clicando duas vezes em cima enquando fica em cima dele. block.glaive-ship-pad.description = Deixe sua atual embarcação e mude para grande, bem armadurada nave de combate.\nUse o pad clicando duas vezes em cima enquando fica em cima dele. @@ -754,7 +809,6 @@ block.titan-factory.description = Produz unidades avancadas, armaduradas e terre block.fortress-factory.description = Produz unidades terrestres pesadas de artilharia. block.revenant-factory.description = Produz unidades laser, pesadas e terrestres. block.repair-point.description = Continuamente repara a unidade danificada mais proxima. -block.command-center.description = Permite mudar o comportamento IA dos aliados. Atualmente, atacar, recuar e patrulha são suportados. block.conduit.description = Bloco de transporte de liquido basico. Funciona como a esteira, Mas com liquidos. Melhor usado com extratores, Bombas ou condutos. block.pulse-conduit.description = Bloco avancado de transporte de liquido. Transporta liquidos mais rapido E armazena mais que os condutos padrões. block.phase-conduit.description = Bloco avancado de transporte de liquido. Usa energia para teleportar liquidos conduto de fase sobre uma distancia severa. @@ -768,13 +822,11 @@ block.thermal-pump.description = A melhor bomba. Trez vezes mais rapida que a bo block.router.description = Aceita itens de uma direção e os divide em 3 direções igualmente. Util para espalhar materiais da fonte para multiplos alvos. block.distributor.description = Um roteador avancada que espalhas os itens em 7 outras direções igualmente. block.bridge-conveyor.description = Bloco de transporte de itens avancado. Possibilita o transporte de itens acima de 3 blocos de construção ou paredes. -block.alpha-mech-pad.description = Quando dado energia o suficiente, Reconstrua sua nave em [accent] Alpha[] mech. block.item-source.description = Infinivamente da itens. Apenas caixa de areia. block.liquid-source.description = Infinitivamente da Liquidos. Apenas caixa de areia. block.item-void.description = Destroi qualquer item que entre sem requerir energia. Apenas caixa de areia. block.power-source.description = Infinitivamente da energia. Apenas caixa de areia. block.power-void.description = Destroi qualquer energia que entre dentro. Apenas caixa de areia. liquid.water.description = Comumente usado em resfriamento e no processo de perda. -liquid.lava.description = Pode ser transformado em[LIGHT_GRAY] pedra[], usado para gerar energia ou usado como munição para certas torres. liquid.oil.description = Pode ser queimado, explodido ou usado como resfriador. liquid.cryofluid.description = A maneira mais eficiente de resfriar qualquer coisa. diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index feeda265f1..c81158f62d 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -1,6 +1,6 @@ -credits.text = Создатель [ROYAL] Anuken. - [SKY]anukendev@gmail.com[][]\n\nЕсть недоработки в переводе?\nПишите в офф. discord-сервер mindustry в канал #русский.\n\nПереводчики на русский язык:\n[YELLOW]Prosta4ok_ua\n[GREEN]xga\n[BLACK]XZimur\n[BLUE]Beryllium +credits.text = Создатель [ROYAL] Anuken. - [SKY]anukendev@gmail.com[][]\n\nЕсть недоработки в переводе или хотите найти союзников для совместной игры?\nПишите в офф. discord-сервер Mindustry в канал #русский.\n\nПереводчики на русский язык:\n[YELLOW]Prosta4ok_ua\n[BLACK]XZimur\n[BLUE]Beryllium credits = Авторы -contributors = Переводчики и контрибьюторы +contributors = Переводчики и Помощники discord = Присоединяйтесь к нашему Discord! link.discord.description = Официальный discord-сервер Mindustry link.github.description = Исходный код игры @@ -10,78 +10,58 @@ link.itch.io.description = itch.io страница с загрузкой ПК link.google-play.description = Скачать для Android c Google play link.wiki.description = Официальная вики Mindustry(англ.) linkfail = Не удалось открыть ссылку!\nURL-адрес был скопирован в буфер обмена. +screenshot = Cкриншот сохранён в {0} gameover = Игра окончена gameover.pvp = [accent] {0}[] команда победила! -sector.gameover = Этот сектор потерян. Высадиться повторно? -sector.retry = Повторить попытку highscore = [YELLOW]Новый рекорд! -wave.lasted = Вы продержались до [accent]{0}[]-ой волны. -level.highscore = Рекорд: [accent]{0} -level.delete.title = Подтвердите удаление +stat.wave = Волн отражено:[accent] {0} +stat.enemiesDestroyed = Врагов уничтожено:[accent] {0} +stat.built = Строений построено:[accent] {0} +stat.destroyed = Строений уничтожено:[accent] {0} +stat.deconstructed = Строений деконструировано:[accent] {0} +stat.delivered = Ресурсов добыто: +stat.rank = Финальный Счёт: [accent]{0} map.delete = Вы действительно хотите удалить карту "[accent]{0}[]"? +level.highscore = Рекорд: [accent]{0} level.select = Выбор карты level.mode = Режим игры: construction.desktop = Чтобы отменить выбор блока или остановить строительство, [accent] используйте пробел[]. construction.title = Руководство по размещению блоков -construction = Вы только что перешли в режим размещения[accent]блоков[].\n\nЧтобы начать размещение, просто коснитесь подходящего места рядом с вашим мехом.\nПосле того, как вы поставили несколько блоков, нажмите на галочку, чтобы подтвердить, и ваш мех начнет их строительство.\n\n- [accent]Удалите блоки [] из вашего плана строительства, нажав на них.n- [accent]Нажав Shift [] и, удерживая, перетащите любой выбранный блок.\n- [accent]Поместите блоки в линию [], нажимая и удерживая на пустое место, а затем перетаскивая в любом направлении.\n- [accent]Отмените размещение блоков [], нажав X в нижнем правом углу. +construction = Вы только что перешли в режим размещения[accent]блоков[].\n\nЧтобы начать размещение, просто коснитесь подходящего места рядом с вашим мехом.\nПосле того, как вы поставили несколько блоков, нажмите на галочку, чтобы подтвердить, и ваш мех начнет их строительство.\n\n- [accent]Удалите блоки [] из вашего плана строительства, нажав на них.n- [accent]Нажав Shift [] и, удерживая, перетащите любой выбранный блок.\n- [accent]Поместите блоки в линию [], нажимая и удерживая на пустое место, а затем перетаскивая в любом направлении.\n- [accent]Отмените размещение блоков [], нажав X в нижнем правом углу. deconstruction.title = Руководство по разрушению блоков -deconstruction = Вы только что перешли в режим сноса[accent] блоков.[].\n\nЧтобы начать удалять, просто нажмите на блок рядом с вашим мехом.\nПосле того как вы выбрали несколько блоков, нажмите на галочку, чтобы подтвердить, и ваш мех начнёт их сносить.\n\n- [accent]Уберите блоки [] из вашего выбора, нажав на них.\n- [accent]Удалите блоки в области [], нажав и удерживая на пустом месте, а затем перетаскивая в нужном направлении.\n- [accent]Отменить снос или выбор [] можно нажав X в нижнем правом углу. +deconstruction = Вы только что перешли в режим сноса[accent] блоков.[].\n\nЧтобы начать удалять, просто нажмите на блок рядом с вашим мехом.\nПосле того как вы выбрали несколько блоков, нажмите на галочку, чтобы подтвердить, и ваш мех начнёт их сносить.\n\n- [accent]Уберите блоки [] из вашего выбора, нажав на них.\n- [accent]Удалите блоки в области [], нажав и удерживая на пустом месте, а затем перетаскивая в нужном направлении.\n- [accent]Отменить снос или выбор [] можно нажав X в нижнем правом углу. showagain = Не показывать снова до следующей сессии coreattack = < Ядро находится под атакой! > -unlocks = Разблокированные +nearpoint = [[ [scarlet]ПОКИНЬТЕ ЗОНУ НЕМЕДЛЕННО[] ]\nаннигиляция неизбежна. +outofbounds = [[ ЗА ГРАНИЦАМИ ]\n[]самоуничтожение через{0} +database = База Данных Ядра savegame = Сохранить игру loadgame = Загрузить игру -joingame = Присоеди\nниться +joingame = Сетевая игра addplayers = Доб/удалить игроков customgame = Пользовательская игра -sectors = Секторы -sector = Выбранный сектор: [LIGHT_GRAY]{0} -sector.time = Время: [LIGHT_GRAY]{0} -sector.deploy = Высадиться -sector.abandon = Отступить -sector.abandon.confirm = Вы уверены, что хотите отступить?\nПрогресс на секторе нельзя восстановить! -sector.resume = Продолжить -sector.locked = [scarlet][[Не завершён] -sector.unexplored = [accent][[Неисследованный] -missions = Миссий:[LIGHT_GRAY] {0} -mission = Миссия:[LIGHT_GRAY] {0} -mission.main = Главная миссия:[LIGHT_GRAY] {0} -mission.info = Информация о миссии -mission.complete = Миссия выполнена! -mission.complete.body = Сектор {0},{1} был завоёван. -mission.wave = Волна[accent] {0}[] из[accent] {1}[]\nВолна через {2} -mission.wave.enemies = Волна[accent] {0} из {1}[]\n{2} враг. -mission.wave.enemy = Волна[accent] {0} из {1}[]\n{2} враг -mission.wave.menu = Пережить[accent] {0} []волн -mission.battle = Уничтожьте ядро противника. -mission.resource.menu = Добыть {0} х{1} -mission.resource = Добыть {0}:\n[accent]{1}/{2}[] -mission.block = Создать {0} -mission.unit = Создать {0} боев. ед. -mission.command = Отправить команду {0} к боев. единицам -mission.linknode = Соединить силовые узлы -mission.display = [accent]Миссия:\n[LIGHT_GRAY]{0} -mission.mech = Переключиться на мех[accent] {0}[] -mission.create = Создать[accent] {0}[] +newgame = Новая игра none = <нет> close = Закрыть quit = Выход maps = Карты continue = Продолжить -nextmission = Следующая миссия maps.none = [LIGHT_GRAY]Карты не найдены! about.button = Об игре name = Ник: +noname = Для начала, придумайте[accent] себе никнейм[]. filename = Имя файла: -unlocked = Новый блок разблокирован! -unlocked.plural = Новые блоки разблокированы! +unlocked = Новый контент разблокирован! +completed = [accent]Завершено +techtree = Технологическое Дерево +research.list = [LIGHT_GRAY]Исследование: +research = Исследование +researched = [LIGHT_GRAY]{0} исследовано. players = Игроков на сервере: {0} players.single = {0} игрок на сервере server.closing = [accent]Закрытие сервера... server.kicked.kick = Вас выгнали с сервера! server.kicked.serverClose = Сервер закрыт. -server.kicked.sectorComplete = Сектор завоёван. -server.kicked.sectorComplete.text = Ваша миссия завершена.\nСервер продолжит работу и высадит вас в следующем секторе. server.kicked.clientOutdated = Устаревший клиент! Обновите игру! server.kicked.serverOutdated = Устаревший сервер! Попросите хоста обновить сервер/игру! server.kicked.banned = Вы заблокированы на этом сервере. @@ -90,6 +70,7 @@ server.kicked.nameInUse = На этом сервере есть кто-то с server.kicked.nameEmpty = Ваше имя должно содержать хотя бы один символ или цифру. server.kicked.idInUse = Вы уже на этом сервере! Соединение с двумя учетными записями не разрешено. server.kicked.customClient = Этот сервер не поддерживает пользовательские сборки. Загрузите официальную версию. +server.kicked.gameover = Игра окончена! host.info = Кнопка [accent] Сервер [] размещает сервер на порт [accent]6567[].[]\nЛюбой пользователь в той же [LIGHT_GRAY]сети [] получет возможность видеть ваш сервер в своём списке серверов.\n\nЕсли вы хотите, чтобы люди могли подключаться из любого места по IP, то требуется переадресация(проброс) портов.[].\n\n[LIGHT_GRAY] Примечание. Если у кого-то возникают проблемы с подключением к вашей локальной сети, убедитесь, что вы разрешили Mindustry доступ к вашей локальной сети в настройках брандмауэра. join.info = Здесь вы можете ввести IP-адрес [accent]сервера[] для подключения или открыть [accent]локальную сеть [] для подключения к другим серверам.\nПоддерживается многопользовательский режим LAN и WAN.\n\n[LIGHT_GRAY] Примечание: это не является автоматическим глобальным списком серверов; если вы хотите подключиться к кому-то по IP, вам нужно будет спросить у хоста его IP-адрес. hostserver = Запустить сервер @@ -160,7 +141,6 @@ save.rename.text = Новое название: selectslot = Выберите сохранение. slot = [accent]Слот {0} save.corrupted = [accent]Сохранённый файл повреждён или имеет недействительный формат!\nЕсли вы только что обновили свою игру, это, вероятно, из-за изменение формата сохранения[scarlet], а не []ошибка. -sector.corrupted = [accent] Файл сохранения для этого сектора был найден, но загрузка не удалась.\nСоздан новый файл. empty = <Пусто> on = Вкл off = Выкл @@ -170,6 +150,7 @@ save.wave = Волна: {0} save.difficulty = Сложность: {0} save.date = Последнее сохранение: {0} save.playtime = Время в игре: {0} +warning = Предупреждение confirm = Подтверждение delete = Удалить ok = ОК @@ -205,7 +186,6 @@ map.nospawn = Эта карта не имеет ядер, в которых иг map.nospawn.pvp = У этой карты нет вражеских ядер, в которых игрок может появиться! Добавьте[SCARLET] красные[] ядра к этой карте в редакторе. map.invalid = Ошибка загрузки карты: повреждённый или недопустимый файл карты. editor.brush = Кисть -editor.slope = \\ editor.openin = Открыть в редакторе editor.oregen = Генерация Руд editor.oregen.info = Генерация Руд: @@ -260,14 +240,47 @@ tutorial = Обучение editor = Редактор mapeditor = Редактор карт donate = Пожертво\nвать +abandon = Покинуть +abandon.text = Эта зона и все ресурсы будут потеряны. +locked = Заблокировано +complete = [LIGHT_GRAY]Завершено: +resume = Возобновить зону:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Наилучшая волна: {0} +launch = < ЗАПУСК > +launch.title = Запуск успешен +launch.next = [LIGHT_GRAY]следующая возможность на волне {0} +launch.unable = [scarlet]ЗАПУСК невозможен.[] {0} Враг. +launch.confirm = Это удалит все ресурсы в Вашем ядре.\nВы не сможете вернуться на эту базу. +uncover = Раскрыть +configure = Выгрузить конфигурацию +configure.locked = [LIGHT_GRAY]Разблокировать настройки выгрузки:\nВолна {0}. +zone.unlocked = [LIGHT_GRAY]{0} разблокировано. +zone.complete = {0} волн достигнуто:\nНовые требования зоны выполнены. +zone.config.complete = {0} волн достигнуто:\nВыгружаемая конфигурация разблокирована +zone.resources = Обнаруженные ресурсы: +add = Добавить... +boss.health = Здоровье босса connectfail = [crimson]Не удалось подключиться к серверу: [accent] {0} error.unreachable = Сервер недоступен. error.invalidaddress = Некорректный адрес. error.timedout = Время ожидания истекло!\nУбедитесь, что хост настроен для перенаправления портов и адрес корректный! -error.mismatch = Ошибка пакета:\nвозможное несоответствие версии клиента/сервера. \nУбедитесь, что у Вас и у владельца сервера установлена последняя версия Mindustry! +error.mismatch = Ошибка пакета:\nвозможное несоответствие версии клиента/сервера. \nУбедитесь, что у Вас и у создателя сервера установлена последняя версия Mindustry! error.alreadyconnected = Вы уже подключены. -error.mapnotfound = Не найден файл карты! +error.mapnotfound = Файл карты не найден! +error.io = Сетевая ошибка ввода-вывода. error.any = Неизвестная сетевая ошибка. +zone.groundZero.name = Нулевая земля +zone.craters.name = Кратеры +zone.frozenForest.name = Ледяной Лес +zone.ruinousShores.name = Разрушенные Берега +zone.crags.name = Утёсы +zone.stainedMountains.name = Окрашенные горы +zone.impact0079.name = Удар 0079 +zone.desolateRift.name = Пустынный Разлом +zone.arcticDesert.name = Арктическия Пустыня +zone.dryWastes.name = Грязные Отходы +zone.nuclearComplex.name = Ядерный Производственный Комплекс +zone.moltenFault.name = Расплавленый Разлом settings.language = Язык settings.reset = Сбросить по умолчанию settings.rebind = Смена @@ -278,7 +291,6 @@ settings.graphics = Графика settings.cleardata = Очистить данные ... settings.clear.confirm = Вы действительно хотите очистить свои данные?\nТо, что сделано, нельзя отменить! settings.clearall.confirm = [scarlet]ОСТОРОЖНО![]\nЭто уничтожит все данные, включая сохранения, карты, разблокированное и настройки управления.\nПосле того как вы нажмете ОК, игра уничтожит все данные и автоматически закроется. -settings.clearsectors = Очистить секторы settings.clearunlocks = Очистить разблокированное settings.clearall = Очистить всё paused = Пауза @@ -287,12 +299,15 @@ no = Нет info.title = Информация error.title = [crimson]Произошла ошибка error.crashtitle = Произошла ошибка +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Информация о блоке +blocks.powerbalance = Энергия: {0} +blocks.poweroutput = Выходная энергия: {0} blocks.powercapacity = Вместимость энергии blocks.powershot = Энергия/выстрел -blocks.targetsair = Атакует воздуш. юнитов? -blocks.itemspeed = Скорость перемещения ресурсов +blocks.targetsair = Атакует воздуш. юнитов +blocks.itemsmoved = Скорость перемещения blocks.shootrange = Радиус действия blocks.size = Размер blocks.liquidcapacity = Вместимость жидкости @@ -313,16 +328,23 @@ blocks.inputitems = Входящие предметы blocks.outputitem = Выходящий предмет blocks.drilltier = Добывает blocks.drillspeed = Базовая скорость сверления +blocks.maxunits = Max Active Units blocks.liquidoutput = Выходящая жидкость blocks.liquidoutputspeed = Выходная скорость жидкости blocks.liquiduse = Используется жидкости blocks.coolant = Охлаждающая жидкость +blocks.liquid = Жидкость blocks.coolantuse = Охлажд. жидкости используется blocks.inputliquidfuel = Жидкое топливо blocks.liquidfueluse = Жидкого топлива используется blocks.boostitem = Ускоряющий предмет blocks.boostliquid = Ускоряющая жидкость blocks.health = Здоровье +blocks.heat = Heat +blocks.power = Энергия +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Энергии хватает blocks.inaccuracy = Разброс blocks.shots = Выстрелы blocks.reload = Выстрелы/секунду @@ -330,11 +352,11 @@ blocks.inputfuel = Входящее топливо blocks.fuelburntime = Время горения топлива blocks.inputcapacity = Макс. вместимость входящих предметов blocks.outputcapacity = Макс. вместимость выходящих предметов +blocks.ammo = Боеприпасы unit.blocks = блоки unit.powersecond = единиц энергии/секунду unit.liquidsecond = жидкостных единиц/секунду unit.itemssecond = предметов/секунду -unit.pixelssecond = пикселей/секунду unit.liquidunits = жидкостных единиц unit.powerunits = энерг. единиц unit.degrees = град. @@ -345,8 +367,9 @@ category.power = Энергия category.liquids = Жидкости category.items = Предметы category.crafting = Создание -category.shooting = Стрельба +category.shooting = Cтрельба category.optional = Дополнительные улучшения +setting.indicators.name = Показывать в сторону союзников setting.autotarget.name = Авто-цель setting.fpscap.name = Макс. FPS setting.fpscap.none = Неограниченный @@ -375,16 +398,20 @@ setting.crashreport.name = Отправлять анонимные отчёты keybind.title = Настройка управления category.general.name = Основное category.view.name = Просмотр -category.multiplayer.name = Мультиплеер +category.multiplayer.name = Сетевая игра command.attack = Атаковать command.retreat = Отступить command.patrol = Патрулирование +keybind.gridMode.name = Выбрать блок +keybind.gridModeShift.name = Выбрать категорию keybind.press = Нажмите клавишу... keybind.press.axis = Нажмите клавишу... +keybind.screenshot.name = Скриншот карты keybind.move_x.name = Движение по оси x keybind.move_y.name = Движение по оси y keybind.select.name = Выбор/Выстрел -keybind.break.name = Разрушение +keybind.pick.name = Выбрать блок +keybind.break_block.name = Разрушить блок keybind.deselect.name = Отмена keybind.shoot.name = Выстрел keybind.zoom_hold.name = Управление масштабом @@ -403,29 +430,28 @@ keybind.chat_scroll.name = Прокрутка чата keybind.drop_unit.name = Сбросить юнита keybind.zoom_minimap.name = Увеличить миникарту. mode.help.title = Описание режимов -mode.waves.name = Волны -mode.waves.description = Обычный режим. В режиме "Волны" надо самим добывать ресурсы и сами волны идут безостановочно. +mode.survival.name = Выживание +mode.survival.description = Обычный режим. В этом режиме надо самим добывать ресурсы и сами волны идут безостановочно. mode.sandbox.name = Песочница mode.sandbox.description = Бесконечные ресурсы и нет таймера для волн, но можно самим вызвать волну. -mode.freebuild.name = Свободная\nстройка +mode.freebuild.name = Cвободная\nстройка mode.freebuild.description = Ограниченные ресурсы и нет таймера для волн. mode.pvp.name = Противо-\nстояние mode.pvp.description = боритесь против других игроков. +mode.attack.name = Атака +mode.attack.description = Нет волн, цель - уничтожить базу противника. content.item.name = Предметы content.liquid.name = Жидкости content.unit.name = Боевые единицы -content.recipe.name = Блоки +content.block.name = Блоки content.mech.name = Мехи -item.stone.name = Камень -item.stone.description = Обычное сырьё. Используется для разделения и переработки в другие материалы или переплавки в лаву. item.copper.name = Медь item.copper.description = Полезный строительный материал. Широко используется во всех типах блоков. item.lead.name = Свинец item.lead.description = Основной начальный материал. Широко используется в электронике и транспортировке жидкости. item.coal.name = Уголь item.coal.description = Распространённое и легкодоступное топливо. -item.dense-alloy.name = Плотный сплав -item.dense-alloy.description = Жёсткий сплав, изготовленный из свинца и меди. Используется в передовых транспортных блоках и высокоуровневых бурах. +item.graphite.name = Графит item.titanium.name = Титан item.titanium.description = Редкий сверхлёгкий металл широко используется в производстве: транспорта, буров и самолётов. item.thorium.name = Торий @@ -436,22 +462,26 @@ item.plastanium.name = Пластиний item.plastanium.description = Легкий, пластичный материал, используемый в современных самолетах и боеприпасах для фрагментации. item.phase-fabric.name = Фазовая ткань item.phase-fabric.description = Невесомое вещество, используемое в современной электронике и технологии самовосстановления. Не для вышивания. -item.surge-alloy.name = Высокопрочный сплав +item.surge-alloy.name = Кинетический сплав item.surge-alloy.description = Передовой сплав с уникальными электрическими свойствами. -item.biomatter.name = Биоматерия -item.biomatter.description = Скопление органической кашки; используется для переработки в нефть или в качестве топлива. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = Песок item.sand.description = Обычный материал, который широко используется при плавке как в сплаве, так и в виде шлака. item.blast-compound.name = Взрывоопасное соединение item.blast-compound.description = Летучее соединение, используемое в бомбах и взрывчатых веществах. Также может гореть в качестве топлива, но не рекомендуется этого делать. item.pyratite.name = Пиротит item.pyratite.description = Очень огнеопасное вещество, используемое в зажигательном оружии. +item.metaglass.name = Биостекло +item.metaglass.description = Сверхпрочная смесь стекла. Широко используется для распределения и хранения жидкости. +item.scrap.name = Металлолом +item.scrap.description = Остатки старых сооружений и подразделений. Содержит незначительные количества многих различных металлов. liquid.water.name = Вода -liquid.lava.name = Лава +liquid.slag.name = Шлак liquid.oil.name = Нефть liquid.cryofluid.name = Криогенная жидкость mech.alpha-mech.name = Альфа -mech.alpha-mech.weapon = Обычный пулемёт +mech.alpha-mech.weapon = Тяжёлый пулемёт mech.alpha-mech.ability = Призыв дронов mech.alpha-mech.description = Стандартный мех для настольных устройств. Имеет приличную скорость и урон; может создать до 3-х дронов для увеличения возможности победы. mech.delta-mech.name = Дельта @@ -463,8 +493,8 @@ mech.tau-mech.weapon = Восстановительный лазер mech.tau-mech.ability = Регенирирующая вспышка mech.tau-mech.description = Мех поддержки. Чинит союзные блоки, стреляя в них. Может исцелить союзников радиусом с его способностью восстанавления. mech.omega-mech.name = Омега -mech.omega-mech.weapon = Ракетомётный пулемёт -mech.omega-mech.ability = Защитная +mech.omega-mech.weapon = Ракетомётная пулемёт +mech.omega-mech.ability = Поглощение урона mech.omega-mech.description = Громоздкий и хорошо бронированный мех, сделанный для фронтовых нападений. Его способность брони может блокировать до 90% входящего урона. mech.dart-ship.name = Дротик mech.dart-ship.weapon = Ретранслятор @@ -475,18 +505,17 @@ mech.javelin-ship.weapon = Взрывные ракеты mech.javelin-ship.ability = Дуговой генератор mech.trident-ship.name = Трезубец mech.trident-ship.description = Тяжелый бомбардировщик. Довольно хорошо бронирован. -mech.trident-ship.weapon = Грузовой отсек с бомбами +mech.trident-ship.weapon = Бомбы mech.glaive-ship.name = Копьё mech.glaive-ship.description = Большой, хорошо бронированный боевой корабль. Оснащён зажигательным ретранслятором. Хорошее ускорение и максимальная скорость. mech.glaive-ship.weapon = Огненный пулемёт item.explosiveness = [LIGHT_GRAY]Взрывоопасность: {0}% item.flammability = [LIGHT_GRAY]Воспламеняемость: {0}% item.radioactivity = [LIGHT_GRAY]Радиоактивность: {0}% -item.fluxiness = [LIGHT_GRAY]Осадочность: {0}% unit.health = [LIGHT_GRAY]Здоровье: {0} unit.speed = [LIGHT_GRAY]Скорость: {0} mech.weapon = [LIGHT_GRAY]Оружие: {0} -mech.armor = [LIGHT_GRAY]Броня: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]Вместимость предметов: {0} mech.minespeed = [LIGHT_GRAY]Скорость добычи: {0} mech.minepower = [LIGHT_GRAY]Мощность добычи: {0} @@ -494,30 +523,60 @@ mech.ability = [LIGHT_GRAY]Способность: {0} liquid.heatcapacity = [LIGHT_GRAY]Теплоёмкость: {0} liquid.viscosity = [LIGHT_GRAY]Вязкость: {0} liquid.temperature = [LIGHT_GRAY]Температура: {0} -block.constructing = {0}[LIGHT_GRAY](В процессе) +block.scrap-wall.name = Стена из металлолома +block.scrap-wall-large.name = Великая стена из металлолома +block.scrap-wall-huge.name = Огромная стена из металлолома +block.scrap-wall-gigantic.name = Гигантская стена из металлолома +block.thruster.name = Толкатель +block.kiln.name = Печь +block.kiln.description = Выплавляет песок и свинец в биостекло. Требует малого количества энергии. +block.graphite-press.name = Графитный пресс +block.multi-press.name = Мульти-пресс +block.constructing = {0}\n[LIGHT_GRAY](Строится) block.spawn.name = Точка появления врагов -block.core.name = Ядро -block.space.name = Пустота -block.metalfloor.name = Металлическая плита +block.core-shard.name = Ядро: Осколок +block.core-foundation.name = Ядро: Штаб +block.core-nucleus.name = Ядро: Атом block.deepwater.name = Глубоководье block.water.name = Вода -block.lava.name = Лава block.tar.name = Дёготь -block.blackstone.name = Чёрный камень block.stone.name = Камень -block.dirt.name = Земля -block.sand.name = Песок +block.sand.name = Тёмный песок block.ice.name = Лёд block.snow.name = Снег -block.grass.name = Трава -block.shrub.name = Куст -block.rock.name = Булыжник -block.blackrock.name = Чёрный булыжник -block.icerock.name = Ледяной булыжник +block.craters.name = Кратеры +block.sand-water.name = Песок с водой +block.char.name = Выжженная Земля +block.holostone.name = Голографический камень +block.ice-snow.name = Ледяной Снег +block.rocks.name = Камни +block.icerocks.name = Ледяные камни +block.snowrocks.name = Снежные камни +block.dunerocks.name = Песчаные Камни +block.pine.name = Сосна +block.white-tree-dead.name = Мёртвое Белое Дерево +block.white-tree.name = Белое Дерево +block.spore-cluster.name = Скопление спор +block.stained-rocks.name = Пятнистые Камни +block.stained-stone.name = Пятнистый Камень +block.stained-rocks-red.name = Красные Пятнистые Камни +block.stained-stone-red.name = Красный Пятнистый Камень +block.stained-rocks-yellow.name = Жёлтые Пятнистые Камни +block.stained-stone-yellow.name = Жёлтый Пятнистый Камень +block.stained-boulder.name = Пятнистый Валун +block.metal-floor.name = Металлический Пол +block.metal-floor-2.name = Металлический Пол 2 +block.metal-floor-3.name = Металлический Пол 3 +block.metal-floor-5.name = Металлический Пол 5 +block.metal-floor-damaged.name = Повреждённый Металлический Пол +block.ignarock.name = Магматические горные породы +block.hotrock.name = Горячий камень +block.magmarock.name = Магма камень +block.cliffs.name = Скалы block.copper-wall.name = Медная стена block.copper-wall-large.name = Большая медная стена -block.dense-alloy-wall.name = Стена из плотного сплава -block.dense-alloy-wall-large.name = Большая стена из плотного сплава +block.titanium-wall.name = Титановая стена +block.titanium-wall-large.name = Большая титановая стена block.phase-wall.name = Фазовая стена block.phase-wall-large.name = Большая фазовая стена block.thorium-wall.name = Ториевая стена @@ -525,7 +584,6 @@ block.thorium-wall-large.name = Большая ториевая стена block.door.name = Дверь block.door-large.name = Большая дверь block.duo.name = Двойная турель -block.scorch.name = Обжигатель block.hail.name = Град block.lancer.name = Копейщик block.conveyor.name = Конвейер @@ -537,31 +595,30 @@ block.sorter.name = Сортировщик block.sorter.description = Сортирует предметы. Если предмет соответствует выбранному, то он проходит насквозь(прямо). В противном случае предмет выводится слева или справа. block.overflow-gate.name = Избыточный затвор block.overflow-gate.description = Комбинированный разветвитель и маршрутизатор, который выводит только слева и справа, если передний путь заблокирован. -block.smelter.name = Плавильный завод -block.arc-smelter.name = Дуговая печь block.silicon-smelter.name = Кремниевый плавильный завод block.phase-weaver.name = Фазовый ткач block.pulverizer.name = Измельчитель block.cryofluidmixer.name = Мешалка для криогенной жидкости block.melter.name = Плавильня block.incinerator.name = Мусоросжигатель -block.biomattercompressor.name = Компрессор биоматерии +block.spore-press.name = Spore Press block.separator.name = Отделитель -block.centrifuge.name = Центрифуга block.power-node.name = Силовой узел block.power-node-large.name = Большой силовой узел +block.surge-tower.name = Кинетическая башня block.battery.name = Аккумулятор block.battery-large.name = Большой аккумулятор block.combustion-generator.name = Генератор внутреннего сгорания block.turbine-generator.name = Турбинный генератор +block.differential-generator.name = Дифференциальный генератор +block.impact-reactor.name = Импульсный реактор block.mechanical-drill.name = Механический бур block.pneumatic-drill.name = Пневматический бур block.laser-drill.name = Лазерный бур block.water-extractor.name = Экстрактор воды block.cultivator.name = Культиватор -block.alpha-mech-pad.name = Реконструктор мехов "Альфа" -block.dart-ship-pad.name = Реконструктор кораблей "Дротик" -block.delta-mech-pad.name = Реконструктор мехов "Дельта" +block.alpha-dart-mech-pad.name = Реконструктор мехов "Альфа-Дротик" +block.delta-mech-pad.name = Delta Mech Pad block.javelin-ship-pad.name = Реконструктор кораблей "Джавелин" block.trident-ship-pad.name = Реконструктор кораблей "Трезубeц" block.glaive-ship-pad.name = Реконструктор кораблей "Копьё" @@ -585,7 +642,6 @@ block.bridge-conveyor.name = Мостовой конвейер block.plastanium-compressor.name = Пластиниевый компрессор block.pyratite-mixer.name = Мешалка пиротита block.blast-mixer.name = Мешалка взрывоопасного соединения -block.solidifer.name = Отвердитель block.solar-panel.name = Солнечная панель block.solar-panel-large.name = Большая солнечная панель block.oil-extractor.name = Нефтяной экстрактор @@ -593,7 +649,7 @@ block.spirit-factory.name = Завод дронов "Призрак" block.phantom-factory.name = Завод дронов "Фантом" block.wraith-factory.name = Завод призрачных истребителей block.ghoul-factory.name = Завод бомбардировщиков "Гуль" -block.dagger-factory.name = Завод мехов "Разведчик" +block.dagger-factory.name = Завод мехов "Кинджал" block.titan-factory.name = Завод мехов "Титан" block.fortress-factory.name = Завод мехов "Крепость" block.revenant-factory.name = Завод бомбардировщиков "Потусторонний убийца" @@ -606,15 +662,14 @@ block.liquid-junction.name = Жидкостный перекрёсток block.bridge-conduit.name = Мостовой трубопровод block.rotary-pump.name = Роторный насос block.thorium-reactor.name = Ториевый реактор -block.command-center.name = Командный центр block.mass-driver.name = Электромагнитная катапульта block.blast-drill.name = Воздушная буровая установка block.thermal-pump.name = Термальный насос block.thermal-generator.name = Термальный генератор -block.alloy-smelter.name = Плавильня высокопрочного сплава +block.alloy-smelter.name = Плавильня кинетического сплава block.mend-projector.name = Ремонтирующий гранатомёт -block.surge-wall.name = Стена из высокопрочного сплава -block.surge-wall-large.name = Большая стена из высокопрочного сплава +block.surge-wall.name = Стена из кинетического сплава +block.surge-wall-large.name = Большая стена из кинетического сплава block.cyclone.name = Циклон block.fuse.name = Взрыватель block.shock-mine.name = Шоковая мина @@ -625,30 +680,35 @@ block.rtg-generator.name = Радиоизотопный термоэлектри block.spectre.name = Призрак block.meltdown.name = Катастрофа block.container.name = Склад -block.core.description = Самое главное здание в игре. +block.launch-pad.name = Стартовая площадка +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = Синяя team.red.name = Красная team.orange.name = Оранжевая team.none.name = Серая team.green.name = Зелёная team.purple.name = Фиолетовая -unit.alpha-drone.name = Альфа unit.spirit.name = Дрон-привидение unit.spirit.description = Начальный дрон. По умолчанию появляется из ядра. Автоматически добывает руды, собирает предметы, ремонтирует блоки. unit.phantom.name = Фантомный дрон unit.phantom.description = Продвинутый дрон. Автоматически добывает руды, собирает предметы, ремонтирует блоки. Значительнее эффективней нежели обычный дрон -unit.dagger.name = Разведчик +unit.dagger.name = Кинджал unit.dagger.description = Основная наземная боевая единица. Может быть полезен в группах. +unit.crawler.name = Crawler unit.titan.name = Титан unit.titan.description = Улучшенная бронированная наземная боевая единица. Атакует наземные и воздушные цели. unit.ghoul.name = Бомбардировщик "Гуль" -unit.ghoul.description = Тяжелый ковровый бомбардировщик. Использует взрывное соединение или пиротит в качестве боеприпасов. +unit.ghoul.description = Тяжелый ковровый бомбардировщик. unit.wraith.name = Призрачный истребитель unit.wraith.description = Быстрый перехватчик, который использует тактику набега с отходом. unit.fortress.name = Крепость unit.fortress.description = Боевая единица с тяжёлой артилерийской установкой. unit.revenant.name = Потусторонний убийца -unit.revenant.description = Боевая единица с тяжёлой лазерной установкой. +unit.eruptor.name = Извергатель +unit.chaos-array.name = Массив хаос +unit.eradicator.name = Искоренитель +unit.lich.name = Лич +unit.reaper.name = Жнец tutorial.begin = Ваша миссия здесь состоит в том, чтобы уничтожить[LIGHT_GRAY] вашего врага[].\n\nНачните с[accent] добычи меди[]. Чтобы добыть её, коснитесь месторождения медной руды рядом с вашим ядром. tutorial.drill = Ручная работа не очень эффективна.\n[accent]Буры[] могут копать автоматически.\nПоставьте один на медной жиле. tutorial.conveyor = [accent]Конвейеры[] используются для транспортировки предметов. \nСоздайте конвейеры от бура к ядру. @@ -666,14 +726,12 @@ tutorial.generatordrill = Генератор внутреннего сгоран tutorial.node = Энергия требует транспортировки.\nСоздайте [accent] силовой узел[] рядом с генератором внутреннего сгорания для передачи энергии. tutorial.nodelink = Энергия может быть передана посредством соприкосновения блоков питания и генераторов или связанных силовых узлов.\n\nСоедините их, нажав на силовой узел и выбрав генератор, а затем кремниевый завод. tutorial.silicon = Производство кремния началось. Получите немного.\nРекомендуется улучшить эту систему. -tutorial.daggerfactory = Постройте[accent] завод по производству "разведчиков".[]\n\nОн будет производить атакуюших мехов. +tutorial.daggerfactory = Постройте[accent] завод по производству "кинжалов".[]\n\nОн будет производить атакуюших мехов. tutorial.router = Заводы нуждаются в ресурсах для работы.\nСоздайте маршрутизатор для разделения ресурсов конвейера. tutorial.dagger = Соедините силовой узел с заводом.\nПосле выполнения требований будет создан мех. \n\nПри необходимости создайте дополнительные буры, генераторы и конвейеры. tutorial.battle = [LIGHT_GRAY] Враг[] показал своё ядро.\nУничтожьте его своим мехом и вашой новой боевой единицой. block.copper-wall.description = Дешевый оборонительный блок.\nПолезно для защиты ядра и турелей во время первых волн. block.copper-wall-large.description = Большая стена самым маленьким запасом прочности.\n Хороша в начале игры. -block.dense-alloy-wall.description = Стена с показателем прочности "ниже среднего". -block.dense-alloy-wall-large.description = Большая стена с показателем прочности "ниже среднего". block.thorium-wall.description = Стена с показателем прочности "выше среднего". block.thorium-wall-large.description = Большая стена с показателем прочности "выше среднего". block.phase-wall.description = Стена с средним показателем прочности . @@ -689,13 +747,13 @@ block.shock-mine.description = Поставьте её на землю. Она block.duo.description = Маленькая и дешёвая турель. block.arc.description = Турель с малым радиусом атаки. В качестве патронов требует воду или криогенную жидкость. Также нужна энергия. block.hail.description = Дальнобойная начальная турель.\nИспользует в качестве снарядов плотный сплав, кремний и пиротит.\nДля ускорения стрельбы можно подвести воду и криогенную жидкость. -block.lancer.description = Турель, которая стреляет лазером на среднее расстояние.\nИспользует в качестве снарядов энергию.\nДля ускорения стрельбы можно подвести воду, нефть и криогенную жидкость. +block.lancer.description = Турель, которая стреляет лазером на среднее расстояние.\nИспользует в качестве снарядов энергию.\nДля ускорения стрельбы можно подвести воду или криогенную жидкость. block.wave.description = Турель с средним радиусом атаки, которая отталкивает противников в стороны. Использует в качестве снарядов воду, нефть, лаву или криогенную жидкость. -block.salvo.description = Турель с средним радиусом атаки. Использует в качестве снарядов медь, плотный сплав, торий, кремний и пиротит.\nТакже нужна какая-то жидкость:вода, нефть или криогенная. -block.swarmer.description = Турель с большим радиусом атаки. Использует в качестве снарядов высокопрочный сплав, пиротит и взрывоопасное соединение.\n Также нужна какая-то жидкость: вода, нефть или криогенная. -block.ripple.description = Первая турель 3х3.\nИспользует в качестве снарядов плотный сплав, кремний, взрывоопасное соединение и пиротит. \nТакже нужна какая-то жидкость: вода, нефть или криогенная. -block.cyclone.description = Турель с большой дальностью атаки. Использует в качестве снарядов пластиний, взрывоопасное соединение и высокопрочный сплав.\nТакже нужна какая-то жидкость:вода, нефть или криогенная. -block.fuse.description = Турель с малой дальностью атаки. Использует в качестве снарядов плотный сплав. \nТакже нужна какая-то жидкость: вода, нефть или криогенная. +block.salvo.description = Турель с средним радиусом атаки. Использует в качестве снарядов медь, плотный сплав, торий, кремний и пиротит.\nТакже нужна какая-то жидкость: вода или криогенная. +block.swarmer.description = Турель с большим радиусом атаки. Использует в качестве снарядов кинетический сплав, пиротит и взрывоопасное соединение.\n Также нужна какая-то жидкость: вода или криогенная. +block.ripple.description = Первая турель 3х3.\nИспользует в качестве снарядов плотный сплав, кремний, взрывоопасное соединение и пиротит. \nТакже нужна какая-то жидкость: вода или криогенная. +block.cyclone.description = Турель с большой дальностью атаки. Использует в качестве снарядов пластиний, взрывоопасное соединение и кинетический сплав.\nТакже нужна какая-то жидкость:вода или криогенная. +block.fuse.description = Турель с малой дальностью атаки. Использует в качестве снарядов плотный сплав. \nТакже нужна какая-то жидкость: вода или криогенная. block.spectre.description = Первая турель 4х4 с средним радиусом атаки. Использует в качестве снарядов плотный сплав, торий или пиротит. block.meltdown.description = Турель с средним радиусом атаки. Для патронов требует воду или криогенную жидкость. Также нужна энергия. block.conveyor.description = Перемещает ресурсы с маленькой скоростью. @@ -703,44 +761,39 @@ block.titanium-conveyor.description = Конвейер второго покол block.phase-conveyor.description = Пока игра находится в 2D, этот конвейер уже в четырёхмерном пространстве(возможно, это ложь).\nТребует энергии и подключается как мостовой конвейер. block.junction.description = Название говорит само за себя. С помощью него можно сделать две конвейерные ленты, которые проходят через друг друга и не смешиваются. block.mass-driver.description = При наличии энергии передают ресурсы на расстояние 100 блоков, стреляя в друг-друга. -block.smelter.description = Производит плотный сплав из меди и свинца. Можно подвести песок для ускорения производства. -block.arc-smelter.description = Улучшенная версия плавильного завода. Требует энергию. Производит плотный сплав из угля, меди и свинца. \nМожно подвести песок для ускорения производства. block.silicon-smelter.description = С помощью песка, угля и энергии производит кремний. block.plastanium-compressor.description = Создаёт пластиний из титана и нефти. Требует энергии. Для ускорения производства можно добавить в компрессор песок. -block.phase-weaver.description = Производит фазовую материю с тория и песка. Требует большего количества энергии. -block.alloy-smelter.description = Создаёт высокопрочный сплав из титана, кремния, меди и свинца. Требует энергию. -block.pulverizer.description = Измельчает камень в песок. Требует энергии. +block.phase-weaver.description = Производит фазовую материю из тория и песка. Требует большего количества энергии. +block.alloy-smelter.description = Создаёт кинетический сплав из титана, кремния, меди и свинца. Требует энергию. +block.pulverizer.description = Измельчает камень в песок. Требует энергию. block.pyratite-mixer.description = Создаёт пиротит из угля, свинца и песка. Требует энергии. block.blast-mixer.description = Создаёт взрывоопасное соединение из нефти и пиротита. Для ускорения производства можно добавить в мешалку песок. block.cryofluidmixer.description = Производит криогенную жидкость из воды и титана. Требует энергии. -block.solidifer.description = Остужает лаву до камня. Требует энергию. -block.melter.description = Переплавляет камень в лаву. Требует энергию. +block.melter.description = Расплавляет металлолом в шлак для дальнейшей обработки или использования в турелях. block.incinerator.description = Если есть ненужные ресурсы, можно просто их сжечь.\n Требует энергии. -block.biomattercompressor.description = Производит нефть из биоматерии, биомусора и энергии. -block.separator.description = Ищет в камне различные ресурсы. Чем ценней ресурс, тем с меньшей вероятностью он "найдётся". -block.centrifuge.description = Улучшенная версия отделителя.\nИщет в камне различные ресурсы. Чем ценней ресурс, тем с меньшей вероятностью он "найдётся".\nТребует энергию. +block.spore-press.description = Compresses spore pods into oil. +block.separator.description = Извлекает полезные минералы из шлака. block.power-node.description = Максимум допустимо 4 подключения.\n Чтобы соединить с каким-то блоком нужно следующее:\n1. Чтобы он находился в радиусе действия\n2.Нажать на нужный силовой узел, а затем на другой силовой узел или блок. block.power-node-large.description = Силовой узел второго поколения. Увеличен радиус действия и количество максимально допустимых подключений. -block.battery.description = Позволяет хранить энергию, но БАТАРЕЙКИ DURACELL ХРАНЯТ БОЛЬШЕ!(скрытая реклама) -block.battery-large.description = Улучшенная версия малого аккумулятора. Наконец-то, хранит больше энергии чем какие-то там батарейки... +block.battery.description = Позволяет хранить энергию. +block.battery-large.description = Улучшенная версия обычного аккумулятора. block.combustion-generator.description = Начальный и дешёвый источник энергии. Для производства энергии использует нефть, уголь, пиротит, биоматерию и взрывоопасное соединение. block.turbine-generator.description = Для производства энергии использует нефть, уголь, пиротит, биоматерию или взрывоопасное соединение.\nТакже обязательно нужна вода. -block.thermal-generator.description = [accent]Горячее воспринимает на ура. []\n Производит энергию из лавы. +block.thermal-generator.description = Генерирует энергию, когда помещается в жаркие места. block.solar-panel.description = Зелёная энергия. Бесконечный источник энергии. block.solar-panel-large.description = Зелёная энергия. Большой и бесконечный источник энергии. block.thorium-reactor.description = Производит энергию в большом количестве. Может взорваться. Требуется торий и жидкость для охлаждения (вода или криогенная). block.rtg-generator.description = Радиоизотопный термоэлектрический генератор, который не требует охлаждения, но обеспечивает меньшую мощность, чем ториевый реактор. block.unloader.description = Выгружает из ядра или хранилища верхний левый предмет. -block.container.description = Хранит небольшое количество предметов(200). Используйте его для создания буферов, когда существует непостоянная потребность в материалах. [LIGHT_GRAY] Разгрузчик[] можно использовать для извлечения элементов из хранилища. -block.vault.description = Хранит большое количество предметов(900). Используйте его для создания буферов, когда существует непостоянная потребность в материалах.[LIGHT_GRAY] Разгрузчик[] можно использовать для извлечения элементов из хранилища. +block.container.description = Хранит небольшое количество предметов. Используйте его для создания буферов, когда существует непостоянная потребность в материалах. [LIGHT_GRAY] Разгрузчик[] можно использовать для извлечения элементов из хранилища. +block.vault.description = Хранит большое количество предметов. Используйте его для создания буферов, когда существует непостоянная потребность в материалах.[LIGHT_GRAY] Разгрузчик[] можно использовать для извлечения элементов из хранилища. block.mechanical-drill.description = Самый первый доступный бур. \n\nДобывает медь, свинец, уголь, песок. \n\nМожно подвести к нему [BLUE] воду[] для увеличения скорости сверления. block.pneumatic-drill.description = Улучшенная версия механического бура.\n\nДобывает тоже самое, что и механический бур. Также может добывать титан и камень.\n\nМожно подвести к нему[BLUE] воду[] для увеличения скорости сверления. block.laser-drill.description = Улучшенная версия пневматического бура.\n\nДобывает тоже самое, что и пневматический бур. Также может добывать торий.\n\nМожно подвести к нему[BLUE] воду[] для увеличения скорости сверления. block.blast-drill.description = Самый мощный бур.\n\nДобывает тоже самое, что и лазерный бур. Сверлит быстрей всех буров, но требует ещё больше энергии.\n\nМожно подвести к нему [BLUE]воду[] для увеличения скорости сверления. block.water-extractor.description = Извлекает воду из земли. Используйте его, когда поблизости нет озера. -block.cultivator.description = Культирует почву водой для получения биоматерии. +block.cultivator.description = Культирует споры водой для получения биоматерии. block.oil-extractor.description = Использует большое количество энергии для добычи нефти из песка, динозавров(зачёркнуто). Используйте его, когда поблизости нет прямого источника нефти. -block.dart-ship-pad.description = Оставьте свое текущее судно и перейдите на основной истребитель.\nИспользуйте двойное нажатие, стоя на реконструкторе, чтобы превратиться в этот мех. block.trident-ship-pad.description = Оставьте свой текущий корабль и перейдите в достаточно хорошо бронированный тяжёлый бомбардировщик.\nИспользуйте двойное нажатие, стоя на реконструкторе, чтобы превратиться в этот мех. block.javelin-ship-pad.description = Оставьте свой текущий корабль и перейдите в сильный и быстрый перехватчик с молниеносным оружием.\nИспользуйте двойное нажатие, стоя на реконструкторе, чтобы превратиться в этот мех. block.glaive-ship-pad.description = Превращает вас в Копьё. Реконструктор требует энергию.\nПодробности про Копьё в "разблокированное". @@ -753,10 +806,9 @@ block.wraith-factory.description = Производит быстрые и лет block.ghoul-factory.description = Производит тяжёлых ковровых бомбардировщиков. block.dagger-factory.description = Производит основных наземных боевых единиц. block.titan-factory.description = Производит продвинутые защищённые боевые единицы. -block.fortress-factory.description = Производит тяжелые артиллерийские боевые единицы. -block.revenant-factory.description = Производит тяжелые наземные боевые единицы. +block.fortress-factory.description = Производит тяжёлые артиллерийские боевые единицы. +block.revenant-factory.description = Производит тяжёлые летающие боевые единицы. block.repair-point.description = Может ремонтировать вас и ваши боевые единицы -block.command-center.description = Позволяет изменять дружественное поведение ИИ. В настоящее время поддерживаются команды атаки, отступления и патрулирования. block.conduit.description = Основной блок транспортировки жидкости. Работает как конвейер, но с жидкостями. Лучше всего использовать экстракторы, насосы или т.п.. block.pulse-conduit.description = Улучшенный блок транспортировки жидкости. Транспортирует жидкости быстрее и хранит больше, чем стандартные. block.phase-conduit.description = Улучшенный блок транспортировки жидкости. Использует энергию для передачи жидкостей на подключенный фазовый канал на несколько плиток. @@ -770,13 +822,11 @@ block.thermal-pump.description = Конечный насос. В три раза block.router.description = Принимает предметы из одного направления и равномерно выводит их до трёх других направлений. Полезно для разделения материалов из одного источника на несколько целей. block.distributor.description = Передовой маршрутизатор, который равномерно разбивает элементы до 7 других направлений. block.bridge-conveyor.description = Улучшенный транспортный блок элементов. Позволяет транспортировать предметы до 3-х блоков над любым ландшафтом или зданием. -block.alpha-mech-pad.description = Превращает вас в мех [accent] Альфа[]. Требует энергию. -block.item-source.description = Бесконечно выводит предметы. Работает только в песочнице. -block.liquid-source.description = Бесконечно выводит жидкости. Работает только в песочнице. -block.item-void.description = Уничтожает любые предметы, которые входят в него, без использования энергии. Работает только в режиме песочницы. -block.power-source.description = Бесконечность — не предел. Бесконечно выводит энергию. Доступен только в режиме песочницы. -block.power-void.description = Энергия просто уходит в пустоту. Присутствует только в песочнице. -liquid.water.description = Намного лучше чем [BLUE]монооксид дигидрогена[].\n\n Для получения воды используйте помпу(насос) на источнике(блоке) или экстрактор воды.\n\n Эту жидкость можно подвести к бурам для ускорения скорости добычи или к турелям для ускорения стрельбы. -liquid.lava.description = [accent]Горячо...\nВещество расплавленное из горно-каменных пород. -liquid.oil.description = Кто-то писал о добавлении золота в игру. Его добавили, правда оно какое-то чёрное...\nСмесь жидких углеводородов, выделяющаяся из природного газа в результате снижения температуры и пластового давления. -liquid.cryofluid.description = Жидкость с температурой ниже чем -273 градусов по цельсию. Может быть использована для ускорения стрельбы турелей или для охлаждения чего-то. +block.item-source.description = Infinitely outputs items. Sandbox only. +block.liquid-source.description = Infinitely outputs liquids. Sandbox only. +block.item-void.description = Destroys any items which go into it without using power. Sandbox only. +block.power-source.description = Infinitely outputs power. Sandbox only. +block.power-void.description = Voids all power inputted into it. Sandbox only. +liquid.water.description = Эту жидкость можно подвести к бурам для ускорения скорости добычи или к турелям для ускорения стрельбы. +liquid.oil.description = Может гореть, взрывоопасна и используется для охлаждения. +liquid.cryofluid.description = Может быть использована для ускорения стрельбы турелей или для охлаждения чего-то. diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties index 7d5e1c9daf..5561216c7b 100644 --- a/core/assets/bundles/bundle_tk.properties +++ b/core/assets/bundles/bundle_tk.properties @@ -1,5 +1,6 @@ credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet!) credits = Emegi gecenler +contributors = Translators and Contributors discord = Mindustry'in Discord'una katilin! link.discord.description = Orjinal Mindustry'in Discord Konusma Odasi link.github.description = Oyunun Kodu @@ -9,15 +10,19 @@ link.itch.io.description = Bilgisayar ve Site versiyonunun bulundugu Site link.google-play.description = Google Play magaza sayfasi link.wiki.description = Orjinal Mindustry Bilgilendirme Sayfasi linkfail = Link Acilamadi!\nLink sizin icin kopyalandi. +screenshot = Screenshot saved to {0} gameover = Cekirdegin yok edildi. gameover.pvp = The[accent] {0}[] team is victorious! -sector.gameover = Sektor kaybedildi. Geri gitmek ister misin? -sector.retry = Gene dene highscore = [accent]Yeni Yuksek skor! -wave.lasted = Su dalgaya kadar dayandin: [accent]{0}[]. -level.highscore = Yuksek Skor: [accent]{0} -level.delete.title = Silmeyi onayla +stat.wave = Waves Defeated:[accent] {0} +stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} +stat.built = Buildings Built:[accent] {0} +stat.destroyed = Buildings Destroyed:[accent] {0} +stat.deconstructed = Buildings Deconstructed:[accent] {0} +stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = Su haritayi silmek istediginden emin misin? "[accent]{0}[]"? +level.highscore = Yuksek Skor: [accent]{0} level.select = Seviye secimi level.mode = Oyun Modu: construction.desktop = Bilgisayar kontrolleri degisti.\nEsyayi secmeyi birakmak istiyorsan [accent]bosluga bas[]. @@ -27,60 +32,36 @@ deconstruction.title = Yapi yikma egitimi deconstruction = Daha demin sen[accent]Yapi yikmak icin yikma moduna girdin..[].\n\nkirmak icin, unitinin cevresindeki bir yapiya/yapilara tikla.\nisin bitince, tamamlama tusuna tikla ve gemin onlari lirbaya basliyacak\n\n- [accent]Yapi yikmak [] icin uzerlerine tikla.\n- [accent]bir arazideki yapilari yikmak[] icin bir arazi sec ve tamamlama tusuna bas\n- [accent]yikma modundan cikmak[] icin kosedeki X tusuna bas showagain = Don't show again next session coreattack = < Cekirdek Saldiri altinda! > -unlocks = Oduller +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = Oyunu kaydet loadgame = Devam et joingame = Oyuna katil addplayers = Oyuncu ekle/cikar customgame = Ozel oyun -sectors = Sektorler -sector = Sector: [LIGHT_GRAY]{0} -sector.time = Time: [LIGHT_GRAY]{0} -sector.deploy = Yukle -sector.abandon = Abandon -sector.abandon.confirm = Are you sure you want to abandon all progress at this sector?\nThis cannot be undone! -sector.resume = Devam et -sector.locked = [scarlet][[Incomplete] -sector.unexplored = [accent][[Unexplored] -missions = Missions:[LIGHT_GRAY] {0} -mission = Mission:[LIGHT_GRAY] {0} -mission.main = Main Mission:[LIGHT_GRAY] {0} -mission.info = Mission Info -mission.complete = Gorev tamamlandi! -mission.complete.body = Sektor {0},{1} ele gecirildi -mission.wave = [accent]{0}/{1}[] Dalga hayatta kal\n{2} Dalga -mission.wave.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies -mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy -mission.wave.menu = Survive[accent] {0} []waves -mission.battle = Dusmanin cekirdegini yok et -mission.resource.menu = Obtain {0} x{1} -mission.resource = {0} x{1} Kazan -mission.block = Create {0} -mission.unit = Create {0} Unit -mission.command = Send Command {0} To Units -mission.linknode = Link Power Node -mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -mission.mech = Switch to mech[accent] {0}[] -mission.create = Create[accent] {0}[] +newgame = New Game none = close = Kapat quit = Cik maps = Haritalar continue = Devam et -nextmission = Yeni gorev maps.none = [LIGHT_GRAY]Harita bulunamadi! about.button = Hakkinda name = isim: +noname = Pick a[accent] player name[] first. filename = File Name: unlocked = Yeni yapi acildi!! -unlocked.plural = Yeni yapilar acildi! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. players = {0} oyuncu cevrimici players.single = {0} oyuncu cevrimici server.closing = [accent]Oyun kapaniyor. server.kicked.kick = Oyundan cikarildin server.kicked.serverClose = Oyun kapandi -server.kicked.sectorComplete = Sektor tamamlandi -server.kicked.sectorComplete.text = Gorev Tamamlandi.\nOyun siradaki sektorden devam edecek server.kicked.clientOutdated = Yeni bir versiyon mevcut! Hemen indir! server.kicked.serverOutdated = Eski oyun! Yapimciya guncellemesini soyle! server.kicked.banned = Oyundan kalici olarak cikarildin. @@ -89,6 +70,7 @@ server.kicked.nameInUse = Oyunda bu isimde bir\nkisi zaten var. server.kicked.nameEmpty = ismin gecerli degil. server.kicked.idInUse = Zaten oyundasin! iki ayri hesapla oyuna katilamazsin! server.kicked.customClient = Bu oyun ayarlanmis vesiyonlara izin vermiyor. Orijinal bir versiyon dene! +server.kicked.gameover = Game over! host.info = [accent]host[] su linkte bir oyun acti! [scarlet]6567[]. \nSeninle [LIGHT_GRAY]ayni internete[] sahip olan kisiler oyunu gorebilir.\n\neger baska yerlerden kisilerind de gelmesini istiyorsan, [accent]oyun acmak[]zorunludur.\n\n[LIGHT_GRAY]Not: eger baglanmakta gucluk cekiliyorsa, antivirusunun internetine baglanmasini izin vermesini sagla. join.info = Buradan,[accent]Oyunun linkini[] kullanarak katilabilir, yada, [accent]internetinle[] baglanacak oyun bulabilirsin\ninternetli ve Linkli oyunlar desteklenir.\n\n[LIGHT_GRAY]Not: Otomatik bir oyun listesi goruntulenemez. Yapimcidan linkini iste. hostserver = Oyun ac @@ -159,7 +141,6 @@ save.rename.text = Yeni isim: selectslot = Kayitli bir dosya sec. slot = [accent]Slot {0} save.corrupted = [accent]Kayit gecersiz!\nOyunu guncellediysen, bu buyuk ihtimalle degistirilecek vebu bir [scarlet]sorun degildir.[] -sector.corrupted = [accent]Yeni dosyalar bulundu, ama yuklenemedi.\nYeni bir tane yapildi. empty = on = Acik off = Kapali @@ -169,6 +150,7 @@ save.wave = Dalga {0} save.difficulty = Zorluk: {0} save.date = En sonki kayit: {0} save.playtime = Oyun Zamani!: {0} +warning = Warning. confirm = Onayla delete = Sil ok = Tamam @@ -204,7 +186,6 @@ map.nospawn = Haritada Oyncularin cikmasi icin cekirdek yok! Haritaya[ROYAL]Mavi map.nospawn.pvp = This map does not have any enemy cores for player to spawn into! Add[SCARLET] red[] cores to this map in the editor. map.invalid = Harita yuklenemedi. Gecersiz yada bozuk dosya. editor.brush = Firca -editor.slope = \\ editor.openin = Editorde ac editor.oregen = Maden Yaratilma hizi editor.oregen.info = Maden Yaratilmasi: @@ -259,6 +240,26 @@ tutorial = Tutorial editor = Editor mapeditor = Harita yaraticisi donate = Bagis yap +abandon = Abandon +abandon.text = This zone and all its resources will be lost to the enemy. +locked = Locked +complete = [LIGHT_GRAY]Complete: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Best: {0} +launch = Launch +launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson]Su Oyuna baglanilamadi: [accent]{0} error.unreachable = Server unreachable. error.invalidaddress = Invalid address. @@ -266,7 +267,20 @@ error.timedout = Timed out!\nMake sure the host has port forwarding set up, and error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! error.alreadyconnected = Already connected. error.mapnotfound = Map file not found! +error.io = Network I/O error. error.any = Unkown network error. +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = Dil settings.reset = ilk ayarlara geri al settings.rebind = Geri al @@ -277,7 +291,6 @@ settings.graphics = Grafikler settings.cleardata = Clear Game Data... settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! settings.clearall.confirm = [scarlet]WARNING![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit. -settings.clearsectors = Clear Sectors settings.clearunlocks = Clear Unlocks settings.clearall = Clear All paused = Duraklatildi @@ -286,12 +299,15 @@ no = Hayir info.title = [accent]Bilgi error.title = [crimson]Bir hata olustu error.crashtitle = Bir hata olustu +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Yapi bilgisi +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = Guc kapasitesi blocks.powershot = Guc/Saldiri hizi blocks.targetsair = Havayi hedef alir mi? -blocks.itemspeed = Ilerleme hizi +blocks.itemsmoved = Move Speed blocks.shootrange = Menzil blocks.size = Buyukluk blocks.liquidcapacity = Sivi kapasitesi @@ -312,16 +328,23 @@ blocks.inputitems = Giris esyalari blocks.outputitem = Sonuc blocks.drilltier = Kazilabilirler blocks.drillspeed = Ana kazma hizi +blocks.maxunits = Max Active Units blocks.liquidoutput = Sivi cikisi blocks.liquidoutputspeed = Liquid Output Speed blocks.liquiduse = Sivi kullanimi blocks.coolant = Sogutma sivisi +blocks.liquid = Liquid blocks.coolantuse = Sogutma sivi kullanimi blocks.inputliquidfuel = Yakit sivisi blocks.liquidfueluse = Sivi yakit kullanimi blocks.boostitem = Boost Item blocks.boostliquid = Boost Liquid blocks.health = Can +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = sekme blocks.shots = vuruslar blocks.reload = Yeniden doldurma @@ -329,11 +352,11 @@ blocks.inputfuel = Yakit blocks.fuelburntime = Yakit yakilma suresi blocks.inputcapacity = Giris kapasitesi blocks.outputcapacity = Cikis kapasitesi +blocks.ammo = Ammo unit.blocks = Yapilar unit.powersecond = saniyede bir unit.liquidsecond = Saniyede bir unit.itemssecond = Saniyede bir -unit.pixelssecond = Saniyede bir unit.liquidunits = Litre unit.powerunits = Volt unit.degrees = derece @@ -346,6 +369,7 @@ category.items = esyalar category.crafting = uretim category.shooting = sikma category.optional = Optional Enhancements +setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS setting.fpscap.none = Yok @@ -378,12 +402,16 @@ category.multiplayer.name = Cok oyunculu command.attack = Attack command.retreat = Retreat command.patrol = Patrol +keybind.gridMode.name = Block Select +keybind.gridModeShift.name = Category Select keybind.press = Bir tusa bas... keybind.press.axis = Bir yone cevir yada tusa bas... +keybind.screenshot.name = Map Screenshot keybind.move_x.name = Sol/Sag hareket keybind.move_y.name = Yukari/asagi hareket keybind.select.name = Sec/silahi sik -keybind.break.name = Kirma +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = Eldeki yapiyi birak keybind.shoot.name = Sik keybind.zoom_hold.name = Yaklasma basili tutmasi @@ -402,29 +430,28 @@ keybind.chat_scroll.name = Konusma kaydir keybind.drop_unit.name = Unit birak keybind.zoom_minimap.name = Haritayi yaklastir mode.help.title = Modlarin aciklamalari -mode.waves.name = Dalgali -mode.waves.description = Klasik mod. Dalgalara karsi cekirdegi koru. +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. mode.sandbox.name = Serbest mode.sandbox.description = Sonsuz esyalar ve Dalga suresi yok mode.freebuild.name = Yapi Yapma mode.freebuild.description = Sinirli esyalar ama dalga suresi yok. mode.pvp.name = PvP mode.pvp.description = fight against other players locally. +mode.attack.name = Attack +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = Esyalar content.liquid.name = Sivilar content.unit.name = Units -content.recipe.name = Yapilar +content.block.name = Blocks content.mech.name = Robotlar -item.stone.name = Tas -item.stone.description = Yaygin bir materyal. Magma'yi eriterek yada Kazma makineleriyle alinabilir. item.copper.name = Bakir item.copper.description = ise yayar bir materyal. Kazma makineleriyle yada tasimayla alinabilir. item.lead.name = Kursun item.lead.description = Basit bir baslangic materyali. sivi tasimada kullanilabilir. item.coal.name = Komur item.coal.description = Yaygin bir yakit. -item.dense-alloy.name = Sert karisim -item.dense-alloy.description = Bakir ve kursunun karistirilmasiyle elde edildi. Gelismis yapilar ve kazma makileneri icin kullanilabilir. +item.graphite.name = Graphite item.titanium.name = Titanyum item.titanium.description = Nadir ve hafif bir materyal. Hava araclarinda, Kazma makinelerinde ve sivi tasima tuplerinde kullanilir. item.thorium.name = Toryum @@ -437,16 +464,20 @@ item.phase-fabric.name = Phase Fabric item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. item.surge-alloy.name = Kabarma karisimi item.surge-alloy.description = An advanced alloy with unique electrical properties. -item.biomatter.name = Biomatter -item.biomatter.description = basit bir yakit olarak kullanilan organik bir madde +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = Kum item.sand.description = karistirma maddesi olark kullanilan yaygin bir madde. item.blast-compound.name = patlama birlesimi item.blast-compound.description = Bombalar ve patlayicilarda kullanilabilir. Yakit olarak kullanilmasi tavsiye edilmez. item.pyratite.name = Pyratite item.pyratite.description = Yakici silahlar icin yakici bir madde. +item.metaglass.name = Metaglass +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = Su -liquid.lava.name = Magma +liquid.slag.name = Slag liquid.oil.name = Benzin liquid.cryofluid.name = kriyo sivisi mech.alpha-mech.name = Alpha @@ -481,11 +512,10 @@ mech.glaive-ship.weapon = Orman yakici item.explosiveness = [LIGHT_GRAY]Patlayicilik: {0} item.flammability = [LIGHT_GRAY]Yanbilirlik: {0} item.radioactivity = [LIGHT_GRAY]Radyoaktivite: {0} -item.fluxiness = [LIGHT_GRAY]akis gucu: {0} unit.health = [LIGHT_GRAY]Can: {0} unit.speed = [LIGHT_GRAY]hiz: {0} mech.weapon = [LIGHT_GRAY]silah: {0} -mech.armor = [LIGHT_GRAY]zirh: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]esya kapasitesi: {0} mech.minespeed = [LIGHT_GRAY]kazma hizi: {0} mech.minepower = [LIGHT_GRAY]kazma gucu: {0} @@ -493,29 +523,60 @@ mech.ability = [LIGHT_GRAY]yetenek gucu: {0} liquid.heatcapacity = [LIGHT_GRAY]isinma kapasitesi: {0} liquid.viscosity = [LIGHT_GRAY]Yari sivilik: {0} liquid.temperature = [LIGHT_GRAY]isi: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](Constructing) block.spawn.name = Enemy Spawn -block.core.name = cekirdek -block.metalfloor.name = metal zemin +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = su alti block.water.name = su -block.lava.name = magma block.tar.name = Tar -block.blackstone.name = kara tas block.stone.name = tas -block.dirt.name = cimen block.sand.name = kum block.ice.name = buz block.snow.name = kar -block.grass.name = cimen -block.shrub.name = cali -block.rock.name = tas -block.blackrock.name = bkara tas -block.icerock.name = buz tasi +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = bakir duvar block.copper-wall-large.name = buyuk bakir duvar -block.dense-alloy-wall.name = Dense Alloy Wall -block.dense-alloy-wall-large.name = Large Dense Alloy Wall +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = faz duvar block.phase-wall-large.name = genis faz duvar block.thorium-wall.name = Toryum duvari @@ -523,7 +584,6 @@ block.thorium-wall-large.name = genis toryum duvari block.door.name = kapi block.door-large.name = genis kapi block.duo.name = ikili -block.scorch.name = Atesleyici block.hail.name = yagdirici block.lancer.name = Lazer topu block.conveyor.name = konvenyor @@ -535,30 +595,29 @@ block.sorter.name = secici block.sorter.description = esyalari secer. rengi ayni olan esya ileriden, digerleri sagdan ve soldan devam eder block.overflow-gate.name = Kapali dagatici block.overflow-gate.description = sadece saga ve sola dagatir. onu kapalidir -block.smelter.name = eritici -block.arc-smelter.name = elektrik eritici block.silicon-smelter.name = Silikon eritici block.phase-weaver.name = Dokumaci block.pulverizer.name = pulvarizor block.cryofluidmixer.name = Cryosivisi karistiricisi block.melter.name = eritici block.incinerator.name = isi firini -block.biomattercompressor.name = Biomatter kompresoru +block.spore-press.name = Spore Press block.separator.name = separator -block.centrifuge.name = Santrifuj block.power-node.name = Guc Dugumu block.power-node-large.name = buyuk Guc Dugumu +block.surge-tower.name = Surge Tower block.battery.name = batarya block.battery-large.name = buyuk batarya block.combustion-generator.name = sicaklik jenaratoru block.turbine-generator.name = termal jenaratoru +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = Mekanikal Kazici block.pneumatic-drill.name = Pneumatik Kazici block.laser-drill.name = Lazer kazici block.water-extractor.name = su ayiricisi block.cultivator.name = ekici -block.alpha-mech-pad.name = Alpha Mech Pad -block.dart-ship-pad.name = Dart Ship Pad +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = Delta Mech Pad block.javelin-ship-pad.name = Javelin Ship Pad block.trident-ship-pad.name = Trident Ship Pad @@ -583,7 +642,6 @@ block.bridge-conveyor.name = kopru konvenyoru block.plastanium-compressor.name = Plastanium Kompresoru block.pyratite-mixer.name = Pyratite karistirici block.blast-mixer.name = Patlayici karistiricisi -block.solidifer.name = Sertlestirici block.solar-panel.name = gunes paneli block.solar-panel-large.name = genis gunes paneli block.oil-extractor.name = benzin ayirici @@ -604,7 +662,6 @@ block.liquid-junction.name = sivi yonlendirici block.bridge-conduit.name = kopru borusu block.rotary-pump.name = donen boru block.thorium-reactor.name = Thorium Reaktoru -block.command-center.name = komut merkezi block.mass-driver.name = kütle surucusu block.blast-drill.name = Patlatici kazici block.thermal-pump.name = Termal pompa @@ -623,20 +680,21 @@ block.rtg-generator.name = RTG Generator block.spectre.name = Spectre block.meltdown.name = Meltdown block.container.name = Container -block.core.description = The most important building in the game. +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = blue team.red.name = red team.orange.name = orange team.none.name = gray team.green.name = green team.purple.name = purple -unit.alpha-drone.name = Alpha Dronu unit.spirit.name = Spirit Drone unit.spirit.description = The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. unit.phantom.name = Phantom Drone unit.phantom.description = An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. unit.dagger.name = Dagger unit.dagger.description = basit bir zemin uniti +unit.crawler.name = Crawler unit.titan.name = Titan unit.titan.description = havaya sikabilen, gelismis bir unit unit.ghoul.name = Ghoul Bomber @@ -646,7 +704,11 @@ unit.wraith.description = A fast, hit-and-run interceptor unit. unit.fortress.name = Fortress unit.fortress.description = A heavy artillery ground unit. unit.revenant.name = Revenant -unit.revenant.description = A heavy laser platform. +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = Your mission here is to eradicate the[LIGHT_GRAY] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this. tutorial.drill = Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein. tutorial.conveyor = [accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core. @@ -670,8 +732,6 @@ tutorial.dagger = Link power nodes to the factory.\nOnce requirements are met, a tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. block.copper-wall.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves. block.copper-wall-large.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves.\nSpans multiple tiles. -block.dense-alloy-wall.description = A standard defensive block.\nAdequate protection from enemies. -block.dense-alloy-wall-large.description = A standard defensive block.\nAdequate protection from enemies.\nSpans multiple tiles. block.thorium-wall.description = A strong defensive block.\nGood protection from enemies. block.thorium-wall-large.description = A strong defensive block.\nGood protection from enemies.\nSpans multiple tiles. block.phase-wall.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful. @@ -701,8 +761,6 @@ block.titanium-conveyor.description = Advanced item transport block. Moves items block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles. block.junction.description = Acts as a bridge for two crossing conveyor belts. Useful in situations with two different conveyors carrying different materials to different locations. block.mass-driver.description = Ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. -block.smelter.description = Burns coal for smelting copper and lead into dense alloy. -block.arc-smelter.description = Smelts copper and lead into dense alloy by using an external power source. block.silicon-smelter.description = Reduces sand with highly pure coke in order to produce silicon. block.plastanium-compressor.description = Produces plastanium from oil and titanium. block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. @@ -711,12 +769,10 @@ block.pulverizer.description = Crushes stone into sand. Useful when there is a l block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. block.blast-mixer.description = Uses oil for transforming pyratite into the less flammable but more explosive blast compound. block.cryofluidmixer.description = Combines water and titanium into cryofluid which is much more efficient for cooling. -block.solidifer.description = Cools lava to stone at a fast pace. block.melter.description = Heats up stone to very high temperatures to obtain lava. block.incinerator.description = Gets rid of any excess item or liquid. -block.biomattercompressor.description = Compresses biomatter in order to retrieve oil. +block.spore-press.description = Compresses spore pods into oil. block.separator.description = Exposes stone to water pressure in order to obtain various minerals contained in the stone. -block.centrifuge.description = More efficient than the separator, but also more expensive to build and requires power. block.power-node.description = Transmits power to connected nodes. Up to four power sources, sinks or nodes can be connected. The node will receive power from or supply power to any adjacent blocks. block.power-node-large.description = Has a larger radius than the power node and connects to up to six power sources, sinks or nodes. block.battery.description = Stores power whenever there is an abundance and provides power whenever there is a shortage, as long as there is capacity left. @@ -738,7 +794,6 @@ block.blast-drill.description = The ultimate drill. Requires large amounts of po block.water-extractor.description = Extracts water from the ground. Use it when there is no lake nearby. block.cultivator.description = Cultivates the soil with water in order to obtain biomatter. block.oil-extractor.description = Uses large amounts of power in order to extract oil from sand. Use it when there is no direct source of oil nearby. -block.dart-ship-pad.description = Leave your current vessel and change into a basic fighter aircraft.\nUse the pad by double tapping while standing on it. block.trident-ship-pad.description = Leave your current vessel and change into a reasonably well armored heavy bomber.\nUse the pad by double tapping while standing on it. block.javelin-ship-pad.description = Leave your current vessel and change into a strong and fast interceptor with lightning weapons.\nUse the pad by double tapping while standing on it. block.glaive-ship-pad.description = Leave your current vessel and change into a large, well-armored gunship.\nUse the pad by double tapping while standing on it. @@ -754,7 +809,6 @@ block.titan-factory.description = Produces advanced, armored ground units. block.fortress-factory.description = Produces heavy artillery ground units. block.revenant-factory.description = Produces heavy laser ground units. block.repair-point.description = Continuously heals the closest damaged unit in its vicinity. -block.command-center.description = Allows changing friendly AI behavior. Currently, attack, retreat and patrol commands are supported. block.conduit.description = Basic liquid transport block. Works like a conveyor, but with liquids. Best used with extractors, pumps or other conduits. block.pulse-conduit.description = Advanced liquid transport block. Transports liquids faster and stores more than standard conduits. block.phase-conduit.description = Advanced liquid transport block. Uses power to teleport liquids to a connected phase conduit over several tiles. @@ -768,13 +822,11 @@ block.thermal-pump.description = The ultimate pump. Three times as fast as a mec block.router.description = Accepts items from one direction and outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets. block.distributor.description = An advanced router which splits items to up to 7 other directions equally. block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building. -block.alpha-mech-pad.description = When given enough power, rebuilds your ship into the[accent] Alpha[] mech. block.item-source.description = Infinitely outputs items. Sandbox only. block.liquid-source.description = Infinitely outputs liquids. Sandbox only. block.item-void.description = Destroys any items which go into it without using power. Sandbox only. block.power-source.description = Infinitely outputs power. Sandbox only. block.power-void.description = Voids all power inputted into it. Sandbox only. liquid.water.description = Commonly used for cooling machines and waste processing. -liquid.lava.description = Can be transformed into[LIGHT_GRAY] stone[], used for generating power or used as ammo for certain turrets. liquid.oil.description = Can be burnt, exploded or used as a coolant. liquid.cryofluid.description = The most efficient liquid for cooling things down. diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 440393ee6a..7f109d2189 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -1,5 +1,6 @@ credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet!) credits = Yapımcılar +contributors = Translators and Contributors discord = Mindustry Discord'una katılın! link.discord.description = Resmi Mindustry Discord iletişim kanalı link.github.description = Oyunun kaynak kodu @@ -8,18 +9,20 @@ link.trello.description = Planlanan özellikler için resmi Trello Bülteni link.itch.io.description = PC yüklemeleri ve web sürümü ile itch.io sayfası link.google-play.description = Google Play mağaza sayfası link.wiki.description = Resmi Mindustry Wikipedi'si -linkfail = Bağlantı açılamadı\! URL, yazı tahtanıza kopyalandı. -editor.web = Web sürümü editörü desteklemiyor\! Editörü kullanmak için oyunu indirin. -web.unsupported = Site versiyonu bunu desteklemiyor\! Oyunu indirip dene. +linkfail = Bağlantı açılamadı! URL, yazı tahtanıza kopyalandı. +screenshot = Screenshot saved to {0} gameover = Çekirdek yok edildi. -gameover.pvp = [accent] {0}[] takimi kazandi \! -sector.gameover = Sektor kaybedildi. -sector.retry = Tekrar dene -highscore = [SARI] Yeni yüksek puan\! -wave.lasted = Su dalgaya kadar yasadin: [accent]{0}[]. -level.highscore = Yüksek Puan\: [accent] {0} -level.delete.title = Silmeyi onaylayın +gameover.pvp = [accent] {0}[] takimi kazandi ! +highscore = [SARI] Yeni yüksek puan! +stat.wave = Waves Defeated:[accent] {0} +stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} +stat.built = Buildings Built:[accent] {0} +stat.destroyed = Buildings Destroyed:[accent] {0} +stat.deconstructed = Buildings Deconstructed:[accent] {0} +stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = Su haritayi silmek istedigine emin misin? "[orange]{0}[]"? +level.highscore = Yüksek Puan: [accent] {0} level.select = Seviye Seç level.mode = Oyun Modu construction.desktop = Masaustu kontrolleri degisti.\nSecmeyi birakip yapmayi kesmek icin, [accent]bosluga bas[]. @@ -28,61 +31,37 @@ construction = Sen su anda [accent]blok yapma moduna gectin[].\n\nYapmaya baslam deconstruction.title = Blok Yikim Ogreticisi deconstruction = Sen su anda [accent]blok yikim moduna gectin[].\n\nKirmaya baslamak icin, geminin cevresinde bir bloga tikla\nBiraz blok sectikten sonra, "tik" tusuna basarak onayla, ve gemin onlari yikmaya baslayacaktir.\n\n- [accent]Blok kaldirmak[] icin onlari secme yerine gene tikla\n- [accent]Bir alanin icinde blok kirmak icin[] bos bir yere tikla, ve surukle\n- [accent]Yikma modundan cikmak icin[] Kosedeki X tusuna bas showagain = Bunu gene gosterme -coreattack = < Cekirdek saldiri altinda\! > -unlocks = Koleksiyon +coreattack = < Cekirdek saldiri altinda! > +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = Oyunu Kaydet loadgame = Oyunu yükle joingame = Oyuna katıl addplayers = Oyuncu ekle/cikar customgame = Ozel oyun -sectors = Sektorler -sector = Su sektoru sectin\: [LIGHT_GRAY]{0} -sector.time = Zaman\: [LIGHT_GRAY]{0} -sector.deploy = Basla -sector.abandon = Terk et -sector.abandon.confirm = Buradaki ilerlemeni silmek istedigine emin misin\nBu geri alinamaz\! -sector.resume = Devam et -sector.locked = [scarlet][[Bitirilmedi] -sector.unexplored = [accent][[Kesvedilmedş] -missions = Gorevler\:[LIGHT_GRAY] {0} -mission = Gorev\:[LIGHT_GRAY] {0} -mission.main = Ana gorev\:[LIGHT_GRAY] {0} -mission.info = Gorev bilgisi -mission.complete = Gorev tamamlandi\! -mission.complete.body = Sektor {0},{1} ele gecirildi -mission.wave = [accent]{0}[] dalga hayatta kal -mission.wave.enemies = [accent] {0}/{1} []dalga hayatta kal\n{2} Dusman oldur -mission.wave.enemy = [accent] {0}/{1} []dalga hayatta kal\n{2} Dusman oldur -mission.wave.menu = [accent] {0} []dalga hayatta kal -mission.battle = Dusman temelini yok et -mission.resource.menu = Sunlari ele gecir {0} x{1} -mission.resource = Sunlari ele gecir {0}\:\n[accent]{1}/{2}[] -mission.block = Su kadar yarat {0} -mission.unit = {0} Kadar unit yarat -mission.command = {0} Unite komut yolla -mission.linknode = Guc nodu bagla -mission.display = [accent]Gorev\:\n[LIGHT_GRAY]{0} -mission.mech = Su gemiye degis[accent] {0}[] -mission.create = Su kadar yarat[accent] {0}[] +newgame = New Game none = close = Kapat quit = Çık maps = Haritalar continue = Devam et -nextmission = Siradaki gorev -maps.none = [LIGHT_GRAY]Harita bulunamadi\! +maps.none = [LIGHT_GRAY]Harita bulunamadi! about.button = Hakkında name = Adı: +noname = Pick a[accent] player name[] first. filename = File Name: unlocked = New Block Unlocked! -unlocked.plural = New Blocks Unlocked! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. players = 1090 oyuncu çevrimiçi players.single = {0} Oyuncu Çevrimiçi server.closing = [accent] Sunucu kapatılıyor ... server.kicked.kick = Sunucudan kovuldun! server.kicked.serverClose = Server closed. -server.kicked.sectorComplete = Sector completed. -server.kicked.sectorComplete.text = Your mission is complete.\nThe server will now continue at the next sector. server.kicked.clientOutdated = Oyun sürümünüz geçerli değil. Oyununu güncelleyin! server.kicked.serverOutdated = Eski sunucu! Ev sahibinden güncellemesini isteyin! server.kicked.banned = Bu sunucudan yasaklandınız. @@ -91,6 +70,7 @@ server.kicked.nameInUse = There is someone with that name\nalready on this serve server.kicked.nameEmpty = Your name must contain at least one character or number. server.kicked.idInUse = You are already on this server! Connecting with two accounts is not permitted. server.kicked.customClient = This server does not support custom builds. Download an official version. +server.kicked.gameover = Game over! host.info = [Vurgu] ana bilgisayarı [] düğmesi, [657] [65] [65] ve [65] [6568] bağlantı noktalarında bir sunucuyu barındırır. [] Aynı [LIGHT_GRAY] wifi veya yerel ağ [] üzerindeki herkes sunucunuzu sunucularında görebilir. liste. Kişilerin IP tarafından herhangi bir yerden bağlanabilmesini istiyorsanız [vurgu] bağlantı noktası iletme [] gereklidir. [LIGHT_GRAY] Not: Birisi LAN oyununuza bağlanırken sorun yaşıyorsa, güvenlik duvarı ayarlarınızda Mindustry'e yerel ağınıza erişebildiğinizden emin olun. join.info = Burada, bağlanmak için yerel ağ [] sunucularına bağlanmak ya da [aksan] sunucularını bulmak için bir [vurgu] sunucunun IP [] girebilirsiniz. Hem LAN hem de WAN çok oyunculu desteklenir. [LIGHT_GRAY] Not: Otomatik bir global sunucu listesi yoktur; Birisine IP ile bağlanmak isterseniz, ana bilgisayardan kendi IP adreslerini sormanız gerekir. hostserver = Oyunu Sun @@ -161,7 +141,6 @@ save.rename.text = Yeni İsim: selectslot = Bir kayıt seçin. slot = [accent] Yuva {0} save.corrupted = [accent] Kayıt dosyası bozuk veya geçersiz! -sector.corrupted = [accent]A save file for this sector was found, but loading failed.\nA new one has been created. empty = on = Açık off = Kapalı @@ -171,6 +150,7 @@ save.wave = Dalga save.difficulty = zorluk save.date = Son Kaydedilen: {0} save.playtime = Playtime: {0} +warning = Warning. confirm = Onayla delete = Sil ok = Tamam @@ -206,7 +186,6 @@ map.nospawn = This map does not have any cores for the player to spawn in! Add a map.nospawn.pvp = This map does not have any enemy cores for player to spawn into! Add[SCARLET] red[] cores to this map in the editor. map.invalid = Error loading map: corrupted or invalid map file. editor.brush = Brush -editor.slope = \\ editor.openin = Open In Editor editor.oregen = Ore Generation editor.oregen.info = Ore Generation: @@ -261,6 +240,26 @@ tutorial = Eğitim editor = Editör mapeditor = Harita Editörü donate = Bağışlamak +abandon = Abandon +abandon.text = This zone and all its resources will be lost to the enemy. +locked = Locked +complete = [LIGHT_GRAY]Complete: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Best: {0} +launch = Launch +launch.title = Launch Successful +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson] Sunucuya bağlanılamadı: [accent] {0} error.unreachable = Server unreachable. error.invalidaddress = Invalid address. @@ -268,7 +267,20 @@ error.timedout = Timed out!\nMake sure the host has port forwarding set up, and error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! error.alreadyconnected = Already connected. error.mapnotfound = Map file not found! +error.io = Network I/O error. error.any = Unkown network error. +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = Dil settings.reset = Varsayılanlara Dön settings.rebind = Rebind @@ -279,7 +291,6 @@ settings.graphics = Grafik settings.cleardata = Clear Game Data... settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! settings.clearall.confirm = [scarlet]WARNING![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit. -settings.clearsectors = Clear Sectors settings.clearunlocks = Clear Unlocks settings.clearall = Clear All paused = Duraklatıldı @@ -288,12 +299,15 @@ no = No info.title = [Vurgu] Bilgi error.title = [crimson] Bir hata oluştu error.crashtitle = Bir hata oluştu +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Blok Bilgisi +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = Güç kapasitesi blocks.powershot = Güç / atış blocks.targetsair = Targets Air -blocks.itemspeed = Units Moved +blocks.itemsmoved = Move Speed blocks.shootrange = Range blocks.size = Boyut blocks.liquidcapacity = Sıvı kapasitesi @@ -314,16 +328,23 @@ blocks.inputitems = Input Items blocks.outputitem = Output Item blocks.drilltier = Drillables blocks.drillspeed = Base Drill Speed +blocks.maxunits = Max Active Units blocks.liquidoutput = Liquid Output blocks.liquidoutputspeed = Liquid Output Speed blocks.liquiduse = Liquid Use blocks.coolant = Coolant +blocks.liquid = Liquid blocks.coolantuse = Coolant Use blocks.inputliquidfuel = Fuel Liquid blocks.liquidfueluse = Liquid Fuel Use blocks.boostitem = Boost Item blocks.boostliquid = Boost Liquid blocks.health = Can +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = yanlışlık blocks.shots = atışlar blocks.reload = Reload @@ -331,11 +352,11 @@ blocks.inputfuel = Fuel blocks.fuelburntime = Fuel Burn Time blocks.inputcapacity = Giriş kapasitesi blocks.outputcapacity = Çıkış kapasitesi +blocks.ammo = Ammo unit.blocks = blocks unit.powersecond = power units/second unit.liquidsecond = liquid units/second unit.itemssecond = items/second -unit.pixelssecond = pixels/second unit.liquidunits = liquid units unit.powerunits = power units unit.degrees = degrees @@ -348,6 +369,7 @@ category.items = Items category.crafting = Crafting category.shooting = Shooting category.optional = Optional Enhancements +setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS setting.fpscap.none = None @@ -380,12 +402,16 @@ category.multiplayer.name = Multiplayer command.attack = Attack command.retreat = Retreat command.patrol = Patrol +keybind.gridMode.name = Block Select +keybind.gridModeShift.name = Category Select keybind.press = Press a key... keybind.press.axis = Press an axis or key... +keybind.screenshot.name = Map Screenshot keybind.move_x.name = sağ / sol keybind.move_y.name = yukarı / aşağı keybind.select.name = seçmek -keybind.break.name = kırmak +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = Deselect keybind.shoot.name = ateş etme keybind.zoom_hold.name = tut ve büyüt @@ -404,29 +430,28 @@ keybind.chat_scroll.name = Chat scroll keybind.drop_unit.name = drop unit keybind.zoom_minimap.name = Zoom minimap mode.help.title = Modların açıklaması -mode.waves.name = dalgalar -mode.waves.description = normal mod. sınırlı kaynaklar ve otomatik gelen dalgalar. +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. mode.sandbox.name = Limitsiz Oynama mode.sandbox.description = sonsuz kaynaklar ve dalgalar için zamanlayıcı yok. mode.freebuild.name = Özgür Oynama mode.freebuild.description = sınırlı kaynaklar ve dalgalar için zamanlayıcı yok. mode.pvp.name = PvP mode.pvp.description = fight against other players locally. +mode.attack.name = Attack +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = Items content.liquid.name = Liquids content.unit.name = Units -content.recipe.name = Blocks +content.block.name = Blocks content.mech.name = Mechs -item.stone.name = taş -item.stone.description = A common raw material. Used for separating and refining into other materials, or melting into lava. item.copper.name = Copper item.copper.description = A useful structure material. Used extensively in all types of blocks. item.lead.name = Lead item.lead.description = A basic starter material. Used extensively in electronics and liquid transportation blocks. item.coal.name = kömür item.coal.description = A common and readily available fuel. -item.dense-alloy.name = Dense Alloy -item.dense-alloy.description = A tough alloy made with lead and copper. Used in advanced transportation blocks and high-tier drills. +item.graphite.name = Graphite item.titanium.name = titanyum item.titanium.description = A rare super-light metal used extensively in liquid transportation, drills and aircraft. item.thorium.name = Thorium @@ -439,16 +464,20 @@ item.phase-fabric.name = Phase Fabric item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. item.surge-alloy.name = Surge Alloy item.surge-alloy.description = An advanced alloy with unique electrical properties. -item.biomatter.name = Biomatter -item.biomatter.description = A clump of organic mush; used for conversion into oil or as a basic fuel. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = kum item.sand.description = A common material that is used extensively in smelting, both in alloying and as a flux. item.blast-compound.name = Blast Compound item.blast-compound.description = A volatile compound used in bombs and explosives. While it can burned as fuel, this is not advised. item.pyratite.name = Pyratite item.pyratite.description = An extremely flammable substance used in incendiary weapons. +item.metaglass.name = Metaglass +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = su -liquid.lava.name = lav +liquid.slag.name = Slag liquid.oil.name = petrol liquid.cryofluid.name = Cryofluid mech.alpha-mech.name = Alpha @@ -483,11 +512,10 @@ mech.glaive-ship.weapon = Flame Repeater item.explosiveness = [LIGHT_GRAY]Explosiveness: {0} item.flammability = [LIGHT_GRAY]Flammability: {0} item.radioactivity = [LIGHT_GRAY]Radioactivity: {0} -item.fluxiness = [LIGHT_GRAY]Flux Power: {0} unit.health = [LIGHT_GRAY]Health: {0} unit.speed = [LIGHT_GRAY]Speed: {0} mech.weapon = [LIGHT_GRAY]Weapon: {0} -mech.armor = [LIGHT_GRAY]Armor: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]Item Capacity: {0} mech.minespeed = [LIGHT_GRAY]Mining Speed: {0} mech.minepower = [LIGHT_GRAY]Mining Power: {0} @@ -495,29 +523,60 @@ mech.ability = [LIGHT_GRAY]Ability: {0} liquid.heatcapacity = [LIGHT_GRAY]Heat Capacity: {0} liquid.viscosity = [LIGHT_GRAY]Viscosity: {0} liquid.temperature = [LIGHT_GRAY]Temperature: {0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](Constructing) block.spawn.name = Enemy Spawn -block.core.name = Core -block.metalfloor.name = Metal Floor +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = deepwater block.water.name = water -block.lava.name = lava block.tar.name = Tar -block.blackstone.name = blackstone block.stone.name = stone -block.dirt.name = dirt block.sand.name = sand block.ice.name = ice block.snow.name = snow -block.grass.name = grass -block.shrub.name = shrub -block.rock.name = rock -block.blackrock.name = blackrock -block.icerock.name = icerock +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = Copper Wall block.copper-wall-large.name = Large Copper Wall -block.dense-alloy-wall.name = Dense Alloy Wall -block.dense-alloy-wall-large.name = Large Dense Alloy Wall +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = Phase Wall block.phase-wall-large.name = Large Phase Wall block.thorium-wall.name = Thorium Wall @@ -525,7 +584,6 @@ block.thorium-wall-large.name = Large Thorium Wall block.door.name = kapı block.door-large.name = büyük kapı block.duo.name = Duo -block.scorch.name = Scorch block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = konveyör @@ -537,30 +595,29 @@ block.sorter.name = ayrıştırıcı block.sorter.description = Sorts items. If an item matches the selection, it is allowed to pass. Otherwise, the item is outputted to the left and right. block.overflow-gate.name = Overflow Gate block.overflow-gate.description = A combination splitter and router that only outputs to the left and right if the front path is blocked. -block.smelter.name = dökümcü -block.arc-smelter.name = Arc Smelter block.silicon-smelter.name = Silicon Smelter block.phase-weaver.name = Phase Weaver block.pulverizer.name = Pulverizer block.cryofluidmixer.name = Cryofluid Mixer block.melter.name = Melter block.incinerator.name = Incinerator -block.biomattercompressor.name = Biomatter Compressor +block.spore-press.name = Spore Press block.separator.name = Separator -block.centrifuge.name = Centrifuge block.power-node.name = Power Node block.power-node-large.name = Large Power Node +block.surge-tower.name = Surge Tower block.battery.name = Battery block.battery-large.name = Large Battery block.combustion-generator.name = Combustion Generator block.turbine-generator.name = Turbine Generator +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = Mechanical Drill block.pneumatic-drill.name = Pneumatic Drill block.laser-drill.name = Laser Drill block.water-extractor.name = Water Extractor block.cultivator.name = Cultivator -block.alpha-mech-pad.name = Alpha Mech Pad -block.dart-ship-pad.name = Dart Ship Pad +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = Delta Mech Pad block.javelin-ship-pad.name = Javelin Ship Pad block.trident-ship-pad.name = Trident Ship Pad @@ -585,7 +642,6 @@ block.bridge-conveyor.name = Bridge Conveyor block.plastanium-compressor.name = Plastanium Compressor block.pyratite-mixer.name = Pyratite Mixer block.blast-mixer.name = Blast Mixer -block.solidifer.name = Solidifer block.solar-panel.name = Solar Panel block.solar-panel-large.name = Large Solar Panel block.oil-extractor.name = Oil Extractor @@ -606,7 +662,6 @@ block.liquid-junction.name = Liquid Junction block.bridge-conduit.name = Bridge Conduit block.rotary-pump.name = Rotary Pump block.thorium-reactor.name = Thorium Reactor -block.command-center.name = Command Center block.mass-driver.name = Mass Driver block.blast-drill.name = Blast Drill block.thermal-pump.name = Thermal Pump @@ -625,20 +680,21 @@ block.rtg-generator.name = RTG Generator block.spectre.name = Spectre block.meltdown.name = Meltdown block.container.name = Container -block.core.description = The most important building in the game. +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = blue team.red.name = red team.orange.name = orange team.none.name = gray team.green.name = green team.purple.name = purple -unit.alpha-drone.name = Alpha Drone unit.spirit.name = Spirit Drone unit.spirit.description = The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. unit.phantom.name = Phantom Drone unit.phantom.description = An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. unit.dagger.name = Dagger unit.dagger.description = A basic ground unit. Useful in swarms. +unit.crawler.name = Crawler unit.titan.name = Titan unit.titan.description = An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. unit.ghoul.name = Ghoul Bomber @@ -648,7 +704,11 @@ unit.wraith.description = A fast, hit-and-run interceptor unit. unit.fortress.name = Fortress unit.fortress.description = A heavy artillery ground unit. unit.revenant.name = Revenant -unit.revenant.description = A heavy laser platform. +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = Your mission here is to eradicate the[LIGHT_GRAY] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this. tutorial.drill = Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein. tutorial.conveyor = [accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core. @@ -672,8 +732,6 @@ tutorial.dagger = Link power nodes to the factory.\nOnce requirements are met, a tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. block.copper-wall.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves. block.copper-wall-large.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves.\nSpans multiple tiles. -block.dense-alloy-wall.description = A standard defensive block.\nAdequate protection from enemies. -block.dense-alloy-wall-large.description = A standard defensive block.\nAdequate protection from enemies.\nSpans multiple tiles. block.thorium-wall.description = A strong defensive block.\nGood protection from enemies. block.thorium-wall-large.description = A strong defensive block.\nGood protection from enemies.\nSpans multiple tiles. block.phase-wall.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful. @@ -703,8 +761,6 @@ block.titanium-conveyor.description = Advanced item transport block. Moves items block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles. block.junction.description = Acts as a bridge for two crossing conveyor belts. Useful in situations with two different conveyors carrying different materials to different locations. block.mass-driver.description = Ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. -block.smelter.description = Burns coal for smelting copper and lead into dense alloy. -block.arc-smelter.description = Smelts copper and lead into dense alloy by using an external power source. block.silicon-smelter.description = Reduces sand with highly pure coke in order to produce silicon. block.plastanium-compressor.description = Produces plastanium from oil and titanium. block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. @@ -713,12 +769,10 @@ block.pulverizer.description = Crushes stone into sand. Useful when there is a l block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. block.blast-mixer.description = Uses oil for transforming pyratite into the less flammable but more explosive blast compound. block.cryofluidmixer.description = Combines water and titanium into cryofluid which is much more efficient for cooling. -block.solidifer.description = Cools lava to stone at a fast pace. block.melter.description = Heats up stone to very high temperatures to obtain lava. block.incinerator.description = Gets rid of any excess item or liquid. -block.biomattercompressor.description = Compresses biomatter in order to retrieve oil. +block.spore-press.description = Compresses spore pods into oil. block.separator.description = Exposes stone to water pressure in order to obtain various minerals contained in the stone. -block.centrifuge.description = More efficient than the separator, but also more expensive to build and requires power. block.power-node.description = Transmits power to connected nodes. Up to four power sources, sinks or nodes can be connected. The node will receive power from or supply power to any adjacent blocks. block.power-node-large.description = Has a larger radius than the power node and connects to up to six power sources, sinks or nodes. block.battery.description = Stores power whenever there is an abundance and provides power whenever there is a shortage, as long as there is capacity left. @@ -740,7 +794,6 @@ block.blast-drill.description = The ultimate drill. Requires large amounts of po block.water-extractor.description = Extracts water from the ground. Use it when there is no lake nearby. block.cultivator.description = Cultivates the soil with water in order to obtain biomatter. block.oil-extractor.description = Uses large amounts of power in order to extract oil from sand. Use it when there is no direct source of oil nearby. -block.dart-ship-pad.description = Leave your current vessel and change into a basic fighter aircraft.\nUse the pad by double tapping while standing on it. block.trident-ship-pad.description = Leave your current vessel and change into a reasonably well armored heavy bomber.\nUse the pad by double tapping while standing on it. block.javelin-ship-pad.description = Leave your current vessel and change into a strong and fast interceptor with lightning weapons.\nUse the pad by double tapping while standing on it. block.glaive-ship-pad.description = Leave your current vessel and change into a large, well-armored gunship.\nUse the pad by double tapping while standing on it. @@ -756,7 +809,6 @@ block.titan-factory.description = Produces advanced, armored ground units. block.fortress-factory.description = Produces heavy artillery ground units. block.revenant-factory.description = Produces heavy laser ground units. block.repair-point.description = Continuously heals the closest damaged unit in its vicinity. -block.command-center.description = Allows changing friendly AI behavior. Currently, attack, retreat and patrol commands are supported. block.conduit.description = Basic liquid transport block. Works like a conveyor, but with liquids. Best used with extractors, pumps or other conduits. block.pulse-conduit.description = Advanced liquid transport block. Transports liquids faster and stores more than standard conduits. block.phase-conduit.description = Advanced liquid transport block. Uses power to teleport liquids to a connected phase conduit over several tiles. @@ -770,13 +822,11 @@ block.thermal-pump.description = The ultimate pump. Three times as fast as a mec block.router.description = Accepts items from one direction and outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets. block.distributor.description = An advanced router which splits items to up to 7 other directions equally. block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building. -block.alpha-mech-pad.description = When given enough power, rebuilds your ship into the[accent] Alpha[] mech. block.item-source.description = Infinitely outputs items. Sandbox only. block.liquid-source.description = Infinitely outputs liquids. Sandbox only. block.item-void.description = Destroys any items which go into it without using power. Sandbox only. block.power-source.description = Infinitely outputs power. Sandbox only. block.power-void.description = Voids all power inputted into it. Sandbox only. liquid.water.description = Commonly used for cooling machines and waste processing. -liquid.lava.description = Can be transformed into[LIGHT_GRAY] stone[], used for generating power or used as ammo for certain turrets. liquid.oil.description = Can be burnt, exploded or used as a coolant. liquid.cryofluid.description = The most efficient liquid for cooling things down. diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index 19ebd95999..0400870ee6 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -13,13 +13,16 @@ linkfail = Не вдалося відкрити посилання!\nURL-адр screenshot = Скріншот збережено в {0} gameover = Гру закінчено gameover.pvp = [accent] {0}[] команда перемогла! -sector.gameover = Цей сектор було втрачено. Повторно висадитися? -sector.retry = Повторити спробу highscore = [YELLOW]Новий рекорд! -wave.lasted = Вы продержались до [accent]{0}[]-ой волны. -level.highscore = Рекорд: [accent]{0} -level.delete.title = Підтвердьте видалення +stat.wave = Хвиль відражено:[accent] {0} +stat.enemiesDestroyed = Ворогів вбито:[accent] {0} +stat.built = Будівель збудувано:[accent] {0} +stat.destroyed = Будівель знищено:[accent] {0} +stat.deconstructed = Будівель декоструйовано[accent] {0} +stat.delivered = Ресурсів здобуто: +stat.rank = Фінальний рахунок: [accent]{0} map.delete = Ви впевнені, що хочете видалити карту "[accent]{0}[]"? +level.highscore = Рекорд: [accent]{0} level.select = Вибір мапи level.mode = Режим гри: construction.desktop = Щоб скасувати вибір блоку або припинити будівництво, [accent] скористайтеся пробілом[]. @@ -29,64 +32,38 @@ deconstruction.title = Інструкція з деконструкції бло deconstruction = Ви тільки що перешли в [accent] режим деконструкції блоків[].\n\nЩоб почати руйнувати, просто торкніться блоку поруч із вашим кораблем.\nПісля вибору деяких блоків натисніть прапорець, щоб підтвердити, і ваш корабель почне їх деконструювати.\n\n- [accent]Вилучіть блоки[] з вашого вибору, торкнувшись їх.\n- [accent]Вилучіть блоки в зоні[] , торкнувшись і утримуючи порожнє місце, потім перетягніть у потрібному напрямку.\n- [accent]Скасуйте деконструкцію або виділення[] натиснувши X внизу праворуч. showagain = Не показувати знову до наступного сеансу coreattack = < Ядро під атакою! > -unlocks = Розблоковане +nearpoint = [[ [scarlet]ЗАЛИШТЕ ТОЧ НЕГАЙНО[] ]\nаннігіляція неминуча. +outofbounds = [[ ПОЗА МЕЖАМИ ]\n[]саморуйнування через{0} +database = База Даних Ядра savegame = Зберегти гру loadgame = Завантажити гру joingame = Мережева гра addplayers = Дод/Видалити гравців customgame = Користувальницька гра -sectors = Сектори -sector = Обраний сектор: [LIGHT_GRAY]{0} -sector.time = Час: [LIGHT_GRAY]{0} -sector.deploy = Висадитися -sector.abandon = Відступити -sector.abandon.confirm = Ви впевнені, що хочете відступити?\nПрогрес в секторі не можна відновити! -sector.resume = Продовжити -sector.locked = [scarlet][[Незавершений] -sector.unexplored = [accent][[Недосліджений] -missions = Місії:[LIGHT_GRAY] {0} -mission = Місія:[LIGHT_GRAY] {0} -mission.main = Головна місія:[LIGHT_GRAY] {0} -mission.info = Інформація про місію -mission.complete = Місія виконана! -mission.complete.body = Сектор {0},{1} був завойований. -mission.wave = Пережити [accent]{0}/{1}[]\nХвиля через {2} -mission.wave.enemies = Пережити [accent] {0}/{1} []хвиль\n{2} ворог. -mission.wave.enemy = Пережити[accent] {0}/{1} []хвил.\n{2} Ворог -mission.wave.menu = Пережити[accent] {0} [] хвиль -mission.battle = Знищте ядро супротивника. -mission.resource.menu = Добути {0} x{1} -mission.resource = Добути {0}:\n[accent]{1}/{2}[] -mission.block = Створити {0} -mission.unit = Створити {0} бой.од. -mission.command = Надіслати команду {0} боїв. одиницям -mission.linknode = З'єднати силові вузли -mission.display = [accent]Місія:\n[LIGHT_GRAY]{0} -mission.mech = Переключитися на мех[accent] {0}[] -mission.create = Створити[accent] {0}[] +newgame = Нова гра none = <нічого> close = Закрити quit = Вийти maps = Мапи continue = Продовжити -nextmission = Наступна місія maps.none = [LIGHT_GRAY]Карт не знайдено! about.button = Про гру name = Нік: noname = Спочатку придумайте[accent] собі нікнейм[]. filename = Ім'я файлу: -unlocked = Новий блок розблоковано! -unlocked.plural = Нові блоки розблоковано! +unlocked = Новий контент розблоковано! +completed = [accent]Завершено +techtree = Технологічне дерево +research.list = [LIGHT_GRAY]Дослідження: +research = Дослідження +researched = [LIGHT_GRAY]{0} досліджено. players = Гравців на сервері: {0} players.single = {0} гравець на сервері server.closing = [accent]Закриття серверу... server.kicked.kick = Ви були вигнані(кікнуті) з сервера! server.kicked.serverClose = Сервер закрито. -server.kicked.sectorComplete = Сектор завойовано. -server.kicked.sectorComplete.text = Ваша місія завершена. \nСервер продовжить роботу і висадить Вас в наступному секторі. server.kicked.clientOutdated = Застарілий клієнт! Оновіть свою гру! server.kicked.serverOutdated = Застарілий сервер! Попросіть адміністратора серверу оновити сервер/гру! -server.kicked.commitMismatch = Номер збірки серверу не співпадає з номером вашої збірки клієнта. Скачайте підходящу версію. server.kicked.banned = Ви були заблоковані на цьому сервері. server.kicked.recentKick = Нещодавно Вас вигнали(кікнули). \nПочекайте трохи перед наступним підключенням. server.kicked.nameInUse = На цьому сервері є хтось \nз таким ніком. @@ -164,7 +141,6 @@ save.rename.text = Нова назва: selectslot = Виберіть збереження. slot = [accent]Слот {0} save.corrupted = [accent]Збережений файл пошкоджено або э недійсним! \nЯкщо ви щойно оновили свою гру, це, мабуть, є зміною формату збереження та [scarlet] не[] є помилкою. -sector.corrupted = [accent]Файл збереження для цього сектора знайдено, але завантаження не вдалося. \n Буде створено новий файл. empty = <порожній> on = Включено off = Вимкнено @@ -174,6 +150,7 @@ save.wave = Хвиля {0} save.difficulty = Складність: {0} save.date = Останнє збереження save.playtime = Час гри: {0} +warning = Попередження confirm = Підтвердження delete = Видалити ok = ОК @@ -209,7 +186,6 @@ map.nospawn = Ця мапа не має жодного ядра для спав map.nospawn.pvp = У цій карти немає ворожих ядер, в яких гравець може з'явитися! Додайте[SCARLET] червоні[] ядра до цієї карті в редакторі. map.invalid = Помилка завантаження карти: пошкоджений або невірний файл карти. editor.brush = Пензлик -editor.slope = editor.openin = Відкрити в редакторі editor.oregen = Генерація руд editor.oregen.info = Генерація руд: @@ -264,6 +240,26 @@ tutorial = Навчання editor = Редактор mapeditor = Редактор мап donate = Пожертву\nвання +abandon = Покинути +abandon.text = Ця зона і всі її ресурси будуть втрачені для ворога. +locked = Заблоковано +complete = [LIGHT_GRAY]Завершено: +resume = Відновити зону:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Найкраща хвиля: {0} +launch = < ЗАПУСК > +launch.title = Запуск вдалий +launch.next = [LIGHT_GRAY]наступна можливість на хвилі{0} +launch.unable = [scarlet]ЗАПУСК неможливий.[] {0} Ворог. +launch.confirm = Це видалить всі ресурси у Вашому ядрі.\nВи не зможете повернутися до цієї бази. +uncover = Розкрити +configure = Вивантаження +configure.locked = [LIGHT_GRAY]Розблокувати можливість вивантаження ресурсів:\nWave {0}. +zone.unlocked = [LIGHT_GRAY]{0} розблоковано +zone.complete = {0} хвиль досясгнено:\nНові вимоги до зони виконані. +zone.config.complete = {0} хвиль досягнено. reached:\nРозблоковано можливість вивантаження. +zone.resources = Виявлені ресурси: +add = Додати... +boss.health = Здоров’я босу connectfail = [crimson]Не вдалося підключитися до сервера: [accent]{0} error.unreachable = Сервер не доступний. error.invalidaddress = Некоректна адреса. @@ -273,6 +269,18 @@ error.alreadyconnected = Ви вже підключилися. error.mapnotfound = Файл мапи не знайдено error.io = Мережева помилка введення-виведення error.any = Невідома мережева помилка +zone.groundZero.name = Нульова земля +zone.craters.name = Кратери +zone.frozenForest.name = Крижаний Ліс +zone.ruinousShores.name = Зруйновані Берега +zone.crags.name = Кручі +zone.stainedMountains.name = Пофарбовані гори +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Пустельний Розлом +zone.arcticDesert.name = Арктична Пустеля +zone.dryWastes.name = Брудні Відходи +zone.nuclearComplex.name = Ядерний Виробничий Комплекс +zone.moltenFault.name = РозплавленийРозлом settings.language = Мова settings.reset = Скинути за замовчуванням settings.rebind = Зміна @@ -283,7 +291,6 @@ settings.graphics = Графіка settings.cleardata = Очистити дані... settings.clear.confirm = Ви впевнені, що хочете очистити ці дані?\nЦя дія не може бути скасовано! settings.clearall.confirm = [scarlet]УВАГА![]\nЦе очистить всі дані, включаючи збереження, карти, розблокуване та призначенні клавіші.\nПісля того, як ви натиснете ОК, гра видалить усі дані та автоматично вийде. -settings.clearsectors = Очистити сектори settings.clearunlocks = Очистити розблоковане settings.clearall = Очистити все paused = Пауза @@ -292,12 +299,15 @@ no = Ні info.title = Інформація error.title = [crimson]Виникла помилка error.crashtitle = Виникла помилка +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Інформація про блок +blocks.powerbalance = Енергія: {0} +blocks.poweroutput = Вихідна енергія: {0} blocks.powercapacity = Місткість енергії blocks.powershot = Енергія/постріл blocks.targetsair = Атакуе повітряних ворогів -blocks.itemspeed = Швидкість переміщення ресурсів +blocks.itemsmoved = Швидкість переміщення blocks.shootrange = Діапазон дії blocks.size = Розмір blocks.liquidcapacity = Місткість рідини @@ -318,16 +328,23 @@ blocks.inputitems = Вхідні предмети blocks.outputitem = Вихідний предмет blocks.drilltier = Видобуває blocks.drillspeed = Базова швидкість свердління +blocks.maxunits = Max Active Units blocks.liquidoutput = Вихідна рідина blocks.liquidoutputspeed = Швидкість вихідної рідини blocks.liquiduse = Використовуеться рідин blocks.coolant = Охолоджуюча рідина +blocks.liquid = Рідина blocks.coolantuse = Охолодж. рідини використовуеться blocks.inputliquidfuel = Рідке паливо blocks.liquidfueluse = Рідкого палива використовуеться blocks.boostitem = Прискорюючий предмет blocks.boostliquid = Прискорююча рідина blocks.health = Здоров'я +blocks.heat = Heat +blocks.power = Енергія +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Енергії вистачає blocks.inaccuracy = Розкид blocks.shots = Постріли blocks.reload = Постріли/секунду @@ -335,11 +352,11 @@ blocks.inputfuel = Паливо blocks.fuelburntime = Час горіння топлива blocks.inputcapacity = Макс. місткість вхідних предметів blocks.outputcapacity = Макс. місткість вихідних предметів +blocks.ammo = Боєприпаси unit.blocks = блоки unit.powersecond = одиниць енергії/секунду unit.liquidsecond = рідких одиниць/секунду unit.itemssecond = предметів/секунду -unit.pixelssecond = пікселів/секунду unit.liquidunits = рідинних одиниць unit.powerunits = енергетичних одиниць unit.degrees = град. @@ -392,8 +409,9 @@ keybind.press.axis = Натисніть клавішу... keybind.screenshot.name = Скріншот мапи keybind.move_x.name = Рух по осі x keybind.move_y.name = Рух по осі x -keybind.select.name = ВибратиПостріл -keybind.break.name = Руйнування +keybind.select.name = Вибір/Постріл +keybind.pick.name = Вибрати блок +keybind.break_block.name = Зламати блок keybind.deselect.name = Скасувати keybind.shoot.name = Постріл keybind.zoom_hold.name = Удержание зума @@ -412,8 +430,8 @@ keybind.chat_scroll.name = Прокрутка чату keybind.drop_unit.name = Скинути бой. од. keybind.zoom_minimap.name = Збільшити мінікарту mode.help.title = Опис режимів -mode.waves.name = Хвилі -mode.waves.description = Звичайний режим. В режимі "Хвилі" треба самим добувати ресурси та хвилі йдуть беззупинно. +mode.survival.name = Хвилі +mode.survival.description = Звичайний режим. В цьому режимі треба самим добувати ресурси та хвилі йдуть беззупинно. mode.sandbox.name = Пісочниця mode.sandbox.description = В режимі "Пісочниця" бескінечні ресурси(але їх все одно можно добувати) та хвилі йдуть за вашим бажанням. mode.freebuild.name = Вільне\nбудівництво @@ -421,27 +439,24 @@ mode.freebuild.description = В режимі "Пісочниця" треба с mode.pvp.name = PVP mode.pvp.description = боріться проти інших гравців. mode.attack.name = Атака -mode.attack.descrption = Немає хвиль, мета - знищити базу противника. +mode.attack.description = Немає хвиль, мета - знищити базу противника. content.item.name = Предмети content.liquid.name = Рідини content.unit.name = Бойові одиниці -content.recipe.name = Блоки +content.block.name = Блоки content.mech.name = Мехи -item.stone.name = Камінь -item.stone.description = Загальна сировина. Використовується для розділення та переробки в інші матеріали або плавки в лаву. item.copper.name = Мідь item.copper.description = Корисний структурний матеріал. Широко використовується у всіх типах блоків. item.lead.name = Свинець item.lead.description = Базовий стартовий матеріал. Широко використовується в електроніки та транспорту рідин. item.coal.name = Вугілля item.coal.description = Загальне та легкодоступне паливо. -item.dense-alloy.name = Щільний сплав -item.dense-alloy.description = Сплав, котрий вироблений зі свинця та міді. Використовується в передових транспортних блоках та високорівневих свердлах. +item.graphite.name = Графіт item.titanium.name = Титан item.titanium.description = Рідкий суперлегкий метал широко використовується в рідкому транспорті, свердлах та літальних апаратах. item.thorium.name = Торій item.thorium.description = Густий, радіоактивний метал, що використовується як структурна підтримка та ядерне паливо. -item.silicon.name = Кремній +item.silicon.name = Кремній item.silicon.description = Надзвичайно корисний напівпровідник з застосуванням в сонячних батареях та складній електроніці. item.plastanium.name = Пластиній item.plastanium.description = Легкий, пластичний матеріал, що використовується в сучасних літальних апаратах та у боєприпасах для фрагментації. @@ -449,16 +464,20 @@ item.phase-fabric.name = Фазова тканина item.phase-fabric.description = Невагоме речовина, що використовується в сучасній електроніці і технології самовідновлення. Не для вишивання. item.surge-alloy.name = Кінетичний сплав item.surge-alloy.description = Передовий сплав з унікальними електричними властивостями. -item.biomatter.name = Біоматерія -item.biomatter.description = Скупчення органічної муси; використовується для перетворення в нафту або як паливо. +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = Пісок item.sand.description = Загальний матеріал, який широко використовується при плавленні, як у процесі плавки, так і у вигляді шлака. item.blast-compound.name = Вибухонебезпечне з'єднання item.blast-compound.description = Нестійке з'єднання, що використовується в бомбах та вибухових речовинах. Хоча воно може спалюватися як паливо, та це не рекомендується. item.pyratite.name = Піротит item.pyratite.description = Вкрай легкозаймиста речовина, що використовується у запальній зброї. +item.metaglass.name = Біоскло +item.metaglass.description = Надміцна суміш скла. Широко використовується для розподілу і зберігання рідини. +item.scrap.name = Металобрухт +item.scrap.description = Залишки старих споруд і бойових одиниць. Містить незначні кількості багатьох різних металів. liquid.water.name = Вода -liquid.lava.name = Лава +liquid.slag.name = Slag liquid.oil.name = Нафта liquid.cryofluid.name = Кріогенна рідина mech.alpha-mech.name = Альфа @@ -493,11 +512,10 @@ mech.glaive-ship.weapon = Вогняний кулемет item.explosiveness = [LIGHT_GRAY]Вибухонебезпечність: {0} item.flammability = [LIGHT_GRAY]Вогненебезпечність: {0} item.radioactivity = [LIGHT_GRAY]Радіоактивність: {0} -item.fluxiness = [LIGHT_GRAY]Осадковість: {0} unit.health = [LIGHT_GRAY]Здоров'я: {0} unit.speed = [LIGHT_GRAY]Швидкість: {0} mech.weapon = [LIGHT_GRAY]Зброя: {0} -mech.armor = [LIGHT_GRAY]Броня: {0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY] Ємність елементів: {0} mech.minespeed = [LIGHT_GRAY]Швидкість видобутку: {0} mech.minepower = [LIGHT_GRAY]Потужність видобутку: {0} @@ -505,30 +523,60 @@ mech.ability = [LIGHT_GRAY]Здібність: {0} liquid.heatcapacity = [LIGHT_GRAY]Теплоємність: {0} liquid.viscosity = [LIGHT_GRAY]В'язкість: {0} liquid.temperature = [LIGHT_GRAY]Температура: {0} +block.scrap-wall.name = Стіна з металобрухту +block.scrap-wall-large.name = Велика стіна з металобрухту +block.scrap-wall-huge.name = Величезна стіна з металобрухту +block.scrap-wall-gigantic.name = Гігантська стіна з металобрухту +block.thruster.name = Штовхач +block.kiln.name = Піч +block.kiln.description = Виплавляє пісок і свинець в біоскло. Потребує малої кількості енергії. +block.graphite-press.name = Графітний прес +block.multi-press.name = Мульти-прес block.constructing = {0}\n[LIGHT_GRAY](В процесі) block.spawn.name = Місце появи ворога -block.core.name = Ядро -block.space.name = Пустота -block.metalfloor.name = Металева плитка +block.core-shard.name = Ядро: Осколок +block.core-foundation.name = Ядро: Штаб +block.core-nucleus.name = Ядро: Атом block.deepwater.name = Глибоководдя block.water.name = Вода -block.lava.name = Лава block.tar.name = Tar -block.blackstone.name = Чорний камінь block.stone.name = Камінь -block.dirt.name = Земля -block.sand.name = Пісок +block.sand.name = Темний пісок block.ice.name = Лід block.snow.name = Сніг -block.grass.name = Трава -block.shrub.name = Кущ -block.rock.name = Кругляк -block.blackrock.name = Чорний кругляк -block.icerock.name = Льодяний кругляк +block.craters.name = Кратери +block.sand-water.name = Пісок з водою +block.char.name = Випалена Земля +block.holostone.name = Голографічний камінь +block.ice-snow.name = Крижаний Сніг +block.rocks.name = Камені +block.icerocks.name = Крижані камені +block.snowrocks.name = Снігові камені +block.dunerocks.name = Піщані Камені +block.pine.name = Сосна +block.white-tree-dead.name = Мертве Біле Дерево +block.white-tree.name = Біле Дерево +block.spore-cluster.name = Скупчення спор +block.stained-rocks.name = Плямисті Камені +block.stained-stone.name = Плямистий Камінь +block.stained-rocks-red.name = Червоні Плямисті Камні +block.stained-stone-red.name = Червоний Плямистий Камінь +block.stained-rocks-yellow.name = Жовті Плямисті Камні +block.stained-stone-yellow.name = Жовтий Плямистий Камінь +block.stained-boulder.name = Плямистий Валун +block.metal-floor.name = Металевий Пол +block.metal-floor-2.name = Металевий Пол 2 +block.metal-floor-3.name = Металевий Пол 3 +block.metal-floor-5.name = Металевий Пол 5 +block.metal-floor-damaged.name = Пошкоджений Металевий Пол +block.ignarock.name = Магматичні Гірські Породи +block.hotrock.name = Гарячий Камінь +block.magmarock.name = Магмакамінь +block.cliffs.name = Скелі block.copper-wall.name = Мідна стіна block.copper-wall-large.name = Велика мідна стіна -block.dense-alloy-wall.name = Стіна з щільного сплаву -block.dense-alloy-wall-large.name = Велика стіна з щільного сплаву +block.titanium-wall.name = Титанова стіна +block.titanium-wall-large.name = Велика титанова стіна block.phase-wall.name = Фазова стіна block.phase-wall-large.name = Велика фазова стіна block.thorium-wall.name = Торієва стіна @@ -536,7 +584,6 @@ block.thorium-wall-large.name = Велика торієва стіна block.door.name = Двері block.door-large.name = Великі двері block.duo.name = Подвійна -block.scorch.name = Випалювач block.hail.name = Град block.lancer.name = Списоносець block.conveyor.name = Конвеєр @@ -548,31 +595,30 @@ block.sorter.name = Сортувальник block.sorter.description = Сортує предмети. Якщо товар відповідає виділенню, йому можна пройти. В іншому випадку предмет виводиться ліворуч і праворуч. block.overflow-gate.name = Надмірний затвор block.overflow-gate.description = Комбінований розподілювач і маршрутизатор, який виводить тільки вліво та вправо, якщо передній шлях заблоковано. -block.smelter.name = Плавильний завод -block.arc-smelter.name = Дуговий плавильний завод block.silicon-smelter.name = Кремнієвий завод block.phase-weaver.name = Фазовий ткач block.pulverizer.name = Розпилювач block.cryofluidmixer.name = Змішувач кріогненної рідини block.melter.name = Плавильня block.incinerator.name = Сміттєспалювальний завод -block.biomattercompressor.name = Біоматерний компресор +block.spore-press.name = Spore Press block.separator.name = Сепаратор -block.centrifuge.name = Центрифуга block.power-node.name = Енергійний вузол block.power-node-large.name = Великий енергетичний вузол +block.surge-tower.name = Кінетична вежа block.battery.name = Акумулятор block.battery-large.name = Великий акумулятор block.combustion-generator.name = Генератор горіння block.turbine-generator.name = Турбогенератор +block.differential-generator.name = Дифернеціальний генератор +block.impact-reactor.name = Імпульсний реактор block.mechanical-drill.name = Механічний дриль block.pneumatic-drill.name = Пневматичний дриль block.laser-drill.name = Лазерний дриль block.water-extractor.name = Екстрактор води block.cultivator.name = Культиватор -block.alpha-mech-pad.name = Реконстуктор "Альфа" -block.dart-ship-pad.name = Завод дротікових літаків -block.delta-mech-pad.name = Реконструктор "Дельта" +block.alpha-dart-mech-pad.name = Реконструктор "Альфа-Дротик" +block.delta-mech-pad.name = Delta Mech Pad block.javelin-ship-pad.name = Реконструктор "Джавелін" block.trident-ship-pad.name = Реконструктор "Тризуб" block.glaive-ship-pad.name = Реконструктор "Спис" @@ -588,7 +634,7 @@ block.power-source.name = Нескінченна енергія block.unloader.name = Розвантажувач block.vault.name = Сховище block.wave.name = Хвиля -block.swarmer.name = Ройевик +block.swarmer.name = Роєвик block.salvo.name = Залп block.ripple.name = Рябь block.phase-conveyor.name = Фазовий конвеєр @@ -596,7 +642,6 @@ block.bridge-conveyor.name = Мостовий конвеєр block.plastanium-compressor.name = Пластиновий компресор block.pyratite-mixer.name = Змішувач піротиту block.blast-mixer.name = Доменний змішувач -block.solidifer.name = Затверджувач block.solar-panel.name = Сонячна панель block.solar-panel-large.name = Велика сонячна панель block.oil-extractor.name = Екстрактор нафти @@ -617,7 +662,6 @@ block.liquid-junction.name = Рідкий з'єднання block.bridge-conduit.name = Мостовий водопровід block.rotary-pump.name = Роторний насос block.thorium-reactor.name = Торієвий реактор -block.command-center.name = Командний центр block.mass-driver.name = Електромагнітна катапульта block.blast-drill.name = Бурова установка block.thermal-pump.name = Тепловий насос @@ -628,7 +672,7 @@ block.surge-wall.name = Хвиляста стіна block.surge-wall-large.name = Велика хвиляста стіна block.cyclone.name = Циклон block.fuse.name = Підривник -block.shock-mine.name = Шокуюча міна +block.shock-mine.name = Міна block.overdrive-projector.name = Сверхприводний проектор block.force-projector.name = Силовий проектор block.arc.name = Дуга @@ -636,19 +680,21 @@ block.rtg-generator.name = Радіоізотопний термоелектри block.spectre.name = Мара block.meltdown.name = Розтоплення block.container.name = Склад +block.launch-pad.name = Стартовий майданчик +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = Синя team.red.name = Червона team.orange.name = Помаренчева team.none.name = Сіра team.green.name = Зелена team.purple.name = Фіолетова -unit.alpha-drone.name = Альфа unit.spirit.name = Дрон-привид unit.spirit.description = Початковий дрон. З'являється в ядрі за замовчуванням. Автоматично добуває руди та ремонтує блоки. unit.phantom.name = Фантом unit.phantom.description = Покращений дрон. Автоматично добуває руди та ремонтує блоки. unit.dagger.name = Кинджал unit.dagger.description = Базова наземна бойова одиниця. Корисен у купі. +unit.crawler.name = Crawler unit.titan.name = Титан unit.titan.description = Улучшенная бронированная наземная боевая единица. Атакует наземные и воздушные цели. unit.ghoul.name = Бомбардувальний "Ґуль" @@ -658,7 +704,11 @@ unit.wraith.description = Швидка бойова одиниця, котрий unit.fortress.name = Фортеця unit.fortress.description = Тяжка артилерійна наземна бойова одиниця. unit.revenant.name = Потойбічний вбивця -unit.revenant.description = Важка бойова одиниця з лазерною зброєю. +unit.eruptor.name = Вивиргатель +unit.chaos-array.name = Масив хаосу +unit.eradicator.name = Викорінювач +unit.lich.name = Лич +unit.reaper.name = Жнець tutorial.begin = Ваша місія тут полягає в ліквідації[LIGHT_GRAY] противника[].\n\nПочнімо з[accent] видобутку міді[]. Щоб зробити це, торкніться мідної рудної жили біля вашого ядра. tutorial.drill = Ручна робота не ефективна\n[accent]Бури []можуть копати автоматично.\nПоставте один на мідній жилі. tutorial.conveyor = [accent]Конвейери[] використовуються для транспортування предметів в ядра.\nЗробіть лінію конвейерів від бурів до ядра. @@ -680,11 +730,8 @@ tutorial.daggerfactory = Побудуйте[accent] завод "Кинджал". tutorial.router = Фабрики потребують ресурсів для функціонування.\nСтворіть маршрутизатор для розподілення ресурсів з конвейера. tutorial.dagger = Зв'яжіть силовий вузол з заводом.\nЯк тільки вимоги будуть виконані, буде створено мех.\n\nЯкщо необхідно, то створіть ще бурів, генераторів та конвейерів tutorial.battle = [LIGHT_GRAY] Супротивник[] показав своє ядро.\nЗнищьте його з вашим мехом та бойовою одиницею. -block.core.description = Найголовніше будівля в грі. block.copper-wall.description = Дешевий оборонний блок.\nКорисен для захисту ядра і турелей під час перших хвиль. block.copper-wall-large.description = Велика стіна найменшим запасом міцності.\nКорисна на початку гри. -block.dense-alloy-wall.description = Стіна з показником міцності "нижче середнього". -block.dense-alloy-wall-large.description = Велика стіна з показником міцності "нижче середнього". block.thorium-wall.description = Стіна з показником міцності "вище середнього". block.thorium-wall-large.description = Велика стіна з показником міцності "вище середнього". block.phase-wall.description = Стіна з середнім показником міцності. @@ -711,11 +758,9 @@ block.spectre.description = Велика вежа, яка стріляє зра block.meltdown.description = Велика турель, яка стріляє могутніми далекобійними променями. block.conveyor.description = Переміщує ресурси з малою швидкістю. block.titanium-conveyor.description = Конвеєр другого покоління. Збільшена швидкість переміщення предметів і міцність конвеєра. -block.phase-conveyor.description = Поки гра знаходиться в 2D, цей конвеєр вже в чотиривимірному просторі (можливо, це брехня).\nПотрібує енергії і підключається як мостовий конвеєр. +block.phase-conveyor.description = Поки гра знаходиться в 2D, цей конвеєр вже в чотиривимірному просторі (можливо, це брехня).\nПотребує енергії і підключається як мостовий конвеєр. block.junction.description = Назва говорить сама за себе. За допомогою нього можна зробити дві конвеєрні стрічки, які проходять через один одного і не змішуються. block.mass-driver.description = При наявності енергії передають ресурси на відстань 100 блоків, стріляючи в один-одного. -block.smelter.description = Виробляє щільний сплав з міді і свинцю. Можна підвести пісок для прискорення виробництва. -block.arc-smelter.description = Покращена версія плавильного заводу. Вимагає енергію. Виробляє щільний сплав з міді і свинця.\nМожно підвести пісок для прискорення виробництва. block.silicon-smelter.description = За допомогою піску, вугілля і енергії виробляє кремній. block.plastanium-compressor.description = Створює пластинійи з титану і нафти. Вимагає енергії. Для прискорення виробництва можна додати в компресор пісок. block.phase-weaver.description = Виробляє фазову тканину торію і піску. Вимагає багато енергії. @@ -723,20 +768,18 @@ block.alloy-smelter.description = Створює кінетичний сплав block.pulverizer.description = Подрібнює камінь в пісок. Вимагає енергії. block.pyratite-mixer.description = Створює піротит з вугілля, свинцю і піску. Вимагає енергії. block.blast-mixer.description = Створює вибухонебезпечне з'єднання з нафти і піротіта. Для прискорення виробництва можна додати в мішалку пісок. -block.cryofluidmixer.description = Виробляє криогенну рідину з води і титану. Вимагає енергії. -block.solidifer.description = Остуджує лаву до каменя. Вимагає енергію. -block.melter.description = Переплавляє камінь в лаву. Вимагає енергію. +block.cryofluidmixer.description = Виробляє криогенну рідину з води і титану. Вимагає енергії. +block.melter.description = Розплавляє металобрухт у шлаки для подальшої переробки або використання у турелях. block.incinerator.description = Якщо є непотрібні ресурси, можна просто їх спалити.\nВимагає енергії. -block.biomattercompressor.description = Виробляє нафту з біоматеріі, біосміття і енергії. -block.separator.description = Шукає в камені різні ресурси. Чим цінніше ресурс, тим з меншою ймовірністю він "знайдеться". -block.centrifuge.description = Шукає в камені різні ресурси. Чим цінніше ресурс, тим з меншою ймовірністю він "знайдеться".\nТребует енергію. -block.power-node.description = Максимум допустимо 4 підключення.\nЩоб з'єднати з якимось блоком потрібно наступне\:\n1. Щоб він знаходився в радіусі дії \n2. Натиснити на потрібний силовий вузол, а потім на інший силовий вузол або блок. +block.spore-press.description = Compresses spore pods into oil. +block.separator.description = Витягує корисні мінерали з шлаку. +block.power-node.description = Максимум допустимо 4 підключення.\nЩоб з'єднати з якимось блоком потрібно наступне:\n1. Щоб він знаходився в радіусі дії \n2. Натиснити на потрібний силовий вузол, а потім на інший силовий вузол або блок. block.power-node-large.description = Силовий вузол другого покоління. Збільшено радіус дії і кількість максимально допустимих підключень. block.battery.description = Хранит энергию всякий раз, когда есть изобилие, и обеспечивает мощность всякий раз, когда есть недостаток, если есть мощность, але БАТАРЕЙКИ DURACELL ЗБЕРІГАЮТЬ БІЛЬШЕ! (прихована реклама) block.battery-large.description = Зберігає значно більше енергії, ніж звичайна батарейка... block.combustion-generator.description = Генерує енергію, спалюючи нафту або легкозаймисті матеріали. block.turbine-generator.description = Більш ефективний, ніж генератор горіння, але вимагає додаткової води. -block.thermal-generator.description = Генерує велику кількість енергії з лави. +block.thermal-generator.description = Генерує енергію при розміщенні в гарячих місцях. block.solar-panel.description = Забезпечує невелику кількість енергії від сонця. block.solar-panel-large.description = Забезпечує набагато краще джерело живлення, ніж стандартна панель, але в той же час набагато дорожче її побудувати. block.thorium-reactor.description = Генерує величезну кількість енергії з високоактивного торію. Потребує постійного охолодження. Вибухне сильно, якщо постачається недостатня кількість рідини. @@ -749,9 +792,8 @@ block.pneumatic-drill.description = Покращена версія механі block.laser-drill.description = Покращена версія пневматичного бура.\nДобивает теж саме, що і пневматичний бур. Також може добувати торій.\nМожно підвести до нього[BLUE] воду []для збільшення швидкості свердління. block.blast-drill.description = Найпотужніший бур.\n\nВидобуває теж саме, що і лазерний бур. Свердлить швидше всіх бурів, але вимагає ще більше енергії.\nМожно підвести до нього[BLUE] воду [] для збільшення швидкості свердління. block.water-extractor.description = Витягує воду з землі. Використовуйте його, коли поблизу немає озера. -block.cultivator.description = Культивує грунт водою для отримання біоматеріі. +block.cultivator.description = Культивує спори водою для отримання біоматеріі. block.oil-extractor.description = Використовує велику кількість енергії для видобутку нафти з піску, динозаврів (закреслено). Використовуйте його, коли поблизу немає прямого джерела нафти. -block.dart-ship-pad.description = Залиште свій поточний судно і перейдіть на основний винищувач.\nВикористовуйте подвійне натискання, стоячи на реконструкторів, щоб перетворитися в цей мех. block.trident-ship-pad.description = Залиште свій поточний корабель і перейдіть в досить добре броньований важкий бомбардувальник.\nВикористовуйте подвійне натискання, стоячи на реконструкторів, щоб перетворитися в цей мех. block.javelin-ship-pad.description = Залиште свій поточний корабель і перейдіть в сильний і швидкий перехоплювач з блискавичним зброєю.\nВикористовуйте подвійне натискання, стоячи на реконструкторів, щоб перетворитися в цей мех. block.glaive-ship-pad.description = Залиште своє існуюче судно і перетворитесь на великий, добре броньований мех.\nВикористовуйте подвійне натискання, стоячи на реконструкторів, щоб перетворитися в цей мех. @@ -765,9 +807,8 @@ block.ghoul-factory.description = Виробляє важких килимови block.dagger-factory.description = Виробляє основні наземні бойові одиниці. block.titan-factory.description = Виробляє просунуті захищені бойові одиниці. block.fortress-factory.description = Виробляє важкі артилерійські бойові одиниці. -block.revenant-factory.description = Виробляє важкі наземні бойові одиниці. +block.revenant-factory.description = Виробляє важкі бойові одиниці, котрі літають. block.repair-point.description = Постійно лікує найближчий пошкоджений апарат в його зоні дії. -block.command-center.description = Дозволяє змінювати дружню поведінку AI. В даний час, атаки, відступ і патрулювання команди підтримуються. block.conduit.description = Основний транспортний блок. Працює як конвеєр, але з рідинами. Найкраще використовується з екстракторами, насосами або іншими трубопроводами. block.pulse-conduit.description = Розширений блок перевезення рідин. Транспортує рідини швидше і зберігає більше, аніж стандартні. block.phase-conduit.description = Покращений блок перевезення рідин. Використовує енергію для телепорту рідин до підключеного фазового каналу по декілька блоків. @@ -781,13 +822,11 @@ block.thermal-pump.description = Остаточний насос. Тричі ш block.router.description = Приймає елементи з одного напрямку і рівномірно виводить їх до 3 інших напрямків. Корисно для розділення матеріалів від одного джерела на кілька. block.distributor.description = Розширений маршрутизатор, який рівномірно розбиває елементи на 7 різних напрямків. block.bridge-conveyor.description = Покращений блок транспортування предметів. Дозволяє транспортувати предмети понад 3 блоки над будь-якої місцевостю або будівлеє. -block.alpha-mech-pad.description = Коли ви отримаєте достатньо енергії, перебудовує ваш корабель у [accent] Альфа[] мех. block.item-source.description = Безліченно виводить предмети. block.liquid-source.description = Безліченно виводить рідини. block.item-void.description = Знищує будь-які предмети, які входять, без використання енергії. block.power-source.description = Нескінченність не межа. Безмежно виводить енергію. block.power-void.description = Енергія просто йде в порожнечу. liquid.water.description = Цю рідину можно підвести до бурів для прискорення швидкості видобутку або к турелям для прискорення стрілянини. -liquid.lava.description = Можна перетворити в[LIGHT_GRAY] камінь[]. liquid.oil.description = Можна спалити, взірвати або використовувати для охолодження. liquid.cryofluid.description = Рідина з температурою нижче ніж -273 градусів за Цельсієм. Може бути використана для прискорення стрільби турелей або для охолодження чогось. diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties index e64258afdd..8cbb346913 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -1,5 +1,6 @@ credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet!) credits = 致谢 +contributors = 译者和贡献者 discord = 加入 Mindustry 的 Discord! link.discord.description = 官方 Mindustry discord 聊天室 link.github.description = 游戏源码 @@ -9,15 +10,19 @@ link.itch.io.description = PC版下载和网页版(itch.io) link.google-play.description = 从谷歌商店获取安卓版 link.wiki.description = 官方 Mindustry 维基 linkfail = 打开链接失败!\nURL 已经复制到剪贴板。 +screenshot = 荧幕截图已放在 {0} gameover = 你的核心被摧毁了! gameover.pvp = accent] {0}[] 队获胜! -sector.gameover = 这个区域失守了,要重新部署吗? -sector.retry = 重试 highscore = [accent]新纪录! -wave.lasted = 你坚持到了第 [accent]{0}[] 波。 -level.highscore = 最高分: [accent]{0} -level.delete.title = 确认删除 +stat.wave = 战胜的波数:[accent] {0} +stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} +stat.built = Buildings Built:[accent] {0} +stat.destroyed = Buildings Destroyed:[accent] {0} +stat.deconstructed = Buildings Deconstructed:[accent] {0} +stat.delivered = Resources Launched: +stat.rank = Final Rank: [accent]{0} map.delete = 确定要删除 "[accent]{0}[]" 地图吗? +level.highscore = 最高分: [accent]{0} level.select = 选择关卡 level.mode = 游戏模式: construction.desktop = 桌面控制已更改.\n取消选择快活停止构建, [accent]使用空间[]. @@ -27,60 +32,36 @@ deconstruction.title = 方块删除指导 deconstruction = 你选择了 [accent]删除模式[]。\n\n点击你附近的有效位置以删除\n选择了方块以后,点击复选框就会开始删除。\n\n- [accent]移除方块-[] 点击想要删除的方块。\n- [accent]移除选中部分-[] 按住并拖动以选中一个区域。\n- [accent]取消删除或选择-[] 按左下角的X. showagain = 不再显示 coreattack = < 核心正在受到攻击! > -unlocks = 已解锁 +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = 保存游戏 loadgame = 载入游戏 joingame = 加入游戏 addplayers = 增加/删除玩家 customgame = 自定义游戏 -sectors = 区域 -sector = 区域: [LIGHT_GRAY]{0} -sector.time = 时间: [LIGHT_GRAY]{0} -sector.deploy = 部署 -sector.abandon = 放弃 -sector.abandon.confirm = 你确定要放弃这个区域的所有进展吗?\n此操作不可撤销! -sector.resume = 继续 -sector.locked = [scarlet][[Incomplete] -sector.unexplored = [accent][[Unexplored] -missions = 任务:[LIGHT_GRAY] {0} -mission = 任务[LIGHT_GRAY] {0} -mission.main = 主要任务:[LIGHT_GRAY] {0} -mission.info = 任务信息 -mission.complete = 任务完成! -mission.complete.body = 区域 {0},攻占了 {1} 个 -mission.wave = 存活了 [accent]{0}/{1}[] 波。\n下一波 {2} -mission.wave.enemies = 存活[accent] {0}/{1} []波\n{2} 敌人 -mission.wave.enemy = 存活[accent] {0}/{1} []波\n{2} 敌人 -mission.wave.menu = 存活[accent] {0} []波 -mission.battle = 摧毁敌方基地。 -mission.resource.menu = 获取{0}x{1} -mission.resource = 获取{0}︰\n[accent]{1}/{2}[] -mission.block = 建造{0} -mission.unit = 生产{0}机组 -mission.command = 发送{0}指令至机组 -mission.linknode = 连接能源节点 -mission.display = [accent]任务︰\n[LIGHT_GRAY]{0} -mission.mech = 转换至[accent]{0}[]机甲 -mission.create = 制造[accent] {0}[] +newgame = 新游戏 none = <无> close = 关闭 quit = 退出 maps = 地图 continue = 继续 -nextmission = 下一个任务 maps.none = [LIGHT_GRAY]未发现地图! about.button = 关于 name = 名字: +noname = Pick a[accent] player name[] first. filename = 文件名: unlocked = 新方块已解锁! -unlocked.plural = 新方块已解锁! +completed = [accent]Completed +techtree = Tech Tree +research.list = [LIGHT_GRAY]Research: +research = Research +researched = [LIGHT_GRAY]{0} researched. players = {0} 玩家在线 players.single = {0} 玩家在线 server.closing = [accent]正在关闭服务器…… server.kicked.kick = 你被踢出服务器了! server.kicked.serverClose = 服务器已关闭。 -server.kicked.sectorComplete = 区域已完成。 -server.kicked.sectorComplete.text = 任务已完成。\n服务器将在下一个区域继续。 server.kicked.clientOutdated = 客户端版本过旧!请升级! server.kicked.serverOutdated = 服务器版本过旧!请联系房主升级! server.kicked.banned = 你被这个服务器拉黑了。 @@ -89,6 +70,7 @@ server.kicked.nameInUse = 服务器中已经\n有人有相同的名字了。 server.kicked.nameEmpty = 你的名字必须至少包含一个字母或数字。 server.kicked.idInUse = 你已经在服务器中!不允许用两个账号。 server.kicked.customClient = 这个服务器不支持修改版客户端,请下载官方版本。 +server.kicked.gameover = ! host.info = [accent]创建局域网游戏[]按钮会在[scarlet]6567[]端口运行一个服务器。[]\n任何在同一个[LIGHT_GRAY]网络或本地网络[]下的人都将在服务器列表中看到你的服务器。\n\n如果你想让别人在任何地方都能通过IP地址连接,你需要设定[accent]端口转发[]。\n\n[LIGHT_GRAY]请注意:如果某人无法连接到你的局域网游戏,请确保你在防火墙设置里允许了Mindustry连接本地网络。 join.info = 你可以在这里输入[accent]服务器的IP地址[]以连接,或寻找[accent]本地网络[]中的服务器以连接。\n目前支持局域网或广域网多人游戏。\n\n[LIGHT_GRAY]请注意:没有全球服务器列表;如果你想通过IP地址连接某个服务器,你需要向房主询问IP地址。 hostserver = 创建服务器 @@ -158,8 +140,7 @@ save.rename = 重命名 save.rename.text = 新名字: selectslot = 选择一个存档。 slot = [accent]存档 {0} -save.corrupted = [accent]存档损坏或无效!\n如果你刚刚升级了游戏,那么这可能是因为存档格式改变了而[scarlet]不是[] bug 。 -sector.corrupted = [accent]发现了一个此区域的保存文件,但是加载失败。\n已经创建了一个新的。 +save.corrupted = [accent]存档损坏或无效!\n如果你刚刚升级了游戏,那么这可能是因为存档格式改变了,而[scarlet]不是[] bug 。 empty = <空> on = 开 off = 关 @@ -169,6 +150,7 @@ save.wave = 第 {0} 波 save.difficulty = 难度: {0} save.date = 最后保存日期:{0} save.playtime = 游戏时间:{0} +warning = Warning. confirm = 确认 delete = 删除 ok = 好的 @@ -204,7 +186,6 @@ map.nospawn = 这个地图没有核心!请在编辑器中添加一个[ROYAL] map.nospawn.pvp = 这个地图没有敌人的核心!请在编辑器中添加一个[ROYAL]红色[]的核心。 map.invalid = 地图载入错误:地图文件可能已经损坏。 editor.brush = 笔刷 -editor.slope = \\ editor.openin = 在编辑器中打开 editor.oregen = 生成矿石 editor.oregen.info = 生成矿石: @@ -214,16 +195,16 @@ editor.description = 描述: editor.name = 名字: editor.teams = 团队 editor.elevation = 高度 -editor.errorimageload = 载入文件出错:\n[accent]{0} -editor.errorimagesave = 保存文件出错:\n[accent]{0} +editor.errorimageload = 载入文件时出错:\n[accent]{0} +editor.errorimagesave = 保存文件时出错:\n[accent]{0} editor.generate = 生成 editor.resize = 调整 editor.loadmap = 载入地图 editor.savemap = 保存地图 editor.saved = 已保存! editor.save.noname = 你的地图还没有名字!在“地图信息”菜单里设置一个名字。 -editor.save.overwrite = 你的地图覆盖了一个内建的地图!在“地图信息”菜单里重新设置一个。 -editor.import.exists = [scarlet]无法导入:[] 一个叫 '{0}' 的内建地图已经存在。 +editor.save.overwrite = 你的地图覆盖了一个内建的地图!在“地图信息”菜单里重新设置一个新的名字。 +editor.import.exists = [scarlet]无法导入:[] 已经有一个叫 '{0}' 的内建地图存在。 editor.import = 导入…… editor.importmap = 导入地图 editor.importmap.description = 导入一个已经存在的地图 @@ -252,13 +233,33 @@ load = 载入游戏 save = 保存 fps = FPS: {0} tps = TPS: {0} -ping = Ping: {0}ms +ping = 延迟: {0}ms language.restart = 为了使语言设置生效请重启游戏。 settings = 设置 tutorial = 教程 editor = 编辑器 mapeditor = 地图编辑器 donate = 捐赠 +abandon = Abandon +abandon.text = 这个区域和它的所有资源会被敌人没收. +locked = 已被锁定 +complete = [LIGHT_GRAY]完成: +resume = Resume Zone:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]最好: {0} +launch = < 发射 > +launch.title = 发射成功 +launch.next = [LIGHT_GRAY]下一个发射机会在第 {0} 波 +launch.unable = [scarlet]发射失败。[] 敌人. +launch.confirm = 这样做会把您基地里的所有资源发射出去\n您不能再回来这个基地。 +uncover = Uncover +configure = 设定 Loadout +configure.locked = [LIGHT_GRAY]到达第 {0} 波\n才设定 loadout. +zone.unlocked = [LIGHT_GRAY]{0} 已解锁。 +zone.complete = 区域条件达成。 +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = 已被发现的资源: +add = Add... +boss.health = Boss Health connectfail = [crimson]服务器连接失败: [accent]{0} error.unreachable = 服务器无法访问。 error.invalidaddress = 地址无效。 @@ -266,7 +267,20 @@ error.timedout = 连接超时!\n确保服务器设置了端口转发,并且 error.mismatch = 包错误:\n可能是客户端/服务器版本不匹配.\n请确保客户端和服务器都是最新的版本! error.alreadyconnected = 已连接。 error.mapnotfound = 找不到地图文件! -error.any = 未知网络错误. +error.io = 网络 I/O 错误。 +error.any = 未知网络错误。 +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = 语言 settings.reset = 恢复默认 settings.rebind = 重新绑定 @@ -277,7 +291,6 @@ settings.graphics = 图像 settings.cleardata = 清除游戏数据…… settings.clear.confirm = 您确定要清除数据吗?\n这个操作无法撤销! settings.clearall.confirm = [scarlet]警告![]\n这将清除所有数据,包括存档、地图、解锁和键绑定。\n按「是」后,游戏将删除所有数据并自动退出。 -settings.clearsectors = 清除区域 settings.clearunlocks = 清除解锁 settings.clearall = 清除所有 paused = 暂停 @@ -286,12 +299,15 @@ no = 不 info.title = [accent]详情 error.title = [crimson]发生了一个错误 error.crashtitle = 发生了一个错误 +blocks.outputspeed = Drill Speed: {0}/s blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = 方块详情 +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = 能量容量 blocks.powershot = 能量/发射 blocks.targetsair = 攻击空中单位 -blocks.itemspeed = 移动速度 +blocks.itemsmoved = 移动速度 blocks.shootrange = 范围 blocks.size = 尺寸 blocks.liquidcapacity = 液体容量 @@ -312,16 +328,23 @@ blocks.inputitems = 物品输入 blocks.outputitem = 物品输出 blocks.drilltier = 可钻探矿物 blocks.drillspeed = 基础钻探速度 +blocks.maxunits = Max Active Units blocks.liquidoutput = 液体输出 blocks.liquidoutputspeed = 液体输出速度 blocks.liquiduse = 液体使用速度 blocks.coolant = 冷却剂 +blocks.liquid = Liquid blocks.coolantuse = 冷却剂使用速度 blocks.inputliquidfuel = 液体燃料输入 blocks.liquidfueluse = 液体燃料使用速度 -blocks.boostitem = Boost Item -blocks.boostliquid = Boost Liquid +blocks.boostitem = 强化物件 +blocks.boostliquid = 强化液体 blocks.health = 生命值 +blocks.heat = Heat +blocks.power = 电力 +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = 电力见面 blocks.inaccuracy = 误差 blocks.shots = 发射数 blocks.reload = 重新装弹 @@ -329,11 +352,11 @@ blocks.inputfuel = 燃料 blocks.fuelburntime = 燃料燃烧时间 blocks.inputcapacity = 输入容量 blocks.outputcapacity = 输出容量 +blocks.ammo = 子弹 unit.blocks = 方块 unit.powersecond = 能量单位/秒 unit.liquidsecond = 液体单位/秒 unit.itemssecond = 物品/秒 -unit.pixelssecond = 像素/秒 unit.liquidunits = 液体单位 unit.powerunits = 能量单位 unit.degrees = 度 @@ -345,7 +368,8 @@ category.liquids = 液体 category.items = 物品 category.crafting = 制造 category.shooting = 发射 -category.optional = Optional Enhancements +category.optional = 可选的增强物品 +setting.indicators.name = 队友指示器 setting.autotarget.name = 自动发射 setting.fpscap.name = 最高 FPS setting.fpscap.none = 无 @@ -378,12 +402,16 @@ category.multiplayer.name = 多人 command.attack = 攻击 command.retreat = 撤退 command.patrol = 巡逻 +keybind.gridMode.name = 选择块 +keybind.gridModeShift.name = 选择类别 keybind.press = 按一下键…… keybind.press.axis = 按一下轴或键…… +keybind.screenshot.name = 地图截图 keybind.move_x.name = 水平移动 keybind.move_y.name = 垂直移动 keybind.select.name = 选择 -keybind.break.name = 破坏 +keybind.pick.name = 选择方块 +keybind.break_block.name = 破坏方块 keybind.deselect.name = 取消 keybind.shoot.name = 射击 keybind.zoom_hold.name = 保持缩放 @@ -402,29 +430,28 @@ keybind.chat_scroll.name = 聊天记录滚动 keybind.drop_unit.name = 掉落单位 keybind.zoom_minimap.name = 小地图缩放 mode.help.title = 模式说明 -mode.waves.name = 普通 -mode.waves.description = 普通模式,有限的资源和自动生成敌人。 +mode.survival.name = 生存 +mode.survival.description = 正常的游戏模式,有限的资源和自动入射波。 mode.sandbox.name = 沙盒 mode.sandbox.description = 无限的资源,不会自动生成敌人。 mode.freebuild.name = 自由建造 mode.freebuild.description = 有限的资源,不会自动生成敌人。 mode.pvp.name = PvP mode.pvp.description = 和本地玩家对战. +mode.attack.name = 攻击 +mode.attack.description = 没有波数,但是有吹毁敌人基地的任务. content.item.name = 物品 content.liquid.name = 液体 content.unit.name = 部队 -content.recipe.name = 方块 +content.block.name = 块 content.mech.name = 机甲 -item.stone.name = 石头 -item.stone.description = 一种常见的原料。用于分离和提炼成其他材料,或熔化成熔岩。 item.copper.name = 铜 item.copper.description = 一种有用的结构材料。在各种类型的方块中广泛使用。 item.lead.name = 铅 item.lead.description = 一种基本的起始材料。被广泛用于电子设备和液体运输方块。 item.coal.name = 煤 item.coal.description = 一种常见并容易获得的燃料。 -item.dense-alloy.name = 致密合金 -item.dense-alloy.description = 一种由铅和铜制成的坚韧合金。用于高级的运输方块和高级钻头。 +item.graphite.name = Graphite item.titanium.name = 钛 item.titanium.description = 一种罕见的超轻金属,被广泛运用于液体运输、钻头和飞机。 item.thorium.name = 钍 @@ -437,16 +464,20 @@ item.phase-fabric.name = 相织物 item.phase-fabric.description = 一种接近0重量的物质,用于先进的电子技术和自我修复技术。 item.surge-alloy.name = 巨浪合金 item.surge-alloy.description = 一种具有独特电气性能的高级合金。 -item.biomatter.name = 生物质 -item.biomatter.description = 一种有机物;用于转化为油或作为基本燃料。 +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = 沙 item.sand.description = 一种常见的材料,广泛用于冶炼,包括制作合金和助熔剂。 item.blast-compound.name = 爆炸混合物 item.blast-compound.description = 一种用于炸弹和炸药的挥发性混合物。虽然它可以作为燃料燃烧,但不建议这样做。 item.pyratite.name = 硫 item.pyratite.description = 一种燃烧武器中使用的极易燃物质。 +item.metaglass.name = Metaglass +item.metaglass.description = 一种超级强硬的复合玻璃。通常用来传送和收藏液体 +item.scrap.name = Scrap +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = 水 -liquid.lava.name = 岩浆 +liquid.slag.name = Slag liquid.oil.name = 石油 liquid.cryofluid.name = 冷冻液 mech.alpha-mech.name = Alpha @@ -481,11 +512,10 @@ mech.glaive-ship.weapon = 火焰机枪 item.explosiveness = [LIGHT_GRAY]爆炸性:{0} item.flammability = [LIGHT_GRAY]易燃性:{0} item.radioactivity = [LIGHT_GRAY]放射性:{0} -item.fluxiness = [LIGHT_GRAY]助熔性:{0} unit.health = [LIGHT_GRAY]生命值:{0} unit.speed = [LIGHT_GRAY]速度:{0} mech.weapon = [LIGHT_GRAY]武器:{0} -mech.armor = [LIGHT_GRAY]装甲:{0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]物品容量:{0} mech.minespeed = [LIGHT_GRAY]采矿速度:{0} mech.minepower = [LIGHT_GRAY]采矿力量:{0} @@ -493,29 +523,60 @@ mech.ability = [LIGHT_GRAY]能力:{0} liquid.heatcapacity = [LIGHT_GRAY]热容量:{0} liquid.viscosity = [LIGHT_GRAY]粘度:{0} liquid.temperature = [LIGHT_GRAY]温度:{0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](Constructing) block.spawn.name = 敌人出生点 -block.core.name = 核心 -block.metalfloor.name = 金属地板 +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = 深水 block.water.name = 水 -block.lava.name = 岩浆 block.tar.name = Tar -block.blackstone.name = 黑石 block.stone.name = 石头 -block.dirt.name = 泥土 block.sand.name = 沙子 block.ice.name = 冰 block.snow.name = 雪 -block.grass.name = 草 -block.shrub.name = 灌木 -block.rock.name = 岩石 -block.blackrock.name = 黑岩 -block.icerock.name = 冰岩 +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = 铜墙 block.copper-wall-large.name = 大型铜墙 -block.dense-alloy-wall.name = 致密合金墙 -block.dense-alloy-wall-large.name = 大型致密合金墙 +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = 相织布墙 block.phase-wall-large.name = 大型相织布墙 block.thorium-wall.name = 钍墙 @@ -523,7 +584,6 @@ block.thorium-wall-large.name = 大型钍墙 block.door.name = 门 block.door-large.name = 大门 block.duo.name = 双管炮 -block.scorch.name = 灼烧炮 block.hail.name = 冰雹炮 block.lancer.name = 蓝瑟炮 block.conveyor.name = 传送带 @@ -535,30 +595,29 @@ block.sorter.name = 分类器 block.sorter.description = 对物品进行分类。如果物品与所选种类,则允许其通过。否则,物品将从左边和右边输出。 block.overflow-gate.name = 溢流门 block.overflow-gate.description = 分离器和路由器的组合,如果前面被挡住,则向从左和右输出。 -block.smelter.name = 冶炼厂 -block.arc-smelter.name = 电弧冶炼厂 block.silicon-smelter.name = 硅冶炼厂 block.phase-weaver.name = 相织布编织器 block.pulverizer.name = 粉碎机 block.cryofluidmixer.name = 冷冻液混合器 block.melter.name = 熔炉 block.incinerator.name = 焚化炉 -block.biomattercompressor.name = 生物质压缩机 +block.spore-press.name = Spore Press block.separator.name = 分离机 -block.centrifuge.name = 离心机 block.power-node.name = 能量节点 block.power-node-large.name = 大型能量节点 +block.surge-tower.name = Surge Tower block.battery.name = 电池 block.battery-large.name = 大型电池 block.combustion-generator.name = 燃烧发电机 block.turbine-generator.name = 涡轮发电机 +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = 机械钻头 block.pneumatic-drill.name = 气动钻头 block.laser-drill.name = 激光钻头 block.water-extractor.name = 抽水机 block.cultivator.name = 耕种机 -block.alpha-mech-pad.name = Alpha 机甲平台 -block.dart-ship-pad.name = Dart 机甲平台 +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = Delta 机甲平台 block.javelin-ship-pad.name = 标枪 机甲平台 block.trident-ship-pad.name = 三叉戟 机甲平台 @@ -583,7 +642,6 @@ block.bridge-conveyor.name = 传送带桥 block.plastanium-compressor.name = 塑钢压缩机 block.pyratite-mixer.name = 硫混合器 block.blast-mixer.name = 爆炸混合器 -block.solidifer.name = 凝固器 block.solar-panel.name = 太阳能电池 block.solar-panel-large.name = 大型太阳能电池 block.oil-extractor.name = 石油钻井 @@ -604,7 +662,6 @@ block.liquid-junction.name = 液体连接点 block.bridge-conduit.name = 导管桥 block.rotary-pump.name = 回旋泵 block.thorium-reactor.name = 钍反应堆 -block.command-center.name = 指令中心 block.mass-driver.name = 质量驱动器 block.blast-drill.name = 爆破钻头 block.thermal-pump.name = 热能泵 @@ -623,20 +680,21 @@ block.rtg-generator.name = RTG 发电机 block.spectre.name = 幽灵 block.meltdown.name = 熔毁 block.container.name = 容器 -block.core.description = 游戏中最重要的建筑。 +block.launch-pad.name = Launch Pad +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = 蓝 team.red.name = 红 team.orange.name = 橙 team.none.name = 灰 team.green.name = 绿 team.purple.name = 紫 -unit.alpha-drone.name = Alpha 无人机 unit.spirit.name = 轻型无人机 unit.spirit.description = 初始无人机。默认情况下在内核中生成。自动开采矿石,收集物品和修理块。 unit.phantom.name = 鬼怪无人机 unit.phantom.description = 一种先进的无人机单位。自动开采矿石,收集物品和修理块。比初始无人机有效得多。 unit.dagger.name = 尖刀 unit.dagger.description = 基础的地面单位,在蜂群中很有用。 +unit.crawler.name = Crawler unit.titan.name = 泰坦 unit.titan.description = 高级的有武装地面单位,使用电石作为弹药.攻击地面单位和空中单位. unit.ghoul.name = 食尸鬼轰炸机 @@ -646,7 +704,11 @@ unit.wraith.description = 一种快速,打了就跑的截击机。 unit.fortress.name = 堡垒 unit.fortress.description = 一种重炮地面部队。 unit.revenant.name = 亡魂 -unit.revenant.description = 一种重型激光平台。 +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = 你的任务是消灭[LIGHT_GRAY] 敌人 [].\n\n首先开始[accent] 采集铜矿 []。点击核心附近的铜矿开始。 tutorial.drill = 手动采矿效率低.\n[accent] 钻头 []可以自动采矿.\n放一个在铜矿上吧. tutorial.conveyor = [accent]传送带[] 可以把物资传送到核心.\n请造一个传送线,从钻头到核心. @@ -670,8 +732,6 @@ tutorial.dagger = 链接能源节点到工厂.\n一旦需求满足, 将会制作 tutorial.battle = [LIGHT_GRAY] 敌人[] 的核心已经暴露。\n用你的尖刀机甲摧毁它。 block.copper-wall.description = 廉价的防守区块。\n用于保护前几波中的核心和炮塔。 block.copper-wall-large.description = 廉价的防御块。\n用于保护前几个波浪中的核心和炮塔。\n跨越多个块。 -block.dense-alloy-wall.description = 标准的防守区块。\n可以较好的防御敌人。 -block.dense-alloy-wall-large.description = 标准的防守区块。\n可以较好的防御敌人。\n跨越多个块。 block.thorium-wall.description = 强大的防守区块。\n很好的防御敌人。 block.thorium-wall-large.description = 强大的防守区块。\n很好地防御敌人。\n跨越多个块。 block.phase-wall.description = 没有钍墙那样坚固,但是它可以使不太强的子弹发生偏转。 @@ -701,8 +761,6 @@ block.titanium-conveyor.description = 高级传送带。能比初级传送带更 block.phase-conveyor.description = 高级传送带。使用电力将物品传送到距离几个块的相位传送带上。 block.junction.description = 为两条交叉传送带的桥梁。适用于两种不同传送带将不同材料运送到不同位置的情况。 block.mass-driver.description = 终极传送带。收集几件物品,然后将它们射向长距离外的另一个批量传送带。 -block.smelter.description = 烧煤,用于冶炼铜和铅成致密合金。 -block.arc-smelter.description = 用外部电源熔炼铜和铅成致密合金。 block.silicon-smelter.description = 用高纯度的焦炭来加工沙子以生产硅。 block.plastanium-compressor.description = 用油和钛生产塑钢。 block.phase-weaver.description = 用放射性钍和大量沙子生产相织物。 @@ -711,12 +769,10 @@ block.pulverizer.description = 将石头压成沙子。当缺少天然沙子时 block.pyratite-mixer.description = 用煤,铅和沙子混合成高度易燃的硫。 block.blast-mixer.description = 用油将硫转化为不易燃但更具爆炸性的爆炸化合物。 block.cryofluidmixer.description = 水和钛结合到低温流体中,冷却效率更高。 -block.solidifer.description = 快速冷却熔岩为石头。 block.melter.description = 石头加热到很高的温度以获得熔岩。 block.incinerator.description = 用于除掉任何多余的物品或液体。 -block.biomattercompressor.description = 压缩生物质以获取油。 +block.spore-press.description = Compresses spore pods into oil. block.separator.description = 将石头暴露在水压下,以获得石头中含有的各种矿物质。 -block.centrifuge.description = 比分离器更有效,但构建起来也更昂贵并且需要动力。 block.power-node.description = 连接节点传输电源。最多可连接四个电源,接收器或节点。节点将从任何相邻块接收电力或向其供电。 block.power-node-large.description = 传输径大于电源节点,最多可连接六个电源,接收器或节点。 block.battery.description = 储存电力,当储存有能量时,可在电力短缺时提供电力。 @@ -738,7 +794,6 @@ block.blast-drill.description = 终极钻头,需要大量电力。 block.water-extractor.description = 从地下提取水。当附近没有湖泊时使用它。 block.cultivator.description = 用水培育土壤以获得生物物质。 block.oil-extractor.description = 使用大量的电力从沙子中提取石油。当附近没有直接的石油来源时使用它。 -block.dart-ship-pad.description = 离开你当前的装置,换成基本的战斗机。\n站在上面时双击切换。 block.trident-ship-pad.description = 离开你当前的装置,换成一个装甲合理的重型轰炸机。\n站在上面时双击切换。 block.javelin-ship-pad.description = 离开你当前的装置,换上一个强大而快速的截击机,用闪电武器。\n站在上面时双击切换。 block.glaive-ship-pad.description = 离开现有的装置,换成装甲良好的大型武装直升机。\n站在上面时双击切换。 @@ -754,7 +809,6 @@ block.titan-factory.description = 生产先进的装甲地面单位。 block.fortress-factory.description = 生产重型火炮地面部队。 block.revenant-factory.description = 生产重型激光地面单元。 block.repair-point.description = 连续治疗附近最近的受损单位。 -block.command-center.description = 允许更改友方AI行为。目前支持攻击,撤退和巡逻命令。 block.conduit.description = 基本液体传输块。像输送机一样工作,但用于液体。最适用于提取器,泵或其他导管。 block.pulse-conduit.description = 高级液体传输块。比标准导管更快地输送液体并储存更多液体。 block.phase-conduit.description = 高级液体传输块。使用电力将液体传送到多个块上的连接相管道。 @@ -768,13 +822,11 @@ block.thermal-pump.description = 终级水泵。速度是机械泵的三倍。 block.router.description = 从一个方向接受物品,并将它们平均输出到最多3个其他方向。用于将材料从一个源分割为多个目标。 block.distributor.description = 一个高级路由器,可以将物品分成最多7个方向。 block.bridge-conveyor.description = 高级项目传输块。允许在跨越任何地形或建筑物上运输物品,最多跨越3个块。 -block.alpha-mech-pad.description = 当给予足够的电力时,将你的装置重建为[accent] Alpha []机甲。 block.item-source.description = 无限输出物品。仅限沙箱。 block.liquid-source.description = 无限输出液体。仅限沙箱。 block.item-void.description = 在不使用电源的情况下销毁任何进入它的物品。仅限沙箱。 block.power-source.description = 无限输出功率。仅限沙箱。 block.power-void.description = 消耗输入的所有功率。仅限沙箱。 liquid.water.description = 通常用于冷却和废物处理。 -liquid.lava.description = 可以转换成[LIGHT_GRAY] 石头 [],用于发电或用作某些炮塔的弹药。 liquid.oil.description = 可以燃烧,爆炸或用作冷却液。 liquid.cryofluid.description = 用于降温的最有效液体。 diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index 16c6ee9909..8f96dc5461 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -11,79 +11,57 @@ link.google-play.description = Google Play 商店頁面 link.wiki.description = 官方 Mindustry 維基 linkfail = 無法打開連結!\n我們已將該網址複製到您的剪貼簿。 screenshot = 截圖保存到{0} -gameover = 核心已被摧毀。 +gameover = 遊戲結束 gameover.pvp = [accent]{0}[]隊獲勝! -sector.gameover = 這個區域失守了,重新部署? -sector.retry = 重試 highscore = [accent]新的高分紀錄! -wave.lasted = 你維持到第[accent]{0}[]波。 -level.highscore = 最高分:[accent]{0} -level.delete.title = 確認刪除 +stat.wave = 打敗的波次:[accent]{0} +stat.enemiesDestroyed = 摧毀的敵人:[accent]{0} +stat.built = 建設的建築:[accent]{0} +stat.destroyed = 摧毀的建築:[accent]{0} +stat.deconstructed = 移除的建築:[accent]{0} +stat.delivered = 發射的資源: +stat.rank = Final Rank: [accent]{0} map.delete = 確認要刪除「[accent]{0}[]」地圖嗎? +level.highscore = 最高分:[accent]{0} level.select = 選擇關卡 level.mode = 遊戲模式: -construction.desktop = 電腦控制已更改。\n要取消選擇或停止建設,[accent]按空格鍵[]。 +construction.desktop = 要取消選擇或停止建設,[accent]按空格鍵[]。 construction.title = 方塊建設指南 construction = 你選擇了[accent]方塊建設模式[]。\n\n要放置方塊,點擊你的船附近的有效位置。\n選擇了方塊後,點擊複選框就會開始建設。\n\n- 點擊方塊以從選擇區[accent]移除方塊[]。\n- 按住並拖動以[accent]直線放置方塊[]。\n- 點擊左下角的「X」以[accent]取消建設或取消選擇[]。 deconstruction.title = 方塊移除指南 deconstruction = 你選擇了[accent]方塊移除模式[]。\n\n要移除方塊,點擊你的船附近的方塊。\n選擇了方塊後,點擊複選框就會開始移除。\n\n- 點擊方塊以從選擇區[accent]移除方塊[]。\n- 按住一個空點向任何方向拖動以[accent]移除選中區域的方塊[]。\n- 點擊左下角的「X」以[accent]取消移除或取消選擇[]。 showagain = 下次不再顯示 coreattack = 〈核心正在受到攻擊!〉 -unlocks = 已解鎖 +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database savegame = 儲存遊戲 loadgame = 載入遊戲 joingame = 多人連線 addplayers = 增加/移除玩家 customgame = 自訂遊戲 -sectors = 區域 -sector = 區域︰[LIGHT_GRAY]{0} -sector.time = 時間︰[LIGHT_GRAY]{0} -sector.deploy = 部署 -sector.abandon = 放棄 -sector.abandon.confirm = 確認要放棄這區域所有進度嗎?\n此操作不可撤回! -sector.resume = 繼續 -sector.locked = [scarlet][[Incomplete] -sector.unexplored = [accent][[Unexplored] -missions = 任務︰[LIGHT_GRAY]{0} -mission = 任務︰[LIGHT_GRAY]{0} -mission.main = 主要任務︰[LIGHT_GRAY]{0} -mission.info = 任務資訊 -mission.complete = 任務完成! -mission.complete.body = 區域{0},{1}已被佔領。 -mission.wave = 存活[accent]{0}/{1}[]波\n下一波於{2}開始 -mission.wave.enemies = 存活[accent]{0}/{1}[]波\n{2}個敵人 -mission.wave.enemy = 存活[accent]{0}/{1}[]波\n{2}個敵人 -mission.wave.menu = 存活[accent]{0}[]波 -mission.battle = 摧毀敵方基地。 -mission.resource.menu = 獲取{0}x{1} -mission.resource = 獲取{0}︰\n[accent]{1}/{2}[] -mission.block = 建造{0} -mission.unit = 生產{0}機組 -mission.command = 發送{0}指令至機組 -mission.linknode = 鏈接能量節點 -mission.display = [accent]任務︰\n[LIGHT_GRAY]{0} -mission.mech = 轉換至[accent]{0}[]機甲 -mission.create = 製造[accent]{0}[] +newgame = New Game none = <沒有> close = 關閉 quit = 退出 maps = 地圖 continue = 繼續 -nextmission = 下一個任務 maps.none = [LIGHT_GRAY]找不到地圖! about.button = 關於 name = 名稱: noname = 先選擇一個[accent]玩家名稱[]。 filename = 檔案名稱︰ unlocked = 新方塊已解鎖! -unlocked.plural = 新方塊已解鎖! +completed = [accent]Completed +techtree = 科技樹 +research.list = [LIGHT_GRAY]研究︰ +research = 研究 +researched = [LIGHT_GRAY]{0}研究完成。 players = {0}個線上玩家 players.single = {0}個線上玩家 server.closing = [accent]正在關閉伺服器…… server.kicked.kick = 您已被踢出伺服器! server.kicked.serverClose = 伺服器已關閉。 -server.kicked.sectorComplete = 區域已完成。 -server.kicked.sectorComplete.text = 任務已完成。\n服務器將於下一個區域繼續。 server.kicked.clientOutdated = 客戶端版本過舊!請更新遊戲! server.kicked.serverOutdated = 伺服器版本過舊!請聯絡伺服主更新伺服器! server.kicked.banned = 您已經從這個伺服器被封禁。 @@ -92,6 +70,7 @@ server.kicked.nameInUse = 伺服器中已經\n有人有相同的名稱了。 server.kicked.nameEmpty = 你的名稱必須至少包含一個字母或數字。 server.kicked.idInUse = 你已經在伺服器中!不允許用兩個賬號。 server.kicked.customClient = 這個伺服器不支持自訂客戶端,請下載官方版本。 +server.kicked.gameover = 遊戲結束! host.info = 目前伺服器監聽於連接埠[scarlet]6567[]。\n所有跟您在同一個[LIGHT_GRAY]網路或區域網路[]環境的玩家應該能在他們的伺服器清單中找到您的伺服器。\n\n如果您希望網際網路上的玩家透過IP 位址連線到您的伺服器,您必須設定[accent]連接埠轉發[]。\n\n[LIGHT_GRAY]注意:如果區域網路內有玩家無法連線至您的伺服器,請務必確認您已於防火牆設定中開放Mindustry存取您的區域網路。 join.info = 您可以在此輸入欲連線的[accent]伺服器的IP位址[],或尋找[accent]區域網路[]內的伺服器。目前支援區域網路與網際網路連線。\n\n[LIGHT_GRAY]注意:這裡沒有網際網路伺服器清單,如果您想透過IP位址連線到某人的伺服器,您必須向他們詢問IP位址。 hostserver = 建立伺服器 @@ -162,7 +141,6 @@ save.rename.text = 新名稱: selectslot = 選取一個存檔。 slot = [accent]存檔{0} save.corrupted = [accent]此存檔無效或已損毀!\n如果你剛剛升級了遊戲,那麼這可能是因為存檔格式改變了而[scarlet]不是[]錯誤。 -sector.corrupted = [accent]找到此區域的存檔,但是加載失敗。\n已經創建了一個新的存檔。 empty = <空白> on = 開啟 off = 關閉 @@ -172,6 +150,7 @@ save.wave = 波次:{0} save.difficulty = 難度:{0} save.date = 最後存檔時間:{0} save.playtime = 遊玩時間: {0} +warning = Warning. confirm = 確認 delete = 刪除 ok = 確定 @@ -207,7 +186,6 @@ map.nospawn = 這個地圖沒有核心!請在編輯器中添加一個[ROYAL] map.nospawn.pvp = 這個地圖沒有核心讓敵人重生!請在編輯器中添加一個[SCARLET]紅色[]的核心。 map.invalid = 地圖載入錯誤:地圖可能已經損壞。 editor.brush = 粉刷 -editor.slope = \\ editor.openin = 在編輯器中開啟 editor.oregen = 礦石產生 editor.oregen.info = 礦石產生: @@ -262,7 +240,26 @@ tutorial = 教學 editor = 地圖編輯器 mapeditor = 地圖編輯器 donate = 贊助 - +abandon = 放棄 +abandon.text = 此區域及其所有資源將會丟失給敵人。 +locked = 鎖定 +complete = [LIGHT_GRAY]完成: +resume = 繼續區域:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]高分:{0} +launch = 發射 +launch.title = 發射成功 +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +configure = Configure Loadout +configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. +zone.unlocked = [LIGHT_GRAY]{0}已解鎖。 +zone.complete = Zone conditions met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.resources = Resources Detected: +add = Add... +boss.health = Boss Health connectfail = [crimson]無法連線到伺服器:[accent]{0} error.unreachable = 無法到達伺服器。 error.invalidaddress = 無效地址。 @@ -270,8 +267,20 @@ error.timedout = 超時連接!\n確保伺服器設置了連接埠轉發,並 error.mismatch = 包裹錯誤:\n客戶端/伺服器版本可能不匹配。 n確保客戶端和伺服器有最新版本的Mindustry! error.alreadyconnected = 已連接。 error.mapnotfound = 找不到地圖! +error.io = 網絡輸入輸出錯誤。 error.any = 未知網絡錯誤。 - +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.crags.name = Crags +zone.stainedMountains.name = Stained Mountains +zone.impact0079.name = Impact 0079 +zone.desolateRift.name = Desolate Rift +zone.arcticDesert.name = Arctic Desert +zone.dryWastes.name = Dry Wastes +zone.nuclearComplex.name = Nuclear Production Complex +zone.moltenFault.name = Molten Fault settings.language = 語言 settings.reset = 重設為預設設定 settings.rebind = 重新綁定 @@ -282,21 +291,23 @@ settings.graphics = 圖形 settings.cleardata = 清除遊戲數據…… settings.clear.confirm = 您確定要清除數據嗎?\n此操作無法撤回! settings.clearall.confirm = [scarlet]警告![]\n這將清除所有數據,包括存檔、地圖、解鎖和熱鍵綁定。\n按「是」後,遊戲將刪除所有數據並自動退出。 -settings.clearsectors = 清除區域 settings.clearunlocks = 清除已解鎖 settings.clearall = 清除所有 -paused = 已暫停 +paused = [accent]〈已暫停〉 yes = 是 no = 否 info.title = [accent]資訊 error.title = [crimson]發生錯誤 error.crashtitle = 發生錯誤 -blocks.unknown = [LIGHT_GRAY]??? +blocks.outputspeed = Drill Speed: {0}/s +blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = 方塊資訊 +blocks.powerbalance = Power: {0} +blocks.poweroutput = Power Output: {0} blocks.powercapacity = 蓄電量 blocks.powershot = 能量/射擊 blocks.targetsair = 攻擊空中目標 -blocks.itemspeed = 移動速度 +blocks.itemsmoved = Move Speed blocks.shootrange = 範圍 blocks.size = 尺寸 blocks.liquidcapacity = 液體容量 @@ -317,16 +328,23 @@ blocks.inputitems = 輸入物品 blocks.outputitem = 輸出物品 blocks.drilltier = 可鑽取礦物 blocks.drillspeed = 基本鑽取速度 +blocks.maxunits = Max Active Units blocks.liquidoutput = 輸出液體 blocks.liquidoutputspeed = 輸出液體速度 blocks.liquiduse = 使用液體速度 blocks.coolant = 冷卻劑 +blocks.liquid = Liquid blocks.coolantuse = 使用冷卻劑 blocks.inputliquidfuel = 輸入液體燃料 blocks.liquidfueluse = 使用液體燃料速度 blocks.boostitem = 強化物品 blocks.boostliquid = 強化液體 blocks.health = 耐久度 +blocks.heat = Heat +blocks.power = Power +blocks.progress = Build Progress +blocks.spawned = Units: {0}/{1} +blocks.power.satisfaction = Power Satisfaction blocks.inaccuracy = 誤差 blocks.shots = 射擊數 blocks.reload = 重裝彈藥 @@ -334,11 +352,11 @@ blocks.inputfuel = 燃料 blocks.fuelburntime = 燃燒燃料時間 blocks.inputcapacity = 輸入容量 blocks.outputcapacity = 輸出容量 +blocks.ammo = Ammo unit.blocks = 方塊 unit.powersecond = 能量單位/秒 unit.liquidsecond = 液體單位/秒 unit.itemssecond = 物品/秒 -unit.pixelssecond = 像素/秒 unit.liquidunits = 液體單位 unit.powerunits = 能量單位 unit.degrees = 度 @@ -392,7 +410,8 @@ keybind.screenshot.name = 地圖截圖 keybind.move_x.name = 水平移動 keybind.move_y.name = 垂直移動 keybind.select.name = 選取 -keybind.break.name = 拆除 +keybind.pick.name = Pick Block +keybind.break_block.name = Break Block keybind.deselect.name = 取消選取 keybind.shoot.name = 射擊 keybind.zoom_hold.name = 按住縮放 @@ -411,8 +430,8 @@ keybind.chat_scroll.name = 聊天記錄滾動 keybind.drop_unit.name = 放下單位 keybind.zoom_minimap.name = 縮放小地圖 mode.help.title = 模式說明 -mode.waves.name = 一般 -mode.waves.description = 一般模式,有限的資源與自動來襲的波次。 +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. mode.sandbox.name = 沙盒 mode.sandbox.description = 無限的資源,與不倒數計時的波次。 mode.freebuild.name = 自由建造 @@ -420,22 +439,19 @@ mode.freebuild.description = 有限的資源,與不倒數計時的波次。 mode.pvp.name = 對戰 mode.pvp.description = 和其他玩家鬥爭。 mode.attack.name = 攻擊 -mode.attack.description = 沒有波次,目標是摧毀敵人的基地。 +mode.attack.description = No waves, with the goal to destroy the enemy base. content.item.name = 物品 content.liquid.name = 液體 content.unit.name = 機組 -content.recipe.name = 方塊 +content.block.name = 方塊 content.mech.name = 機甲 -item.stone.name = 石材 -item.stone.description = 一種常見的原料。用於分離和提煉成其他材料,或熔化成熔岩。 item.copper.name = 銅 item.copper.description = 一種有用的結構材料。在各種類型的方塊中廣泛使用。 item.lead.name = 鉛 item.lead.description = 一種基本的起始材料。被廣泛用於電子設備和運輸液體方塊。 item.coal.name = 煤 item.coal.description = 一種常見並容易獲得的燃料。 -item.dense-alloy.name = 稠密合金 -item.dense-alloy.description = 一種由鉛和銅製成的堅韌合金。用於高級的運輸方塊和高級鑽頭。 +item.graphite.name = 石墨 item.titanium.name = 鈦 item.titanium.description = 一種罕見的超輕金屬,被廣泛運用於運輸液體、鑽頭和飛機。 item.thorium.name = 釷 @@ -448,16 +464,20 @@ item.phase-fabric.name = 相織布 item.phase-fabric.description = 一種近乎無重量的物質,用於先進的電子設備和自修復技術。 item.surge-alloy.name = 波動合金 item.surge-alloy.description = 一種具有獨特電子特性的高級合金。 -item.biomatter.name = 生物物質 -item.biomatter.description = 一叢有機糊;用於轉化為油或作為基本燃料。 +item.spore-pod.name = Spore Pod +item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = 沙 item.sand.description = 一種常見的材料,廣泛用於冶煉,包括製作合金和助熔劑。 item.blast-compound.name = 爆炸混合物 item.blast-compound.description = 一種用於炸彈和炸藥的揮發性混合物。雖然它可以作為燃料燃燒,但不建議這樣做。 item.pyratite.name = 硫 item.pyratite.description = 一種在燃燒武器中使用的極易燃物質。 +item.metaglass.name = 金屬玻璃 +item.metaglass.description = 一種超級強硬玻璃混合物。廣泛用於液體分配和存儲。 +item.scrap.name = 廢料 +item.scrap.description = 舊結構和單位的遺留剩餘物。含有痕量的許多不同的金屬。 liquid.water.name = 水 -liquid.lava.name = 岩漿 +liquid.slag.name = Slag liquid.oil.name = 原油 liquid.cryofluid.name = 冷凍液 mech.alpha-mech.name = 阿爾法 @@ -492,11 +512,10 @@ mech.glaive-ship.weapon = 火焰機關槍 item.explosiveness = [LIGHT_GRAY]爆炸性:{0} item.flammability = [LIGHT_GRAY]易燃性:{0} item.radioactivity = [LIGHT_GRAY]放射性:{0} -item.fluxiness = [LIGHT_GRAY]助熔性:{0} unit.health = [LIGHT_GRAY]耐久度:{0} unit.speed = [LIGHT_GRAY]速度:{0} mech.weapon = [LIGHT_GRAY]武器:{0} -mech.armor = [LIGHT_GRAY]裝甲:{0} +mech.health = [LIGHT_GRAY]Health: {0} mech.itemcapacity = [LIGHT_GRAY]物品容量:{0} mech.minespeed = [LIGHT_GRAY]採礦速度:{0} mech.minepower = [LIGHT_GRAY]採礦力度:{0} @@ -504,29 +523,60 @@ mech.ability = [LIGHT_GRAY]能力:{0} liquid.heatcapacity = [LIGHT_GRAY]熱容量:{0} liquid.viscosity = [LIGHT_GRAY]粘性:{0} liquid.temperature = [LIGHT_GRAY]温度:{0} +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. +block.graphite-press.name = Graphite Press +block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](Constructing) block.spawn.name = 敵人生成 -block.core.name = 核心 -block.metalfloor.name = 金屬地板 +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.deepwater.name = 深水 block.water.name = 水 -block.lava.name = 岩浆 block.tar.name = 焦油 -block.blackstone.name = 黑石頭 block.stone.name = 石頭 -block.dirt.name = 泥土 block.sand.name = 沙 block.ice.name = 冰 block.snow.name = 雪 -block.grass.name = 草 -block.shrub.name = 灌木 -block.rock.name = 岩石 -block.blackrock.name = 黑岩石 -block.icerock.name = 冰岩石 +block.craters.name = Craters +block.sand-water.name = Sand water +block.char.name = Char +block.holostone.name = Holo stone +block.ice-snow.name = Ice Snow +block.rocks.name = Rocks +block.icerocks.name = Ice rocks +block.snowrocks.name = Snow Rocks +block.dunerocks.name = Dune Rocks +block.pine.name = Pine +block.white-tree-dead.name = White Tree Dead +block.white-tree.name = White Tree +block.spore-cluster.name = Spore Cluster +block.stained-rocks.name = Stained Rocks +block.stained-stone.name = Stained Stone +block.stained-rocks-red.name = Stained Rocks Red +block.stained-stone-red.name = Stained Stone Red +block.stained-rocks-yellow.name = Stained Rocks Yellow +block.stained-stone-yellow.name = Stained Stone Yellow +block.stained-boulder.name = Stained Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-2.name = Metal Floor 2 +block.metal-floor-3.name = Metal Floor 3 +block.metal-floor-5.name = Metal Floor 5 +block.metal-floor-damaged.name = Metal Floor Damaged +block.ignarock.name = Igna Rock +block.hotrock.name = Hot Rock +block.magmarock.name = Magma Rock +block.cliffs.name = Cliffs block.copper-wall.name = 銅牆 block.copper-wall-large.name = 大型銅牆 -block.dense-alloy-wall.name = 稠密合金牆 -block.dense-alloy-wall-large.name = 大型稠密合金牆 +block.titanium-wall.name = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = 相織布牆 block.phase-wall-large.name = 大型相織布牆 block.thorium-wall.name = 釷牆 @@ -534,7 +584,6 @@ block.thorium-wall-large.name = 大型釷牆 block.door.name = 門 block.door-large.name = 大門 block.duo.name = 雙炮 -block.scorch.name = 灼燒炮 block.hail.name = 冰雹炮 block.lancer.name = 藍瑟炮 block.conveyor.name = 輸送帶 @@ -546,30 +595,29 @@ block.sorter.name = 分類器 block.sorter.description = 對物品進行分類。如果物品與所選種類匹配,則允許其通過。否則,物品將從左邊和右邊輸出。 block.overflow-gate.name = 溢流器 block.overflow-gate.description = 分離器和分配器的組合。如果前面被擋住,則向從左邊和右邊輸出物品。 -block.smelter.name = 冶煉廠 -block.arc-smelter.name = 電弧冶煉廠 block.silicon-smelter.name = 煉矽廠 block.phase-weaver.name = 相織布編織器 block.pulverizer.name = 粉碎機 block.cryofluidmixer.name = 冷凍液混合器 block.melter.name = 熔爐 block.incinerator.name = 焚化爐 -block.biomattercompressor.name = 生物物質壓縮機 +block.spore-press.name = Spore Press block.separator.name = 分離機 -block.centrifuge.name = 離心機 block.power-node.name = 能量節點 block.power-node-large.name = 大型能量節點 +block.surge-tower.name = Surge Tower block.battery.name = 電池 block.battery-large.name = 大型電池 block.combustion-generator.name = 燃燒發電機 block.turbine-generator.name = 渦輪發電機 +block.differential-generator.name = Differential Generator +block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = 機械鑽頭 block.pneumatic-drill.name = 氣動鑽頭 block.laser-drill.name = 激光鑽頭 block.water-extractor.name = 水提取器 block.cultivator.name = 耕種機 -block.alpha-mech-pad.name = 阿爾法機甲墊 -block.dart-ship-pad.name = 鏢船墊 +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad block.delta-mech-pad.name = 德爾塔機甲墊 block.javelin-ship-pad.name = 標槍機甲墊 block.trident-ship-pad.name = 三叉船墊 @@ -594,7 +642,6 @@ block.bridge-conveyor.name = 傳送帶橋 block.plastanium-compressor.name = 塑料壓縮機 block.pyratite-mixer.name = 硫混合器 block.blast-mixer.name = 爆炸混合器 -block.solidifer.name = 凝固器 block.solar-panel.name = 太陽能板 block.solar-panel-large.name = 大型太陽能板 block.oil-extractor.name = 石油鑽井 @@ -615,7 +662,6 @@ block.liquid-junction.name = 液體連接點 block.bridge-conduit.name = 管線橋 block.rotary-pump.name = 迴旋泵 block.thorium-reactor.name = 釷反應堆 -block.command-center.name = 指令中心 block.mass-driver.name = 質量驅動器 block.blast-drill.name = 爆破鑽頭 block.thermal-pump.name = 熱能泵 @@ -634,20 +680,21 @@ block.rtg-generator.name = 放射性同位素熱發電機 block.spectre.name = 幽靈炮 block.meltdown.name = 熔毀炮 block.container.name = 容器 -block.core.description = 遊戲中最重要的建築。 +block.launch-pad.name = 發射台 +block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. team.blue.name = 藍 team.red.name = 紅 team.orange.name = 橙 team.none.name = 灰 team.green.name = 綠 team.purple.name = 紫 -unit.alpha-drone.name = 阿爾法無人機 unit.spirit.name = 輕型無人機 unit.spirit.description = 起始的無人機。默認在核心產生。自動挖掘礦石、收集物品和修理方塊。 unit.phantom.name = 幻影無人機 unit.phantom.description = 一種高級的無人機。自動挖掘礦石、收集物品和修理方塊。比輕型無人機明顯更有效。 unit.dagger.name = 匕首 unit.dagger.description = 一種基本的地面單位。最好一群地使用。 +unit.crawler.name = Crawler unit.titan.name = 泰坦 unit.titan.description = 一種高級的具有裝甲的地面單位。使用碳化物作為彈藥。攻擊地面單位和空中單位。 unit.ghoul.name = 食屍鬼轟炸機 @@ -657,7 +704,11 @@ unit.wraith.description = 一種快速、打了就跑的攔截機。 unit.fortress.name = 堡壘 unit.fortress.description = 一種具有重型大砲的地面單位。 unit.revenant.name = 亡魂 -unit.revenant.description = 一種重型的激光平台。 +unit.eruptor.name = Eruptor +unit.chaos-array.name = Chaos Array +unit.eradicator.name = Eradicator +unit.lich.name = Lich +unit.reaper.name = Reaper tutorial.begin = 你的任務是毀滅[LIGHT_GRAY]敵人[]。\n\n首先[accent]挖掘銅礦[]。點擊核心附近的銅脈以開始。 tutorial.drill = 手動挖掘礦石是低效率的。\n[accent]鑽頭[]能夠自動挖掘礦石。\n在銅脈上放置一個鑽頭。 tutorial.conveyor = [accent]輸送帶[]能夠將物品運輸到核心。\n製作一條從鑽頭開始到核心的輸送帶。 @@ -681,8 +732,6 @@ tutorial.dagger = 連接能量節點至工廠。\n一旦要求滿足,將製作 tutorial.battle = [LIGHT_GRAY]敵人[]透露了他們的核心。\n用你的單位和匕首機甲以摧毀它。 block.copper-wall.description = 一種便宜的防衛方塊。\n用於前幾波防衛核心和砲塔。 block.copper-wall-large.description = 一種便宜的防衛方塊。\n用於前幾波防衛核心和砲塔\n佔據多個方塊。 -block.dense-alloy-wall.description = 一種標準的防衛方塊。\n充分地防衛敵人。 -block.dense-alloy-wall-large.description = 一種標準的防衛方塊。\n充分地防衛敵人。\n佔據多個方塊。 block.thorium-wall.description = 一種堅強的防衛方塊。\n良好地防衛敵人。 block.thorium-wall-large.description = 一種堅強的防衛方塊。\n良好地防衛敵人。\n佔據多個方塊。 block.phase-wall.description = 沒有釷牆那麼強但會使不太強的子彈偏離。 @@ -712,8 +761,6 @@ block.titanium-conveyor.description = 高級物品傳輸方塊。比標準輸送 block.phase-conveyor.description = 高級物品傳輸方塊。使用能量將物品傳送到幾個方塊外連接的相織輸送帶。 block.junction.description = 作為兩個交叉輸送帶的橋樑。適用於兩條不同輸送帶將不同物品運送到不同位置的情況。 block.mass-driver.description = 終極物品運輸方塊。收集幾件物品,然後將它們射向另一個長距離的質量驅動器。 -block.smelter.description = 燒煤以冶煉銅和鉛成稠密合金。 -block.arc-smelter.description = 使用外部能量以冶煉銅和鉛成稠密合金。 block.silicon-smelter.description = 使用高純度焦炭還原沙子以生產矽。 block.plastanium-compressor.description = 使用油和鈦以生產塑料。 block.phase-weaver.description = 使用放射性的釷和大量的沙子以生產相織布。 @@ -722,12 +769,10 @@ block.pulverizer.description = 將石頭壓成沙子。當缺少天然沙子時 block.pyratite-mixer.description = 混合煤、鉛和沙子成為易燃的硫。 block.blast-mixer.description = 使用油將硫變成比較不易燃但更具爆炸性的爆炸混合器。 block.cryofluidmixer.description = 合水和鈦成冷卻效率更高的冷凍液。 -block.solidifer.description = 快速冷卻熔岩至石頭。 block.melter.description = 將石頭加熱到很高的溫度以獲得熔岩。 block.incinerator.description = 清除任何多餘的物品或液體。 -block.biomattercompressor.description = 壓縮生物物質以提取油。 +block.spore-press.description = Compresses spore pods into oil. block.separator.description = 將石頭暴露在水壓下以獲得石頭中的各種礦物質。 -block.centrifuge.description = 比分離器更有效,但建造更昂貴和需要能量以操作。 block.power-node.description = 將能量傳輸到連接的節點。最多可連接四個能量來源、接收或節點。節點將從任何相鄰方塊接收能量或向其供能量。 block.power-node-large.description = 範圍大於能量節點,最多可連接六個能量來源、接收或節點。 block.battery.description = 有能量剩餘時,存儲電力並在能量短缺時提供能量。 @@ -749,7 +794,6 @@ block.blast-drill.description = 終極的鑽頭。需要大量能量。 block.water-extractor.description = 從地下提取水。當附近沒有湖泊時使用它。 block.cultivator.description = 用水培養土壤以獲得生物物質。 block.oil-extractor.description = 使用大量的能量從沙子中提取油。當附近沒有直接的石油來源時使用它。 -block.dart-ship-pad.description = 離開現有的船隻,換成基本的戰鬥機。\n站在上面雙擊墊以使用它。 block.trident-ship-pad.description = 離開現在的船隻,換成具有相當不錯裝甲的重型轟炸機。\n站在上面雙擊墊以使用它。 block.javelin-ship-pad.description = 離開現在的船隻,換成具有閃電武器、強大而快速的攔截器。\n站在上面雙擊墊以使用它。 block.glaive-ship-pad.description = 離開現在的船隻,換成具有重裝甲的武裝直升機。\n站在上面雙擊墊以使用它。 @@ -765,7 +809,6 @@ block.titan-factory.description = 生產具有裝甲的高級地面單位。 block.fortress-factory.description = 生產重型火砲地面單位。 block.revenant-factory.description = 生產重型激光地面單位。 block.repair-point.description = 持續治療附近最近的受損單位。 -block.command-center.description = 允許更改友好的AI行為。目前支持攻擊、撤退和巡邏命令。 block.conduit.description = 基本液體運輸方塊。像輸送帶一樣工作,但是液體用的。最適用於提取器、泵或其他管線。 block.pulse-conduit.description = 高級的液體運輸方塊。比標準管線更快地輸送並儲存更多液體。 block.phase-conduit.description = 高級的液體運輸方塊。使用能量將液體傳送到多個方塊外連接的相織管線。 @@ -779,13 +822,11 @@ block.thermal-pump.description = 終極泵。輸出速度是機械泵的三倍 block.router.description = 接受來自一個方向的物品並將它們平均輸出到最多3個其他方向。 用於將物品從一個來源分割為多個目標。 block.distributor.description = 高級的分配器,可將物品均分到最多7個其他方向。 block.bridge-conveyor.description = 高級的物品運輸方塊。允許跨過最多3個任何地形或建築物的方塊運輸物品。 -block.alpha-mech-pad.description = 當給予足夠能量時,將你的船重建為[accent]阿爾法[]機甲。 block.item-source.description = 不限地輸出物品。僅限沙盒。 block.liquid-source.description = 不限地輸出液體。僅限沙盒。 block.item-void.description = 不使用能量銷毀任何進入它的物品。僅限沙盒。 block.power-source.description = 不限地輸出能量。僅限沙盒。 block.power-void.description = 銷毀所有輸入的能量。僅限沙盒。 liquid.water.description = 常用於冷卻機器和廢物處理。 -liquid.lava.description = 可以轉換為[LIGHT_GRAY]石頭[]、用於發電或用作某些砲塔的彈藥。 liquid.oil.description = 可以燃燒、爆炸或用作冷卻劑。 liquid.cryofluid.description = 冷卻東西最有效的液體。 diff --git a/core/assets/cursors/cursor.png b/core/assets/cursors/cursor.png index ece5696be0..d8487b7fa1 100644 Binary files a/core/assets/cursors/cursor.png and b/core/assets/cursors/cursor.png differ diff --git a/core/assets/cursors/drill.png b/core/assets/cursors/drill.png index e524b82762..9672daf2e3 100644 Binary files a/core/assets/cursors/drill.png and b/core/assets/cursors/drill.png differ diff --git a/core/assets/cursors/hand.png b/core/assets/cursors/hand.png index 1613b1eac3..ef489d4554 100644 Binary files a/core/assets/cursors/hand.png and b/core/assets/cursors/hand.png differ diff --git a/core/assets/cursors/ibeam.png b/core/assets/cursors/ibeam.png index 61ddc4b423..7ce778a271 100644 Binary files a/core/assets/cursors/ibeam.png and b/core/assets/cursors/ibeam.png differ diff --git a/core/assets/cursors/unload.png b/core/assets/cursors/unload.png index 2340e6d94e..faa0fe9476 100644 Binary files a/core/assets/cursors/unload.png and b/core/assets/cursors/unload.png differ diff --git a/core/assets/fonts/font.ttf b/core/assets/fonts/font.ttf new file mode 100644 index 0000000000..3ccb1ada7c Binary files /dev/null and b/core/assets/fonts/font.ttf differ diff --git a/core/assets/fonts/pixel.ttf b/core/assets/fonts/pixel.ttf deleted file mode 100644 index 177fff5182..0000000000 Binary files a/core/assets/fonts/pixel.ttf and /dev/null differ diff --git a/core/assets/maps/craters.mmap b/core/assets/maps/craters.mmap index b07cbda03e..6b614e442a 100644 Binary files a/core/assets/maps/craters.mmap and b/core/assets/maps/craters.mmap differ diff --git a/core/assets/maps/desolateRift.mmap b/core/assets/maps/desolateRift.mmap new file mode 100644 index 0000000000..f6a9515fee Binary files /dev/null and b/core/assets/maps/desolateRift.mmap differ diff --git a/core/assets/maps/frozenForest.mmap b/core/assets/maps/frozenForest.mmap new file mode 100644 index 0000000000..6b8bfc55f9 Binary files /dev/null and b/core/assets/maps/frozenForest.mmap differ diff --git a/core/assets/maps/groundZero.mmap b/core/assets/maps/groundZero.mmap index ff8b5a9b56..b73cd867af 100644 Binary files a/core/assets/maps/groundZero.mmap and b/core/assets/maps/groundZero.mmap differ diff --git a/core/assets/maps/impact0079.mmap b/core/assets/maps/impact0079.mmap new file mode 100644 index 0000000000..0353276104 Binary files /dev/null and b/core/assets/maps/impact0079.mmap differ diff --git a/core/assets/maps/nuclearProductionComplex.mmap b/core/assets/maps/nuclearProductionComplex.mmap new file mode 100644 index 0000000000..dcffed46cc Binary files /dev/null and b/core/assets/maps/nuclearProductionComplex.mmap differ diff --git a/core/assets/maps/ruinousShores.mmap b/core/assets/maps/ruinousShores.mmap new file mode 100644 index 0000000000..a05f857fe3 Binary files /dev/null and b/core/assets/maps/ruinousShores.mmap differ diff --git a/core/assets/maps/stainedMountains.mmap b/core/assets/maps/stainedMountains.mmap new file mode 100644 index 0000000000..b57ae403d3 Binary files /dev/null and b/core/assets/maps/stainedMountains.mmap differ diff --git a/core/assets/shaders/blockbuild.fragment b/core/assets/shaders/blockbuild.fragment index e683997ba4..858018291f 100644 --- a/core/assets/shaders/blockbuild.fragment +++ b/core/assets/shaders/blockbuild.fragment @@ -22,7 +22,7 @@ bool id(vec2 coords, vec4 base){ } bool cont(vec2 T, vec2 v){ - float step = 1.0; + const float step = 3.0; vec4 base = texture2D(u_texture, T); return base.a > 0.1 && (id(T + vec2(0, step) * v, base) || id(T + vec2(0, -step) * v, base) || @@ -41,13 +41,8 @@ void main() { vec2 center = ((u_uv + u_uv2)/2.0 - u_uv) /v; float dst = (abs(center.x - coords.x) + abs(center.y - coords.y))/2.0; - float chance = 1.0; - if(u_progress > 0.8){ - chance = 1.0-(u_progress-0.8)*5.0; - } - - if((mod(u_time / 1.5 + value, 20.0) < 5.0 && cont(t, v))){ + if((mod(u_time / 1.5 + value, 20.0) < 15.0 && cont(t, v))){ gl_FragColor = u_color; }else if(dst > (1.0-u_progress) * (center.x)){ gl_FragColor = color; diff --git a/core/assets/shaders/blockpreview.fragment b/core/assets/shaders/blockpreview.fragment deleted file mode 100644 index 0f571d632b..0000000000 --- a/core/assets/shaders/blockpreview.fragment +++ /dev/null @@ -1,40 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D u_texture; - -uniform vec4 u_color; -uniform vec2 u_texsize; -uniform vec2 u_uv; -uniform vec2 u_uv2; - -varying vec4 v_color; -varying vec2 v_texCoord; - -bool id(vec2 coords, vec4 base){ - vec4 target = texture2D(u_texture, coords); - return target.a < 0.1 || (coords.x < u_uv.x || coords.y < u_uv.y || coords.x > u_uv2.x || coords.y > u_uv2.y); -} - -bool cont(vec2 T, vec2 v){ - float step = 1.0; - vec4 base = texture2D(u_texture, T); - return base.a > 0.1 && - (id(T + vec2(0, step) * v, base) || id(T + vec2(0, -step) * v, base) || - id(T + vec2(step, 0) * v, base) || id(T + vec2(-step, 0) * v, base)); -} - -void main() { - vec2 t = v_texCoord.xy; - vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y); - vec2 coord = t / v; - vec4 c = texture2D(u_texture, t); - - if(cont(t, v) ){ - gl_FragColor = u_color; - }else{ - gl_FragColor = vec4(0.0); - } -} diff --git a/core/assets/shaders/build.fragment b/core/assets/shaders/build.fragment deleted file mode 100644 index a5bd5c05f1..0000000000 --- a/core/assets/shaders/build.fragment +++ /dev/null @@ -1,46 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D u_texture; - -uniform float u_time; -uniform float u_progress; -uniform vec4 u_color; -uniform vec2 u_uv; -uniform vec2 u_uv2; -uniform vec2 u_texsize; - -varying vec4 v_color; -varying vec2 v_texCoord; - -float rand(vec2 co){ - return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); -} - -bool id(vec4 v){ - return v.a > 0.1; -} - -void main() { - vec2 coords = (v_texCoord.xy - u_uv) / (u_uv2 - u_uv); - vec2 t = v_texCoord.xy; - - vec4 c = texture2D(u_texture, v_texCoord.xy); - - if(1.0-abs(coords.x - 0.5)*2.0 < 1.0-u_progress){ - c = vec4(0.0); - } - - if(c.a > 0.01){ - float f = abs(sin(coords.x*2.0 + u_time)); - if(f > 0.9 ) - f = 1.0; - else - f = 0.0; - c = mix(c, u_color, f * u_color.a); - } - - gl_FragColor = c * v_color; -} diff --git a/core/assets/shaders/fog.fragment b/core/assets/shaders/fog.fragment index 8955cc9665..7ac266711a 100644 --- a/core/assets/shaders/fog.fragment +++ b/core/assets/shaders/fog.fragment @@ -5,18 +5,11 @@ precision mediump int; uniform sampler2D u_texture; -const float round = 0.23; - varying vec4 v_color; varying vec2 v_texCoord; void main() { vec4 color = texture2D(u_texture, v_texCoord.xy); - color.a = 1.0 - color.r; - color.rgb = vec3(0.0); - color.a = float(int(color.a / round)) * round; - if(color.a >= 1.0 - round){ - color.a = 1.0; - } - gl_FragColor = color * v_color; + color = vec4(0.0, 0.0, 0.0, 1.0 - color.r); + gl_FragColor = color; } diff --git a/core/assets/shaders/fullmix.fragment b/core/assets/shaders/fullmix.fragment deleted file mode 100644 index 00ff3997a2..0000000000 --- a/core/assets/shaders/fullmix.fragment +++ /dev/null @@ -1,19 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D u_texture; -uniform vec4 u_color; - -varying vec4 v_color; -varying vec2 v_texCoord; - -void main() { - - vec4 c = texture2D(u_texture, v_texCoord.xy); - - c = mix(c, vec4(v_color.r, v_color.g, v_color.b, c.a), v_color.a); - - gl_FragColor = c * vec4(v_color.rgb, 1.0); -} diff --git a/core/assets/shaders/inline-blocks.fragment b/core/assets/shaders/inline-blocks.fragment deleted file mode 100644 index e6b3c94b21..0000000000 --- a/core/assets/shaders/inline-blocks.fragment +++ /dev/null @@ -1,96 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D u_texture; - -uniform vec4 u_color; -uniform vec2 u_texsize; -uniform vec2 u_uv; -uniform vec2 u_uv2; -uniform float u_progress; -uniform float u_time; - -varying vec4 v_color; -varying vec2 v_texCoord; - -const float chunk = 4.0; -const float start = 0.7; -const float end = 0.9; - -float rand(vec2 co){ - return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); -} - -float round(float f){ - return float(int(f / chunk)) * chunk; -} - -bool id(vec2 coords, vec4 base, float basediff){ - vec4 target = texture2D(u_texture, coords); - return target.a < 0.1 || (coords.x < u_uv.x || coords.y < u_uv.y || coords.x > u_uv2.x || coords.y > u_uv2.y); -} - -bool cont(vec2 T, vec2 v, float basediff){ - float step = 1.0; - vec4 base = texture2D(u_texture, T); - return base.a > 0.1 && - (id(T + vec2(0, step) * v, base, basediff) || id(T + vec2(0, -step) * v, base, basediff) || - id(T + vec2(step, 0) * v, base, basediff) || id(T + vec2(-step, 0) * v, base, basediff)); -} - -bool complete(vec2 coords){ - vec2 rc = vec2(round(coords.x), round(coords.y)); - float r = clamp(rand(rc) + u_progress, 0.0, 1.0); - float fr = (r-start)*(1.0/(end-start)); - - vec2 next = rc + chunk/2.0; - float rdst = max(abs(coords.x - next.x), abs(coords.y - next.y)); - return rdst / (chunk/2.0) < fr; -} - -void main() { - - vec2 t = v_texCoord.xy; - - vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y); - - bool any = false; - - vec2 coords = (v_texCoord-u_uv) / v; - - - float value = coords.x + coords.y; - - vec4 color = texture2D(u_texture, t); - vec2 rc = vec2(round(coords.x), round(coords.y)); - vec2 center = ((u_uv + u_uv2)/2.0 - u_uv) /v; - - float r = clamp(rand(rc) + u_progress, 0.0, 1.0); - - const float scl = 10.0; - float dst = (abs(center.x - coords.x) + abs(center.y - coords.y)) / 2.0; - - if(dst - 1.0 < u_progress * (center.x) && dst> u_progress * (center.x) && color.a > 0.1){ - gl_FragColor = u_color; - }else if(r > end){ - gl_FragColor = color; - }else if((cont(t, v, 100.0) && mod(u_time / 1.5 + value, 20.0) < 5.0 && color.a > 0.1) || - (complete(coords) && (!complete(coords + vec2(1.0, 0.0)) || !complete(coords + vec2(-1.0, 0.0)) || !complete(coords + vec2(0.0, 1.0)) - || !complete(coords + vec2(0.0, -1.0))))){ - gl_FragColor = u_color; - }else if(r > start && color.a > 0.1){ - float fr = (r-start)*(1.0/(end-start)); - - vec2 next = rc + chunk/2.0; - float rdst = max(abs(coords.x - next.x), abs(coords.y - next.y)); - if(rdst / (chunk/2.0) < fr){ - gl_FragColor = u_color; - }else{ - gl_FragColor = vec4(0.0); - } - }else{ - gl_FragColor = vec4(0.0); - } -} diff --git a/core/assets/shaders/inline-contour.fragment b/core/assets/shaders/inline-contour.fragment deleted file mode 100644 index b7b201d373..0000000000 --- a/core/assets/shaders/inline-contour.fragment +++ /dev/null @@ -1,63 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D u_texture; - -uniform vec4 u_color; -uniform vec2 u_texsize; -uniform vec2 u_uv; -uniform vec2 u_uv2; -uniform float u_progress; -uniform float u_time; - -varying vec4 v_color; -varying vec2 v_texCoord; - -float diff(vec4 target, vec4 base){ - return (max(target.a / base.a, max(target.r / base.r, max(target.g / base.g, target.b / base.b))) - - min (target.a / base.a, min(target.r / base.r, min(target.g / base.g, target.b / base.b)))) * 4.0; -} - -bool id(vec2 coords, vec4 base, float basediff){ - vec4 target = texture2D(u_texture, coords); - return (diff(target, base)) > basediff - basediff*u_progress - || (basediff < 5.0 && (coords.x < u_uv.x || coords.y < u_uv.y || coords.x > u_uv2.x || coords.y > u_uv2.y)); -} - -bool cont(vec2 T, vec2 v, float basediff){ - float step = 1.0; - vec4 base = texture2D(u_texture, T); - return base.a > 0.1 && - (id(T + vec2(0, step) * v, base, basediff) || id(T + vec2(0, -step) * v, base, basediff) || - id(T + vec2(step, 0) * v, base, basediff) || id(T + vec2(-step, 0) * v, base, basediff)); -} - -float rand(vec2 co){ - return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); -} - -void main() { - - vec2 t = v_texCoord.xy; - - vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y); - vec2 coords = (v_texCoord-u_uv) / v; - float value = coords.x + coords.y; - - vec4 color = texture2D(u_texture, t); - - vec2 center = ((u_uv + u_uv2)/2.0 - u_uv) /v; - float dst = (abs(center.x - coords.x) + abs(center.y - coords.y)) / 2.0; - - if(dst - 1.0 < u_progress * (center.x) && dst> u_progress * (center.x) && color.a > 0.1){ - gl_FragColor = u_color; - }else if(cont(t, v, 6.0)){ - gl_FragColor = color; - }else if(cont(t, v, 3.0) && color.a > 0.1){ - gl_FragColor = u_color; - }else{ - gl_FragColor = vec4(0.0); - } -} diff --git a/core/assets/shaders/inline-noise.fragment b/core/assets/shaders/inline-noise.fragment deleted file mode 100644 index f7167d1dcf..0000000000 --- a/core/assets/shaders/inline-noise.fragment +++ /dev/null @@ -1,111 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D u_texture; - -uniform vec4 u_color; -uniform vec2 u_texsize; -uniform vec2 u_uv; -uniform vec2 u_uv2; -uniform float u_progress; -uniform float u_time; - -varying vec4 v_color; -varying vec2 v_texCoord; - -vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} -vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} - -float snoise(vec3 v){ - const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; - const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); - -// First corner - vec3 i = floor(v + dot(v, C.yyy) ); - vec3 x0 = v - i + dot(i, C.xxx) ; - -// Other corners - vec3 g = step(x0.yzx, x0.xyz); - vec3 l = 1.0 - g; - vec3 i1 = min( g.xyz, l.zxy ); - vec3 i2 = max( g.xyz, l.zxy ); - - // x0 = x0 - 0. + 0.0 * C - vec3 x1 = x0 - i1 + 1.0 * C.xxx; - vec3 x2 = x0 - i2 + 2.0 * C.xxx; - vec3 x3 = x0 - 1. + 3.0 * C.xxx; - -// Permutations - i = mod(i, 289.0 ); - vec4 p = permute( permute( permute( - i.z + vec4(0.0, i1.z, i2.z, 1.0 )) - + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) - + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); - -// Gradients -// ( N*N points uniformly over a square, mapped onto an octahedron.) - float n_ = 1.0/7.0; // N=7 - vec3 ns = n_ * D.wyz - D.xzx; - - vec4 j = p - 49.0 * floor(p * ns.z *ns.z); // mod(p,N*N) - - vec4 x_ = floor(j * ns.z); - vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) - - vec4 x = x_ *ns.x + ns.yyyy; - vec4 y = y_ *ns.x + ns.yyyy; - vec4 h = 1.0 - abs(x) - abs(y); - - vec4 b0 = vec4( x.xy, y.xy ); - vec4 b1 = vec4( x.zw, y.zw ); - - vec4 s0 = floor(b0)*2.0 + 1.0; - vec4 s1 = floor(b1)*2.0 + 1.0; - vec4 sh = -step(h, vec4(0.0)); - - vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; - vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; - - vec3 p0 = vec3(a0.xy,h.x); - vec3 p1 = vec3(a0.zw,h.y); - vec3 p2 = vec3(a1.xy,h.z); - vec3 p3 = vec3(a1.zw,h.w); - -//Normalise gradients - vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); - p0 *= norm.x; - p1 *= norm.y; - p2 *= norm.z; - p3 *= norm.w; - -// Mix final noise value - vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); - m = m * m; - return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), - dot(p2,x2), dot(p3,x3) ) ); -} - -void main() { - - vec2 t = v_texCoord.xy; - - vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y); - - vec2 coords = (v_texCoord-u_uv) / v; - - const float scl = 10.0; - float result = (snoise(vec3(coords.x / scl, coords.y / scl, u_time/400000.0)) + 1.0)/2.0; - - vec4 color = texture2D(u_texture, t); - - if(result < u_progress){ - gl_FragColor = color; - }else if(result < u_progress*2.0 && color.a > 0.1){ - gl_FragColor = u_color; - }else{ - gl_FragColor = vec4(0.0); - } - -} diff --git a/core/assets/shaders/inline.fragment b/core/assets/shaders/inline.fragment deleted file mode 100644 index d5d2f06f5b..0000000000 --- a/core/assets/shaders/inline.fragment +++ /dev/null @@ -1,184 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D u_texture; - -uniform vec4 u_color; -uniform vec2 u_texsize; -uniform vec2 u_uv; -uniform vec2 u_uv2; -uniform float u_progress; -uniform float u_time; - -varying vec4 v_color; -varying vec2 v_texCoord; - -const float chunk = 4.0; - -bool id(vec2 coords, vec4 base, float basediff){ - vec4 target = texture2D(u_texture, coords); - return target.a < 0.1 || (coords.x < u_uv.x || coords.y < u_uv.y || coords.x > u_uv2.x || coords.y > u_uv2.y); -} - -bool cont(vec2 T, vec2 v, float basediff){ - float step = 1.0; - vec4 base = texture2D(u_texture, T); - return base.a > 0.1 && - (id(T + vec2(0, step) * v, base, basediff) || id(T + vec2(0, -step) * v, base, basediff) || - id(T + vec2(step, 0) * v, base, basediff) || id(T + vec2(-step, 0) * v, base, basediff)); -} - -float rand(vec2 co){ - return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); -} - -float round(float f){ - return float(int(f / chunk)) * chunk; -} - -vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} -vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} - -float snoise(vec3 v){ - const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; - const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); - -// First corner - vec3 i = floor(v + dot(v, C.yyy) ); - vec3 x0 = v - i + dot(i, C.xxx) ; - -// Other corners - vec3 g = step(x0.yzx, x0.xyz); - vec3 l = 1.0 - g; - vec3 i1 = min( g.xyz, l.zxy ); - vec3 i2 = max( g.xyz, l.zxy ); - - // x0 = x0 - 0. + 0.0 * C - vec3 x1 = x0 - i1 + 1.0 * C.xxx; - vec3 x2 = x0 - i2 + 2.0 * C.xxx; - vec3 x3 = x0 - 1. + 3.0 * C.xxx; - -// Permutations - i = mod(i, 289.0 ); - vec4 p = permute( permute( permute( - i.z + vec4(0.0, i1.z, i2.z, 1.0 )) - + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) - + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); - -// Gradients -// ( N*N points uniformly over a square, mapped onto an octahedron.) - float n_ = 1.0/7.0; // N=7 - vec3 ns = n_ * D.wyz - D.xzx; - - vec4 j = p - 49.0 * floor(p * ns.z *ns.z); // mod(p,N*N) - - vec4 x_ = floor(j * ns.z); - vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) - - vec4 x = x_ *ns.x + ns.yyyy; - vec4 y = y_ *ns.x + ns.yyyy; - vec4 h = 1.0 - abs(x) - abs(y); - - vec4 b0 = vec4( x.xy, y.xy ); - vec4 b1 = vec4( x.zw, y.zw ); - - vec4 s0 = floor(b0)*2.0 + 1.0; - vec4 s1 = floor(b1)*2.0 + 1.0; - vec4 sh = -step(h, vec4(0.0)); - - vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; - vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; - - vec3 p0 = vec3(a0.xy,h.x); - vec3 p1 = vec3(a0.zw,h.y); - vec3 p2 = vec3(a1.xy,h.z); - vec3 p3 = vec3(a1.zw,h.w); - -//Normalise gradients - vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); - p0 *= norm.x; - p1 *= norm.y; - p2 *= norm.z; - p3 *= norm.w; - -// Mix final noise value - vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); - m = m * m; - return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), - dot(p2,x2), dot(p3,x3) ) ); -} - -void main() { - - vec2 t = v_texCoord.xy; - - vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y); - - bool any = false; - - vec2 coords = (v_texCoord-u_uv) / v; - - /* - const float scl = 10.0; - float result = (snoise(vec3(coords.x / scl, coords.y / scl, u_time/400000.0)) + 1.0)/2.0; - - vec4 color = texture2D(u_texture, t); - - if(result < u_progress){ - gl_FragColor = color; - }else if(result < u_progress*2.0 && color.a > 0.1){ - gl_FragColor = u_color; - }else{ - gl_FragColor = vec4(0.0); - }*/ - - - float value = coords.x + coords.y; - - vec4 color = texture2D(u_texture, t); - vec2 rc = vec2(round(coords.x), round(coords.y)); - vec2 center = ((u_uv + u_uv2)/2.0 - u_uv) /v; - - float r = clamp(rand(rc) + u_progress, 0.0, 1.0); - - const float start = 0.7; - const float end = 0.9; - - const float scl = 10.0; - float result = snoise(vec3(coords.x / scl, coords.y / scl, u_time/400.0))*2.0; - float dst = (abs(center.x - coords.x) + abs(center.y - coords.y)) / 2.0; - - if(dst - 1.0 < u_progress * (center.x) && dst> u_progress * (center.x) && color.a > 0.1){ - gl_FragColor = u_color; - }else if(r > end){ - gl_FragColor = color; - }else if(cont(t, v, 100.0) && mod(u_time / 1.5 + value, 20.0) < 5.0 && color.a > 0.1){ - gl_FragColor = u_color; - }else if(r > start && color.a > 0.1){ - float fr = (r-start)*(1.0/(end-start)); - - vec2 next = rc + chunk/2.0; - float rdst = max(abs(coords.x - next.x), abs(coords.y - next.y)) + result; - if(rdst / (chunk/2.0) < fr){ - gl_FragColor = u_color; - }else{ - gl_FragColor = vec4(0.0); - } - }else{ - gl_FragColor = vec4(0.0); - } -/* - if(mod(u_time / 1.5 + value, 30.0) < 15.0 && color.a > 0.1){ - gl_FragColor = u_color; - }else if(cont(t, v, 3.0)){ - gl_FragColor = color; - }else if(cont(t, v, 1.5)){ - gl_FragColor = u_color; - //}else if(mix(rand(vec2(dst)) * u_progress, 1.0, u_progress) > 0.5){ - // gl_FragColor = texture2D(u_texture, T); - }else{ - gl_FragColor = vec4(0.0); - }*/ -} diff --git a/core/assets/shaders/lava.fragment b/core/assets/shaders/lava.fragment deleted file mode 100644 index d7f3b3235e..0000000000 --- a/core/assets/shaders/lava.fragment +++ /dev/null @@ -1,91 +0,0 @@ -#ifdef GL_ES -precision highp float; -precision mediump int; -#endif - -#define s2 vec4(255.0, 165.0, 0.0, 255.0) / 255.0 -#define s1 vec4(255.0, 121.0, 62.0, 255.0) / 255.0 - -uniform sampler2D u_texture; - -uniform vec2 camerapos; -uniform vec2 screensize; -uniform float time; - -varying vec4 v_color; -varying vec2 v_texCoord; - -float round(float num, float f){ - return float(int(num / f)) * f; -} - -vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); } - -float snoise(vec2 v){ - const vec4 C = vec4(0.211324865405187, 0.366025403784439, - -0.577350269189626, 0.024390243902439); - vec2 i = floor(v + dot(v, C.yy) ); - vec2 x0 = v - i + dot(i, C.xx); - vec2 i1; - i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); - vec4 x12 = x0.xyxy + C.xxzz; - x12.xy -= i1; - i = mod(i, 289.0); - vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) - + i.x + vec3(0.0, i1.x, 1.0 )); - vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), - dot(x12.zw,x12.zw)), 0.0); - m = m*m ; - m = m*m ; - vec3 x = 2.0 * fract(p * C.www) - 1.0; - vec3 h = abs(x) - 0.5; - vec3 ox = floor(x + 0.5); - vec3 a0 = x - ox; - m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); - vec3 g; - g.x = a0.x * x0.x + h.x * x0.y; - g.yz = a0.yz * x12.xz + h.yz * x12.yw; - return 130.0 * dot(m, g); -} - -void main() { - - vec2 c = v_texCoord.xy; - vec4 color = texture2D(u_texture, c); - - vec2 v = vec2(1.0/screensize.x, 1.0/screensize.y); - ivec2 icoords = ivec2(int(c.x / v.x + camerapos.x), int(c.y / v.y + camerapos.y)); - vec2 coords = vec2(float(icoords.x), float(icoords.y)); - - float stime = time / 5.0; - - float mscl = 30.0; - float mth = 5.0; - - //if there's something actually there - if(color.r > 0.01){ - vec4 old = color; - color = texture2D(u_texture, c + vec2(sin(stime/3.0 + coords.y/0.75) * v.x, 0.0)) * vec4(0.9, 0.9, 1, 1.0); - color.a = 1.0; - - if(color.r < 0.01){ - color = old; - } - - const float bs = 1.0; - - float n1 = snoise(coords / (20.0 * bs) + vec2(time) / 250.0); - float n2 = snoise((coords + vec2(632.0)) / (9.0 * bs) + vec2(0.0, -time) / 220.0); - float n3 = snoise((coords + vec2(2233.0)) / (15.0 * bs) + vec2(time, 0.0) / 290.0); - - float r = (n1 + n2 + n3) / 3.0; - - if(r < -0.5){ - color = s2; - }else if(r < -0.2){ - color = s1; - } - } - - gl_FragColor = color; -} diff --git a/core/assets/shaders/mix.fragment b/core/assets/shaders/mix.fragment deleted file mode 100644 index 4a9ea9c64b..0000000000 --- a/core/assets/shaders/mix.fragment +++ /dev/null @@ -1,19 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D u_texture; -uniform vec4 u_color; - -varying vec4 v_color; -varying vec2 v_texCoord; - -void main() { - - vec4 c = texture2D(u_texture, v_texCoord.xy); - - c = mix(c, vec4(u_color.r, u_color.g, u_color.b, c.a), v_color.a); - - gl_FragColor = c * vec4(v_color.rgb, 1.0); -} diff --git a/core/assets/shaders/oil.fragment b/core/assets/shaders/oil.fragment deleted file mode 100644 index 52701e09a2..0000000000 --- a/core/assets/shaders/oil.fragment +++ /dev/null @@ -1,86 +0,0 @@ -#ifdef GL_ES -precision highp float; -precision mediump int; -#endif - -#define s1 vec4(63.0, 63.0, 63.0, 255.0) / 255.0 - -uniform sampler2D u_texture; - -uniform vec2 camerapos; -uniform vec2 screensize; -uniform float time; - -varying vec4 v_color; -varying vec2 v_texCoord; - -float round(float num, float f){ - return float(int(num / f)) * f; -} - -vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); } - -float snoise(vec2 v){ - const vec4 C = vec4(0.211324865405187, 0.366025403784439, - -0.577350269189626, 0.024390243902439); - vec2 i = floor(v + dot(v, C.yy) ); - vec2 x0 = v - i + dot(i, C.xx); - vec2 i1; - i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); - vec4 x12 = x0.xyxy + C.xxzz; - x12.xy -= i1; - i = mod(i, 289.0); - vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) - + i.x + vec3(0.0, i1.x, 1.0 )); - vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), - dot(x12.zw,x12.zw)), 0.0); - m = m*m ; - m = m*m ; - vec3 x = 2.0 * fract(p * C.www) - 1.0; - vec3 h = abs(x) - 0.5; - vec3 ox = floor(x + 0.5); - vec3 a0 = x - ox; - m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); - vec3 g; - g.x = a0.x * x0.x + h.x * x0.y; - g.yz = a0.yz * x12.xz + h.yz * x12.yw; - return 130.0 * dot(m, g); -} - -void main() { - - vec2 c = v_texCoord.xy; - vec4 color = texture2D(u_texture, c); - - vec2 v = vec2(1.0/screensize.x, 1.0/screensize.y); - ivec2 icoords = ivec2(int(c.x / v.x + camerapos.x), int(c.y / v.y + camerapos.y)); - vec2 coords = vec2(float(icoords.x), float(icoords.y)); - - float stime = time / 5.0; - - float mscl = 30.0; - float mth = 5.0; - - //if there's something actually there - if(color.r > 0.01){ - vec4 old = color; - color = texture2D(u_texture, c + vec2(sin(stime/3.0 + coords.y/0.75) * v.x, 0.0)) * vec4(0.9, 0.9, 1, 1.0); - color.a = 1.0; - - if(color.r < 0.01){ - color = old; - } - - float n1 = snoise(coords / 22.0 + vec2(-time) / 540.0); - float n2 = snoise((coords + vec2(632.0)) / 8.0 + vec2(0.0, time) / 510.0); - - float r = (n1 + n2) / 2.0; - - if(r < -0.3 && r > -0.6){ - color *= 1.4; - color.a = 1.0; - } - } - - gl_FragColor = color; -} diff --git a/core/assets/shaders/pattern.fragment b/core/assets/shaders/pattern.fragment deleted file mode 100644 index 4a25d505b3..0000000000 --- a/core/assets/shaders/pattern.fragment +++ /dev/null @@ -1,60 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D u_texture; - -uniform vec4 u_color; -uniform vec2 u_texsize; -uniform float u_time; -uniform vec2 u_offset; - -varying vec4 v_color; -varying vec2 v_texCoord; - -void main() { - - vec2 T = v_texCoord.xy; - vec2 coords = (T * u_texsize) + u_offset; - - float si = 1.0 + sin(u_time / 20.0 /*+ (coords.x + coords.y) / 30.0*/) / 8.0; - - vec4 color = texture2D(u_texture, T) * vec4(si, si, si, 1.0); - - vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y); - - bool any = false; - - float thickness = 1.0; - float step = 1.0; - - if(texture2D(u_texture, T).a < 0.1 && - (texture2D(u_texture, T + vec2(0, step) * v).a > 0.1 || texture2D(u_texture, T + vec2(0, -step) * v).a > 0.1 || - texture2D(u_texture, T + vec2(step, 0) * v).a > 0.1 || texture2D(u_texture, T + vec2(-step, 0) * v).a > 0.1)) - any = true; - - if(any){ - gl_FragColor = u_color * vec4(si, si, si, 1.0); - }else{ - - //coords.x = float(int(coords.x)); - if(color.a > 0.1){ - float x = coords.x; - float y = coords.y; - float time = u_time; - float w = 1.0; - float h = 1.0; - float f1 = sin(2.0*time+(y/4.0*cos(time/3.0)+(x/2.0)-w/4.0)*((y/3.0)-h/4.0)/w); - float f2 = -2.0*cos(11.0*time/9.0-11.0*pow(y, x)/9.0); - - color.r = (f2 + f1) / 4.0*abs(cos(2.0*(x-y)/w + time)); - color.g = (f2 + f1) /(3.0 + color.r); - color.b = (f2 + f1) /(2.5 + color.g); - - - } - - gl_FragColor = color; - } -} diff --git a/core/assets/shaders/outline.fragment b/core/assets/shaders/shadow.fragment similarity index 95% rename from core/assets/shaders/outline.fragment rename to core/assets/shaders/shadow.fragment index 09a9a4e041..7346d78142 100644 --- a/core/assets/shaders/outline.fragment +++ b/core/assets/shaders/shadow.fragment @@ -20,7 +20,7 @@ void main() { vec4 c = texture2D(u_texture, v_texCoord.xy); float spacing = SPACE * u_scl; - gl_FragColor = mix(c * v_color, u_color, + gl_FragColor = mix(vec4(0.0, 0.0, 0.0, min(c.a, u_color.a)), u_color, (1.0-step(0.001, texture2D(u_texture, v_texCoord.xy).a)) * step(0.001, //cardinals @@ -41,4 +41,4 @@ void main() { texture2D(u_texture, v_texCoord.xy + vec2(spacing, 0) * v*2.0).a + texture2D(u_texture, v_texCoord.xy + vec2(-spacing, 0) * v*2.0).a )); -} +} \ No newline at end of file diff --git a/core/assets/shaders/shield.fragment b/core/assets/shaders/shield.fragment index f771e59dd3..cf8b6a7132 100644 --- a/core/assets/shaders/shield.fragment +++ b/core/assets/shaders/shield.fragment @@ -18,10 +18,6 @@ uniform vec2 u_offset; varying vec4 v_color; varying vec2 v_texCoord; -float round(float f){ - return float(int(f)); -} - void main() { vec2 T = v_texCoord.xy; @@ -41,7 +37,7 @@ void main() { }else{ if(color.a > 0.1){ - if(mod(coords.x / u_dp + coords.y / u_dp + sin(round(coords.x / u_dp) / 5.0) * 3.0 + sin(round(coords.y / u_dp) / 5.0) * 3.0 + u_time / 4.0, 10.0) < 2.0){ + if(mod(coords.x / u_dp + coords.y / u_dp + sin(floor(coords.x / u_dp) / 5.0) * 3.0 + sin(floor(coords.y / u_dp) / 5.0) * 3.0 + u_time / 4.0, 10.0) < 2.0){ color *= 1.65; } diff --git a/core/assets/shaders/space2.fragment b/core/assets/shaders/space2.fragment deleted file mode 100644 index 5b9ea44853..0000000000 --- a/core/assets/shaders/space2.fragment +++ /dev/null @@ -1,88 +0,0 @@ -#ifdef GL_ES -precision highp float; -precision mediump int; -#endif - -uniform sampler2D u_texture; - -uniform vec2 u_center; -uniform vec2 camerapos; -uniform vec2 screensize; -uniform float time; - -varying vec4 v_color; -varying vec2 v_texCoord; - -const float tau = 6.28318530717958647692; -const float tscl = 0.4; - -// Gamma correction -#define GAMMA (2.2) - -vec3 ToLinear(vec3 col ){ - // simulate a monitor, converting colour values into light values - return pow( col, vec3(GAMMA) ); -} - -vec3 ToGamma(vec3 col ){ - // convert back into colour values, so the correct light will come out of the monitor - return pow( col, vec3(1.0/GAMMA) ); -} - -float srand(vec2 co){ - return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); -} - -vec4 Noise(ivec2 x ){ - return vec4(srand((vec2(x)+0.5)/256.0)); -} - -void main(){ - vec4 resultc = texture2D(u_texture, v_texCoord.xy); - - if(resultc.a > 0.0){ - - vec2 coords = v_texCoord.xy*screensize; - - vec3 ray; - ray.xy = 2.0*(coords-screensize.xy*.5)/screensize.x; - ray.z = 1.0; - - float literallyzero = 0.000000000001; - - float offset = time/60.0*.5 * tscl + camerapos.x * u_center.x * resultc.r * literallyzero; - float speed2 = 0.3; - float speed = speed2+.1; - offset += .1; - offset *= 2.0; - - vec3 col = vec3(0.0); - - vec3 stp = ray/max(abs(ray.x),abs(ray.y)); - - vec3 pos = 2.0*stp+.5; - for ( int i=0; i < 20; i++){ - float z = Noise(ivec2(pos.xy)).x; - z = fract(z-offset); - float d = 50.0*z-pos.z; - float w = pow(max(0.0,1.0-8.0*length(fract(pos.xy)-.5)),2.0); - vec3 c = max(vec3(0),vec3(1.0-abs(d+speed2*.5)/speed,1.0-abs(d)/speed,1.0-abs(d-speed2*.5)/speed)); - col += 1.5*(1.0-z)*c*w; - pos += stp; - } - - vec3 color = ToGamma(col); - - if(color.r > 0.3 && color.b > 0.3){ - color = vec3(240.0, 245.0, 255.0) / 255.0; - }else{ - color = vec3(0.0); - } - - gl_FragColor = vec4(color,1.0); - }else{ - gl_FragColor = vec4(0.0); - } - - -} diff --git a/core/assets/shaders/space.fragment b/core/assets/shaders/tar.fragment similarity index 71% rename from core/assets/shaders/space.fragment rename to core/assets/shaders/tar.fragment index f2522b4fca..17169aa018 100644 --- a/core/assets/shaders/space.fragment +++ b/core/assets/shaders/tar.fragment @@ -7,7 +7,6 @@ precision mediump int; uniform sampler2D u_texture; -uniform vec2 u_center; uniform vec2 camerapos; uniform vec2 screensize; uniform float time; @@ -15,10 +14,6 @@ uniform float time; varying vec4 v_color; varying vec2 v_texCoord; -float round(float num, float f){ - return float(int(num / f)) * f; -} - vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); } float snoise(vec2 v){ @@ -54,24 +49,31 @@ void main() { vec4 color = texture2D(u_texture, c); vec2 v = vec2(1.0/screensize.x, 1.0/screensize.y); - ivec2 icoords = ivec2(int(c.x / v.x + camerapos.x), int(c.y / v.y + camerapos.y)); - vec2 coords = vec2(float(icoords.x), float(icoords.y)); - + vec2 coords = vec2(c.x / v.x + camerapos.x, c.y / v.y + camerapos.y); + float stime = time / 5.0; - + float mscl = 30.0; float mth = 5.0; - - //if there's something actually there - if(color.a > 0.01){ - vec2 diff = camerapos + screensize/2.0 - u_center; - - float dst = mod((distance(coords, camerapos + screensize/2.0 - diff/5.0) + time * 2.0 + snoise(coords / 100.0) * 10.0), 150.0); - - if(dst < 40.0){ - color = vec4(vec3(0.2), 1.0); - } - } + + vec4 old = color; + color = texture2D(u_texture, c + vec2(sin(stime/3.0 + coords.y/0.75) * v.x, 0.0)) * vec4(0.9, 0.9, 1, 1.0); + color.a = 1.0; + + if(color.r < 0.01){ + color = old; + } + + float n1 = snoise(coords / 22.0 + vec2(-time) / 540.0); + float n2 = snoise((coords + vec2(632.0)) / 8.0 + vec2(0.0, time) / 510.0); + + float r = (n1 + n2) / 2.0; + + if(r < -0.3 && r > -0.6){ + color *= 1.4; + color.a = 1.0; + } + gl_FragColor = color; -} +} \ No newline at end of file diff --git a/core/assets/shaders/unitbuild.fragment b/core/assets/shaders/unitbuild.fragment new file mode 100644 index 0000000000..35a956c35a --- /dev/null +++ b/core/assets/shaders/unitbuild.fragment @@ -0,0 +1,60 @@ +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + +#define step 3.0 + +uniform sampler2D u_texture; + +uniform float u_time; +uniform float u_progress; +uniform vec4 u_color; +uniform vec2 u_uv; +uniform vec2 u_uv2; +uniform vec2 u_texsize; + +varying vec4 v_color; +varying vec2 v_texCoord; + +bool id(vec4 v){ + return v.a > 0.1; +} + +bool id(vec2 coords, vec4 base){ + vec4 target = texture2D(u_texture, coords); + return target.a < 0.1 || (coords.x < u_uv.x || coords.y < u_uv.y || coords.x > u_uv2.x || coords.y > u_uv2.y); +} + +bool cont(vec2 T, vec2 v){ + vec4 base = texture2D(u_texture, T); + return base.a > 0.1 && + (id(T + vec2(0, step) * v, base) || id(T + vec2(0, -step) * v, base) || + id(T + vec2(step, 0) * v, base) || id(T + vec2(-step, 0) * v, base) || + id(T + vec2(step, step) * v, base) || id(T + vec2(-step, -step) * v, base) || + id(T + vec2(step, -step) * v, base) || id(T + vec2(-step, step) * v, base)); +} + +void main() { + vec2 coords = (v_texCoord.xy - u_uv) / (u_uv2 - u_uv); + vec2 t = v_texCoord.xy; + vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y); + + vec4 c = texture2D(u_texture, v_texCoord.xy); + bool outl = cont(t, v); + + if(1.0-abs(coords.x - 0.5)*2.0 < 1.0-u_progress && !outl){ + c = vec4(0.0); + } + + if(c.a > 0.01){ + float f = abs(sin(coords.x*2.0 + u_time)); + if(f > 0.9 || outl) + f = 1.0; + else + f = 0.0; + c = mix(c, u_color, f * u_color.a); + } + + gl_FragColor = c * v_color; +} diff --git a/core/assets/shaders/water.fragment b/core/assets/shaders/water.fragment index d8f26bebb1..83910bbe5f 100644 --- a/core/assets/shaders/water.fragment +++ b/core/assets/shaders/water.fragment @@ -12,10 +12,6 @@ uniform float time; varying vec4 v_color; varying vec2 v_texCoord; -float round(float num, float f){ - return float(int(num / f)) * f; -} - vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); } float snoise(vec2 v){ @@ -51,40 +47,31 @@ void main() { vec4 color = texture2D(u_texture, c) * v_color; vec2 v = vec2(1.0/screensize.x, 1.0/screensize.y); - ivec2 icoords = ivec2(int(c.x / v.x + camerapos.x), int(c.y / v.y + camerapos.y)); - vec2 coords = vec2(float(icoords.x), float(icoords.y)); - + vec2 coords = vec2(c.x / v.x + camerapos.x, c.y / v.y + camerapos.y); + float stime = time / 5.0; - + float mscl = 30.0; float mth = 5.0; - - //if there's something actually there - if(color.r > 0.01){ - vec4 old = color; - color = texture2D(u_texture, c + vec2(sin(stime/3.0 + coords.y/0.75) * v.x, 0.0)) * vec4(0.9, 0.9, 1, 1.0); - color.a = 1.0; - - if(color.r < 0.01){ - color = old; - } - - float n1 = snoise(coords / 40.0 + vec2(time) / 200.0); - float n2 = snoise((coords + vec2(632.0)) / 25.0 + vec2(0.0, -time) / 190.0); - - float r = (n1 + n2) * 3.0; - - if(mod(float(int(coords.x + coords.y*1.1 + sin(stime / 8.0 + coords.x/5.0 - coords.y/100.0)*2.0)) + - sin(stime / 20.0 + coords.y/3.0) * 1.0 + - sin(stime / 10.0 + coords.y/2.0) * 2.0 + - sin(stime / 7.0 + coords.y/1.0) * 0.5 + - sin(coords.x + coords.y) + - sin(stime / 20.0 + coords.x/4.0) * 1.0, mscl) + r < mth){ - - color *= 1.2; - color.a = 1.0; - } - } + + color = texture2D(u_texture, c + vec2(sin(stime/3.0 + coords.y/0.75) * v.x, 0.0)) * vec4(0.9, 0.9, 1, 1.0); + color.a = 1.0; + + float n1 = snoise(coords / 40.0 + vec2(time) / 200.0); + float n2 = snoise((coords + vec2(632.0)) / 25.0 + vec2(0.0, -time) / 190.0); + + float r = (n1 + n2) * 3.0; + + if(mod(float(int(coords.x + coords.y*1.1 + sin(stime / 8.0 + coords.x/5.0 - coords.y/100.0)*2.0)) + + sin(stime / 20.0 + coords.y/3.0) * 1.0 + + sin(stime / 10.0 + coords.y/2.0) * 2.0 + + sin(stime / 7.0 + coords.y/1.0) * 0.5 + + sin(coords.x + coords.y) + + sin(stime / 20.0 + coords.x/4.0) * 1.0, mscl) + r < mth){ + + color *= 1.2; + color.a = 1.0; + } gl_FragColor = color; -} +} \ No newline at end of file diff --git a/core/assets/sprites/background.png b/core/assets/sprites/background.png deleted file mode 100644 index ee3aa9ba6f..0000000000 Binary files a/core/assets/sprites/background.png and /dev/null differ diff --git a/core/assets/sprites/block_colors.png b/core/assets/sprites/block_colors.png new file mode 100644 index 0000000000..67415b39d3 Binary files /dev/null and b/core/assets/sprites/block_colors.png differ diff --git a/core/assets/sprites/sprites.atlas b/core/assets/sprites/sprites.atlas index 49843cb01e..4776a7378b 100644 --- a/core/assets/sprites/sprites.atlas +++ b/core/assets/sprites/sprites.atlas @@ -6,8617 +6,6965 @@ filter: Nearest,Nearest repeat: none force-projector rotate: false - xy: 457, 1439 + xy: 415, 1530 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 force-projector-top rotate: false - xy: 359, 1243 + xy: 415, 1432 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mend-projector rotate: false - xy: 653, 1645 + xy: 1645, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mend-projector-top rotate: false - xy: 785, 1777 + xy: 1711, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 overdrive-projector rotate: false - xy: 653, 1579 + xy: 1843, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 overdrive-projector-top rotate: false - xy: 785, 1711 + xy: 1909, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 shock-mine rotate: false - xy: 915, 615 + xy: 1654, 646 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor rotate: false - xy: 1858, 1388 + xy: 987, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-bridge rotate: false - xy: 1157, 1211 + xy: 979, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-end rotate: false - xy: 1191, 1211 + xy: 1021, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-0 rotate: false - xy: 745, 621 + xy: 1353, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-1 rotate: false - xy: 707, 579 + xy: 1395, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-2 rotate: false - xy: 1041, 1215 + xy: 1387, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-3 rotate: false - xy: 1041, 1181 + xy: 1429, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-0 rotate: false - xy: 779, 291 + xy: 1421, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-1 rotate: false - xy: 779, 257 + xy: 1463, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-2 rotate: false - xy: 779, 223 + xy: 1455, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-3 rotate: false - xy: 779, 189 + xy: 1497, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-0 rotate: false - xy: 779, 155 + xy: 1489, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-1 rotate: false - xy: 779, 121 + xy: 1531, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-2 rotate: false - xy: 779, 87 + xy: 1523, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-3 rotate: false - xy: 779, 53 + xy: 1565, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-0 rotate: false - xy: 1225, 1245 + xy: 1557, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-1 rotate: false - xy: 1225, 1211 + xy: 1599, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-2 rotate: false - xy: 1259, 1257 + xy: 1591, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-3 rotate: false - xy: 1259, 1223 + xy: 1633, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-0 rotate: false - xy: 1293, 1257 + xy: 1625, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-1 rotate: false - xy: 1293, 1223 + xy: 1667, 884 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-2 rotate: false - xy: 1327, 1257 + xy: 1659, 850 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-3 rotate: false - xy: 1327, 1223 + xy: 1701, 871 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-0 rotate: false - xy: 1047, 946 + xy: 1790, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-1 rotate: false - xy: 1051, 912 + xy: 1819, 895 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-2 rotate: false - xy: 1051, 878 + xy: 1837, 861 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-3 rotate: false - xy: 1051, 844 + xy: 1829, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-0 rotate: false - xy: 1051, 810 + xy: 1829, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-1 rotate: false - xy: 1051, 776 + xy: 1825, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-2 rotate: false - xy: 1051, 742 + xy: 1825, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-3 rotate: false - xy: 1051, 708 + xy: 1825, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-0 rotate: false - xy: 1051, 674 + xy: 1824, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-1 rotate: false - xy: 1051, 640 + xy: 1824, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-2 rotate: false - xy: 1051, 606 + xy: 1817, 1063 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-3 rotate: false - xy: 1051, 572 + xy: 1851, 1071 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-0 rotate: false - xy: 1051, 538 + xy: 1885, 1071 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-1 rotate: false - xy: 1051, 504 + xy: 1823, 963 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-2 rotate: false - xy: 813, 507 + xy: 1823, 929 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-3 rotate: false - xy: 847, 507 + xy: 1853, 895 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-0 rotate: false - xy: 881, 504 + xy: 1871, 861 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-1 rotate: false - xy: 915, 479 + xy: 1863, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-2 rotate: false - xy: 949, 479 + xy: 1863, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-3 rotate: false - xy: 983, 479 + xy: 1859, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 distributor rotate: false - xy: 858, 1843 + xy: 1249, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 junction rotate: false - xy: 1445, 1354 + xy: 1145, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -mass-driver +mass-driver-base rotate: false - xy: 359, 655 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -mass-driver-turret - rotate: false - xy: 457, 655 + xy: 1395, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 overflow-gate rotate: false - xy: 1993, 1048 + xy: 906, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor rotate: false - xy: 945, 1023 + xy: 1110, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-arrow rotate: false - xy: 945, 989 + xy: 1144, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-bridge rotate: false - xy: 945, 955 + xy: 1178, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-end rotate: false - xy: 945, 921 + xy: 1212, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 router rotate: false - xy: 881, 742 + xy: 1212, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sorter rotate: false - xy: 813, 575 + xy: 1761, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -warp-gate - rotate: false - xy: 539, 459 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -warp-gate-top - rotate: false - xy: 539, 361 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 blast-drill rotate: false - xy: 261, 1635 - size: 96, 96 - orig: 96, 96 + xy: 1, 601 + size: 128, 128 + orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rim rotate: false - xy: 261, 1537 - size: 96, 96 - orig: 96, 96 + xy: 1, 341 + size: 128, 128 + orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rotator rotate: false - xy: 359, 1635 - size: 96, 96 - orig: 96, 96 + xy: 1, 211 + size: 128, 128 + orig: 128, 128 offset: 0, 0 index: -1 blast-drill-top rotate: false - xy: 457, 1733 - size: 96, 96 - orig: 96, 96 + xy: 1, 81 + size: 128, 128 + orig: 128, 128 offset: 0, 0 index: -1 laser-drill rotate: false - xy: 1716, 1851 - size: 64, 64 - orig: 64, 64 + xy: 905, 1561 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +laser-drill-rim + rotate: false + xy: 1003, 1577 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 laser-drill-rotator rotate: false - xy: 1848, 1851 - size: 64, 64 - orig: 64, 64 + xy: 1003, 1479 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 laser-drill-top rotate: false - xy: 1914, 1851 - size: 64, 64 - orig: 64, 64 + xy: 1101, 1593 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 mechanical-drill rotate: false - xy: 1980, 1851 + xy: 1381, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-rotator rotate: false - xy: 653, 1711 + xy: 1513, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-top rotate: false - xy: 719, 1777 + xy: 1579, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 oil-extractor rotate: false - xy: 261, 557 + xy: 1591, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-liquid rotate: false - xy: 457, 557 + xy: 1689, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-rotator rotate: false - xy: 245, 459 + xy: 1689, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-top rotate: false - xy: 245, 361 + xy: 1787, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -plasma-drill - rotate: false - xy: 1, 68 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -plasma-drill-rim - rotate: false - xy: 131, 1628 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -plasma-drill-rotator - rotate: false - xy: 131, 1498 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -plasma-drill-top - rotate: false - xy: 131, 1368 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 pneumatic-drill rotate: false - xy: 653, 1381 + xy: 1645, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-rotator rotate: false - xy: 785, 1513 + xy: 1777, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-top rotate: false - xy: 851, 1579 + xy: 1843, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor rotate: false - xy: 917, 1249 + xy: 385, 1036 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-liquid rotate: false - xy: 1049, 1381 + xy: 319, 904 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-rotator rotate: false - xy: 1115, 1447 + xy: 385, 970 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-top rotate: false - xy: 653, 919 + xy: 451, 1036 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -blackrock1 - rotate: false - xy: 1620, 1388 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -blackstone1 - rotate: false - xy: 1688, 1388 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -blackstone2 - rotate: false - xy: 1722, 1388 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -blackstone3 - rotate: false - xy: 1173, 1313 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -blackstoneedge - rotate: false - xy: 329, 311 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -coal1 - rotate: false - xy: 1241, 1291 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -coal2 - rotate: false - xy: 1275, 1291 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -coal3 - rotate: false - xy: 1309, 1291 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -copper1 - rotate: false - xy: 1293, 1189 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -copper2 - rotate: false - xy: 1327, 1189 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -copper3 - rotate: false - xy: 785, 959 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters1 - rotate: false - xy: 1892, 1379 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters2 - rotate: false - xy: 1926, 1379 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters3 - rotate: false - xy: 1960, 1379 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -deepwater - rotate: false - xy: 307, 77 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -deepwater-icon-full - rotate: false - xy: 307, 77 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -deepwater-icon-medium - rotate: false - xy: 307, 77 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dirt1 - rotate: false - xy: 375, 77 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dirt2 - rotate: false - xy: 409, 77 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dirt3 - rotate: false - xy: 443, 77 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dirtedge - rotate: false - xy: 579, 161 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -generic-cliff-edge - rotate: false - xy: 328, 9 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -generic-cliff-edge-1 - rotate: false - xy: 362, 9 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -generic-cliff-edge-2 - rotate: false - xy: 396, 9 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -generic-cliff-side - rotate: false - xy: 430, 9 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -grass1 - rotate: false - xy: 532, 9 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -grass2 - rotate: false - xy: 566, 9 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -grass3 - rotate: false - xy: 600, 41 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -grassedge - rotate: false - xy: 679, 275 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ice1 - rotate: false - xy: 736, 41 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice2 - rotate: false - xy: 600, 7 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice3 - rotate: false - xy: 634, 7 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -iceedge - rotate: false - xy: 629, 125 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -icerock1 - rotate: false - xy: 702, 7 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icerock2 - rotate: false - xy: 736, 7 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -lava - rotate: false - xy: 1513, 1320 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -lavaedge - rotate: false - xy: 1388, 1801 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -lead1 - rotate: false - xy: 1547, 1320 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -lead2 - rotate: false - xy: 1581, 1354 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -lead3 - rotate: false - xy: 1581, 1320 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metalfloor1 - rotate: false - xy: 1955, 1277 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metalfloor2 - rotate: false - xy: 1989, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metalfloor3 - rotate: false - xy: 1989, 1252 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metalfloor4 - rotate: false - xy: 1361, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metalfloor5 - rotate: false - xy: 1361, 1252 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metalfloor6 - rotate: false - xy: 1361, 1218 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metalflooredge - rotate: false - xy: 1181, 1651 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rock1 - rotate: false - xy: 1531, 1501 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rock2 - rotate: false - xy: 1581, 1551 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rocks1 - rotate: false - xy: 881, 878 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -rocks2 - rotate: false - xy: 881, 844 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand1 - rotate: false - xy: 915, 887 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand2 - rotate: false - xy: 915, 853 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand3 - rotate: false - xy: 949, 887 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sandedge - rotate: false - xy: 1681, 1601 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -scrap1 - rotate: false - xy: 915, 751 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap2 - rotate: false - xy: 949, 785 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap3 - rotate: false - xy: 915, 717 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shrub - rotate: false - xy: 983, 887 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow1 - rotate: false - xy: 983, 785 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow2 - rotate: false - xy: 983, 751 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow3 - rotate: false - xy: 983, 717 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snowedge - rotate: false - xy: 1681, 1551 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -space - rotate: false - xy: 881, 572 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -space-icon-full - rotate: false - xy: 881, 572 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -space-icon-medium - rotate: false - xy: 881, 572 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spaceedge - rotate: false - xy: 1631, 1451 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -stone-cliff-edge - rotate: false - xy: 1013, 1082 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone-cliff-edge-1 - rotate: false - xy: 1017, 912 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone-cliff-edge-2 - rotate: false - xy: 1017, 878 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone-cliff-side - rotate: false - xy: 1017, 844 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone1 - rotate: false - xy: 1013, 1014 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone2 - rotate: false - xy: 1013, 980 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone3 - rotate: false - xy: 1013, 946 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stoneedge - rotate: false - xy: 1931, 1751 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -tar - rotate: false - xy: 1017, 640 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -tar-icon-full - rotate: false - xy: 1017, 640 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -tar-icon-medium - rotate: false - xy: 1017, 640 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -taredge - rotate: false - xy: 1931, 1701 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thorium1 - rotate: false - xy: 813, 541 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium2 - rotate: false - xy: 847, 541 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium3 - rotate: false - xy: 881, 538 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium1 - rotate: false - xy: 1047, 1048 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium2 - rotate: false - xy: 1047, 1014 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium3 - rotate: false - xy: 1047, 980 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water - rotate: false - xy: 821, 371 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water-icon-full - rotate: false - xy: 821, 371 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water-icon-medium - rotate: false - xy: 821, 371 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water-cliff-edge - rotate: false - xy: 821, 337 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water-cliff-edge-1 - rotate: false - xy: 813, 303 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water-cliff-edge-2 - rotate: false - xy: 813, 269 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water-cliff-side - rotate: false - xy: 813, 235 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -wateredge - rotate: false - xy: 1981, 1451 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 block-border rotate: false - xy: 1241, 1325 + xy: 843, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-middle rotate: false - xy: 1275, 1325 + xy: 885, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pump-liquid rotate: false - xy: 1275, 1325 + xy: 885, 897 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +block-select + rotate: false + xy: 877, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-liquid rotate: false - xy: 745, 893 + xy: 1225, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 place-arrow rotate: false - xy: 441, 459 + xy: 1885, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rubble-1-0 rotate: false - xy: 1115, 1777 + xy: 253, 1003 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-1-1 rotate: false - xy: 653, 1249 + xy: 253, 937 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-2-0 rotate: false - xy: 719, 1315 + xy: 253, 871 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-2-1 rotate: false - xy: 785, 1381 + xy: 253, 805 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-3-0 rotate: false - xy: 555, 1537 + xy: 155, 1103 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rubble-3-1 rotate: false - xy: 555, 1537 + xy: 155, 1103 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 +rubble-4-0 + rotate: false + xy: 1696, 1789 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +rubble-4-1 + rotate: false + xy: 1696, 1789 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 spawn rotate: false - xy: 915, 547 + xy: 1723, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit rotate: false - xy: 1299, 1359 + xy: 919, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-arrow rotate: false - xy: 1309, 1325 + xy: 911, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-arrow rotate: false - xy: 1309, 1325 + xy: 911, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-bridge rotate: false - xy: 1756, 1379 + xy: 953, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-end rotate: false - xy: 1790, 1379 + xy: 945, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom rotate: false - xy: 951, 1091 + xy: 1047, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-0 rotate: false - xy: 711, 885 + xy: 1089, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-1 rotate: false - xy: 711, 851 + xy: 1081, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-2 rotate: false - xy: 711, 817 + xy: 1123, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-3 rotate: false - xy: 711, 783 + xy: 1115, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-4 rotate: false - xy: 711, 749 + xy: 1157, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-5 rotate: false - xy: 711, 715 + xy: 1149, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-6 rotate: false - xy: 711, 681 + xy: 1191, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-0 rotate: false - xy: 745, 859 + xy: 1217, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-1 rotate: false - xy: 745, 825 + xy: 1259, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-2 rotate: false - xy: 745, 791 + xy: 1251, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-3 rotate: false - xy: 745, 757 + xy: 1293, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-4 rotate: false - xy: 745, 723 + xy: 1285, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-5 rotate: false - xy: 745, 689 + xy: 1327, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-6 rotate: false - xy: 745, 655 + xy: 1319, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-junction rotate: false - xy: 1615, 1320 + xy: 1247, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-bottom rotate: false - xy: 1683, 1354 + xy: 1281, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-liquid rotate: false - xy: 1717, 1354 + xy: 1315, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-top rotate: false - xy: 1717, 1320 + xy: 1349, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-tank-bottom rotate: false - xy: 457, 949 + xy: 1199, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-liquid rotate: false - xy: 359, 753 + xy: 1297, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-top rotate: false - xy: 457, 851 + xy: 1297, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-pump rotate: false - xy: 1887, 1311 + xy: 1451, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit rotate: false - xy: 911, 1014 + xy: 974, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-arrow rotate: false - xy: 911, 980 + xy: 1008, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-bridge rotate: false - xy: 911, 946 + xy: 1042, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-end rotate: false - xy: 911, 1048 + xy: 1076, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-0 rotate: false - xy: 813, 779 + xy: 1689, 769 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-1 rotate: false - xy: 813, 745 + xy: 1655, 714 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-2 rotate: false - xy: 813, 711 + xy: 1689, 735 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-3 rotate: false - xy: 813, 677 + xy: 1689, 701 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-4 rotate: false - xy: 813, 643 + xy: 1654, 680 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-5 rotate: false - xy: 813, 609 + xy: 1688, 667 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-6 rotate: false - xy: 779, 925 + xy: 838, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump rotate: false - xy: 851, 1513 + xy: 253, 1135 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-pump rotate: false - xy: 983, 1447 - size: 64, 64 - orig: 64, 64 + xy: 131, 613 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 -alpha-mech-pad +alpha-dart-mech-pad rotate: false - xy: 1252, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -dart-ship-pad - rotate: false - xy: 1980, 1917 + xy: 919, 1397 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 delta-mech-pad rotate: false - xy: 726, 1843 + xy: 1183, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 glaive-ship-pad rotate: false - xy: 359, 949 + xy: 807, 1463 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 javelin-ship-pad rotate: false - xy: 1386, 1851 + xy: 1909, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 omega-mech-pad rotate: false - xy: 343, 459 + xy: 1787, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 tau-mech-pad rotate: false - xy: 719, 1183 + xy: 393, 1300 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 trident-ship-pad rotate: false - xy: 983, 1381 + xy: 319, 1102 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 battery rotate: false - xy: 1484, 1388 + xy: 1763, 997 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-large rotate: false - xy: 131, 66 + xy: 219, 1443 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 combustion-generator rotate: false - xy: 1995, 1388 + xy: 1013, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 combustion-generator-top rotate: false - xy: 843, 1017 + xy: 1055, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -fusion-reactor +differential-generator rotate: false - xy: 1, 1498 + xy: 1675, 1691 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +differential-generator-top + rotate: false + xy: 1773, 1691 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +impact-reactor + rotate: false + xy: 1102, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -fusion-reactor-bottom +impact-reactor-bottom rotate: false - xy: 334, 1831 + xy: 1232, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -fusion-reactor-light +impact-reactor-light rotate: false - xy: 1, 1238 + xy: 1492, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -fusion-reactor-plasma-0 +impact-reactor-plasma-0 rotate: false - xy: 1, 1108 + xy: 1622, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -fusion-reactor-plasma-1 +impact-reactor-plasma-1 rotate: false - xy: 1, 978 + xy: 1752, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -fusion-reactor-plasma-2 +impact-reactor-plasma-2 rotate: false - xy: 1, 848 + xy: 1882, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -fusion-reactor-plasma-3 +impact-reactor-plasma-3 rotate: false - xy: 1, 718 + xy: 526, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -fusion-reactor-top +impact-reactor-top rotate: false - xy: 1, 588 + xy: 656, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 power-node rotate: false - xy: 779, 785 + xy: 1450, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-node-large rotate: false - xy: 917, 1645 + xy: 1909, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 power-source rotate: false - xy: 779, 683 + xy: 1518, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-void rotate: false - xy: 779, 615 + xy: 1552, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 powerinfinite rotate: false - xy: 813, 881 + xy: 1586, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 powervoid rotate: false - xy: 813, 847 + xy: 1620, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rtg-generator rotate: false - xy: 983, 1645 + xy: 253, 1069 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rtg-generator-top rotate: false - xy: 881, 640 + xy: 1280, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel rotate: false - xy: 983, 649 + xy: 1727, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-large rotate: false - xy: 555, 1439 + xy: 155, 711 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 +surge-tower + rotate: false + xy: 583, 1350 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 thermal-generator rotate: false - xy: 851, 1315 + xy: 459, 1300 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thorium-reactor rotate: false - xy: 555, 1243 + xy: 131, 515 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-center rotate: false - xy: 555, 1145 + xy: 131, 417 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-lights rotate: false - xy: 555, 949 + xy: 131, 319 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 turbine-generator rotate: false - xy: 1115, 1513 + xy: 385, 1168 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-top rotate: false - xy: 719, 1051 + xy: 319, 1036 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 alloy-smelter rotate: false - xy: 131, 262 + xy: 219, 1541 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 alloy-smelter-top rotate: false - xy: 1186, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -arc-smelter - rotate: false - xy: 1384, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -arc-smelter-top - rotate: false - xy: 1450, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -silicon-smelter-top - rotate: false - xy: 1450, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -biomattercompressor - rotate: false - xy: 1516, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -biomattercompressor-frame0 - rotate: false - xy: 1582, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -biomattercompressor-frame1 - rotate: false - xy: 1648, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -biomattercompressor-frame2 - rotate: false - xy: 1714, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -biomattercompressor-liquid - rotate: false - xy: 1846, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -biomattercompressor-top - rotate: false - xy: 1912, 1983 - size: 64, 64 - orig: 64, 64 + xy: 1087, 1691 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 blast-mixer rotate: false - xy: 1978, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -centrifuge - rotate: false - xy: 726, 1909 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -centrifuge-liquid - rotate: false - xy: 792, 1909 + xy: 1983, 1779 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-bottom rotate: false - xy: 1188, 1917 + xy: 229, 513 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-liquid rotate: false - xy: 1320, 1917 + xy: 229, 381 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-top rotate: false - xy: 1386, 1917 + xy: 229, 315 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator rotate: false - xy: 1452, 1917 + xy: 229, 249 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-middle rotate: false - xy: 1584, 1917 + xy: 229, 117 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-top rotate: false - xy: 1650, 1917 + xy: 229, 51 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +graphite-press + rotate: false + xy: 1843, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 incinerator rotate: false - xy: 1075, 1197 + xy: 1591, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-source rotate: false - xy: 1279, 1121 + xy: 1009, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-void rotate: false - xy: 1377, 1320 + xy: 1111, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +kiln + rotate: false + xy: 1051, 1347 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +kiln-top + rotate: false + xy: 1117, 1363 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +silicon-smelter-top + rotate: false + xy: 1117, 1363 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 lavasmelter rotate: false - xy: 1547, 1354 + xy: 1213, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-source rotate: false - xy: 1785, 1345 + xy: 1383, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 melter rotate: false - xy: 1853, 1286 + xy: 1485, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -oilrefinery +multi-press rotate: false - xy: 1395, 1218 - size: 32, 32 - orig: 32, 32 + xy: 1493, 1495 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 phase-weaver rotate: false - xy: 917, 1777 + xy: 1249, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-bottom rotate: false - xy: 653, 1447 + xy: 1315, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-weave rotate: false - xy: 785, 1579 + xy: 1447, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor rotate: false - xy: 851, 1645 + xy: 1513, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor-top rotate: false - xy: 983, 1777 + xy: 1579, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pulverizer rotate: false - xy: 847, 915 + xy: 872, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulverizer-rotator rotate: false - xy: 847, 847 + xy: 940, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pyratite-mixer rotate: false - xy: 1049, 1777 + xy: 1975, 1251 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator rotate: false - xy: 949, 717 - size: 32, 32 - orig: 32, 32 + xy: 1447, 1231 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 separator-liquid rotate: false - xy: 949, 683 - size: 32, 32 - orig: 32, 32 + xy: 1513, 1231 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 silicon-smelter rotate: false - xy: 653, 1183 + xy: 1579, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 smelter rotate: false - xy: 983, 819 + xy: 1769, 861 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -solidifer +spore-press rotate: false - xy: 949, 581 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -container - rotate: false - xy: 924, 1909 + xy: 1843, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -core +spore-press-frame0 rotate: false - xy: 457, 1635 + xy: 1909, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press-frame1 + rotate: false + xy: 1975, 1185 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press-frame2 + rotate: false + xy: 319, 1368 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press-liquid + rotate: false + xy: 451, 1366 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press-top + rotate: false + xy: 517, 1366 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +container + rotate: false + xy: 1983, 1647 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +core-foundation + rotate: false + xy: 972, 1919 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +core-nucleus + rotate: false + xy: 1, 1235 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +core-shard + rotate: false + xy: 1283, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -core-open +core-shard-top rotate: false - xy: 359, 1439 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -core-top - rotate: false - xy: 457, 1537 + xy: 1381, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad rotate: false - xy: 261, 753 + xy: 1101, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 sortedunloader rotate: false - xy: 983, 581 + xy: 1727, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 unloader rotate: false - xy: 787, 371 + xy: 1885, 1037 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 vault rotate: false - xy: 555, 655 + xy: 131, 25 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -block-1 +arc-heat rotate: false - xy: 1199, 1279 + xy: 2012, 1955 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-1-top +block-1 rotate: false - xy: 1191, 1245 + xy: 851, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-2 rotate: false - xy: 594, 1870 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -block-2-top - rotate: false - xy: 660, 1909 + xy: 1983, 1713 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-3 rotate: false - xy: 261, 1439 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -block-3-top - rotate: false - xy: 359, 1537 + xy: 1185, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-4 rotate: false - xy: 1, 1628 + xy: 323, 1628 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -block-4-top - rotate: false - xy: 204, 1831 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -arc - rotate: false - xy: 1382, 1388 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -arc-heat - rotate: false - xy: 1416, 1388 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cyclone - rotate: false - xy: 261, 1243 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -duo - rotate: false - xy: 362, 43 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -fuse - rotate: false - xy: 261, 949 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -hail - rotate: false - xy: 668, 41 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 hail-heat rotate: false - xy: 1223, 1359 + xy: 526, 1919 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -lancer - rotate: false - xy: 1518, 1851 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 lancer-heat rotate: false - xy: 1584, 1851 + xy: 1249, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -meltdown - rotate: false - xy: 1, 458 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 meltdown-heat rotate: false - xy: 1, 328 + xy: 916, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -ripple - rotate: false - xy: 441, 361 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 ripple-heat rotate: false - xy: 555, 1733 + xy: 163, 1299 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -salvo - rotate: false - xy: 851, 1447 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 salvo-heat rotate: false - xy: 917, 1513 + xy: 919, 1331 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-panel-left rotate: false - xy: 1049, 1645 + xy: 1051, 1281 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-panel-right rotate: false - xy: 1115, 1711 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -scatter - rotate: false - xy: 949, 853 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scorch - rotate: false - xy: 915, 785 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scorch-shoot - rotate: false - xy: 949, 819 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spectre - rotate: false - xy: 131, 718 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -swarmer - rotate: false - xy: 1115, 1645 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -wave - rotate: false - xy: 719, 985 + xy: 1117, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wave-liquid rotate: false - xy: 851, 1117 + xy: 451, 970 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -command-center +crawler-factory rotate: false - xy: 858, 1909 + xy: 1983, 1515 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory rotate: false - xy: 1716, 1917 + xy: 1983, 1515 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phantom-factory rotate: false - xy: 1716, 1917 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -reconstructor - rotate: false - xy: 1716, 1917 + xy: 1983, 1515 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spirit-factory rotate: false - xy: 1716, 1917 + xy: 1983, 1515 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith-factory rotate: false - xy: 1716, 1917 + xy: 1983, 1515 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +crawler-factory-top + rotate: false + xy: 229, 645 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +crawler-factory-top-open + rotate: false + xy: 229, 579 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory-top rotate: false - xy: 1848, 1917 + xy: 1051, 1413 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory-top-open rotate: false - xy: 1914, 1917 + xy: 1117, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-factory rotate: false - xy: 457, 1341 + xy: 1871, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fortress-factory-top rotate: false - xy: 359, 1145 + xy: 513, 1432 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory-top rotate: false - xy: 359, 1145 + xy: 513, 1432 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 titan-factory-top rotate: false - xy: 359, 1145 + xy: 513, 1432 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fortress-factory-top-open rotate: false - xy: 457, 1243 + xy: 611, 1561 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory-top-open rotate: false - xy: 457, 1243 + xy: 611, 1561 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 titan-factory-top-open rotate: false - xy: 457, 1243 + xy: 611, 1561 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory rotate: false - xy: 457, 1145 + xy: 709, 1463 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 phantom-factory-top rotate: false - xy: 653, 1513 + xy: 1975, 1317 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phantom-factory-top-open rotate: false - xy: 719, 1579 + xy: 1117, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -reconstructor-open +repair-point-base rotate: false - xy: 785, 1447 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -repair-point - rotate: false - xy: 847, 745 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -repair-point-turret - rotate: false - xy: 847, 677 + xy: 1042, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 revenant-factory rotate: false - xy: 131, 1238 + xy: 1176, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 revenant-factory-top rotate: false - xy: 131, 978 + xy: 1436, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 revenant-factory-top-open rotate: false - xy: 131, 848 + xy: 1566, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spirit-factory-top rotate: false - xy: 851, 1381 + xy: 1711, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spirit-factory-top-open rotate: false - xy: 917, 1447 + xy: 1777, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 titan-factory rotate: false - xy: 555, 851 + xy: 131, 221 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 wraith-factory-top rotate: false - xy: 983, 1249 + xy: 385, 838 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith-factory-top-open rotate: false - xy: 1049, 1315 + xy: 451, 904 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 copper-wall rotate: false - xy: 877, 957 + xy: 1693, 837 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-large rotate: false - xy: 1056, 1909 + xy: 1983, 1581 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door rotate: false - xy: 545, 77 + xy: 1013, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 door-large rotate: false - xy: 990, 1843 + xy: 1315, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-large-open rotate: false - xy: 1122, 1843 + xy: 1381, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-open rotate: false - xy: 328, 43 + xy: 1081, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall rotate: false - xy: 979, 1023 + xy: 1246, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-large rotate: false - xy: 785, 1645 + xy: 1183, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +scrap-wall-gigantic + rotate: false + xy: 1826, 1789 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +scrap-wall-huge1 + rotate: false + xy: 155, 1005 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-huge2 + rotate: false + xy: 155, 907 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-huge3 + rotate: false + xy: 155, 809 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-large1 + rotate: false + xy: 1183, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-large2 + rotate: false + xy: 1249, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-large3 + rotate: false + xy: 1315, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-large4 + rotate: false + xy: 1381, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall1 + rotate: false + xy: 1348, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall2 + rotate: false + xy: 1382, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall3 + rotate: false + xy: 1416, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall4 + rotate: false + xy: 1450, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall5 + rotate: false + xy: 1450, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 surge-wall rotate: false - xy: 1017, 776 + xy: 1722, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall-large rotate: false - xy: 983, 1513 + xy: 261, 1302 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thorium-wall rotate: false - xy: 949, 513 + xy: 1791, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-wall-large rotate: false - xy: 1115, 1579 + xy: 327, 1234 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +thruster + rotate: false + xy: 713, 1659 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 titanium-wall rotate: false - xy: 1051, 470 + xy: 1859, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-large rotate: false - xy: 851, 1249 + xy: 319, 1168 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -beam - rotate: false - xy: 2038, 1801 - size: 4, 48 - orig: 4, 48 - offset: 0, 0 - index: -1 -beam-end - rotate: false - xy: 668, 1975 - size: 72, 72 - orig: 72, 72 - offset: 0, 0 - index: -1 bullet rotate: false - xy: 204, 1777 + xy: 295, 544 size: 52, 52 orig: 52, 52 offset: 0, 0 index: -1 bullet-back rotate: false - xy: 653, 575 + xy: 295, 490 size: 52, 52 orig: 52, 52 offset: 0, 0 index: -1 casing rotate: false - xy: 1133, 1145 + xy: 1041, 1313 size: 8, 16 orig: 8, 16 offset: 0, 0 index: -1 -command-attack - rotate: false - xy: 843, 983 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -command-idle - rotate: false - xy: 877, 1025 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -command-patrol - rotate: false - xy: 877, 991 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -command-retreat - rotate: false - xy: 917, 1091 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -enemyarrow - rotate: false - xy: 464, 47 - size: 32, 28 - orig: 32, 28 - offset: 0, 0 - index: -1 error rotate: false - xy: 703, 525 + xy: 675, 1000 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 laser rotate: false - xy: 1155, 679 + xy: 2035, 860 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 laser-end rotate: false - xy: 816, 1975 - size: 72, 72 - orig: 72, 72 - offset: 0, 0 - index: -1 -laserfull - rotate: false - xy: 890, 1975 + xy: 697, 1389 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 minelaser rotate: false - xy: 2043, 1218 + xy: 2041, 1399 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 minelaser-end rotate: false - xy: 964, 1975 + xy: 771, 1389 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 missile rotate: false - xy: 1767, 1413 + xy: 1951, 1114 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 missile-back rotate: false - xy: 1805, 1413 + xy: 1989, 1118 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 scale_marker rotate: false - xy: 1101, 1251 + xy: 517, 1228 size: 4, 4 orig: 4, 4 offset: 0, 0 index: -1 scorch1 rotate: false - xy: 1081, 993 + xy: 445, 362 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch2 rotate: false - xy: 1111, 1027 + xy: 445, 260 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch3 rotate: false - xy: 1141, 1041 + xy: 445, 158 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch4 rotate: false - xy: 1171, 1041 + xy: 1927, 691 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch5 rotate: false - xy: 1201, 1041 + xy: 453, 598 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 shell rotate: false - xy: 1919, 1413 + xy: 1717, 943 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 shell-back rotate: false - xy: 1957, 1413 + xy: 1713, 905 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 shot rotate: false - xy: 949, 615 + xy: 1688, 633 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 transfer rotate: false - xy: 1231, 1081 + xy: 2035, 810 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 transfer-arrow rotate: false - xy: 787, 439 + xy: 1858, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 transfer-end rotate: false - xy: 1038, 1975 + xy: 845, 1389 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 -alloy-smelter-icon-full - rotate: false - xy: 131, 164 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 alloy-smelter-icon-large rotate: false - xy: 210, 16 + xy: 229, 1 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alloy-smelter-icon-medium rotate: false - xy: 1265, 1359 + xy: 691, 1205 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 alloy-smelter-icon-small rotate: false - xy: 1075, 1231 + xy: 1091, 1255 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -alpha-mech-pad-icon-full +alpha-dart-mech-pad-icon-large rotate: false - xy: 1318, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -alpha-mech-pad-icon-large - rotate: false - xy: 1115, 1281 + xy: 279, 1 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -alpha-mech-pad-icon-medium +alpha-dart-mech-pad-icon-medium rotate: false - xy: 1348, 1388 + xy: 575, 894 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -alpha-mech-pad-icon-small +alpha-dart-mech-pad-icon-small rotate: false - xy: 2023, 1294 + xy: 583, 1633 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -arc-icon-full +arc rotate: false - xy: 1450, 1388 + xy: 2012, 1989 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -arc-icon-medium +arc-icon-full rotate: false - xy: 1450, 1388 + xy: 2012, 1921 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 arc-icon-large rotate: false - xy: 229, 310 + xy: 295, 290 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 arc-icon-small rotate: false - xy: 2023, 1268 + xy: 1956, 1819 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -battery-icon-full - rotate: false - xy: 1518, 1388 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -battery-icon-medium - rotate: false - xy: 1518, 1388 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 battery-icon-large rotate: false - xy: 229, 210 + xy: 295, 182 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 battery-icon-small rotate: false - xy: 855, 481 + xy: 295, 56 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -battery-large-icon-full - rotate: false - xy: 261, 1733 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 battery-large-icon-large rotate: false - xy: 229, 160 + xy: 295, 132 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 battery-large-icon-medium rotate: false - xy: 1552, 1388 + xy: 1755, 963 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-large-icon-small rotate: false - xy: 779, 589 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -biomattercompressor-icon-full - rotate: false - xy: 1780, 1983 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -biomattercompressor-icon-large - rotate: false - xy: 229, 110 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -biomattercompressor-icon-medium - rotate: false - xy: 1586, 1388 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -biomattercompressor-icon-small - rotate: false - xy: 787, 563 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -blackrock-icon-full - rotate: false - xy: 1654, 1388 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -blackrock-icon-medium - rotate: false - xy: 1654, 1388 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -blackrock-icon-large - rotate: false - xy: 279, 311 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -blackrock-icon-small - rotate: false - xy: 787, 537 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -blackstone-icon-full - rotate: false - xy: 1165, 1279 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -blackstone-icon-medium - rotate: false - xy: 1165, 1279 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -blackstone-icon-large - rotate: false - xy: 279, 261 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -blackstone-icon-small - rotate: false - xy: 787, 511 + xy: 891, 1363 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 blast-drill-icon-full rotate: false - xy: 359, 1733 - size: 96, 96 - orig: 96, 96 + xy: 1, 471 + size: 128, 128 + orig: 128, 128 offset: 0, 0 index: -1 blast-drill-icon-large rotate: false - xy: 279, 211 + xy: 295, 82 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 blast-drill-icon-medium rotate: false - xy: 1157, 1245 + xy: 1755, 929 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 blast-drill-icon-small rotate: false - xy: 1085, 866 + xy: 1926, 665 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -blast-mixer-icon-full - rotate: false - xy: 594, 1936 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 blast-mixer-icon-large rotate: false - xy: 329, 261 + xy: 509, 830 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 blast-mixer-icon-medium rotate: false - xy: 1207, 1313 + xy: 1751, 895 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 blast-mixer-icon-small rotate: false - xy: 855, 455 + xy: 1919, 1039 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -bridge-conduit-icon-full - rotate: false - xy: 1824, 1379 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -bridge-conduit-icon-medium - rotate: false - xy: 1824, 1379 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 bridge-conduit-icon-large rotate: false - xy: 329, 211 + xy: 559, 830 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 bridge-conduit-icon-small rotate: false - xy: 881, 478 + xy: 453, 572 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -bridge-conveyor-icon-full - rotate: false - xy: 260, 32 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -bridge-conveyor-icon-medium - rotate: false - xy: 260, 32 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 bridge-conveyor-icon-large rotate: false - xy: 379, 261 + xy: 353, 564 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 bridge-conveyor-icon-small rotate: false - xy: 753, 527 + xy: 1956, 1793 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -combustion-generator-icon-full +char-icon-large rotate: false - xy: 1858, 1354 - size: 32, 32 - orig: 32, 32 + xy: 349, 464 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 -combustion-generator-icon-medium +char-icon-small rotate: false - xy: 1858, 1354 - size: 32, 32 - orig: 32, 32 + xy: 1922, 1013 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +cliffs-icon-large + rotate: false + xy: 345, 414 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cliffs-icon-small + rotate: false + xy: 1886, 977 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 combustion-generator-icon-large rotate: false - xy: 279, 111 + xy: 345, 364 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 combustion-generator-icon-small rotate: false - xy: 855, 429 + xy: 1886, 951 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 conduit-icon-full rotate: false - xy: 711, 647 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-icon-medium - rotate: false - xy: 711, 647 + xy: 1183, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-icon-large rotate: false - xy: 329, 161 + xy: 345, 314 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 conduit-icon-small rotate: false - xy: 881, 452 + xy: 1950, 1088 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -container-icon-full - rotate: false - xy: 990, 1909 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 container-icon-large rotate: false - xy: 379, 211 + xy: 345, 264 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 container-icon-medium rotate: false - xy: 711, 613 + xy: 1361, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 container-icon-small rotate: false - xy: 1085, 814 + xy: 1949, 1062 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -conveyor-icon-full - rotate: false - xy: 1259, 1189 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-icon-medium - rotate: false - xy: 1259, 1189 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 conveyor-icon-large rotate: false - xy: 429, 261 + xy: 345, 214 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 conveyor-icon-small rotate: false - xy: 855, 403 + xy: 1976, 1088 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -copper-wall-icon-full - rotate: false - xy: 745, 587 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -copper-wall-icon-medium - rotate: false - xy: 745, 587 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 copper-wall-icon-large rotate: false - xy: 479, 311 + xy: 345, 164 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 copper-wall-icon-small rotate: false - xy: 881, 426 + xy: 1975, 1062 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -copper-wall-large-icon-full - rotate: false - xy: 1122, 1909 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 copper-wall-large-icon-large rotate: false - xy: 329, 111 + xy: 345, 114 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 copper-wall-large-icon-medium rotate: false - xy: 753, 553 + xy: 1817, 1097 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-large-icon-small rotate: false - xy: 1085, 788 + xy: 2002, 1092 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -core-icon-full +core-foundation-icon-large rotate: false - xy: 261, 1341 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -core-icon-large - rotate: false - xy: 379, 161 + xy: 345, 64 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -core-icon-medium +core-foundation-icon-medium rotate: false - xy: 975, 1149 + xy: 1851, 1105 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -core-icon-small +core-foundation-icon-small rotate: false - xy: 855, 377 + xy: 1805, 1034 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -craters-icon-full +core-nucleus-icon-large rotate: false - xy: 1892, 1345 + xy: 329, 14 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +core-nucleus-icon-medium + rotate: false + xy: 1885, 1105 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -craters-icon-medium +core-nucleus-icon-small rotate: false - xy: 1892, 1345 + xy: 77, 8 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +core-shard-icon-large + rotate: false + xy: 379, 14 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +core-shard-icon-medium + rotate: false + xy: 1797, 997 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +core-shard-icon-small + rotate: false + xy: 103, 11 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 craters-icon-large rotate: false - xy: 429, 211 + xy: 641, 1300 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 craters-icon-small rotate: false - xy: 881, 400 + xy: 1922, 987 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +crawler-factory-icon-full + rotate: false + xy: 1983, 1449 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +crawler-factory-icon-large + rotate: false + xy: 451, 796 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-factory-icon-medium + rotate: false + xy: 1789, 963 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +crawler-factory-icon-small + rotate: false + xy: 1912, 961 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 cryofluidmixer-icon-full rotate: false - xy: 1254, 1917 + xy: 229, 447 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-icon-large rotate: false - xy: 479, 261 + xy: 551, 780 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 cryofluidmixer-icon-medium rotate: false - xy: 1926, 1345 + xy: 1789, 929 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cryofluidmixer-icon-small rotate: false - xy: 1085, 762 + xy: 1938, 961 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 cultivator-icon-full rotate: false - xy: 1518, 1917 + xy: 229, 183 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-icon-large rotate: false - xy: 529, 311 + xy: 450, 746 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 cultivator-icon-medium rotate: false - xy: 1960, 1345 + xy: 1785, 895 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cultivator-icon-small rotate: false - xy: 855, 351 + xy: 1912, 935 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 +cyclone + rotate: false + xy: 1479, 1691 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 cyclone-icon-full rotate: false - xy: 359, 1341 + xy: 1577, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cyclone-icon-large rotate: false - xy: 379, 111 + xy: 500, 730 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 cyclone-icon-medium rotate: false - xy: 1994, 1354 + xy: 843, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cyclone-icon-small rotate: false - xy: 881, 374 + xy: 1938, 935 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 dagger-factory-icon-full rotate: false - xy: 1782, 1917 + xy: 985, 1397 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory-icon-large rotate: false - xy: 529, 261 + xy: 575, 1128 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-factory-icon-medium rotate: false - xy: 1994, 1320 + xy: 877, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dagger-factory-icon-small rotate: false - xy: 1085, 736 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dart-ship-pad-icon-full - rotate: false - xy: 660, 1843 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -dart-ship-pad-icon-large - rotate: false - xy: 479, 161 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dart-ship-pad-icon-medium - rotate: false - xy: 273, 76 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dart-ship-pad-icon-small - rotate: false - xy: 1085, 710 + xy: 1926, 639 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 deepwater-icon-large rotate: false - xy: 529, 211 + xy: 575, 978 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 deepwater-icon-small rotate: false - xy: 1085, 684 + xy: 1922, 613 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -delta-mech-pad-icon-full - rotate: false - xy: 792, 1843 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 delta-mech-pad-icon-large rotate: false - xy: 579, 211 + xy: 625, 1050 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech-pad-icon-medium rotate: false - xy: 341, 77 + xy: 911, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 delta-mech-pad-icon-small rotate: false - xy: 1085, 658 + xy: 453, 546 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -dirt-icon-full +differential-generator-icon-large rotate: false - xy: 477, 77 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dirt-icon-medium - rotate: false - xy: 477, 77 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dirt-icon-large - rotate: false - xy: 529, 111 + xy: 625, 1000 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -dirt-icon-small +differential-generator-icon-medium rotate: false - xy: 1085, 632 + xy: 945, 829 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +differential-generator-icon-small + rotate: false + xy: 449, 520 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -distributor-icon-full - rotate: false - xy: 924, 1843 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 distributor-icon-large rotate: false - xy: 579, 111 + xy: 625, 950 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 distributor-icon-medium rotate: false - xy: 511, 77 + xy: 979, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 distributor-icon-small rotate: false - xy: 1085, 606 + xy: 449, 494 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -door-icon-full - rotate: false - xy: 579, 77 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -door-icon-medium - rotate: false - xy: 579, 77 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 door-icon-large rotate: false - xy: 687, 475 + xy: 625, 900 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 door-icon-small rotate: false - xy: 1085, 580 + xy: 449, 468 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -door-large-icon-full - rotate: false - xy: 1056, 1843 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 door-large-icon-large rotate: false - xy: 687, 425 + xy: 675, 1150 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 door-large-icon-medium rotate: false - xy: 294, 42 + xy: 1047, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 door-large-icon-small rotate: false - xy: 1085, 554 + xy: 1952, 665 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -duo-icon-full +dunerocks-icon-large rotate: false - xy: 396, 43 + xy: 675, 1100 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dunerocks-icon-small + rotate: false + xy: 1952, 639 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +duo + rotate: false + xy: 1115, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -duo-icon-medium +duo-icon-full rotate: false - xy: 396, 43 + xy: 1149, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 duo-icon-large rotate: false - xy: 687, 375 + xy: 675, 1050 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 duo-icon-small rotate: false - xy: 1085, 528 + xy: 1948, 613 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -force-projector-icon-full - rotate: false - xy: 261, 1145 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 force-projector-icon-large rotate: false - xy: 737, 425 + xy: 403, 664 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 force-projector-icon-medium rotate: false - xy: 498, 43 + xy: 1217, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 force-projector-icon-small rotate: false - xy: 1085, 502 + xy: 479, 572 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 fortress-factory-icon-full rotate: false - xy: 261, 1047 + xy: 513, 1530 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fortress-factory-icon-large rotate: false - xy: 737, 375 + xy: 403, 614 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 fortress-factory-icon-medium rotate: false - xy: 532, 43 + xy: 1251, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 fortress-factory-icon-small rotate: false - xy: 1085, 476 + xy: 479, 546 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 +fuse + rotate: false + xy: 611, 1463 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 fuse-icon-full rotate: false - xy: 359, 1047 + xy: 709, 1561 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fuse-icon-large rotate: false - xy: 637, 325 + xy: 403, 564 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 fuse-icon-medium rotate: false - xy: 566, 43 + xy: 1285, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 fuse-icon-small rotate: false - xy: 1110, 963 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -fusion-reactor-icon-full - rotate: false - xy: 1, 1368 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -fusion-reactor-icon-large - rotate: false - xy: 687, 325 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -fusion-reactor-icon-medium - rotate: false - xy: 294, 8 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -fusion-reactor-icon-small - rotate: false - xy: 881, 348 + xy: 475, 520 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ghoul-factory-icon-full rotate: false - xy: 261, 851 + xy: 807, 1561 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory-icon-large rotate: false - xy: 737, 325 + xy: 399, 514 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ghoul-factory-icon-medium rotate: false - xy: 464, 13 + xy: 1319, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ghoul-factory-icon-small rotate: false - xy: 907, 453 + xy: 475, 494 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -glaive-ship-pad-icon-full - rotate: false - xy: 457, 1047 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 glaive-ship-pad-icon-large rotate: false - xy: 629, 275 + xy: 399, 464 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 glaive-ship-pad-icon-medium rotate: false - xy: 498, 9 + xy: 1353, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 glaive-ship-pad-icon-small rotate: false - xy: 933, 453 + xy: 475, 468 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -grass-icon-full +graphite-press-icon-large rotate: false - xy: 634, 41 + xy: 395, 414 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +graphite-press-icon-medium + rotate: false + xy: 1387, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -grass-icon-medium +graphite-press-icon-small rotate: false - xy: 634, 41 - size: 32, 32 - orig: 32, 32 + xy: 475, 442 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 grass-icon-large rotate: false - xy: 629, 225 + xy: 395, 364 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 grass-icon-small rotate: false - xy: 907, 427 + xy: 475, 416 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -hail-icon-full +hail rotate: false - xy: 702, 41 + xy: 1421, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -hail-icon-medium +hail-icon-full rotate: false - xy: 702, 41 + xy: 1455, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hail-icon-large rotate: false - xy: 629, 175 + xy: 395, 314 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 hail-icon-small rotate: false - xy: 959, 453 + xy: 475, 390 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ice-icon-full +holostone-icon-large rotate: false - xy: 668, 7 - size: 32, 32 - orig: 32, 32 + xy: 395, 214 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 -ice-icon-medium +holostone-icon-small rotate: false - xy: 668, 7 - size: 32, 32 - orig: 32, 32 + xy: 475, 364 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +hotrock-icon-large + rotate: false + xy: 395, 164 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +hotrock-icon-small + rotate: false + xy: 475, 338 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 ice-icon-large rotate: false - xy: 729, 275 + xy: 395, 114 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ice-icon-small rotate: false - xy: 907, 401 + xy: 475, 312 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -icerock-icon-full +ice-snow-icon-large rotate: false - xy: 770, 19 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icerock-icon-medium - rotate: false - xy: 770, 19 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icerock-icon-large - rotate: false - xy: 679, 175 + xy: 395, 64 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -icerock-icon-small +ice-snow-icon-small rotate: false - xy: 933, 427 + xy: 475, 286 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -incinerator-icon-full +icerocks-icon-large rotate: false - xy: 1109, 1197 + xy: 429, 14 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icerocks-icon-small + rotate: false + xy: 475, 260 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ignarock-icon-large + rotate: false + xy: 659, 842 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ignarock-icon-small + rotate: false + xy: 475, 156 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +impact-reactor-icon-full + rotate: false + xy: 1362, 1919 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-icon-large + rotate: false + xy: 609, 800 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +impact-reactor-icon-medium + rotate: false + xy: 1557, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -incinerator-icon-medium +impact-reactor-icon-small rotate: false - xy: 1109, 1197 - size: 32, 32 - orig: 32, 32 + xy: 474, 130 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 incinerator-icon-large rotate: false - xy: 679, 125 + xy: 659, 792 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 incinerator-icon-small rotate: false - xy: 959, 427 + xy: 474, 104 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -item-source-icon-full +item-blast-compound-medium rotate: false - xy: 1313, 1121 - size: 32, 32 - orig: 32, 32 + xy: 501, 478 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 -item-source-icon-medium +item-blast-compound-small rotate: false - xy: 1313, 1121 - size: 32, 32 - orig: 32, 32 + xy: 1585, 641 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-blast-compound-xlarge + rotate: false + xy: 649, 1374 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-coal-medium + rotate: false + xy: 501, 452 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-coal-small + rotate: false + xy: 1603, 641 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-coal-xlarge + rotate: false + xy: 219, 1401 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-copper-medium + rotate: false + xy: 501, 426 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-copper-small + rotate: false + xy: 1621, 641 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-copper-xlarge + rotate: false + xy: 261, 1401 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-graphite-medium + rotate: false + xy: 501, 400 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-graphite-small + rotate: false + xy: 427, 755 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-graphite-xlarge + rotate: false + xy: 725, 897 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-lead-medium + rotate: false + xy: 501, 374 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-lead-small + rotate: false + xy: 1886, 933 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-lead-xlarge + rotate: false + xy: 1675, 989 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-metaglass-medium + rotate: false + xy: 501, 348 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-metaglass-small + rotate: false + xy: 1887, 915 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-metaglass-xlarge + rotate: false + xy: 1725, 1039 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-phase-fabric-medium + rotate: false + xy: 501, 322 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-phase-fabric-small + rotate: false + xy: 1887, 897 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-phase-fabric-xlarge + rotate: false + xy: 1775, 1089 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-plastanium-medium + rotate: false + xy: 501, 296 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-plastanium-small + rotate: false + xy: 1831, 1045 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-plastanium-xlarge + rotate: false + xy: 1825, 1139 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-pyratite-medium + rotate: false + xy: 501, 270 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-pyratite-small + rotate: false + xy: 2030, 1903 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-pyratite-xlarge + rotate: false + xy: 767, 897 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-sand-medium + rotate: false + xy: 501, 244 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-sand-small + rotate: false + xy: 2030, 1885 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-sand-xlarge + rotate: false + xy: 1675, 947 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-scrap-medium + rotate: false + xy: 501, 218 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-scrap-small + rotate: false + xy: 2030, 1867 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-scrap-xlarge + rotate: false + xy: 1867, 1139 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-silicon-medium + rotate: false + xy: 501, 192 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-silicon-small + rotate: false + xy: 2030, 1849 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-silicon-xlarge + rotate: false + xy: 809, 897 + size: 40, 40 + orig: 40, 40 offset: 0, 0 index: -1 item-source-icon-large rotate: false - xy: 729, 175 + xy: 709, 842 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-source-icon-small rotate: false - xy: 907, 349 + xy: 501, 166 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -item-void-icon-full +item-spore-pod-medium rotate: false - xy: 1411, 1354 - size: 32, 32 - orig: 32, 32 + xy: 474, 78 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 -item-void-icon-medium +item-spore-pod-small rotate: false - xy: 1411, 1354 - size: 32, 32 - orig: 32, 32 + xy: 2027, 1167 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-spore-pod-xlarge + rotate: false + xy: 1909, 1139 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-surge-alloy-medium + rotate: false + xy: 501, 140 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-surge-alloy-small + rotate: false + xy: 2027, 1149 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-surge-alloy-xlarge + rotate: false + xy: 759, 855 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-thorium-medium + rotate: false + xy: 500, 114 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-thorium-small + rotate: false + xy: 2027, 1131 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-thorium-xlarge + rotate: false + xy: 801, 855 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-titanium-medium + rotate: false + xy: 500, 88 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-titanium-small + rotate: false + xy: 129, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-titanium-xlarge + rotate: false + xy: 759, 813 + size: 40, 40 + orig: 40, 40 offset: 0, 0 index: -1 item-void-icon-large rotate: false - xy: 729, 125 + xy: 709, 792 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-void-icon-small rotate: false - xy: 933, 375 + xy: 500, 62 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -javelin-ship-pad-icon-full - rotate: false - xy: 1452, 1851 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 javelin-ship-pad-icon-large rotate: false - xy: 679, 75 + xy: 651, 742 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 javelin-ship-pad-icon-medium rotate: false - xy: 1411, 1320 + xy: 1111, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 javelin-ship-pad-icon-small rotate: false - xy: 959, 401 + xy: 479, 36 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -junction-icon-full - rotate: false - xy: 1445, 1320 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -junction-icon-medium - rotate: false - xy: 1445, 1320 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 junction-icon-large rotate: false - xy: 1188, 1801 + xy: 600, 700 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 junction-icon-small rotate: false - xy: 985, 427 + xy: 479, 10 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 +kiln-icon-large + rotate: false + xy: 650, 692 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +kiln-icon-medium + rotate: false + xy: 1145, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +kiln-icon-small + rotate: false + xy: 505, 36 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +lancer + rotate: false + xy: 1183, 1363 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 lancer-icon-full rotate: false - xy: 1650, 1851 + xy: 1315, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 lancer-icon-large rotate: false - xy: 1238, 1801 + xy: 700, 692 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 lancer-icon-medium rotate: false - xy: 1479, 1354 + xy: 1179, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 lancer-icon-small rotate: false - xy: 1114, 895 + xy: 505, 10 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 laser-drill-icon-full rotate: false - xy: 1782, 1851 - size: 64, 64 - orig: 64, 64 + xy: 905, 1463 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 laser-drill-icon-large rotate: false - xy: 1288, 1801 + xy: 751, 742 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 laser-drill-icon-medium rotate: false - xy: 1479, 1320 + xy: 1179, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 laser-drill-icon-small rotate: false - xy: 933, 349 + xy: 2002, 1066 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -launch-pad-icon-full - rotate: false - xy: 359, 851 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 launch-pad-icon-large rotate: false - xy: 1338, 1801 + xy: 750, 692 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 launch-pad-icon-medium rotate: false - xy: 1513, 1354 + xy: 1213, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 launch-pad-icon-small rotate: false - xy: 959, 375 + xy: 1974, 613 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -liquid-junction-icon-full - rotate: false - xy: 1649, 1354 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-junction-icon-medium - rotate: false - xy: 1649, 1354 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 liquid-junction-icon-large rotate: false - xy: 1438, 1801 + xy: 691, 1289 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-junction-icon-small rotate: false - xy: 985, 401 + xy: 427, 720 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-router-icon-full rotate: false - xy: 1683, 1320 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-router-icon-medium - rotate: false - xy: 1683, 1320 + xy: 1315, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-icon-large rotate: false - xy: 1488, 1801 + xy: 741, 1339 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-router-icon-small rotate: false - xy: 959, 349 + xy: 453, 720 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -liquid-source-icon-full - rotate: false - xy: 1819, 1345 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-source-icon-medium - rotate: false - xy: 1819, 1345 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 liquid-source-icon-large rotate: false - xy: 1538, 1801 + xy: 691, 1239 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-source-icon-small rotate: false - xy: 985, 375 + xy: 2001, 1040 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-tank-icon-full rotate: false - xy: 261, 655 + xy: 1199, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-icon-large rotate: false - xy: 1588, 1801 + xy: 791, 1339 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-tank-icon-medium rotate: false - xy: 1751, 1311 + xy: 1383, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-tank-icon-small rotate: false - xy: 985, 349 + xy: 1948, 1036 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 +magmarock-icon-large + rotate: false + xy: 741, 1289 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +magmarock-icon-small + rotate: false + xy: 1948, 1010 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mass-driver + rotate: false + xy: 1395, 1593 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 mass-driver-icon-full rotate: false - xy: 457, 753 + xy: 1493, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-driver-icon-large rotate: false - xy: 1638, 1801 + xy: 841, 1339 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mass-driver-icon-medium rotate: false - xy: 1819, 1311 + xy: 1417, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mass-driver-icon-small rotate: false - xy: 1011, 444 + xy: 1974, 1036 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 mech-icon-alpha-mech rotate: false - xy: 1688, 1801 + xy: 741, 1239 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-dart-ship rotate: false - xy: 1738, 1801 + xy: 791, 1289 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-delta-mech rotate: false - xy: 1788, 1801 + xy: 841, 1289 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-glaive-ship rotate: false - xy: 653, 861 + xy: 583, 1292 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mech-icon-javelin-ship rotate: false - xy: 1838, 1801 + xy: 791, 1239 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-omega-mech rotate: false - xy: 719, 927 + xy: 583, 1234 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mech-icon-tau-mech rotate: false - xy: 785, 993 + xy: 517, 1170 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mech-icon-trident-ship rotate: false - xy: 851, 1059 + xy: 517, 1112 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mechanical-drill-icon-full rotate: false - xy: 653, 1777 + xy: 1447, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-icon-large rotate: false - xy: 1888, 1801 + xy: 841, 1239 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mechanical-drill-icon-medium rotate: false - xy: 1853, 1320 + xy: 1451, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mechanical-drill-icon-small rotate: false - xy: 1011, 418 + xy: 1974, 1010 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -mechanical-pump-icon-full - rotate: false - xy: 1921, 1311 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -mechanical-pump-icon-medium - rotate: false - xy: 1921, 1311 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 mechanical-pump-icon-large rotate: false - xy: 1938, 1801 + xy: 891, 1281 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mechanical-pump-icon-small rotate: false - xy: 1037, 444 + xy: 2000, 1014 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 +meltdown + rotate: false + xy: 786, 1789 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 meltdown-icon-full rotate: false - xy: 1, 198 + xy: 1046, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 meltdown-icon-large rotate: false - xy: 1988, 1801 + xy: 941, 1281 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 meltdown-icon-medium rotate: false - xy: 1955, 1311 + xy: 1485, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 meltdown-icon-small rotate: false - xy: 1011, 392 + xy: 2000, 988 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -melter-icon-full - rotate: false - xy: 1887, 1277 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -melter-icon-medium - rotate: false - xy: 1887, 1277 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 melter-icon-large rotate: false - xy: 1181, 1751 + xy: 991, 1281 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 melter-icon-small rotate: false - xy: 1037, 418 + xy: 1964, 984 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -mend-projector-icon-full - rotate: false - xy: 719, 1711 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 mend-projector-icon-large rotate: false - xy: 1181, 1701 + xy: 891, 1231 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mend-projector-icon-medium rotate: false - xy: 1921, 1277 + xy: 1519, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mend-projector-icon-small rotate: false - xy: 1011, 366 + xy: 1964, 958 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -metalfloor-icon-full +metal-floor-2-icon-large rotate: false - xy: 1395, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metalfloor-icon-medium - rotate: false - xy: 1395, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metalfloor-icon-large - rotate: false - xy: 1231, 1751 + xy: 941, 1231 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -metalfloor-icon-small +metal-floor-2-icon-small rotate: false - xy: 1037, 392 + xy: 1964, 932 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-3-icon-large + rotate: false + xy: 991, 1231 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-3-icon-small + rotate: false + xy: 1990, 962 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-5-icon-large + rotate: false + xy: 1041, 1231 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-5-icon-small + rotate: false + xy: 1990, 936 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-damaged-icon-large + rotate: false + xy: 725, 1189 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-damaged-icon-small + rotate: false + xy: 2016, 962 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-icon-large + rotate: false + xy: 725, 1139 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-icon-small + rotate: false + xy: 2016, 936 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +multi-press-icon-large + rotate: false + xy: 775, 1189 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +multi-press-icon-medium + rotate: false + xy: 1519, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +multi-press-icon-small + rotate: false + xy: 1990, 910 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 oil-extractor-icon-full rotate: false - xy: 359, 557 + xy: 1591, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-icon-large rotate: false - xy: 1231, 1701 + xy: 725, 1089 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 oil-extractor-icon-medium rotate: false - xy: 1395, 1252 + xy: 1553, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 oil-extractor-icon-small rotate: false - xy: 1037, 366 + xy: 2016, 910 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -omega-mech-pad-icon-full - rotate: false - xy: 343, 361 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 omega-mech-pad-icon-large rotate: false - xy: 1281, 1751 + xy: 825, 1189 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 omega-mech-pad-icon-medium rotate: false - xy: 1429, 1286 + xy: 1553, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 omega-mech-pad-icon-small rotate: false - xy: 1063, 444 + xy: 526, 114 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-coal-blackstone-icon-large +ore-coal-holostone-icon-full rotate: false - xy: 1181, 1601 + xy: 1587, 795 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-holostone-icon-medium + rotate: false + xy: 1587, 795 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-holostone-icon-large + rotate: false + xy: 775, 1139 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-coal-blackstone-icon-small +ore-coal-holostone-icon-small rotate: false - xy: 1063, 418 + xy: 526, 88 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-coal-blackstone1 - rotate: false - xy: 1429, 1252 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-blackstone2 - rotate: false - xy: 1429, 1218 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-blackstone3 - rotate: false - xy: 1463, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-blackstone-icon-full - rotate: false - xy: 1463, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-blackstone-icon-medium - rotate: false - xy: 1463, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-grass-icon-large - rotate: false - xy: 1231, 1651 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-coal-grass-icon-small - rotate: false - xy: 1063, 392 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-coal-grass1 - rotate: false - xy: 1463, 1252 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-grass2 - rotate: false - xy: 1463, 1218 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-grass3 - rotate: false - xy: 1497, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-grass-icon-full - rotate: false - xy: 1497, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-grass-icon-medium - rotate: false - xy: 1497, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-ice-icon-large - rotate: false - xy: 1281, 1701 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-coal-ice-icon-small - rotate: false - xy: 1063, 366 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-coal-ice1 - rotate: false - xy: 1497, 1252 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-ice2 - rotate: false - xy: 1497, 1218 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-ice3 - rotate: false - xy: 1531, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-ice-icon-full - rotate: false - xy: 1531, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-ice-icon-medium - rotate: false - xy: 1531, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-sand-icon-large - rotate: false - xy: 1331, 1751 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-coal-sand-icon-small - rotate: false - xy: 855, 325 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-coal-sand1 - rotate: false - xy: 1531, 1252 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-sand2 - rotate: false - xy: 1531, 1218 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-sand3 - rotate: false - xy: 1565, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 ore-coal-sand-icon-full rotate: false - xy: 1565, 1286 + xy: 1587, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-coal-sand-icon-medium rotate: false - xy: 1565, 1286 + xy: 1587, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-snow-icon-large +ore-coal-sand-icon-large rotate: false - xy: 1181, 1551 + xy: 725, 1039 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-coal-snow-icon-small +ore-coal-sand-icon-small rotate: false - xy: 881, 322 + xy: 526, 62 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-coal-snow1 +ore-coal-stained-stone-icon-full rotate: false - xy: 1565, 1252 + xy: 1621, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-snow2 +ore-coal-stained-stone-icon-medium rotate: false - xy: 1565, 1218 + xy: 1621, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-snow3 +ore-coal-stained-stone-icon-large rotate: false - xy: 1599, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-snow-icon-full - rotate: false - xy: 1599, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-snow-icon-medium - rotate: false - xy: 1599, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-stone-icon-large - rotate: false - xy: 1231, 1601 + xy: 775, 1089 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-coal-stone-icon-small +ore-coal-stained-stone-icon-small rotate: false - xy: 907, 323 + xy: 531, 36 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-coal-stone1 +ore-coal-stained-stone-red-icon-full rotate: false - xy: 1599, 1252 + xy: 1621, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-stone2 +ore-coal-stained-stone-red-icon-medium rotate: false - xy: 1599, 1218 + xy: 1621, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-stone3 +ore-coal-stained-stone-red-icon-large rotate: false - xy: 1633, 1286 - size: 32, 32 - orig: 32, 32 + xy: 825, 1139 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-red-icon-small + rotate: false + xy: 531, 10 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 ore-coal-stone-icon-full rotate: false - xy: 1633, 1286 + xy: 1655, 782 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-coal-stone-icon-medium rotate: false - xy: 1633, 1286 + xy: 1655, 782 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-copper-blackstone-icon-large +ore-coal-stone-icon-large rotate: false - xy: 1281, 1651 + xy: 725, 989 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-copper-blackstone-icon-small +ore-coal-stone-icon-small rotate: false - xy: 933, 323 + xy: 483, 674 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-copper-blackstone1 +ore-copper-holostone-icon-full rotate: false - xy: 1633, 1252 + xy: 839, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-copper-blackstone2 +ore-copper-holostone-icon-medium rotate: false - xy: 1633, 1218 + xy: 839, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-copper-blackstone3 +ore-copper-holostone-icon-large rotate: false - xy: 1667, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-blackstone-icon-full - rotate: false - xy: 1667, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-blackstone-icon-medium - rotate: false - xy: 1667, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-grass-icon-large - rotate: false - xy: 1331, 1701 + xy: 775, 1039 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-copper-grass-icon-small +ore-copper-holostone-icon-small rotate: false - xy: 959, 323 + xy: 483, 648 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-copper-grass1 - rotate: false - xy: 1667, 1252 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-grass2 - rotate: false - xy: 1667, 1218 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-grass3 - rotate: false - xy: 1701, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-grass-icon-full - rotate: false - xy: 1701, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-grass-icon-medium - rotate: false - xy: 1701, 1286 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-ice-icon-large - rotate: false - xy: 1381, 1751 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-copper-ice-icon-small - rotate: false - xy: 985, 323 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-copper-ice1 - rotate: false - xy: 1701, 1252 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-ice2 - rotate: false - xy: 1701, 1218 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-ice3 - rotate: false - xy: 1735, 1277 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-ice-icon-full - rotate: false - xy: 1735, 1277 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-ice-icon-medium - rotate: false - xy: 1735, 1277 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-sand-icon-large - rotate: false - xy: 1181, 1501 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-copper-sand-icon-small - rotate: false - xy: 1011, 340 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-copper-sand1 - rotate: false - xy: 1735, 1243 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-sand2 - rotate: false - xy: 1769, 1277 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-sand3 - rotate: false - xy: 1769, 1243 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 ore-copper-sand-icon-full rotate: false - xy: 1769, 1243 + xy: 873, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-copper-sand-icon-medium rotate: false - xy: 1769, 1243 + xy: 873, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-copper-snow-icon-large +ore-copper-sand-icon-large rotate: false - xy: 1231, 1551 + xy: 825, 1089 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-copper-snow-icon-small +ore-copper-sand-icon-small rotate: false - xy: 1037, 340 + xy: 483, 622 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-copper-snow1 +ore-copper-stained-stone-icon-full rotate: false - xy: 1803, 1277 + xy: 907, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-copper-snow2 +ore-copper-stained-stone-icon-medium rotate: false - xy: 1803, 1243 + xy: 907, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-copper-snow3 +ore-copper-stained-stone-icon-large rotate: false - xy: 1735, 1209 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-snow-icon-full - rotate: false - xy: 1735, 1209 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-snow-icon-medium - rotate: false - xy: 1735, 1209 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stone-icon-large - rotate: false - xy: 1281, 1601 + xy: 725, 939 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-copper-stone-icon-small +ore-copper-stained-stone-icon-small rotate: false - xy: 1063, 340 + xy: 1931, 909 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-copper-stone1 +ore-copper-stained-stone-red-icon-full rotate: false - xy: 1769, 1209 + xy: 941, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-copper-stone2 +ore-copper-stained-stone-red-icon-medium rotate: false - xy: 1803, 1209 + xy: 941, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-copper-stone3 +ore-copper-stained-stone-red-icon-large rotate: false - xy: 1837, 1252 - size: 32, 32 - orig: 32, 32 + xy: 775, 989 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-red-icon-small + rotate: false + xy: 1905, 909 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 ore-copper-stone-icon-full rotate: false - xy: 1837, 1252 + xy: 975, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-copper-stone-icon-medium rotate: false - xy: 1837, 1252 + xy: 975, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-lead-blackstone-icon-large +ore-copper-stone-icon-large rotate: false - xy: 1331, 1651 + xy: 825, 1039 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-lead-blackstone-icon-small +ore-copper-stone-icon-small rotate: false - xy: 847, 299 + xy: 1957, 906 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-lead-blackstone1 +ore-lead-holostone-icon-full rotate: false - xy: 1837, 1218 + xy: 1009, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-lead-blackstone2 +ore-lead-holostone-icon-medium rotate: false - xy: 1871, 1243 + xy: 1009, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-lead-blackstone3 +ore-lead-holostone-icon-large rotate: false - xy: 1905, 1243 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-blackstone-icon-full - rotate: false - xy: 1905, 1243 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-blackstone-icon-medium - rotate: false - xy: 1905, 1243 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-grass-icon-large - rotate: false - xy: 1381, 1701 + xy: 775, 939 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-lead-grass-icon-small +ore-lead-holostone-icon-small rotate: false - xy: 847, 273 + xy: 1905, 883 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-lead-grass1 - rotate: false - xy: 1939, 1243 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-grass2 - rotate: false - xy: 1871, 1209 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-grass3 - rotate: false - xy: 1905, 1209 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-grass-icon-full - rotate: false - xy: 1905, 1209 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-grass-icon-medium - rotate: false - xy: 1905, 1209 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-ice-icon-large - rotate: false - xy: 1431, 1751 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-lead-ice-icon-small - rotate: false - xy: 847, 247 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-lead-ice1 - rotate: false - xy: 1939, 1209 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-ice2 - rotate: false - xy: 1973, 1218 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-ice3 - rotate: false - xy: 1837, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-ice-icon-full - rotate: false - xy: 1837, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-ice-icon-medium - rotate: false - xy: 1837, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-sand-icon-large - rotate: false - xy: 1181, 1451 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-lead-sand-icon-small - rotate: false - xy: 847, 221 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-lead-sand1 - rotate: false - xy: 1871, 1175 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-sand2 - rotate: false - xy: 1905, 1175 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-sand3 - rotate: false - xy: 1939, 1175 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 ore-lead-sand-icon-full rotate: false - xy: 1939, 1175 + xy: 1043, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-lead-sand-icon-medium rotate: false - xy: 1939, 1175 + xy: 1043, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-lead-snow-icon-large +ore-lead-sand-icon-large rotate: false - xy: 1231, 1501 + xy: 825, 989 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-lead-snow-icon-small +ore-lead-sand-icon-small rotate: false - xy: 847, 195 + xy: 1931, 883 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-lead-snow1 +ore-lead-stained-stone-icon-full rotate: false - xy: 1973, 1184 + xy: 1077, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-lead-snow2 +ore-lead-stained-stone-icon-medium rotate: false - xy: 2007, 1218 + xy: 1077, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-lead-snow3 +ore-lead-stained-stone-icon-large rotate: false - xy: 2007, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-snow-icon-full - rotate: false - xy: 2007, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-snow-icon-medium - rotate: false - xy: 2007, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stone-icon-large - rotate: false - xy: 1281, 1551 + xy: 825, 939 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-lead-stone-icon-small +ore-lead-stained-stone-icon-small rotate: false - xy: 847, 169 + xy: 1957, 880 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-lead-stone1 +ore-lead-stained-stone-red-icon-full rotate: false - xy: 1973, 1150 + xy: 1111, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-lead-stone2 +ore-lead-stained-stone-red-icon-medium rotate: false - xy: 2007, 1150 + xy: 1111, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-lead-stone3 +ore-lead-stained-stone-red-icon-large rotate: false - xy: 1381, 1184 - size: 32, 32 - orig: 32, 32 + xy: 875, 1181 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-red-icon-small + rotate: false + xy: 1983, 884 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 ore-lead-stone-icon-full rotate: false - xy: 1381, 1184 + xy: 1145, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-lead-stone-icon-medium rotate: false - xy: 1381, 1184 + xy: 1145, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-scrap-blackstone-icon-large +ore-lead-stone-icon-large rotate: false - xy: 1331, 1601 + xy: 925, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-scrap-blackstone-icon-small +ore-lead-stone-icon-small rotate: false - xy: 847, 143 + xy: 2009, 884 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-scrap-blackstone1 +ore-scrap-holostone-icon-full rotate: false - xy: 1381, 1150 + xy: 1179, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-scrap-blackstone2 +ore-scrap-holostone-icon-medium rotate: false - xy: 1415, 1184 + xy: 1179, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-scrap-blackstone3 +ore-scrap-holostone-icon-large rotate: false - xy: 1415, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-blackstone-icon-full - rotate: false - xy: 1415, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-blackstone-icon-medium - rotate: false - xy: 1415, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-grass-icon-large - rotate: false - xy: 1381, 1651 + xy: 875, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-scrap-grass-icon-small +ore-scrap-holostone-icon-small rotate: false - xy: 873, 296 + xy: 1931, 857 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-scrap-grass1 - rotate: false - xy: 1449, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-grass2 - rotate: false - xy: 1449, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-grass3 - rotate: false - xy: 1483, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-grass-icon-full - rotate: false - xy: 1483, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-grass-icon-medium - rotate: false - xy: 1483, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-ice-icon-large - rotate: false - xy: 1431, 1701 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-scrap-ice-icon-small - rotate: false - xy: 873, 270 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-scrap-ice1 - rotate: false - xy: 1483, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-ice2 - rotate: false - xy: 1517, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-ice3 - rotate: false - xy: 1517, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-ice-icon-full - rotate: false - xy: 1517, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-ice-icon-medium - rotate: false - xy: 1517, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-sand-icon-large - rotate: false - xy: 1481, 1751 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-scrap-sand-icon-small - rotate: false - xy: 873, 244 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-scrap-sand1 - rotate: false - xy: 1551, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-sand2 - rotate: false - xy: 1551, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-sand3 - rotate: false - xy: 1585, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 ore-scrap-sand-icon-full rotate: false - xy: 1585, 1184 + xy: 1213, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap-sand-icon-medium rotate: false - xy: 1585, 1184 + xy: 1213, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-scrap-snow-icon-large +ore-scrap-sand-icon-large rotate: false - xy: 1231, 1451 + xy: 975, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-scrap-snow-icon-small +ore-scrap-sand-icon-small rotate: false - xy: 873, 218 + xy: 1931, 831 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-scrap-snow1 - rotate: false - xy: 1585, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-snow2 - rotate: false - xy: 1619, 1184 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-snow3 - rotate: false - xy: 1619, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 ore-scrap-snow-icon-full rotate: false - xy: 1619, 1150 + xy: 1247, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap-snow-icon-medium rotate: false - xy: 1619, 1150 + xy: 1247, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-scrap-stone-icon-large +ore-scrap-snow-icon-large rotate: false - xy: 1281, 1501 + xy: 875, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-scrap-stone-icon-small +ore-scrap-snow-icon-small rotate: false - xy: 873, 192 + xy: 1957, 854 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-scrap-stone1 +ore-scrap-stained-stone-icon-full rotate: false - xy: 1653, 1184 + xy: 1281, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-scrap-stone2 +ore-scrap-stained-stone-icon-medium rotate: false - xy: 1653, 1150 + xy: 1281, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-scrap-stone3 +ore-scrap-stained-stone-icon-large rotate: false - xy: 1687, 1184 + xy: 925, 1131 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-icon-small + rotate: false + xy: 1983, 858 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red-icon-full + rotate: false + xy: 1315, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +ore-scrap-stained-stone-red-icon-medium + rotate: false + xy: 1315, 727 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red-icon-large + rotate: false + xy: 1025, 1181 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red-icon-small + rotate: false + xy: 1931, 805 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 ore-scrap-stone-icon-full rotate: false - xy: 1687, 1184 + xy: 1349, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap-stone-icon-medium rotate: false - xy: 1687, 1184 + xy: 1349, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-thorium-blackstone-icon-large +ore-scrap-stone-icon-large rotate: false - xy: 1331, 1551 + xy: 875, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-thorium-blackstone-icon-small +ore-scrap-stone-icon-small rotate: false - xy: 873, 166 + xy: 1957, 828 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-thorium-blackstone1 +ore-thorium-holostone-icon-full rotate: false - xy: 1687, 1150 + xy: 1383, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-thorium-blackstone2 +ore-thorium-holostone-icon-medium rotate: false - xy: 1381, 1116 + xy: 1383, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-thorium-blackstone3 +ore-thorium-holostone-icon-large rotate: false - xy: 1415, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-blackstone-icon-full - rotate: false - xy: 1415, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-blackstone-icon-medium - rotate: false - xy: 1415, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-grass-icon-large - rotate: false - xy: 1381, 1601 + xy: 925, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-thorium-grass-icon-small +ore-thorium-holostone-icon-small rotate: false - xy: 873, 140 + xy: 2009, 858 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-thorium-grass1 - rotate: false - xy: 1449, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-grass2 - rotate: false - xy: 1483, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-grass3 - rotate: false - xy: 1517, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-grass-icon-full - rotate: false - xy: 1517, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-grass-icon-medium - rotate: false - xy: 1517, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-ice-icon-large - rotate: false - xy: 1431, 1651 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-thorium-ice-icon-small - rotate: false - xy: 1011, 314 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-thorium-ice1 - rotate: false - xy: 1551, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-ice2 - rotate: false - xy: 1585, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-ice3 - rotate: false - xy: 1619, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-ice-icon-full - rotate: false - xy: 1619, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-ice-icon-medium - rotate: false - xy: 1619, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-sand-icon-large - rotate: false - xy: 1481, 1701 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-thorium-sand-icon-small - rotate: false - xy: 1037, 314 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-thorium-sand1 - rotate: false - xy: 1653, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-sand2 - rotate: false - xy: 1687, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-sand3 - rotate: false - xy: 1721, 1175 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 ore-thorium-sand-icon-full rotate: false - xy: 1721, 1175 + xy: 1417, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-thorium-sand-icon-medium rotate: false - xy: 1721, 1175 + xy: 1417, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-thorium-snow-icon-large +ore-thorium-sand-icon-large rotate: false - xy: 1531, 1751 + xy: 975, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-thorium-snow-icon-small +ore-thorium-sand-icon-small rotate: false - xy: 1063, 314 + xy: 1983, 832 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-thorium-snow1 +ore-thorium-stained-stone-icon-full rotate: false - xy: 1721, 1141 + xy: 1451, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-thorium-snow2 +ore-thorium-stained-stone-icon-medium rotate: false - xy: 1755, 1175 + xy: 1451, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-thorium-snow3 +ore-thorium-stained-stone-icon-large rotate: false - xy: 1755, 1141 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-snow-icon-full - rotate: false - xy: 1755, 1141 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-snow-icon-medium - rotate: false - xy: 1755, 1141 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stone-icon-large - rotate: false - xy: 1281, 1451 + xy: 875, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-thorium-stone-icon-small +ore-thorium-stained-stone-icon-small rotate: false - xy: 260, 6 + xy: 2009, 832 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-thorium-stone1 +ore-thorium-stained-stone-red-icon-full rotate: false - xy: 1789, 1175 + xy: 1485, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-thorium-stone2 +ore-thorium-stained-stone-red-icon-medium rotate: false - xy: 1789, 1141 + xy: 1485, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-thorium-stone3 +ore-thorium-stained-stone-red-icon-large rotate: false - xy: 1721, 1107 - size: 32, 32 - orig: 32, 32 + xy: 925, 1031 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-red-icon-small + rotate: false + xy: 1957, 802 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 ore-thorium-stone-icon-full rotate: false - xy: 1721, 1107 + xy: 1519, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-thorium-stone-icon-medium rotate: false - xy: 1721, 1107 + xy: 1519, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-titanium-blackstone-icon-large +ore-thorium-stone-icon-large rotate: false - xy: 1331, 1501 + xy: 975, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-titanium-blackstone-icon-small +ore-thorium-stone-icon-small rotate: false - xy: 1089, 450 + xy: 1983, 806 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-titanium-blackstone1 +ore-titanium-holostone-icon-full rotate: false - xy: 1755, 1107 + xy: 1553, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-titanium-blackstone2 +ore-titanium-holostone-icon-medium rotate: false - xy: 1789, 1107 + xy: 1553, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-titanium-blackstone3 +ore-titanium-holostone-icon-large rotate: false - xy: 1823, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-blackstone-icon-full - rotate: false - xy: 1823, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-blackstone-icon-medium - rotate: false - xy: 1823, 1150 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-grass-icon-large - rotate: false - xy: 1381, 1551 + xy: 1025, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-titanium-grass-icon-small +ore-titanium-holostone-icon-small rotate: false - xy: 1089, 424 + xy: 2009, 806 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-titanium-grass1 - rotate: false - xy: 1823, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-grass2 - rotate: false - xy: 1857, 1141 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-grass3 - rotate: false - xy: 1891, 1141 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-grass-icon-full - rotate: false - xy: 1891, 1141 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-grass-icon-medium - rotate: false - xy: 1891, 1141 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-ice-icon-large - rotate: false - xy: 1431, 1601 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-titanium-ice-icon-small - rotate: false - xy: 1089, 398 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-titanium-ice1 - rotate: false - xy: 1925, 1141 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-ice2 - rotate: false - xy: 1857, 1107 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-ice3 - rotate: false - xy: 1891, 1107 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-ice-icon-full - rotate: false - xy: 1891, 1107 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-ice-icon-medium - rotate: false - xy: 1891, 1107 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-sand-icon-large - rotate: false - xy: 1481, 1651 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-titanium-sand-icon-small - rotate: false - xy: 1089, 372 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-titanium-sand1 - rotate: false - xy: 1925, 1107 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-sand2 - rotate: false - xy: 1959, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-sand3 - rotate: false - xy: 1993, 1116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 ore-titanium-sand-icon-full rotate: false - xy: 1993, 1116 + xy: 1587, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-titanium-sand-icon-medium rotate: false - xy: 1993, 1116 + xy: 1587, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-titanium-snow-icon-large +ore-titanium-sand-icon-large rotate: false - xy: 1531, 1701 + xy: 925, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-titanium-snow-icon-small +ore-titanium-sand-icon-small rotate: false - xy: 1089, 346 + xy: 1957, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-titanium-snow1 +ore-titanium-stained-stone-icon-full rotate: false - xy: 1823, 1082 + xy: 1621, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-titanium-snow2 +ore-titanium-stained-stone-icon-medium rotate: false - xy: 1857, 1073 + xy: 1621, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-titanium-snow3 +ore-titanium-stained-stone-icon-large rotate: false - xy: 1891, 1073 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-snow-icon-full - rotate: false - xy: 1891, 1073 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-snow-icon-medium - rotate: false - xy: 1891, 1073 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stone-icon-large - rotate: false - xy: 1581, 1751 + xy: 975, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-titanium-stone-icon-small +ore-titanium-stained-stone-icon-small rotate: false - xy: 1089, 320 + xy: 1983, 780 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-titanium-stone1 +ore-titanium-stained-stone-red-icon-full rotate: false - xy: 1925, 1073 + xy: 1655, 748 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-titanium-stone2 +ore-titanium-stained-stone-red-icon-medium rotate: false - xy: 1959, 1082 + xy: 1655, 748 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-titanium-stone3 +ore-titanium-stained-stone-red-icon-large rotate: false - xy: 1993, 1082 - size: 32, 32 - orig: 32, 32 + xy: 1025, 1081 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-red-icon-small + rotate: false + xy: 1957, 750 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 ore-titanium-stone-icon-full rotate: false - xy: 1993, 1082 + xy: 838, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-titanium-stone-icon-medium rotate: false - xy: 1993, 1082 + xy: 838, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -overdrive-projector-icon-full +ore-titanium-stone-icon-large rotate: false - xy: 719, 1645 - size: 64, 64 - orig: 64, 64 + xy: 975, 981 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-titanium-stone-icon-small + rotate: false + xy: 2009, 780 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 overdrive-projector-icon-large rotate: false - xy: 1331, 1451 + xy: 1025, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 overdrive-projector-icon-medium rotate: false - xy: 1959, 1048 + xy: 872, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 overdrive-projector-icon-small rotate: false - xy: 1141, 1015 + xy: 1983, 754 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -overflow-gate-icon-full - rotate: false - xy: 819, 949 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -overflow-gate-icon-medium - rotate: false - xy: 819, 949 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 overflow-gate-icon-large rotate: false - xy: 1381, 1501 + xy: 1025, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 overflow-gate-icon-small rotate: false - xy: 1167, 1015 + xy: 1957, 724 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phantom-factory-icon-full rotate: false - xy: 851, 1777 + xy: 1975, 1383 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phantom-factory-icon-large rotate: false - xy: 1431, 1551 + xy: 875, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phantom-factory-icon-medium rotate: false - xy: 1009, 1147 + xy: 940, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phantom-factory-icon-small rotate: false - xy: 1193, 1015 + xy: 2009, 754 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -phase-conduit-icon-full - rotate: false - xy: 945, 1057 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conduit-icon-medium - rotate: false - xy: 945, 1057 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 phase-conduit-icon-large rotate: false - xy: 1481, 1601 + xy: 925, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-conduit-icon-small rotate: false - xy: 1140, 989 + xy: 1983, 728 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -phase-conveyor-icon-full - rotate: false - xy: 979, 1057 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conveyor-icon-medium - rotate: false - xy: 979, 1057 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 phase-conveyor-icon-large rotate: false - xy: 1531, 1651 + xy: 975, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-conveyor-icon-small rotate: false - xy: 1136, 963 + xy: 1957, 698 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -phase-wall-icon-full - rotate: false - xy: 979, 989 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-wall-icon-medium - rotate: false - xy: 979, 989 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 phase-wall-icon-large rotate: false - xy: 1581, 1701 + xy: 1025, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-wall-icon-small rotate: false - xy: 1166, 989 + xy: 2009, 728 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -phase-wall-large-icon-full - rotate: false - xy: 851, 1711 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 phase-wall-large-icon-large rotate: false - xy: 1631, 1751 + xy: 1075, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-wall-large-icon-medium rotate: false - xy: 979, 955 + xy: 1280, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-large-icon-small rotate: false - xy: 1162, 963 + xy: 1983, 702 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phase-weaver-icon-full rotate: false - xy: 719, 1513 + xy: 1381, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-icon-large rotate: false - xy: 1381, 1451 + xy: 1125, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-weaver-icon-medium rotate: false - xy: 979, 921 + xy: 1314, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-weaver-icon-small rotate: false - xy: 1140, 937 + xy: 2009, 702 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -plasma-drill-icon-full +pine-icon-medium rotate: false - xy: 464, 1831 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -plasma-drill-icon-large - rotate: false - xy: 1431, 1501 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -plasma-drill-icon-medium - rotate: false - xy: 779, 887 + xy: 1348, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -plasma-drill-icon-small +pine-icon-small rotate: false - xy: 1192, 989 + xy: 1983, 676 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -plastanium-compressor-icon-full - rotate: false - xy: 917, 1711 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 plastanium-compressor-icon-large rotate: false - xy: 1481, 1551 + xy: 1075, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 plastanium-compressor-icon-medium rotate: false - xy: 779, 853 + xy: 1382, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-compressor-icon-small rotate: false - xy: 1188, 963 + xy: 2009, 676 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 pneumatic-drill-icon-full rotate: false - xy: 719, 1447 + xy: 1711, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-icon-large rotate: false - xy: 1531, 1601 + xy: 1175, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 pneumatic-drill-icon-medium rotate: false - xy: 779, 819 + xy: 1416, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pneumatic-drill-icon-small rotate: false - xy: 1140, 911 + xy: 1978, 650 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -power-node-icon-full - rotate: false - xy: 779, 751 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-node-icon-medium - rotate: false - xy: 779, 751 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 power-node-icon-large rotate: false - xy: 1581, 1651 + xy: 1075, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 power-node-icon-small rotate: false - xy: 1166, 937 + xy: 2004, 650 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -power-node-large-icon-full - rotate: false - xy: 983, 1711 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 power-node-large-icon-large rotate: false - xy: 1631, 1701 + xy: 1125, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 power-node-large-icon-medium rotate: false - xy: 779, 717 + xy: 1484, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-node-large-icon-small rotate: false - xy: 1166, 911 + xy: 2000, 624 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -power-source-icon-full - rotate: false - xy: 779, 649 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-source-icon-medium - rotate: false - xy: 779, 649 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 power-source-icon-large rotate: false - xy: 1681, 1751 + xy: 1225, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 power-source-icon-small rotate: false - xy: 1192, 937 + xy: 2000, 598 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -power-void-icon-full - rotate: false - xy: 813, 915 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-void-icon-medium - rotate: false - xy: 813, 915 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 power-void-icon-large rotate: false - xy: 1431, 1451 + xy: 1075, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 power-void-icon-small rotate: false - xy: 1192, 911 + xy: 527, 704 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 pulse-conduit-icon-full rotate: false - xy: 813, 813 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-icon-medium - rotate: false - xy: 813, 813 + xy: 1693, 803 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-icon-large rotate: false - xy: 1481, 1501 + xy: 1125, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 pulse-conduit-icon-small rotate: false - xy: 1140, 885 + xy: 553, 704 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 pulverizer-icon-full rotate: false - xy: 847, 881 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulverizer-icon-medium - rotate: false - xy: 847, 881 + xy: 906, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulverizer-icon-large rotate: false - xy: 1531, 1551 + xy: 1175, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 pulverizer-icon-small rotate: false - xy: 1166, 885 + xy: 509, 678 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -pyratite-mixer-icon-full - rotate: false - xy: 653, 1315 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 pyratite-mixer-icon-large rotate: false - xy: 1581, 1601 + xy: 1275, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 pyratite-mixer-icon-medium rotate: false - xy: 847, 813 + xy: 974, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pyratite-mixer-icon-small rotate: false - xy: 1192, 885 + xy: 509, 652 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -reconstructor-icon-full +repair-point rotate: false - xy: 719, 1381 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -reconstructor-icon-large - rotate: false - xy: 1631, 1651 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -reconstructor-icon-medium - rotate: false - xy: 847, 779 + xy: 1008, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -reconstructor-icon-small - rotate: false - xy: 847, 117 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 repair-point-icon-full rotate: false - xy: 847, 711 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -repair-point-icon-medium - rotate: false - xy: 847, 711 + xy: 1076, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 repair-point-icon-large rotate: false - xy: 1681, 1701 + xy: 1125, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 repair-point-icon-small rotate: false - xy: 844, 91 + xy: 535, 678 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 revenant-factory-icon-full rotate: false - xy: 131, 1108 + xy: 1306, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 revenant-factory-icon-large rotate: false - xy: 1731, 1751 + xy: 1175, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 revenant-factory-icon-medium rotate: false - xy: 847, 643 + xy: 1110, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 revenant-factory-icon-small rotate: false - xy: 844, 65 + xy: 509, 626 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 +ripple + rotate: false + xy: 1885, 1495 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 ripple-icon-full rotate: false - xy: 555, 1635 + xy: 163, 1201 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ripple-icon-large rotate: false - xy: 1481, 1451 + xy: 1325, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ripple-icon-medium rotate: false - xy: 847, 609 + xy: 1144, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ripple-icon-small rotate: false - xy: 873, 114 + xy: 535, 652 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -rock-icon-full - rotate: false - xy: 1631, 1601 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rock-icon-large - rotate: false - xy: 1631, 1601 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rock-icon-medium - rotate: false - xy: 881, 912 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -rock-icon-small - rotate: false - xy: 870, 88 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -rocks-icon-full - rotate: false - xy: 881, 810 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -rocks-icon-medium - rotate: false - xy: 881, 810 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 rocks-icon-large rotate: false - xy: 1681, 1651 + xy: 1075, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rocks-icon-small rotate: false - xy: 870, 62 + xy: 535, 626 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -rotary-pump-icon-full - rotate: false - xy: 917, 1579 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 rotary-pump-icon-large rotate: false - xy: 1731, 1701 + xy: 1125, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rotary-pump-icon-medium rotate: false - xy: 881, 776 + xy: 1178, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump-icon-small rotate: false - xy: 844, 39 + xy: 561, 678 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -router-icon-full - rotate: false - xy: 881, 708 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -router-icon-medium - rotate: false - xy: 881, 708 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 router-icon-large rotate: false - xy: 1781, 1751 + xy: 1175, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 router-icon-small rotate: false - xy: 870, 36 + xy: 561, 652 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -rtg-generator-icon-full - rotate: false - xy: 1049, 1711 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 rtg-generator-icon-large rotate: false - xy: 1531, 1451 + xy: 1225, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rtg-generator-icon-medium rotate: false - xy: 881, 674 + xy: 1246, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rtg-generator-icon-small rotate: false - xy: 838, 13 + xy: 561, 626 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 +salt-icon-large + rotate: false + xy: 1275, 1131 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +salt-icon-small + rotate: false + xy: 587, 674 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +salvo + rotate: false + xy: 253, 739 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 salvo-icon-full rotate: false - xy: 983, 1579 + xy: 985, 1331 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-icon-large rotate: false - xy: 1581, 1501 + xy: 1375, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 salvo-icon-medium rotate: false - xy: 881, 606 + xy: 1314, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 salvo-icon-small rotate: false - xy: 864, 10 + xy: 613, 674 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -sand-icon-full - rotate: false - xy: 915, 819 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand-icon-medium - rotate: false - xy: 915, 819 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 sand-icon-large rotate: false - xy: 1631, 1551 + xy: 1125, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sand-icon-small rotate: false - xy: 1114, 869 + xy: 587, 648 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -separator-icon-full +sand-water-icon-large rotate: false - xy: 915, 649 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -separator-icon-medium - rotate: false - xy: 915, 649 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -separator-icon-large - rotate: false - xy: 1731, 1651 + xy: 1175, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -separator-icon-small +sand-water-icon-small rotate: false - xy: 1111, 764 + xy: 613, 648 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -shock-mine-icon-full +sandrocks-icon-large rotate: false - xy: 949, 649 + xy: 1225, 1031 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sandrocks-icon-small + rotate: false + xy: 587, 622 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-large + rotate: false + xy: 1275, 1081 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-medium + rotate: false + xy: 1484, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -shock-mine-icon-medium +scrap-wall-gigantic-icon-small rotate: false - xy: 949, 649 + xy: 613, 622 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-large + rotate: false + xy: 1325, 1131 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-medium + rotate: false + xy: 1518, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +scrap-wall-huge-icon-small + rotate: false + xy: 639, 666 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-icon-large + rotate: false + xy: 1425, 1181 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-icon-small + rotate: false + xy: 665, 666 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-large + rotate: false + xy: 1175, 931 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-medium + rotate: false + xy: 1552, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-small + rotate: false + xy: 639, 640 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +separator-icon-large + rotate: false + xy: 1225, 981 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +separator-icon-medium + rotate: false + xy: 1620, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +separator-icon-small + rotate: false + xy: 639, 614 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 shock-mine-icon-large rotate: false - xy: 1781, 1701 + xy: 1275, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 shock-mine-icon-small rotate: false - xy: 1111, 738 + xy: 717, 666 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -silicon-smelter-icon-full - rotate: false - xy: 719, 1249 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 silicon-smelter-icon-large rotate: false - xy: 1581, 1451 + xy: 1375, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 silicon-smelter-icon-medium rotate: false - xy: 983, 853 + xy: 1735, 861 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 silicon-smelter-icon-small rotate: false - xy: 1111, 712 + xy: 743, 666 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -snow-icon-full - rotate: false - xy: 983, 683 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow-icon-medium - rotate: false - xy: 983, 683 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 snow-icon-large rotate: false - xy: 1631, 1501 + xy: 1475, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 snow-icon-small rotate: false - xy: 1111, 686 + xy: 769, 666 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -solar-panel-icon-full +snowrocks-icon-large rotate: false - xy: 983, 615 - size: 32, 32 - orig: 32, 32 + xy: 1225, 931 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 -solar-panel-icon-medium +snowrocks-icon-small rotate: false - xy: 983, 615 - size: 32, 32 - orig: 32, 32 + xy: 691, 624 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 solar-panel-icon-large rotate: false - xy: 1731, 1601 + xy: 1275, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 solar-panel-icon-small rotate: false - xy: 1111, 660 + xy: 717, 640 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -solar-panel-large-icon-full - rotate: false - xy: 555, 1341 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 solar-panel-large-icon-large rotate: false - xy: 1781, 1651 + xy: 1325, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 solar-panel-large-icon-medium rotate: false - xy: 915, 581 + xy: 1761, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-large-icon-small rotate: false - xy: 1111, 634 + xy: 743, 640 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -sorter-icon-full - rotate: false - xy: 847, 575 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sorter-icon-medium - rotate: false - xy: 847, 575 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 sorter-icon-large rotate: false - xy: 1831, 1701 + xy: 1375, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sorter-icon-small rotate: false - xy: 1111, 608 + xy: 769, 640 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -space-icon-large - rotate: false - xy: 1881, 1751 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -space-icon-small - rotate: false - xy: 1111, 582 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -spawn-icon-full - rotate: false - xy: 949, 547 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spawn-icon-medium - rotate: false - xy: 949, 547 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 spawn-icon-large rotate: false - xy: 1681, 1501 + xy: 1425, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spawn-icon-small rotate: false - xy: 1111, 556 + xy: 795, 655 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 +spectre + rotate: false + xy: 453, 1628 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 spectre-icon-full rotate: false - xy: 131, 588 + xy: 583, 1659 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spectre-icon-large rotate: false - xy: 1731, 1551 + xy: 1525, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spectre-icon-medium rotate: false - xy: 983, 547 + xy: 1723, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spectre-icon-small rotate: false - xy: 1111, 530 + xy: 665, 603 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spirit-factory-icon-full rotate: false - xy: 785, 1315 + xy: 1645, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spirit-factory-icon-large rotate: false - xy: 1831, 1651 + xy: 1325, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spirit-factory-icon-medium rotate: false - xy: 1013, 1048 + xy: 1757, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spirit-factory-icon-small rotate: false - xy: 1111, 504 + xy: 691, 598 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -stone-icon-full +spore-cluster-icon-large rotate: false - xy: 1017, 810 + xy: 1375, 1031 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-cluster-icon-medium + rotate: false + xy: 1757, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -stone-icon-medium +spore-cluster-icon-small rotate: false - xy: 1017, 810 + xy: 717, 614 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spore-press-icon-full + rotate: false + xy: 385, 1366 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-press-icon-large + rotate: false + xy: 1425, 1081 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-press-icon-medium + rotate: false + xy: 1723, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +spore-press-icon-small + rotate: false + xy: 743, 614 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-boulder-icon-large + rotate: false + xy: 1475, 1131 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-boulder-icon-small + rotate: false + xy: 769, 614 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-rocks-icon-large + rotate: false + xy: 1575, 1181 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-rocks-icon-small + rotate: false + xy: 795, 629 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-rocks-red-icon-large + rotate: false + xy: 1325, 931 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-rocks-red-icon-small + rotate: false + xy: 717, 588 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-rocks-yellow-icon-large + rotate: false + xy: 1375, 981 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-rocks-yellow-icon-small + rotate: false + xy: 743, 588 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-stone-icon-large + rotate: false + xy: 1425, 1031 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-stone-icon-small + rotate: false + xy: 769, 588 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-stone-red-icon-large + rotate: false + xy: 1475, 1081 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-stone-red-icon-small + rotate: false + xy: 795, 603 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-stone-yellow-icon-large + rotate: false + xy: 1525, 1131 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-stone-yellow-icon-small + rotate: false + xy: 795, 577 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 stone-icon-large rotate: false - xy: 1881, 1701 + xy: 1625, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 stone-icon-small rotate: false - xy: 1111, 478 + xy: 821, 633 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -surge-wall-icon-full +surge-tower-icon-large rotate: false - xy: 1017, 742 + xy: 1375, 931 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +surge-tower-icon-medium + rotate: false + xy: 1757, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -surge-wall-icon-medium +surge-tower-icon-small rotate: false - xy: 1017, 742 - size: 32, 32 - orig: 32, 32 + xy: 821, 607 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 surge-wall-icon-large rotate: false - xy: 1681, 1451 + xy: 1425, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 surge-wall-icon-small rotate: false - xy: 1115, 452 + xy: 847, 633 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -surge-wall-large-icon-full - rotate: false - xy: 1049, 1579 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 surge-wall-large-icon-large rotate: false - xy: 1731, 1501 + xy: 1475, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 surge-wall-large-icon-medium rotate: false - xy: 1017, 708 + xy: 1756, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall-large-icon-small rotate: false - xy: 1115, 426 + xy: 847, 607 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 +swarmer + rotate: false + xy: 261, 1236 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 swarmer-icon-full rotate: false - xy: 653, 1117 + xy: 327, 1300 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 swarmer-icon-large rotate: false - xy: 1831, 1601 + xy: 1575, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 swarmer-icon-medium rotate: false - xy: 1017, 674 + xy: 1722, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 swarmer-icon-small rotate: false - xy: 1115, 400 + xy: 821, 581 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 tar-icon-large rotate: false - xy: 1881, 1651 + xy: 1675, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 tar-icon-small rotate: false - xy: 1115, 374 + xy: 873, 633 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -tau-mech-pad-icon-full - rotate: false - xy: 785, 1249 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 tau-mech-pad-icon-large rotate: false - xy: 1781, 1501 + xy: 1525, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 tau-mech-pad-icon-medium rotate: false - xy: 1017, 606 + xy: 1756, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tau-mech-pad-icon-small rotate: false - xy: 1115, 348 + xy: 873, 607 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -thermal-generator-icon-full - rotate: false - xy: 917, 1381 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 thermal-generator-icon-large rotate: false - xy: 1831, 1551 + xy: 1575, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thermal-generator-icon-medium rotate: false - xy: 1017, 572 + xy: 1803, 861 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thermal-generator-icon-small rotate: false - xy: 1115, 322 + xy: 847, 581 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -thermal-pump-icon-full - rotate: false - xy: 1049, 1513 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 thermal-pump-icon-large rotate: false - xy: 1881, 1601 + xy: 1625, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thermal-pump-icon-medium rotate: false - xy: 1017, 538 + xy: 1795, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thermal-pump-icon-small rotate: false - xy: 1140, 859 + xy: 899, 633 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -thorium-reactor-icon-full - rotate: false - xy: 555, 1047 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 thorium-reactor-icon-large rotate: false - xy: 1931, 1651 + xy: 1725, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thorium-reactor-icon-medium rotate: false - xy: 915, 513 + xy: 1795, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-reactor-icon-small rotate: false - xy: 1166, 859 + xy: 899, 607 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -thorium-wall-icon-full - rotate: false - xy: 983, 513 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium-wall-icon-medium - rotate: false - xy: 983, 513 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 thorium-wall-icon-large rotate: false - xy: 1981, 1701 + xy: 1475, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thorium-wall-icon-small rotate: false - xy: 1192, 859 + xy: 873, 581 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -thorium-wall-large-icon-full - rotate: false - xy: 653, 1051 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 thorium-wall-large-icon-large rotate: false - xy: 1781, 1451 + xy: 1525, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thorium-wall-large-icon-medium rotate: false - xy: 1017, 504 + xy: 1791, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-wall-large-icon-small rotate: false - xy: 1137, 833 + xy: 925, 633 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thruster-icon-large + rotate: false + xy: 1575, 1031 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thruster-icon-medium + rotate: false + xy: 1791, 691 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thruster-icon-small + rotate: false + xy: 925, 607 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 titan-factory-icon-full rotate: false - xy: 555, 753 + xy: 131, 123 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 titan-factory-icon-large rotate: false - xy: 1831, 1501 + xy: 1625, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titan-factory-icon-medium rotate: false - xy: 1047, 1082 + xy: 1790, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titan-factory-icon-small rotate: false - xy: 1163, 833 + xy: 899, 581 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -titanium-conveyor-icon-full - rotate: false - xy: 1017, 470 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-icon-medium - rotate: false - xy: 1017, 470 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 titanium-conveyor-icon-large rotate: false - xy: 1881, 1551 + xy: 1675, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titanium-conveyor-icon-small rotate: false - xy: 1137, 807 + xy: 951, 633 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -titanium-wall-icon-full - rotate: false - xy: 787, 473 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-wall-icon-medium - rotate: false - xy: 787, 473 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 titanium-wall-icon-large rotate: false - xy: 1931, 1601 + xy: 1775, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titanium-wall-icon-small rotate: false - xy: 1189, 833 + xy: 951, 607 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -titanium-wall-large-icon-full - rotate: false - xy: 917, 1315 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 titanium-wall-large-icon-large rotate: false - xy: 1981, 1651 + xy: 1525, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titanium-wall-large-icon-medium rotate: false - xy: 821, 473 + xy: 1859, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-large-icon-small rotate: false - xy: 1163, 807 + xy: 925, 581 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -trident-ship-pad-icon-full - rotate: false - xy: 1049, 1447 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 trident-ship-pad-icon-large rotate: false - xy: 1831, 1451 + xy: 1575, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 trident-ship-pad-icon-medium rotate: false - xy: 787, 405 + xy: 1858, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 trident-ship-pad-icon-small rotate: false - xy: 1137, 781 + xy: 977, 633 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -turbine-generator-icon-full - rotate: false - xy: 653, 985 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 turbine-generator-icon-large rotate: false - xy: 1881, 1501 + xy: 1625, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 turbine-generator-icon-medium rotate: false - xy: 821, 439 + xy: 1851, 1037 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 turbine-generator-icon-small rotate: false - xy: 1189, 807 + xy: 977, 607 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -unit-icon-dagger +unit-icon-chaos-array rotate: false - xy: 1931, 1551 + xy: 843, 1659 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +unit-icon-crawler + rotate: false + xy: 1675, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 +unit-icon-dagger + rotate: false + xy: 1725, 1131 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unit-icon-eradicator + rotate: false + xy: 1, 731 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +unit-icon-eruptor + rotate: false + xy: 385, 1102 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 unit-icon-fortress rotate: false - xy: 785, 1117 + xy: 451, 1168 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -unit-icon-ghoul - rotate: false - xy: 1112, 1975 - size: 72, 72 - orig: 72, 72 - offset: 0, 0 - index: -1 -unit-icon-phantom - rotate: false - xy: 653, 629 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -unit-icon-revenant - rotate: false - xy: 131, 360 - size: 112, 112 - orig: 112, 112 - offset: 0, 0 - index: -1 -unit-icon-spirit - rotate: false - xy: 1981, 1601 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 unit-icon-titan rotate: false - xy: 851, 1183 + xy: 319, 970 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -unit-icon-wraith - rotate: false - xy: 1881, 1451 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -unloader-icon-full - rotate: false - xy: 821, 405 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -unloader-icon-medium - rotate: false - xy: 821, 405 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 unloader-icon-large rotate: false - xy: 1931, 1501 + xy: 1825, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 unloader-icon-small rotate: false - xy: 1163, 781 + xy: 951, 581 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -vault-icon-full - rotate: false - xy: 555, 557 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 vault-icon-large rotate: false - xy: 1981, 1551 + xy: 1575, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 vault-icon-medium rotate: false - xy: 787, 337 + xy: 1897, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 vault-icon-small rotate: false - xy: 1137, 755 + xy: 1003, 633 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 water-extractor-icon-full rotate: false - xy: 983, 1315 + xy: 451, 1102 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-icon-large rotate: false - xy: 1931, 1451 + xy: 1625, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 water-extractor-icon-medium rotate: false - xy: 813, 201 + xy: 1897, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 water-extractor-icon-small rotate: false - xy: 1189, 781 + xy: 1003, 607 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 water-icon-large rotate: false - xy: 1981, 1501 + xy: 1675, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 water-icon-small rotate: false - xy: 1163, 755 + xy: 977, 581 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 +wave + rotate: false + xy: 319, 838 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 wave-icon-full rotate: false - xy: 785, 1051 + xy: 385, 904 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wave-icon-large rotate: false - xy: 1173, 1397 + xy: 1725, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 wave-icon-medium rotate: false - xy: 813, 167 + xy: 1893, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 wave-icon-small rotate: false - xy: 1137, 729 + xy: 1029, 633 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +white-tree-dead-icon-large + rotate: false + xy: 1775, 1131 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +white-tree-dead-icon-medium + rotate: false + xy: 1893, 725 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +white-tree-dead-icon-small + rotate: false + xy: 1029, 607 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +white-tree-icon-large + rotate: false + xy: 1875, 1181 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +white-tree-icon-medium + rotate: false + xy: 1893, 691 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +white-tree-icon-small + rotate: false + xy: 1003, 581 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 wraith-factory-icon-full rotate: false - xy: 917, 1183 + xy: 319, 772 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith-factory-icon-large rotate: false - xy: 1223, 1401 + xy: 1625, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 wraith-factory-icon-medium rotate: false - xy: 813, 133 + xy: 1892, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 wraith-factory-icon-small rotate: false - xy: 1189, 755 + xy: 1055, 633 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-biomatter rotate: false - xy: 1075, 1163 + xy: 1625, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-blast-compound rotate: false - xy: 1109, 1163 + xy: 1659, 816 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-coal rotate: false - xy: 1143, 1177 + xy: 839, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-copper rotate: false - xy: 1177, 1177 + xy: 839, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-graphite rotate: false - xy: 1211, 1177 + xy: 873, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-lead rotate: false - xy: 1143, 1143 + xy: 873, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-metaglass rotate: false - xy: 1177, 1143 + xy: 907, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-phase-fabric rotate: false - xy: 1211, 1143 + xy: 907, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-plastanium rotate: false - xy: 1245, 1155 + xy: 941, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-pyratite rotate: false - xy: 1279, 1155 + xy: 941, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-sand rotate: false - xy: 1313, 1155 + xy: 975, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-scrap rotate: false - xy: 1347, 1155 + xy: 975, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-silicon rotate: false - xy: 1245, 1121 + xy: 1009, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -item-stone +item-spore-pod rotate: false - xy: 1347, 1121 + xy: 1043, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-surge-alloy rotate: false - xy: 1343, 1354 + xy: 1043, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-thorium rotate: false - xy: 1343, 1320 + xy: 1077, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-titanium rotate: false - xy: 1377, 1354 + xy: 1077, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-cryofluid rotate: false - xy: 1615, 1354 + xy: 1247, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-oil rotate: false - xy: 1649, 1320 + xy: 1281, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-slag rotate: false - xy: 1751, 1345 + xy: 1349, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-water rotate: false - xy: 1785, 1311 + xy: 1417, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 alpha-mech rotate: false - xy: 637, 475 + xy: 295, 440 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alpha-mech-base rotate: false - xy: 637, 425 + xy: 295, 390 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alpha-mech-leg rotate: false - xy: 637, 375 + xy: 295, 340 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech rotate: false - xy: 579, 261 + xy: 575, 928 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech-base rotate: false - xy: 479, 111 + xy: 625, 1150 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech-leg rotate: false - xy: 529, 161 + xy: 625, 1100 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 omega-mech rotate: false - xy: 917, 1125 + xy: 517, 1054 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 omega-mech-armor rotate: false - xy: 983, 1191 - size: 56, 56 - orig: 56, 56 + xy: 1777, 1363 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 omega-mech-base rotate: false - xy: 1049, 1257 + xy: 517, 996 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 omega-mech-leg rotate: false - xy: 152, 8 + xy: 517, 938 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 tau-mech rotate: false - xy: 653, 745 + xy: 295, 656 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 tau-mech-base rotate: false - xy: 1981, 1751 + xy: 1425, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 tau-mech-leg rotate: false - xy: 1731, 1451 + xy: 1475, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dart-ship rotate: false - xy: 429, 111 + xy: 575, 1028 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 glaive-ship rotate: false - xy: 1115, 1389 + xy: 451, 846 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 javelin-ship rotate: false - xy: 629, 75 + xy: 601, 750 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 javelin-ship-shield rotate: false - xy: 729, 75 + xy: 701, 742 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 trident-ship rotate: false - xy: 653, 687 + xy: 295, 598 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 blank rotate: false - xy: 870, 114 + xy: 87, 34 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 circle rotate: false - xy: 1, 1758 + xy: 323, 1758 size: 201, 201 orig: 201, 201 offset: 0, 0 index: -1 clear rotate: false - xy: 258, 1828 + xy: 1957, 932 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 shape-3 rotate: false - xy: 87, 1 + xy: 385, 773 size: 63, 63 orig: 63, 63 offset: 0, 0 index: -1 bar rotate: false - xy: 1111, 989 + xy: 445, 82 size: 27, 36 split: 9, 9, 9, 9 orig: 27, 36 @@ -8624,7 +6972,7 @@ bar index: -1 bar-top rotate: false - xy: 1081, 955 + xy: 445, 120 size: 27, 36 split: 9, 10, 9, 10 orig: 27, 36 @@ -8632,7 +6980,15 @@ bar-top index: -1 button rotate: false - xy: 1615, 1422 + xy: 801, 768 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-disabled + rotate: false + xy: 526, 1760 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8640,7 +6996,7 @@ button index: -1 button-down rotate: false - xy: 1273, 1422 + xy: 1, 5 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8648,7 +7004,7 @@ button-down index: -1 button-edge-1 rotate: false - xy: 1311, 1422 + xy: 261, 1207 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8656,7 +7012,7 @@ button-edge-1 index: -1 button-edge-2 rotate: false - xy: 1349, 1422 + xy: 801, 826 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8664,7 +7020,7 @@ button-edge-2 index: -1 button-edge-3 rotate: false - xy: 1387, 1422 + xy: 39, 5 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8672,7 +7028,7 @@ button-edge-3 index: -1 button-edge-4 rotate: false - xy: 1425, 1422 + xy: 261, 1372 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8680,7 +7036,7 @@ button-edge-4 index: -1 button-over rotate: false - xy: 1463, 1422 + xy: 1675, 918 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8688,7 +7044,7 @@ button-over index: -1 button-right rotate: false - xy: 1577, 1422 + xy: 801, 797 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8696,7 +7052,7 @@ button-right index: -1 button-right-down rotate: false - xy: 1501, 1422 + xy: 1951, 1152 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8704,7 +7060,7 @@ button-right-down index: -1 button-right-over rotate: false - xy: 1539, 1422 + xy: 1989, 1156 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8712,7 +7068,7 @@ button-right-over index: -1 button-select rotate: false - xy: 1085, 840 + xy: 891, 1337 size: 24, 24 split: 4, 4, 4, 4 orig: 24, 24 @@ -8720,42 +7076,42 @@ button-select index: -1 check-off rotate: false - xy: 1043, 1147 + xy: 1892, 623 size: 28, 32 orig: 28, 32 offset: 0, 0 index: -1 check-on rotate: false - xy: 1073, 1129 + xy: 1862, 1003 size: 28, 32 orig: 28, 32 offset: 0, 0 index: -1 check-on-over rotate: false - xy: 1103, 1129 + xy: 1919, 1065 size: 28, 32 orig: 28, 32 offset: 0, 0 index: -1 check-over rotate: false - xy: 1081, 1095 + xy: 1892, 1003 size: 28, 32 orig: 28, 32 offset: 0, 0 index: -1 clear rotate: false - xy: 741, 575 + xy: 1701, 906 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 content-background rotate: false - xy: 1729, 1422 + xy: 800, 681 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8763,7 +7119,7 @@ content-background index: -1 content-background-locked rotate: false - xy: 1653, 1422 + xy: 801, 739 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8771,7 +7127,7 @@ content-background-locked index: -1 content-background-over rotate: false - xy: 1691, 1422 + xy: 800, 710 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8779,875 +7135,903 @@ content-background-over index: -1 cursor rotate: false - xy: 813, 953 + xy: 317, 1633 size: 4, 4 orig: 4, 4 offset: 0, 0 index: -1 discord-banner rotate: false - xy: 582, 2002 + xy: 1, 34 size: 84, 45 orig: 84, 45 offset: 0, 0 index: -1 empty-sector rotate: false - xy: 430, 43 + xy: 1183, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icon-crafting rotate: false - xy: 2031, 1729 + xy: 1091, 1237 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-defense rotate: false - xy: 2031, 1711 + xy: 479, 728 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-distribution rotate: false - xy: 2031, 1693 + xy: 1905, 865 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-effect rotate: false - xy: 2031, 1675 + xy: 579, 712 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-liquid rotate: false - xy: 2031, 1513 + xy: 1135, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-power rotate: false - xy: 915, 928 + xy: 1297, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-production rotate: false - xy: 1163, 737 + xy: 1315, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-turret rotate: false - xy: 57, 3 + xy: 1477, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-units rotate: false - xy: 1137, 639 + xy: 1513, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-upgrade rotate: false - xy: 1137, 603 + xy: 1549, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 controller-cursor rotate: false - xy: 1343, 1302 + xy: 445, 64 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-about rotate: false - xy: 245, 572 + xy: 1101, 1479 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-add rotate: false - xy: 637, 541 + xy: 973, 1659 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-admin rotate: false - xy: 637, 525 + xy: 1003, 1463 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-admin-small rotate: false - xy: 1265, 1393 + xy: 651, 792 size: 6, 6 orig: 6, 6 offset: 0, 0 index: -1 icon-areaDelete rotate: false - xy: 582, 1990 + xy: 1931, 793 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow rotate: false - xy: 770, 1 + xy: 321, 64 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-arrow-16 rotate: false - xy: 770, 1 + xy: 321, 64 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-arrow-down rotate: false - xy: 1223, 1347 + xy: 599, 1420 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-left rotate: false - xy: 787, 325 + xy: 609, 900 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-right rotate: false - xy: 933, 934 + xy: 1943, 793 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-up rotate: false - xy: 75, 9 + xy: 587, 700 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-back rotate: false - xy: 788, 1 + xy: 649, 1356 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-ban rotate: false - xy: 613, 95 + xy: 583, 1416 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-break rotate: false - xy: 806, 1 + xy: 295, 721 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-cancel rotate: false - xy: 2031, 1783 + xy: 564, 1771 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-cancel-2 rotate: false - xy: 985, 453 + xy: 475, 234 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 icon-chat rotate: false - xy: 582, 1978 + xy: 1087, 1679 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-check rotate: false - xy: 2031, 1765 + xy: 299, 1218 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-check-2 rotate: false - xy: 907, 375 + xy: 475, 208 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 icon-copy rotate: false - xy: 2031, 1747 + xy: 759, 795 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-cursor rotate: false - xy: 799, 325 + xy: 568, 1949 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-database + rotate: false + xy: 609, 912 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-database-small + rotate: false + xy: 575, 882 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-dev-builds rotate: false - xy: 1837, 1295 + xy: 1948, 994 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-discord rotate: false - xy: 1973, 1261 + xy: 1019, 1463 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-donate rotate: false - xy: 2023, 1252 + xy: 1035, 1463 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-dots rotate: false - xy: 853, 949 + xy: 625, 1218 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-editor rotate: false - xy: 613, 79 + xy: 625, 1202 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-egg rotate: false - xy: 2033, 1443 + xy: 303, 1418 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-elevation rotate: false - xy: 2031, 1657 + xy: 483, 604 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-eraser rotate: false - xy: 2031, 1639 + xy: 1055, 615 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-exit rotate: false - xy: 2033, 1427 + xy: 303, 1402 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-file rotate: false - xy: 2031, 1621 + xy: 1029, 589 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-file-image rotate: false - xy: 2031, 1603 + xy: 1081, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-file-text rotate: false - xy: 2033, 1411 + xy: 479, 62 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-fill rotate: false - xy: 2031, 1585 + xy: 667, 1356 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-floppy rotate: false - xy: 993, 1133 + xy: 303, 1386 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-floppy-16 rotate: false - xy: 2031, 1567 + xy: 777, 795 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-folder rotate: false - xy: 1199, 739 + xy: 821, 665 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-folder-parent rotate: false - xy: 1137, 569 + xy: 147, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-generated rotate: false - xy: 729, 225 + xy: 609, 850 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 icon-github rotate: false - xy: 1137, 553 + xy: 163, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-google-play rotate: false - xy: 1137, 537 + xy: 179, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-grid rotate: false - xy: 2031, 1549 + xy: 1099, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-hold rotate: false - xy: 582, 1966 + xy: 329, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-holdDelete rotate: false - xy: 933, 922 + xy: 1639, 647 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-home rotate: false - xy: 1137, 521 + xy: 195, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-host rotate: false - xy: 1137, 505 + xy: 211, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-info rotate: false - xy: 1137, 489 + xy: 299, 1202 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-itch.io rotate: false - xy: 2027, 1134 + xy: 453, 704 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-item rotate: false - xy: 1233, 1279 + xy: 2027, 1119 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-items-none rotate: false - xy: 273, 66 + xy: 1735, 895 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-line rotate: false - xy: 2031, 1531 + xy: 1117, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-link rotate: false - xy: 2027, 1118 + xy: 299, 1370 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-liquid-small rotate: false - xy: 1245, 1279 + xy: 989, 1663 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-load rotate: false - xy: 2027, 1102 + xy: 469, 704 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-load-image rotate: false - xy: 2031, 1495 + xy: 1153, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-load-map rotate: false - xy: 2031, 1477 + xy: 1171, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-loading rotate: false - xy: 2031, 1459 + xy: 1189, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-locked rotate: false - xy: 204, 1759 + xy: 1207, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-logic rotate: false - xy: 464, 1 + xy: 1265, 629 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-map rotate: false - xy: 2027, 1086 + xy: 501, 606 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-menu rotate: false - xy: 476, 1 + xy: 568, 1937 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-menu-large rotate: false - xy: 636, 1852 + xy: 1225, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-missing rotate: false - xy: 594, 1832 + xy: 587, 882 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-mission-background rotate: false - xy: 1, 1 + xy: 131, 711 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 icon-mission-battle rotate: false - xy: 1143, 1219 + xy: 341, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-mission-defense rotate: false - xy: 1245, 1199 + xy: 1277, 629 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-mission-done rotate: false - xy: 1823, 1197 + xy: 568, 1925 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-none rotate: false - xy: 1959, 1163 + xy: 353, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-paste rotate: false - xy: 1361, 1200 + xy: 1243, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-pause rotate: false - xy: 824, 7 + xy: 1289, 629 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-pencil rotate: false - xy: 975, 1131 + xy: 1261, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-pencil-small rotate: false - xy: 2027, 1070 + xy: 517, 610 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-pick rotate: false - xy: 853, 965 + xy: 1279, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-play rotate: false - xy: 836, 1 + xy: 365, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-play-2 rotate: false - xy: 2027, 1054 + xy: 533, 610 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-play-custom + rotate: false + xy: 549, 610 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-players rotate: false - xy: 848, 1 + xy: 1301, 629 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 +icon-power-requirement + rotate: false + xy: 1489, 829 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 icon-power-small rotate: false - xy: 245, 560 + xy: 377, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-quit rotate: false - xy: 1009, 1131 + xy: 565, 610 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-redo rotate: false - xy: 1137, 711 + xy: 1333, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-refresh rotate: false - xy: 1025, 1131 + xy: 1073, 617 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rename rotate: false - xy: 1041, 1131 + xy: 1055, 599 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-resize rotate: false - xy: 21, 3 + xy: 1351, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-rotate rotate: false - xy: 1057, 1131 + xy: 1029, 573 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-arrow rotate: false - xy: 1219, 1025 + xy: 1089, 625 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-left rotate: false - xy: 2029, 1395 + xy: 1105, 625 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-right rotate: false - xy: 1219, 1009 + xy: 1121, 625 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-save rotate: false - xy: 1218, 993 + xy: 1137, 625 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-save-image rotate: false - xy: 222, 1759 + xy: 1369, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-save-map rotate: false - xy: 1181, 737 + xy: 1387, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-settings rotate: false - xy: 1231, 1131 + xy: 1313, 629 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-spray rotate: false - xy: 1137, 693 + xy: 1405, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-terrain rotate: false - xy: 39, 3 + xy: 1423, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-tools rotate: false - xy: 899, 306 + xy: 1153, 625 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-touch rotate: false - xy: 899, 198 + xy: 389, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-touchDelete rotate: false - xy: 606, 1832 + xy: 1325, 629 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-trash rotate: false - xy: 899, 290 + xy: 1169, 625 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-trash-16 rotate: false - xy: 240, 1759 + xy: 1441, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-tree rotate: false - xy: 1137, 675 + xy: 1459, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-tree-locked rotate: false - xy: 804, 19 + xy: 1523, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icon-trello rotate: false - xy: 899, 274 + xy: 1185, 625 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-tutorial rotate: false - xy: 899, 258 + xy: 1201, 625 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-undo rotate: false - xy: 1137, 657 + xy: 1495, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-unlocked rotate: false - xy: 1137, 621 + xy: 1531, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-unlocks rotate: false - xy: 899, 242 + xy: 1217, 625 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-wiki rotate: false - xy: 899, 226 + xy: 1233, 625 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-zone rotate: false - xy: 933, 401 + xy: 475, 182 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 icon-zone-locked rotate: false - xy: 229, 66 + xy: 87, 37 size: 42, 42 orig: 42, 42 offset: 0, 0 index: -1 icon-zoom rotate: false - xy: 1137, 585 + xy: 1567, 641 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-zoom-small rotate: false - xy: 899, 210 + xy: 1249, 625 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 info-banner rotate: false - xy: 1, 21 + xy: 611, 1416 size: 84, 45 orig: 84, 45 offset: 0, 0 index: -1 inventory rotate: false - xy: 1114, 921 + xy: 501, 504 size: 24, 40 split: 10, 10, 10, 14 orig: 24, 40 @@ -9662,7 +8046,7 @@ logotext index: -1 pane rotate: false - xy: 1881, 1422 + xy: 1717, 981 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -9670,7 +8054,7 @@ pane index: -1 pane-2 rotate: false - xy: 1843, 1422 + xy: 1725, 1010 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -9678,7 +8062,7 @@ pane-2 index: -1 scroll rotate: false - xy: 1111, 790 + xy: 665, 629 size: 24, 35 split: 10, 10, 6, 5 orig: 24, 35 @@ -9686,7 +8070,7 @@ scroll index: -1 scroll-horizontal rotate: false - xy: 1311, 1396 + xy: 2012, 2023 size: 35, 24 split: 6, 5, 10, 10 orig: 35, 24 @@ -9694,7 +8078,7 @@ scroll-horizontal index: -1 scroll-knob-horizontal-black rotate: false - xy: 594, 1844 + xy: 253, 713 size: 40, 24 split: 11, 10, 10, 10 orig: 40, 24 @@ -9702,71 +8086,64 @@ scroll-knob-horizontal-black index: -1 scroll-knob-vertical-black rotate: false - xy: 1111, 827 + xy: 691, 650 size: 24, 40 split: 10, 10, 6, 10 orig: 24, 40 offset: 0, 0 index: -1 -sector-edge - rotate: false - xy: 949, 751 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 sector-select rotate: false - xy: 915, 683 + xy: 1586, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 selection rotate: false - xy: 873, 322 + xy: 759, 792 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 slider rotate: false - xy: 1137, 859 + xy: 497, 736 size: 1, 8 orig: 1, 8 offset: 0, 0 index: -1 slider-knob rotate: false - xy: 813, 93 + xy: 1831, 997 size: 29, 38 orig: 29, 38 offset: 0, 0 index: -1 slider-knob-down rotate: false - xy: 813, 53 + xy: 1919, 1099 size: 29, 38 orig: 29, 38 offset: 0, 0 index: -1 slider-knob-over rotate: false - xy: 813, 53 + xy: 1919, 1099 size: 29, 38 orig: 29, 38 offset: 0, 0 index: -1 slider-vertical rotate: false - xy: 1311, 1393 + xy: 1805, 1031 size: 8, 1 orig: 8, 1 offset: 0, 0 index: -1 underline rotate: false - xy: 1273, 1393 + xy: 1767, 1031 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -9774,7 +8151,7 @@ underline index: -1 underline-2 rotate: false - xy: 1995, 1422 + xy: 1775, 1060 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -9782,198 +8159,4137 @@ underline-2 index: -1 white rotate: false - xy: 2044, 2044 + xy: 725, 892 size: 3, 3 orig: 3, 3 offset: 0, 0 index: -1 window-empty rotate: false - xy: 1085, 892 + xy: 1857, 934 size: 27, 61 split: 8, 8, 44, 11 orig: 27, 61 offset: 0, 0 index: -1 -alpha-drone +chaos-array rotate: false - xy: 653, 525 + xy: 582, 1919 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +chaos-array-base + rotate: false + xy: 712, 1919 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +chaos-array-leg + rotate: false + xy: 842, 1919 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +crawler + rotate: false + xy: 641, 1250 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-base + rotate: false + xy: 641, 1200 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-leg + rotate: false + xy: 501, 780 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger rotate: false - xy: 429, 161 + xy: 550, 730 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-base rotate: false - xy: 479, 211 + xy: 575, 1178 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-leg rotate: false - xy: 579, 311 + xy: 575, 1078 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 +eradicator + rotate: false + xy: 1, 1109 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +eradicator-base + rotate: false + xy: 1, 983 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +eradicator-leg + rotate: false + xy: 1, 857 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +eruptor + rotate: false + xy: 1447, 1429 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +eruptor-base + rotate: false + xy: 1513, 1429 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +eruptor-leg + rotate: false + xy: 1579, 1429 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 fortress rotate: false - xy: 1188, 1851 + xy: 1645, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-base rotate: false - xy: 1254, 1851 + xy: 1711, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 titan-base rotate: false - xy: 1254, 1851 + xy: 1711, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-leg rotate: false - xy: 1320, 1851 + xy: 1777, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 ghoul rotate: false - xy: 742, 1975 + xy: 1956, 1845 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 +lich + rotate: false + xy: 1, 1397 + size: 216, 240 + orig: 216, 240 + offset: 0, 0 + index: -1 phantom rotate: false - xy: 1115, 1331 + xy: 517, 880 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 power-cell rotate: false - xy: 653, 803 + xy: 319, 714 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 +reaper + rotate: false + xy: 1, 1639 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 revenant rotate: false - xy: 131, 474 + xy: 973, 1675 size: 112, 112 orig: 112, 112 offset: 0, 0 index: -1 spirit rotate: false - xy: 1781, 1601 + xy: 1275, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titan rotate: false - xy: 719, 1117 + xy: 393, 1234 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 titan-leg rotate: false - xy: 785, 1183 + xy: 459, 1234 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith rotate: false - xy: 1173, 1347 + xy: 1925, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 artillery-equip rotate: false - xy: 229, 260 - size: 48, 48 - orig: 48, 48 + xy: 295, 232 + size: 48, 56 + orig: 48, 56 offset: 0, 0 index: -1 blaster-equip rotate: false - xy: 379, 311 + xy: 353, 664 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 bomber-equip rotate: false - xy: 279, 161 + xy: 353, 614 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 missiles-equip rotate: false - xy: 279, 161 + xy: 353, 614 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 chain-blaster-equip rotate: false - xy: 429, 311 + xy: 349, 514 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 +chaos-equip + rotate: false + xy: 525, 1228 + size: 56, 136 + orig: 56, 136 + offset: 0, 0 + index: -1 +eradication-equip + rotate: false + xy: 317, 1434 + size: 96, 192 + orig: 96, 192 + offset: 0, 0 + index: -1 +eruption-equip + rotate: false + xy: 675, 942 + size: 48, 56 + orig: 48, 56 + offset: 0, 0 + index: -1 flakgun-equip rotate: false - xy: 1107, 1231 + xy: 675, 892 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 flamethrower-equip rotate: false - xy: 737, 475 - size: 48, 48 - orig: 48, 48 + xy: 377, 714 + size: 48, 56 + orig: 48, 56 offset: 0, 0 index: -1 heal-blaster-equip rotate: false - xy: 679, 225 + xy: 395, 264 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +lich-missiles-equip + rotate: false + xy: 691, 1339 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +reaper-gun-equip + rotate: false + xy: 1075, 981 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +revenant-missiles-equip + rotate: false + xy: 1225, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 shockgun-equip rotate: false - xy: 1831, 1751 + xy: 1325, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 swarmer-equip rotate: false - xy: 1781, 1551 + xy: 1525, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 + +sprites2.png +size: 2048,1024 +format: RGBA8888 +filter: Nearest,Nearest +repeat: none +alloy-smelter-icon-editor + rotate: false + xy: 1, 17 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +alpha-dart-mech-pad-icon-editor + rotate: false + xy: 681, 823 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +arc-icon-editor + rotate: false + xy: 1341, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +battery-icon-editor + rotate: false + xy: 311, 145 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +battery-large-icon-editor + rotate: false + xy: 323, 499 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +blast-drill-icon-editor + rotate: false + xy: 1, 245 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +blast-mixer-icon-editor + rotate: false + xy: 453, 725 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +block-border-editor + rotate: false + xy: 463, 427 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conduit-icon-editor + rotate: false + xy: 1375, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conveyor-icon-editor + rotate: false + xy: 497, 427 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +char-icon-editor + rotate: false + xy: 1409, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-char1 + rotate: false + xy: 1409, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +clear-editor + rotate: false + xy: 453, 854 + size: 1, 1 + orig: 1, 1 + offset: 0, 0 + index: -1 +cliffs-icon-editor + rotate: false + xy: 531, 427 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +combustion-generator-icon-editor + rotate: false + xy: 1443, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-icon-editor + rotate: false + xy: 565, 427 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +container-icon-editor + rotate: false + xy: 453, 659 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +conveyor-icon-editor + rotate: false + xy: 1477, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper-wall-icon-editor + rotate: false + xy: 1511, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper-wall-large-icon-editor + rotate: false + xy: 519, 725 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +core-foundation-icon-editor + rotate: false + xy: 323, 727 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +core-nucleus-icon-editor + rotate: false + xy: 323, 857 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +core-shard-icon-editor + rotate: false + xy: 745, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +craters-icon-editor + rotate: false + xy: 1545, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters1 + rotate: false + xy: 1545, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +crawler-factory-icon-editor + rotate: false + xy: 519, 659 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-editor + rotate: false + xy: 585, 725 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cultivator-icon-editor + rotate: false + xy: 585, 659 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cyclone-icon-editor + rotate: false + xy: 99, 17 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +dagger-factory-icon-editor + rotate: false + xy: 453, 593 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +deepwater-icon-editor + rotate: false + xy: 1579, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-deepwater + rotate: false + xy: 1579, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-editor + rotate: false + xy: 519, 593 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +differential-generator-icon-editor + rotate: false + xy: 323, 401 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +distributor-icon-editor + rotate: false + xy: 585, 593 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +door-icon-editor + rotate: false + xy: 1613, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +door-large-icon-editor + rotate: false + xy: 747, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dunerocks-icon-editor + rotate: false + xy: 1647, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +duo-icon-editor + rotate: false + xy: 1681, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-char2 + rotate: false + xy: 1715, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-char3 + rotate: false + xy: 1749, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-clear + rotate: false + xy: 323, 389 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +editor-craters2 + rotate: false + xy: 1783, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters3 + rotate: false + xy: 1817, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters4 + rotate: false + xy: 1851, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters5 + rotate: false + xy: 1885, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stone1 + rotate: false + xy: 1885, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone-icon-editor + rotate: false + xy: 1885, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters6 + rotate: false + xy: 1919, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stone2 + rotate: false + xy: 1919, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-grass1 + rotate: false + xy: 1953, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass-icon-editor + rotate: false + xy: 1953, 821 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-grass2 + rotate: false + xy: 619, 559 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-grass3 + rotate: false + xy: 619, 525 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-holostone1 + rotate: false + xy: 619, 491 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone-icon-editor + rotate: false + xy: 619, 491 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-holostone2 + rotate: false + xy: 747, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-holostone3 + rotate: false + xy: 781, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-hotrock1 + rotate: false + xy: 815, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock-icon-editor + rotate: false + xy: 815, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-hotrock2 + rotate: false + xy: 849, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-hotrock3 + rotate: false + xy: 883, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice-snow1 + rotate: false + xy: 1019, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow-icon-editor + rotate: false + xy: 1019, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice-snow2 + rotate: false + xy: 1053, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice-snow3 + rotate: false + xy: 1087, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice1 + rotate: false + xy: 917, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-icon-editor + rotate: false + xy: 917, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice2 + rotate: false + xy: 951, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice3 + rotate: false + xy: 985, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ignarock1 + rotate: false + xy: 1121, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock-icon-editor + rotate: false + xy: 1121, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ignarock2 + rotate: false + xy: 1155, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ignarock3 + rotate: false + xy: 1189, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-magmarock1 + rotate: false + xy: 1223, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock-icon-editor + rotate: false + xy: 1223, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-magmarock2 + rotate: false + xy: 1257, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-magmarock3 + rotate: false + xy: 1291, 755 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor + rotate: false + xy: 1341, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged5 + rotate: false + xy: 1341, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-icon-editor + rotate: false + xy: 1341, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-2 + rotate: false + xy: 1375, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-2-icon-editor + rotate: false + xy: 1375, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-3 + rotate: false + xy: 1409, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-3-icon-editor + rotate: false + xy: 1409, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-5 + rotate: false + xy: 1443, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-5-icon-editor + rotate: false + xy: 1443, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged1 + rotate: false + xy: 1477, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged-icon-editor + rotate: false + xy: 1477, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged2 + rotate: false + xy: 1511, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged3 + rotate: false + xy: 1545, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged4 + rotate: false + xy: 1579, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged6 + rotate: false + xy: 1613, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-holostone1 + rotate: false + xy: 1647, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-holostone2 + rotate: false + xy: 1681, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-holostone3 + rotate: false + xy: 1715, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-sand1 + rotate: false + xy: 1749, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-sand2 + rotate: false + xy: 1783, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-sand3 + rotate: false + xy: 1817, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-stained-stone-red1 + rotate: false + xy: 1953, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-stained-stone-red2 + rotate: false + xy: 619, 457 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-stained-stone-red3 + rotate: false + xy: 359, 171 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-stained-stone1 + rotate: false + xy: 1851, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-stained-stone2 + rotate: false + xy: 1885, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-stained-stone3 + rotate: false + xy: 1919, 787 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-stone1 + rotate: false + xy: 393, 171 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-stone2 + rotate: false + xy: 427, 171 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal-stone3 + rotate: false + xy: 2001, 887 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-holostone1 + rotate: false + xy: 2001, 853 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-holostone2 + rotate: false + xy: 1987, 819 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-holostone3 + rotate: false + xy: 1987, 785 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-sand1 + rotate: false + xy: 311, 111 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-sand2 + rotate: false + xy: 345, 137 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-sand3 + rotate: false + xy: 379, 137 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-stained-stone-red1 + rotate: false + xy: 413, 103 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-stained-stone-red2 + rotate: false + xy: 295, 77 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-stained-stone-red3 + rotate: false + xy: 295, 43 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-stained-stone1 + rotate: false + xy: 413, 137 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-stained-stone2 + rotate: false + xy: 345, 103 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-stained-stone3 + rotate: false + xy: 379, 103 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-stone1 + rotate: false + xy: 295, 9 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-stone2 + rotate: false + xy: 329, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper-stone3 + rotate: false + xy: 329, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-holostone1 + rotate: false + xy: 363, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-holostone2 + rotate: false + xy: 363, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-holostone3 + rotate: false + xy: 397, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-sand1 + rotate: false + xy: 397, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-sand2 + rotate: false + xy: 329, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-sand3 + rotate: false + xy: 363, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-stained-stone-red1 + rotate: false + xy: 1393, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-stained-stone-red2 + rotate: false + xy: 1427, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-stained-stone-red3 + rotate: false + xy: 1461, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-stained-stone1 + rotate: false + xy: 397, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-stained-stone2 + rotate: false + xy: 1325, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-stained-stone3 + rotate: false + xy: 1359, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-stone1 + rotate: false + xy: 1495, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-stone2 + rotate: false + xy: 1529, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead-stone3 + rotate: false + xy: 1563, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-holostone1 + rotate: false + xy: 1597, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-holostone2 + rotate: false + xy: 1631, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-holostone3 + rotate: false + xy: 1665, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-sand1 + rotate: false + xy: 1699, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-sand2 + rotate: false + xy: 1733, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-sand3 + rotate: false + xy: 1767, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-snow1 + rotate: false + xy: 1801, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-snow2 + rotate: false + xy: 1835, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-snow3 + rotate: false + xy: 1869, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-stained-stone-red1 + rotate: false + xy: 431, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-stained-stone-red2 + rotate: false + xy: 431, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-stained-stone-red3 + rotate: false + xy: 1971, 751 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-stained-stone1 + rotate: false + xy: 1903, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-stained-stone2 + rotate: false + xy: 1937, 753 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-stained-stone3 + rotate: false + xy: 431, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-stone1 + rotate: false + xy: 2005, 751 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-stone2 + rotate: false + xy: 447, 137 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap-stone3 + rotate: false + xy: 447, 103 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-holostone1 + rotate: false + xy: 465, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-holostone2 + rotate: false + xy: 465, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-holostone3 + rotate: false + xy: 465, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-sand1 + rotate: false + xy: 599, 423 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-sand2 + rotate: false + xy: 633, 423 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-sand3 + rotate: false + xy: 463, 393 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-stained-stone-red1 + rotate: false + xy: 599, 389 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-stained-stone-red2 + rotate: false + xy: 633, 389 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-stained-stone-red3 + rotate: false + xy: 457, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-stained-stone1 + rotate: false + xy: 497, 393 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-stained-stone2 + rotate: false + xy: 531, 393 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-stained-stone3 + rotate: false + xy: 565, 393 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-stone1 + rotate: false + xy: 457, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-stone2 + rotate: false + xy: 491, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium-stone3 + rotate: false + xy: 457, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-holostone1 + rotate: false + xy: 525, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-holostone2 + rotate: false + xy: 491, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-holostone3 + rotate: false + xy: 457, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-sand1 + rotate: false + xy: 559, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-sand2 + rotate: false + xy: 525, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-sand3 + rotate: false + xy: 491, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-stained-stone-red1 + rotate: false + xy: 491, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-stained-stone-red2 + rotate: false + xy: 559, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-stained-stone-red3 + rotate: false + xy: 525, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-stained-stone1 + rotate: false + xy: 457, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-stained-stone2 + rotate: false + xy: 559, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-stained-stone3 + rotate: false + xy: 525, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-stone1 + rotate: false + xy: 491, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-stone2 + rotate: false + xy: 559, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium-stone3 + rotate: false + xy: 525, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-salt + rotate: false + xy: 559, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +salt-icon-editor + rotate: false + xy: 559, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-sand-water + rotate: false + xy: 593, 287 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-water-icon-editor + rotate: false + xy: 593, 287 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-sand1 + rotate: false + xy: 593, 355 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-icon-editor + rotate: false + xy: 593, 355 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-sand2 + rotate: false + xy: 593, 321 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-sand3 + rotate: false + xy: 627, 355 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-snow1 + rotate: false + xy: 627, 321 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow-icon-editor + rotate: false + xy: 627, 321 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-snow2 + rotate: false + xy: 593, 253 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-snow3 + rotate: false + xy: 627, 287 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stained-stone-red1 + rotate: false + xy: 593, 219 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-red-icon-editor + rotate: false + xy: 593, 219 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stained-stone-yellow1 + rotate: false + xy: 627, 219 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-yellow-icon-editor + rotate: false + xy: 627, 219 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stained-stone1 + rotate: false + xy: 627, 253 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-icon-editor + rotate: false + xy: 627, 253 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stone3 + rotate: false + xy: 461, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-tar + rotate: false + xy: 495, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tar-icon-editor + rotate: false + xy: 495, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-water + rotate: false + xy: 529, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water-icon-editor + rotate: false + xy: 529, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +force-projector-icon-editor + rotate: false + xy: 843, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fortress-factory-icon-editor + rotate: false + xy: 941, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fuse-icon-editor + rotate: false + xy: 1039, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ghoul-factory-icon-editor + rotate: false + xy: 1137, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-editor + rotate: false + xy: 1235, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +graphite-press-icon-editor + rotate: false + xy: 813, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +hail-icon-editor + rotate: false + xy: 481, 155 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icerocks-icon-editor + rotate: false + xy: 481, 121 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +impact-reactor-icon-editor + rotate: false + xy: 485, 889 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +incinerator-icon-editor + rotate: false + xy: 515, 155 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-source-icon-editor + rotate: false + xy: 515, 121 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-void-icon-editor + rotate: false + xy: 499, 87 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-editor + rotate: false + xy: 879, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +junction-icon-editor + rotate: false + xy: 499, 53 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +kiln-icon-editor + rotate: false + xy: 945, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +lancer-icon-editor + rotate: false + xy: 1011, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +laser-drill-icon-editor + rotate: false + xy: 1333, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +launch-pad-icon-editor + rotate: false + xy: 1431, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +liquid-junction-icon-editor + rotate: false + xy: 499, 19 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-router-icon-editor + rotate: false + xy: 533, 87 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-source-icon-editor + rotate: false + xy: 533, 53 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-tank-icon-editor + rotate: false + xy: 1529, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +mass-driver-icon-editor + rotate: false + xy: 1627, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +mechanical-drill-icon-editor + rotate: false + xy: 1077, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mechanical-pump-icon-editor + rotate: false + xy: 533, 19 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +meltdown-icon-editor + rotate: false + xy: 1, 115 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +melter-icon-editor + rotate: false + xy: 549, 155 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mend-projector-icon-editor + rotate: false + xy: 1143, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +multi-press-icon-editor + rotate: false + xy: 1725, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +oil-extractor-icon-editor + rotate: false + xy: 1823, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-editor + rotate: false + xy: 1921, 921 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +overdrive-projector-icon-editor + rotate: false + xy: 1209, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +overflow-gate-icon-editor + rotate: false + xy: 549, 121 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phantom-factory-icon-editor + rotate: false + xy: 1275, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-conduit-icon-editor + rotate: false + xy: 567, 87 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conveyor-icon-editor + rotate: false + xy: 567, 53 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-icon-editor + rotate: false + xy: 567, 19 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-large-icon-editor + rotate: false + xy: 1341, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-weaver-icon-editor + rotate: false + xy: 1407, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pine-icon-editor + rotate: false + xy: 261, 129 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-editor + rotate: false + xy: 1473, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-editor + rotate: false + xy: 1539, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +power-node-icon-editor + rotate: false + xy: 661, 355 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-node-large-icon-editor + rotate: false + xy: 1605, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +power-source-icon-editor + rotate: false + xy: 661, 321 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-void-icon-editor + rotate: false + xy: 661, 287 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-icon-editor + rotate: false + xy: 661, 253 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulverizer-icon-editor + rotate: false + xy: 661, 219 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-editor + rotate: false + xy: 1671, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +repair-point-icon-editor + rotate: false + xy: 651, 723 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +revenant-factory-icon-editor + rotate: false + xy: 131, 245 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +ripple-icon-editor + rotate: false + xy: 197, 17 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +rocks-icon-editor + rotate: false + xy: 651, 689 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rotary-pump-icon-editor + rotate: false + xy: 1737, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +router-icon-editor + rotate: false + xy: 685, 723 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rtg-generator-icon-editor + rotate: false + xy: 1803, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +salvo-icon-editor + rotate: false + xy: 1869, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +sandrocks-icon-editor + rotate: false + xy: 651, 655 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-editor + rotate: false + xy: 323, 597 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-editor + rotate: false + xy: 261, 277 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-icon-editor + rotate: false + xy: 685, 689 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-editor + rotate: false + xy: 1935, 855 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +separator-icon-editor + rotate: false + xy: 421, 527 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +shock-mine-icon-editor + rotate: false + xy: 651, 621 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +silicon-smelter-icon-editor + rotate: false + xy: 421, 461 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +snowrocks-icon-editor + rotate: false + xy: 685, 655 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-icon-editor + rotate: false + xy: 685, 621 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-large-icon-editor + rotate: false + xy: 261, 179 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +sorter-icon-editor + rotate: false + xy: 719, 721 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spawn-icon-editor + rotate: false + xy: 753, 721 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spectre-icon-editor + rotate: false + xy: 615, 889 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +spirit-factory-icon-editor + rotate: false + xy: 487, 527 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-cluster-icon-editor + rotate: false + xy: 421, 419 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-press-icon-editor + rotate: false + xy: 487, 461 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +stained-boulder-icon-editor + rotate: false + xy: 719, 687 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks-icon-editor + rotate: false + xy: 787, 721 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks-red-icon-editor + rotate: false + xy: 719, 653 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks-yellow-icon-editor + rotate: false + xy: 753, 687 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-tower-icon-editor + rotate: false + xy: 553, 527 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +surge-wall-icon-editor + rotate: false + xy: 821, 721 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-wall-large-icon-editor + rotate: false + xy: 553, 461 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +swarmer-icon-editor + rotate: false + xy: 681, 757 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-editor + rotate: false + xy: 747, 789 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thermal-generator-icon-editor + rotate: false + xy: 813, 789 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thermal-pump-icon-editor + rotate: false + xy: 359, 303 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +thorium-reactor-icon-editor + rotate: false + xy: 359, 205 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +thorium-wall-icon-editor + rotate: false + xy: 753, 653 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-editor + rotate: false + xy: 879, 789 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thruster-icon-editor + rotate: false + xy: 131, 115 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +titan-factory-icon-editor + rotate: false + xy: 485, 791 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +titanium-conveyor-icon-editor + rotate: false + xy: 787, 687 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-wall-icon-editor + rotate: false + xy: 855, 721 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-editor + rotate: false + xy: 945, 789 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-editor + rotate: false + xy: 1011, 789 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +turbine-generator-icon-editor + rotate: false + xy: 1077, 789 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +unloader-icon-editor + rotate: false + xy: 787, 653 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +vault-icon-editor + rotate: false + xy: 583, 791 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +water-extractor-icon-editor + rotate: false + xy: 1143, 789 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wave-icon-editor + rotate: false + xy: 1209, 789 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +white-tree-dead-icon-editor + rotate: false + xy: 1, 697 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 +white-tree-icon-editor + rotate: false + xy: 1, 375 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 +wraith-factory-icon-editor + rotate: false + xy: 1275, 789 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 + +sprites3.png +size: 2048,1024 +format: RGBA8888 +filter: Nearest,Nearest +repeat: none +char1 + rotate: false + xy: 613, 457 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +char2 + rotate: false + xy: 679, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +char3 + rotate: false + xy: 745, 589 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cliffs1 + rotate: false + xy: 373, 393 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +coal1 + rotate: false + xy: 1019, 687 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +coal2 + rotate: false + xy: 1309, 785 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +coal3 + rotate: false + xy: 1591, 883 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper1 + rotate: false + xy: 1881, 981 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper2 + rotate: false + xy: 175, 43 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper3 + rotate: false + xy: 779, 589 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters1 + rotate: false + xy: 407, 393 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters2 + rotate: false + xy: 1053, 687 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters3 + rotate: false + xy: 1343, 785 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters4 + rotate: false + xy: 1625, 883 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters5 + rotate: false + xy: 1915, 981 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone1 + rotate: false + xy: 1915, 981 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters6 + rotate: false + xy: 209, 43 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone2 + rotate: false + xy: 209, 43 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +deepwater + rotate: false + xy: 813, 589 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +deepwater-edge + rotate: false + xy: 323, 917 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +dunerocks-large + rotate: false + xy: 1, 11 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dunerocks1 + rotate: false + xy: 441, 393 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dunerocks2 + rotate: false + xy: 1087, 687 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +edge-stencil-blocky + rotate: false + xy: 1, 273 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +edge-stencil-smooth + rotate: false + xy: 323, 819 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +grass-edge + rotate: false + xy: 613, 917 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +grass1 + rotate: false + xy: 1377, 785 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass2 + rotate: false + xy: 1659, 883 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass3 + rotate: false + xy: 1949, 981 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone-edge + rotate: false + xy: 1, 175 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +holostone1 + rotate: false + xy: 243, 43 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone2 + rotate: false + xy: 847, 589 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone3 + rotate: false + xy: 475, 393 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock1 + rotate: false + xy: 1121, 687 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock2 + rotate: false + xy: 1411, 785 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock3 + rotate: false + xy: 1693, 883 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-edge + rotate: false + xy: 323, 721 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +ice-snow-edge + rotate: false + xy: 613, 819 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +ice-snow1 + rotate: false + xy: 1445, 785 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow2 + rotate: false + xy: 1727, 883 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow3 + rotate: false + xy: 543, 393 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice1 + rotate: false + xy: 1983, 981 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice2 + rotate: false + xy: 509, 393 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice3 + rotate: false + xy: 1155, 687 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icerocks-large + rotate: false + xy: 613, 557 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +icerocks1 + rotate: false + xy: 577, 393 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icerocks2 + rotate: false + xy: 291, 337 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock-edge + rotate: false + xy: 903, 917 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +ignarock1 + rotate: false + xy: 291, 303 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock2 + rotate: false + xy: 291, 269 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock3 + rotate: false + xy: 291, 235 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lead1 + rotate: false + xy: 291, 201 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lead2 + rotate: false + xy: 291, 167 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lead3 + rotate: false + xy: 291, 133 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock1 + rotate: false + xy: 291, 99 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock2 + rotate: false + xy: 903, 621 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock3 + rotate: false + xy: 1193, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor + rotate: false + xy: 1483, 817 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged5 + rotate: false + xy: 1483, 817 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-2 + rotate: false + xy: 1773, 915 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-3 + rotate: false + xy: 647, 457 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-5 + rotate: false + xy: 713, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged1 + rotate: false + xy: 937, 621 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged2 + rotate: false + xy: 1227, 719 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged3 + rotate: false + xy: 1517, 817 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged4 + rotate: false + xy: 1807, 915 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged6 + rotate: false + xy: 613, 423 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-edge + rotate: false + xy: 1, 77 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +ore-coal-holostone1 + rotate: false + xy: 647, 423 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-holostone2 + rotate: false + xy: 325, 343 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-holostone3 + rotate: false + xy: 325, 309 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-sand1 + rotate: false + xy: 325, 275 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-sand2 + rotate: false + xy: 325, 241 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-sand3 + rotate: false + xy: 325, 207 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-red1 + rotate: false + xy: 1189, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-red2 + rotate: false + xy: 1223, 685 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-red3 + rotate: false + xy: 1479, 783 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone1 + rotate: false + xy: 325, 173 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone2 + rotate: false + xy: 325, 139 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone3 + rotate: false + xy: 325, 105 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stone1 + rotate: false + xy: 1513, 783 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stone2 + rotate: false + xy: 611, 389 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stone3 + rotate: false + xy: 645, 389 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-holostone1 + rotate: false + xy: 133, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-holostone2 + rotate: false + xy: 291, 65 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-holostone3 + rotate: false + xy: 325, 71 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-sand1 + rotate: false + xy: 1761, 881 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-sand2 + rotate: false + xy: 1795, 881 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-sand3 + rotate: false + xy: 971, 637 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-red1 + rotate: false + xy: 1087, 653 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-red2 + rotate: false + xy: 1121, 653 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-red3 + rotate: false + xy: 1155, 653 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone1 + rotate: false + xy: 1261, 735 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone2 + rotate: false + xy: 1019, 653 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone3 + rotate: false + xy: 1053, 653 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stone1 + rotate: false + xy: 1189, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stone2 + rotate: false + xy: 1223, 651 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stone3 + rotate: false + xy: 1309, 751 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-holostone1 + rotate: false + xy: 1343, 751 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-holostone2 + rotate: false + xy: 1377, 751 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-holostone3 + rotate: false + xy: 1411, 751 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-sand1 + rotate: false + xy: 1445, 751 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-sand2 + rotate: false + xy: 1479, 749 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-sand3 + rotate: false + xy: 1513, 749 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-red1 + rotate: false + xy: 475, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-red2 + rotate: false + xy: 509, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-red3 + rotate: false + xy: 543, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone1 + rotate: false + xy: 373, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone2 + rotate: false + xy: 407, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone3 + rotate: false + xy: 441, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stone1 + rotate: false + xy: 577, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stone2 + rotate: false + xy: 611, 355 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stone3 + rotate: false + xy: 645, 355 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-holostone1 + rotate: false + xy: 359, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-holostone2 + rotate: false + xy: 359, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-holostone3 + rotate: false + xy: 393, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-sand1 + rotate: false + xy: 359, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-sand2 + rotate: false + xy: 393, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-sand3 + rotate: false + xy: 427, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-snow1 + rotate: false + xy: 359, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-snow2 + rotate: false + xy: 393, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-snow3 + rotate: false + xy: 427, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red1 + rotate: false + xy: 427, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red2 + rotate: false + xy: 461, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red3 + rotate: false + xy: 495, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone1 + rotate: false + xy: 461, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone2 + rotate: false + xy: 359, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone3 + rotate: false + xy: 393, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stone1 + rotate: false + xy: 359, 155 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stone2 + rotate: false + xy: 393, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stone3 + rotate: false + xy: 427, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-holostone1 + rotate: false + xy: 461, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-holostone2 + rotate: false + xy: 495, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-holostone3 + rotate: false + xy: 529, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-sand1 + rotate: false + xy: 359, 121 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-sand2 + rotate: false + xy: 393, 155 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-sand3 + rotate: false + xy: 427, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-red1 + rotate: false + xy: 563, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-red2 + rotate: false + xy: 359, 87 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-red3 + rotate: false + xy: 393, 121 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone1 + rotate: false + xy: 461, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone2 + rotate: false + xy: 495, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone3 + rotate: false + xy: 529, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stone1 + rotate: false + xy: 427, 155 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stone2 + rotate: false + xy: 461, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stone3 + rotate: false + xy: 495, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-holostone1 + rotate: false + xy: 529, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-holostone2 + rotate: false + xy: 563, 291 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-holostone3 + rotate: false + xy: 393, 87 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-sand1 + rotate: false + xy: 427, 121 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-sand2 + rotate: false + xy: 461, 155 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-sand3 + rotate: false + xy: 495, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-red1 + rotate: false + xy: 461, 121 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-red2 + rotate: false + xy: 495, 155 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-red3 + rotate: false + xy: 529, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone1 + rotate: false + xy: 529, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone2 + rotate: false + xy: 563, 257 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone3 + rotate: false + xy: 427, 87 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stone1 + rotate: false + xy: 563, 223 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stone2 + rotate: false + xy: 461, 87 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stone3 + rotate: false + xy: 495, 121 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pine + rotate: false + xy: 323, 377 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rock1 + rotate: false + xy: 969, 671 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rock2 + rotate: false + xy: 1259, 769 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rocks-large + rotate: false + xy: 903, 655 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rocks1 + rotate: false + xy: 529, 155 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rocks2 + rotate: false + xy: 563, 189 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +salt + rotate: false + xy: 495, 87 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +salt-edge + rotate: false + xy: 323, 623 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +sand-edge + rotate: false + xy: 613, 721 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +sand-water + rotate: false + xy: 563, 121 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-water-edge + rotate: false + xy: 903, 819 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +sand1 + rotate: false + xy: 529, 121 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand2 + rotate: false + xy: 563, 155 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand3 + rotate: false + xy: 529, 87 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sandrocks-large + rotate: false + xy: 1193, 753 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +sandrocks1 + rotate: false + xy: 563, 87 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sandrocks2 + rotate: false + xy: 597, 321 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap1 + rotate: false + xy: 597, 287 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap2 + rotate: false + xy: 631, 321 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap3 + rotate: false + xy: 597, 253 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow-edge + rotate: false + xy: 1193, 917 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +snow1 + rotate: false + xy: 631, 287 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow2 + rotate: false + xy: 597, 219 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow3 + rotate: false + xy: 631, 253 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrocks-large + rotate: false + xy: 1483, 851 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +snowrocks1 + rotate: false + xy: 597, 185 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrocks2 + rotate: false + xy: 631, 219 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-cluster1 + rotate: false + xy: 1549, 875 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-cluster2 + rotate: false + xy: 1839, 973 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-cluster3 + rotate: false + xy: 133, 35 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +stained-boulder1 + rotate: false + xy: 597, 151 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-boulder2 + rotate: false + xy: 631, 185 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks-large + rotate: false + xy: 1773, 949 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +stained-rocks-red-large + rotate: false + xy: 67, 11 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +stained-rocks-red1 + rotate: false + xy: 631, 117 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks-red2 + rotate: false + xy: 597, 83 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks-yellow-large + rotate: false + xy: 613, 491 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +stained-rocks-yellow1 + rotate: false + xy: 631, 83 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks-yellow2 + rotate: false + xy: 971, 603 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks1 + rotate: false + xy: 597, 117 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks2 + rotate: false + xy: 631, 151 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-edge + rotate: false + xy: 323, 525 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +stained-stone-red-edge + rotate: false + xy: 613, 623 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +stained-stone-red1 + rotate: false + xy: 1107, 619 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-red3 + rotate: false + xy: 1107, 619 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-red2 + rotate: false + xy: 1141, 619 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-yellow-edge + rotate: false + xy: 903, 721 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +stained-stone-yellow1 + rotate: false + xy: 1175, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-yellow2 + rotate: false + xy: 1209, 617 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-yellow3 + rotate: false + xy: 1261, 701 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone1 + rotate: false + xy: 1005, 619 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone2 + rotate: false + xy: 1039, 619 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone3 + rotate: false + xy: 1073, 619 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stainedrocks-large + rotate: false + xy: 679, 557 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +stainedrocks1 + rotate: false + xy: 1257, 667 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stainedrocks2 + rotate: false + xy: 1295, 717 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone-edge + rotate: false + xy: 1193, 819 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +stone3 + rotate: false + xy: 1329, 717 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tar + rotate: false + xy: 1363, 717 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tar-edge + rotate: false + xy: 1483, 917 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +thorium1 + rotate: false + xy: 1397, 717 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium2 + rotate: false + xy: 1431, 717 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium3 + rotate: false + xy: 1465, 715 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium1 + rotate: false + xy: 1499, 715 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium2 + rotate: false + xy: 359, 53 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium3 + rotate: false + xy: 393, 53 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water + rotate: false + xy: 427, 53 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water-edge + rotate: false + xy: 323, 427 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +white-tree + rotate: false + xy: 1, 693 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 +white-tree-dead + rotate: false + xy: 1, 371 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index 911b882020..c744ce7a1c 100644 Binary files a/core/assets/sprites/sprites.png and b/core/assets/sprites/sprites.png differ diff --git a/core/assets/sprites/sprites2.png b/core/assets/sprites/sprites2.png new file mode 100644 index 0000000000..cf0a8e1fde Binary files /dev/null and b/core/assets/sprites/sprites2.png differ diff --git a/core/assets/sprites/sprites3.png b/core/assets/sprites/sprites3.png new file mode 100644 index 0000000000..6c749afad5 Binary files /dev/null and b/core/assets/sprites/sprites3.png differ diff --git a/core/assets/sprites/uiskin.json b/core/assets/sprites/uiskin.json index 3006ee32f2..f57d3613ec 100644 --- a/core/assets/sprites/uiskin.json +++ b/core/assets/sprites/uiskin.json @@ -1,81 +1,308 @@ { -Color: { - black: {a: 1, b: 0, g: 0, r: 0 }, - white: {a: 1, b: 1, g: 1, r: 1 }, - gray: {a: 1, b: 0.32, g: 0.32, r: 0.32 }, - lightgray: {a: 1, b: 0.65, g: 0.65, r: 0.65 } - orange: {hex: "FFA500"}, - accent: {hex: "ffd37f"} -}, -TintedDrawable: { - dialogDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.9} }, - invis: {name: white, color: {r: 0, g: 0, b: 0, a: 0} } - loadDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.8} }, - chatfield: {name: white, color: {r: 0, g: 0, b: 0, a: 0.2}}, - dark: {name: white, color: {hex: "#000000ff"}}, - none: {name: white, color: {r: 0, g: 0, b: 0, a: 0}}, - flat: {name: white, color: {r: 0.0, g: 0.0, b: 0.0, a: 0.6}}, - flat-over: {name: white, color: { hex: "#ffffff82" }}, - flat-down: {name: white, color: { hex: "#ffd37fff" }} -}, -ButtonStyle: { - default: {down: button-down, up: button }, - toggle: {checked: button-down, down: button-down, up: button } -}, -TextButtonStyle: { - default: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: gray, down: button-down, up: button}, - node: {disabled: content-background, font: default-font, fontColor: white, disabledFontColor: gray, up: content-background, over: content-background-over}, - right: {over: button-right-over, font: default-font, fontColor: white, disabledFontColor: gray, down: button-right-down, up: button-right}, - wave: {font: default-font, fontColor: white, disabledFontColor: gray, up: button-edge-4}, - clear: {over: flat-over, font: default-font, fontColor: white, disabledFontColor: gray, down: flat-over, up: flat}, - discord: {font: default-font, fontColor: white, up: discord-banner}, - info: {font: default-font, fontColor: white, up: info-banner}, - clear-partial: {down: white, up: button-select, over: flat-down, font: default-font, fontColor: white, disabledFontColor: gray }, - clear-partial-2: {down: flat-over, up: none, over: flat-over, font: default-font, fontColor: white, disabledFontColor: gray }, - empty: {font: default-font}, - clear-toggle: {font: default-font, fontColor: white, checked: flat-down, down: flat-down, up: flat, over: flat-over, disabled: flat, disabledFontColor: gray } - toggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: gray } -}, -ImageButtonStyle: { - default: {down: button-down, up: button, over: button-over, imageDisabledColor: gray, imageUpColor: white }, - node: {up: content-background, over: content-background-over}, - right: {over: button-right-over, down: button-right-down, up: button-right}, - empty: { imageDownColor: accent, imageUpColor: white}, - emptytoggle: {imageCheckedColor: white, imageDownColor: white, imageUpColor: gray}, - static: {up: button }, - static-down: {up: button-down }, - toggle: {checked: button-down, down: button-down, up: button, imageDisabledColor: gray, imageUpColor: white }, - select: {checked: button-select, up: none }, - clear: {down: flat-over, up: flat, over: flat-over}, - clear-full: {down: white, up: button-select, over: flat-down}, - clear-partial: {down: flat-down, up: none, over: flat-over}, - clear-toggle: {down: flat-down, checked: flat-down, up: flat, over: flat-over}, - clear-toggle-partial: {down: flat-down, checked: flat-down, up: none, over: flat-over}, -}, -ScrollPaneStyle: { - default: {vScroll: scroll, vScrollKnob: scroll-knob-vertical-black}, - horizontal: {vScroll: scroll, vScrollKnob: scroll-knob-vertical-black, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal-black}, -}, -WindowStyle: { - default: {titleFont: default-font, titleFontColor: accent }, - dialog: {stageBackground: dialogDim, titleFont: default-font, background: window-empty, titleFontColor: accent } -}, -KeybindDialogStyle: { - default: {keyColor: accent, keyNameColor: white, controllerColor: lightgray}, -}, -SliderStyle: { - default-horizontal: {background: slider, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down}, - default-vertical: {background: slider-vertical, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down} -}, -LabelStyle: { - default: {font: default-font, fontColor: white }, - small: {font: default-font, fontColor: white } -}, -TextFieldStyle: { - default: {font: default-font-chat, fontColor: white, disabledFontColor: gray, selection: selection, background: underline, cursor: cursor, messageFont: default-font, messageFontColor: gray } - textarea: {font: default-font-chat, fontColor: white, disabledFontColor: gray, selection: selection, background: underline, cursor: cursor, messageFont: default-font, messageFontColor: gray } -}, -CheckBoxStyle: { - default: {checkboxOn: check-on, checkboxOff: check-off, checkboxOnOver: check-on-over, checkboxOver: check-over, font: default-font, fontColor: white, disabledFontColor: gray } -} + Color: { + black: { a: 1, b: 0, g: 0, r: 0 }, + white: { a: 1, b: 1, g: 1, r: 1 }, + gray: { a: 1, b: 0.32, g: 0.32, r: 0.32 }, + lightgray: { a: 1, b: 0.65, g: 0.65, r: 0.65 } + orange: { hex: "FFA500" }, + accent: { hex: "ffd37f" } + }, + TintedDrawable: { + dialogDim: { + name: white, + color: { r: 0, g: 0, b: 0, a: 0.9 } + }, + invis: { + name: white, + color: { r: 0, g: 0, b: 0, a: 0 } + } + loadDim: { + name: white, + color: { r: 0, g: 0, b: 0, a: 0.8 } + }, + chatfield: { + name: white, + color: { r: 0, g: 0, b: 0, a: 0.2 } + }, + dark: { + name: white, + color: { hex: "#000000ff" } + }, + none: { + name: white, + color: { r: 0, g: 0, b: 0, a: 0 } + }, + flat: { + name: white, + color: { r: 0.0, g: 0.0, b: 0.0, a: 0.6 } + }, + flat-over: { + name: white, + color: { hex: "#ffffff82" } + }, + flat-down: { + name: white, + color: { hex: "#ffd37fff" } + } + }, + ButtonStyle: { + default: { + down: button-down, + up: button + }, + toggle: { + checked: button-down, + down: button-down, + up: button + } + }, + TextButtonStyle: { + default: { + over: button-over, + disabled: button-disabled, + font: default-font, + fontColor: white, + disabledFontColor: gray, + down: button-down, + up: button + }, + node: { + disabled: content-background-locked, + font: default-font, + fontColor: white, + disabledFontColor: gray, + up: content-background, + over: content-background-over + }, + right: { + over: button-right-over, + font: default-font, + fontColor: white, + disabledFontColor: gray, + down: button-right-down, + up: button-right + }, + wave: { + font: default-font, + fontColor: white, + disabledFontColor: gray, + up: button-edge-4 + }, + clear: { + over: flat-over, + font: default-font, + fontColor: white, + disabledFontColor: gray, + down: flat-over, + up: flat + }, + discord: { + font: default-font, + fontColor: white, + up: discord-banner + }, + info: { + font: default-font, + fontColor: white, + up: info-banner + }, + clear-partial: { + down: white, + up: button-select, + over: flat-down, + font: default-font, + fontColor: white, + disabledFontColor: gray + }, + clear-partial-2: { + down: flat-over, + up: none, + over: flat-over, + font: default-font, + fontColor: white, + disabledFontColor: gray + }, + empty: { + font: default-font + }, + clear-toggle: { + font: default-font, + fontColor: white, + checked: flat-down, + down: flat-down, + up: flat, + over: flat-over, + disabled: flat, + disabledFontColor: gray + } + toggle: { + font: default-font, + fontColor: white, + checked: button-down, + down: button-down, + up: button, + over: button-over, + disabled: button, + disabledFontColor: gray + } + }, + ImageButtonStyle: { + default: { + down: button-down, + up: button, + over: button-over, + imageDisabledColor: gray, + imageUpColor: white + }, + node: { + up: content-background, + over: content-background-over + }, + right: { + over: button-right-over, + down: button-right-down, + up: button-right + }, + empty: { + imageDownColor: accent, + imageUpColor: white + }, + emptytoggle: { + imageCheckedColor: white, + imageDownColor: white, + imageUpColor: gray + }, + static: { + up: button + }, + static-down: { + up: button-down + }, + toggle: { + checked: button-down, + down: button-down, + up: button, + imageDisabledColor: gray, + imageUpColor: white + }, + select: { + checked: button-select, + up: none + }, + clear: { + down: flat-over, + up: flat, + over: flat-over + }, + clear-full: { + down: white, + up: button-select, + over: flat-down + }, + clear-partial: { + down: flat-down, + up: none, + over: flat-over + }, + clear-toggle: { + down: flat-down, + checked: flat-down, + up: flat, + over: flat-over + }, + clear-toggle-partial: { + down: flat-down, + checked: flat-down, + up: none, + over: flat-over + }, + }, + ScrollPaneStyle: { + default: { + vScroll: scroll, + vScrollKnob: scroll-knob-vertical-black + }, + horizontal: { + vScroll: scroll, + vScrollKnob: scroll-knob-vertical-black, + hScroll: scroll-horizontal, + hScrollKnob: scroll-knob-horizontal-black + }, + }, + WindowStyle: { + default: { + titleFont: default-font, + titleFontColor: accent + }, + dialog: { + stageBackground: dialogDim, + titleFont: default-font, + background: window-empty, + titleFontColor: accent + } + }, + KeybindDialogStyle: { + default: { + keyColor: accent, + keyNameColor: white, + controllerColor: lightgray + }, + }, + SliderStyle: { + default-horizontal: { + background: slider, + knob: slider-knob, + knobOver: slider-knob-over, + knobDown: slider-knob-down + }, + default-vertical: { + background: slider-vertical, + knob: slider-knob, + knobOver: slider-knob-over, + knobDown: slider-knob-down + } + }, + LabelStyle: { + default: { + font: default-font, + fontColor: white + }, + small: { + font: default-font, + fontColor: white + } + }, + TextFieldStyle: { + default: { + font: default-font-chat, + fontColor: white, + disabledFontColor: gray, + selection: selection, + background: underline, + cursor: cursor, + messageFont: default-font, + messageFontColor: gray + } + textarea: { + font: default-font-chat, + fontColor: white, + disabledFontColor: gray, + selection: selection, + background: underline, + cursor: cursor, + messageFont: default-font, + messageFontColor: gray + } + }, + CheckBoxStyle: { + default: { + checkboxOn: check-on, + checkboxOff: check-off, + checkboxOnOver: check-on-over, + checkboxOver: check-over, + font: default-font, + fontColor: white, + disabledFontColor: gray + } + } } diff --git a/core/build.gradle b/core/build.gradle index f4c5695bbb..abcec6d8f6 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,8 +1,4 @@ apply plugin: "java" sourceCompatibility = 1.8 [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' -sourceSets.main.java.srcDirs = ["src/"] - -compileJava{ - options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" -} \ No newline at end of file +sourceSets.main.java.srcDirs = ["src/"] \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/Mindustry.java b/core/src/io/anuke/mindustry/Mindustry.java index c00058a403..44840a9aa4 100644 --- a/core/src/io/anuke/mindustry/Mindustry.java +++ b/core/src/io/anuke/mindustry/Mindustry.java @@ -17,7 +17,7 @@ public class Mindustry extends ApplicationCore{ public void setup(){ Time.setDeltaProvider(() -> { float result = Core.graphics.getDeltaTime() * 60f; - return Float.isNaN(result) || Float.isInfinite(result) ? 1f : Math.min(result, 60f / 10f); + return (Float.isNaN(result) || Float.isInfinite(result)) ? 1f : Math.min(result, 60f / 10f); }); Time.mark(); @@ -27,6 +27,7 @@ public class Mindustry extends ApplicationCore{ Log.setUseColors(false); BundleLoader.load(); content.load(); + content.loadColors(); add(logic = new Logic()); add(world = new World()); @@ -47,18 +48,18 @@ public class Mindustry extends ApplicationCore{ @Override public void update(){ - long lastFrameTime = Time.millis(); + long lastFrameTime = Time.nanos(); super.update(); int fpsCap = Core.settings.getInt("fpscap", 125); if(fpsCap <= 120){ - long target = 1000/fpsCap; - long elapsed = Time.timeSinceMillis(lastFrameTime); + long target = (1000 * 1000000)/fpsCap; //target in nanos + long elapsed = Time.timeSinceNanos(lastFrameTime); if(elapsed < target){ try{ - Thread.sleep(target - elapsed); + Thread.sleep((target - elapsed) / 1000000, (int)((target - elapsed) % 1000000)); }catch(InterruptedException e){ e.printStackTrace(); } diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index 5164fd56ae..707f1d586c 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -2,21 +2,21 @@ package io.anuke.mindustry; import io.anuke.arc.Application.ApplicationType; import io.anuke.arc.Core; -import io.anuke.arc.entities.Entities; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.impl.EffectEntity; -import io.anuke.arc.entities.trait.DrawTrait; import io.anuke.arc.files.FileHandle; import io.anuke.arc.graphics.Color; import io.anuke.arc.util.Structs; import io.anuke.mindustry.core.*; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.Entities; +import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.effect.Fire; import io.anuke.mindustry.entities.effect.Puddle; +import io.anuke.mindustry.entities.impl.EffectEntity; +import io.anuke.mindustry.entities.traits.DrawTrait; import io.anuke.mindustry.entities.traits.SyncTrait; -import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.game.GlobalData; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Version; @@ -24,11 +24,14 @@ import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity; +import java.nio.charset.Charset; import java.util.Arrays; import java.util.Locale; @SuppressWarnings("unchecked") public class Vars{ + /**global charset*/ + public static final Charset charset = Charset.forName("UTF-8"); /**main application name, capitalized*/ public static final String appName = "Mindustry"; /**URL for discord invite.*/ @@ -45,12 +48,22 @@ public class Vars{ public static final Team defaultTeam = Team.blue; /**team of the enemy in waves/sectors*/ public static final Team waveTeam = Team.red; + /**how many times longer a boss wave takes*/ + public static final float bossWaveMultiplier = 3f; + /**how many times longer a launch wave takes*/ + public static final float launchWaveMultiplier = 2f; /**max chat message length*/ public static final int maxTextLength = 150; /**max player name length in bytes*/ public static final int maxNameLength = 40; /**displayed item size when ingame, TODO remove.*/ public static final float itemSize = 5f; + /**extra padding around the world; units outside this bound will begin to self-destruct.*/ + public static final float worldBounds = 100f; + /**units outside of this bound will simply die instantly*/ + public static final float finalWorldBounds = worldBounds + 500; + /**ticks spent out of bound until self destruct.*/ + public static final float boundsCountdown = 60*7; /**size of tiles in units*/ public static final int tilesize = 8; /**all choosable player colors in join/host dialog*/ @@ -146,6 +159,9 @@ public class Vars{ Version.init(); content = new ContentLoader(); + if(!headless){ + content.setVerbose(); + } playerGroup = Entities.addGroup(Player.class).enableMapping(); tileGroup = Entities.addGroup(TileEntity.class, false); diff --git a/core/src/io/anuke/mindustry/ai/BlockIndexer.java b/core/src/io/anuke/mindustry/ai/BlockIndexer.java index 6f5e840dcf..604b63e294 100644 --- a/core/src/io/anuke/mindustry/ai/BlockIndexer.java +++ b/core/src/io/anuke/mindustry/ai/BlockIndexer.java @@ -6,7 +6,7 @@ import io.anuke.arc.function.Predicate; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.game.EventType.TileChangeEvent; import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.Team; @@ -17,8 +17,6 @@ import io.anuke.mindustry.world.meta.BlockFlag; import static io.anuke.mindustry.Vars.*; -//TODO consider using quadtrees for finding specific types of blocks within an area - /**Class used for indexing special target blocks for AI.*/ @SuppressWarnings("unchecked") public class BlockIndexer{ @@ -28,7 +26,7 @@ public class BlockIndexer{ private final static int structQuadrantSize = 12; /**Set of all ores that are being scanned.*/ - private final ObjectSet scanOres = new ObjectSet(){{addAll(Item.getAllOres());}}; + private final ObjectSet scanOres = ObjectSet.with(Item.getAllOres().toArray(Item.class)); private final ObjectSet itemSet = new ObjectSet<>(); /**Stores all ore quadtrants on the map.*/ private ObjectMap> ores; @@ -215,7 +213,7 @@ public class BlockIndexer{ } private void process(Tile tile){ - if(tile.block().flags != null && + if(tile.block().flags.size() > 0 && tile.getTeam() != Team.none){ ObjectSet[] map = getFlagged(tile.getTeam()); @@ -282,7 +280,7 @@ public class BlockIndexer{ outer: for(int x = quadrantX * structQuadrantSize; x < world.width() && x < (quadrantX + 1) * structQuadrantSize; x++){ for(int y = quadrantY * structQuadrantSize; y < world.height() && y < (quadrantY + 1) * structQuadrantSize; y++){ - Tile result = world.tile(x, y); + Tile result = world.tile(x, y).target(); //when a targetable block is found, mark this quadrant as occupied and stop searching if(result.entity != null && result.getTeam() == data.team){ structQuadrants[data.team.ordinal()].set(index); diff --git a/core/src/io/anuke/mindustry/ai/Pathfinder.java b/core/src/io/anuke/mindustry/ai/Pathfinder.java index 2f27133d89..bd162140e5 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfinder.java +++ b/core/src/io/anuke/mindustry/ai/Pathfinder.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.ai; import io.anuke.arc.Events; import io.anuke.arc.collection.IntArray; -import io.anuke.arc.collection.Queue; +import io.anuke.arc.collection.IntQueue; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Point2; import io.anuke.arc.util.Structs; @@ -12,6 +12,7 @@ import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Teams.TeamData; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.world.Pos; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockFlag; @@ -19,7 +20,7 @@ import static io.anuke.mindustry.Vars.state; import static io.anuke.mindustry.Vars.world; public class Pathfinder{ - private long maxUpdate = Time.millisToNanos(4); + private static final long maxUpdate = Time.millisToNanos(4); private PathData[] paths; private IntArray blocked = new IntArray(); @@ -39,10 +40,6 @@ public class Pathfinder{ }); } - public void activateTeamPath(Team team){ - createFor(team); - } - public void update(){ if(Net.client() || paths == null) return; @@ -110,7 +107,7 @@ public class Pathfinder{ for(Tile other : world.indexer.getEnemy(team, BlockFlag.target)){ path.weights[other.x][other.y] = 0; path.searches[other.x][other.y] = (short)path.search; - path.frontier.addFirst(other); + path.frontier.addFirst(other.pos()); } } } @@ -128,9 +125,9 @@ public class Pathfinder{ for(int y = 0; y < world.height(); y++){ Tile tile = world.tile(x, y); - if(tile.block().flags != null && state.teams.areEnemies(tile.getTeam(), team) + if(state.teams.areEnemies(tile.getTeam(), team) && tile.block().flags.contains(BlockFlag.target)){ - path.frontier.addFirst(tile); + path.frontier.addFirst(tile.pos()); path.weights[x][y] = 0; path.searches[x][y] = (short)path.search; }else{ @@ -145,12 +142,19 @@ public class Pathfinder{ private void updateFrontier(Team team, long nsToRun){ PathData path = paths[team.ordinal()]; - long start = Time.nanoTime(); + long start = Time.nanos(); while(path.frontier.size > 0 && (nsToRun < 0 || Time.timeSinceNanos(start) <= nsToRun)){ - Tile tile = path.frontier.removeLast(); + Tile tile = world.tile(path.frontier.removeLast()); + if(tile == null || path.weights == null) return; //something went horribly wrong, bail float cost = path.weights[tile.x][tile.y]; + //pathfinding overflowed for some reason, time to bail. the next block update will handle this, hopefully + if(path.frontier.size >= world.width() * world.height()){ + path.frontier.clear(); + return; + } + if(cost < Float.MAX_VALUE){ for(Point2 point : Geometry.d4){ @@ -159,7 +163,8 @@ public class Pathfinder{ if(other != null && (path.weights[dx][dy] > cost + other.cost || path.searches[dx][dy] < path.search) && passable(other, team)){ - path.frontier.addFirst(world.tile(dx, dy)); + if(other.cost < 0) throw new IllegalArgumentException("Tile cost cannot be negative! " + other); + path.frontier.addFirst(Pos.get(dx, dy)); path.weights[dx][dy] = cost + other.cost; path.searches[dx][dy] = (short)path.search; } @@ -189,6 +194,6 @@ public class Pathfinder{ short[][] searches; int search = 0; long lastSearchTime; - Queue frontier = new Queue<>(); + IntQueue frontier = new IntQueue(); } } diff --git a/core/src/io/anuke/mindustry/ai/WaveSpawner.java b/core/src/io/anuke/mindustry/ai/WaveSpawner.java index ec098dcf8d..c32006b4de 100644 --- a/core/src/io/anuke/mindustry/ai/WaveSpawner.java +++ b/core/src/io/anuke/mindustry/ai/WaveSpawner.java @@ -2,25 +2,61 @@ package io.anuke.mindustry.ai; import io.anuke.arc.Events; import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.IntArray; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Time; +import io.anuke.arc.util.Tmp; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.entities.units.BaseUnit; -import io.anuke.mindustry.entities.units.Squad; +import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Damage; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.type.BaseUnit; import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.SpawnGroup; +import io.anuke.mindustry.world.Pos; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; import static io.anuke.mindustry.Vars.*; public class WaveSpawner{ + private static final float shockwaveBase = 380f, shockwaveRand = 50f, maxShockwaveDst = shockwaveBase + shockwaveRand; private Array groups; private Array flySpawns = new Array<>(); private Array groundSpawns = new Array<>(); + private IntArray loadedSpawns = new IntArray(); public WaveSpawner(){ Events.on(WorldLoadEvent.class, e -> reset()); } + public void write(DataOutput stream) throws IOException{ + stream.writeInt(groundSpawns.size); + for(GroundSpawn spawn : groundSpawns){ + stream.writeInt(Pos.get(spawn.x, spawn.y)); + } + } + + public void read(DataInput stream) throws IOException{ + flySpawns.clear(); + groundSpawns.clear(); + loadedSpawns.clear(); + + int amount = stream.readInt(); + + for(int i = 0; i < amount; i++){ + loadedSpawns.add(stream.readInt()); + } + } + + /**@return true if the player is near a ground spawn point.*/ + public boolean playerNear(){ + return groundSpawns.count(g -> Mathf.dst(g.x * tilesize, g.y * tilesize, players[0].x, players[0].y) < maxShockwaveDst) > 0; + } + public void spawnEnemies(){ for(SpawnGroup group : groups){ @@ -31,7 +67,6 @@ public class WaveSpawner{ if(group.type.isFlying){ for(FlyerSpawn spawn : flySpawns){ - Squad squad = new Squad(); float margin = 40f; //how far away from the edge flying units spawn float trns = (world.width() + world.height()) * tilesize; spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(spawn.angle, trns), -margin, world.width() * tilesize + margin); @@ -40,32 +75,34 @@ public class WaveSpawner{ for(int i = 0; i < spawned; i++){ BaseUnit unit = group.createUnit(waveTeam); - unit.setWave(); - unit.setSquad(squad); unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread)); unit.add(); } } }else{ for(GroundSpawn spawn : groundSpawns){ - Squad squad = new Squad(); spawnX = spawn.x * tilesize; spawnY = spawn.y * tilesize; - spread = tilesize; + spread = tilesize*2; for(int i = 0; i < spawned; i++){ + Tmp.v1.rnd(spread); + BaseUnit unit = group.createUnit(waveTeam); - unit.setWave(); - unit.setSquad(squad); - unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread)); - unit.add(); + unit.set(spawnX + Tmp.v1.x, spawnY + Tmp.v1.y); + + Time.run(i*5, () -> shockwave(unit)); } + Time.run(20f, () -> Effects.effect(Fx.spawnShockwave, spawn.x * tilesize, spawn.y * tilesize)); + //would be interesting to see player structures survive this without hacks + Time.run(40f, () -> Damage.damage(waveTeam, spawn.x * tilesize, spawn.y * tilesize, shockwaveBase + Mathf.random(shockwaveRand), 99999999f)); } } } } private void reset(){ + flySpawns.clear(); groundSpawns.clear(); groups = state.rules.spawns; @@ -73,17 +110,39 @@ public class WaveSpawner{ for(int x = 0; x < world.width(); x++){ for(int y = 0; y < world.height(); y++){ if(world.tile(x, y).block() == Blocks.spawn){ - GroundSpawn spawn = new GroundSpawn(); - spawn.x = x; - spawn.y = y; - groundSpawns.add(spawn); + addSpawns(x, y); - FlyerSpawn fspawn = new FlyerSpawn(); - fspawn.angle = Angles.angle(world.width()/2f, world.height()/2f, x, y); - flySpawns.add(fspawn); + //hide spawnpoints, they have served their purpose + world.tile(x, y).setBlock(Blocks.air); } } } + + for(int i = 0; i < loadedSpawns.size; i++){ + int pos = loadedSpawns.get(i); + addSpawns(Pos.x(pos), Pos.y(pos)); + } + + loadedSpawns.clear(); + } + + private void addSpawns(int x, int y){ + GroundSpawn spawn = new GroundSpawn(); + spawn.x = x; + spawn.y = y; + groundSpawns.add(spawn); + + FlyerSpawn fspawn = new FlyerSpawn(); + fspawn.angle = Angles.angle(world.width()/2f, world.height()/2f, x, y); + flySpawns.add(fspawn); + } + + private void shockwave(BaseUnit unit){ + Effects.effect(Fx.unitSpawn, unit.x, unit.y, 0f, unit); + Time.run(30f, () -> { + unit.add(); + Effects.effect(Fx.spawn, unit); + }); } private class FlyerSpawn{ diff --git a/core/src/io/anuke/mindustry/content/Blocks.java b/core/src/io/anuke/mindustry/content/Blocks.java index 192a83863a..43ff6bdc00 100644 --- a/core/src/io/anuke/mindustry/content/Blocks.java +++ b/core/src/io/anuke/mindustry/content/Blocks.java @@ -1,7 +1,9 @@ package io.anuke.mindustry.content; +import io.anuke.arc.Core; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.graphics.CacheLayer; import io.anuke.mindustry.type.Category; @@ -18,31 +20,34 @@ import io.anuke.mindustry.world.blocks.production.*; import io.anuke.mindustry.world.blocks.sandbox.*; import io.anuke.mindustry.world.blocks.storage.CoreBlock; import io.anuke.mindustry.world.blocks.storage.LaunchPad; -import io.anuke.mindustry.world.blocks.storage.SortedUnloader; +import io.anuke.mindustry.world.blocks.storage.Unloader; import io.anuke.mindustry.world.blocks.storage.Vault; import io.anuke.mindustry.world.blocks.units.MechPad; -import io.anuke.mindustry.world.blocks.units.Reconstructor; import io.anuke.mindustry.world.blocks.units.RepairPoint; import io.anuke.mindustry.world.blocks.units.UnitFactory; +import io.anuke.mindustry.world.consumers.ConsumeItemFilter; +import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; -import static io.anuke.mindustry.Vars.content; -import static io.anuke.mindustry.Vars.state; +import static io.anuke.mindustry.Vars.*; public class Blocks implements ContentList{ public static Block //environment - air, part, spawn, space, metalfloor, deepwater, water, tar, stone, craters, blackstone, dirt, sand, ice, snow, - grass, shrub, rock, icerock, blackrock, rocks, + air, part, spawn, deepwater, water, tar, stone, craters, charr, sand, ice, snow, + holostone, rocks, icerocks, cliffs, pine, whiteTree, whiteTreeDead, sporeCluster, + iceSnow, sandWater, duneRocks, sandRocks, stainedRocks, moss, stainedRocksRed, stainedStoneRed, stainedRocksYellow, stainedStoneYellow, stainedBoulder, grass, salt, + metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor5, ignarock, magmarock, hotrock, snowrocks, //crafting - siliconSmelter, plastaniumCompressor, phaseWeaver, surgeSmelter, pyratiteMixer, blastMixer, cryofluidMixer, - melter, separator, centrifuge, biomatterCompressor, pulverizer, incinerator, + siliconSmelter, kiln, graphitePress, plastaniumCompressor, multiPress, phaseWeaver, surgeSmelter, pyratiteMixer, blastMixer, cryofluidMixer, + melter, separator, sporePress, pulverizer, incinerator, //sandbox powerVoid, powerSource, itemSource, liquidSource, itemVoid, //defense + scrapWall, scrapWallLarge, scrapWallHuge, scrapWallGigantic, thruster, //ok, these names are getting ridiculous, but at least I don't have humongous walls yet copperWall, copperWallLarge, titaniumWall, titaniumWallLarge, thoriumWall, thoriumWallLarge, door, doorLarge, phaseWall, phaseWallLarge, surgeWall, surgeWallLarge, mendProjector, overdriveProjector, forceProjector, shockMine, @@ -53,24 +58,24 @@ public class Blocks implements ContentList{ mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, liquidRouter, liquidTank, liquidJunction, bridgeConduit, phaseConduit, //power - combustionGenerator, thermalGenerator, turbineGenerator, rtgGenerator, solarPanel, largeSolarPanel, thoriumReactor, - fusionReactor, battery, batteryLarge, powerNode, powerNodeLarge, + combustionGenerator, thermalGenerator, turbineGenerator, differentialGenerator, rtgGenerator, solarPanel, largeSolarPanel, thoriumReactor, + impactReactor, battery, batteryLarge, powerNode, powerNodeLarge, surgeTower, //production - mechanicalDrill, pneumaticDrill, laserDrill, blastDrill, plasmaDrill, waterExtractor, oilExtractor, cultivator, + mechanicalDrill, pneumaticDrill, laserDrill, blastDrill, waterExtractor, oilExtractor, cultivator, //storage - core, vault, container, unloader, launchPad, + coreShard, coreFoundation, coreNucleus, vault, container, unloader, launchPad, //turrets duo, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, //units - spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, titanFactory, - fortressFactory, reconstructor, repairPoint, + spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, crawlerFactory, titanFactory, + fortressFactory, repairPoint, //upgrades - alphaPad, deltaPad, tauPad, omegaPad, dartPad, javelinPad, tridentPad, glaivePad; + alphaDartPad, deltaPad, tauPad, omegaPad, javelinPad, tridentPad, glaivePad; @Override public void load(){ @@ -83,6 +88,13 @@ public class Blocks implements ContentList{ public void draw(Tile tile){} public void load(){} public void init(){} + public boolean isHidden(){ return true; } + public TextureRegion[] variantRegions(){ + if(variantRegions == null){ + variantRegions = new TextureRegion[]{Core.atlas.find("clear")}; + } + return variantRegions; + } }; part = new BlockPart(); @@ -97,20 +109,8 @@ public class Blocks implements ContentList{ new BuildBlock("build" + i); } - space = new Floor("space"){{ - placeableOn = false; - variants = 0; - cacheLayer = CacheLayer.space; - solid = true; - minimapColor = Color.valueOf("000001"); - }}; - - metalfloor = new Floor("metalfloor"){{ - variants = 6; - }}; - deepwater = new Floor("deepwater"){{ - liquidColor = Color.valueOf("546bb3"); + liquidColor = Color.valueOf("4d5ca4"); speedMultiplier = 0.2f; variants = 0; liquidDrop = Liquids.water; @@ -119,11 +119,10 @@ public class Blocks implements ContentList{ statusDuration = 120f; drownTime = 140f; cacheLayer = CacheLayer.water; - minimapColor = Color.valueOf("465a96"); }}; water = new Floor("water"){{ - liquidColor = Color.valueOf("546bb3"); + liquidColor = Color.valueOf("596ab8"); speedMultiplier = 0.5f; variants = 0; status = StatusEffects.wet; @@ -131,7 +130,6 @@ public class Blocks implements ContentList{ liquidDrop = Liquids.water; isLiquid = true; cacheLayer = CacheLayer.water; - minimapColor = Color.valueOf("506eb4"); }}; tar = new Floor("tar"){{ @@ -143,86 +141,228 @@ public class Blocks implements ContentList{ variants = 0; liquidDrop = Liquids.oil; isLiquid = true; - cacheLayer = CacheLayer.oil; - minimapColor = Color.valueOf("292929"); + cacheLayer = CacheLayer.tar; }}; stone = new Floor("stone"){{ hasOres = true; - minimapColor = Color.valueOf("323232"); }}; craters = new Floor("craters"){{ - minimapColor = Color.valueOf("323232"); + variants = 6; + blendGroup = stone; }}; - blackstone = new Floor("blackstone"){{ - minimapColor = Color.valueOf("252525"); - playerUnmineable = true; - hasOres = true; + charr = new Floor("char"){{ + blendGroup = stone; }}; - dirt = new Floor("dirt"){{ - minimapColor = Color.valueOf("6e501e"); + sandWater = new Floor("sand-water"){{ + liquidColor = Color.valueOf("596ab8"); + speedMultiplier = 0.8f; + variants = 0; + status = StatusEffects.wet; + statusDuration = 50f; + liquidDrop = Liquids.water; + isLiquid = true; + cacheLayer = CacheLayer.water; }}; sand = new Floor("sand"){{ itemDrop = Items.sand; - minimapColor = Color.valueOf("988a67"); hasOres = true; playerUnmineable = true; }}; - ice = new Floor("ice"){{ - dragMultiplier = 0.2f; - speedMultiplier = 0.4f; - minimapColor = Color.valueOf("b8eef8"); - hasOres = true; - }}; - - snow = new Floor("snow"){{ - minimapColor = Color.valueOf("c2d1d2"); + holostone = new Floor("holostone"){{ hasOres = true; + edgeStyle = "blocky"; }}; grass = new Floor("grass"){{ - hasOres = true; - minimapColor = Color.valueOf("549d5b"); + }}; - shrub = new Rock("shrub"); - - rock = new Rock("rock"){{ - variants = 2; + salt = new Floor("salt"){{ + variants = 0; }}; - icerock = new Rock("icerock"){{ - variants = 2; + iceSnow = new Floor("ice-snow"){{ + variants = 3; }}; - blackrock = new Rock("blackrock"){{ + snow = new Floor("snow"){{ + }}; + + ice = new Floor("ice"){{ + //TODO fix + dragMultiplier = 1f; + speedMultiplier = 1f; + }}; + + cliffs = new StaticWall("cliffs"){{ variants = 1; + fillsTile = false; }}; rocks = new StaticWall("rocks"){{ variants = 2; }}; + icerocks = new StaticWall("icerocks"){{ + variants = 2; + }}; + + snowrocks = new StaticWall("snowrocks"){{ + variants = 2; + }}; + + duneRocks = new StaticWall("dunerocks"){{ + variants = 2; + }}; + + sandRocks = new StaticWall("sandrocks"){{ + variants = 2; + }}; + + pine = new StaticWall("pine"){{ + //fillsTile = false; + variants = 0; + }}; + + whiteTreeDead = new TreeBlock("white-tree-dead"){{ + }}; + + whiteTree = new TreeBlock("white-tree"){{ + }}; + + sporeCluster = new Rock("spore-cluster"){{ + variants = 3; + }}; + + stainedRocks = new StaticWall("stained-rocks"){{ + variants = 2; + }}; + + moss = new Floor("moss"){{ + variants = 3; + }}; + + stainedRocksRed = new StaticWall("stained-rocks-red"){{ + variants = 2; + }}; + + stainedStoneRed = new Floor("stained-stone-red"){{ + hasOres = true; + variants = 1; + }}; + + stainedRocksYellow = new StaticWall("stained-rocks-yellow"){{ + variants = 2; + }}; + + stainedStoneYellow = new Floor("stained-stone-yellow"){{ + variants = 1; + }}; + + stainedBoulder = new Rock("stained-boulder"){{ + variants = 2; + }}; + + metalFloor = new Floor("metal-floor"){{ + variants = 0; + }}; + + metalFloorDamaged = new Floor("metal-floor-damaged"){{ + variants = 6; + blendGroup = metalFloor; + }}; + + metalFloor2 = new Floor("metal-floor-2"){{ + variants = 0; + blendGroup = metalFloor; + }}; + + metalFloor3 = new Floor("metal-floor-3"){{ + variants = 0; + blendGroup = metalFloor; + }}; + + metalFloor5 = new Floor("metal-floor-5"){{ + variants = 0; + blendGroup = metalFloor; + }}; + + ignarock = new Floor("ignarock"){{ + + }}; + + hotrock = new Floor("hotrock"){{ + heat = 0.5f; + blendGroup = ignarock; + }}; + + magmarock = new Floor("magmarock"){{ + heat = 0.75f; + updateEffect = Fx.magmasmoke; + blendGroup = ignarock; + }}; + //endregion //region crafting + graphitePress = new GenericCrafter("graphite-press"){{ + requirements(Category.crafting, ItemStack.with(Items.copper, 150, Items.lead, 60)); + + craftEffect = Fx.pulverizeMedium; + output = Items.graphite; + craftTime = 90f; + size = 2; + hasItems = true; + + consumes.item(Items.coal, 2); + }}; + + multiPress = new GenericCrafter("multi-press"){{ + requirements(Category.crafting, ItemStack.with(Items.titanium, 200, Items.silicon, 50, Items.lead, 200, Items.graphite, 100)); + + craftEffect = Fx.pulverizeMedium; + output = Items.graphite; + craftTime = 30f; + size = 3; + hasItems = true; + hasLiquids = true; + hasPower = true; + + consumes.power(2f); + consumes.item(Items.coal, 2); + consumes.liquid(Liquids.water, 0.1f); + }}; + siliconSmelter = new PowerSmelter("silicon-smelter"){{ requirements(Category.crafting, ItemStack.with(Items.copper, 60, Items.lead, 50)); - health = 90; craftEffect = Fx.smeltsmoke; - result = Items.silicon; + output = Items.silicon; craftTime = 40f; size = 2; hasLiquids = false; flameColor = Color.valueOf("ffef99"); consumes.items(new ItemStack(Items.coal, 1), new ItemStack(Items.sand, 2)); - consumes.power(0.05f); + consumes.power(0.50f); + }}; + + kiln = new PowerSmelter("kiln"){{ + requirements(Category.crafting, ItemStack.with(Items.copper, 120, Items.graphite, 60, Items.lead, 60)); + craftEffect = Fx.smeltsmoke; + output = Items.metaglass; + craftTime = 30f; + size = 2; + hasPower = hasItems = true; + flameColor = Color.valueOf("ffc099"); + + consumes.items(new ItemStack(Items.lead, 1), new ItemStack(Items.sand, 1)); + consumes.power(0.60f); }}; plastaniumCompressor = new PlastaniumCompressor("plastanium-compressor"){{ @@ -238,32 +378,29 @@ public class Blocks implements ContentList{ updateEffect = Fx.plasticburn; consumes.liquid(Liquids.oil, 0.25f); - consumes.power(0.3f); + consumes.power(3f); consumes.item(Items.titanium, 2); }}; phaseWeaver = new PhaseWeaver("phase-weaver"){{ requirements(Category.crafting, ItemStack.with(Items.silicon, 260, Items.lead, 240, Items.thorium, 150)); craftEffect = Fx.smeltsmoke; - result = Items.phasefabric; + output = Items.phasefabric; craftTime = 120f; size = 2; consumes.items(new ItemStack(Items.thorium, 4), new ItemStack(Items.sand, 10)); - consumes.power(0.5f); + consumes.power(5f); }}; surgeSmelter = new PowerSmelter("alloy-smelter"){{ requirements(Category.crafting, ItemStack.with(Items.silicon, 160, Items.lead, 160, Items.thorium, 140)); craftEffect = Fx.smeltsmoke; - result = Items.surgealloy; + output = Items.surgealloy; craftTime = 75f; - size = 2; + size = 3; - useFlux = true; - fluxNeeded = 3; - - consumes.power(0.4f); + consumes.power(4f); consumes.items(new ItemStack(Items.titanium, 2), new ItemStack(Items.lead, 4), new ItemStack(Items.silicon, 3), new ItemStack(Items.copper, 3)); }}; @@ -274,7 +411,7 @@ public class Blocks implements ContentList{ size = 2; hasPower = true; - consumes.power(0.1f); + consumes.power(1f); consumes.item(Items.titanium); consumes.liquid(Liquids.water, 0.3f); }}; @@ -283,13 +420,11 @@ public class Blocks implements ContentList{ requirements(Category.crafting, ItemStack.with(Items.lead, 60, Items.titanium, 40)); hasItems = true; hasPower = true; - hasLiquids = true; output = Items.blastCompound; size = 2; - consumes.liquid(Liquids.oil, 0.05f); - consumes.item(Items.pyratite, 1); - consumes.power(0.04f); + consumes.items(new ItemStack(Items.pyratite, 1), new ItemStack(Items.sporePod, 1)); + consumes.power(0.40f); }}; pyratiteMixer = new PowerSmelter("pyratite-mixer"){{ @@ -297,11 +432,11 @@ public class Blocks implements ContentList{ flameColor = Color.CLEAR; hasItems = true; hasPower = true; - result = Items.pyratite; + output = Items.pyratite; size = 2; - consumes.power(0.02f); + consumes.power(0.20f); consumes.items(new ItemStack(Items.coal, 1), new ItemStack(Items.lead, 2), new ItemStack(Items.sand, 2)); }}; @@ -309,35 +444,48 @@ public class Blocks implements ContentList{ requirements(Category.crafting, ItemStack.with(Items.copper, 60, Items.lead, 70, Items.graphite, 90)); health = 200; outputLiquid = Liquids.slag; - outputLiquidAmount = 1.5f; + outputLiquidAmount = 2f; craftTime = 10f; hasLiquids = hasPower = true; - consumes.power(0.1f); + consumes.power(1f); consumes.item(Items.scrap, 1); }}; separator = new Separator("separator"){{ requirements(Category.crafting, ItemStack.with(Items.copper, 60, Items.titanium, 50)); - results = new ItemStack[]{ - new ItemStack(Items.copper, 5), - new ItemStack(Items.lead, 3), - new ItemStack(Items.titanium, 2), - new ItemStack(Items.thorium, 1) - }; + results = ItemStack.with( + Items.copper, 5, + Items.lead, 3, + Items.graphite, 2, + Items.titanium, 2 + ); hasPower = true; - filterTime = 15f; - health = 50 * 4; + filterTime = 35f; spinnerLength = 1.5f; spinnerRadius = 3.5f; spinnerThickness = 1.5f; spinnerSpeed = 3f; size = 2; - consumes.liquid(Liquids.slag, 0.3f); + consumes.power(1f); + consumes.liquid(Liquids.slag, 0.07f); }}; - biomatterCompressor = new Compressor("biomattercompressor"){{ + cultivator = new Cultivator("cultivator"){{ + requirements(Category.crafting, ItemStack.with(Items.copper, 20, Items.lead, 50, Items.silicon, 20)); + output = Items.sporePod; + craftTime = 200; + size = 2; + hasLiquids = true; + hasPower = true; + hasItems = true; + + consumes.power(0.80f); + consumes.liquid(Liquids.water, 0.15f); + }}; + + sporePress = new Compressor("spore-press"){{ requirements(Category.crafting, ItemStack.with(Items.lead, 70, Items.silicon, 60)); liquidCapacity = 60f; craftTime = 20f; @@ -347,8 +495,8 @@ public class Blocks implements ContentList{ health = 320; hasLiquids = true; - consumes.item(Items.biomatter, 1); - consumes.power(0.06f); + consumes.item(Items.sporePod, 1); + consumes.power(0.60f); }}; pulverizer = new Pulverizer("pulverizer"){{ @@ -360,12 +508,13 @@ public class Blocks implements ContentList{ hasItems = hasPower = true; consumes.item(Items.scrap, 1); - consumes.power(0.05f); + consumes.power(0.50f); }}; incinerator = new Incinerator("incinerator"){{ requirements(Category.crafting, ItemStack.with(Items.graphite, 10, Items.lead, 30)); health = 90; + consumes.power(0.50f); }}; //endregion @@ -397,6 +546,33 @@ public class Blocks implements ContentList{ int wallHealthMultiplier = 3; + scrapWall = new Wall("scrap-wall"){{ + health = 60 * wallHealthMultiplier; + variants = 5; + }}; + + scrapWallLarge = new Wall("scrap-wall-large"){{ + health = 60 * 4 * wallHealthMultiplier; + size = 2; + variants = 4; + }}; + + scrapWallHuge = new Wall("scrap-wall-huge"){{ + health = 60 * 9 * wallHealthMultiplier; + size = 3; + variants = 3; + }}; + + scrapWallGigantic = new Wall("scrap-wall-gigantic"){{ + health = 60 * 16 * wallHealthMultiplier; + size = 4; + }}; + + thruster = new Wall("thruster"){{ + health = 55 * 16 * wallHealthMultiplier; + size = 4; + }}; + copperWall = new Wall("copper-wall"){{ requirements(Category.defense, ItemStack.with(Items.copper, 12)); health = 80 * wallHealthMultiplier; @@ -404,7 +580,6 @@ public class Blocks implements ContentList{ copperWallLarge = new Wall("copper-wall-large"){{ requirements(Category.defense, ItemStack.with(Items.copper, 12 * 4)); - requirements(Category.defense, ItemStack.with(Items.copper, 12)); health = 80 * 4 * wallHealthMultiplier; size = 2; }}; @@ -416,7 +591,6 @@ public class Blocks implements ContentList{ titaniumWallLarge = new Wall("titanium-wall-large"){{ requirements(Category.defense, ItemStack.with(Items.titanium, 12 * 4)); - requirements(Category.defense, ItemStack.with(Items.titanium, 12)); health = 110 * wallHealthMultiplier * 4; size = 2; }}; @@ -428,7 +602,6 @@ public class Blocks implements ContentList{ thoriumWallLarge = new Wall("thorium-wall-large"){{ requirements(Category.defense, ItemStack.with(Items.thorium, 12 * 4)); - requirements(Category.defense, ItemStack.with(Items.thorium, 12)); health = 200 * wallHealthMultiplier * 4; size = 2; }}; @@ -440,7 +613,6 @@ public class Blocks implements ContentList{ phaseWallLarge = new DeflectorWall("phase-wall-large"){{ requirements(Category.defense, ItemStack.with(Items.phasefabric, 12 * 4)); - requirements(Category.defense, ItemStack.with(Items.phasefabric, 12)); health = 150 * 4 * wallHealthMultiplier; size = 2; }}; @@ -452,7 +624,6 @@ public class Blocks implements ContentList{ surgeWallLarge = new SurgeWall("surge-wall-large"){{ requirements(Category.defense, ItemStack.with(Items.surgealloy, 12 * 4)); - requirements(Category.defense, ItemStack.with(Items.surgealloy, 12)); health = 230 * 4 * wallHealthMultiplier; size = 2; }}; @@ -464,7 +635,6 @@ public class Blocks implements ContentList{ doorLarge = new Door("door-large"){{ requirements(Category.defense, ItemStack.with(Items.titanium, 12 * 4, Items.silicon, 8 * 4)); - requirements(Category.defense, ItemStack.with(Items.titanium, 12, Items.silicon, 8)); openfx = Fx.dooropenlarge; closefx = Fx.doorcloselarge; health = 100 * 4 * wallHealthMultiplier; @@ -472,23 +642,23 @@ public class Blocks implements ContentList{ }}; mendProjector = new MendProjector("mend-projector"){{ - requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 150, Items.titanium, 50, Items.silicon, 180)); - consumes.power(0.2f, 1.0f); + requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 50, Items.silicon, 180)); + consumes.power(2f); size = 2; consumes.item(Items.phasefabric).optional(true); }}; overdriveProjector = new OverdriveProjector("overdrive-projector"){{ - requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 150, Items.titanium, 150, Items.silicon, 250)); - consumes.power(0.35f, 1.0f); + requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 150, Items.silicon, 150, Items.plastanium, 60)); + consumes.power(3.50f); size = 2; - consumes.item(Items.phasefabric).optional(true); + consumes.item(Items.phasefabric).optional(true).boost(true); }}; forceProjector = new ForceProjector("force-projector"){{ - requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 150, Items.titanium, 150, Items.silicon, 250)); + requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 150, Items.silicon, 250)); size = 3; - consumes.item(Items.phasefabric).optional(true); + consumes.item(Items.phasefabric).optional(true).boost(true); }}; shockMine = new ShockMine("shock-mine"){{ @@ -510,19 +680,20 @@ public class Blocks implements ContentList{ }}; titaniumConveyor = new Conveyor("titanium-conveyor"){{ - requirements(Category.distribution, ItemStack.with(Items.copper, 2, Items.titanium, 1)); + requirements(Category.distribution, ItemStack.with(Items.copper, 2, Items.lead, 1, Items.titanium, 1)); health = 65; speed = 0.07f; }}; junction = new Junction("junction"){{ - requirements(Category.distribution, ItemStack.with(Items.copper, 2)); + requirements(Category.distribution, ItemStack.with(Items.copper, 3)); speed = 26; capacity = 32; + health = 25; }}; itemBridge = new BufferedItemBridge("bridge-conveyor"){{ - requirements(Category.distribution, ItemStack.with(Items.titanium, 8, Items.copper, 8)); + requirements(Category.distribution, ItemStack.with(Items.lead, 8, Items.copper, 8)); range = 4; speed = 60f; bufferCapacity = 15; @@ -532,11 +703,11 @@ public class Blocks implements ContentList{ requirements(Category.distribution, ItemStack.with(Items.phasefabric, 10, Items.silicon, 15, Items.lead, 20, Items.graphite, 20)); range = 12; hasPower = true; - consumes.power(0.03f, 1.0f); + consumes.power(0.30f); }}; sorter = new Sorter("sorter"){{ - requirements(Category.distribution, ItemStack.with(Items.titanium, 4, Items.copper, 4)); + requirements(Category.distribution, ItemStack.with(Items.lead, 4, Items.copper, 4)); }}; @@ -546,19 +717,19 @@ public class Blocks implements ContentList{ }}; distributor = new Router("distributor"){{ - requirements(Category.distribution, ItemStack.with(Items.titanium, 8, Items.copper, 8)); + requirements(Category.distribution, ItemStack.with(Items.lead, 8, Items.copper, 8)); size = 2; }}; overflowGate = new OverflowGate("overflow-gate"){{ - requirements(Category.distribution, ItemStack.with(Items.titanium, 4, Items.copper, 8)); - + requirements(Category.distribution, ItemStack.with(Items.lead, 4, Items.copper, 8)); }}; massDriver = new MassDriver("mass-driver"){{ requirements(Category.distribution, ItemStack.with(Items.titanium, 250, Items.silicon, 150, Items.lead, 250, Items.thorium, 100)); size = 3; - itemCapacity = 60; + itemCapacity = 120; + reloadTime = 200f; range = 440f; }}; @@ -568,68 +739,65 @@ public class Blocks implements ContentList{ mechanicalPump = new Pump("mechanical-pump"){{ requirements(Category.liquid, ItemStack.with(Items.copper, 30, Items.lead, 20)); pumpAmount = 0.1f; - tier = 0; }}; rotaryPump = new Pump("rotary-pump"){{ requirements(Category.liquid, ItemStack.with(Items.copper, 140, Items.lead, 100, Items.silicon, 40, Items.titanium, 70)); - pumpAmount = 0.2f; - consumes.power(0.015f); + pumpAmount = 0.8f; + consumes.power(0.15f); liquidCapacity = 30f; hasPower = true; size = 2; - tier = 1; }}; thermalPump = new Pump("thermal-pump"){{ requirements(Category.liquid, ItemStack.with(Items.copper, 160, Items.lead, 130, Items.silicon, 60, Items.titanium, 80, Items.thorium, 70)); - pumpAmount = 0.275f; - consumes.power(0.03f); + pumpAmount = 1.95f; + consumes.power(0.30f); liquidCapacity = 40f; hasPower = true; - size = 2; - tier = 2; + size = 3; }}; conduit = new Conduit("conduit"){{ - requirements(Category.liquid, ItemStack.with(Items.lead, 1)); + requirements(Category.liquid, ItemStack.with(Items.metaglass, 1)); health = 45; }}; pulseConduit = new Conduit("pulse-conduit"){{ - requirements(Category.liquid, ItemStack.with(Items.titanium, 1, Items.lead, 1)); + requirements(Category.liquid, ItemStack.with(Items.titanium, 1, Items.metaglass, 2)); liquidCapacity = 16f; liquidFlowFactor = 4.9f; health = 90; }}; liquidRouter = new LiquidRouter("liquid-router"){{ - requirements(Category.liquid, ItemStack.with(Items.titanium, 4, Items.lead, 4)); + requirements(Category.liquid, ItemStack.with(Items.titanium, 4, Items.metaglass, 4)); liquidCapacity = 20f; }}; liquidTank = new LiquidTank("liquid-tank"){{ - requirements(Category.liquid, ItemStack.with(Items.titanium, 50, Items.lead, 50)); + requirements(Category.liquid, ItemStack.with(Items.titanium, 50, Items.metaglass, 50)); size = 3; liquidCapacity = 1500f; health = 500; }}; liquidJunction = new LiquidJunction("liquid-junction"){{ - requirements(Category.liquid, ItemStack.with(Items.titanium, 4, Items.lead, 4)); + requirements(Category.liquid, ItemStack.with(Items.titanium, 4, Items.metaglass, 4)); }}; bridgeConduit = new LiquidExtendingBridge("bridge-conduit"){{ - requirements(Category.liquid, ItemStack.with(Items.titanium, 8, Items.lead, 8)); + requirements(Category.liquid, ItemStack.with(Items.titanium, 8, Items.metaglass, 8)); range = 4; hasPower = false; }}; phaseConduit = new LiquidBridge("phase-conduit"){{ - requirements(Category.liquid, ItemStack.with(Items.phasefabric, 10, Items.silicon, 15, Items.lead, 20, Items.titanium, 20)); + requirements(Category.liquid, ItemStack.with(Items.phasefabric, 10, Items.silicon, 15, Items.metaglass, 40, Items.titanium, 20)); range = 12; hasPower = true; - consumes.power(0.03f, 1.0f); + consumes.power(0.30f); }}; //endregion @@ -643,81 +811,105 @@ public class Blocks implements ContentList{ powerNodeLarge = new PowerNode("power-node-large"){{ requirements(Category.power, ItemStack.with(Items.titanium, 10, Items.lead, 20, Items.silicon, 6)); - requirements(Category.power, ItemStack.with(Items.copper, 2, Items.lead, 6)); size = 2; maxNodes = 6; laserRange = 9.5f; }}; + surgeTower = new PowerNode("surge-tower"){{ + requirements(Category.power, ItemStack.with(Items.titanium, 15, Items.lead, 20, Items.silicon, 30, Items.surgealloy, 30)); + size = 2; + maxNodes = 2; + laserRange = 30f; + }}; + battery = new Battery("battery"){{ requirements(Category.power, ItemStack.with(Items.copper, 8, Items.lead, 30, Items.silicon, 4)); - consumes.powerBuffered(320f, 1f); + consumes.powerBuffered(3200f, 1f); }}; batteryLarge = new Battery("battery-large"){{ requirements(Category.power, ItemStack.with(Items.titanium, 40, Items.lead, 80, Items.silicon, 30)); - requirements(Category.power, ItemStack.with(Items.copper, 8, Items.lead, 30, Items.silicon, 4)); size = 3; - consumes.powerBuffered(2000f, 1f); + consumes.powerBuffered(20000f, 1f); }}; combustionGenerator = new BurnerGenerator("combustion-generator"){{ requirements(Category.power, ItemStack.with(Items.copper, 50, Items.lead, 30)); - powerProduction = 0.09f; + powerProduction = 1f; itemDuration = 40f; }}; - thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{ - requirements(Category.power, ItemStack.with(Items.copper, 80, Items.graphite, 70, Items.lead, 100, Items.silicon, 70, Items.thorium, 70)); - maxLiquidGenerate = 2f; - powerProduction = 2f; + thermalGenerator = new ThermalGenerator("thermal-generator"){{ + requirements(Category.power, ItemStack.with(Items.copper, 80, Items.graphite, 70, Items.lead, 100, Items.silicon, 70, Items.metaglass, 80)); + powerProduction = 1.8f; generateEffect = Fx.redgeneratespark; size = 2; }}; turbineGenerator = new TurbineGenerator("turbine-generator"){{ requirements(Category.power, ItemStack.with(Items.copper, 70, Items.graphite, 50, Items.lead, 80, Items.silicon, 60)); - powerProduction = 0.28f; + powerProduction = 6f; itemDuration = 30f; consumes.liquid(Liquids.water, 0.05f); + hasLiquids = true; size = 2; }}; + differentialGenerator = new DifferentialGenerator("differential-generator"){{ + requirements(Category.power, ItemStack.with(Items.copper, 140, Items.titanium, 100, Items.lead, 200, Items.silicon, 130, Items.metaglass, 100)); + powerProduction = 13f; + itemDuration = 50f; + consumes.remove(ConsumeItemFilter.class); + consumes.remove(ConsumeLiquidFilter.class); + consumes.item(Items.pyratite); + consumes.liquid(Liquids.cryofluid, 0.2f); + size = 3; + }}; + rtgGenerator = new DecayGenerator("rtg-generator"){{ requirements(Category.power, ItemStack.with(Items.lead, 200, Items.silicon, 150, Items.phasefabric, 50, Items.plastanium, 150, Items.thorium, 100)); size = 2; - powerProduction = 0.3f; + powerProduction = 3f; itemDuration = 220f; }}; solarPanel = new SolarGenerator("solar-panel"){{ requirements(Category.power, ItemStack.with(Items.lead, 20, Items.silicon, 30)); - powerProduction = 0.0045f; + powerProduction = 0.045f; }}; largeSolarPanel = new SolarGenerator("solar-panel-large"){{ requirements(Category.power, ItemStack.with(Items.lead, 200, Items.silicon, 290, Items.phasefabric, 30)); size = 3; - powerProduction = 0.055f; + powerProduction = 0.55f; }}; thoriumReactor = new NuclearReactor("thorium-reactor"){{ requirements(Category.power, ItemStack.with(Items.lead, 600, Items.silicon, 400, Items.graphite, 300, Items.thorium, 300)); size = 3; health = 700; - powerProduction = 1.1f; + powerProduction = 14f; + consumes.item(Items.thorium); + consumes.liquid(Liquids.cryofluid, 0.1f); }}; - fusionReactor = new FusionReactor("fusion-reactor"){{ + impactReactor = new ImpactReactor("impact-reactor"){{ + requirements(Category.power, ItemStack.with(Items.lead, 1000, Items.silicon, 600, Items.graphite, 800, Items.thorium, 200, Items.surgealloy, 500, Items.metaglass, 500)); size = 4; - health = 600; + health = 900; + powerProduction = 80f; + useTime = 40f; + consumes.power(23f); + consumes.item(Items.blastCompound); + consumes.liquid(Liquids.cryofluid, 0.8f); }}; //endregion power //region production mechanicalDrill = new Drill("mechanical-drill"){{ - requirements(Category.production, ItemStack.with(Items.copper, 20), true); + requirements(Category.production, ItemStack.with(Items.copper, 25), true); tier = 2; drillTime = 600; size = 2; @@ -730,24 +922,26 @@ public class Blocks implements ContentList{ drillTime = 480; size = 2; drawMineItem = true; + consumes.liquid(Liquids.water, 0.06f).optional(true); }}; laserDrill = new Drill("laser-drill"){{ requirements(Category.production, ItemStack.with(Items.copper, 70, Items.graphite, 90, Items.silicon, 60, Items.titanium, 50)); drillTime = 280; - size = 2; + size = 3; hasPower = true; tier = 4; updateEffect = Fx.pulverizeMedium; drillEffect = Fx.mineBig; - consumes.power(0.11f); + consumes.power(1.10f); + consumes.liquid(Liquids.water, 0.08f).optional(true); }}; blastDrill = new Drill("blast-drill"){{ requirements(Category.production, ItemStack.with(Items.copper, 130, Items.silicon, 120, Items.titanium, 100, Items.thorium, 60)); - drillTime = 120; - size = 3; + drillTime = 200; + size = 4; drawRim = true; hasPower = true; tier = 5; @@ -757,35 +951,19 @@ public class Blocks implements ContentList{ rotateSpeed = 6f; warmupSpeed = 0.01f; - consumes.power(0.3f); - }}; - - plasmaDrill = new Drill("plasma-drill"){{ - heatColor = Color.valueOf("ff461b"); - drillTime = 100; - size = 4; - hasLiquids = true; - hasPower = true; - tier = 5; - rotateSpeed = 9f; - drawRim = true; - updateEffect = Fx.pulverizeRedder; - updateEffectChance = 0.04f; - drillEffect = Fx.mineHuge; - warmupSpeed = 0.005f; - - consumes.power(0.7f); + consumes.power(3f); + consumes.liquid(Liquids.water, 0.1f).optional(true); }}; waterExtractor = new SolidPump("water-extractor"){{ requirements(Category.production, ItemStack.with(Items.copper, 50, Items.graphite, 50, Items.lead, 40)); result = Liquids.water; - pumpAmount = 0.065f; + pumpAmount = 0.13f; size = 2; liquidCapacity = 30f; rotateSpeed = 1.4f; - consumes.power(0.09f); + consumes.power(0.90f); }}; oilExtractor = new Fracker("oil-extractor"){{ @@ -794,39 +972,41 @@ public class Blocks implements ContentList{ updateEffect = Fx.pulverize; liquidCapacity = 50f; updateEffectChance = 0.05f; - pumpAmount = 0.09f; + pumpAmount = 0.25f; size = 3; liquidCapacity = 30f; consumes.item(Items.sand); - consumes.power(0.3f); - consumes.liquid(Liquids.water, 0.15f); - }}; - - cultivator = new Cultivator("cultivator"){{ - requirements(Category.production, ItemStack.with(Items.copper, 20, Items.lead, 50, Items.silicon, 20)); - result = Items.biomatter; - drillTime = 200; - size = 2; - hasLiquids = true; - hasPower = true; - - consumes.power(0.08f); + consumes.power(3f); consumes.liquid(Liquids.water, 0.15f); }}; //endregion //region storage - core = new CoreBlock("core"){{ + coreShard = new CoreBlock("core-shard"){{ requirements(Category.effect, () -> false, ItemStack.with(Items.titanium, 2000)); alwaysUnlocked = true; health = 1100; - itemCapacity = 1000; - launchThreshold = 500; - launchTime = 60f * 10; - launchChunkSize = 100; + itemCapacity = 3000; + size = 3; + }}; + + coreFoundation = new CoreBlock("core-foundation"){{ + requirements(Category.effect, () -> false, ItemStack.with(Items.titanium, 3000, Items.silicon, 2000)); + + health = 2000; + itemCapacity = 6000; + size = 4; + }}; + + coreNucleus = new CoreBlock("core-nucleus"){{ + requirements(Category.effect, () -> false, ItemStack.with(Items.titanium, 8000, Items.silicon, 4000, Items.surgealloy, 2000)); + + health = 4000; + itemCapacity = 10000; + size = 5; }}; vault = new Vault("vault"){{ @@ -841,25 +1021,25 @@ public class Blocks implements ContentList{ itemCapacity = 300; }}; - unloader = new SortedUnloader("unloader"){{ + unloader = new Unloader("unloader"){{ requirements(Category.distribution, ItemStack.with(Items.titanium, 50, Items.silicon, 60)); speed = 7f; }}; launchPad = new LaunchPad("launch-pad"){{ - requirements(Category.effect, ItemStack.with(Items.copper, 500)); + requirements(Category.effect, () -> world.isZone(), ItemStack.with(Items.copper, 500, Items.titanium, 200, Items.silicon, 200, Items.lead, 200)); size = 3; itemCapacity = 100; - launchTime = 60f * 6; + launchTime = 60f * 8; hasPower = true; - consumes.power(0.1f); + consumes.power(1f); }}; //endregion //region turrets duo = new DoubleTurret("duo"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 60), true); + requirements(Category.turret, ItemStack.with(Items.copper, 70), true); ammo( Items.copper, Bullets.standardCopper, Items.graphite, Bullets.standardDense, @@ -868,10 +1048,10 @@ public class Blocks implements ContentList{ ); reload = 20f; restitution = 0.03f; - range = 90f; + range = 95f; shootCone = 15f; ammoUseEffect = Fx.shellEjectSmall; - health = 110; + health = 210; inaccuracy = 2f; rotatespeed = 10f; }}; @@ -879,9 +1059,9 @@ public class Blocks implements ContentList{ hail = new ArtilleryTurret("hail"){{ requirements(Category.turret, ItemStack.with(Items.copper, 60, Items.graphite, 35)); ammo( - Items.graphite, Bullets.artilleryDense, - Items.silicon, Bullets.artilleryHoming, - Items.pyratite, Bullets.artlleryIncendiary + Items.graphite, Bullets.artilleryDense, + Items.silicon, Bullets.artilleryHoming, + Items.pyratite, Bullets.artlleryIncendiary ); reload = 60f; recoil = 2f; @@ -892,20 +1072,20 @@ public class Blocks implements ContentList{ }}; wave = new LiquidTurret("wave"){{ - requirements(Category.turret, ItemStack.with(Items.titanium, 70, Items.lead, 150)); + requirements(Category.turret, ItemStack.with(Items.metaglass, 90, Items.lead, 150)); ammo( - Liquids.water, Bullets.waterShot, - Liquids.slag, Bullets.slagShot, - Liquids.cryofluid, Bullets.cryoShot, - Liquids.oil, Bullets.oilShot + Liquids.water, Bullets.waterShot, + Liquids.slag, Bullets.slagShot, + Liquids.cryofluid, Bullets.cryoShot, + Liquids.oil, Bullets.oilShot ); size = 2; recoil = 0f; - reload = 4f; + reload = 3f; inaccuracy = 5f; shootCone = 50f; shootEffect = Fx.shootLiquid; - range = 90f; + range = 100f; health = 360; drawer = (tile, entity) -> { @@ -920,16 +1100,16 @@ public class Blocks implements ContentList{ lancer = new ChargeTurret("lancer"){{ requirements(Category.turret, ItemStack.with(Items.copper, 50, Items.lead, 100, Items.silicon, 90)); - range = 90f; - chargeTime = 60f; + range = 155f; + chargeTime = 50f; chargeMaxDelay = 30f; chargeEffects = 7; shootType = Bullets.lancerLaser; recoil = 2f; - reload = 100f; + reload = 90f; cooldown = 0.03f; powerUsed = 1 / 3f; - consumes.powerBuffered(60f); + consumes.powerBuffered(600f); shootShake = 2f; shootEffect = Fx.lancerLaserShoot; smokeEffect = Fx.lancerLaserShootSmoke; @@ -942,15 +1122,14 @@ public class Blocks implements ContentList{ }}; arc = new PowerTurret("arc"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 70, Items.lead, 60)); + requirements(Category.turret, ItemStack.with(Items.copper, 70, Items.lead, 70)); shootType = Bullets.arc; - reload = 85f; - shootShake = 1f; + reload = 20f; shootCone = 40f; rotatespeed = 8f; - powerUsed = 1f / 3f; - consumes.powerBuffered(30f); - range = 150f; + powerUsed = 1f / 2f; + consumes.powerBuffered(80f); + range = 80f; shootEffect = Fx.lightningShoot; heatColor = Color.RED; recoil = 1f; @@ -960,9 +1139,9 @@ public class Blocks implements ContentList{ swarmer = new BurstTurret("swarmer"){{ requirements(Category.turret, ItemStack.with(Items.graphite, 70, Items.titanium, 70, Items.plastanium, 90, Items.silicon, 60)); ammo( - Items.blastCompound, Bullets.missileExplosive, - Items.pyratite, Bullets.missileIncendiary, - Items.surgealloy, Bullets.missileSurge + Items.blastCompound, Bullets.missileExplosive, + Items.pyratite, Bullets.missileIncendiary, + Items.surgealloy, Bullets.missileSurge ); reload = 50f; shots = 4; @@ -975,13 +1154,13 @@ public class Blocks implements ContentList{ }}; salvo = new BurstTurret("salvo"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 210, Items.graphite, 190, Items.thorium, 130)); + requirements(Category.turret, ItemStack.with(Items.copper, 210, Items.graphite, 190, Items.titanium, 120)); ammo( - Items.copper, Bullets.standardCopper, - Items.graphite, Bullets.standardDense, - Items.pyratite, Bullets.standardIncendiary, - Items.silicon, Bullets.standardHoming, - Items.thorium, Bullets.standardThorium + Items.copper, Bullets.standardCopper, + Items.graphite, Bullets.standardDense, + Items.pyratite, Bullets.standardIncendiary, + Items.silicon, Bullets.standardHoming, + Items.thorium, Bullets.standardThorium ); size = 2; @@ -999,13 +1178,13 @@ public class Blocks implements ContentList{ }}; ripple = new ArtilleryTurret("ripple"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 300, Items.graphite, 220, Items.thorium, 120)); + requirements(Category.turret, ItemStack.with(Items.copper, 300, Items.graphite, 270, Items.titanium, 120)); ammo( - Items.graphite, Bullets.artilleryDense, - Items.silicon, Bullets.artilleryHoming, - Items.pyratite, Bullets.artlleryIncendiary, - Items.blastCompound, Bullets.artilleryExplosive, - Items.plastanium, Bullets.arilleryPlastic + Items.graphite, Bullets.artilleryDense, + Items.silicon, Bullets.artilleryHoming, + Items.pyratite, Bullets.artlleryIncendiary, + Items.blastCompound, Bullets.artilleryExplosive, + Items.plastanium, Bullets.arilleryPlastic ); size = 3; shots = 4; @@ -1018,17 +1197,17 @@ public class Blocks implements ContentList{ restitution = 0.02f; recoil = 6f; shootShake = 2f; - range = 320f; + range = 290f; health = 550; }}; cyclone = new ItemTurret("cyclone"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 400, Items.surgealloy, 200, Items.plastanium, 150)); + requirements(Category.turret, ItemStack.with(Items.copper, 400, Items.titanium, 250, Items.plastanium, 160)); ammo( - Items.blastCompound, Bullets.flakExplosive, - Items.plastanium, Bullets.flakPlastic, - Items.surgealloy, Bullets.flakSurge + Items.blastCompound, Bullets.flakExplosive, + Items.plastanium, Bullets.flakPlastic, + Items.surgealloy, Bullets.flakSurge ); xRand = 4f; reload = 8f; @@ -1045,22 +1224,22 @@ public class Blocks implements ContentList{ fuse = new ItemTurret("fuse"){{ requirements(Category.turret, ItemStack.with(Items.copper, 450, Items.graphite, 450, Items.surgealloy, 250)); ammo(Items.graphite, Bullets.fuseShot); - reload = 50f; + reload = 40f; shootShake = 4f; range = 80f; recoil = 5f; restitution = 0.1f; size = 3; - health = 155 * size * size; + health = 165 * size * size; }}; spectre = new DoubleTurret("spectre"){{ requirements(Category.turret, ItemStack.with(Items.copper, 700, Items.graphite, 600, Items.surgealloy, 500, Items.plastanium, 350, Items.thorium, 500)); ammo( - Items.graphite, Bullets.standardDenseBig, - Items.pyratite, Bullets.standardIncendiaryBig, - Items.thorium, Bullets.standardThoriumBig + Items.graphite, Bullets.standardDenseBig, + Items.pyratite, Bullets.standardIncendiaryBig, + Items.thorium, Bullets.standardThoriumBig ); reload = 6f; coolantMultiplier = 0.5f; @@ -1089,7 +1268,7 @@ public class Blocks implements ContentList{ size = 4; shootShake = 2f; powerUsed = 0.5f; - consumes.powerBuffered(120f); + consumes.powerBuffered(1200f); range = 160f; reload = 200f; firingMoveFract = 0.1f; @@ -1106,7 +1285,7 @@ public class Blocks implements ContentList{ type = UnitTypes.spirit; produceTime = 5700; size = 2; - consumes.power(0.08f); + consumes.power(0.80f); consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.lead, 30)); }}; @@ -1115,7 +1294,7 @@ public class Blocks implements ContentList{ type = UnitTypes.phantom; produceTime = 7300; size = 2; - consumes.power(0.2f); + consumes.power(2f); consumes.items(new ItemStack(Items.silicon, 70), new ItemStack(Items.lead, 80), new ItemStack(Items.titanium, 80)); }}; @@ -1124,7 +1303,7 @@ public class Blocks implements ContentList{ type = UnitTypes.wraith; produceTime = 1800; size = 2; - consumes.power(0.1f); + consumes.power(1f); consumes.items(new ItemStack(Items.silicon, 10), new ItemStack(Items.titanium, 10)); }}; @@ -1133,7 +1312,7 @@ public class Blocks implements ContentList{ type = UnitTypes.ghoul; produceTime = 3600; size = 3; - consumes.power(0.2f); + consumes.power(2f); consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.titanium, 30), new ItemStack(Items.plastanium, 20)); }}; @@ -1142,7 +1321,7 @@ public class Blocks implements ContentList{ type = UnitTypes.revenant; produceTime = 8000; size = 4; - consumes.power(0.3f); + consumes.power(3f); consumes.items(new ItemStack(Items.silicon, 80), new ItemStack(Items.titanium, 80), new ItemStack(Items.plastanium, 50)); }}; @@ -1151,16 +1330,25 @@ public class Blocks implements ContentList{ type = UnitTypes.dagger; produceTime = 1700; size = 2; - consumes.power(0.05f); + consumes.power(0.50f); consumes.items(new ItemStack(Items.silicon, 10)); }}; + crawlerFactory = new UnitFactory("crawler-factory"){{ + requirements(Category.units, ItemStack.with(Items.lead, 100, Items.silicon, 80)); + type = UnitTypes.crawler; + produceTime = 1200; + size = 2; + consumes.power(0.4f); + consumes.items(new ItemStack(Items.blastCompound, 10)); + }}; + titanFactory = new UnitFactory("titan-factory"){{ requirements(Category.units, ItemStack.with(Items.thorium, 90, Items.lead, 140, Items.silicon, 90)); type = UnitTypes.titan; produceTime = 3400; size = 3; - consumes.power(0.15f); + consumes.power(1.50f); consumes.items(new ItemStack(Items.silicon, 20), new ItemStack(Items.thorium, 30)); }}; @@ -1169,7 +1357,7 @@ public class Blocks implements ContentList{ type = UnitTypes.fortress; produceTime = 5000; size = 3; - consumes.power(0.2f); + consumes.power(2f); consumes.items(new ItemStack(Items.silicon, 40), new ItemStack(Items.thorium, 50)); }}; @@ -1178,14 +1366,10 @@ public class Blocks implements ContentList{ repairSpeed = 0.1f; }}; - reconstructor = new Reconstructor("reconstructor"){{ - size = 2; - }}; - //endregion //region upgrades - alphaPad = new MechPad("alpha-mech-pad"){{ + alphaDartPad = new MechPad("alpha-dart-mech-pad"){{ requirements(Category.upgrade, ItemStack.with(Items.lead, 200, Items.graphite, 100, Items.copper, 150)); mech = Mechs.alpha; size = 2; @@ -1213,13 +1397,6 @@ public class Blocks implements ContentList{ consumes.powerBuffered(120f); }}; - dartPad = new MechPad("dart-ship-pad"){{ - requirements(Category.upgrade, ItemStack.with(Items.lead, 150, Items.copper, 150, Items.silicon, 200, Items.titanium, 240)); - mech = Mechs.dart; - size = 2; - consumes.powerBuffered(50f); - }}; - javelinPad = new MechPad("javelin-ship-pad"){{ requirements(Category.upgrade, ItemStack.with(Items.lead, 350, Items.silicon, 450, Items.titanium, 500, Items.plastanium, 400, Items.phasefabric, 200)); mech = Mechs.javelin; @@ -1255,6 +1432,9 @@ public class Blocks implements ContentList{ } } + //special variants + new OreBlock(Items.scrap, (Floor)snow); + //endregion } } diff --git a/core/src/io/anuke/mindustry/content/Bullets.java b/core/src/io/anuke/mindustry/content/Bullets.java index a9d7abd474..0edd7aca6c 100644 --- a/core/src/io/anuke/mindustry/content/Bullets.java +++ b/core/src/io/anuke/mindustry/content/Bullets.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.content; -import io.anuke.arc.entities.Effects; +import io.anuke.mindustry.entities.Effects; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.CapStyle; import io.anuke.arc.graphics.g2d.Draw; @@ -10,12 +10,13 @@ import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; import io.anuke.mindustry.entities.Damage; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.entities.bullet.*; import io.anuke.mindustry.entities.effect.Fire; import io.anuke.mindustry.entities.effect.Lightning; import io.anuke.mindustry.entities.effect.Puddle; import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Shapes; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.BuildBlock; @@ -32,7 +33,7 @@ public class Bullets implements ContentList{ flakPlastic, flakExplosive, flakSurge, //missiles - missileExplosive, missileIncendiary, missileSurge, missileJavelin, missileSwarm, + missileExplosive, missileIncendiary, missileSurge, missileJavelin, missileSwarm, missileRevenant, //standard standardCopper, standardDense, standardThorium, standardHoming, standardIncendiary, standardMechSmall, @@ -45,10 +46,10 @@ public class Bullets implements ContentList{ waterShot, cryoShot, slagShot, oilShot, //environment, misc. - fireball, basicFlame, fuseShot, driverBolt, healBullet, frag, + fireball, basicFlame, fuseShot, driverBolt, healBullet, frag, eruptorShot, //bombs - bombExplosive, bombIncendiary, bombOil; + bombExplosive, bombIncendiary, bombOil, explode; @Override public void load(){ @@ -63,28 +64,28 @@ public class Bullets implements ContentList{ splashDamage = 33f; }}; - artilleryPlasticFrag = new BasicBulletType(2.5f, 6, "bullet"){{ + artilleryPlasticFrag = new BasicBulletType(2.5f, 7, "bullet"){{ bulletWidth = 10f; bulletHeight = 12f; bulletShrink = 1f; lifetime = 15f; - backColor = Palette.plastaniumBack; - frontColor = Palette.plastaniumFront; + backColor = Pal.plastaniumBack; + frontColor = Pal.plastaniumFront; despawnEffect = Fx.none; }}; - arilleryPlastic = new ArtilleryBulletType(3.3f, 0, "shell"){{ + arilleryPlastic = new ArtilleryBulletType(3.4f, 0, "shell"){{ hitEffect = Fx.plasticExplosion; knockback = 1f; lifetime = 55f; bulletWidth = bulletHeight = 13f; collidesTiles = false; splashDamageRadius = 35f; - splashDamage = 35f; + splashDamage = 45f; fragBullet = artilleryPlasticFrag; - fragBullets = 9; - backColor = Palette.plastaniumBack; - frontColor = Palette.plastaniumFront; + fragBullets = 10; + backColor = Pal.plastaniumBack; + frontColor = Pal.plastaniumFront; }}; artilleryHoming = new ArtilleryBulletType(3f, 0, "shell"){{ @@ -109,8 +110,8 @@ public class Bullets implements ContentList{ splashDamage = 30f; incendAmount = 4; incendSpread = 11f; - frontColor = Palette.lightishOrange; - backColor = Palette.lightOrange; + frontColor = Pal.lightishOrange; + backColor = Pal.lightOrange; trailEffect = Fx.incendTrail; }}; @@ -122,8 +123,8 @@ public class Bullets implements ContentList{ collidesTiles = false; splashDamageRadius = 45f; splashDamage = 50f; - backColor = Palette.missileYellowBack; - frontColor = Palette.missileYellow; + backColor = Pal.missileYellowBack; + frontColor = Pal.missileYellow; }}; artilleryUnit = new ArtilleryBulletType(2f, 0, "shell"){{ @@ -135,27 +136,30 @@ public class Bullets implements ContentList{ collidesTiles = true; splashDamageRadius = 45f; splashDamage = 50f; - backColor = Palette.bulletYellowBack; - frontColor = Palette.bulletYellow; + backColor = Pal.bulletYellowBack; + frontColor = Pal.bulletYellow; }}; - flakPlastic = new FlakBulletType(4f, 5){{ - splashDamageRadius = 40f; + flakPlastic = new FlakBulletType(4f, 6){{ + splashDamageRadius = 50f; fragBullet = artilleryPlasticFrag; - fragBullets = 4; + fragBullets = 6; hitEffect = Fx.plasticExplosion; - frontColor = Palette.plastaniumFront; - backColor = Palette.plastaniumBack; + frontColor = Pal.plastaniumFront; + backColor = Pal.plastaniumBack; + shootEffect = Fx.shootBig; }}; flakExplosive = new FlakBulletType(4f, 5){{ //default bullet type, no changes + shootEffect = Fx.shootBig; }}; flakSurge = new FlakBulletType(4f, 7){{ splashDamage = 33f; lightining = 2; lightningLength = 12; + shootEffect = Fx.shootBig; }}; missileExplosive = new MissileBulletType(1.8f, 10, "missile"){{ @@ -171,8 +175,8 @@ public class Bullets implements ContentList{ }}; missileIncendiary = new MissileBulletType(2f, 12, "missile"){{ - frontColor = Palette.lightishOrange; - backColor = Palette.lightOrange; + frontColor = Pal.lightishOrange; + backColor = Pal.lightOrange; bulletWidth = 7f; bulletHeight = 8f; bulletShrink = 0f; @@ -212,8 +216,8 @@ public class Bullets implements ContentList{ trailColor = Color.valueOf("b6c6fd"); hitEffect = Fx.blastExplosion; despawnEffect = Fx.blastExplosion; - backColor = Palette.bulletYellowBack; - frontColor = Palette.bulletYellow; + backColor = Pal.bulletYellowBack; + frontColor = Pal.bulletYellow; weaveScale = 8f; weaveMag = 2f; }}; @@ -229,20 +233,39 @@ public class Bullets implements ContentList{ splashDamage = 10f; lifetime = 120f; trailColor = Color.GRAY; - backColor = Palette.bulletYellowBack; - frontColor = Palette.bulletYellow; + backColor = Pal.bulletYellowBack; + frontColor = Pal.bulletYellow; hitEffect = Fx.blastExplosion; despawnEffect = Fx.blastExplosion; weaveScale = 8f; weaveMag = 2f; }}; - standardCopper = new BasicBulletType(2.5f, 7, "bullet"){{ + missileRevenant = new MissileBulletType(2.7f, 12, "missile"){{ + bulletWidth = 8f; + bulletHeight = 8f; + bulletShrink = 0f; + drag = -0.003f; + homingRange = 60f; + keepVelocity = false; + splashDamageRadius = 25f; + splashDamage = 10f; + lifetime = 80f; + trailColor = Pal.unitBack; + backColor = Pal.unitBack; + frontColor = Pal.unitFront; + hitEffect = Fx.blastExplosion; + despawnEffect = Fx.blastExplosion; + weaveScale = 6f; + weaveMag = 1f; + }}; + + standardCopper = new BasicBulletType(2.5f, 9, "bullet"){{ bulletWidth = 7f; bulletHeight = 9f; shootEffect = Fx.shootSmall; smokeEffect = Fx.shootSmallSmoke; - ammoMultiplier = 2; + ammoMultiplier = 1; }}; standardDense = new BasicBulletType(3.5f, 18, "bullet"){{ @@ -273,8 +296,8 @@ public class Bullets implements ContentList{ standardIncendiary = new BasicBulletType(3.2f, 11, "bullet"){{ bulletWidth = 10f; bulletHeight = 12f; - frontColor = Palette.lightishOrange; - backColor = Palette.lightOrange; + frontColor = Pal.lightishOrange; + backColor = Pal.lightOrange; incendSpread = 3f; incendAmount = 1; incendChance = 0.3f; @@ -303,22 +326,25 @@ public class Bullets implements ContentList{ bulletWidth = 15f; bulletHeight = 21f; armorPierce = 0.2f; + shootEffect = Fx.shootBig; }}; standardThoriumBig = new BasicBulletType(8f, 65, "bullet"){{ bulletWidth = 16f; bulletHeight = 23f; armorPierce = 0.5f; + shootEffect = Fx.shootBig; }}; standardIncendiaryBig = new BasicBulletType(7f, 38, "bullet"){{ bulletWidth = 16f; bulletHeight = 21f; - frontColor = Palette.lightishOrange; - backColor = Palette.lightOrange; + frontColor = Pal.lightishOrange; + backColor = Pal.lightOrange; incendSpread = 3f; incendAmount = 2; incendChance = 0.3f; + shootEffect = Fx.shootBig; }}; damageLightning = new BulletType(0.0001f, 0f){{ @@ -333,6 +359,7 @@ public class Bullets implements ContentList{ float healPercent = 3f; { + shootEffect = Fx.shootHeal; hitEffect = Fx.hitLaser; despawnEffect = Fx.hitLaser; collidesTeam = true; @@ -345,7 +372,7 @@ public class Bullets implements ContentList{ @Override public void draw(Bullet b){ - Draw.color(Palette.heal); + Draw.color(Pal.heal); Lines.stroke(2f); Lines.lineAngleCenter(b.x, b.y, b.rot(), 7f); Draw.color(Color.WHITE); @@ -359,7 +386,7 @@ public class Bullets implements ContentList{ tile = tile.target(); if(tile != null && tile.getTeam() == b.getTeam() && !(tile.block() instanceof BuildBlock)){ - Effects.effect(Fx.healBlockFull, Palette.heal, tile.drawx(), tile.drawy(), tile.block().size); + Effects.effect(Fx.healBlockFull, Pal.heal, tile.drawx(), tile.drawy(), tile.block().size); tile.entity.healBy(healPercent / 100f * tile.entity.maxHealth()); } } @@ -383,7 +410,7 @@ public class Bullets implements ContentList{ @Override public void draw(Bullet b){ //TODO add color to the bullet depending on the color of the flame it came from - Draw.color(Palette.lightFlame, Palette.darkFlame, Color.GRAY, b.fin()); + Draw.color(Pal.lightFlame, Pal.darkFlame, Color.GRAY, b.fin()); Fill.circle(b.x, b.y, 3f * b.fout()); Draw.reset(); } @@ -413,6 +440,8 @@ public class Bullets implements ContentList{ lifetime = 35f; pierce = true; drag = 0.05f; + statusDuration = 60f * 4; + shootEffect = Fx.shootSmallFlame; hitEffect = Fx.hitFlameSmall; despawnEffect = Fx.none; status = StatusEffects.burning; @@ -424,10 +453,10 @@ public class Bullets implements ContentList{ }; lancerLaser = new BulletType(0.001f, 140){ - Color[] colors = {Palette.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Palette.lancerLaser, Color.WHITE}; + Color[] colors = {Pal.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Pal.lancerLaser, Color.WHITE}; float[] tscales = {1f, 0.7f, 0.5f, 0.2f}; float[] lenscales = {1f, 1.1f, 1.13f, 1.14f}; - float length = 100f; + float length = 160f; { hitEffect = Fx.hitLancer; @@ -437,6 +466,11 @@ public class Bullets implements ContentList{ pierce = true; } + @Override + public float range(){ + return length; + } + @Override public void init(Bullet b){ Damage.collideLine(b, b.getTeam(), hitEffect, b.x, b.y, b.rot(), length); @@ -459,7 +493,7 @@ public class Bullets implements ContentList{ } }; - meltdownLaser = new BulletType(0.001f, 26){ + meltdownLaser = new BulletType(0.001f, 35){ Color tmpColor = new Color(); Color[] colors = {Color.valueOf("ec745855"), Color.valueOf("ec7458aa"), Color.valueOf("ff9c5a"), Color.WHITE}; float[] tscales = {1f, 0.7f, 0.5f, 0.2f}; @@ -529,7 +563,7 @@ public class Bullets implements ContentList{ @Override public void draw(Bullet b) { super.draw(b); - Draw.color(Color.WHITE, Palette.surge, b.fin()); + Draw.color(Color.WHITE, Pal.surge, b.fin()); for(int i = 0; i < 7; i++){ Tmp.v1.trns(b.rot(), i * 8f); float sl = Mathf.clamp(b.fout()-0.5f) * (80f - i *10); @@ -543,7 +577,7 @@ public class Bullets implements ContentList{ }; waterShot = new LiquidBulletType(Liquids.water){{ - knockback = 0.65f; + knockback = 0.7f; }}; cryoShot = new LiquidBulletType(Liquids.cryofluid){{ @@ -556,6 +590,12 @@ public class Bullets implements ContentList{ drag = 0.03f; }}; + eruptorShot = new LiquidBulletType(Liquids.slag){{ + damage = 2; + speed = 2.1f; + drag = 0.02f; + }}; + oilShot = new LiquidBulletType(Liquids.oil){{ speed = 2f; drag = 0.03f; @@ -569,17 +609,22 @@ public class Bullets implements ContentList{ keepVelocity = false; } + @Override + public float range(){ + return 70f; + } + @Override public void draw(Bullet b){ } @Override public void init(Bullet b){ - Lightning.create(b.getTeam(), Palette.lancerLaser, damage, b.x, b.y, b.rot(), 30); + Lightning.create(b.getTeam(), Pal.lancerLaser, damage, b.x, b.y, b.rot(), 30); } }; - arc = new BulletType(0.001f, 26){{ + arc = new BulletType(0.001f, 20){{ lifetime = 1; despawnEffect = Fx.none; hitEffect = Fx.hitLancer; @@ -590,7 +635,7 @@ public class Bullets implements ContentList{ @Override public void init(Bullet b){ - Lightning.create(b.getTeam(), Palette.lancerLaser, damage, b.x, b.y, b.rot(), 36); + Lightning.create(b.getTeam(), Pal.lancerLaser, damage, b.x, b.y, b.rot(), 14); } }; @@ -614,8 +659,8 @@ public class Bullets implements ContentList{ bulletWidth = 8f; bulletHeight = 12f; hitEffect = Fx.flakExplosion; - backColor = Palette.lightOrange; - frontColor = Palette.lightishOrange; + backColor = Pal.lightOrange; + frontColor = Pal.lightishOrange; incendChance = 1f; incendAmount = 3; incendSpread = 10f; @@ -639,5 +684,22 @@ public class Bullets implements ContentList{ } } }; + + explode = new BombBulletType(2f, 3f, "clear"){{ + hitEffect = Fx.pulverize; + lifetime = 23f; + speed = 1f; + splashDamageRadius = 50f; + splashDamage = 20f; + } + + @Override + public void init(Bullet b){ + if(b.getOwner() instanceof Unit){ + ((Unit)b.getOwner()).kill(); + } + b.time(b.lifetime()); + } + }; } } diff --git a/core/src/io/anuke/mindustry/content/Fx.java b/core/src/io/anuke/mindustry/content/Fx.java index 3fad4e7458..dece137ea4 100644 --- a/core/src/io/anuke/mindustry/content/Fx.java +++ b/core/src/io/anuke/mindustry/content/Fx.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.content; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects.Effect; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Fill; @@ -9,11 +8,14 @@ import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Tmp; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.entities.effect.GroundEffectEntity.GroundEffect; +import io.anuke.mindustry.entities.type.BaseUnit; import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Shapes; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Item.Icon; import static io.anuke.mindustry.Vars.tilesize; @@ -32,29 +34,43 @@ public class Fx implements ContentList{ bigShockwave, nuclearShockwave, explosion, blockExplosion, blockExplosionSmoke, shootSmall, shootHeal, shootSmallSmoke, shootBig, shootBig2, shootBigSmoke, shootBigSmoke2, shootSmallFlame, shootLiquid, shellEjectSmall, shellEjectMedium, shellEjectBig, lancerLaserShoot, lancerLaserShootSmoke, lancerLaserCharge, lancerLaserChargeBegin, lightningCharge, lightningShoot, - launchFull; + unitSpawn, spawnShockwave, magmasmoke, impactShockwave, impactcloud, impactsmoke, dynamicExplosion; @Override public void load(){ none = new Effect(0, 0f, e -> {}); + unitSpawn = new Effect(30f, e -> { + if(!(e.data instanceof BaseUnit)) return; + + Draw.alpha(e.fin()); + + float scl = 1f + e.fout()*2f; + + BaseUnit unit = (BaseUnit)e.data; + Draw.rect(unit.getIconRegion(), e.x, e.y, + unit.getIconRegion().getWidth() * Draw.scl * scl, unit.getIconRegion().getWidth() * Draw.scl * scl, 180f); + + Draw.reset(); + }); + placeBlock = new Effect(16, e -> { - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.stroke(3f - e.fin() * 2f); Lines.square(e.x, e.y, tilesize / 2f * e.rotation + e.fin() * 3f); Draw.reset(); }); tapBlock = new Effect(12, e -> { - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.stroke(3f - e.fin() * 2f); Lines.circle(e.x, e.y, 4f + (tilesize / 1.5f * e.rotation) * e.fin()); Draw.reset(); }); breakBlock = new Effect(12, e -> { - Draw.color(Palette.remove); + Draw.color(Pal.remove); Lines.stroke(3f - e.fin() * 2f); Lines.square(e.x, e.y, tilesize / 2f * e.rotation + e.fin() * 3f); @@ -65,36 +81,42 @@ public class Fx implements ContentList{ }); select = new Effect(23, e -> { - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.stroke(e.fout() * 3f); Lines.circle(e.x, e.y, 3f + e.fin() * 14f); Draw.reset(); }); smoke = new Effect(100, e -> { - Draw.color(Color.GRAY, Palette.darkishGray, e.fin()); + Draw.color(Color.GRAY, Pal.darkishGray, e.fin()); float size = 7f - e.fin() * 7f; Draw.rect("circle", e.x, e.y, size, size); Draw.reset(); }); - spawn = new Effect(23, e -> { + magmasmoke = new Effect(110, e -> { + Draw.color(Color.GRAY); + Fill.circle(e.x, e.y, e.fslope() * 6f); + Draw.reset(); + }); + + spawn = new Effect(30, e -> { Lines.stroke(2f * e.fout()); - Draw.color(Palette.accent); - Lines.poly(e.x, e.y, 4, 3f + e.fin() * 8f); + Draw.color(Pal.accent); + Lines.poly(e.x, e.y, 4, 5f + e.fin() * 12f); Draw.reset(); }); vtolHover = new Effect(40f, e -> { float len = e.finpow() * 10f; float ang = e.rotation + Mathf.randomSeedRange(e.id, 30f); - Draw.color(Palette.lightFlame, Palette.lightOrange, e.fin()); + Draw.color(Pal.lightFlame, Pal.lightOrange, e.fin()); Fill.circle(e.x + Angles.trnsx(ang, len), e.y + Angles.trnsy(ang, len), 2f * e.fout()); Draw.reset(); }); unitDrop = new GroundEffect(30, e -> { - Draw.color(Palette.lightishGray); + Draw.color(Pal.lightishGray); Angles.randLenVectors(e.id, 9, 3 + 20f * e.finpow(), (x, y) -> { Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.4f); }); @@ -102,7 +124,7 @@ public class Fx implements ContentList{ }); unitLand = new GroundEffect(30, e -> { - Draw.color(Palette.lightishGray, e.color, e.rotation); + Draw.color(Tmp.c1.set(e.color).mul(1.1f)); Angles.randLenVectors(e.id, 6, 17f * e.finpow(), (x, y) -> { Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.3f); }); @@ -110,35 +132,35 @@ public class Fx implements ContentList{ }); unitPickup = new GroundEffect(18, e -> { - Draw.color(Palette.lightishGray); + Draw.color(Pal.lightishGray); Lines.stroke(e.fin() * 2f); Lines.poly(e.x, e.y, 4, 13f * e.fout()); Draw.reset(); }); landShock = new GroundEffect(12, e -> { - Draw.color(Palette.lancerLaser); + Draw.color(Pal.lancerLaser); Lines.stroke(e.fout() * 3f); Lines.poly(e.x, e.y, 12, 20f * e.fout()); Draw.reset(); }); pickup = new Effect(18, e -> { - Draw.color(Palette.lightishGray); + Draw.color(Pal.lightishGray); Lines.stroke(e.fout() * 2f); Lines.spikes(e.x, e.y, 1f + e.fin() * 6f, e.fout() * 4f, 6); Draw.reset(); }); healWave = new Effect(22, e -> { - Draw.color(Palette.heal); + Draw.color(Pal.heal); Lines.stroke(e.fout() * 2f); Lines.poly(e.x, e.y, 30, 4f + e.finpow() * 60f); Draw.color(); }); heal = new Effect(11, e -> { - Draw.color(Palette.heal); + Draw.color(Pal.heal); Lines.stroke(e.fout() * 2f); Lines.poly(e.x, e.y, 10, 2f + e.finpow() * 7f); Draw.color(); @@ -146,7 +168,7 @@ public class Fx implements ContentList{ hitBulletSmall = new Effect(14, e -> { - Draw.color(Color.WHITE, Palette.lightOrange, e.fin()); + Draw.color(Color.WHITE, Pal.lightOrange, e.fin()); e.scaled(7f, s -> { Lines.stroke(0.5f + s.fout()); @@ -165,7 +187,7 @@ public class Fx implements ContentList{ }); hitFuse = new Effect(14, e -> { - Draw.color(Color.WHITE, Palette.surge, e.fin()); + Draw.color(Color.WHITE, Pal.surge, e.fin()); e.scaled(7f, s -> { Lines.stroke(0.5f + s.fout()); @@ -184,7 +206,7 @@ public class Fx implements ContentList{ }); hitBulletBig = new Effect(13, e -> { - Draw.color(Color.WHITE, Palette.lightOrange, e.fin()); + Draw.color(Color.WHITE, Pal.lightOrange, e.fin()); Lines.stroke(0.5f + e.fout() * 1.5f); Angles.randLenVectors(e.id, 8, e.finpow() * 30f, e.rotation, 50f, (x, y) -> { @@ -196,7 +218,7 @@ public class Fx implements ContentList{ }); hitFlameSmall = new Effect(14, e -> { - Draw.color(Palette.lightFlame, Palette.darkFlame, e.fin()); + Draw.color(Pal.lightFlame, Pal.darkFlame, e.fin()); Lines.stroke(0.5f + e.fout()); Angles.randLenVectors(e.id, 5, e.fin() * 15f, e.rotation, 50f, (x, y) -> { @@ -230,7 +252,7 @@ public class Fx implements ContentList{ }); hitMeltdown = new Effect(12, e -> { - Draw.color(Palette.meltdownHit); + Draw.color(Pal.meltdownHit); Lines.stroke(e.fout() * 2f); Angles.randLenVectors(e.id, 6, e.finpow() * 18f, e.rotation, 360f, (x, y) -> { @@ -242,14 +264,14 @@ public class Fx implements ContentList{ }); hitLaser = new Effect(8, e -> { - Draw.color(Color.WHITE, Palette.heal, e.fin()); + Draw.color(Color.WHITE, Pal.heal, e.fin()); Lines.stroke(0.5f + e.fout()); Lines.circle(e.x, e.y, e.fin()*5f); Draw.reset(); }); despawn = new Effect(12, e -> { - Draw.color(Palette.lighterOrange, Color.GRAY, e.fin()); + Draw.color(Pal.lighterOrange, Color.GRAY, e.fin()); Lines.stroke(e.fout()); Angles.randLenVectors(e.id, 7, e.fin() * 7f, e.rotation, 40f, (x, y) -> { @@ -262,7 +284,7 @@ public class Fx implements ContentList{ flakExplosion = new Effect(20, e -> { - Draw.color(Palette.bulletYellow); + Draw.color(Pal.bulletYellow); e.scaled(6, i -> { Lines.stroke(3f * i.fout()); Lines.circle(e.x, e.y, 3f + i.fin() * 10f); @@ -274,7 +296,7 @@ public class Fx implements ContentList{ Fill.circle(e.x + x, e.y + y, e.fout() * 3f + 0.5f); }); - Draw.color(Palette.lighterOrange); + Draw.color(Pal.lighterOrange); Lines.stroke(1f * e.fout()); Angles.randLenVectors(e.id + 1, 4, 1f + 23f * e.finpow(), (x, y) -> { @@ -286,7 +308,7 @@ public class Fx implements ContentList{ plasticExplosion = new Effect(24, e -> { - Draw.color(Palette.plastaniumFront); + Draw.color(Pal.plastaniumFront); e.scaled(7, i -> { Lines.stroke(3f * i.fout()); Lines.circle(e.x, e.y, 3f + i.fin() * 24f); @@ -298,7 +320,7 @@ public class Fx implements ContentList{ Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f); }); - Draw.color(Palette.plastaniumBack); + Draw.color(Pal.plastaniumBack); Lines.stroke(1f * e.fout()); Angles.randLenVectors(e.id + 1, 4, 1f + 25f * e.finpow(), (x, y) -> { @@ -310,7 +332,7 @@ public class Fx implements ContentList{ plasticExplosionFlak = new Effect(28, e -> { - Draw.color(Palette.plastaniumFront); + Draw.color(Pal.plastaniumFront); e.scaled(7, i -> { Lines.stroke(3f * i.fout()); Lines.circle(e.x, e.y, 3f + i.fin() * 34f); @@ -322,7 +344,7 @@ public class Fx implements ContentList{ Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f); }); - Draw.color(Palette.plastaniumBack); + Draw.color(Pal.plastaniumBack); Lines.stroke(1f * e.fout()); Angles.randLenVectors(e.id + 1, 4, 1f + 30f * e.finpow(), (x, y) -> { @@ -334,7 +356,7 @@ public class Fx implements ContentList{ blastExplosion = new Effect(22, e -> { - Draw.color(Palette.missileYellow); + Draw.color(Pal.missileYellow); e.scaled(6, i -> { Lines.stroke(3f * i.fout()); Lines.circle(e.x, e.y, 3f + i.fin() * 15f); @@ -346,7 +368,7 @@ public class Fx implements ContentList{ Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f); }); - Draw.color(Palette.missileYellowBack); + Draw.color(Pal.missileYellowBack); Lines.stroke(1f * e.fout()); Angles.randLenVectors(e.id + 1, 4, 1f + 23f * e.finpow(), (x, y) -> { @@ -363,7 +385,7 @@ public class Fx implements ContentList{ }); incendTrail = new Effect(50, e -> { - Draw.color(Palette.lightOrange); + Draw.color(Pal.lightOrange); Fill.circle(e.x, e.y, e.rotation * e.fout()); Draw.reset(); }); @@ -375,7 +397,7 @@ public class Fx implements ContentList{ }); absorb = new Effect(12, e -> { - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.stroke(2f * e.fout()); Lines.circle(e.x, e.y, 5f * e.fout()); Draw.reset(); @@ -383,7 +405,7 @@ public class Fx implements ContentList{ flakExplosionBig = new Effect(30, e -> { - Draw.color(Palette.bulletYellowBack); + Draw.color(Pal.bulletYellowBack); e.scaled(6, i -> { Lines.stroke(3f * i.fout()); Lines.circle(e.x, e.y, 3f + i.fin() * 25f); @@ -395,7 +417,7 @@ public class Fx implements ContentList{ Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f); }); - Draw.color(Palette.bulletYellow); + Draw.color(Pal.bulletYellow); Lines.stroke(1f * e.fout()); Angles.randLenVectors(e.id + 1, 4, 1f + 23f * e.finpow(), (x, y) -> { @@ -407,7 +429,7 @@ public class Fx implements ContentList{ burning = new Effect(35f, e -> { - Draw.color(Palette.lightFlame, Palette.darkFlame, e.fin()); + Draw.color(Pal.lightFlame, Pal.darkFlame, e.fin()); Angles.randLenVectors(e.id, 3, 2f + e.fin() * 7f, (x, y) -> { Fill.circle(e.x + x, e.y + y, 0.1f + e.fout() * 1.4f); @@ -417,7 +439,7 @@ public class Fx implements ContentList{ }); fire = new Effect(35f, e -> { - Draw.color(Palette.lightFlame, Palette.darkFlame, e.fin()); + Draw.color(Pal.lightFlame, Pal.darkFlame, e.fin()); Angles.randLenVectors(e.id, 2, 2f + e.fin() * 7f, (x, y) -> { Fill.circle(e.x + x, e.y + y, 0.2f + e.fslope() * 1.5f); @@ -457,7 +479,7 @@ public class Fx implements ContentList{ }); ballfire = new Effect(25f, e -> { - Draw.color(Palette.lightFlame, Palette.darkFlame, e.fin()); + Draw.color(Pal.lightFlame, Pal.darkFlame, e.fin()); Angles.randLenVectors(e.id, 2, 2f + e.fin() * 7f, (x, y) -> { Fill.circle(e.x + x, e.y + y, 0.2f + e.fout() * 1.5f); @@ -507,7 +529,7 @@ public class Fx implements ContentList{ }); overdriven = new Effect(20f, e -> { - Draw.color(Palette.accent); + Draw.color(Pal.accent); Angles.randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> { Fill.square(e.x + x, e.y + y, e.fout() * 2.3f+0.5f); @@ -520,7 +542,7 @@ public class Fx implements ContentList{ float length = 20f * e.finpow(); float size = 7f * e.fout(); - Draw.rect(((Item) e.data).region, e.x + Angles.trnsx(e.rotation, length), e.y + Angles.trnsy(e.rotation, length), size, size); + Draw.rect(((Item) e.data).icon(Icon.large), e.x + Angles.trnsx(e.rotation, length), e.y + Angles.trnsy(e.rotation, length), size, size); }); @@ -545,6 +567,20 @@ public class Fx implements ContentList{ Draw.reset(); }); + impactShockwave = new Effect(13f, 300f, e -> { + Draw.color(Pal.lighterOrange, Color.LIGHT_GRAY, e.fin()); + Lines.stroke(e.fout() * 4f + 0.2f); + Lines.poly(e.x, e.y, 60, e.fin() * 200f); + Draw.reset(); + }); + + spawnShockwave = new Effect(20f, 400f, e -> { + Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin()); + Lines.stroke(e.fout() * 3f + 0.5f); + Lines.poly(e.x, e.y, 60, e.fin() * 450f); + Draw.reset(); + }); + explosion = new Effect(30, e -> { e.scaled(7, i -> { Lines.stroke(3f * i.fout()); @@ -558,7 +594,7 @@ public class Fx implements ContentList{ Fill.circle(e.x + x / 2f, e.y + y / 2f, e.fout() * 1f); }); - Draw.color(Palette.lighterOrange, Palette.lightOrange, Color.GRAY, e.fin()); + Draw.color(Pal.lighterOrange, Pal.lightOrange, Color.GRAY, e.fin()); Lines.stroke(1.5f * e.fout()); Angles.randLenVectors(e.id + 1, 8, 1f + 23f * e.finpow(), (x, y) -> { @@ -568,6 +604,31 @@ public class Fx implements ContentList{ Draw.reset(); }); + dynamicExplosion = new Effect(30, e -> { + float intensity = e.rotation; + + e.scaled(5 + intensity*2, i -> { + Lines.stroke(3.1f * i.fout()); + Lines.poly(e.x, e.y, (int)(20 * intensity), (3f + i.fin() * 14f) * intensity); + }); + + Draw.color(Color.GRAY); + + Angles.randLenVectors(e.id, e.finpow(), (int)(6 * intensity), 21f*intensity, (x, y, in, out) -> { + Fill.circle(e.x + x, e.y + y, out * (2f+intensity) * 3 + 0.5f); + Fill.circle(e.x + x / 2f, e.y + y / 2f, out * (intensity) * 3); + }); + + Draw.color(Pal.lighterOrange, Pal.lightOrange, Color.GRAY, e.fin()); + Lines.stroke((1.7f * e.fout()) * (1f + (intensity - 1f) / 2f)); + + Angles.randLenVectors(e.id + 1, e.finpow(), (int)(9*intensity), 40f*intensity, (x, y, in, out) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + out * 4 * (3f+intensity)); + }); + + Draw.reset(); + }); + blockExplosion = new Effect(30, e -> { e.scaled(7, i -> { Lines.stroke(3.1f * i.fout()); @@ -581,7 +642,7 @@ public class Fx implements ContentList{ Fill.circle(e.x + x / 2f, e.y + y / 2f, e.fout() * 1f); }); - Draw.color(Palette.lighterOrange, Palette.lightOrange, Color.GRAY, e.fin()); + Draw.color(Pal.lighterOrange, Pal.lightOrange, Color.GRAY, e.fin()); Lines.stroke(1.7f * e.fout()); Angles.randLenVectors(e.id + 1, 9, 1f + 23f * e.finpow(), (x, y) -> { @@ -604,7 +665,7 @@ public class Fx implements ContentList{ shootSmall = new Effect(8, e -> { - Draw.color(Palette.lighterOrange, Palette.lightOrange, e.fin()); + Draw.color(Pal.lighterOrange, Pal.lightOrange, e.fin()); float w = 1f + 5 * e.fout(); Shapes.tri(e.x, e.y, w, 15f * e.fout(), e.rotation); Shapes.tri(e.x, e.y, w, 3f * e.fout(), e.rotation + 180f); @@ -612,7 +673,7 @@ public class Fx implements ContentList{ }); shootHeal = new Effect(8, e -> { - Draw.color(Palette.heal); + Draw.color(Pal.heal); float w = 1f + 5 * e.fout(); Shapes.tri(e.x, e.y, w, 17f * e.fout(), e.rotation); Shapes.tri(e.x, e.y, w, 4f * e.fout(), e.rotation + 180f); @@ -620,7 +681,7 @@ public class Fx implements ContentList{ }); shootSmallSmoke = new Effect(20f, e -> { - Draw.color(Palette.lighterOrange, Color.LIGHT_GRAY, Color.GRAY, e.fin()); + Draw.color(Pal.lighterOrange, Color.LIGHT_GRAY, Color.GRAY, e.fin()); Angles.randLenVectors(e.id, 5, e.finpow() * 6f, e.rotation, 20f, (x, y) -> { Fill.circle(e.x + x, e.y + y, e.fout() * 1.5f); @@ -630,7 +691,7 @@ public class Fx implements ContentList{ }); shootBig = new Effect(9, e -> { - Draw.color(Palette.lighterOrange, Palette.lightOrange, e.fin()); + Draw.color(Pal.lighterOrange, Pal.lightOrange, e.fin()); float w = 1.2f + 7 * e.fout(); Shapes.tri(e.x, e.y, w, 25f * e.fout(), e.rotation); Shapes.tri(e.x, e.y, w, 4f * e.fout(), e.rotation + 180f); @@ -638,7 +699,7 @@ public class Fx implements ContentList{ }); shootBig2 = new Effect(10, e -> { - Draw.color(Palette.lightOrange, Color.GRAY, e.fin()); + Draw.color(Pal.lightOrange, Color.GRAY, e.fin()); float w = 1.2f + 8 * e.fout(); Shapes.tri(e.x, e.y, w, 29f * e.fout(), e.rotation); Shapes.tri(e.x, e.y, w, 5f * e.fout(), e.rotation + 180f); @@ -646,7 +707,7 @@ public class Fx implements ContentList{ }); shootBigSmoke = new Effect(17f, e -> { - Draw.color(Palette.lighterOrange, Color.LIGHT_GRAY, Color.GRAY, e.fin()); + Draw.color(Pal.lighterOrange, Color.LIGHT_GRAY, Color.GRAY, e.fin()); Angles.randLenVectors(e.id, 8, e.finpow() * 19f, e.rotation, 10f, (x, y) -> { Fill.circle(e.x + x, e.y + y, e.fout() * 2f + 0.2f); @@ -656,7 +717,7 @@ public class Fx implements ContentList{ }); shootBigSmoke2 = new Effect(18f, e -> { - Draw.color(Palette.lightOrange, Color.LIGHT_GRAY, Color.GRAY, e.fin()); + Draw.color(Pal.lightOrange, Color.LIGHT_GRAY, Color.GRAY, e.fin()); Angles.randLenVectors(e.id, 9, e.finpow() * 23f, e.rotation, 20f, (x, y) -> { Fill.circle(e.x + x, e.y + y, e.fout() * 2.4f + 0.2f); @@ -665,10 +726,10 @@ public class Fx implements ContentList{ Draw.reset(); }); - shootSmallFlame = new Effect(30f, e -> { - Draw.color(Palette.lightFlame, Palette.darkFlame, Color.GRAY, e.fin()); + shootSmallFlame = new Effect(32f, e -> { + Draw.color(Pal.lightFlame, Pal.darkFlame, Color.GRAY, e.fin()); - Angles.randLenVectors(e.id, 8, e.finpow() * 36f, e.rotation, 10f, (x, y) -> { + Angles.randLenVectors(e.id, 8, e.finpow() * 44f, e.rotation, 10f, (x, y) -> { Fill.circle(e.x + x, e.y + y, 0.65f + e.fout() * 1.5f); }); @@ -686,7 +747,7 @@ public class Fx implements ContentList{ }); shellEjectSmall = new GroundEffect(30f, 400f, e -> { - Draw.color(Palette.lightOrange, Color.LIGHT_GRAY, Palette.lightishGray, e.fin()); + Draw.color(Pal.lightOrange, Color.LIGHT_GRAY, Pal.lightishGray, e.fin()); float rot = Math.abs(e.rotation) + 90f; int i = Mathf.sign(e.rotation); @@ -701,7 +762,7 @@ public class Fx implements ContentList{ }); shellEjectMedium = new GroundEffect(34f, 400f, e -> { - Draw.color(Palette.lightOrange, Color.LIGHT_GRAY, Palette.lightishGray, e.fin()); + Draw.color(Pal.lightOrange, Color.LIGHT_GRAY, Pal.lightishGray, e.fin()); float rot = e.rotation + 90f; for(int i : Mathf.signs){ float len = (2f + e.finpow() * 10f) * i; @@ -724,7 +785,7 @@ public class Fx implements ContentList{ }); shellEjectBig = new GroundEffect(22f, 400f, e -> { - Draw.color(Palette.lightOrange, Color.LIGHT_GRAY, Palette.lightishGray, e.fin()); + Draw.color(Pal.lightOrange, Color.LIGHT_GRAY, Pal.lightishGray, e.fin()); float rot = e.rotation + 90f; for(int i : Mathf.signs){ float len = (4f + e.finpow() * 8f) * i; @@ -748,7 +809,7 @@ public class Fx implements ContentList{ }); lancerLaserShoot = new Effect(21f, e -> { - Draw.color(Palette.lancerLaser); + Draw.color(Pal.lancerLaser); for(int i : Mathf.signs){ Shapes.tri(e.x, e.y, 4f * e.fout(), 29f, e.rotation + 90f * i); @@ -758,7 +819,7 @@ public class Fx implements ContentList{ }); lancerLaserShootSmoke = new Effect(26f, e -> { - Draw.color(Palette.lancerLaser); + Draw.color(Pal.lancerLaser); Angles.randLenVectors(e.id, 7, 80f, e.rotation, 0f, (x, y) -> { Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fout() * 9f); @@ -768,7 +829,7 @@ public class Fx implements ContentList{ }); lancerLaserCharge = new Effect(38f, e -> { - Draw.color(Palette.lancerLaser); + Draw.color(Pal.lancerLaser); Angles.randLenVectors(e.id, 2, 1f + 20f * e.fout(), e.rotation, 120f, (x, y) -> { Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fslope() * 3f + 1f); @@ -778,7 +839,7 @@ public class Fx implements ContentList{ }); lancerLaserChargeBegin = new Effect(71f, e -> { - Draw.color(Palette.lancerLaser); + Draw.color(Pal.lancerLaser); Fill.circle(e.x, e.y, e.fin() * 3f); Draw.color(); @@ -786,7 +847,7 @@ public class Fx implements ContentList{ }); lightningCharge = new Effect(38f, e -> { - Draw.color(Palette.lancerLaser); + Draw.color(Pal.lancerLaser); Angles.randLenVectors(e.id, 2, 1f + 20f * e.fout(), e.rotation, 120f, (x, y) -> { Shapes.tri(e.x + x, e.y + y, e.fslope() * 3f + 1, e.fslope() * 3f + 1, Mathf.angle(x, y)); @@ -796,7 +857,7 @@ public class Fx implements ContentList{ }); lightningShoot = new Effect(12f, e -> { - Draw.color(Color.WHITE, Palette.lancerLaser, e.fin()); + Draw.color(Color.WHITE, Pal.lancerLaser, e.fin()); Lines.stroke(e.fout() * 1.2f + 0.5f); Angles.randLenVectors(e.id, 7, 25f * e.finpow(), e.rotation, 50f, (x, y) -> { @@ -831,11 +892,26 @@ public class Fx implements ContentList{ Draw.reset(); }); }); + impactsmoke = new Effect(60, e -> { + Angles.randLenVectors(e.id, 7, e.fin() * 20f, (x, y) -> { + float size = e.fslope() * 4f; + Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin()); + Draw.rect("circle", e.x + x, e.y + y, size, size); + Draw.reset(); + }); + }); + impactcloud = new Effect(140, 400f, e -> { + Angles.randLenVectors(e.id, 20, e.finpow() * 160f, (x, y) -> { + float size = e.fout() * 15f; + Draw.color(Pal.lighterOrange, Color.LIGHT_GRAY, e.fin()); + Draw.rect("circle", e.x + x, e.y + y, size, size); + Draw.reset(); + }); + }); redgeneratespark = new Effect(18, e -> { Angles.randLenVectors(e.id, 5, e.fin() * 8f, (x, y) -> { float len = e.fout() * 4f; - Draw.color(Palette.redSpark, Color.GRAY, e.fin()); - //Draw.alpha(e.fout()); + Draw.color(Pal.redSpark, Color.GRAY, e.fin()); Draw.rect("circle", e.x + x, e.y + y, len, len); Draw.reset(); }); @@ -843,7 +919,7 @@ public class Fx implements ContentList{ generatespark = new Effect(18, e -> { Angles.randLenVectors(e.id, 5, e.fin() * 8f, (x, y) -> { float len = e.fout() * 4f; - Draw.color(Palette.orangeSpark, Color.GRAY, e.fin()); + Draw.color(Pal.orangeSpark, Color.GRAY, e.fin()); Draw.rect("circle", e.x + x, e.y + y, len, len); Draw.reset(); }); @@ -865,42 +941,42 @@ public class Fx implements ContentList{ }); pulverize = new Effect(40, e -> { Angles.randLenVectors(e.id, 5, 3f + e.fin() * 8f, (x, y) -> { - Draw.color(Palette.stoneGray); + Draw.color(Pal.stoneGray); Fill.square(e.x + x, e.y + y, e.fout() * 2f + 0.5f, 45); Draw.reset(); }); }); pulverizeRed = new Effect(40, e -> { Angles.randLenVectors(e.id, 5, 3f + e.fin() * 8f, (x, y) -> { - Draw.color(Palette.redDust, Palette.stoneGray, e.fin()); + Draw.color(Pal.redDust, Pal.stoneGray, e.fin()); Fill.square(e.x + x, e.y + y, e.fout() * 2f + 0.5f, 45); Draw.reset(); }); }); pulverizeRedder = new Effect(40, e -> { Angles.randLenVectors(e.id, 5, 3f + e.fin() * 9f, (x, y) -> { - Draw.color(Palette.redderDust, Palette.stoneGray, e.fin()); + Draw.color(Pal.redderDust, Pal.stoneGray, e.fin()); Fill.square(e.x + x, e.y + y, e.fout() * 2.5f + 0.5f, 45); Draw.reset(); }); }); pulverizeSmall = new Effect(30, e -> { Angles.randLenVectors(e.id, 3, e.fin() * 5f, (x, y) -> { - Draw.color(Palette.stoneGray); + Draw.color(Pal.stoneGray); Fill.square(e.x + x, e.y + y, e.fout() * 1f + 0.5f, 45); Draw.reset(); }); }); pulverizeMedium = new Effect(30, e -> { Angles.randLenVectors(e.id, 5, 3f + e.fin() * 8f, (x, y) -> { - Draw.color(Palette.stoneGray); + Draw.color(Pal.stoneGray); Fill.square(e.x + x, e.y + y, e.fout() * 1f + 0.5f, 45); Draw.reset(); }); }); producesmoke = new Effect(12, e -> { Angles.randLenVectors(e.id, 8, 4f + e.fin() * 18f, (x, y) -> { - Draw.color(Color.WHITE, Palette.accent, e.fin()); + Draw.color(Color.WHITE, Pal.accent, e.fin()); Fill.square(e.x + x, e.y + y, 1f + e.fout() * 3f, 45); Draw.reset(); }); @@ -914,7 +990,7 @@ public class Fx implements ContentList{ }); formsmoke = new Effect(40, e -> { Angles.randLenVectors(e.id, 6, 5f + e.fin() * 8f, (x, y) -> { - Draw.color(Palette.plasticSmoke, Color.LIGHT_GRAY, e.fin()); + Draw.color(Pal.plasticSmoke, Color.LIGHT_GRAY, e.fin()); Fill.square(e.x + x, e.y + y, 0.2f + e.fout() * 2f, 45); Draw.reset(); }); @@ -1046,7 +1122,7 @@ public class Fx implements ContentList{ Draw.reset(); }); ripple = new GroundEffect(false, 30, e -> { - Draw.color(Tmp.c1.set(e.color).shiftValue(0.1f)); + Draw.color(Tmp.c1.set(e.color).mul(1.2f)); Lines.stroke(e.fout() + 0.4f); Lines.circle(e.x, e.y, 2f + e.fin() * 4f); Draw.reset(); @@ -1062,7 +1138,7 @@ public class Fx implements ContentList{ }); launch = new Effect(28, e -> { - Draw.color(Palette.command); + Draw.color(Pal.command); Lines.stroke(e.fout() * 2f); Lines.poly(e.x, e.y, 40, 4f + e.finpow() * 120f); Draw.color(); @@ -1083,7 +1159,7 @@ public class Fx implements ContentList{ }); healBlock = new Effect(20, e -> { - Draw.color(Palette.heal); + Draw.color(Pal.heal); Lines.stroke(2f * e.fout() + 0.5f); Lines.square(e.x, e.y, 1f + (e.fin() * e.rotation * tilesize/2f-1f)); Draw.color(); @@ -1104,17 +1180,10 @@ public class Fx implements ContentList{ }); shieldBreak = new Effect(40, e -> { - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.stroke(3f * e.fout()); Lines.poly(e.x, e.y, 6, e.rotation + e.fin(), 90); Draw.reset(); }); - - launchFull = new Effect(60, 9999999999f, e -> { - Draw.color(); - Draw.alpha(e.fslope()); - Fill.rect(Core.camera.position.x, Core.camera.position.y, Core.camera.width + 10, Core.camera.height + 10); - Draw.reset(); - }); } } diff --git a/core/src/io/anuke/mindustry/content/Items.java b/core/src/io/anuke/mindustry/content/Items.java index a3e7279909..54945c53c5 100644 --- a/core/src/io/anuke/mindustry/content/Items.java +++ b/core/src/io/anuke/mindustry/content/Items.java @@ -7,7 +7,7 @@ import io.anuke.mindustry.type.ItemType; public class Items implements ContentList{ public static Item scrap, copper, lead, graphite, coal, titanium, thorium, silicon, plastanium, phasefabric, surgealloy, - biomatter, sand, blastCompound, pyratite, metaglass; + sporePod, sand, blastCompound, pyratite, metaglass; @Override public void load(){ @@ -26,7 +26,7 @@ public class Items implements ContentList{ genOre = true; }}; - metaglass = new Item("metaglass", Color.valueOf("648b55")){{ + metaglass = new Item("metaglass", Color.valueOf("ebeef5")){{ type = ItemType.material; cost = 2f; }}; @@ -37,8 +37,8 @@ public class Items implements ContentList{ }}; coal = new Item("coal", Color.valueOf("272727")){{ - explosiveness = 0.2f; - flammability = 0.5f; + explosiveness = 0.4f; + flammability = 1f; hardness = 2; genOre = true; }}; @@ -52,9 +52,9 @@ public class Items implements ContentList{ thorium = new Item("thorium", Color.valueOf("f9a3c7")){{ type = ItemType.material; - explosiveness = 0.1f; + explosiveness = 0.2f; hardness = 4; - radioactivity = 0.5f; + radioactivity = 1f; cost = 1.4f; genOre = true; }}; @@ -70,39 +70,37 @@ public class Items implements ContentList{ plastanium = new Item("plastanium", Color.valueOf("cbd97f")){{ type = ItemType.material; - flammability = 0.1f; - explosiveness = 0.1f; + flammability = 0.2f; + explosiveness = 0.2f; cost = 1.6f; }}; phasefabric = new Item("phase-fabric", Color.valueOf("f4ba6e")){{ type = ItemType.material; cost = 1.5f; - fluxiness = 0.9f; - radioactivity = 0.3f; + radioactivity = 0.6f; }}; surgealloy = new Item("surge-alloy", Color.valueOf("f3e979")){{ type = ItemType.material; }}; - biomatter = new Item("biomatter", Color.valueOf("648b55")){{ - flammability = 0.55f; - fluxiness = 0.3f; + sporePod = new Item("spore-pod", Color.valueOf("7457ce")){{ + flammability = 1.05f; }}; - sand = new Item("sand", Color.valueOf("e3d39e")){{ - fluxiness = 0.5f; + sand = new Item("sand", Color.valueOf("f7cba4")){{ + }}; blastCompound = new Item("blast-compound", Color.valueOf("ff795e")){{ - flammability = 0.2f; - explosiveness = 0.6f; + flammability = 0.4f; + explosiveness = 1.2f; }}; pyratite = new Item("pyratite", Color.valueOf("ffaa5f")){{ - flammability = 0.7f; - explosiveness = 0.2f; + flammability = 1.4f; + explosiveness = 0.4f; }}; } } diff --git a/core/src/io/anuke/mindustry/content/Liquids.java b/core/src/io/anuke/mindustry/content/Liquids.java index f7f120725f..17cc695c0e 100644 --- a/core/src/io/anuke/mindustry/content/Liquids.java +++ b/core/src/io/anuke/mindustry/content/Liquids.java @@ -10,32 +10,28 @@ public class Liquids implements ContentList{ @Override public void load(){ - water = new Liquid("water", Color.valueOf("486acd")){{ + water = new Liquid("water", Color.valueOf("596ab8")){{ heatCapacity = 0.4f; - tier = 0; effect = StatusEffects.wet; }}; - slag = new Liquid("slag", Color.valueOf("ffcd66")){{ + slag = new Liquid("slag", Color.valueOf("ffa166")){{ temperature = 1f; viscosity = 0.8f; - tier = 2; effect = StatusEffects.melting; }}; oil = new Liquid("oil", Color.valueOf("313131")){{ viscosity = 0.7f; - flammability = 0.6f; - explosiveness = 0.6f; + flammability = 1.2f; + explosiveness = 1.2f; heatCapacity = 0.7f; - tier = 1; effect = StatusEffects.tarred; }}; cryofluid = new Liquid("cryofluid", Color.valueOf("6ecdec")){{ heatCapacity = 0.9f; temperature = 0.25f; - tier = 1; effect = StatusEffects.freezing; }}; } diff --git a/core/src/io/anuke/mindustry/content/Loadouts.java b/core/src/io/anuke/mindustry/content/Loadouts.java new file mode 100644 index 0000000000..a9c7f5bc3f --- /dev/null +++ b/core/src/io/anuke/mindustry/content/Loadouts.java @@ -0,0 +1,54 @@ +package io.anuke.mindustry.content; + +import io.anuke.mindustry.game.ContentList; +import io.anuke.mindustry.type.Loadout; + +public class Loadouts implements ContentList{ + public static Loadout + basicShard, + advancedShard, + basicFoundation, + basicNucleus; + + @Override + public void load(){ + basicShard = new Loadout( + " ### ", + " #1# ", + " ### ", + " ^ ^ ", + " ## ## ", + " C# C# " + ); + + advancedShard = new Loadout( + " ### ", + " #1# ", + "#######", + "C#^ ^C#", + " ## ## ", + " C# C# " + ); + + basicFoundation = new Loadout( + " #### ", + " #### ", + " #2## ", + " #### ", + " ^^^^ ", + " ###### ", + " C#C#C# " + ); + + basicNucleus = new Loadout( + " ##### ", + " ##### ", + " ##3## ", + " ##### ", + " >#####< ", + " ^ ^ ^ ^ ", + "#### ####", + "C#C# C#C#" + ); + } +} diff --git a/core/src/io/anuke/mindustry/content/Mechs.java b/core/src/io/anuke/mindustry/content/Mechs.java index 59e654c357..4ba2506664 100644 --- a/core/src/io/anuke/mindustry/content/Mechs.java +++ b/core/src/io/anuke/mindustry/content/Mechs.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.content; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; @@ -9,13 +8,15 @@ import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.effect.Lightning; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.type.Mech; +import io.anuke.mindustry.type.Weapon; public class Mechs implements ContentList{ public static Mech alpha, delta, tau, omega, dart, javelin, trident, glaive; @@ -34,9 +35,16 @@ public class Mechs implements ContentList{ mass = 1.2f; speed = 0.5f; boostSpeed = 0.85f; - weapon = Weapons.blaster; - trailColorTo = Color.valueOf("ffd37f"); - armor = 20f; + engineColor = Color.valueOf("ffd37f"); + health = 250f; + + weapon = new Weapon("blaster"){{ + length = 1.5f; + reload = 14f; + roundrobin = true; + ejectEffect = Fx.shellEjectSmall; + bullet = Bullets.standardMechSmall; + }}; } @Override @@ -54,11 +62,21 @@ public class Mechs implements ContentList{ boostSpeed = 0.95f; itemCapacity = 15; mass = 0.9f; - armor = 30f; + health = 220f; weaponOffsetX = -1; weaponOffsetY = -1; - weapon = Weapons.shockgun; - trailColorTo = Color.valueOf("d3ddff"); + engineColor = Color.valueOf("d3ddff"); + + weapon = new Weapon("shockgun"){{ + length = 1f; + reload = 40f; + roundrobin = true; + shots = 1; + inaccuracy = 0f; + velocityRnd = 0.2f; + ejectEffect = Fx.none; + bullet = Bullets.lightning; + }}; } @Override @@ -67,7 +85,7 @@ public class Mechs implements ContentList{ Effects.shake(1f, 1f, player); Effects.effect(Fx.landShock, player); for(int i = 0; i < 8; i++){ - Time.run(Mathf.random(8f), () -> Lightning.create(player.getTeam(), Palette.lancerLaser, 17f, player.x, player.y, Mathf.random(360f), 14)); + Time.run(Mathf.random(8f), () -> Lightning.create(player.getTeam(), Pal.lancerLaser, 17f, player.x, player.y, Mathf.random(360f), 14)); } } } @@ -91,9 +109,17 @@ public class Mechs implements ContentList{ drag = 0.35f; boostSpeed = 0.8f; canHeal = true; - weapon = Weapons.healBlaster; - armor = 15f; - trailColorTo = Palette.heal; + health = 200f; + engineColor = Pal.heal; + + weapon = new Weapon("heal-blaster"){{ + length = 1.5f; + reload = 24f; + roundrobin = false; + ejectEffect = Fx.none; + recoil = 2f; + bullet = Bullets.healBullet; + }}; } @Override @@ -133,9 +159,20 @@ public class Mechs implements ContentList{ shake = 4f; weaponOffsetX = 1; weaponOffsetY = 0; - weapon = Weapons.swarmer; - trailColorTo = Color.valueOf("feb380"); - armor = 45f; + engineColor = Color.valueOf("feb380"); + health = 300f; + weapon = new Weapon("swarmer"){{ + length = 1.5f; + recoil = 4f; + reload = 60f; + shots = 4; + spacing = 8f; + inaccuracy = 8f; + roundrobin = true; + ejectEffect = Fx.none; + shake = 3f; + bullet = Bullets.missileSwarm; + }}; } @Override @@ -169,16 +206,13 @@ public class Mechs implements ContentList{ public void draw(Player player){ if(player.shootHeat <= 0.01f) return; - float alpha = Draw.getColor().a; Shaders.build.progress = player.shootHeat; Shaders.build.region = armorRegion; Shaders.build.time = Time.time() / 10f; - Shaders.build.color.set(Palette.accent).a = player.shootHeat; + Shaders.build.color.set(Pal.accent).a = player.shootHeat; Draw.shader(Shaders.build); - Draw.alpha(1f); Draw.rect(armorRegion, player.x, player.y, player.rotation); - Draw.shader(Shaders.mix); - Draw.color(1f, 1f, 1f, alpha); + Draw.shader(); } }; @@ -188,12 +222,18 @@ public class Mechs implements ContentList{ mineSpeed = 0.9f; speed = 0.4f; drag = 0.1f; - armor = 10f; - weapon = Weapons.blasterSmall; + health = 180f; weaponOffsetX = -1; weaponOffsetY = -1; - trailColor = Palette.lightTrail; + engineColor = Pal.lightTrail; cellTrnsY = 1f; + weapon = new Weapon("blaster"){{ + length = 1.5f; + reload = 20f; + roundrobin = true; + ejectEffect = Fx.shellEjectSmall; + bullet = Bullets.standardCopper; + }}; } @Override @@ -211,10 +251,20 @@ public class Mechs implements ContentList{ speed = 0.11f; drag = 0.01f; mass = 2f; - armor = 5f; - weapon = Weapons.missiles; - trailColor = Color.valueOf("d3ddff"); + health = 170f; + engineColor = Color.valueOf("d3ddff"); cellTrnsY = 1f; + weapon = new Weapon("missiles"){{ + length = 1.5f; + reload = 70f; + shots = 4; + inaccuracy = 2f; + roundrobin = true; + ejectEffect = Fx.none; + velocityRnd = 0.2f; + spacing = 1f; + bullet = Bullets.missileJavelin; + }}; } @Override @@ -232,8 +282,8 @@ public class Mechs implements ContentList{ public void updateAlt(Player player){ float scl = scld(player); if(Mathf.chance(Time.delta() * (0.15*scl))){ - Effects.effect(Fx.hitLancer, Palette.lancerLaser, player.x, player.y); - Lightning.create(player.getTeam(), Palette.lancerLaser, 10f, + Effects.effect(Fx.hitLancer, Pal.lancerLaser, player.x, player.y); + Lightning.create(player.getTeam(), Pal.lancerLaser, 10f, player.x + player.velocity().x, player.y + player.velocity().y, player.rotation, 14); } } @@ -242,16 +292,11 @@ public class Mechs implements ContentList{ public void draw(Player player){ float scl = scld(player); if(scl < 0.01f) return; - float alpha = Draw.getColor().a; - Draw.shader(); - Draw.color(Palette.lancerLaser); + Draw.color(Pal.lancerLaser); Draw.alpha(scl/2f); Draw.blend(Blending.additive); Draw.rect(shield, player.x + Mathf.range(scl/2f), player.y + Mathf.range(scl/2f), player.rotation - 90); Draw.blend(); - Draw.shader(Shaders.mix); - Draw.color(); - Draw.alpha(alpha); } float scld(Player player){ @@ -266,11 +311,22 @@ public class Mechs implements ContentList{ drag = 0.034f; mass = 2.5f; turnCursor = false; - armor = 20f; + health = 220f; itemCapacity = 30; - trailColor = Color.valueOf("84f491"); - weapon = Weapons.bomberTrident; + engineColor = Color.valueOf("84f491"); cellTrnsY = 1f; + weapon = new Weapon("bomber"){{ + length = 0f; + width = 2f; + reload = 8f; + shots = 2; + roundrobin = true; + ejectEffect = Fx.none; + velocityRnd = 1f; + inaccuracy = 40f; + ignoreRotation = true; + bullet = Bullets.bombExplosive; + }}; } @Override @@ -281,16 +337,23 @@ public class Mechs implements ContentList{ glaive = new Mech("glaive-ship", true){ { - weapon = Weapons.glaiveBlaster; drillPower = 4; mineSpeed = 1.3f; speed = 0.32f; drag = 0.06f; mass = 3f; - armor = 30f; + health = 240f; itemCapacity = 60; - trailColor = Color.valueOf("feb380"); + engineColor = Color.valueOf("feb380"); cellTrnsY = 1f; + + weapon = new Weapon("bomber"){{ + length = 1.5f; + reload = 13f; + roundrobin = true; + ejectEffect = Fx.shellEjectSmall; + bullet = Bullets.standardGlaive; + }}; } }; diff --git a/core/src/io/anuke/mindustry/content/StatusEffects.java b/core/src/io/anuke/mindustry/content/StatusEffects.java index fe676e591d..e9c87b39b6 100644 --- a/core/src/io/anuke/mindustry/content/StatusEffects.java +++ b/core/src/io/anuke/mindustry/content/StatusEffects.java @@ -1,12 +1,12 @@ package io.anuke.mindustry.content; -import io.anuke.arc.entities.Effects; +import io.anuke.mindustry.entities.Effects; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.type.StatusEffect; public class StatusEffects implements ContentList{ - public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded, shocked, corroded; + public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded, shocked, corroded, boss; @Override public void load(){ @@ -71,6 +71,14 @@ public class StatusEffects implements ContentList{ armorMultiplier = 3f; }}; + boss = new StatusEffect(){{ + armorMultiplier = 3f; + damageMultiplier = 3f; + speedMultiplier = 1.1f; + //TODO custom effect + //effect = Fx.overdriven; + }}; + shocked = new StatusEffect(); //no effects, just small amounts of damage. diff --git a/core/src/io/anuke/mindustry/content/TechTree.java b/core/src/io/anuke/mindustry/content/TechTree.java index 92e3103a91..746e5dd2cb 100644 --- a/core/src/io/anuke/mindustry/content/TechTree.java +++ b/core/src/io/anuke/mindustry/content/TechTree.java @@ -12,12 +12,9 @@ public class TechTree implements ContentList{ @Override public void load(){ - root = node(core, () -> { + root = node(coreShard, () -> { node(conveyor, () -> { - node(launchPad, () -> { - - }); node(junction, () -> { node(itemBridge); @@ -28,14 +25,17 @@ public class TechTree implements ContentList{ node(container, () -> { node(unloader); node(vault, () -> { + node(launchPad, () -> { + }); }); }); - }); - node(titaniumConveyor, () -> { - node(phaseConveyor, () -> { - node(massDriver, () -> { + node(titaniumConveyor, () -> { + node(phaseConveyor, () -> { + node(massDriver, () -> { + + }); }); }); }); @@ -99,25 +99,24 @@ public class TechTree implements ContentList{ }); node(mechanicalDrill, () -> { - node(pneumaticDrill, () -> { - node(cultivator, () -> { - - }); - - node(laserDrill, () -> { - node(blastDrill, () -> { + node(graphitePress, () -> { + node(pneumaticDrill, () -> { + node(cultivator, () -> { }); - node(waterExtractor, () -> { - node(oilExtractor, () -> { + node(laserDrill, () -> { + node(blastDrill, () -> { }); + + node(waterExtractor, () -> { + node(oilExtractor, () -> { + + }); + }); }); }); - }); - - node(siliconSmelter, () -> { node(pyratiteMixer, () -> { node(blastMixer, () -> { @@ -125,33 +124,44 @@ public class TechTree implements ContentList{ }); }); - node(biomatterCompressor, () -> { - node(plastaniumCompressor, () -> { - node(phaseWeaver, () -> { + node(siliconSmelter, () -> { - }); - }); - }); - - node(incinerator, () -> { - node(melter, () -> { - node(surgeSmelter, () -> { + node(sporePress, () -> { + node(multiPress, () -> { }); - node(separator, () -> { - node(pulverizer, () -> { + node(plastaniumCompressor, () -> { + node(phaseWeaver, () -> { }); }); + }); - node(cryofluidMixer, () -> { + node(kiln, () -> { + node(incinerator, () -> { + node(melter, () -> { + node(surgeSmelter, () -> { + }); + + node(separator, () -> { + node(pulverizer, () -> { + + }); + }); + + node(cryofluidMixer, () -> { + + }); + }); }); }); }); }); + + node(mechanicalPump, () -> { node(conduit, () -> { node(liquidJunction, () -> { @@ -174,72 +184,69 @@ public class TechTree implements ContentList{ }); }); }); - }); - node(powerNode, () -> { node(combustionGenerator, () -> { - node(powerNodeLarge, () -> { - node(battery, () -> { - node(batteryLarge, () -> { + node(powerNode, () -> { + node(powerNodeLarge, () -> { + node(battery, () -> { + node(batteryLarge, () -> { + node(surgeTower, () -> { - }); - }); - - node(mendProjector, () -> { - node(forceProjector, () -> { - node(overdriveProjector, () -> { - - }); - }); - - node(repairPoint, () -> { - - }); - }); - }); - - node(turbineGenerator, () -> { - node(thermalGenerator, () -> { - node(rtgGenerator, () -> { - node(thoriumReactor, () -> { - - }); - }); - }); - }); - - node(solarPanel, () -> { - node(largeSolarPanel, () -> { - - }); - }); - }); - - node(alphaPad, () -> { - node(dartPad); - node(deltaPad, () -> { - node(javelinPad); - node(tauPad, () -> { - node(tridentPad); - node(omegaPad, () -> { - node(glaivePad); - }); - }); - }); - - node(spiritFactory, () -> { - node(daggerFactory, () -> { - node(daggerFactory, () -> { - node(titanFactory, () -> { - node(fortressFactory); - }); - node(wraithFactory, () -> { - node(phantomFactory); - node(ghoulFactory, () -> { - node(revenantFactory); }); }); }); + + node(mendProjector, () -> { + node(forceProjector, () -> { + node(overdriveProjector, () -> { + + }); + }); + + node(repairPoint, () -> { + + }); + }); + }); + + node(turbineGenerator, () -> { + node(thermalGenerator, () -> { + node(rtgGenerator, () -> { + node(differentialGenerator, () -> { + node(thoriumReactor, () -> { + node(impactReactor, () -> { + + }); + }); + }); + }); + }); + }); + + node(solarPanel, () -> { + node(largeSolarPanel, () -> { + + }); + }); + }); + + node(alphaDartPad, () -> { + node(deltaPad, () -> { + node(spiritFactory, () -> { + node(phantomFactory); + }); + + node(javelinPad, () -> { + node(tridentPad, () -> { + node(glaivePad); + }); + }); + + node(tauPad, () -> { + node(omegaPad, () -> { + + }); + }); }); }); }); @@ -250,7 +257,7 @@ public class TechTree implements ContentList{ private TechNode node(Block block, Runnable children){ ItemStack[] requirements = new ItemStack[block.buildRequirements.length]; for(int i = 0; i < requirements.length; i++){ - requirements[i] = new ItemStack(block.buildRequirements[i].item, block.buildRequirements[i].amount * 50); + requirements[i] = new ItemStack(block.buildRequirements[i].item, block.buildRequirements[i].amount * 8); } return new TechNode(block, requirements, children); @@ -272,7 +279,6 @@ public class TechTree implements ContentList{ context.children.add(this); } - //TODO remove requirements... for now this.block = block; this.requirements = requirements; diff --git a/core/src/io/anuke/mindustry/content/UnitTypes.java b/core/src/io/anuke/mindustry/content/UnitTypes.java index 0bbbb20e4a..01410348cc 100644 --- a/core/src/io/anuke/mindustry/content/UnitTypes.java +++ b/core/src/io/anuke/mindustry/content/UnitTypes.java @@ -1,26 +1,37 @@ package io.anuke.mindustry.content; import io.anuke.arc.collection.ObjectSet; -import io.anuke.mindustry.entities.units.UnitType; -import io.anuke.mindustry.entities.units.types.*; +import io.anuke.mindustry.entities.type.base.*; import io.anuke.mindustry.game.ContentList; +import io.anuke.mindustry.type.UnitType; +import io.anuke.mindustry.type.Weapon; public class UnitTypes implements ContentList{ public static UnitType spirit, phantom, - wraith, ghoul, revenant, - dagger, titan, fortress; + wraith, ghoul, revenant, lich, reaper, + dagger, crawler, titan, fortress, eruptor, chaosArray, eradicator; @Override public void load(){ spirit = new UnitType("spirit", Spirit.class, Spirit::new){{ - weapon = Weapons.healBlasterDrone; isFlying = true; drag = 0.01f; speed = 0.2f; maxVelocity = 0.8f; range = 50f; health = 60; + engineSize = 1.8f; + engineOffset = 5.7f; + weapon = new Weapon("heal-blaster"){{ + length = 1.5f; + reload = 40f; + width = 0.5f; + roundrobin = true; + ejectEffect = Fx.none; + recoil = 2f; + bullet = Bullets.healBullet; + }}; }}; dagger = new UnitType("dagger", Dagger.class, Dagger::new){{ @@ -29,8 +40,28 @@ public class UnitTypes implements ContentList{ drag = 0.4f; hitsize = 8f; mass = 1.75f; - weapon = Weapons.chainBlaster; health = 130; + weapon = new Weapon("chain-blaster"){{ + length = 1.5f; + reload = 28f; + roundrobin = true; + ejectEffect = Fx.shellEjectSmall; + bullet = Bullets.standardCopper; + }}; + }}; + + crawler = new UnitType("crawler", Crawler.class, Crawler::new){{ + maxVelocity = 1.2f; + speed = 0.26f; + drag = 0.4f; + hitsize = 8f; + mass = 1.75f; + health = 100; + weapon = new Weapon("bomber"){{ + reload = 12f; + ejectEffect = Fx.none; + bullet = Bullets.explode; + }}; }}; titan = new UnitType("titan", Titan.class, Titan::new){{ @@ -40,21 +71,105 @@ public class UnitTypes implements ContentList{ mass = 3.5f; hitsize = 9f; rotatespeed = 0.1f; - weapon = Weapons.flamethrower; health = 440; + immunities.add(StatusEffects.burning); + weapon = new Weapon("flamethrower"){{ + length = 1f; + reload = 14f; + roundrobin = true; + recoil = 1f; + ejectEffect = Fx.none; + bullet = Bullets.basicFlame; + }}; }}; fortress = new UnitType("fortress", Fortress.class, Fortress::new){{ - maxVelocity = 0.8f; + maxVelocity = 0.78f; speed = 0.15f; drag = 0.4f; mass = 5f; hitsize = 10f; rotatespeed = 0.06f; - weaponOffsetX = 1; targetAir = false; - weapon = Weapons.artillery; health = 800; + weapon = new Weapon("artillery"){{ + length = 1f; + reload = 60f; + width = 10f; + roundrobin = true; + recoil = 4f; + shake = 2f; + ejectEffect = Fx.shellEjectMedium; + bullet = Bullets.artilleryUnit; + }}; + }}; + + eruptor = new UnitType("eruptor", Eruptor.class, Eruptor::new){{ + maxVelocity = 0.81f; + speed = 0.16f; + drag = 0.4f; + mass = 5f; + hitsize = 9f; + rotatespeed = 0.05f; + targetAir = false; + health = 600; + immunities = ObjectSet.with(StatusEffects.burning, StatusEffects.melting); + weapon = new Weapon("eruption"){{ + length = 3f; + reload = 10f; + roundrobin = true; + ejectEffect = Fx.none; + bullet = Bullets.eruptorShot; + recoil = 1f; + width = 7f; + }}; + }}; + + chaosArray = new UnitType("chaos-array", Dagger.class, Dagger::new){{ + maxVelocity = 0.68f; + speed = 0.12f; + drag = 0.4f; + mass = 5f; + hitsize = 20f; + rotatespeed = 0.06f; + health = 4000; + weapon = new Weapon("chaos"){{ + length = 8f; + reload = 50f; + width = 17f; + roundrobin = true; + recoil = 3f; + shake = 2f; + shots = 4; + spacing = 4f; + shotDelay = 5; + ejectEffect = Fx.shellEjectMedium; + bullet = Bullets.flakSurge; + }}; + }}; + + eradicator = new UnitType("eradicator", Dagger.class, Dagger::new){{ + maxVelocity = 0.68f; + speed = 0.12f; + drag = 0.4f; + mass = 5f; + hitsize = 20f; + rotatespeed = 0.06f; + health = 10000; + weapon = new Weapon("eradication"){{ + length = 13f; + reload = 30f; + width = 22f; + roundrobin = true; + recoil = 3f; + shake = 2f; + inaccuracy = 3f; + shots = 4; + spacing = 0f; + shotDelay = 3; + ejectEffect = Fx.shellEjectMedium; + bullet = Bullets.standardThoriumBig; + }}; }}; wraith = new UnitType("wraith", Wraith.class, Wraith::new){{ @@ -62,9 +177,16 @@ public class UnitTypes implements ContentList{ maxVelocity = 1.9f; drag = 0.01f; mass = 1.5f; - weapon = Weapons.chainBlaster; isFlying = true; health = 70; + engineOffset = 5.5f; + weapon = new Weapon("chain-blaster"){{ + length = 1.5f; + reload = 28f; + roundrobin = true; + ejectEffect = Fx.shellEjectSmall; + bullet = Bullets.standardCopper; + }}; }}; ghoul = new UnitType("ghoul", Ghoul.class, Ghoul::new){{ @@ -75,23 +197,21 @@ public class UnitTypes implements ContentList{ drag = 0.01f; isFlying = true; targetAir = false; - weapon = Weapons.bomber; - }}; - - revenant = new UnitType("revenant", Revenant.class, Revenant::new){{ - health = 250; - mass = 5f; - hitsize = 12f; - speed = 0.14f; - maxVelocity = 1.3f; - drag = 0.01f; - range = 80f; - isFlying = true; - weapon = Weapons.laserBurster; + engineOffset = 7.8f; + weapon = new Weapon("bomber"){{ + length = 0f; + width = 2f; + reload = 12f; + roundrobin = true; + ejectEffect = Fx.none; + velocityRnd = 1f; + inaccuracy = 40f; + ignoreRotation = true; + bullet = Bullets.bombExplosive; + }}; }}; phantom = new UnitType("phantom", Phantom.class, Phantom::new){{ - weapon = Weapons.healBlasterDrone2; isFlying = true; drag = 0.01f; mass = 2f; @@ -102,7 +222,107 @@ public class UnitTypes implements ContentList{ health = 220; buildPower = 0.9f; minePower = 1.1f; + engineOffset = 6.5f; toMine = ObjectSet.with(Items.lead, Items.copper, Items.titanium); + weapon = new Weapon("heal-blaster"){{ + length = 1.5f; + reload = 20f; + width = 0.5f; + roundrobin = true; + ejectEffect = Fx.none; + recoil = 2f; + bullet = Bullets.healBullet; + }}; + }}; + + revenant = new UnitType("revenant", Revenant.class, Revenant::new){{ + health = 1000; + mass = 5f; + hitsize = 20f; + speed = 0.1f; + maxVelocity = 1f; + drag = 0.01f; + range = 80f; + shootCone = 40f; + isFlying = true; + rotateWeapon = true; + engineOffset = 12f; + engineSize = 3f; + rotatespeed = 0.01f; + attackLength = 90f; + baseRotateSpeed = 0.06f; + weapon = new Weapon("revenant-missiles"){{ + length = 3f; + reload = 70f; + width = 10f; + shots = 2; + inaccuracy = 2f; + roundrobin = true; + ejectEffect = Fx.none; + velocityRnd = 0.2f; + spacing = 1f; + bullet = Bullets.missileRevenant; + }}; + }}; + + lich = new UnitType("lich", Revenant.class, Revenant::new){{ + health = 7000; + mass = 20f; + hitsize = 40f; + speed = 0.01f; + maxVelocity = 0.6f; + drag = 0.02f; + range = 80f; + shootCone = 20f; + isFlying = true; + rotateWeapon = true; + engineOffset = 21; + engineSize = 5.3f; + rotatespeed = 0.01f; + attackLength = 90f; + baseRotateSpeed = 0.04f; + weapon = new Weapon("lich-missiles"){{ + length = 4f; + reload = 180f; + width = 22f; + shots = 22; + shotDelay = 2; + inaccuracy = 10f; + roundrobin = true; + ejectEffect = Fx.none; + velocityRnd = 0.2f; + spacing = 1f; + bullet = Bullets.missileRevenant; + }}; + }}; + + reaper = new UnitType("reaper", Revenant.class, Revenant::new){{ + health = 13000; + mass = 30f; + hitsize = 56f; + speed = 0.01f; + maxVelocity = 0.6f; + drag = 0.02f; + range = 80f; + shootCone = 30f; + isFlying = true; + rotateWeapon = true; + engineOffset = 40; + engineSize = 7.3f; + rotatespeed = 0.01f; + baseRotateSpeed = 0.04f; + weapon = new Weapon("reaper-gun"){{ + length = 3f; + reload = 10f; + width = 32f; + shots = 1; + + shake = 1f; + inaccuracy = 3f; + roundrobin = true; + ejectEffect = Fx.none; + bullet = Bullets.standardDenseBig; + }}; }}; } } diff --git a/core/src/io/anuke/mindustry/content/Weapons.java b/core/src/io/anuke/mindustry/content/Weapons.java deleted file mode 100644 index 647e41ac04..0000000000 --- a/core/src/io/anuke/mindustry/content/Weapons.java +++ /dev/null @@ -1,182 +0,0 @@ -package io.anuke.mindustry.content; - -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.Weapon; - -public class Weapons implements ContentList{ - public static Weapon blaster, blasterSmall, glaiveBlaster, droneBlaster, healBlaster, healBlasterDrone, chainBlaster, shockgun, - swarmer, bomber, bomberTrident, flakgun, flamethrower, missiles, artillery, laserBurster, healBlasterDrone2; - - @Override - public void load(){ - - blaster = new Weapon("blaster"){{ - length = 1.5f; - reload = 14f; - roundrobin = true; - ejectEffect = Fx.shellEjectSmall; - ammo = Bullets.standardMechSmall; - }}; - - blasterSmall = new Weapon("blaster"){{ - length = 1.5f; - reload = 20f; - roundrobin = true; - ejectEffect = Fx.shellEjectSmall; - ammo = Bullets.standardCopper; - }}; - - glaiveBlaster = new Weapon("bomber"){{ - length = 1.5f; - reload = 13f; - roundrobin = true; - ejectEffect = Fx.shellEjectSmall; - ammo = Bullets.standardGlaive; - }}; - - droneBlaster = new Weapon("blaster"){{ - length = 2f; - reload = 25f; - width = 1f; - roundrobin = true; - ejectEffect = Fx.shellEjectSmall; - ammo = Bullets.standardCopper; - }}; - - healBlaster = new Weapon("heal-blaster"){{ - length = 1.5f; - reload = 24f; - roundrobin = false; - ejectEffect = Fx.none; - recoil = 2f; - ammo = Bullets.healBullet; - }}; - - missiles = new Weapon("missiles"){{ - length = 1.5f; - reload = 70f; - shots = 4; - inaccuracy = 2f; - roundrobin = true; - ejectEffect = Fx.none; - velocityRnd = 0.2f; - spacing = 1f; - ammo = Bullets.missileJavelin; - }}; - - swarmer = new Weapon("swarmer"){{ - length = 1.5f; - recoil = 4f; - reload = 60f; - shots = 4; - spacing = 8f; - inaccuracy = 8f; - roundrobin = true; - ejectEffect = Fx.none; - shake = 3f; - ammo = Bullets.missileSwarm; - }}; - - chainBlaster = new Weapon("chain-blaster"){{ - length = 1.5f; - reload = 28f; - roundrobin = true; - ejectEffect = Fx.shellEjectSmall; - ammo = Bullets.standardCopper; - }}; - - shockgun = new Weapon("shockgun"){{ - length = 1f; - reload = 40f; - roundrobin = true; - shots = 1; - inaccuracy = 0f; - velocityRnd = 0.2f; - ejectEffect = Fx.none; - ammo = Bullets.lightning; - }}; - - flakgun = new Weapon("flakgun"){{ - length = 1f; - reload = 70f; - roundrobin = true; - shots = 1; - inaccuracy = 3f; - recoil = 3f; - velocityRnd = 0.1f; - ejectEffect = Fx.shellEjectMedium; - ammo = Bullets.artilleryDense; - }}; - - flamethrower = new Weapon("flamethrower"){{ - length = 1f; - reload = 14f; - roundrobin = true; - recoil = 1f; - ejectEffect = Fx.none; - ammo = Bullets.basicFlame; - }}; - - artillery = new Weapon("artillery"){{ - length = 1f; - reload = 60f; - roundrobin = true; - recoil = 5f; - shake = 2f; - ejectEffect = Fx.shellEjectMedium; - ammo = Bullets.artilleryUnit; - }}; - - bomber = new Weapon("bomber"){{ - length = 0f; - width = 2f; - reload = 12f; - roundrobin = true; - ejectEffect = Fx.none; - velocityRnd = 1f; - inaccuracy = 40f; - ammo = Bullets.bombExplosive; - }}; - - bomberTrident = new Weapon("bomber"){{ - length = 0f; - width = 2f; - reload = 8f; - shots = 2; - roundrobin = true; - ejectEffect = Fx.none; - velocityRnd = 1f; - inaccuracy = 40f; - ammo = Bullets.bombExplosive; - }}; - - laserBurster = new Weapon("bomber"){{ - reload = 80f; - shake = 3f; - width = 0f; - roundrobin = true; - ejectEffect = Fx.none; - ammo = Bullets.lancerLaser; - }}; - - healBlasterDrone = new Weapon("heal-blaster"){{ - length = 1.5f; - reload = 40f; - width = 0.5f; - roundrobin = true; - ejectEffect = Fx.none; - recoil = 2f; - ammo = Bullets.healBullet; - }}; - - healBlasterDrone2 = new Weapon("heal-blaster"){{ - length = 1.5f; - reload = 20f; - width = 0.5f; - roundrobin = true; - ejectEffect = Fx.none; - recoil = 2f; - ammo = Bullets.healBullet; - }}; - } -} diff --git a/core/src/io/anuke/mindustry/content/Zones.java b/core/src/io/anuke/mindustry/content/Zones.java index c3fa1aeaf7..f42d1d3d6d 100644 --- a/core/src/io/anuke/mindustry/content/Zones.java +++ b/core/src/io/anuke/mindustry/content/Zones.java @@ -5,101 +5,267 @@ import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.game.Rules; import io.anuke.mindustry.game.SpawnGroup; import io.anuke.mindustry.maps.generators.MapGenerator; +import io.anuke.mindustry.maps.generators.MapGenerator.Decoration; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Zone; import io.anuke.mindustry.world.Block; public class Zones implements ContentList{ - public static Zone groundZero, craters, frozenForest, ruinousShores, crags, stainedMountains, - impact, desolateRift, arcticDesert, dryWastes, nuclearComplex, moltenFault; + public static Zone groundZero, craters, frozenForest, ruinousShores, stainedMountains, + desolateRift, nuclearComplex; @Override public void load(){ groundZero = new Zone("groundZero", new MapGenerator("groundZero", 1)){{ - deployCost = ItemStack.with(Items.copper, 60); - startingItems = ItemStack.with(Items.copper, 50); + baseLaunchCost = ItemStack.with(Items.copper, -100); + startingItems = ItemStack.list(Items.copper, 100); alwaysUnlocked = true; - conditionWave = 10; + conditionWave = 5; + launchPeriod = 5; + resources = new Item[]{Items.copper, Items.scrap}; rules = () -> new Rules(){{ waves = true; waveTimer = true; - waveSpacing = 60 * 60 * 2; //2 mins + waveSpacing = 60 * 60 * 2; spawns = Array.with( new SpawnGroup(UnitTypes.dagger){{ - unitScaling = 2; + unitScaling = 1.5f; }}, new SpawnGroup(UnitTypes.dagger){{ - begin = 10; + begin = 5; unitScaling = 2; }}, new SpawnGroup(UnitTypes.dagger){{ begin = 15; - unitScaling = 1; + unitScaling = 3; }}, new SpawnGroup(UnitTypes.dagger){{ begin = 20; - unitScaling = 1; + unitScaling = 3; }}, new SpawnGroup(UnitTypes.dagger){{ begin = 25; - unitScaling = 1; + unitScaling = 3; }}, new SpawnGroup(UnitTypes.dagger){{ begin = 30; - unitScaling = 1; - }} + unitScaling = 2; + }}, + + + bossGroup(UnitTypes.fortress) ); }}; }}; - craters = new Zone("craters", new MapGenerator("craters", 1){{ distortion = 1.44f; }}){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; + craters = new Zone("craters", new MapGenerator("craters", 1).dist(0)){{ + startingItems = ItemStack.list(Items.copper, 200); + conditionWave = 10; itemRequirements = ItemStack.with(Items.copper, 2000); zoneRequirements = new Zone[]{groundZero}; blockRequirements = new Block[]{Blocks.router}; + resources = new Item[]{Items.copper, Items.lead}; rules = () -> new Rules(){{ waves = true; waveTimer = true; - waveSpacing = 60 * 80; + waveSpacing = 60 * 60 * 1f; + spawns = Array.with( + new SpawnGroup(UnitTypes.crawler){{ + unitScaling = 2f; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + begin = 5; + unitAmount = 2; + spacing = 2; + unitScaling = 2; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 3; + unitScaling = 2f; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + begin = 15; + unitScaling = 1; + unitAmount = 2; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 20; + unitScaling = 2; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + begin = 25; + unitScaling = 1; + unitAmount = 2; + }}, + + bossGroup(UnitTypes.revenant) + ); }}; }}; - frozenForest = new Zone("frozenForest", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; + frozenForest = new Zone("frozenForest", new MapGenerator("frozenForest", 1) + .decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.02))){{ + loadout = Loadouts.basicFoundation; + baseLaunchCost = ItemStack.with(Items.copper, 100); + startingItems = ItemStack.list(Items.copper, 400); + conditionWave = 10; + zoneRequirements = new Zone[]{craters}; + itemRequirements = ItemStack.with(Items.copper, 4000, Items.lead, 2000); + resources = new Item[]{Items.copper, Items.lead, Items.coal}; + rules = () -> new Rules(){{ + waves = true; + waveTimer = true; + waveSpacing = 60 * 60 * 1.5f; + spawns = Array.with( + new SpawnGroup(UnitTypes.titan){{ + unitScaling = 3; + end = 9; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + unitScaling = 2; + begin = 2; + end = 9; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + unitScaling = 2; + begin = 5; + end = 9; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + unitScaling = 0.5f; + begin = 10; + spacing = 10; + unitAmount = 5; + }}, + + new SpawnGroup(UnitTypes.titan){{ + begin = 11; + unitAmount = 2; + unitScaling = 2; + spacing = 2; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 12; + unitAmount = 2; + unitScaling = 2; + spacing = 2; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + unitScaling = 0.5f; + begin = 35; + spacing = 10; + unitAmount = 6; + }}, + + //boss + new SpawnGroup(UnitTypes.revenant){{ + begin = configureWave; + effect = StatusEffects.boss; + unitScaling = never; + }}, + + bossGroup(UnitTypes.eruptor) + ); + }}; + }}; + + ruinousShores = new Zone("ruinousShores", new MapGenerator("ruinousShores", 1).dist(3f, true)){{ + loadout = Loadouts.basicFoundation; + baseLaunchCost = ItemStack.with(Items.copper, 200, Items.graphite, 50); + startingItems = ItemStack.list(Items.copper, 400); + conditionWave = 20; + launchPeriod = 20; zoneRequirements = new Zone[]{frozenForest}; - blockRequirements = new Block[]{Blocks.copperWall}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 80; - }}; - }}; - - ruinousShores = new Zone("ruinousShores", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; - zoneRequirements = new Zone[]{frozenForest}; - blockRequirements = new Block[]{Blocks.copperWall}; + itemRequirements = ItemStack.with(Items.lead, 6000, Items.graphite, 2000); + blockRequirements = new Block[]{Blocks.graphitePress, Blocks.combustionGenerator}; + resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.sand}; rules = () -> new Rules(){{ waves = true; waveTimer = true; waveSpacing = 60 * 80; + spawns = Array.with( + new SpawnGroup(UnitTypes.wraith){{ + unitScaling = 2; + spacing = 2; + end = 10; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 1; + spacing = 2; + unitScaling = 2; + }}, + + new SpawnGroup(UnitTypes.wraith){{ + begin = 10; + unitScaling = 0.5f; + unitAmount = 6; + spacing = 10; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + begin = 5; + unitScaling = 1; + spacing = 5; + unitAmount = 1; + effect = StatusEffects.overdrive; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + begin = 22; + unitScaling = 1; + spacing = 20; + unitScaling = 0.5f; + unitAmount = 10; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 11; + spacing = 2; + unitScaling = 2; + unitAmount = 2; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 12; + spacing = 2; + unitScaling = 2; + unitAmount = 2; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + begin = 12; + spacing = 3; + unitScaling = 3; + unitAmount = 2; + }}, + + bossGroup(UnitTypes.revenant), + bossGroup(UnitTypes.revenant) + ); }}; }}; + /* crags = new Zone("crags", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); + baseLaunchCost = ItemStack.with(Items.copper, 300); startingItems = ItemStack.with(Items.copper, 200); conditionWave = 15; zoneRequirements = new Zone[]{frozenForest}; @@ -109,99 +275,245 @@ public class Zones implements ContentList{ waveTimer = true; waveSpacing = 60 * 80; }}; - }}; + }};*/ - stainedMountains = new Zone("stainedMountains", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; + stainedMountains = new Zone("stainedMountains", new MapGenerator("stainedMountains", 2) + .dist(2.5f, true) + .decor(new Decoration(Blocks.moss, Blocks.stainedBoulder, 0.01))){{ + loadout = Loadouts.basicFoundation; + baseLaunchCost = ItemStack.with(Items.copper, 100, Items.lead, 200, Items.silicon, 100); + startingItems = ItemStack.list(Items.copper, 400, Items.lead, 100); + conditionWave = 10; + launchPeriod = 10; zoneRequirements = new Zone[]{frozenForest}; - blockRequirements = new Block[]{Blocks.copperWall}; + blockRequirements = new Block[]{Blocks.pneumaticDrill}; + itemRequirements = ItemStack.with(Items.copper, 8000, Items.silicon, 2000); + resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium}; rules = () -> new Rules(){{ waves = true; waveTimer = true; - waveSpacing = 60 * 80; + waveSpacing = 60 * 60 * 2; + spawns = Array.with( + new SpawnGroup(UnitTypes.titan){{ + unitScaling = 2; + spacing = 2; + end = 10; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 1; + unitScaling = 1; + spacing = 2; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 11; + spacing = 2; + unitScaling = 2; + unitAmount = 2; + }}, + + new SpawnGroup(UnitTypes.ghoul){{ + begin = 6; + unitScaling = 0.5f; + unitAmount = 1; + spacing = 5; + }}, + + new SpawnGroup(UnitTypes.wraith){{ + begin = 10; + unitScaling = 1f; + unitAmount = 1; + spacing = 5; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 2; + unitScaling = 1; + spacing = 2; + }}, + + new SpawnGroup(UnitTypes.wraith){{ + begin = 23; + unitScaling = 1f; + unitAmount = 1; + spacing = 2; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + begin = 20; + unitScaling = 1; + spacing = 10; + unitScaling = 0.5f; + unitAmount = 10; + }}, + + bossGroup(UnitTypes.chaosArray) + ); }}; }}; - impact = new Zone("impact", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; - zoneRequirements = new Zone[]{frozenForest}; - blockRequirements = new Block[]{Blocks.copperWall}; + desolateRift = new Zone("desolateRift", new MapGenerator("desolateRift").dist(2f)){{ + loadout = Loadouts.basicNucleus; + baseLaunchCost = ItemStack.with(Items.copper, 500); + startingItems = ItemStack.list(Items.copper, 1500); + itemRequirements = ItemStack.with(Items.copper, 8000, Items.metaglass, 2000, Items.graphite, 3000); + conditionWave = 10; + launchPeriod = 20; + zoneRequirements = new Zone[]{ruinousShores}; + blockRequirements = new Block[]{Blocks.thermalGenerator}; + resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.sand}; rules = () -> new Rules(){{ waves = true; waveTimer = true; - waveSpacing = 60 * 80; + waveSpacing = 60 * 60 * 1.5f; + spawns = Array.with( + new SpawnGroup(UnitTypes.crawler){{ + unitScaling = 1; + spacing = 2; + end = 10; + }}, + + new SpawnGroup(UnitTypes.titan){{ + begin = 1; + unitScaling = 3; + spacing = 2; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 2; + spacing = 2; + unitScaling = 2; + }}, + + new SpawnGroup(UnitTypes.titan){{ + begin = 10; + unitScaling = 1f; + unitAmount = 3; + spacing = 3; + }}, + + new SpawnGroup(UnitTypes.fortress){{ + begin = 5; + unitScaling = 1; + spacing = 5; + unitAmount = 1; + }}, + + new SpawnGroup(UnitTypes.fortress){{ + begin = 13; + unitScaling = 1; + spacing = 4; + unitAmount = 1; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 11; + spacing = 2; + unitScaling = 2; + unitAmount = 2; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + unitScaling = 1; + spacing = 2; + unitAmount = 4; + begin = 13; + }}, + + bossGroup(UnitTypes.chaosArray) + ); }}; }}; - desolateRift = new Zone("desolateRift", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; - zoneRequirements = new Zone[]{frozenForest}; - blockRequirements = new Block[]{Blocks.copperWall}; + nuclearComplex = new Zone("nuclearComplex", new MapGenerator("nuclearProductionComplex", 1) + .drops(ItemStack.with(Items.copper, 2000, Items.lead, 1500, Items.silicon, 1000, Items.graphite, 1000, Items.thorium, 200, Items.titanium, 2000, Items.metaglass, 1000)) + .decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01))){{ + loadout = Loadouts.basicNucleus; + baseLaunchCost = ItemStack.with(Items.copper, 500, Items.silicon, 200, Items.metaglass, 100); + startingItems = ItemStack.list(Items.copper, 2500, Items.lead, 3000, Items.silicon, 800, Items.metaglass, 400); + itemRequirements = ItemStack.with(Items.copper, 10000, Items.titanium, 8000, Items.metaglass, 6000, Items.plastanium, 2000); + conditionWave = 30; + launchPeriod = 15; + zoneRequirements = new Zone[]{desolateRift}; + blockRequirements = new Block[]{Blocks.blastDrill, Blocks.thermalGenerator}; + resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.thorium, Items.sand}; rules = () -> new Rules(){{ waves = true; waveTimer = true; - waveSpacing = 60 * 80; + waveSpacing = 60 * 60 * 2; + + spawns = Array.with( + new SpawnGroup(UnitTypes.titan){{ + unitScaling = 2; + spacing = 2; + end = 10; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + begin = 1; + unitScaling = 2; + spacing = 2; + unitAmount = 3; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 2; + unitScaling = 1; + spacing = 2; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 10; + spacing = 2; + unitScaling = 2; + unitAmount = 2; + }}, + + new SpawnGroup(UnitTypes.ghoul){{ + begin = 5; + unitScaling = 0.5f; + unitAmount = 1; + spacing = 5; + }}, + + new SpawnGroup(UnitTypes.fortress){{ + begin = 13; + unitScaling = 2; + spacing = 3; + }}, + + new SpawnGroup(UnitTypes.wraith){{ + begin = 10; + unitScaling = 1f; + unitAmount = 1; + spacing = 5; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 2; + unitScaling = 1; + spacing = 2; + }}, + + new SpawnGroup(UnitTypes.wraith){{ + begin = 23; + unitScaling = 1f; + unitAmount = 1; + spacing = 2; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + begin = 20; + unitScaling = 1; + spacing = 10; + unitScaling = 0.5f; + unitAmount = 10; + }}, + + bossGroup(UnitTypes.reaper) + ); }}; }}; - - arcticDesert = new Zone("arcticDesert", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; - zoneRequirements = new Zone[]{frozenForest}; - blockRequirements = new Block[]{Blocks.copperWall}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 80; - }}; - }}; - - dryWastes = new Zone("dryWastes", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; - zoneRequirements = new Zone[]{frozenForest}; - blockRequirements = new Block[]{Blocks.copperWall}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 80; - }}; - }}; - - nuclearComplex = new Zone("nuclearComplex", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; - zoneRequirements = new Zone[]{frozenForest}; - blockRequirements = new Block[]{Blocks.copperWall}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 80; - }}; - }}; - - moltenFault = new Zone("moltenFault", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; - zoneRequirements = new Zone[]{frozenForest}; - blockRequirements = new Block[]{Blocks.copperWall}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 80; - }}; - }}; - - frozenForest.zoneRequirements = new Zone[]{frozenForest}; } } diff --git a/core/src/io/anuke/mindustry/core/ContentLoader.java b/core/src/io/anuke/mindustry/core/ContentLoader.java index c2ce06754a..8ce56c10de 100644 --- a/core/src/io/anuke/mindustry/core/ContentLoader.java +++ b/core/src/io/anuke/mindustry/core/ContentLoader.java @@ -4,9 +4,11 @@ import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectMap; import io.anuke.arc.collection.ObjectSet; import io.anuke.arc.function.Consumer; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.Pixmap; import io.anuke.arc.util.Log; import io.anuke.mindustry.content.*; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.entities.effect.Fire; @@ -16,11 +18,15 @@ import io.anuke.mindustry.entities.traits.TypeTrait; import io.anuke.mindustry.game.Content; import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.game.MappableContent; -import io.anuke.mindustry.type.*; +import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.type.Zone; import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.ColorMapper; import io.anuke.mindustry.world.LegacyColorMapper; +import static io.anuke.arc.Core.files; + /** * Loads all game content. * Call load() before doing anything with content. @@ -28,7 +34,7 @@ import io.anuke.mindustry.world.LegacyColorMapper; @SuppressWarnings("unchecked") public class ContentLoader{ private boolean loaded = false; - private boolean verbose = true; + private boolean verbose = false; private ObjectMap[] contentNameMap = new ObjectMap[ContentType.values().length]; private Array[] contentMap = new Array[ContentType.values().length]; @@ -40,18 +46,21 @@ public class ContentLoader{ new StatusEffects(), new Liquids(), new Bullets(), - new Weapons(), new Mechs(), new UnitTypes(), new Blocks(), + new Loadouts(), new TechTree(), new Zones(), //these are not really content classes, but this makes initialization easier - new ColorMapper(), new LegacyColorMapper(), }; + public void setVerbose(){ + verbose = true; + } + /**Creates all content types.*/ public void load(){ if(loaded){ @@ -76,7 +85,7 @@ public class ContentLoader{ for(Content c : contentMap[type.ordinal()]){ if(c instanceof MappableContent){ - String name = ((MappableContent) c).getContentName(); + String name = ((MappableContent) c).name; if(contentNameMap[type.ordinal()].containsKey(name)){ throw new IllegalArgumentException("Two content objects cannot have the same name! (issue: '" + name + "')"); } @@ -126,6 +135,22 @@ public class ContentLoader{ initialization.add(callable); } + /**Loads block colors.*/ + public void loadColors(){ + Pixmap pixmap = new Pixmap(files.internal("sprites/block_colors.png")); + for(int i = 0; i < 256; i++){ + if(blocks().size > i){ + int color = pixmap.getPixel(i, 0); + + if(color == 0) continue; + + Block block = block(i); + Color.rgba8888ToColor(block.color, color); + } + } + pixmap.dispose(); + } + public void verbose(boolean verbose){ this.verbose = verbose; } diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index e9b793fc73..1ec4d8176e 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -3,22 +3,22 @@ package io.anuke.mindustry.core; import io.anuke.arc.ApplicationListener; import io.anuke.arc.Core; import io.anuke.arc.Events; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.EntityQuery; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureAtlas; import io.anuke.arc.input.KeyCode; -import io.anuke.arc.scene.ui.TextField; import io.anuke.arc.util.Interval; import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.EntityQuery; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.Content; import io.anuke.mindustry.game.EventType.*; import io.anuke.mindustry.game.GlobalData; +import io.anuke.mindustry.game.Rules; import io.anuke.mindustry.game.Saves; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.input.Binding; @@ -27,7 +27,9 @@ import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.input.MobileInput; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.ui.dialogs.FloatingDialog; +import io.anuke.mindustry.world.Tile; import java.io.IOException; @@ -61,10 +63,11 @@ public class Control implements ApplicationListener{ Draw.scl = 1f / Core.atlas.find("scale_marker").getWidth(); content.initialize(Content::load); + /* if(Core.atlas.getTextures().size != 1){ throw new IllegalStateException("Atlas must be exactly one texture. " + "If more textures are used, the map editor will not display them correctly."); - } + }*/ data.load(); @@ -98,9 +101,7 @@ public class Control implements ApplicationListener{ }); Events.on(WorldLoadEvent.class, event -> { - if(mobile){ - Core.app.post(() -> Core.camera.position.set(players[0])); - } + Core.app.post(() -> Core.camera.position.set(players[0])); }); Events.on(ResetEvent.class, event -> { @@ -164,6 +165,14 @@ public class Control implements ApplicationListener{ state.stats.enemyUnitsDestroyed ++; } }); + + Events.on(ZoneCompleteEvent.class, e -> { + ui.hudfrag.showToast(Core.bundle.format("zone.complete", e.zone.conditionWave)); + }); + + Events.on(ZoneConfigureCompleteEvent.class, e -> { + ui.hudfrag.showToast(Core.bundle.format("zone.config.complete", e.zone.configureWave)); + }); } public void addPlayer(int index){ @@ -227,9 +236,10 @@ public class Control implements ApplicationListener{ return inputs[index]; } - public void playMap(Map map){ + public void playMap(Map map, Rules rules){ ui.loadAnd(() -> { logic.reset(); + state.rules = rules; world.loadMap(map); logic.play(); }); @@ -270,16 +280,16 @@ public class Control implements ApplicationListener{ if(!Core.settings.getBool("4.0-warning-2", false)){ Time.run(5f, () -> { - FloatingDialog dialog = new FloatingDialog("WARNING!"); + FloatingDialog dialog = new FloatingDialog("VERY IMPORTANT"); dialog.buttons.addButton("$ok", () -> { dialog.hide(); Core.settings.put("4.0-warning-2", true); Core.settings.save(); }).size(100f, 60f); - dialog.cont.add("Reminder: The alpha version you are about to play is very unstable, and is [accent]not representative of the final 4.0 release.[]\n\n " + + dialog.cont.add("Reminder: The alpha version you are about to play is very unstable, and is [accent]not representative of the final v4 release.[]\n\n " + "\nThere is currently[scarlet] no sound implemented[]; this is intentional.\n" + - "All current art and UI is temporary, and will be re-drawn before release. " + - "\n\n[accent]Saves and maps may be corrupted without warning between updates.").wrap().width(400f); + "All current art and UI is unfinished, and will be changed before release. " + + "\n\n[accent]Saves may be corrupted without warning between updates.").wrap().width(400f); dialog.show(); }); } @@ -287,25 +297,32 @@ public class Control implements ApplicationListener{ @Override public void update(){ - saves.update(); for(InputHandler inputHandler : inputs){ inputHandler.updateController(); } + //autosave global data if it's modified + data.checkSave(); + if(!state.is(State.menu)){ for(InputHandler input : inputs){ input.update(); } - //autosave global data every second if it's modified - if(timer.get(1, 60)){ - data.checkSave(); + if(world.isZone()){ + for(Tile tile : state.teams.get(players[0].getTeam()).cores){ + for(Item item : content.items()){ + if(tile.entity.items.has(item)){ + data.unlockContent(item); + } + } + } } //auto-update rpc every 5 seconds - if(timer.get(60 * 5)){ + if(timer.get(0, 60 * 5)){ Platform.instance.updateRPC(); } @@ -322,10 +339,6 @@ public class Control implements ApplicationListener{ } } - if(!mobile && Core.input.keyTap(Binding.screenshot) && !(scene.getKeyboardFocus() instanceof TextField) && !ui.chatfrag.chatOpen()){ - renderer.takeMapScreenshot(); - } - }else{ if(!state.isPaused()){ Time.update(); diff --git a/core/src/io/anuke/mindustry/core/GameState.java b/core/src/io/anuke/mindustry/core/GameState.java index b1d19aa9ec..9765ae1786 100644 --- a/core/src/io/anuke/mindustry/core/GameState.java +++ b/core/src/io/anuke/mindustry/core/GameState.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.core; import io.anuke.arc.Events; +import io.anuke.mindustry.entities.type.BaseUnit; import io.anuke.mindustry.game.EventType.StateChangeEvent; import io.anuke.mindustry.game.Rules; import io.anuke.mindustry.game.Stats; @@ -32,13 +33,17 @@ public class GameState{ return Net.client() ? enemies : unitGroups[waveTeam.ordinal()].size(); } + public BaseUnit boss(){ + return unitGroups[waveTeam.ordinal()].find(BaseUnit::isBoss); + } + public void set(State astate){ Events.fire(new StateChangeEvent(state, astate)); state = astate; } public boolean isPaused(){ - return is(State.paused) && !Net.active(); + return (is(State.paused) && !Net.active()) || (gameOver && !Net.active()); } public boolean is(State astate){ diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index 50681fb1b4..5b3bb71f47 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -4,15 +4,19 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.ApplicationListener; import io.anuke.arc.Events; -import io.anuke.arc.entities.Entities; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.EntityQuery; +import io.anuke.arc.collection.ObjectSet.ObjectSetIterator; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Entities; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.EntityQuery; import io.anuke.arc.util.Time; +import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.game.EventType.*; import io.anuke.mindustry.game.*; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; import static io.anuke.mindustry.Vars.*; @@ -28,15 +32,9 @@ import static io.anuke.mindustry.Vars.*; public class Logic implements ApplicationListener{ public Logic(){ - Events.on(TileChangeEvent.class, event -> { - if(event.tile.getTeam() == defaultTeam && event.tile.block().isVisible()){ - handleContent(event.tile.block()); - } - }); - Events.on(WaveEvent.class, event -> { if(world.isZone()){ - data.updateWaveScore(world.getZone(), state.wave); + world.getZone().updateWave(state.wave); } }); } @@ -70,7 +68,6 @@ public class Logic implements ApplicationListener{ state.gameOver = state.launched = false; state.teams = new Teams(); state.rules = new Rules(); - state.rules.spawns = Waves.getDefaultSpawns(); state.stats = new Stats(); Time.clear(); @@ -83,16 +80,17 @@ public class Logic implements ApplicationListener{ public void runWave(){ world.spawner.spawnEnemies(); state.wave++; - state.wavetime = state.rules.waveSpacing; + state.wavetime = world.isZone() && world.getZone().isBossWave(state.wave) ? state.rules.waveSpacing * bossWaveMultiplier : + world.isZone() && world.getZone().isLaunchWave(state.wave) ? state.rules.waveSpacing * launchWaveMultiplier : state.rules.waveSpacing; Events.fire(new WaveEvent()); } private void checkGameOver(){ - if(!state.rules.pvp && state.teams.get(defaultTeam).cores.size == 0 && !state.gameOver){ + if(state.rules.waves && state.teams.get(defaultTeam).cores.size == 0 && !state.gameOver){ state.gameOver = true; Events.fire(new GameOverEvent(waveTeam)); - }else if(state.rules.pvp){ + }else if(!state.rules.waves){ Team alive = null; for(Team team : Team.all){ @@ -111,6 +109,27 @@ public class Logic implements ApplicationListener{ } } + @Remote(called = Loc.both) + public static void launchZone(){ + if(!headless){ + ui.hudfrag.showLaunch(); + } + + for(Tile tile : new ObjectSetIterator<>(state.teams.get(defaultTeam).cores)){ + Effects.effect(Fx.launch, tile); + } + + Time.runTask(30f, () -> { + for(Tile tile : new ObjectSetIterator<>(state.teams.get(defaultTeam).cores)){ + for(Item item : content.items()){ + data.addItem(item, tile.entity.items.get(item)); + } + world.removeBlock(tile); + } + state.launched = true; + }); + } + @Remote(called = Loc.both) public static void onGameOver(Team winner){ ui.restart.show(winner); diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 86a4fb4735..45da7f1586 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -7,9 +7,8 @@ import io.anuke.annotations.Annotations.Variant; import io.anuke.arc.ApplicationListener; import io.anuke.arc.Core; import io.anuke.arc.collection.IntSet; -import io.anuke.arc.entities.Entities; -import io.anuke.arc.entities.EntityGroup; import io.anuke.arc.graphics.Color; +import io.anuke.arc.math.RandomXS128; import io.anuke.arc.util.Interval; import io.anuke.arc.util.Log; import io.anuke.arc.util.Time; @@ -17,10 +16,12 @@ import io.anuke.arc.util.io.ReusableByteArrayInputStream; import io.anuke.arc.util.serialization.Base64Coder; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.Entities; +import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; import io.anuke.mindustry.entities.traits.SyncTrait; import io.anuke.mindustry.entities.traits.TypeTrait; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.gen.RemoteReadClient; @@ -34,7 +35,6 @@ import io.anuke.mindustry.world.modules.ItemModule; import java.io.DataInputStream; import java.io.IOException; -import java.util.Random; import java.util.zip.InflaterInputStream; import static io.anuke.mindustry.Vars.*; @@ -345,7 +345,7 @@ public class NetClient implements ApplicationListener{ requests[i] = player.getPlaceQueue().get(i); } - Call.onClientShapshot(lastSent++, Time.millis(), player.x, player.y, + Call.onClientShapshot(lastSent++, player.x, player.y, player.pointerX, player.pointerY, player.rotation, player.baseRotation, player.velocity().x, player.velocity().y, player.getMineTile(), @@ -364,7 +364,7 @@ public class NetClient implements ApplicationListener{ return Core.settings.getString("usid-" + ip, null); }else{ byte[] bytes = new byte[8]; - new Random().nextBytes(bytes); + new RandomXS128().nextBytes(bytes); String result = new String(Base64Coder.encode(bytes)); Core.settings.put("usid-" + ip, result); Core.settings.save(); diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index 1df4e182e1..fceb8136af 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -7,10 +7,6 @@ import io.anuke.arc.Events; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.IntMap; import io.anuke.arc.collection.ObjectSet; -import io.anuke.arc.entities.Entities; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.EntityQuery; -import io.anuke.arc.entities.trait.Entity; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.Colors; import io.anuke.arc.math.Mathf; @@ -19,14 +15,19 @@ import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Log; import io.anuke.arc.util.Structs; import io.anuke.arc.util.Time; +import io.anuke.arc.util.Tmp; import io.anuke.arc.util.io.ByteBufferOutput; import io.anuke.arc.util.io.CountableByteArrayOutputStream; -import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.Entities; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.EntityQuery; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; +import io.anuke.mindustry.entities.traits.Entity; import io.anuke.mindustry.entities.traits.SyncTrait; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Version; @@ -51,12 +52,6 @@ import static io.anuke.mindustry.Vars.*; public class NetServer implements ApplicationListener{ public final static int maxSnapshotSize = 430; - - public final static boolean debugSnapshots = false; - public final static float maxSnapshotDelay = 200; - public final static float snapshotDropchance = 0.01f; - - private final static byte[] reusableSnapArray = new byte[maxSnapshotSize]; private final static float serverSyncTime = 4, kickDuration = 30 * 1000; private final static Vector2 vector = new Vector2(); private final static Rectangle viewport = new Rectangle(); @@ -156,7 +151,7 @@ public class NetServer implements ApplicationListener{ return; } - Log.info("Recieved connect packet for player '{0}' / UUID {1} / IP {2}", packet.name, uuid, connection.address); + Log.debug("Recieved connect packet for player '{0}' / UUID {1} / IP {2}", packet.name, uuid, connection.address); String ip = Net.getConnection(id).address; @@ -234,7 +229,7 @@ public class NetServer implements ApplicationListener{ data.stream = new ByteArrayInputStream(stream.toByteArray()); Net.sendStream(clientID, data); - Log.info("Packed {0} compressed bytes of world data.", stream.size()); + Log.debug("Packed {0} compressed bytes of world data.", stream.size()); } public static void onDisconnect(Player player){ @@ -259,7 +254,7 @@ public class NetServer implements ApplicationListener{ @Remote(targets = Loc.client, unreliable = true) public static void onClientShapshot( Player player, - int snapshotID, long sent, + int snapshotID, float x, float y, float pointerX, float pointerY, float rotation, float baseRotation, @@ -272,7 +267,7 @@ public class NetServer implements ApplicationListener{ NetConnection connection = player.con; if(connection == null || snapshotID < connection.lastRecievedClientSnapshot) return; - boolean verifyPosition = !player.isDead() && netServer.admins.getStrict() && headless && player.getCarrier() == null; + boolean verifyPosition = !player.isDead() && netServer.admins.getStrict() && headless; if(connection.lastRecievedClientTime == 0) connection.lastRecievedClientTime = Time.millis() - 16; @@ -329,7 +324,7 @@ public class NetServer implements ApplicationListener{ player.y = prevy; //set interpolator target to *new* position so it moves toward it - player.getInterpolator().read(player.x, player.y, newx, newy, sent, rotation, baseRotation); + player.getInterpolator().read(player.x, player.y, newx, newy, rotation, baseRotation); player.velocity().set(xVelocity, yVelocity); //only for visual calculation purposes, doesn't actually update the player connection.lastRecievedClientSnapshot = snapshotID; @@ -340,13 +335,13 @@ public class NetServer implements ApplicationListener{ public static void onAdminRequest(Player player, Player other, AdminAction action){ if(!player.isAdmin){ - Log.err("ACCESS DENIED: Player {0} / {1} attempted to perform admin action without proper security access.", + Log.warn("ACCESS DENIED: Player {0} / {1} attempted to perform admin action without proper security access.", player.name, player.con.address); return; } if(other == null || ((other.isAdmin && !player.isLocal) && other != player)){ - Log.err("{0} attempted to perform admin action on nonexistant or admin player.", player.name); + Log.warn("{0} attempted to perform admin action on nonexistant or admin player.", player.name); return; } @@ -475,7 +470,7 @@ public class NetServer implements ApplicationListener{ returnArray.clear(); if(represent.isClipped()){ EntityQuery.getNearby(group, viewport, entity -> { - if(((SyncTrait) entity).isSyncing() && viewport.contains(entity.getX(), entity.getY())){ + if(((SyncTrait) entity).isSyncing() && viewport.overlaps(Tmp.r3.setSize(((SyncTrait)entity).clipSize(), ((SyncTrait)entity).clipSize()).setCenter(entity.getX(), entity.getY()))){ returnArray.add(entity); } }); diff --git a/core/src/io/anuke/mindustry/core/Platform.java b/core/src/io/anuke/mindustry/core/Platform.java index 999c57fa7f..4e7591f323 100644 --- a/core/src/io/anuke/mindustry/core/Platform.java +++ b/core/src/io/anuke/mindustry/core/Platform.java @@ -4,11 +4,10 @@ import io.anuke.arc.Core; import io.anuke.arc.Input.TextInput; import io.anuke.arc.files.FileHandle; import io.anuke.arc.function.Consumer; +import io.anuke.arc.math.RandomXS128; import io.anuke.arc.scene.ui.TextField; import io.anuke.arc.util.serialization.Base64Coder; -import java.util.Random; - import static io.anuke.mindustry.Vars.mobile; public abstract class Platform { @@ -49,7 +48,7 @@ public abstract class Platform { String uuid = Core.settings.getString("uuid", ""); if(uuid.isEmpty()){ byte[] result = new byte[8]; - new Random().nextBytes(result); + new RandomXS128().nextBytes(result); uuid = new String(Base64Coder.encode(result)); Core.settings.put("uuid", uuid); Core.settings.save(); diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index a1fd94c4bb..a6dbfdab31 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -2,12 +2,6 @@ package io.anuke.mindustry.core; import io.anuke.arc.ApplicationListener; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.EntityDraw; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.impl.EffectEntity; -import io.anuke.arc.entities.trait.DrawTrait; -import io.anuke.arc.entities.trait.Entity; import io.anuke.arc.function.Consumer; import io.anuke.arc.function.Predicate; import io.anuke.arc.graphics.Camera; @@ -15,23 +9,32 @@ import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.graphics.g2d.SpriteBatch; +import io.anuke.arc.graphics.glutils.FrameBuffer; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.ScreenRecorder; import io.anuke.arc.util.Time; +import io.anuke.arc.util.Tmp; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.EntityDraw; +import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.effect.GroundEffectEntity; import io.anuke.mindustry.entities.effect.GroundEffectEntity.GroundEffect; +import io.anuke.mindustry.entities.impl.EffectEntity; import io.anuke.mindustry.entities.traits.BelowLiquidTrait; -import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.entities.traits.DrawTrait; +import io.anuke.mindustry.entities.traits.Entity; +import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.graphics.*; +import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity; import static io.anuke.arc.Core.*; import static io.anuke.mindustry.Vars.*; @@ -41,18 +44,17 @@ public class Renderer implements ApplicationListener{ public final MinimapRenderer minimap = new MinimapRenderer(); public final OverlayRenderer overlays = new OverlayRenderer(); + public FrameBuffer shieldBuffer = new FrameBuffer(2, 2); private Color clearColor; private float targetscale = io.anuke.arc.scene.ui.layout.Unit.dp.scl(4); private float camerascale = targetscale; private Rectangle rect = new Rectangle(), rect2 = new Rectangle(); - private Vector2 avgPosition = new Vector2(); private float shakeIntensity, shaketime; public Renderer(){ batch = new SpriteBatch(4096); camera = new Camera(); Lines.setCircleVertices(14); - Shaders.init(); Effects.setScreenShakeProvider((intensity, duration) -> { @@ -63,8 +65,7 @@ public class Renderer implements ApplicationListener{ Effects.setEffectProvider((effect, color, x, y, rotation, data) -> { if(effect == Fx.none) return; if(Core.settings.getBool("effects")){ - Rectangle view = rect.setSize(camera.width, camera.height) - .setCenter(camera.position.x, camera.position.y); + Rectangle view = camera.bounds(rect); Rectangle pos = rect2.setSize(effect.size).setCenter(x, y); if(view.overlaps(pos)){ @@ -72,7 +73,7 @@ public class Renderer implements ApplicationListener{ if(!(effect instanceof GroundEffect)){ EffectEntity entity = Pools.obtain(EffectEntity.class, EffectEntity::new); entity.effect = effect; - entity.color = color; + entity.color.set(color); entity.rotation = rotation; entity.data = data; entity.id++; @@ -84,7 +85,7 @@ public class Renderer implements ApplicationListener{ }else{ GroundEffectEntity entity = Pools.obtain(GroundEffectEntity.class, GroundEffectEntity::new); entity.effect = effect; - entity.color = color; + entity.color.set(color); entity.rotation = rotation; entity.id++; entity.data = data; @@ -113,11 +114,11 @@ public class Renderer implements ApplicationListener{ if(state.is(State.menu)){ graphics.clear(Color.BLACK); }else{ - Vector2 position = averagePosition(); + Vector2 position = Tmp.v3.set(players[0]); if(players[0].isDead()){ TileEntity core = players[0].getClosestCore(); - if(core != null && players[0].spawner == Unit.noSpawner){ + if(core != null && players[0].spawner == null){ camera.position.lerpDelta(core.x, core.y, 0.08f); }else{ camera.position.lerpDelta(position, 0.08f); @@ -126,9 +127,6 @@ public class Renderer implements ApplicationListener{ camera.position.lerpDelta(position, 0.08f); } - camera.position.x = Mathf.clamp(camera.position.x, -tilesize / 2f, world.width() * tilesize - tilesize / 2f); - camera.position.y = Mathf.clamp(camera.position.y, -tilesize / 2f, world.height() * tilesize - tilesize / 2f); - updateShake(0.75f); draw(); @@ -161,6 +159,10 @@ public class Renderer implements ApplicationListener{ graphics.clear(clearColor); + if(graphics.getWidth() >= 2 && graphics.getHeight() >= 2 && (shieldBuffer.getWidth() != graphics.getWidth() || shieldBuffer.getHeight() != graphics.getHeight())){ + shieldBuffer.resize(graphics.getWidth(), graphics.getHeight()); + } + Draw.proj(camera.projection()); blocks.floor.drawFloor(); @@ -172,7 +174,13 @@ public class Renderer implements ApplicationListener{ blocks.processBlocks(); blocks.drawShadows(); + + blocks.floor.beginDraw(); + blocks.floor.drawLayer(CacheLayer.walls); + blocks.floor.endDraw(); + blocks.drawBlocks(Layer.block); + blocks.drawFog(); Draw.shader(Shaders.blockbuild, true); blocks.drawBlocks(Layer.placement); @@ -195,17 +203,20 @@ public class Renderer implements ApplicationListener{ overlays.drawBottom(); drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests); - //TODO shield - /* - if(shieldGroup.size() > 0){ - Graphics.beginShaders(Shaders.shield); + if(EntityDraw.countInBounds(shieldGroup) > 0){ + Draw.flush(); + shieldBuffer.begin(); + graphics.clear(Color.CLEAR); EntityDraw.draw(shieldGroup); EntityDraw.drawWith(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawOver()); - Draw.color(Palette.accent); - Graphics.endShaders(); + Draw.flush(); + shieldBuffer.end(); + Draw.shader(Shaders.shield); + Draw.color(Pal.accent); + Draw.rect(Draw.wrap(shieldBuffer.getTexture()), camera.position.x, camera.position.y, camera.width, -camera.height); Draw.color(); + Draw.shader(); } - */ overlays.drawTop(); @@ -218,11 +229,8 @@ public class Renderer implements ApplicationListener{ } private void drawFlyerShadows(){ - //TODO fix flyer shadows - //Graphics.surface(effectSurface, true, false); - float trnsX = -12, trnsY = -13; - Draw.color(0, 0, 0, 0.15f); + Draw.color(0, 0, 0, 0.22f); for(EntityGroup group : unitGroups){ if(!group.isEmpty()){ @@ -234,8 +242,6 @@ public class Renderer implements ApplicationListener{ drawAndInterpolate(playerGroup, unit -> unit.isFlying() && !unit.isDead(), player -> player.drawShadow(trnsX, trnsY)); } - //Draw.color(0, 0, 0, 0.15f); - //Graphics.flushSurface(); Draw.color(); } @@ -247,18 +253,11 @@ public class Renderer implements ApplicationListener{ playerGroup.count(p -> p.isFlying() == flying && p.getTeam() == team) == 0 && flying) continue; drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder); - drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawUnder); + drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team && !p.isDead(), Unit::drawUnder); - Shaders.outline.color.set(team.color); - Shaders.mix.color.set(Color.WHITE); - - //Graphics.beginShaders(Shaders.outline); - Draw.shader(Shaders.mix, true); drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawAll); drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawAll); - Draw.shader(); blocks.drawTeamBlocks(Layer.turret, team); - //Graphics.endShaders(); drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver); drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver); @@ -281,15 +280,6 @@ public class Renderer implements ApplicationListener{ return camerascale; } - public Vector2 averagePosition(){ - avgPosition.setZero(); - - drawAndInterpolate(playerGroup, p -> p.isLocal, p -> avgPosition.add(p.x, p.y)); - - avgPosition.scl(1f / players.length); - return avgPosition; - } - public void scaleCamera(float amount){ targetscale += amount; clampScale(); @@ -297,47 +287,7 @@ public class Renderer implements ApplicationListener{ public void clampScale(){ float s = io.anuke.arc.scene.ui.layout.Unit.dp.scl(1f); - targetscale = Mathf.clamp(targetscale, s * 2.5f, Math.round(s * 7)); - } - - public void takeMapScreenshot(){ - //TODO fix/implement - /* - float vpW = camera.width, vpH = camera.height; - int w = world.width()*tilesize, h = world.height()*tilesize; - int pw = pixelSurface.width(), ph = pixelSurface.height(); - disableUI = true; - pixelSurface.setSize(w, h, true); - Graphics.getEffectSurface().setSize(w, h, true); - camera.width = w; - camera.height = h; - camera.position.x = w/2f + tilesize/2f; - camera.position.y = h/2f + tilesize/2f; - - draw(); - - disableUI = false; - camera.width = vpW; - camera.height = vpH; - - pixelSurface.getBuffer().begin(); - byte[] lines = ScreenUtils.getFrameBufferPixels(0, 0, w, h, true); - for(int i = 0; i < lines.length; i+= 4){ - lines[i + 3] = (byte)255; - } - pixelSurface.getBuffer().end(); - - Pixmap fullPixmap = new Pixmap(w, h, Pixmap.Format.RGBA8888); - - BufferUtils.copy(lines, 0, fullPixmap.getPixels(), lines.length); - FileHandle file = screenshotDirectory.child("screenshot-" + Time.millis() + ".png"); - PixmapIO.writePNG(file, fullPixmap); - fullPixmap.dispose(); - - pixelSurface.setSize(pw, ph, false); - Graphics.getEffectSurface().setSize(pw, ph, false); - - ui.showInfoFade(Core.bundle.format("screenshot", file.toString()));*/ + targetscale = Mathf.clamp(targetscale, s * 1.5f, Math.round(s * 5)); } } diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index e1db7dcfd8..abf9b8cf9e 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -28,7 +28,7 @@ import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; import io.anuke.mindustry.editor.MapEditorDialog; import io.anuke.mindustry.game.EventType.ResizeEvent; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.ui.dialogs.*; import io.anuke.mindustry.ui.fragments.*; @@ -48,7 +48,7 @@ public class UI implements ApplicationListener{ public AboutDialog about; public GameOverDialog restart; - public CustomGameDialog levels; + public CustomGameDialog custom; public MapsDialog maps; public LoadDialog load; public DiscordDialog discord; @@ -108,28 +108,28 @@ public class UI implements ApplicationListener{ Core.app.post(() -> showError("Failed to access local storage.\nSettings will not be saved.")); }); - Colors.put("accent", Palette.accent); + Colors.put("accent", Pal.accent); loadCursors(); } void loadCursors(){ - int cursorScaling = 3; + int cursorScaling = 1, outlineThickness = 3; Color outlineColor = Color.valueOf("444444"); - drillCursor = Core.graphics.newCursor("drill", cursorScaling, outlineColor); - unloadCursor = Core.graphics.newCursor("unload", cursorScaling, outlineColor); - SystemCursor.arrow.set(Core.graphics.newCursor("cursor", cursorScaling, outlineColor)); - SystemCursor.hand.set(Core.graphics.newCursor("hand", cursorScaling, outlineColor)); - SystemCursor.ibeam.set(Core.graphics.newCursor("ibeam", cursorScaling, outlineColor)); + drillCursor = Core.graphics.newCursor("drill", cursorScaling, outlineColor, outlineThickness); + unloadCursor = Core.graphics.newCursor("unload", cursorScaling, outlineColor, outlineThickness); + SystemCursor.arrow.set(Core.graphics.newCursor("cursor", cursorScaling, outlineColor, outlineThickness)); + SystemCursor.hand.set(Core.graphics.newCursor("hand", cursorScaling, outlineColor, outlineThickness)); + SystemCursor.ibeam.set(Core.graphics.newCursor("ibeam", cursorScaling, outlineColor, outlineThickness)); Core.graphics.restoreCursor(); } void generateFonts(Skin skin){ - generator = new FreeTypeFontGenerator(Core.files.internal("fonts/pixel.ttf")); + generator = new FreeTypeFontGenerator(Core.files.internal("fonts/font.ttf")); FreeTypeFontParameter param = new FreeTypeFontParameter(); - param.size = (int)(14*2 * Math.max(Unit.dp.scl(1f), 0.5f)); + param.size = (int)(9*2 * Math.max(Unit.dp.scl(1f), 0.5f)); param.shadowColor = Color.DARK_GRAY; param.shadowOffsetY = 2; param.incremental = true; @@ -163,7 +163,7 @@ public class UI implements ApplicationListener{ join = new JoinDialog(); discord = new DiscordDialog(); load = new LoadDialog(); - levels = new CustomGameDialog(); + custom = new CustomGameDialog(); language = new LanguageDialog(); database = new DatabaseDialog(); settings = new SettingsMenuDialog(); @@ -238,7 +238,7 @@ public class UI implements ApplicationListener{ Table table = new Table(); table.setFillParent(true); table.actions(Actions.fadeOut(7f, Interpolation.fade), Actions.removeActor()); - table.top().add(info).padTop(40); + table.top().add(info).padTop(10); Core.scene.add(table); } @@ -250,17 +250,6 @@ public class UI implements ApplicationListener{ }}.show(); } - public void showInfo(String info, Runnable clicked){ - new Dialog("", "dialog"){{ - getCell(cont).growX(); - cont.margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center); - buttons.addButton("$ok", () -> { - clicked.run(); - hide(); - }).size(90, 50).pad(4); - }}.show(); - } - public void showError(String text){ new Dialog("$error.title", "dialog"){{ cont.margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center); @@ -275,9 +264,16 @@ public class UI implements ApplicationListener{ }}.show(); } + public void showInfoText(String titleText, String text){ + new Dialog(titleText, "dialog"){{ + cont.margin(15).add(text).width(400f).wrap().left().get().setAlignment(Align.left, Align.left); + buttons.addButton("$ok", this::hide).size(90, 50).pad(4); + }}.show(); + } + public void showConfirm(String title, String text, Runnable confirmed){ FloatingDialog dialog = new FloatingDialog(title); - dialog.cont.add(text).width(400f).wrap().pad(4f).get().setAlignment(Align.center, Align.center); + dialog.cont.add(text).width(500f).wrap().pad(4f).get().setAlignment(Align.center, Align.center); dialog.buttons.defaults().size(200f, 54f).pad(2f); dialog.setFillParent(false); dialog.buttons.addButton("$cancel", dialog::hide); diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index 5725acf4c4..8a8cfe1251 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -5,22 +5,18 @@ import io.anuke.arc.Core; import io.anuke.arc.Events; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.IntArray; -import io.anuke.arc.collection.ObjectSet.ObjectSetIterator; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.EntityQuery; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Point2; import io.anuke.arc.util.Log; import io.anuke.arc.util.Structs; -import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; import io.anuke.mindustry.ai.BlockIndexer; import io.anuke.mindustry.ai.Pathfinder; import io.anuke.mindustry.ai.WaveSpawner; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.entities.EntityQuery; import io.anuke.mindustry.game.EventType.TileChangeEvent; import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.Team; @@ -29,7 +25,6 @@ import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.maps.Maps; import io.anuke.mindustry.maps.generators.Generator; import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Zone; import io.anuke.mindustry.world.Block; @@ -188,7 +183,7 @@ public class World implements ApplicationListener{ addDarkness(tiles); - EntityQuery.resizeTree(0, 0, tiles.length * tilesize, tiles[0].length * tilesize); + EntityQuery.resizeTree(-finalWorldBounds, -finalWorldBounds, tiles.length * tilesize + finalWorldBounds, tiles[0].length * tilesize + finalWorldBounds); generating = false; Events.fire(new WorldLoadEvent()); @@ -198,24 +193,6 @@ public class World implements ApplicationListener{ return generating; } - public void launchZone(){ - Effects.effect(Fx.launchFull, 0, 0); - - for(Tile tile : new ObjectSetIterator<>(state.teams.get(defaultTeam).cores)){ - Effects.effect(Fx.launch, tile); - } - - Time.runTask(30f, () -> { - for(Tile tile : new ObjectSetIterator<>(state.teams.get(defaultTeam).cores)){ - for(Item item : content.items()){ - data.addItem(item, tile.entity.items.get(item)); - } - world.removeBlock(tile); - } - state.launched = true; - }); - } - public boolean isZone(){ return getZone() != null; } @@ -228,13 +205,14 @@ public class World implements ApplicationListener{ ui.loadAnd(() -> { logic.reset(); state.rules = zone.rules.get(); + state.rules.zone = zone.id; loadGenerator(zone.generator); for(Tile core : state.teams.get(defaultTeam).cores){ - for(ItemStack stack : zone.startingItems){ + for(ItemStack stack : zone.getStartingItems()){ core.entity.items.add(stack.item, stack.amount); } } - state.rules.zone = zone.id; + state.set(State.playing); control.saves.zoneSave(); logic.play(); }); @@ -290,6 +268,17 @@ public class World implements ApplicationListener{ ui.showError("$map.nospawn.pvp"); } } + }else{ + invalidMap = true; + for(Team team : Team.all){ + if(state.teams.get(team).cores.size != 0){ + invalidMap = false; + } + } + + if(invalidMap){ + throw new MapException(map, "Map has no cores!"); + } } if(invalidMap) Core.app.post(() -> state.set(State.menu)); @@ -440,7 +429,6 @@ public class World implements ApplicationListener{ } public void addDarkness(Tile[][] tiles){ - byte[][] dark = new byte[tiles.length][tiles[0].length]; byte[][] writeBuffer = new byte[tiles.length][tiles[0].length]; @@ -448,7 +436,7 @@ public class World implements ApplicationListener{ for(int x = 0; x < tiles.length; x++){ for(int y = 0; y < tiles[0].length; y++){ Tile tile = tiles[x][y]; - if(tile.block().solid && !tile.block().update){ + if(tile.block().solid && !tile.block().synthetic() && tile.block().fillsTile){ dark[x][y] = darkIterations; } } @@ -479,7 +467,7 @@ public class World implements ApplicationListener{ for(int x = 0; x < tiles.length; x++){ for(int y = 0; y < tiles[0].length; y++){ Tile tile = tiles[x][y]; - if(tile.block().solid && !tile.block().update){ + if(tile.block().solid && !tile.block().synthetic()){ tiles[x][y].setRotation(dark[x][y]); } } diff --git a/core/src/io/anuke/mindustry/editor/EditorTool.java b/core/src/io/anuke/mindustry/editor/EditorTool.java index 51ac91362e..c15b7d9e64 100644 --- a/core/src/io/anuke/mindustry/editor/EditorTool.java +++ b/core/src/io/anuke/mindustry/editor/EditorTool.java @@ -1,15 +1,17 @@ package io.anuke.mindustry.editor; +import io.anuke.arc.Core; import io.anuke.arc.collection.IntArray; import io.anuke.arc.function.IntPositionConsumer; +import io.anuke.arc.input.KeyCode; import io.anuke.arc.util.Pack; import io.anuke.arc.util.Structs; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.blocks.BlockPart; import io.anuke.mindustry.world.blocks.Floor; -import static io.anuke.mindustry.Vars.content; -import static io.anuke.mindustry.Vars.ui; +import static io.anuke.mindustry.Vars.*; public enum EditorTool{ pick{ @@ -40,7 +42,7 @@ public enum EditorTool{ @Override public void touched(MapEditor editor, int x, int y){ - editor.draw(x, y); + editor.draw(x, y, isPaint()); } }, eraser{ @@ -51,7 +53,7 @@ public enum EditorTool{ @Override public void touched(MapEditor editor, int x, int y){ - editor.draw(x, y, Blocks.air); + editor.draw(x, y, isPaint(), Blocks.air); } }, spray{ @@ -62,7 +64,7 @@ public enum EditorTool{ @Override public void touched(MapEditor editor, int x, int y){ - editor.draw(x, y, editor.getDrawBlock(), 0.012); + editor.draw(x, y, isPaint(), editor.getDrawBlock(), 0.012); } }, line{ @@ -102,20 +104,13 @@ public enum EditorTool{ dest = floor ? bf : bw; byte draw = editor.getDrawBlock().id; - if(dest == draw){ + if(dest == draw || content.block(bw) instanceof BlockPart || content.block(bw).isMultiblock()){ return; } width = world.width(); int height = world.height(); - int x1; - boolean spanAbove, spanBelow; - - stack.clear(); - - stack.add(asi(x, y)); - IntPositionConsumer writer = (px, py) -> { TileDataMarker prev = editor.getPrev(px, py, false); @@ -132,32 +127,60 @@ public enum EditorTool{ editor.onWrite(px, py, prev); }; - while(stack.size > 0){ - int popped = stack.pop(); - x = popped % width; - y = popped / width; - - x1 = x; - while(x1 >= 0 && eq(x1, y)) x1--; - x1++; - spanAbove = spanBelow = false; - while(x1 < width && eq(x1, y)){ - writer.accept(x1, y); - - if(!spanAbove && y > 0 && eq(x1, y - 1)){ - stack.add(asi(x1, y - 1)); - spanAbove = true; - }else if(spanAbove && y > 0 && eq(x1, y - 1)){ - spanAbove = false; + if(isAlt()){ + for(int cx = 0; cx < width; cx++){ + for(int cy = 0; cy < height; cy++){ + if(eq(cx, cy)){ + writer.accept(cx, cy); + } } - - if(!spanBelow && y < height - 1 && eq(x1, y + 1)){ - stack.add(asi(x1, y + 1)); - spanBelow = true; - }else if(spanBelow && y < height - 1 && eq(x1, y + 1)){ - spanBelow = false; + } + }else if(isAlt2()){ + for(int cx = 0; cx < width; cx++){ + for(int cy = 0; cy < height; cy++){ + byte w = data.read(cx, cy, DataPosition.wall); + if(content.block(w).synthetic()){ + TileDataMarker prev = editor.getPrev(cx, cy, false); + data.write(cx, cy, DataPosition.rotationTeam, (byte)editor.getDrawTeam().ordinal()); + editor.onWrite(cx, cy, prev); + } } + } + }else{ + int x1; + boolean spanAbove, spanBelow; + + stack.clear(); + + stack.add(asi(x, y)); + + while(stack.size > 0){ + int popped = stack.pop(); + x = popped % width; + y = popped / width; + + x1 = x; + while(x1 >= 0 && eq(x1, y)) x1--; x1++; + spanAbove = spanBelow = false; + while(x1 < width && eq(x1, y)){ + writer.accept(x1, y); + + if(!spanAbove && y > 0 && eq(x1, y - 1)){ + stack.add(asi(x1, y - 1)); + spanAbove = true; + }else if(spanAbove && y > 0 && eq(x1, y - 1)){ + spanAbove = false; + } + + if(!spanBelow && y < height - 1 && eq(x1, y + 1)){ + stack.add(asi(x1, y + 1)); + spanBelow = true; + }else if(spanBelow && y < height - 1 && eq(x1, y + 1)){ + spanBelow = false; + } + x1++; + } } } } @@ -178,6 +201,18 @@ public enum EditorTool{ boolean edit, draggable; + public static boolean isPaint(){ + return Core.input.keyDown(KeyCode.CONTROL_LEFT); + } + + public static boolean isAlt(){ + return Core.input.keyDown(KeyCode.TAB); + } + + public static boolean isAlt2(){ + return Core.input.keyDown(KeyCode.GRAVE); + } + public void touched(MapEditor editor, int x, int y){ } diff --git a/core/src/io/anuke/mindustry/editor/MapEditor.java b/core/src/io/anuke/mindustry/editor/MapEditor.java index e1fdcb7e0b..cb5aabeb19 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditor.java +++ b/core/src/io/anuke/mindustry/editor/MapEditor.java @@ -79,15 +79,15 @@ public class MapEditor{ this.brushSize = size; } - public void draw(int x, int y){ - draw(x, y, drawBlock); + public void draw(int x, int y, boolean paint){ + draw(x, y, paint, drawBlock); } - public void draw(int x, int y, Block drawBlock){ - draw(x, y, drawBlock, 1.0); + public void draw(int x, int y, boolean paint, Block drawBlock){ + draw(x, y, paint, drawBlock, 1.0); } - public void draw(int x, int y, Block drawBlock, double chance){ + public void draw(int x, int y, boolean paint, Block drawBlock, double chance){ byte writeID = drawBlock.id; byte partID = Blocks.part.id; byte rotationTeam = Pack.byteByte(drawBlock.rotate ? (byte)rotation : 0, drawBlock.synthetic() ? (byte)drawTeam.ordinal() : 0); @@ -144,7 +144,7 @@ public class MapEditor{ if(Mathf.dst(rx, ry) <= brushSize - 0.5f && (chance >= 0.999 || Mathf.chance(chance))){ int wx = x + rx, wy = y + ry; - if(wx < 0 || wy < 0 || wx >= map.width() || wy >= map.height()){ + if(wx < 0 || wy < 0 || wx >= map.width() || wy >= map.height() || (paint && !isfloor && content.block(map.read(wx, wy, DataPosition.wall)) == Blocks.air)){ continue; } @@ -230,10 +230,21 @@ public class MapEditor{ } public void resize(int width, int height){ + MapTileData previous = map; + int offsetX = -(width - previous.width())/2, offsetY = -(height - previous.height())/2; + map = new MapTileData(width, height); for(int x = 0; x < map.width(); x++){ for(int y = 0; y < map.height(); y++){ - map.write(x, y, DataPosition.floor, Blocks.stone.id); + int px = offsetX + x, py = offsetY + y; + if(Structs.inBounds(px, py, previous.width(), previous.height())){ + map.write(x, y, DataPosition.floor, previous.read(px, py, DataPosition.floor)); + map.write(x, y, DataPosition.wall, previous.read(px, py, DataPosition.wall)); + map.write(x, y, DataPosition.link, previous.read(px, py, DataPosition.link)); + map.write(x, y, DataPosition.rotationTeam, previous.read(px, py, DataPosition.rotationTeam)); + }else{ + map.write(x, y, DataPosition.floor, Blocks.stone.id); + } } } renderer.resize(width, height); diff --git a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java index a1616a402e..42d8103856 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java @@ -27,6 +27,7 @@ import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; import io.anuke.mindustry.world.blocks.OreBlock; +import io.anuke.mindustry.world.blocks.storage.CoreBlock; import java.io.DataInputStream; import java.io.InputStream; @@ -165,7 +166,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ editor.beginEdit(data, meta.tags, false); view.clearStack(); }catch(Exception e){ - ui.showError(Core.bundle.format("editor.errormapload", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false))); Log.err(e); } })); @@ -200,7 +201,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ view.clearStack(); Core.scene.setScrollFocus(view); if(!shownWithMap){ - editor.beginEdit(new MapTileData(256, 256), new ObjectMap<>(), true); + editor.beginEdit(new MapTileData(200, 200), new ObjectMap<>(), true); } shownWithMap = false; @@ -501,14 +502,20 @@ public class MapEditorDialog extends Dialog implements Disposable{ blocksOut.clear(); blocksOut.addAll(Vars.content.blocks()); - blocksOut.sort((b1, b2) -> b1.synthetic() && !b2.synthetic() ? 1 : b2.synthetic() && !b1.synthetic() ? -1 : - b1 instanceof OreBlock && !(b2 instanceof OreBlock) ? 1 : !(b1 instanceof OreBlock) && b2 instanceof OreBlock ? -1 : - Integer.compare(b1.id, b2.id)); + blocksOut.sort((b1, b2) -> { + int core = -Boolean.compare(b1 instanceof CoreBlock, b2 instanceof CoreBlock); + if(core != 0) return core; + int synth = Boolean.compare(b1.synthetic(), b2.synthetic()); + if(synth != 0) return synth; + int ore = Boolean.compare(b1 instanceof OreBlock, b2 instanceof OreBlock); + if(ore != 0) return ore; + return Integer.compare(b1.id, b2.id); + }); for(Block block : blocksOut){ TextureRegion region = block.icon(Icon.medium); - if(region == Core.atlas.find("jjfgj")) continue; + if(!Core.atlas.isFound(region)) continue; ImageButton button = new ImageButton("white", "clear-toggle"); button.getStyle().imageUp = new TextureRegionDrawable(region); @@ -525,7 +532,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ group.getButtons().get(2).setChecked(true); - table.table("underline", extra -> extra.labelWrap(() -> editor.getDrawBlock().formalName).width(200f).center()).growX(); + table.table("underline", extra -> extra.labelWrap(() -> editor.getDrawBlock().localizedName).width(200f).center()).growX(); table.row(); table.add(pane).growY().fillX(); } diff --git a/core/src/io/anuke/mindustry/editor/MapInfoDialog.java b/core/src/io/anuke/mindustry/editor/MapInfoDialog.java index 73b6ce6220..f1e81e7ab0 100644 --- a/core/src/io/anuke/mindustry/editor/MapInfoDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapInfoDialog.java @@ -60,13 +60,6 @@ public class MapInfoDialog extends FloatingDialog{ }).size(400, 55f).get(); author.setMessageText("$unknown"); - cont.row(); - - cont.add().padRight(8).left(); - cont.addCheck("$editor.oregen", enabled -> { - tags.put("oregen", enabled ? "1" : "0"); - }).update(c -> c.setChecked(!tags.get("oregen", "0").equals("0"))).left(); - name.change(); description.change(); author.change(); diff --git a/core/src/io/anuke/mindustry/editor/MapRenderer.java b/core/src/io/anuke/mindustry/editor/MapRenderer.java index c472db4f8c..d0da1def5b 100644 --- a/core/src/io/anuke/mindustry/editor/MapRenderer.java +++ b/core/src/io/anuke/mindustry/editor/MapRenderer.java @@ -4,15 +4,16 @@ import io.anuke.arc.Core; import io.anuke.arc.collection.IntSet; import io.anuke.arc.collection.IntSet.IntSetIterator; import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.Texture; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Disposable; import io.anuke.arc.util.Pack; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.graphics.IndexedRenderer; import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Block.Icon; import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.tilesize; @@ -24,9 +25,11 @@ public class MapRenderer implements Disposable{ private IntSet delayedUpdates = new IntSet(); private MapEditor editor; private int width, height; + private Texture texture; public MapRenderer(MapEditor editor){ this.editor = editor; + texture = Core.atlas.find("clear-editor").getTexture(); } public void resize(int width, int height){ @@ -50,7 +53,6 @@ public class MapRenderer implements Disposable{ updateAll(); } - public void draw(float tx, float ty, float tw, float th){ Draw.flush(); @@ -78,7 +80,7 @@ public class MapRenderer implements Disposable{ mesh.getTransformMatrix().setToTranslation(tx, ty).scale(tw / (width * tilesize), th / (height * tilesize)); mesh.setProjectionMatrix(Draw.proj()); - mesh.render(Core.atlas.getTextures().first()); + mesh.render(texture); } } } @@ -114,7 +116,7 @@ public class MapRenderer implements Disposable{ int idxDecal = (wx % chunksize) + (wy % chunksize) * chunksize + chunksize * chunksize; if(bw != 0 && (wall.synthetic() || wall == Blocks.part)){ - region = wall.icon(Icon.full) == Core.atlas.find("____") ? Core.atlas.find("clear") : wall.icon(Icon.full); + region = !Core.atlas.isFound(wall.editorIcon()) ? Core.atlas.find("clear-editor") : wall.editorIcon(); if(wall.rotate){ mesh.draw(idxWall, region, @@ -127,22 +129,26 @@ public class MapRenderer implements Disposable{ region.getWidth() * Draw.scl, region.getHeight() * Draw.scl); } }else{ - region = floor.icon(Icon.full); + region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length-1)]; mesh.draw(idxWall, region, wx * tilesize, wy * tilesize, 8, 8); } + float offsetX = -(wall.size/3)*tilesize, offsetY = -(wall.size/3) * tilesize; + if(wall.update || wall.destructible){ mesh.setColor(team.color); - region = Core.atlas.find("block-border"); + region = Core.atlas.find("block-border-editor"); }else if(!wall.synthetic() && bw != 0){ - region = wall.icon(Icon.full) == Core.atlas.find("____") ? Core.atlas.find("clear") : wall.icon(Icon.full); + region = !Core.atlas.isFound(wall.editorIcon()) ? Core.atlas.find("clear-editor") : wall.editorIcon(); + offsetX = tilesize/2f - region.getWidth()/2f * Draw.scl; + offsetY = tilesize/2f - region.getHeight()/2f * Draw.scl; }else{ - region = Core.atlas.find("clear"); + region = Core.atlas.find("clear-editor"); } mesh.draw(idxDecal, region, - wx * tilesize - (wall.size/3) * tilesize, wy * tilesize - (wall.size/3) * tilesize, + wx * tilesize + offsetX, wy * tilesize + offsetY, region.getWidth() * Draw.scl, region.getHeight() * Draw.scl); mesh.setColor(Color.WHITE); } diff --git a/core/src/io/anuke/mindustry/editor/MapResizeDialog.java b/core/src/io/anuke/mindustry/editor/MapResizeDialog.java index 9aa263b42a..b0a9ec2cfb 100644 --- a/core/src/io/anuke/mindustry/editor/MapResizeDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapResizeDialog.java @@ -1,14 +1,13 @@ package io.anuke.mindustry.editor; -import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.arc.function.BiConsumer; -import io.anuke.arc.scene.ui.ButtonGroup; -import io.anuke.arc.scene.ui.TextButton; -import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.math.Mathf; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.maps.MapTileData; +import io.anuke.mindustry.ui.dialogs.FloatingDialog; public class MapResizeDialog extends FloatingDialog{ - int[] validMapSizes = {200, 300, 400, 500}; + private static final int minSize = 50, maxSize = 500, increment = 50; int width, height; public MapResizeDialog(MapEditor editor, BiConsumer cons){ @@ -22,28 +21,23 @@ public class MapResizeDialog extends FloatingDialog{ Table table = new Table(); for(boolean w : Mathf.booleans){ - int curr = w ? data.width() : data.height(); - int idx = 0; - for(int i = 0; i < validMapSizes.length; i++){ - if(validMapSizes[i] == curr) idx = i; - } - table.add(w ? "$width" : "$height").padRight(8f); - ButtonGroup group = new ButtonGroup<>(); - for(int i = 0; i < validMapSizes.length; i++){ - int size = validMapSizes[i]; - TextButton button = new TextButton(size + "", "toggle"); - button.clicked(() -> { - if(w) - width = size; - else - height = size; - }); - group.add(button); - if(i == idx) button.setChecked(true); - table.add(button).size(100f, 54f).pad(2f); - } + table.defaults().height(60f).padTop(8); + table.addButton("<", () -> { + if(w) + width = move(width, -1); + else + height = move(height, -1); + }).size(60f); + table.table("button", t -> t.label(() -> (w ? width : height) + "")).width(200); + + table.addButton(">", () -> { + if(w) + width = move(width, 1); + else + height = move(height, 1); + }).size(60f); table.row(); } cont.row(); @@ -57,6 +51,9 @@ public class MapResizeDialog extends FloatingDialog{ cons.accept(width, height); hide(); }); + } + static int move(int value, int direction){ + return Mathf.clamp((value / increment + direction) * increment, minSize, maxSize); } } diff --git a/core/src/io/anuke/mindustry/editor/MapView.java b/core/src/io/anuke/mindustry/editor/MapView.java index 1b6972e717..222694d7a5 100644 --- a/core/src/io/anuke/mindustry/editor/MapView.java +++ b/core/src/io/anuke/mindustry/editor/MapView.java @@ -19,7 +19,6 @@ import io.anuke.arc.scene.event.Touchable; import io.anuke.arc.scene.ui.TextField; import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.util.Tmp; -import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.ui.GridImage; import io.anuke.mindustry.world.Pos; @@ -59,6 +58,8 @@ public class MapView extends Element implements GestureListener{ Core.input.getInputProcessors().insert(0, new GestureDetector(20, 0.5f, 2, 0.15f, this)); touchable(Touchable.enabled); + Point2 firstTouch = new Point2(); + addListener(new InputListener(){ @Override @@ -68,7 +69,6 @@ public class MapView extends Element implements GestureListener{ return false; } - @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){ if(pointer != 0){ @@ -102,6 +102,7 @@ public class MapView extends Element implements GestureListener{ startx = p.x; starty = p.y; tool.touched(editor, p.x, p.y); + firstTouch.set(p); if(tool.edit){ updated = true; @@ -123,10 +124,18 @@ public class MapView extends Element implements GestureListener{ Point2 p = project(x, y); if(tool == EditorTool.line){ + if(Core.input.keyDown(KeyCode.TAB)){ + if(Math.abs(p.x - firstTouch.x) > Math.abs(p.y - firstTouch.y)){ + p.y = firstTouch.y; + }else{ + p.x = firstTouch.x; + } + } + ui.editor.resetSaved(); Array points = br.line(startx, starty, p.x, p.y); for(Point2 point : points){ - editor.draw(point.x, point.y); + editor.draw(point.x, point.y, EditorTool.isPaint()); } updated = true; } @@ -138,7 +147,7 @@ public class MapView extends Element implements GestureListener{ op = null; } - if(lastTool != null){ + if(button == KeyCode.MOUSE_MIDDLE && lastTool != null){ tool = lastTool; lastTool = null; } @@ -147,6 +156,7 @@ public class MapView extends Element implements GestureListener{ @Override public void touchDragged(InputEvent event, float x, float y, int pointer){ + mousex = x; mousey = y; @@ -160,8 +170,19 @@ public class MapView extends Element implements GestureListener{ } updated = true; } - lastx = p.x; - lasty = p.y; + + if(tool == EditorTool.line && Core.input.keyDown(KeyCode.TAB)){ + if(Math.abs(p.x - firstTouch.x) > Math.abs(p.y - firstTouch.y)){ + lastx = p.x; + lasty = firstTouch.y; + }else{ + lastx = firstTouch.x; + lasty = p.y; + } + }else{ + lastx = p.x; + lasty = p.y; + } } }); } @@ -223,6 +244,16 @@ public class MapView extends Element implements GestureListener{ offsety -= ay * 15f / zoom; } + if(Core.input.keyTap(KeyCode.SHIFT_LEFT)){ + lastTool = tool; + tool = EditorTool.pick; + } + + if(Core.input.keyRelease(KeyCode.SHIFT_LEFT) && lastTool != null){ + tool = lastTool; + lastTool = null; + } + if(ui.editor.hasPane()) return; zoom += Core.input.axis(KeyCode.SCROLL) / 10f * zoom; @@ -274,7 +305,7 @@ public class MapView extends Element implements GestureListener{ return; } - Draw.color(Palette.remove); + Draw.color(Pal.remove); Lines.stroke(2f); Lines.rect(centerx - sclwidth / 2 - 1, centery - sclheight / 2 - 1, sclwidth + 2, sclheight + 2); editor.renderer().draw(centerx - sclwidth / 2, centery - sclheight / 2, sclwidth, sclheight); @@ -301,10 +332,10 @@ public class MapView extends Element implements GestureListener{ float scaling = zoom * Math.min(width, height) / world.width(); - Draw.color(Palette.accent); - Lines.stroke(Unit.dp.scl(1f * zoom)); + Draw.color(Pal.accent); + Lines.stroke(Unit.dp.scl(2f)); - if(!editor.getDrawBlock().isMultiblock() || tool == EditorTool.eraser){ + if((!editor.getDrawBlock().isMultiblock() || tool == EditorTool.eraser) && tool != EditorTool.fill){ if(tool == EditorTool.line && drawing){ Vector2 v1 = unproject(startx, starty).add(x, y); float sx = v1.x, sy = v1.y; @@ -314,7 +345,7 @@ public class MapView extends Element implements GestureListener{ Lines.poly(brushPolygons[index], v2.x, v2.y, scaling); } - if(tool.edit && (!mobile || drawing)){ + if((tool.edit || (tool == EditorTool.line && !drawing)) && (!mobile || drawing)){ Point2 p = project(mousex, mousey); Vector2 v = unproject(p.x, p.y).add(x, y); Lines.poly(brushPolygons[index], v.x, v.y, scaling); @@ -331,7 +362,7 @@ public class MapView extends Element implements GestureListener{ } } - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.stroke(Unit.dp.scl(3f)); Lines.rect(x, y, width, height); Draw.reset(); diff --git a/core/src/io/anuke/mindustry/entities/Damage.java b/core/src/io/anuke/mindustry/entities/Damage.java index e8b51dbf35..093c3f7b14 100644 --- a/core/src/io/anuke/mindustry/entities/Damage.java +++ b/core/src/io/anuke/mindustry/entities/Damage.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.entities; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.function.Consumer; import io.anuke.arc.function.Predicate; import io.anuke.arc.graphics.Color; @@ -15,9 +14,10 @@ import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.effect.Fire; import io.anuke.mindustry.entities.effect.Lightning; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.world.Tile; import static io.anuke.mindustry.Vars.*; @@ -32,7 +32,7 @@ public class Damage{ public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, Color color){ for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i++){ int branches = 5 + Mathf.clamp((int) (power / 30), 1, 20); - Time.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.none, Palette.power, 3, + Time.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.none, Pal.power, 3, x, y, Mathf.random(360f), branches + Mathf.range(2))); } @@ -60,7 +60,7 @@ public class Damage{ float shake = Math.min(explosiveness / 4f + 3f, 9f); Effects.shake(shake, shake, x, y); - Effects.effect(Fx.blockExplosion, x, y); + Effects.effect(Fx.dynamicExplosion, x, y, radius/8f); } public static void createIncend(float x, float y, float range, int amount){ @@ -109,7 +109,7 @@ public class Damage{ rect.width += expand * 2; rect.height += expand * 2; - Consumer cons = e -> { + Consumer cons = e -> { e.hitbox(hitrect); Rectangle other = hitrect; other.y -= expand; @@ -130,8 +130,8 @@ public class Damage{ } /**Damages all entities and blocks in a radius that are enemies of the team.*/ - public static void damageUnits(Team team, float x, float y, float size, float damage, Predicate predicate, Consumer acceptor){ - Consumer cons = entity -> { + public static void damageUnits(Team team, float x, float y, float size, float damage, Predicate predicate, Consumer acceptor){ + Consumer cons = entity -> { if(!predicate.test(entity)) return; entity.hitbox(hitrect); @@ -158,14 +158,14 @@ public class Damage{ /**Damages all entities and blocks in a radius that are enemies of the team.*/ public static void damage(Team team, float x, float y, float radius, float damage){ Consumer cons = entity -> { - if(entity.team == team || entity.dst(x, y) > radius){ + if(entity.getTeam() == team || entity.dst(x, y) > radius){ return; } float amount = calculateDamage(x, y, entity.x, entity.y, radius, damage); entity.damage(amount); //TODO better velocity displacement float dst = tr.set(entity.x - x, entity.y - y).len(); - entity.velocity().add(tr.setLength((1f - dst / radius) * 2f)); + entity.velocity().add(tr.setLength((1f - dst / radius) * 2f / entity.mass())); }; rect.setSize(radius * 2).setCenter(x, y); diff --git a/core/src/io/anuke/mindustry/entities/Effects.java b/core/src/io/anuke/mindustry/entities/Effects.java new file mode 100644 index 0000000000..576d5cc56e --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/Effects.java @@ -0,0 +1,166 @@ +package io.anuke.mindustry.entities; + +import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Position; +import io.anuke.arc.util.pooling.Pools; +import io.anuke.mindustry.entities.impl.EffectEntity; +import io.anuke.mindustry.entities.traits.ScaleTrait; + +public class Effects{ + private static final EffectContainer container = new EffectContainer(); + private static Array effects = new Array<>(); + private static ScreenshakeProvider shakeProvider; + private static float shakeFalloff = 1000f; + private static EffectProvider provider = (effect, color, x, y, rotation, data) -> { + EffectEntity entity = Pools.obtain(EffectEntity.class, EffectEntity::new); + entity.effect = effect; + entity.color = color; + entity.rotation = rotation; + entity.data = data; + entity.set(x, y); + entity.add(); + }; + + public static void setEffectProvider(EffectProvider prov){ + provider = prov; + } + + public static void setScreenShakeProvider(ScreenshakeProvider provider){ + shakeProvider = provider; + } + + public static void renderEffect(int id, Effect render, Color color, float life, float rotation, float x, float y, Object data){ + container.set(id, color, life, render.lifetime, rotation, x, y, data); + render.draw.render(container); + } + + public static Effect getEffect(int id){ + if(id >= effects.size || id < 0) + throw new IllegalArgumentException("The effect with ID \"" + id + "\" does not exist!"); + return effects.get(id); + } + + public static Array all(){ + return effects; + } + + public static void effect(Effect effect, float x, float y, float rotation){ + provider.createEffect(effect, Color.WHITE, x, y, rotation, null); + } + + public static void effect(Effect effect, float x, float y){ + effect(effect, x, y, 0); + } + + public static void effect(Effect effect, Color color, float x, float y){ + provider.createEffect(effect, color, x, y, 0f, null); + } + + public static void effect(Effect effect, Position loc){ + provider.createEffect(effect, Color.WHITE, loc.getX(), loc.getY(), 0f, null); + } + + public static void effect(Effect effect, Color color, float x, float y, float rotation){ + provider.createEffect(effect, color, x, y, rotation, null); + } + + public static void effect(Effect effect, Color color, float x, float y, float rotation, Object data){ + provider.createEffect(effect, color, x, y, rotation, data); + } + + public static void effect(Effect effect, float x, float y, float rotation, Object data){ + provider.createEffect(effect, Color.WHITE, x, y, rotation, data); + } + + /** Default value is 1000. Higher numbers mean more powerful shake (less falloff). */ + public static void setShakeFalloff(float falloff){ + shakeFalloff = falloff; + } + + private static void shake(float intensity, float duration){ + if(shakeProvider == null) throw new RuntimeException("Screenshake provider is null! Set it first."); + shakeProvider.accept(intensity, duration); + } + + public static void shake(float intensity, float duration, float x, float y){ + if(Core.camera == null) return; + + float distance = Core.camera.position.dst(x, y); + if(distance < 1) distance = 1; + + shake(Mathf.clamp(1f / (distance * distance / shakeFalloff)) * intensity, duration); + } + + public static void shake(float intensity, float duration, Position loc){ + shake(intensity, duration, loc.getX(), loc.getY()); + } + + public interface ScreenshakeProvider{ + void accept(float intensity, float duration); + } + + public static class Effect{ + private static int lastid = 0; + public final int id; + public final EffectRenderer draw; + public final float lifetime; + /** Clip size. */ + public float size; + + public Effect(float life, float clipsize, EffectRenderer draw){ + this.id = lastid++; + this.lifetime = life; + this.draw = draw; + this.size = clipsize; + effects.add(this); + } + + public Effect(float life, EffectRenderer draw){ + this(life, 28f, draw); + } + } + + public static class EffectContainer implements ScaleTrait{ + public float x, y, time, lifetime, rotation; + public Color color; + public int id; + public Object data; + private EffectContainer innerContainer; + + public void set(int id, Color color, float life, float lifetime, float rotation, float x, float y, Object data){ + this.x = x; + this.y = y; + this.color = color; + this.time = life; + this.lifetime = lifetime; + this.id = id; + this.rotation = rotation; + this.data = data; + } + + public void scaled(float lifetime, Consumer cons){ + if(innerContainer == null) innerContainer = new EffectContainer(); + if(time <= lifetime){ + innerContainer.set(id, color, time, lifetime, rotation, x, y, data); + cons.accept(innerContainer); + } + } + + @Override + public float fin(){ + return time / lifetime; + } + } + + public static interface EffectProvider{ + void createEffect(Effect effect, Color color, float x, float y, float rotation, Object data); + } + + public static interface EffectRenderer{ + void render(EffectContainer effect); + } +} diff --git a/core/src/io/anuke/mindustry/entities/Entities.java b/core/src/io/anuke/mindustry/entities/Entities.java new file mode 100755 index 0000000000..94a2baa629 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/Entities.java @@ -0,0 +1,66 @@ +package io.anuke.mindustry.entities; + +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.IntMap; +import io.anuke.mindustry.entities.traits.Entity; + +public class Entities{ + public static final int maxLeafObjects = 5; + private static final EntityGroup defaultGroup; + private static final Array> groupArray = new Array<>(); + private static final IntMap> groups = new IntMap<>(); + + static{ + defaultGroup = addGroup(Entity.class); + } + + public static void clear(){ + for(EntityGroup group : groupArray){ + group.clear(); + } + } + + public static Iterable all(){ + return defaultGroup.all(); + } + + public static EntityGroup getGroup(int id){ + return groups.get(id); + } + + public static Iterable> getAllGroups(){ + return groups.values(); + } + + public static EntityGroup defaultGroup(){ + return defaultGroup; + } + + public static EntityGroup addGroup(Class type){ + return addGroup(type, true); + } + + public static EntityGroup addGroup(Class type, boolean useTree){ + EntityGroup group = new EntityGroup<>(type, useTree); + groups.put(group.getID(), group); + groupArray.add(group); + return group; + } + + public static void update(){ + update(defaultGroup()); + EntityQuery.collideGroups(defaultGroup(), defaultGroup()); + } + + public static void update(EntityGroup group){ + group.updateEvents(); + + if(group.useTree()){ + EntityQuery.collisions().updatePhysics(group); + } + + for(Entity e : group.all()){ + e.update(); + } + } +} diff --git a/core/src/io/anuke/mindustry/entities/EntityCollisions.java b/core/src/io/anuke/mindustry/entities/EntityCollisions.java new file mode 100644 index 0000000000..62e5e214d6 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/EntityCollisions.java @@ -0,0 +1,261 @@ +package io.anuke.mindustry.entities; + +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.IntSet; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Geometry; +import io.anuke.arc.math.geom.QuadTree; +import io.anuke.arc.math.geom.Rectangle; +import io.anuke.arc.math.geom.Vector2; +import io.anuke.mindustry.entities.traits.Entity; +import io.anuke.mindustry.entities.traits.SolidTrait; + +public class EntityCollisions{ + //range for tile collision scanning + private static final int r = 2; + //move in 1-unit chunks + private static final float seg = 1f; + + //tile collisions + private float tilesize; + private Rectangle tmp = new Rectangle(); + private TileCollider collider; + private TileHitboxProvider hitboxProvider; + private Vector2 vector = new Vector2(); + private Vector2 l1 = new Vector2(); + private Rectangle r1 = new Rectangle(); + private Rectangle r2 = new Rectangle(); + + //entity collisions + private IntSet collided = new IntSet(); + private Array arrOut = new Array<>(); + + public void setCollider(float tilesize, TileCollider collider, TileHitboxProvider hitbox){ + this.tilesize = tilesize; + this.collider = collider; + this.hitboxProvider = hitbox; + } + + public void setCollider(float tilesize, TileCollider collider){ + setCollider(tilesize, collider, (x, y, out) -> out.setSize(tilesize).setCenter(x * tilesize, y * tilesize)); + } + + public void move(SolidTrait entity, float deltax, float deltay){ + + boolean movedx = false; + + while(Math.abs(deltax) > 0 || !movedx){ + movedx = true; + moveInternal(entity, Math.min(Math.abs(deltax), seg) * Mathf.sign(deltax), 0, true); + + if(Math.abs(deltax) >= seg){ + deltax -= seg * Mathf.sign(deltax); + }else{ + deltax = 0f; + } + } + + boolean movedy = false; + + while(Math.abs(deltay) > 0 || !movedy){ + movedy = true; + moveInternal(entity, 0, Math.min(Math.abs(deltay), seg) * Mathf.sign(deltay), false); + + if(Math.abs(deltay) >= seg){ + deltay -= seg * Mathf.sign(deltay); + }else{ + deltay = 0f; + } + } + } + + public void moveInternal(SolidTrait entity, float deltax, float deltay, boolean x){ + if(collider == null) + throw new IllegalArgumentException("No tile collider specified! Call setCollider() first."); + + Rectangle rect = r1; + entity.hitboxTile(rect); + entity.hitboxTile(r2); + rect.x += deltax; + rect.y += deltay; + + int tilex = Math.round((rect.x + rect.width / 2) / tilesize), tiley = Math.round((rect.y + rect.height / 2) / tilesize); + + for(int dx = -r; dx <= r; dx++){ + for(int dy = -r; dy <= r; dy++){ + int wx = dx + tilex, wy = dy + tiley; + if(collider.solid(wx, wy) && entity.collidesGrid(wx, wy)){ + + hitboxProvider.getHitbox(wx, wy, tmp); + + if(tmp.overlaps(rect)){ + Vector2 v = Geometry.overlap(rect, tmp, x); + rect.x += v.x; + rect.y += v.y; + } + } + } + } + + entity.setX(entity.getX() + rect.x - r2.x); + entity.setY(entity.getY() + rect.y - r2.y); + } + + public boolean overlapsTile(Rectangle rect){ + if(collider == null) + throw new IllegalArgumentException("No tile collider specified! Call setCollider() first."); + + rect.getCenter(vector); + int r = 1; + + //assumes tiles are centered + int tilex = Math.round(vector.x / tilesize); + int tiley = Math.round(vector.y / tilesize); + + for(int dx = -r; dx <= r; dx++){ + for(int dy = -r; dy <= r; dy++){ + int wx = dx + tilex, wy = dy + tiley; + if(collider.solid(wx, wy)){ + hitboxProvider.getHitbox(wx, wy, r2); + + if(r2.overlaps(rect)){ + return true; + } + } + } + } + return false; + } + + public void updatePhysics(EntityGroup group){ + collided.clear(); + + QuadTree tree = group.tree(); + tree.clear(); + + for(Entity entity : group.all()){ + if(entity instanceof SolidTrait){ + SolidTrait s = (SolidTrait) entity; + s.lastPosition().set(s.getX(), s.getY()); + tree.insert(s); + } + } + } + + private void checkCollide(Entity entity, Entity other){ + + SolidTrait a = (SolidTrait) entity; + SolidTrait b = (SolidTrait) other; + + a.hitbox(this.r1); + b.hitbox(this.r2); + + r1.x += (a.lastPosition().x - a.getX()); + r1.y += (a.lastPosition().y - a.getY()); + r2.x += (b.lastPosition().x - b.getX()); + r2.y += (b.lastPosition().y - b.getY()); + + float vax = a.getX() - a.lastPosition().x; + float vay = a.getY() - a.lastPosition().y; + float vbx = b.getX() - b.lastPosition().x; + float vby = b.getY() - b.lastPosition().y; + + if(a != b && a.collides(b) && b.collides(a)){ + l1.set(a.getX(), a.getY()); + boolean collide = r1.overlaps(r2) || collide(r1.x, r1.y, r1.width, r1.height, vax, vay, + r2.x, r2.y, r2.width, r2.height, vbx, vby, l1); + if(collide){ + a.collision(b, l1.x, l1.y); + b.collision(a, l1.x, l1.y); + } + } + } + + private boolean collide(float x1, float y1, float w1, float h1, float vx1, float vy1, + float x2, float y2, float w2, float h2, float vx2, float vy2, Vector2 out){ + float px = vx1, py = vy1; + + vx1 -= vx2; + vy1 -= vy2; + + float xInvEntry, yInvEntry; + float xInvExit, yInvExit; + + if(vx1 > 0.0f){ + xInvEntry = x2 - (x1 + w1); + xInvExit = (x2 + w2) - x1; + }else{ + xInvEntry = (x2 + w2) - x1; + xInvExit = x2 - (x1 + w1); + } + + if(vy1 > 0.0f){ + yInvEntry = y2 - (y1 + h1); + yInvExit = (y2 + h2) - y1; + }else{ + yInvEntry = (y2 + h2) - y1; + yInvExit = y2 - (y1 + h1); + } + + float xEntry, yEntry; + float xExit, yExit; + + xEntry = xInvEntry / vx1; + xExit = xInvExit / vx1; + + yEntry = yInvEntry / vy1; + yExit = yInvExit / vy1; + + float entryTime = Math.max(xEntry, yEntry); + float exitTime = Math.min(xExit, yExit); + + if(entryTime > exitTime || xExit < 0.0f || yExit < 0.0f || xEntry > 1.0f || yEntry > 1.0f){ + return false; + }else{ + float dx = x1 + w1 / 2f + px * entryTime; + float dy = y1 + h1 / 2f + py * entryTime; + + out.set(dx, dy); + + return true; + } + } + + public void collideGroups(EntityGroup groupa, EntityGroup groupb){ + collided.clear(); + + for(Entity entity : groupa.all()){ + if(!(entity instanceof SolidTrait) || collided.contains(entity.getID())) + continue; + + SolidTrait solid = (SolidTrait) entity; + + solid.hitbox(r1); + r1.x += (solid.lastPosition().x - solid.getX()); + r1.y += (solid.lastPosition().y - solid.getY()); + + solid.hitbox(r2); + r2.merge(r1); + + arrOut.clear(); + groupb.tree().getIntersect(arrOut, r2); + + for(SolidTrait sc : arrOut){ + sc.hitbox(r1); + if(r2.overlaps(r1) && !collided.contains(sc.getID())){ + checkCollide(entity, sc); + } + } + + collided.add(entity.getID()); + } + } + + public interface TileCollider{ + boolean solid(int x, int y); + } + + public interface TileHitboxProvider{ + void getHitbox(int x, int y, Rectangle out); + } +} diff --git a/core/src/io/anuke/mindustry/entities/EntityDraw.java b/core/src/io/anuke/mindustry/entities/EntityDraw.java new file mode 100644 index 0000000000..e0a95627c2 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/EntityDraw.java @@ -0,0 +1,56 @@ +package io.anuke.mindustry.entities; + +import io.anuke.arc.Core; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.function.Predicate; +import io.anuke.arc.graphics.Camera; +import io.anuke.arc.math.geom.Rectangle; +import io.anuke.mindustry.entities.traits.DrawTrait; + +public class EntityDraw{ + private static final Rectangle viewport = new Rectangle(); + private static final Rectangle rect = new Rectangle(); + private static boolean clip = true; + private static int count = 0; + + public static void setClip(boolean clip){ + EntityDraw.clip = clip; + } + + public static int countInBounds(EntityGroup group){ + count = 0; + drawWith(group, e -> true, e -> count++); + return count; + } + + public static void draw(){ + draw(Entities.defaultGroup()); + } + + public static void draw(EntityGroup group){ + draw(group, e -> true); + } + + public static void draw(EntityGroup group, Predicate toDraw){ + drawWith(group, toDraw, DrawTrait::draw); + } + + @SuppressWarnings("unchecked") + public static void drawWith(EntityGroup group, Predicate toDraw, Consumer cons){ + if(clip){ + Camera cam = Core.camera; + viewport.set(cam.position.x - cam.width / 2, cam.position.y - cam.height / 2, cam.width, cam.height); + } + + group.forEach(e -> { + if(!(e instanceof DrawTrait)) return; + T t = (T) e; + + if(!toDraw.test(t) || !e.isAdded()) return; + + if(!clip || rect.setSize(((DrawTrait) e).drawSize()).setCenter(e.getX(), e.getY()).overlaps(viewport)){ + cons.accept(t); + } + }); + } +} diff --git a/core/src/io/anuke/mindustry/entities/EntityGroup.java b/core/src/io/anuke/mindustry/entities/EntityGroup.java new file mode 100644 index 0000000000..2050535843 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/EntityGroup.java @@ -0,0 +1,194 @@ +package io.anuke.mindustry.entities; + +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.IntMap; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.function.Predicate; +import io.anuke.arc.math.geom.QuadTree; +import io.anuke.arc.math.geom.Rectangle; +import io.anuke.mindustry.entities.traits.Entity; + +public class EntityGroup{ + private static int lastid; + private final boolean useTree; + private final int id; + private final Class type; + private final Array entityArray = new Array<>(false, 16); + private final Array entitiesToRemove = new Array<>(false, 16); + private final Array entitiesToAdd = new Array<>(false, 16); + private IntMap map; + private QuadTree tree; + private Consumer removeListener; + private Consumer addListener; + + public EntityGroup(Class type, boolean useTree){ + this.useTree = useTree; + this.id = lastid++; + this.type = type; + } + + public boolean useTree(){ + return useTree; + } + + public void setRemoveListener(Consumer removeListener){ + this.removeListener = removeListener; + } + + public void setAddListener(Consumer addListener){ + this.addListener = addListener; + } + + public EntityGroup enableMapping(){ + map = new IntMap<>(); + return this; + } + + public boolean mappingEnabled(){ + return map != null; + } + + public Class getType(){ + return type; + } + + public int getID(){ + return id; + } + + public void updateEvents(){ + + for(T e : entitiesToAdd){ + if(e == null) + continue; + entityArray.add(e); + e.added(); + + if(map != null){ + map.put(e.getID(), e); + } + } + + entitiesToAdd.clear(); + + for(T e : entitiesToRemove){ + entityArray.removeValue(e, true); + if(map != null){ + map.remove(e.getID()); + } + e.removed(); + } + + entitiesToRemove.clear(); + } + + public T getByID(int id){ + if(map == null) throw new RuntimeException("Mapping is not enabled for group " + id + "!"); + return map.get(id); + } + + public void removeByID(int id){ + if(map == null) throw new RuntimeException("Mapping is not enabled for group " + id + "!"); + T t = map.get(id); + if(t != null){ //remove if present in map already + remove(t); + }else{ //maybe it's being queued? + for(T check : entitiesToAdd){ + if(check.getID() == id){ //if it is indeed queued, remove it + entitiesToAdd.removeValue(check, true); + if(removeListener != null){ + removeListener.accept(check); + } + break; + } + } + } + } + + public QuadTree tree(){ + return tree; + } + + public void setTree(float x, float y, float w, float h){ + tree = new QuadTree<>(Entities.maxLeafObjects, new Rectangle(x, y, w, h)); + } + + public boolean isEmpty(){ + return entityArray.size == 0; + } + + public int size(){ + return entityArray.size; + } + + public int count(Predicate pred){ + int count = 0; + for(int i = 0; i < entityArray.size; i++){ + if(pred.test(entityArray.get(i))) count++; + } + return count; + } + + public void add(T type){ + if(type == null) throw new RuntimeException("Cannot add a null entity!"); + if(type.getGroup() != null) return; + type.setGroup(this); + entitiesToAdd.add(type); + + if(mappingEnabled()){ + map.put(type.getID(), type); + } + + if(addListener != null){ + addListener.accept(type); + } + } + + public void remove(T type){ + if(type == null) throw new RuntimeException("Cannot remove a null entity!"); + type.setGroup(null); + entitiesToRemove.add(type); + + if(removeListener != null){ + removeListener.accept(type); + } + } + + public void clear(){ + for(T entity : entityArray) + entity.setGroup(null); + + for(T entity : entitiesToAdd) + entity.setGroup(null); + + for(T entity : entitiesToRemove) + entity.setGroup(null); + + entitiesToAdd.clear(); + entitiesToRemove.clear(); + entityArray.clear(); + if(map != null) + map.clear(); + } + + public T find(Predicate pred){ + + for(int i = 0; i < entityArray.size; i++){ + if(pred.test(entityArray.get(i))) return entityArray.get(i); + } + + return null; + } + + /**Returns the logic-only array for iteration.*/ + public Array all(){ + return entityArray; + } + + public void forEach(Consumer cons){ + + for(T t : entityArray){ + cons.accept(t); + } + } +} diff --git a/core/src/io/anuke/mindustry/entities/EntityQuery.java b/core/src/io/anuke/mindustry/entities/EntityQuery.java new file mode 100644 index 0000000000..8e25527400 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/EntityQuery.java @@ -0,0 +1,95 @@ +package io.anuke.mindustry.entities; + +import io.anuke.arc.collection.Array; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.function.Predicate; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Rectangle; +import io.anuke.mindustry.entities.traits.Entity; +import io.anuke.mindustry.entities.traits.SolidTrait; + +import static io.anuke.mindustry.entities.Entities.defaultGroup; + +public class EntityQuery{ + private static final EntityCollisions collisions = new EntityCollisions(); + private static final Array array = new Array<>(); + private static final Rectangle r1 = new Rectangle(); + + public static EntityCollisions collisions(){ + return collisions; + } + + public static void init(float x, float y, float w, float h){ + + for(EntityGroup group : Entities.getAllGroups()){ + if(group.useTree()){ + group.setTree(x, y, w, h); + } + } + } + + public static void init(){ + init(0, 0, 0, 0); + } + + public static void resizeTree(float x, float y, float w, float h){ + init(x, y, w, h); + } + + public static void getNearby(EntityGroup group, Rectangle rect, Consumer out){ + + if(!group.useTree()) + throw new RuntimeException("This group does not support quadtrees! Enable quadtrees when creating it."); + group.tree().getIntersect(out, rect); + } + + public static Array getNearby(EntityGroup group, Rectangle rect){ + + array.clear(); + if(!group.useTree()) + throw new RuntimeException("This group does not support quadtrees! Enable quadtrees when creating it."); + group.tree().getIntersect(array, rect); + return array; + } + + public static void getNearby(float x, float y, float size, Consumer out){ + getNearby(defaultGroup(), r1.setSize(size).setCenter(x, y), out); + } + + public static void getNearby(EntityGroup group, float x, float y, float size, Consumer out){ + getNearby(group, r1.setSize(size).setCenter(x, y), out); + } + + public static Array getNearby(float x, float y, float size){ + return getNearby(defaultGroup(), r1.setSize(size).setCenter(x, y)); + } + + public static Array getNearby(EntityGroup group, float x, float y, float size){ + return getNearby(group, r1.setSize(size).setCenter(x, y)); + } + + public static T getClosest(EntityGroup group, float x, float y, float range, Predicate pred){ + + T closest = null; + float cdist = 0f; + Array entities = getNearby(group, x, y, range * 2f); + for(int i = 0; i < entities.size; i++){ + T e = (T) entities.get(i); + if(!pred.test(e)) + continue; + + float dist = Mathf.dst(e.getX(), e.getY(), x, y); + if(dist < range) + if(closest == null || dist < cdist){ + closest = e; + cdist = dist; + } + } + + return closest; + } + + public static void collideGroups(EntityGroup groupa, EntityGroup groupb){ + collisions().collideGroups(groupa, groupb); + } +} diff --git a/core/src/io/anuke/mindustry/entities/UnitInventory.java b/core/src/io/anuke/mindustry/entities/UnitInventory.java deleted file mode 100644 index d4d27d3a3d..0000000000 --- a/core/src/io/anuke/mindustry/entities/UnitInventory.java +++ /dev/null @@ -1,88 +0,0 @@ -package io.anuke.mindustry.entities; - -import io.anuke.mindustry.entities.traits.Saveable; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import static io.anuke.mindustry.Vars.content; - -public class UnitInventory implements Saveable{ - private final Unit unit; - private ItemStack item = new ItemStack(content.item(0), 0); - - public UnitInventory(Unit unit){ - this.unit = unit; - } - - public boolean isFull(){ - return item != null && item.amount >= unit.getItemCapacity(); - } - - @Override - public void writeSave(DataOutput stream) throws IOException{ - stream.writeByte(item.amount); - stream.writeByte(item.item.id); - } - - @Override - public void readSave(DataInput stream) throws IOException{ - int iamount = stream.readUnsignedByte(); - byte iid = stream.readByte(); - - item.item = content.item(iid); - item.amount = iamount; - } - - public void clear(){ - item.amount = 0; - } - - public int capacity(){ - return unit.getItemCapacity(); - } - - public boolean isEmpty(){ - return item.amount == 0; - } - - public int itemCapacityUsed(Item type){ - if(canAcceptItem(type)){ - return !hasItem() ? unit.getItemCapacity() : (unit.getItemCapacity() - item.amount); - }else{ - return unit.getItemCapacity(); - } - } - - public boolean canAcceptItem(Item type){ - return (!hasItem() && 1 <= unit.getItemCapacity()) || (item.item == type && unit.getItemCapacity() - item.amount > 0); - } - - public boolean canAcceptItem(Item type, int amount){ - return (!hasItem() && amount <= unit.getItemCapacity()) || (item.item == type && item.amount + amount <= unit.getItemCapacity()); - } - - public void clearItem(){ - item.amount = 0; - } - - public boolean hasItem(){ - return item.amount > 0; - } - - public boolean hasItem(Item i, int amount){ - return item.item == i && item.amount >= amount; - } - - public void addItem(Item item, int amount){ - getItem().amount = getItem().item == item ? getItem().amount + amount : amount; - getItem().item = item; - } - - public ItemStack getItem(){ - return item; - } -} diff --git a/core/src/io/anuke/mindustry/entities/Units.java b/core/src/io/anuke/mindustry/entities/Units.java index a265a9bcd0..7c72ad9492 100644 --- a/core/src/io/anuke/mindustry/entities/Units.java +++ b/core/src/io/anuke/mindustry/entities/Units.java @@ -1,15 +1,16 @@ package io.anuke.mindustry.entities; import io.anuke.arc.collection.EnumSet; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.EntityQuery; import io.anuke.arc.function.Consumer; import io.anuke.arc.function.Predicate; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Rectangle; import io.anuke.mindustry.entities.traits.TargetTrait; -import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -21,11 +22,10 @@ import static io.anuke.mindustry.Vars.*; */ public class Units{ private static Rectangle rect = new Rectangle(); - private static Rectangle rectGraphics = new Rectangle(); private static Rectangle hitrect = new Rectangle(); private static Unit result; private static float cdist; - private static boolean boolResult, boolResultGraphics; + private static boolean boolResult; /** * Validates a target. @@ -48,7 +48,7 @@ public class Units{ /**See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}*/ public static boolean invalidateTarget(TargetTrait target, Unit targeter){ - return invalidateTarget(target, targeter.team, targeter.x, targeter.y, targeter.getWeapon().getAmmo().range()); + return invalidateTarget(target, targeter.getTeam(), targeter.x, targeter.y, targeter.getWeapon().bullet.range()); } /**Returns whether there are any entities on this tile.*/ @@ -113,6 +113,8 @@ public class Units{ /**Returns the neareset enemy tile in a range.*/ public static TileEntity findEnemyTile(Team team, float x, float y, float range, Predicate pred){ + if(team == Team.none) return null; + for(Team enemy : state.teams.enemiesOf(team)){ TileEntity entity = world.indexer.findTile(enemy, x, y, range, pred); if(entity != null){ @@ -141,21 +143,28 @@ public class Units{ /**Returns the closest target enemy. First, units are checked, then tile entities.*/ public static TargetTrait getClosestTarget(Team team, float x, float y, float range){ - return getClosestTarget(team, x, y, range, u -> !u.isDead() && u.isAdded()); + return getClosestTarget(team, x, y, range, Unit::isValid); } /**Returns the closest target enemy. First, units are checked, then tile entities.*/ public static TargetTrait getClosestTarget(Team team, float x, float y, float range, Predicate unitPred){ + return getClosestTarget(team, x, y, range, unitPred, t -> true); + } + + /**Returns the closest target enemy. First, units are checked, then tile entities.*/ + public static TargetTrait getClosestTarget(Team team, float x, float y, float range, Predicate unitPred, Predicate tilePred){ Unit unit = getClosestEnemy(team, x, y, range, unitPred); if(unit != null){ return unit; }else{ - return findEnemyTile(team, x, y, range, tile -> true); + return findEnemyTile(team, x, y, range, tilePred); } } /**Returns the closest enemy of this team. Filter by predicate.*/ public static Unit getClosestEnemy(Team team, float x, float y, float range, Predicate predicate){ + if(team == Team.none) return null; + result = null; cdist = 0f; @@ -210,7 +219,7 @@ public class Units{ //now check all players EntityQuery.getNearby(playerGroup, rect, player -> { - if(((Unit) player).team == team) cons.accept((Unit) player); + if(((Unit) player).getTeam() == team) cons.accept((Unit) player); }); } @@ -229,7 +238,7 @@ public class Units{ //now check all players EntityQuery.getNearby(playerGroup, rect, player -> { - if(((Unit) player).team == team && player.dst(x, y) <= radius){ + if(((Unit) player).getTeam() == team && player.dst(x, y) <= radius){ cons.accept((Unit) player); } }); @@ -262,7 +271,7 @@ public class Units{ //now check all enemy players EntityQuery.getNearby(playerGroup, rect, player -> { - if(targets.contains(((Player) player).team)){ + if(targets.contains(((Player) player).getTeam())){ cons.accept((Unit) player); } }); diff --git a/core/src/io/anuke/mindustry/entities/bullet/ArtilleryBulletType.java b/core/src/io/anuke/mindustry/entities/bullet/ArtilleryBulletType.java index ee5237a2c8..5c74a9f9f7 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/ArtilleryBulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/ArtilleryBulletType.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.entities.bullet; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.mindustry.content.Fx; diff --git a/core/src/io/anuke/mindustry/entities/bullet/BasicBulletType.java b/core/src/io/anuke/mindustry/entities/bullet/BasicBulletType.java index 6152de43fa..b1127b6581 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/BasicBulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/BasicBulletType.java @@ -1,22 +1,21 @@ package io.anuke.mindustry.entities.bullet; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; -import io.anuke.arc.util.Time; import io.anuke.mindustry.entities.Damage; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.effect.Lightning; import io.anuke.mindustry.entities.traits.TargetTrait; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; /**An extended BulletType for most ammo-based bullets shot from turrets and units.*/ public class BasicBulletType extends BulletType{ - public Color backColor = Palette.bulletYellowBack, frontColor = Palette.bulletYellow; + public Color backColor = Pal.bulletYellowBack, frontColor = Pal.bulletYellow; public float bulletWidth = 5f, bulletHeight = 7f; public float bulletShrink = 0.5f; public String bulletSprite; @@ -72,7 +71,7 @@ public class BasicBulletType extends BulletType{ if(homingPower > 0.0001f){ TargetTrait target = Units.getClosestTarget(b.getTeam(), b.x, b.y, homingRange); if(target != null){ - b.velocity().setAngle(Angles.moveToward(b.velocity().angle(), b.angleTo(target), homingPower * Time.delta())); + b.velocity().setAngle(Mathf.slerpDelta(b.velocity().angle(), b.angleTo(target), 0.08f)); } } } @@ -108,7 +107,7 @@ public class BasicBulletType extends BulletType{ } for (int i = 0; i < lightining; i++) { - Lightning.create(b.getTeam(), Palette.surge, damage, b.x, b.y, Mathf.random(360f), lightningLength); + Lightning.create(b.getTeam(), Pal.surge, damage, b.x, b.y, Mathf.random(360f), lightningLength); } } } diff --git a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java index a860cb4ef6..ae61553586 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java +++ b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java @@ -2,9 +2,6 @@ package io.anuke.mindustry.entities.bullet; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.impl.SolidEntity; -import io.anuke.arc.entities.trait.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; @@ -13,11 +10,11 @@ import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; import io.anuke.arc.util.pooling.Pool.Poolable; import io.anuke.arc.util.pooling.Pools; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.effect.Lightning; -import io.anuke.mindustry.entities.traits.AbsorbTrait; -import io.anuke.mindustry.entities.traits.SyncTrait; -import io.anuke.mindustry.entities.traits.TeamTrait; +import io.anuke.mindustry.entities.impl.SolidEntity; +import io.anuke.mindustry.entities.traits.*; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.Tile; @@ -89,11 +86,21 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool } /**Internal use only.*/ - @Remote(called = Loc.server) + @Remote(called = Loc.server, unreliable = true) public static void createBullet(BulletType type, float x, float y, float angle){ create(type, null, Team.none, x, y, angle); } + /**ok*/ + @Remote(called = Loc.server, unreliable = true) + public static void createBullet(BulletType type, Team team, float x, float y, float angle){ + create(type, null, team, x, y, angle); + } + + public Entity getOwner(){ + return owner; + } + public boolean collidesTiles(){ return type.collidesTiles; } diff --git a/core/src/io/anuke/mindustry/entities/bullet/BulletType.java b/core/src/io/anuke/mindustry/entities/bullet/BulletType.java index 59ef42b6d6..198adaaf37 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/BulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/BulletType.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.entities.bullet; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.content.StatusEffects; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.game.Content; @@ -66,7 +66,7 @@ public abstract class BulletType extends Content{ /**Returns maximum distance the bullet this bullet type has can travel.*/ public float range(){ - return speed * lifetime; + return speed * lifetime * (1f - drag); } public boolean collides(Bullet bullet, Tile tile){ diff --git a/core/src/io/anuke/mindustry/entities/bullet/LiquidBulletType.java b/core/src/io/anuke/mindustry/entities/bullet/LiquidBulletType.java index 8b1677360d..6b4c7d8bb9 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/LiquidBulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/LiquidBulletType.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.entities.bullet; -import io.anuke.arc.entities.Effects; +import io.anuke.mindustry.entities.Effects; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Fill; @@ -20,16 +20,22 @@ public class LiquidBulletType extends BulletType{ Liquid liquid; public LiquidBulletType(Liquid liquid){ - super(2.5f, 0); + super(2.8f, 0); this.liquid = liquid; - lifetime = 70f; + lifetime = 74f; status = liquid.effect; statusDuration = 90f; despawnEffect = Fx.none; hitEffect = Fx.hitLiquid; - drag = 0.01f; - knockback = 0.5f; + shootEffect = Fx.none; + drag = 0.009f; + knockback = 0.55f; + } + + @Override + public float range(){ + return speed * lifetime /2f; } @Override diff --git a/core/src/io/anuke/mindustry/entities/bullet/MassDriverBolt.java b/core/src/io/anuke/mindustry/entities/bullet/MassDriverBolt.java index a10421113a..237aa09a15 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/MassDriverBolt.java +++ b/core/src/io/anuke/mindustry/entities/bullet/MassDriverBolt.java @@ -1,12 +1,12 @@ package io.anuke.mindustry.entities.bullet; -import io.anuke.arc.entities.Effects; +import io.anuke.mindustry.entities.Effects; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.world.blocks.distribution.MassDriver.DriverBulletData; import static io.anuke.mindustry.Vars.content; @@ -26,10 +26,10 @@ public class MassDriverBolt extends BulletType{ public void draw(Bullet b){ float w = 11f, h = 13f; - Draw.color(Palette.bulletYellowBack); + Draw.color(Pal.bulletYellowBack); Draw.rect("shell-back", b.x, b.y, w, h, b.rot() + 90); - Draw.color(Palette.bulletYellow); + Draw.color(Pal.bulletYellow); Draw.rect("shell", b.x, b.y, w, h, b.rot() + 90); Draw.reset(); diff --git a/core/src/io/anuke/mindustry/entities/bullet/MissileBulletType.java b/core/src/io/anuke/mindustry/entities/bullet/MissileBulletType.java index 6200666f1f..351078866d 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/MissileBulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/MissileBulletType.java @@ -2,21 +2,21 @@ package io.anuke.mindustry.entities.bullet; import io.anuke.arc.graphics.Color; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.arc.entities.Effects; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.entities.Effects; import io.anuke.arc.util.Time; import io.anuke.arc.math.Mathf; public class MissileBulletType extends BasicBulletType{ - protected Color trailColor = Palette.missileYellowBack; + protected Color trailColor = Pal.missileYellowBack; protected float weaveScale = 0f; protected float weaveMag = -1f; public MissileBulletType(float speed, float damage, String bulletSprite){ super(speed, damage, bulletSprite); - backColor = Palette.missileYellowBack; - frontColor = Palette.missileYellow; + backColor = Pal.missileYellowBack; + frontColor = Pal.missileYellow; homingPower = 7f; } diff --git a/core/src/io/anuke/mindustry/entities/effect/Decal.java b/core/src/io/anuke/mindustry/entities/effect/Decal.java index 9bcaf7a2c3..1cb773a3cc 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Decal.java +++ b/core/src/io/anuke/mindustry/entities/effect/Decal.java @@ -2,9 +2,9 @@ package io.anuke.mindustry.entities.effect; import io.anuke.arc.graphics.Color; import io.anuke.mindustry.entities.traits.BelowLiquidTrait; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.impl.TimedEntity; -import io.anuke.arc.entities.trait.DrawTrait; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.impl.TimedEntity; +import io.anuke.mindustry.entities.traits.DrawTrait; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.math.Mathf; diff --git a/core/src/io/anuke/mindustry/entities/effect/Fire.java b/core/src/io/anuke/mindustry/entities/effect/Fire.java index 28a2dc42f5..e4b1731661 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Fire.java +++ b/core/src/io/anuke/mindustry/entities/effect/Fire.java @@ -3,9 +3,9 @@ package io.anuke.mindustry.entities.effect; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.collection.IntMap; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.impl.TimedEntity; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.impl.TimedEntity; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Point2; @@ -17,12 +17,13 @@ import io.anuke.mindustry.content.Bullets; import io.anuke.mindustry.content.StatusEffects; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Damage; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.traits.SaveTrait; import io.anuke.mindustry.entities.traits.SyncTrait; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Pos; import io.anuke.mindustry.world.Tile; import java.io.DataInput; @@ -64,10 +65,10 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ } public static boolean has(int x, int y){ - if(!Structs.inBounds(x, y, world.width(), world.height()) || !map.containsKey(x + y * world.width())){ + if(!Structs.inBounds(x, y, world.width(), world.height()) || !map.containsKey(Pos.get(x, y))){ return false; } - Fire fire = map.get(x + y * world.width()); + Fire fire = map.get(Pos.get(x, y)); return fire.isAdded() && fire.fin() < 1f && fire.tile != null && fire.tile.x == x && fire.tile.y == y; } @@ -152,7 +153,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ entity.damage(0.4f); } Damage.damageUnits(null, tile.worldx(), tile.worldy(), tilesize, 3f, - unit -> !unit.isFlying(), + unit -> !unit.isFlying() && !unit.isImmune(StatusEffects.burning), unit -> unit.applyEffect(StatusEffects.burning, 60 * 5)); } } diff --git a/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java b/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java index 812cbd0db4..bc98f1619a 100644 --- a/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java +++ b/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java @@ -1,9 +1,9 @@ package io.anuke.mindustry.entities.effect; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; -import io.anuke.arc.entities.Effects.EffectRenderer; -import io.anuke.arc.entities.impl.EffectEntity; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects.EffectRenderer; +import io.anuke.mindustry.entities.impl.EffectEntity; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; diff --git a/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java b/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java index 8c32ccde94..5083897a33 100644 --- a/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java +++ b/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java @@ -2,9 +2,9 @@ package io.anuke.mindustry.entities.effect; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.impl.TimedEntity; -import io.anuke.arc.entities.trait.DrawTrait; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.impl.TimedEntity; +import io.anuke.mindustry.entities.traits.DrawTrait; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Fill; import io.anuke.arc.graphics.g2d.Lines; @@ -14,8 +14,8 @@ import io.anuke.arc.math.geom.Position; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; import io.anuke.arc.util.pooling.Pools; -import io.anuke.mindustry.entities.Unit; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; @@ -43,7 +43,7 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{ @Remote(called = Loc.server, unreliable = true) public static void transferItemToUnit(Item item, float x, float y, Unit to){ if(to == null) return; - create(item, x, y, to, () -> to.inventory.addItem(item, 1)); + create(item, x, y, to, () -> to.addItem(item)); } @Remote(called = Loc.server) @@ -105,7 +105,7 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{ @Override public void draw(){ - Lines.stroke(fslope() * 2f, Palette.accent); + Lines.stroke(fslope() * 2f, Pal.accent); Lines.circle(x, y, fslope() * 2f); diff --git a/core/src/io/anuke/mindustry/entities/effect/Lightning.java b/core/src/io/anuke/mindustry/entities/effect/Lightning.java index 7ee5e771af..7a89b29f9d 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Lightning.java +++ b/core/src/io/anuke/mindustry/entities/effect/Lightning.java @@ -4,13 +4,14 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.IntSet; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.impl.TimedEntity; -import io.anuke.arc.entities.trait.DrawTrait; -import io.anuke.arc.entities.trait.TimeTrait; +import io.anuke.arc.graphics.g2d.Fill; +import io.anuke.arc.graphics.g2d.Lines; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.impl.TimedEntity; +import io.anuke.mindustry.entities.traits.DrawTrait; +import io.anuke.mindustry.entities.traits.TimeTrait; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.RandomXS128; @@ -20,13 +21,13 @@ import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.content.Bullets; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.traits.SyncTrait; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import java.io.DataInput; import java.io.DataOutput; @@ -45,7 +46,7 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time private static int lastSeed = 0; private Array lines = new Array<>(); - private Color color = Palette.lancerLaser; + private Color color = Pal.lancerLaser; /**For pooling use only. Do not call directly!*/ public Lightning(){ @@ -118,7 +119,7 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time @Override public void reset(){ super.reset(); - color = Palette.lancerLaser; + color = Pal.lancerLaser; lines.clear(); } @@ -130,31 +131,22 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time @Override public void draw(){ - float lx = x, ly = y; + Lines.stroke(3f * fout()); Draw.color(color, Color.WHITE, fin()); - //TODO this is really, really bad rendering - /* - for(int i = 0; i < lines.size; i++){ - Position v = lines.get(i); + Lines.beginLine(); - float f = (float) i / lines.size; + Lines.linePoint(x, y); + for(Position p : lines){ + Lines.linePoint(p.getX(), p.getY()); + } + Lines.endLine(); - Lines.stroke(fout() * 3f * (1.5f - f)); + int i = 0; - Lines.stroke(Lines.getStroke() * 4f); - Draw.alpha(0.3f); - Lines.line(lx, ly, v.getX(), v.getY()); - - Lines.stroke(Lines.getStroke()/4f); - Draw.alpha(1f); - Lines.line(lx, ly, v.getX(), v.getY()); - - Lines.stroke(3f * fout() * (1f - f)); - - lx = v.getX(); - ly = v.getY(); - }*/ - Draw.color(); + for(Position p : lines){ + Fill.square(p.getX(), p.getY(), (5f - (float)i++/lines.size*2f) * fout(), 45); + } + Draw.reset(); } @Override diff --git a/core/src/io/anuke/mindustry/entities/effect/Puddle.java b/core/src/io/anuke/mindustry/entities/effect/Puddle.java index 68f590cc5f..8c3eb67ff7 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Puddle.java +++ b/core/src/io/anuke/mindustry/entities/effect/Puddle.java @@ -3,10 +3,10 @@ package io.anuke.mindustry.entities.effect; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.collection.IntMap; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.impl.SolidEntity; -import io.anuke.arc.entities.trait.DrawTrait; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.impl.SolidEntity; +import io.anuke.mindustry.entities.traits.DrawTrait; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Fill; @@ -212,7 +212,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai } }); - if(liquid.temperature > 0.7f && tile.entity != null && Mathf.chance(0.3 * Time.delta())){ + if(liquid.temperature > 0.7f && (tile.target().entity != null) && Mathf.chance(0.3 * Time.delta())){ Fire.create(tile); } diff --git a/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java b/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java index 51dda93718..bc94ecbec9 100644 --- a/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java +++ b/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java @@ -2,30 +2,43 @@ package io.anuke.mindustry.entities.effect; import io.anuke.arc.Core; import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; -public class RubbleDecal extends Decal{ - private int size; +import static io.anuke.mindustry.Vars.headless; - /** - * Creates a rubble effect at a position. Provide a block size to use. - */ +public class RubbleDecal extends Decal{ + private static final TextureRegion[][] regions = new TextureRegion[16][0]; + private TextureRegion region; + + /**Creates a rubble effect at a position. Provide a block size to use.*/ public static void create(float x, float y, int size){ + if(headless) return; + + if(regions[size].length == 0){ + regions[size] = new TextureRegion[2]; + for(int j = 0; j < 2; j++){ + regions[size][j] = Core.atlas.find("rubble-" + size + "-" + j); + } + } + RubbleDecal decal = new RubbleDecal(); - decal.size = size; + decal.region = regions[size][Mathf.clamp(Mathf.randomSeed(decal.id, 0, 1), 0, regions[size].length - 1)]; + + if(!Core.atlas.isFound(decal.region)){ + return; + } + decal.set(x, y); decal.add(); } @Override public void drawDecal(){ - String region = "rubble-" + size + "-" + Mathf.randomSeed(id, 0, 1); - - if(!Core.atlas.has(region)){ + if(!Core.atlas.isFound(region)){ remove(); return; } - Draw.rect(region, x, y, Mathf.randomSeed(id, 0, 4) * 90); } } diff --git a/core/src/io/anuke/mindustry/entities/effect/ScorchDecal.java b/core/src/io/anuke/mindustry/entities/effect/ScorchDecal.java index 58aa066d06..eba584b76b 100644 --- a/core/src/io/anuke/mindustry/entities/effect/ScorchDecal.java +++ b/core/src/io/anuke/mindustry/entities/effect/ScorchDecal.java @@ -7,6 +7,7 @@ import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.world.Tile; +import static io.anuke.mindustry.Vars.headless; import static io.anuke.mindustry.Vars.world; public class ScorchDecal extends Decal{ @@ -14,6 +15,8 @@ public class ScorchDecal extends Decal{ private static final TextureRegion[] regions = new TextureRegion[scorches]; public static void create(float x, float y){ + if(headless) return; + if(regions[0] == null){ for(int i = 0; i < regions.length; i++){ regions[i] = Core.atlas.find("scorch" + (i + 1)); diff --git a/core/src/io/anuke/mindustry/entities/impl/BaseEntity.java b/core/src/io/anuke/mindustry/entities/impl/BaseEntity.java new file mode 100755 index 0000000000..4fb4462c03 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/impl/BaseEntity.java @@ -0,0 +1,61 @@ +package io.anuke.mindustry.entities.impl; + +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.traits.Entity; + +public abstract class BaseEntity implements Entity{ + private static int lastid; + /** Do not modify. Used for network operations and mapping. */ + public int id; + public float x, y; + protected transient EntityGroup group; + + public BaseEntity(){ + id = lastid++; + } + + @Override + public int getID(){ + return id; + } + + @Override + public void resetID(int id){ + this.id = id; + } + + @Override + public EntityGroup getGroup(){ + return group; + } + + @Override + public void setGroup(EntityGroup group){ + this.group = group; + } + + @Override + public float getX(){ + return x; + } + + @Override + public void setX(float x){ + this.x = x; + } + + @Override + public float getY(){ + return y; + } + + @Override + public void setY(float y){ + this.y = y; + } + + @Override + public String toString(){ + return getClass() + " " + id; + } +} diff --git a/core/src/io/anuke/mindustry/entities/impl/DestructibleEntity.java b/core/src/io/anuke/mindustry/entities/impl/DestructibleEntity.java new file mode 100644 index 0000000000..fdb22094c6 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/impl/DestructibleEntity.java @@ -0,0 +1,45 @@ +package io.anuke.mindustry.entities.impl; + + +import io.anuke.mindustry.entities.traits.DamageTrait; +import io.anuke.mindustry.entities.traits.HealthTrait; +import io.anuke.mindustry.entities.traits.SolidTrait; + +public abstract class DestructibleEntity extends SolidEntity implements HealthTrait{ + public transient boolean dead; + public float health; + + @Override + public boolean collides(SolidTrait other){ + return other instanceof DamageTrait; + } + + @Override + public void collision(SolidTrait other, float x, float y){ + if(other instanceof DamageTrait){ + onHit(other); + damage(((DamageTrait) other).damage()); + } + } + + @Override + public void health(float health){ + this.health = health; + } + + @Override + public float health(){ + return health; + } + + @Override + public boolean isDead(){ + return dead; + } + + @Override + public void setDead(boolean dead){ + this.dead = dead; + } + +} diff --git a/core/src/io/anuke/mindustry/entities/impl/EffectEntity.java b/core/src/io/anuke/mindustry/entities/impl/EffectEntity.java new file mode 100644 index 0000000000..e678f29964 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/impl/EffectEntity.java @@ -0,0 +1,72 @@ +package io.anuke.mindustry.entities.impl; + +import io.anuke.arc.graphics.Color; +import io.anuke.arc.util.pooling.Pool.Poolable; +import io.anuke.arc.util.pooling.Pools; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; +import io.anuke.mindustry.entities.traits.DrawTrait; +import io.anuke.mindustry.entities.traits.Entity; + +public class EffectEntity extends TimedEntity implements Poolable, DrawTrait{ + public Effect effect; + public Color color = new Color(Color.WHITE); + public Object data; + public float rotation = 0f; + + public Entity parent; + public float poffsetx, poffsety; + + /** For pooling use only! */ + public EffectEntity(){ + } + + public void setParent(Entity parent){ + this.parent = parent; + this.poffsetx = x - parent.getX(); + this.poffsety = y - parent.getY(); + } + + @Override + public float lifetime(){ + return effect.lifetime; + } + + @Override + public float drawSize(){ + return effect.size; + } + + @Override + public void update(){ + if(effect == null){ + remove(); + return; + } + + super.update(); + if(parent != null){ + x = parent.getX() + poffsetx; + y = parent.getY() + poffsety; + } + } + + @Override + public void reset(){ + effect = null; + color.set(Color.WHITE); + rotation = time = poffsetx = poffsety = 0f; + parent = null; + data = null; + } + + @Override + public void draw(){ + Effects.renderEffect(id, effect, color, time, rotation, x, y, data); + } + + @Override + public void removed(){ + Pools.free(this); + } +} diff --git a/core/src/io/anuke/mindustry/entities/impl/SolidEntity.java b/core/src/io/anuke/mindustry/entities/impl/SolidEntity.java new file mode 100644 index 0000000000..544abdbefa --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/impl/SolidEntity.java @@ -0,0 +1,19 @@ +package io.anuke.mindustry.entities.impl; + +import io.anuke.arc.math.geom.Vector2; +import io.anuke.mindustry.entities.traits.SolidTrait; + +public abstract class SolidEntity extends BaseEntity implements SolidTrait{ + protected transient Vector2 velocity = new Vector2(0f, 0.0001f); + private transient Vector2 lastPosition = new Vector2(); + + @Override + public Vector2 lastPosition(){ + return lastPosition; + } + + @Override + public Vector2 velocity(){ + return velocity; + } +} diff --git a/core/src/io/anuke/mindustry/entities/impl/TimedEntity.java b/core/src/io/anuke/mindustry/entities/impl/TimedEntity.java new file mode 100644 index 0000000000..e4007a5c4b --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/impl/TimedEntity.java @@ -0,0 +1,34 @@ +package io.anuke.mindustry.entities.impl; + +import io.anuke.arc.util.pooling.Pool.Poolable; +import io.anuke.mindustry.entities.traits.ScaleTrait; +import io.anuke.mindustry.entities.traits.TimeTrait; + +public abstract class TimedEntity extends BaseEntity implements ScaleTrait, TimeTrait, Poolable{ + public float time; + + @Override + public void time(float time){ + this.time = time; + } + + @Override + public float time(){ + return time; + } + + @Override + public void update(){ + updateTime(); + } + + @Override + public void reset(){ + time = 0f; + } + + @Override + public float fin(){ + return time() / lifetime(); + } +} diff --git a/core/src/io/anuke/mindustry/entities/traits/AbsorbTrait.java b/core/src/io/anuke/mindustry/entities/traits/AbsorbTrait.java index dedffc5203..d408296c7c 100644 --- a/core/src/io/anuke/mindustry/entities/traits/AbsorbTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/AbsorbTrait.java @@ -1,8 +1,5 @@ package io.anuke.mindustry.entities.traits; -import io.anuke.arc.entities.trait.DamageTrait; -import io.anuke.arc.entities.trait.Entity; - public interface AbsorbTrait extends Entity, TeamTrait, DamageTrait{ void absorb(); diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java index 503f5d780e..047a9d0dd5 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java @@ -4,8 +4,6 @@ import io.anuke.arc.Core; import io.anuke.arc.Events; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.Queue; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.trait.Entity; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Fill; @@ -17,12 +15,13 @@ import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.EventType.BuildSelectEvent; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Shapes; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; @@ -43,7 +42,7 @@ import static io.anuke.mindustry.Vars.*; /** * Interface for units that build, break or mine things. */ -public interface BuilderTrait extends Entity{ +public interface BuilderTrait extends Entity, TeamTrait{ //these are not instance variables! Vector2[] tmptr = new Vector2[]{new Vector2(), new Vector2(), new Vector2(), new Vector2()}; float placeDistance = 150f; @@ -125,22 +124,6 @@ public interface BuilderTrait extends Entity{ return getPlaceQueue().size != 0; } - /** - * If a place request matching this signature is present, it is removed. - * Otherwise, a new place request is added to the queue. - */ - default void replaceBuilding(int x, int y, int rotation, Block block){ - for(BuildRequest request : getPlaceQueue()){ - if(request.x == x && request.y == y){ - clearBuilding(); - addBuildRequest(request); - return; - } - } - - addBuildRequest(new BuildRequest(x, y, rotation, block)); - } - /**Clears the placement queue.*/ default void clearBuilding(){ getPlaceQueue().clear(); @@ -172,7 +155,8 @@ public interface BuilderTrait extends Entity{ * Update building mechanism for this unit. * This includes mining. */ - default void updateBuilding(Unit unit){ + default void updateBuilding(){ + Unit unit = (Unit)this; //remove already completed build requests removal.clear(); for(BuildRequest req : getPlaceQueue()){ @@ -183,8 +167,7 @@ public interface BuilderTrait extends Entity{ for(BuildRequest request : removal){ if(!((request.breaking && world.tile(request.x, request.y).block() == Blocks.air) || - (!request.breaking && - (world.tile(request.x, request.y).getRotation() == request.rotation || !request.block.rotate) + (!request.breaking && (world.tile(request.x, request.y).getRotation() == request.rotation || !request.block.rotate) && world.tile(request.x, request.y).block() == request.block))){ getPlaceQueue().addLast(request); } @@ -195,7 +178,7 @@ public interface BuilderTrait extends Entity{ //update mining here if(current == null){ if(getMineTile() != null){ - updateMining(unit); + updateMining(); } return; }else{ @@ -204,15 +187,19 @@ public interface BuilderTrait extends Entity{ Tile tile = world.tile(current.x, current.y); - if(unit.dst(tile) > placeDistance){ + if(dst(tile) > placeDistance){ + if(getPlaceQueue().size > 1){ + getPlaceQueue().removeFirst(); + getPlaceQueue().addLast(current); + } return; } if(!(tile.block() instanceof BuildBlock)){ - if(canCreateBlocks() && !current.breaking && Build.validPlace(unit.getTeam(), current.x, current.y, current.block, current.rotation)){ - Build.beginPlace(unit.getTeam(), current.x, current.y, current.block, current.rotation); - }else if(canCreateBlocks() && current.breaking && Build.validBreak(unit.getTeam(), current.x, current.y)){ - Build.beginBreak(unit.getTeam(), current.x, current.y); + if(canCreateBlocks() && !current.breaking && Build.validPlace(getTeam(), current.x, current.y, current.block, current.rotation)){ + Build.beginPlace(getTeam(), current.x, current.y, current.block, current.rotation); + }else if(canCreateBlocks() && current.breaking && Build.validBreak(getTeam(), current.x, current.y)){ + Build.beginBreak(getTeam(), current.x, current.y); }else{ getPlaceQueue().removeFirst(); return; @@ -259,12 +246,13 @@ public interface BuilderTrait extends Entity{ } /**Do not call directly.*/ - default void updateMining(Unit unit){ + default void updateMining(){ + Unit unit = (Unit)this; Tile tile = getMineTile(); TileEntity core = unit.getClosestCore(); - if(core == null || tile.block() != Blocks.air || unit.dst(tile.worldx(), tile.worldy()) > mineDistance - || tile.floor().itemDrop == null || !unit.inventory.canAcceptItem(tile.floor().itemDrop) || !canMine(tile.floor().itemDrop)){ + if(core == null || tile.block() != Blocks.air || dst(tile.worldx(), tile.worldy()) > mineDistance + || tile.floor().itemDrop == null || !unit.acceptsItem(tile.floor().itemDrop) || !canMine(tile.floor().itemDrop)){ setMineTile(null); }else{ Item item = tile.floor().itemDrop; @@ -276,7 +264,7 @@ public interface BuilderTrait extends Entity{ Call.transferItemTo(item, 1, tile.worldx() + Mathf.range(tilesize / 2f), tile.worldy() + Mathf.range(tilesize / 2f), core.tile); - }else if(unit.inventory.canAcceptItem(item)){ + }else if(unit.acceptsItem(item)){ Call.transferItemToUnit(item, tile.worldx() + Mathf.range(tilesize / 2f), tile.worldy() + Mathf.range(tilesize / 2f), @@ -293,11 +281,12 @@ public interface BuilderTrait extends Entity{ } /**Draw placement effects for an entity. This includes mining*/ - default void drawBuilding(Unit unit){ + default void drawBuilding(){ + Unit unit = (Unit)this; BuildRequest request; if(!isBuilding()){ if(getMineTile() != null){ - drawMining(unit); + drawMining(); } return; } @@ -306,11 +295,11 @@ public interface BuilderTrait extends Entity{ Tile tile = world.tile(request.x, request.y); - if(unit.dst(tile) > placeDistance){ + if(dst(tile) > placeDistance){ return; } - Lines.stroke(1f, Palette.accent); + Lines.stroke(1f, Pal.accent); float focusLen = 3.8f + Mathf.absin(Time.time(), 1.1f, 0.6f); float px = unit.x + Angles.trnsx(unit.rotation, focusLen); float py = unit.y + Angles.trnsy(unit.rotation, focusLen); @@ -340,7 +329,8 @@ public interface BuilderTrait extends Entity{ } /**Internal use only.*/ - default void drawMining(Unit unit){ + default void drawMining(){ + Unit unit = (Unit)this; Tile tile = getMineTile(); if(tile == null) return; @@ -357,10 +347,10 @@ public interface BuilderTrait extends Entity{ Draw.color(Color.LIGHT_GRAY, Color.WHITE, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl)); - Shapes.laser("minelaser", "minelaser-end", px, py, ex, ey); + Shapes.laser("minelaser", "minelaser-end", px, py, ex, ey, 0.75f); if(unit instanceof Player && ((Player) unit).isLocal){ - Lines.stroke(1f, Palette.accent); + Lines.stroke(1f, Pal.accent); Lines.poly(tile.worldx(), tile.worldy(), 4, tilesize / 2f * Mathf.sqrt2, Time.time()); } diff --git a/core/src/io/anuke/mindustry/entities/traits/CarriableTrait.java b/core/src/io/anuke/mindustry/entities/traits/CarriableTrait.java deleted file mode 100644 index 3755245e8e..0000000000 --- a/core/src/io/anuke/mindustry/entities/traits/CarriableTrait.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.anuke.mindustry.entities.traits; - -import io.anuke.arc.entities.trait.SolidTrait; - -public interface CarriableTrait extends TeamTrait, TargetTrait, SolidTrait{ - - default boolean isCarried(){ - return getCarrier() != null; - } - - CarryTrait getCarrier(); - - void setCarrier(CarryTrait carrier); -} diff --git a/core/src/io/anuke/mindustry/entities/traits/CarryTrait.java b/core/src/io/anuke/mindustry/entities/traits/CarryTrait.java deleted file mode 100644 index de7f571161..0000000000 --- a/core/src/io/anuke/mindustry/entities/traits/CarryTrait.java +++ /dev/null @@ -1,69 +0,0 @@ -package io.anuke.mindustry.entities.traits; - -import io.anuke.annotations.Annotations.Loc; -import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.gen.Call; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.trait.SolidTrait; - -public interface CarryTrait extends TeamTrait, SolidTrait, TargetTrait{ - - @Remote(called = Loc.both, targets = Loc.both, forward = true) - static void dropSelf(Player player){ - if(player != null && player.getCarrier() != null){ - player.getCarrier().dropCarry(); - } - } - - @Remote(called = Loc.both, targets = Loc.both, forward = true) - static void setCarryOf(Player player, CarryTrait trait, CarriableTrait unit){ - if(trait == null) return; - if(player != null){ //when a server recieves this called from a player, set the carrier to the player. - trait = player; - } - - if(trait.getCarry() != null){ //already carrying something, drop it - //drop current - Effects.effect(Fx.unitDrop, trait.getCarry()); - trait.getCarry().setCarrier(null); - trait.setCarry(null); - - if(unit != null){ - trait.carry(unit); //now carry this new thing - } - }else if(unit != null){ //not currently carrying anything, make sure it's not null - trait.setCarry(unit); - unit.setCarrier(trait); - - Effects.effect(Fx.unitPickup, trait); - } - } - - /**Returns the thing this carrier is carrying.*/ - CarriableTrait getCarry(); - - /**Sets the carrying unit. Internal use only! Use {@link #carry(CarriableTrait)} to set state.*/ - void setCarry(CarriableTrait unit); - - /**Returns maximum mass this carrier can carry.*/ - float getCarryWeight(); - - /**Drops the unit that is being carried, if applicable.*/ - default void dropCarry(){ - carry(null); - } - - default void dropCarryLocal(){ - setCarryOf(null, this, null); - } - - /** - * Do not override unless absolutely necessary. - * Carries a unit. To drop a unit, call with {@code null}. - */ - default void carry(CarriableTrait unit){ - Call.setCarryOf(this instanceof Player ? (Player) this : null, this, unit); - } -} diff --git a/core/src/io/anuke/mindustry/entities/traits/DamageTrait.java b/core/src/io/anuke/mindustry/entities/traits/DamageTrait.java new file mode 100644 index 0000000000..3f009687d6 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/traits/DamageTrait.java @@ -0,0 +1,5 @@ +package io.anuke.mindustry.entities.traits; + +public interface DamageTrait{ + float damage(); +} diff --git a/core/src/io/anuke/mindustry/entities/traits/DrawTrait.java b/core/src/io/anuke/mindustry/entities/traits/DrawTrait.java new file mode 100644 index 0000000000..648d9797b3 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/traits/DrawTrait.java @@ -0,0 +1,10 @@ +package io.anuke.mindustry.entities.traits; + +public interface DrawTrait extends Entity{ + + default float drawSize(){ + return 20f; + } + + void draw(); +} diff --git a/core/src/io/anuke/mindustry/entities/traits/Entity.java b/core/src/io/anuke/mindustry/entities/traits/Entity.java new file mode 100644 index 0000000000..582880beac --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/traits/Entity.java @@ -0,0 +1,46 @@ +package io.anuke.mindustry.entities.traits; + +import io.anuke.mindustry.entities.Entities; +import io.anuke.mindustry.entities.EntityGroup; + +public interface Entity extends MoveTrait{ + + int getID(); + + void resetID(int id); + + default void update(){ + } + + default void removed(){ + } + + default void added(){ + } + + default EntityGroup targetGroup(){ + return Entities.defaultGroup(); + } + + @SuppressWarnings("unchecked") + default void add(){ + targetGroup().add(this); + } + + @SuppressWarnings("unchecked") + default void remove(){ + if(getGroup() != null){ + getGroup().remove(this); + } + + setGroup(null); + } + + EntityGroup getGroup(); + + void setGroup(EntityGroup group); + + default boolean isAdded(){ + return getGroup() != null; + } +} diff --git a/core/src/io/anuke/mindustry/entities/traits/HealthTrait.java b/core/src/io/anuke/mindustry/entities/traits/HealthTrait.java new file mode 100644 index 0000000000..536b6caad2 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/traits/HealthTrait.java @@ -0,0 +1,48 @@ +package io.anuke.mindustry.entities.traits; + +import io.anuke.arc.math.Mathf; + +public interface HealthTrait{ + + void health(float health); + + float health(); + + float maxHealth(); + + boolean isDead(); + + void setDead(boolean dead); + + default void onHit(SolidTrait entity){ + } + + default void onDeath(){ + } + + default void damage(float amount){ + health(health() - amount); + if(health() <= 0 && !isDead()){ + onDeath(); + setDead(true); + } + } + + default void clampHealth(){ + health(Mathf.clamp(health(), 0, maxHealth())); + } + + default float healthf(){ + return health() / maxHealth(); + } + + default void healBy(float amount){ + health(health() + amount); + clampHealth(); + } + + default void heal(){ + health(maxHealth()); + setDead(false); + } +} diff --git a/core/src/io/anuke/mindustry/entities/traits/InventoryTrait.java b/core/src/io/anuke/mindustry/entities/traits/InventoryTrait.java deleted file mode 100644 index c84eaea6b4..0000000000 --- a/core/src/io/anuke/mindustry/entities/traits/InventoryTrait.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.anuke.mindustry.entities.traits; - -import io.anuke.mindustry.entities.UnitInventory; - -public interface InventoryTrait{ - UnitInventory getInventory(); -} diff --git a/core/src/io/anuke/mindustry/entities/traits/MoveTrait.java b/core/src/io/anuke/mindustry/entities/traits/MoveTrait.java new file mode 100644 index 0000000000..561c7a76bd --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/traits/MoveTrait.java @@ -0,0 +1,20 @@ +package io.anuke.mindustry.entities.traits; + +import io.anuke.arc.math.geom.Position; + +public interface MoveTrait extends Position{ + + void setX(float x); + + void setY(float y); + + default void moveBy(float x, float y){ + setX(getX() + x); + setY(getY() + y); + } + + default void set(float x, float y){ + setX(x); + setY(y); + } +} diff --git a/core/src/io/anuke/mindustry/entities/traits/SaveTrait.java b/core/src/io/anuke/mindustry/entities/traits/SaveTrait.java index bcf357f4e5..dfaf8011aa 100644 --- a/core/src/io/anuke/mindustry/entities/traits/SaveTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/SaveTrait.java @@ -1,7 +1,5 @@ package io.anuke.mindustry.entities.traits; -import io.anuke.arc.entities.trait.Entity; - /** * Marks an entity as serializable. */ diff --git a/core/src/io/anuke/mindustry/entities/traits/ScaleTrait.java b/core/src/io/anuke/mindustry/entities/traits/ScaleTrait.java new file mode 100644 index 0000000000..9975bb12a8 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/traits/ScaleTrait.java @@ -0,0 +1,43 @@ +package io.anuke.mindustry.entities.traits; + +import io.anuke.arc.math.Interpolation; + +public interface ScaleTrait{ + /** 0 to 1. */ + float fin(); + + /** 1 to 0 */ + default float fout(){ + return 1f - fin(); + } + + /** 1 to 0 */ + default float fout(Interpolation i){ + return i.apply(fout()); + } + + /** 1 to 0, ending at the specified margin */ + default float fout(float margin){ + float f = fin(); + if(f >= 1f - margin){ + return 1f - (f - (1f - margin)) / margin; + }else{ + return 1f; + } + } + + /** 0 to 1 **/ + default float fin(Interpolation i){ + return i.apply(fin()); + } + + /** 0 to 1 */ + default float finpow(){ + return Interpolation.pow3Out.apply(fin()); + } + + /** 0 to 1 to 0 */ + default float fslope(){ + return (0.5f - Math.abs(fin() - 0.5f)) * 2f; + } +} diff --git a/core/src/io/anuke/mindustry/entities/traits/ShooterTrait.java b/core/src/io/anuke/mindustry/entities/traits/ShooterTrait.java index 22072cfd64..ca3010eec3 100644 --- a/core/src/io/anuke/mindustry/entities/traits/ShooterTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/ShooterTrait.java @@ -1,10 +1,9 @@ package io.anuke.mindustry.entities.traits; -import io.anuke.arc.entities.trait.VelocityTrait; import io.anuke.arc.util.Interval; import io.anuke.mindustry.type.Weapon; -public interface ShooterTrait extends VelocityTrait, TeamTrait, InventoryTrait{ +public interface ShooterTrait extends VelocityTrait, TeamTrait{ Interval getTimer(); diff --git a/core/src/io/anuke/mindustry/entities/traits/SolidTrait.java b/core/src/io/anuke/mindustry/entities/traits/SolidTrait.java new file mode 100644 index 0000000000..83f5a70524 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/traits/SolidTrait.java @@ -0,0 +1,43 @@ +package io.anuke.mindustry.entities.traits; + + +import io.anuke.mindustry.entities.EntityQuery; +import io.anuke.arc.math.geom.Position; +import io.anuke.arc.math.geom.QuadTree.QuadTreeObject; +import io.anuke.arc.math.geom.Rectangle; +import io.anuke.arc.math.geom.Vector2; + +public interface SolidTrait extends QuadTreeObject, MoveTrait, VelocityTrait, Entity, Position{ + + void hitbox(Rectangle rectangle); + + void hitboxTile(Rectangle rectangle); + + Vector2 lastPosition(); + + default boolean collidesGrid(int x, int y){ + return true; + } + + default float getDeltaX(){ + return getX() - lastPosition().x; + } + + default float getDeltaY(){ + return getY() - lastPosition().y; + } + + default boolean movable(){ + return false; + } + + default boolean collides(SolidTrait other){ + return true; + } + + default void collision(SolidTrait other, float x, float y){} + + default void move(float x, float y){ + EntityQuery.collisions().move(this, x, y); + } +} diff --git a/core/src/io/anuke/mindustry/entities/traits/SpawnerTrait.java b/core/src/io/anuke/mindustry/entities/traits/SpawnerTrait.java index 55c1763b1f..df23a1053d 100644 --- a/core/src/io/anuke/mindustry/entities/traits/SpawnerTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/SpawnerTrait.java @@ -1,12 +1,16 @@ package io.anuke.mindustry.entities.traits; -import io.anuke.mindustry.entities.Unit; +import io.anuke.arc.math.geom.Position; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.world.Tile; -public interface SpawnerTrait{ +public interface SpawnerTrait extends TargetTrait, Position{ Tile getTile(); - void updateSpawning(Unit unit); + void updateSpawning(Player unit); - float getSpawnProgress(); + @Override + default boolean isValid(){ + return getTile().entity instanceof SpawnerTrait; + } } diff --git a/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java b/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java index 38bbe23088..81e5419014 100644 --- a/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java @@ -3,7 +3,6 @@ package io.anuke.mindustry.entities.traits; import io.anuke.mindustry.core.NetClient; import io.anuke.mindustry.net.Interpolator; import io.anuke.arc.Core; -import io.anuke.arc.entities.trait.Entity; import io.anuke.arc.util.Tmp; import java.io.DataInput; @@ -63,6 +62,10 @@ public interface SyncTrait extends Entity, TypeTrait{ return true; } + default float clipSize(){ + return (this instanceof DrawTrait ? ((DrawTrait)this).drawSize() : 8f); + } + //Read and write sync data, usually position void write(DataOutput data) throws IOException; diff --git a/core/src/io/anuke/mindustry/entities/traits/TargetTrait.java b/core/src/io/anuke/mindustry/entities/traits/TargetTrait.java index f59ed37091..dcc7a876b9 100644 --- a/core/src/io/anuke/mindustry/entities/traits/TargetTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/TargetTrait.java @@ -1,7 +1,5 @@ package io.anuke.mindustry.entities.traits; -import io.anuke.arc.entities.trait.SolidTrait; -import io.anuke.arc.entities.trait.VelocityTrait; import io.anuke.arc.math.geom.Position; import io.anuke.mindustry.game.Team; diff --git a/core/src/io/anuke/mindustry/entities/traits/TeamTrait.java b/core/src/io/anuke/mindustry/entities/traits/TeamTrait.java index 6954258423..5f800b2098 100644 --- a/core/src/io/anuke/mindustry/entities/traits/TeamTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/TeamTrait.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.entities.traits; import io.anuke.mindustry.game.Team; -import io.anuke.arc.entities.trait.Entity; public interface TeamTrait extends Entity{ Team getTeam(); diff --git a/core/src/io/anuke/mindustry/entities/traits/TimeTrait.java b/core/src/io/anuke/mindustry/entities/traits/TimeTrait.java new file mode 100644 index 0000000000..47dc7dfe48 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/traits/TimeTrait.java @@ -0,0 +1,23 @@ +package io.anuke.mindustry.entities.traits; + +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Time; + +public interface TimeTrait extends ScaleTrait, Entity{ + + float lifetime(); + + void time(float time); + + float time(); + + default void updateTime(){ + time(Mathf.clamp(time() + Time.delta(), 0, lifetime())); + + if(time() >= lifetime()){ + remove(); + } + } + + //fin() is not implemented due to compiler issues with iOS/RoboVM +} diff --git a/core/src/io/anuke/mindustry/entities/traits/VelocityTrait.java b/core/src/io/anuke/mindustry/entities/traits/VelocityTrait.java new file mode 100644 index 0000000000..c836154f9c --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/traits/VelocityTrait.java @@ -0,0 +1,36 @@ +package io.anuke.mindustry.entities.traits; + +import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.util.Time; + +public interface VelocityTrait extends MoveTrait{ + + Vector2 velocity(); + + default void applyImpulse(float x, float y){ + velocity().x += x / mass(); + velocity().y += y / mass(); + } + + default float maxVelocity(){ + return Float.MAX_VALUE; + } + + default float mass(){ + return 1f; + } + + default float drag(){ + return 0f; + } + + default void updateVelocity(){ + velocity().scl(1f - drag() * Time.delta()); + + if(this instanceof SolidTrait){ + ((SolidTrait) this).move(velocity().x * Time.delta(), velocity().y * Time.delta()); + }else{ + moveBy(velocity().x * Time.delta(), velocity().y * Time.delta()); + } + } +} diff --git a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java similarity index 75% rename from core/src/io/anuke/mindustry/entities/units/BaseUnit.java rename to core/src/io/anuke/mindustry/entities/type/BaseUnit.java index 3894e22ea5..7d62c05d16 100644 --- a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java @@ -1,10 +1,8 @@ -package io.anuke.mindustry.entities.units; +package io.anuke.mindustry.entities.type; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.EntityGroup; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Angles; @@ -14,22 +12,18 @@ import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.util.Interval; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Damage; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.content.StatusEffects; +import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.entities.effect.ScorchDecal; import io.anuke.mindustry.entities.traits.ShooterTrait; -import io.anuke.mindustry.entities.traits.SpawnerTrait; import io.anuke.mindustry.entities.traits.TargetTrait; +import io.anuke.mindustry.entities.units.StateMachine; +import io.anuke.mindustry.entities.units.UnitDrops; +import io.anuke.mindustry.entities.units.UnitState; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Weapon; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockFlag; @@ -53,8 +47,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ protected StateMachine state = new StateMachine(); protected TargetTrait target; - protected boolean isWave; - protected Squad squad; protected int spawner = noSpawner; /**internal constructor used for deserialization, DO NOT USE*/ @@ -69,16 +61,8 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ UnitDrops.dropItems(unit); } - float explosiveness = 2f + (unit.inventory.hasItem() ? unit.inventory.getItem().item.explosiveness * unit.inventory.getItem().amount : 0f); - float flammability = (unit.inventory.hasItem() ? unit.inventory.getItem().item.flammability * unit.inventory.getItem().amount : 0f); - Damage.dynamicExplosion(unit.x, unit.y, flammability, explosiveness, 0f, unit.getSize() / 2f, Palette.darkFlame); - unit.onSuperDeath(); - ScorchDecal.create(unit.x, unit.y); - Effects.effect(Fx.explosion, unit); - Effects.shake(2f, 2f, unit); - //must run afterwards so the unit's group is not null when sending the removal packet Core.app.post(unit::remove); } @@ -104,36 +88,12 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ this.spawner = tile.pos(); } - /**Sets this to a 'wave' unit, which means it has slightly different AI and will not run out of ammo.*/ - public void setWave(){ - isWave = true; - } - - public void setSquad(Squad squad){ - this.squad = squad; - squad.units++; - } - public void rotate(float angle){ rotation = Mathf.slerpDelta(rotation, angle, type.rotatespeed); } public boolean targetHasFlag(BlockFlag flag){ - return target instanceof TileEntity && ((TileEntity) target).tile.block().flags != null && - ((TileEntity) target).tile.block().flags.contains(flag); - } - - public void updateRespawning(){ - if(spawner == noSpawner) return; - - Tile tile = world.tile(spawner); - if(tile != null && tile.entity != null){ - if(tile.entity instanceof SpawnerTrait){ - ((SpawnerTrait) tile.entity).updateSpawning(this); - } - }else{ - spawner = noSpawner; - } + return target instanceof TileEntity && ((TileEntity) target).tile.block().flags.contains(flag); } public void setState(UnitState state){ @@ -169,7 +129,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } public void targetClosest(){ - target = Units.getClosestTarget(team, x, y, Math.max(getWeapon().getAmmo().range(), type.range), u -> type.targetAir || !u.isFlying()); + target = Units.getClosestTarget(team, x, y, Math.max(getWeapon().bullet.range(), type.range), u -> type.targetAir || !u.isFlying()); } public TileEntity getClosestEnemyCore(){ @@ -189,15 +149,14 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } protected void drawItems(){ - float backTrns = 4f, itemSize = 5f; - if(inventory.hasItem()){ - ItemStack stack = inventory.getItem(); - int stored = Mathf.clamp(stack.amount / 6, 1, 8); + float backTrns = 4f; + if(item.amount > 0){ + int stored = Mathf.clamp(item.amount / 6, 1, 8); for(int i = 0; i < stored; i++){ float angT = i == 0 ? 0 : Mathf.randomSeedRange(i + 2, 60f); float lenT = i == 0 ? 0 : Mathf.randomSeedRange(i + 3, 1f) - 1f; - Draw.rect(stack.item.region, + Draw.rect(item.item.icon(Item.Icon.large), x + Angles.trnsx(rotation + 180f + angT, backTrns + lenT), y + Angles.trnsy(rotation + 180f + angT, backTrns + lenT), itemSize, itemSize, rotation); @@ -205,6 +164,15 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } } + public boolean isBoss(){ + return hasEffect(StatusEffects.boss); + } + + @Override + public boolean isImmune(StatusEffect effect){ + return type.immunities.contains(effect); + } + @Override public boolean isValid(){ return super.isValid() && isAdded(); @@ -249,16 +217,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ return type.health; } - @Override - public float getArmor(){ - return type.armor; - } - - @Override - public float getSize(){ - return 8; - } - @Override public float mass(){ return type.mass; @@ -274,7 +232,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ hitTime -= Time.delta(); if(isDead()){ - updateRespawning(); return; } @@ -290,10 +247,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ damage(health); } - if(squad != null){ - squad.update(); - } - updateTargeting(); state.update(); @@ -301,8 +254,9 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ if(target != null) behavior(); - x = Mathf.clamp(x, tilesize, world.width() * tilesize - tilesize); - y = Mathf.clamp(y, tilesize, world.height() * tilesize - tilesize); + if(!isFlying()){ + clampPosition(); + } } @Override @@ -317,12 +271,22 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ @Override public void removed(){ + Tile tile = world.tile(spawner); + if(tile != null){ + tile.block().unitRemoved(tile, this); + } + spawner = noSpawner; } @Override public float drawSize(){ - return 14; + return type.hitsize * 10; + } + + @Override + public float clipSize(){ + return isBoss() ? 10000000000f : super.clipSize(); } @Override @@ -356,7 +320,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ public void writeSave(DataOutput stream) throws IOException{ super.writeSave(stream); stream.writeByte(type.id); - stream.writeBoolean(isWave); stream.writeInt(spawner); } @@ -364,7 +327,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ public void readSave(DataInput stream) throws IOException{ super.readSave(stream); byte type = stream.readByte(); - this.isWave = stream.readBoolean(); this.spawner = stream.readInt(); this.type = content.getByID(ContentType.unit, type); diff --git a/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java b/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java new file mode 100644 index 0000000000..65d324e742 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java @@ -0,0 +1,221 @@ +package io.anuke.mindustry.entities.type; + +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.Fill; +import io.anuke.arc.math.Angles; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.util.Time; +import io.anuke.arc.util.Tmp; +import io.anuke.mindustry.entities.Predict; +import io.anuke.mindustry.entities.Units; +import io.anuke.mindustry.entities.bullet.BulletType; +import io.anuke.mindustry.entities.units.UnitState; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.world.meta.BlockFlag; + +public abstract class FlyingUnit extends BaseUnit{ + protected float[] weaponAngles = {0, 0}; + + protected final UnitState + + attack = new UnitState(){ + public void entered(){ + target = null; + } + + public void update(){ + + if(Units.invalidateTarget(target, team, x, y)){ + target = null; + } + + if(target == null){ + + retarget(() -> { + targetClosest(); + + if(target == null) targetClosestEnemyFlag(BlockFlag.producer); + if(target == null) targetClosestEnemyFlag(BlockFlag.turret); + + if(target == null){ + setState(patrol); + } + }); + + }else{ + attack(type.attackLength); + + if((Angles.near(angleTo(target), rotation, type.shootCone) || getWeapon().ignoreRotation) //bombers and such don't care about rotation + && dst(target) < Math.max(getWeapon().bullet.range(), type.range)){ + BulletType ammo = getWeapon().bullet; + + if(type.rotateWeapon){ + for(boolean left : Mathf.booleans){ + int wi = Mathf.num(left); + float wx = x + Angles.trnsx(rotation - 90, getWeapon().width * Mathf.sign(left)); + float wy = y + Angles.trnsy(rotation - 90, getWeapon().width * Mathf.sign(left)); + + weaponAngles[wi] = Mathf.slerpDelta(weaponAngles[wi], Angles.angle(wx, wy, target.getX(), target.getY()), 0.1f); + + Tmp.v2.trns(weaponAngles[wi], getWeapon().length); + getWeapon().update(FlyingUnit.this, wx + Tmp.v2.x, wy + Tmp.v2.y, weaponAngles[wi], left); + } + }else{ + Vector2 to = Predict.intercept(FlyingUnit.this, target, ammo.speed); + getWeapon().update(FlyingUnit.this, to.x, to.y); + } + } + } + } + }, + patrol = new UnitState(){ + public void update(){ + retarget(() -> { + targetClosest(); + targetClosestEnemyFlag(BlockFlag.target); + + if(target != null){ + setState(attack); + } + + target = getClosestCore(); + }); + + if(target != null){ + circle(60f + Mathf.absin(Time.time() + id * 23525, 70f, 1200f)); + } + } + }; + + @Override + public void move(float x, float y){ + moveBy(x, y); + } + + @Override + public void update(){ + super.update(); + + if(!Net.client()){ + updateRotation(); + wobble(); + } + } + + @Override + public void drawUnder(){ + drawEngine(); + } + + @Override + public void draw(){ + Draw.mixcol(Color.WHITE, hitTime / hitDuration); + Draw.rect(type.region, x, y, rotation - 90); + + drawWeapons(); + drawItems(); + + Draw.mixcol(); + } + + public void drawWeapons(){ + + } + + public void drawEngine(){ + Draw.color(Pal.engine); + Fill.circle(x + Angles.trnsx(rotation + 180, type.engineOffset), y + Angles.trnsy(rotation + 180, type.engineOffset), + type.engineSize + Mathf.absin(Time.time(), 2f, type.engineSize/4f)); + + Draw.color(Color.WHITE); + Fill.circle(x + Angles.trnsx(rotation + 180, type.engineOffset-1f), y + Angles.trnsy(rotation + 180, type.engineOffset-1f), + (type.engineSize + Mathf.absin(Time.time(), 2f, type.engineSize/4f)) / 2f); + Draw.color(); + } + + @Override + public void behavior(){ + + if(Units.invalidateTarget(target, this)){ + for(boolean left : Mathf.booleans){ + int wi = Mathf.num(left); + weaponAngles[wi] = Mathf.slerpDelta(weaponAngles[wi],rotation, 0.1f); + } + } + } + + @Override + public UnitState getStartState(){ + return attack; + } + + protected void wobble(){ + if(Net.client()) return; + + x += Mathf.sin(Time.time() + id * 999, 25f, 0.05f)*Time.delta(); + y += Mathf.cos(Time.time() + id * 999, 25f, 0.05f)*Time.delta(); + + if(velocity.len() <= 0.05f){ + //rotation += Mathf.sin(Time.time() + id * 99, 10f, 2f * type.speed)*Time.delta(); + } + } + + protected void updateRotation(){ + rotation = velocity.angle(); + } + + protected void circle(float circleLength){ + circle(circleLength, type.speed); + } + + protected void circle(float circleLength, float speed){ + if(target == null) return; + + Tmp.v1.set(target.getX() - x, target.getY() - y); + + if(Tmp.v1.len() < circleLength){ + Tmp.v1.rotate((circleLength - Tmp.v1.len()) / circleLength * 180f); + } + + Tmp.v1.setLength(speed * Time.delta()); + + velocity.add(Tmp.v1); + } + + protected void moveTo(float circleLength){ + if(target == null) return; + + Tmp.v1.set(target.getX() - x, target.getY() - y); + + float length = circleLength <= 0.001f ? 1f : Mathf.clamp((dst(target) - circleLength) / 100f, -1f, 1f); + + Tmp.v1.setLength(type.speed * Time.delta() * length); + if(length < -0.5f){ + Tmp.v1.rotate(180f); + }else if(length < 0){ + Tmp.v1.setZero(); + } + + velocity.add(Tmp.v1); + } + + protected void attack(float circleLength){ + Tmp.v1.set(target.getX() - x, target.getY() - y); + + float ang = angleTo(target); + float diff = Angles.angleDist(ang, rotation); + + if(diff > 100f && Tmp.v1.len() < circleLength){ + Tmp.v1.setAngle(velocity.angle()); + }else{ + Tmp.v1.setAngle(Mathf.slerpDelta(velocity.angle(), Tmp.v1.angle(), 0.44f)); + } + + Tmp.v1.setLength(type.speed * Time.delta()); + + velocity.add(Tmp.v1); + } +} diff --git a/core/src/io/anuke/mindustry/entities/units/GroundUnit.java b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java similarity index 67% rename from core/src/io/anuke/mindustry/entities/units/GroundUnit.java rename to core/src/io/anuke/mindustry/entities/type/GroundUnit.java index ae278c9c36..985f551bc6 100644 --- a/core/src/io/anuke/mindustry/entities/units/GroundUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java @@ -1,4 +1,4 @@ -package io.anuke.mindustry.entities.units; +package io.anuke.mindustry.entities.type; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; @@ -8,21 +8,14 @@ import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Predict; -import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.bullet.BulletType; +import io.anuke.mindustry.entities.units.UnitState; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.graphics.Shaders; -import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Weapon; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.world; public abstract class GroundUnit extends BaseUnit{ @@ -31,7 +24,6 @@ public abstract class GroundUnit extends BaseUnit{ protected float walkTime; protected float stuckTime; protected float baseRotation; - protected Weapon weapon; public final UnitState @@ -42,13 +34,19 @@ public abstract class GroundUnit extends BaseUnit{ public void update(){ TileEntity core = getClosestEnemyCore(); - float dst = core == null ? 0 : dst(core); - if(core != null && dst < getWeapon().getAmmo().range() / 1.1f){ + if(core == null){ + setState(patrol); + return; + } + + float dst = dst(core); + + if(dst < getWeapon().bullet.range() / 1.1f){ target = core; } - if(dst > getWeapon().getAmmo().range() * 0.5f){ + if(dst > getWeapon().bullet.range() * 0.5f){ moveToCore(); } } @@ -64,27 +62,8 @@ public abstract class GroundUnit extends BaseUnit{ } } } - }, - retreat = new UnitState(){ - public void entered(){ - target = null; - } - - public void update(){ - if(health >= maxHealth()){ - state.set(attack); - } - - moveAwayFromCore(); - } }; - @Override - public void init(UnitType type, Team team){ - super.init(type, team); - this.weapon = type.weapon; - } - @Override public void interpolate(){ super.interpolate(); @@ -124,36 +103,32 @@ public abstract class GroundUnit extends BaseUnit{ @Override public Weapon getWeapon(){ - return weapon; - } - - public void setWeapon(Weapon weapon){ - this.weapon = weapon; + return type.weapon; } @Override public void draw(){ - Draw.alpha(Draw.getShader() != Shaders.mix ? 1f : hitTime / hitDuration); + Draw.mixcol(Color.WHITE, hitTime / hitDuration); - float ft = Mathf.sin(walkTime * type.speed*5f, 6f, 2f); + float ft = Mathf.sin(walkTime * type.speed*5f, 6f, 2f + type.hitsize/15f); Floor floor = getFloorOn(); if(floor.isLiquid){ - Draw.tint(Color.WHITE, floor.liquidColor, 0.5f); + Draw.color(Color.WHITE, floor.liquidColor, 0.5f); } for(int i : Mathf.signs){ Draw.rect(type.legRegion, x + Angles.trnsx(baseRotation, ft * i), y + Angles.trnsy(baseRotation, ft * i), - 12f * i, 12f - Mathf.clamp(ft * i, 0, 2), baseRotation - 90); + type.legRegion.getWidth() * i * Draw.scl, type.legRegion.getHeight() * Draw.scl - Mathf.clamp(ft * i, 0, 2), baseRotation - 90); } if(floor.isLiquid){ - Draw.tint(Color.WHITE, floor.liquidColor, drownTime * 0.4f); + Draw.color(Color.WHITE, floor.liquidColor, drownTime * 0.4f); }else{ - Draw.tint(Color.WHITE); + Draw.color(Color.WHITE); } Draw.rect(type.baseRegion, x, y, baseRotation - 90); @@ -161,30 +136,27 @@ public abstract class GroundUnit extends BaseUnit{ Draw.rect(type.region, x, y, rotation - 90); for(int i : Mathf.signs){ - float tra = rotation - 90, trY = -weapon.getRecoil(this, i > 0) + type.weaponOffsetY; - float w = i > 0 ? -12 : 12; - Draw.rect(weapon.equipRegion, - x + Angles.trnsx(tra, type.weaponOffsetX * i, trY), - y + Angles.trnsy(tra, type.weaponOffsetX * i, trY), w, 12, rotation - 90); + float tra = rotation - 90, trY = -type.weapon.getRecoil(this, i > 0) + type.weaponOffsetY; + float w = - i * type.weapon.region.getWidth() * Draw.scl; + Draw.rect(type.weapon.region, + x + Angles.trnsx(tra, getWeapon().width * i, trY), + y + Angles.trnsy(tra, getWeapon().width * i, trY), w, type.weapon.region.getHeight() * Draw.scl, rotation - 90); } drawItems(); - Draw.alpha(1f); + Draw.mixcol(); } @Override public void behavior(){ - if(health <= health * type.retreatPercent){ - setState(retreat); - } if(!Units.invalidateTarget(target, this)){ - if(dst(target) < getWeapon().getAmmo().range()){ + if(dst(target) < getWeapon().bullet.range()){ rotate(angleTo(target)); if(Angles.near(angleTo(target), rotation, 13f)){ - BulletType ammo = getWeapon().getAmmo(); + BulletType ammo = getWeapon().bullet; Vector2 to = Predict.intercept(GroundUnit.this, target, ammo.speed); @@ -205,32 +177,8 @@ public abstract class GroundUnit extends BaseUnit{ retarget(this::targetClosest); } - @Override - public void write(DataOutput data) throws IOException{ - super.write(data); - data.writeByte(weapon.id); - } - - @Override - public void read(DataInput data) throws IOException{ - super.read(data); - weapon = content.getByID(ContentType.weapon, data.readByte()); - } - - @Override - public void writeSave(DataOutput stream) throws IOException{ - stream.writeByte(weapon.id); - super.writeSave(stream); - } - - @Override - public void readSave(DataInput stream) throws IOException{ - weapon = content.getByID(ContentType.weapon, stream.readByte()); - super.readSave(stream); - } - protected void patrol(){ - vec.trns(baseRotation, type.speed * Time.delta()); + vec.trns(baseRotation, type.speed * Time.delta() * 2); velocity.add(vec.x, vec.y); vec.trns(baseRotation, type.hitsizeTile); Tile tile = world.tileWorld(x + vec.x, y + vec.y); diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/type/Player.java similarity index 78% rename from core/src/io/anuke/mindustry/entities/Player.java rename to core/src/io/anuke/mindustry/entities/type/Player.java index a1dbab0c41..a592a0ce85 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/type/Player.java @@ -1,12 +1,9 @@ -package io.anuke.mindustry.entities; +package io.anuke.mindustry.entities.type; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; import io.anuke.arc.collection.Queue; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.EntityQuery; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Angles; @@ -14,19 +11,18 @@ import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; -import io.anuke.arc.util.Align; -import io.anuke.arc.util.Interval; -import io.anuke.arc.util.Pack; -import io.anuke.arc.util.Time; +import io.anuke.arc.util.*; import io.anuke.arc.util.pooling.Pools; -import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.effect.ScorchDecal; -import io.anuke.mindustry.entities.traits.*; +import io.anuke.mindustry.content.Mechs; +import io.anuke.mindustry.entities.*; +import io.anuke.mindustry.entities.traits.BuilderTrait; +import io.anuke.mindustry.entities.traits.ShooterTrait; +import io.anuke.mindustry.entities.traits.SpawnerTrait; +import io.anuke.mindustry.entities.traits.TargetTrait; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.graphics.Shaders; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.io.TypeIO; import io.anuke.mindustry.net.Net; @@ -36,7 +32,6 @@ import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.mindustry.world.blocks.storage.CoreBlock.CoreEntity; import java.io.DataInput; import java.io.DataOutput; @@ -44,7 +39,7 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.*; -public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTrait{ +public class Player extends Unit implements BuilderTrait, ShooterTrait{ public static final int timerSync = 2; public static final int timerAbility = 3; private static final int timerShootLeft = 0; @@ -60,11 +55,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra public String name = "name"; public String uuid, usid; public boolean isAdmin, isTransferring, isShooting, isBoosting, isMobile; - public float boostHeat, shootHeat; + public float boostHeat, shootHeat, destructTime; public boolean achievedFlight; public Color color = new Color(); public Mech mech; - public int spawner = noSpawner; + public SpawnerTrait spawner, lastSpawner; public NetConnection con; public int playerIndex = 0; @@ -76,7 +71,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra private float walktime; private Queue placeQueue = new Queue<>(); private Tile mining; - private CarriableTrait carrying; private Vector2 movement = new Vector2(); private boolean moved; @@ -90,15 +84,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra player.dead = true; player.placeQueue.clear(); - - player.dropCarry(); - - float explosiveness = 2f + (player.inventory.hasItem() ? player.inventory.getItem().item.explosiveness * player.inventory.getItem().amount : 0f); - float flammability = (player.inventory.hasItem() ? player.inventory.getItem().item.flammability * player.inventory.getItem().amount : 0f); - Damage.dynamicExplosion(player.x, player.y, flammability, explosiveness, 0f, player.getSize() / 2f, Palette.darkFlame); - - ScorchDecal.create(player.x, player.y); player.onDeath(); + player.mech = (player.isMobile ? Mechs.starterMobile : Mechs.starterDesktop); } @Override @@ -129,11 +116,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra @Override public boolean collidesGrid(int x, int y){ Tile tile = world.tile(x, y); - if(!isFlying()) return true; - if(!mech.flying && tile != null && !tile.block().synthetic() && tile.block().solid){ - return true; - } - return false; + return !isFlying() || (!mech.flying && tile != null && !tile.block().synthetic() && tile.block().solid); } @Override @@ -184,21 +167,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra } } - @Override - public CarriableTrait getCarry(){ - return carrying; - } - - @Override - public void setCarry(CarriableTrait unit){ - this.carrying = unit; - } - - @Override - public float getCarryWeight(){ - return mech.carryWeight; - } - @Override public float getBuildPower(Tile tile){ return mech.buildPower; @@ -206,7 +174,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra @Override public float maxHealth(){ - return 200; + return mech.health; } @Override @@ -225,8 +193,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra } @Override - public float getArmor(){ - return mech.armor + mech.getExtraArmor(this); + public float calculateDamage(float amount){ + return amount * Mathf.clamp(1f - (status.getArmorMultiplier() + mech.getExtraArmor(this)) / 100f); } @Override @@ -241,12 +209,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra @Override public boolean isFlying(){ - return mech.flying || boostHeat > liftoffBoost || isCarried(); - } - - @Override - public float getSize(){ - return 8; + return mech.flying || boostHeat > liftoffBoost; } @Override @@ -282,16 +245,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra return "Player{" + id + ", mech=" + mech.name + ", local=" + isLocal + ", " + x + ", " + y + "}"; } - @Override - public void removed(){ - dropCarryLocal(); - - TileEntity core = getClosestCore(); - if(core != null && ((CoreEntity) core).currentUnit == this){ - ((CoreEntity) core).currentUnit = null; - } - } - @Override public EntityGroup targetGroup(){ return playerGroup; @@ -322,7 +275,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra if(dead) return; if(!movement.isZero() && moved && !state.isPaused()){ - walktime += movement.len() / 0.7f * getFloorOn().speedMultiplier; + walktime += movement.len() / 1f * getFloorOn().speedMultiplier; baseRotation = Mathf.slerpDelta(baseRotation, movement.angle(), 0.13f); } @@ -331,11 +284,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra Floor floor = getFloorOn(); Draw.color(); - Draw.alpha(Draw.getShader() != Shaders.mix ? 1f : hitTime / hitDuration); + Draw.mixcol(Color.WHITE, hitTime / hitDuration); if(!mech.flying){ if(floor.isLiquid){ - Draw.tint(Color.WHITE, floor.liquidColor, 0.5f); + Draw.color(Color.WHITE, floor.liquidColor, 0.5f); } float boostTrnsY = -boostHeat * 3f; @@ -355,9 +308,9 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra } if(floor.isLiquid){ - Draw.tint(Color.WHITE, floor.liquidColor, drownTime); + Draw.color(Color.WHITE, floor.liquidColor, drownTime); }else{ - Draw.tint(Color.WHITE); + Draw.color(Color.WHITE); } Draw.rect(mech.region, x, y, rotation - 90); @@ -366,37 +319,36 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra for(int i : Mathf.signs){ float tra = rotation - 90, trY = -mech.weapon.getRecoil(this, i > 0) + mech.weaponOffsetY; - float w = i > 0 ? -mech.weapon.equipRegion.getWidth() : mech.weapon.equipRegion.getWidth(); - Draw.rect(mech.weapon.equipRegion, + float w = i > 0 ? -mech.weapon.region.getWidth() : mech.weapon.region.getWidth(); + Draw.rect(mech.weapon.region, x + Angles.trnsx(tra, (mech.weaponOffsetX + mech.spreadX(this)) * i, trY), y + Angles.trnsy(tra, (mech.weaponOffsetX + mech.spreadX(this)) * i, trY), w * Draw.scl, - mech.weapon.equipRegion.getHeight() * Draw.scl, + mech.weapon.region.getHeight() * Draw.scl, rotation - 90); } - float backTrns = 4f, itemSize = 5f; - if(inventory.hasItem()){ - ItemStack stack = inventory.getItem(); + float backTrns = 4f; + if(item.amount > 0){ + ItemStack stack = item; int stored = Mathf.clamp(stack.amount / 6, 1, 8); for(int i = 0; i < stored; i++){ float angT = i == 0 ? 0 : Mathf.randomSeedRange(i + 1, 60f); float lenT = i == 0 ? 0 : Mathf.randomSeedRange(i + 2, 1f) - 1f; - Draw.rect(stack.item.region, + Draw.rect(stack.item.icon(Item.Icon.large), x + Angles.trnsx(rotation + 180f + angT, backTrns + lenT), y + Angles.trnsy(rotation + 180f + angT, backTrns + lenT), itemSize, itemSize, rotation); } } - Draw.alpha(1f); + Draw.reset(); } @Override public void drawStats(){ Draw.color(Color.BLACK, team.color, healthf() + Mathf.absin(Time.time(), healthf() * 5f, 1f - healthf())); - Draw.alpha(hitTime / hitDuration); Draw.rect(getPowerCellRegion(), x + Angles.trnsx(rotation, mech.cellTrnsY, 0f), y + Angles.trnsy(rotation, mech.cellTrnsY, 0f), rotation - 90); Draw.color(); } @@ -405,7 +357,22 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra public void drawOver(){ if(dead) return; - drawBuilding(this); + drawBuilding(); + } + + @Override + public void drawUnder(){ + if(dead) return; + + float size = mech.engineSize * (mech.flying ? 1f : boostHeat); + Draw.color(mech.engineColor); + Fill.circle(x + Angles.trnsx(rotation + 180, mech.engineOffset), y + Angles.trnsy(rotation + 180, mech.engineOffset), + size + Mathf.absin(Time.time(), 2f, size/4f)); + + Draw.color(Color.WHITE); + Fill.circle(x + Angles.trnsx(rotation + 180, mech.engineOffset-1f), y + Angles.trnsy(rotation + 180, mech.engineOffset-1f), + (size + Mathf.absin(Time.time(), 2f, size/4f)) / 2f); + Draw.color(); } public void drawName(){ @@ -434,19 +401,20 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra Draw.reset(); Pools.free(layout); font.getData().setScale(1f); + font.setColor(Color.WHITE); font.setUseIntegerPositions(ints); } /** Draw all current build requests. Does not draw the beam effect, only the positions. */ public void drawBuildRequests(){ for(BuildRequest request : getPlaceQueue()){ - if(getCurrentRequest() == request) continue; + if(getCurrentRequest() == request && request.progress > 0.001f) continue; if(request.breaking){ Block block = world.tile(request.x, request.y).target().block(); //draw removal request - Lines.stroke(2f, Palette.removeBack); + Lines.stroke(2f, Pal.removeBack); float rad = Mathf.absin(Time.time(), 7f, 1f) + block.size * tilesize / 2f - 1; Lines.square( @@ -454,7 +422,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra request.y * tilesize + block.offset() - 1, rad); - Draw.color(Palette.remove); + Draw.color(Pal.remove); Lines.square( request.x * tilesize + block.offset(), @@ -464,7 +432,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra float rad = Mathf.absin(Time.time(), 7f, 1f) - 1.5f + request.block.size * tilesize / 2f; //draw place request - Lines.stroke(1f, Palette.accentBack); + Lines.stroke(1f, Pal.accentBack); Lines.square( request.x * tilesize + request.block.offset(), @@ -475,10 +443,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra Draw.rect(request.block.icon(Icon.full), request.x * tilesize + request.block.offset(), - request.y * tilesize + request.block.offset(), rad*2, rad*2, request.rotation * 90); + request.y * tilesize + request.block.offset(), rad*2, rad*2, request.block.rotate ? request.rotation * 90 : 0); - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.square( request.x * tilesize + request.block.offset(), @@ -496,6 +464,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra @Override public void update(){ + hitTime -= Time.delta(); if(Float.isNaN(x) || Float.isNaN(y)){ @@ -509,13 +478,23 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra setDead(true); } + if(!isDead() && isOutOfBounds()){ + destructTime += Time.delta(); + + if(destructTime >= boundsCountdown){ + kill(); + } + }else{ + destructTime = 0f; + } + if(isDead()){ isBoosting = false; boostHeat = 0f; updateRespawning(); return; }else{ - spawner = noSpawner; + spawner = null; } avoidOthers(1f); @@ -535,7 +514,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra if(mech.shake > 1f){ Effects.shake(mech.shake, mech.shake, this); } - Effects.effect(Fx.unitLand, tile.floor().minimapColor, x, y, tile.floor().isLiquid ? 1f : 0.5f); + Effects.effect(Fx.unitLand, tile.floor().liquidColor == null ? tile.floor().color : tile.floor().color, x, y, tile.floor().isLiquid ? 1f : 0.5f); } mech.onLand(this); achievedFlight = false; @@ -543,15 +522,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra if(!isLocal){ interpolate(); - updateBuilding(this); //building happens even with non-locals + updateBuilding(); //building happens even with non-locals status.update(this); //status effect updating also happens with non locals for effect purposes updateVelocityStatus(); //velocity too, for visual purposes - if(getCarrier() != null){ - x = getCarrier().getX(); - y = getCarrier().getY(); - } - if(Net.server()){ updateShooting(); //server simulates player shooting } @@ -567,10 +541,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra updateMech(); } - updateBuilding(this); + updateBuilding(); - x = Mathf.clamp(x, 0, world.width() * tilesize - tilesize); - y = Mathf.clamp(y, 0, world.height() * tilesize - tilesize); + if(!mech.flying){ + clampPosition(); + } } protected void updateMech(){ @@ -584,10 +559,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra } float speed = isBoosting && !mech.flying ? mech.boostSpeed : mech.speed; - //fraction of speed when at max load - float carrySlowdown = 0.7f; - - speed *= ((inventory.hasItem() ? Mathf.lerp(1f, carrySlowdown, (float) inventory.getItem().amount / inventory.capacity()) : 1f)); if(mech.flying){ //prevent strafing backwards, have a penalty for doing so @@ -595,23 +566,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra speed *= Mathf.lerp(1f, penalty, Angles.angleDist(rotation, velocity.angle()) / 180f); } - //drop from carrier on key press - if(!ui.chatfrag.chatOpen() && Core.input.keyTap(Binding.drop_unit)){ - if(!mech.flying){ - if(getCarrier() != null){ - Call.dropSelf(this); - } - }else if(getCarry() != null){ - dropCarry(); - }else{ - Unit unit = Units.getClosest(team, x, y, 8f, u -> !u.isFlying() && u.mass() <= mech.carryWeight); - - if(unit != null){ - carry(unit); - } - } - } - movement.setZero(); float xa = Core.input.axis(Binding.move_x); @@ -628,18 +582,12 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra movement.limit(speed).scl(Time.delta()); - if(getCarrier() == null){ - if(!ui.chatfrag.chatOpen()){ - velocity.add(movement.x, movement.y); - } - float prex = x, prey = y; - updateVelocityStatus(); - moved = dst(prex, prey) > 0.001f; - }else{ - velocity.setZero(); - x = Mathf.lerpDelta(x, getCarrier().getX(), 0.1f); - y = Mathf.lerpDelta(y, getCarrier().getY(), 0.1f); + if(!ui.chatfrag.chatOpen()){ + velocity.add(movement.x, movement.y); } + float prex = x, prey = y; + updateVelocityStatus(); + moved = dst(prex, prey) > 0.001f; if(!ui.chatfrag.chatOpen()){ float baseLerp = mech.getRotationAlpha(this); @@ -662,7 +610,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra protected void updateFlying(){ if(Units.invalidateTarget(target, this) && !(target instanceof TileEntity && ((TileEntity) target).damaged() && target.getTeam() == team && - mech.canHeal && dst(target) < getWeapon().getAmmo().range())){ + mech.canHeal && dst(target) < getWeapon().bullet.range())){ target = null; } @@ -680,9 +628,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra } if(dst(moveTarget) < 2f){ - if(moveTarget instanceof CarriableTrait){ - carry((CarriableTrait) moveTarget); - }else if(tapping){ + if(tapping){ Tile tile = ((TileEntity) moveTarget).tile; tile.block().tapped(tile, this); } @@ -693,12 +639,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra moveTarget = null; } - if(getCarrier() != null){ - velocity.setZero(); - x = Mathf.lerpDelta(x, getCarrier().getX(), 0.1f); - y = Mathf.lerpDelta(y, getCarrier().getY(), 0.1f); - } - movement.set(targetX - x, targetY - y).limit(isBoosting && !mech.flying ? mech.boostSpeed : mech.speed); movement.setAngle(Mathf.slerp(movement.angle(), velocity.angle(), 0.05f)); @@ -726,7 +666,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra float lx = x, ly = y; updateVelocityStatus(); - moved = dst(lx, ly) > 0.001f && !isCarried(); + moved = dst(lx, ly) > 0.001f; if(mech.flying){ //hovering effect @@ -742,11 +682,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra if(target == null){ isShooting = false; if(Core.settings.getBool("autotarget")){ - target = Units.getClosestTarget(team, x, y, getWeapon().getAmmo().range()); + target = Units.getClosestTarget(team, x, y, getWeapon().bullet.range(), u -> u.getTeam() != Team.none, u -> u.getTeam() != Team.none); if(mech.canHeal && target == null){ target = Geometry.findClosest(x, y, world.indexer.getDamaged(Team.blue)); - if(target != null && dst(target) > getWeapon().getAmmo().range()){ + if(target != null && dst(target) > getWeapon().bullet.range()){ target = null; }else if(target != null){ target = ((Tile) target).entity; @@ -758,14 +698,14 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra } } }else if(target.isValid() || (target instanceof TileEntity && ((TileEntity) target).damaged() && target.getTeam() == team && - mech.canHeal && dst(target) < getWeapon().getAmmo().range())){ + mech.canHeal && dst(target) < getWeapon().bullet.range())){ //rotate toward and shoot the target if(mech.turnCursor){ rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.2f); } Vector2 intercept = - Predict.intercept(x, y, target.getX(), target.getY(), target.velocity().x - velocity.x, target.velocity().y - velocity.y, getWeapon().getAmmo().speed); + Predict.intercept(x, y, target.getX(), target.getY(), target.velocity().x - velocity.x, target.velocity().y - velocity.y, getWeapon().bullet.speed); pointerX = intercept.x; pointerY = intercept.y; @@ -799,12 +739,12 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra public void resetNoAdd(){ status.clear(); team = Team.blue; - inventory.clear(); + item.amount = 0; placeQueue.clear(); dead = true; target = null; moveTarget = null; - carrier = null; + spawner = lastSpawner = null; health = maxHealth(); boostHeat = drownTime = hitTime = 0f; mech = (isMobile ? Mechs.starterMobile : Mechs.starterDesktop); @@ -817,23 +757,27 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra public void updateRespawning(){ - if(spawner != noSpawner && world.tile(spawner) != null && world.tile(spawner).entity instanceof SpawnerTrait){ - ((SpawnerTrait) world.tile(spawner).entity).updateSpawning(this); - }else{ - CoreEntity entity = (CoreEntity) getClosestCore(); - if(entity != null && !netServer.isWaitingForPlayers()){ - this.spawner = entity.tile.pos(); + if(spawner != null && spawner.isValid()){ + spawner.updateSpawning(this); + }else if(!netServer.isWaitingForPlayers()){ + if(lastSpawner != null && lastSpawner.isValid()){ + this.spawner = lastSpawner; + }else if(getClosestCore() != null){ + this.spawner = (SpawnerTrait)getClosestCore(); } + }else if(getClosestCore() != null){ + set(getClosestCore().getX(), getClosestCore().getY()); } } public void beginRespawning(SpawnerTrait spawner){ - this.spawner = spawner.getTile().pos(); + this.spawner = spawner; + this.lastSpawner = spawner; this.dead = true; } public void endRespawning(){ - spawner = noSpawner; + spawner = null; } //endregion @@ -853,6 +797,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra if(isLocal){ stream.writeByte(mech.id); stream.writeByte(playerIndex); + stream.writeInt(lastSpawner == null ? noSpawner : lastSpawner.getTile().pos()); super.writeSave(stream, false); } } @@ -864,12 +809,17 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra if(local && !headless){ byte mechid = stream.readByte(); int index = stream.readByte(); + int spawner = stream.readInt(); + if(world.tile(spawner) != null && world.tile(spawner).entity != null && world.tile(spawner).entity instanceof SpawnerTrait){ + lastSpawner = (SpawnerTrait)(world.tile(spawner).entity); + } players[index].readSaveSuper(stream); players[index].mech = content.getByID(ContentType.mech, mechid); players[index].dead = false; }else if(local){ byte mechid = stream.readByte(); stream.readByte(); + stream.readInt(); readSaveSuper(stream); mech = content.getByID(ContentType.mech, mechid); dead = false; @@ -889,8 +839,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra buffer.writeByte(Pack.byteValue(isAdmin) | (Pack.byteValue(dead) << 1) | (Pack.byteValue(isBoosting) << 2)); buffer.writeInt(Color.rgba8888(color)); buffer.writeByte(mech.id); - buffer.writeInt(mining == null ? -1 : mining.pos()); - buffer.writeInt(spawner); + buffer.writeInt(mining == null ? noSpawner : mining.pos()); + buffer.writeInt(spawner == null ? noSpawner : spawner.getTile().pos()); buffer.writeShort((short) (baseRotation * 2)); writeBuilding(buffer); @@ -898,7 +848,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra @Override public void read(DataInput buffer) throws IOException{ - float lastx = x, lasty = y, lastrot = rotation; + float lastx = x, lasty = y, lastrot = rotation, lastvx = velocity.x, lastvy = velocity.y; super.readSave(buffer); name = TypeIO.readStringData(buffer); byte bools = buffer.readByte(); @@ -919,10 +869,17 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra if(isLocal){ x = lastx; y = lasty; + velocity.x = lastvx; + velocity.y = lastvy; }else{ mining = world.tile(mine); isBoosting = boosting; - this.spawner = spawner; + Tile tile = world.tile(spawner); + if(tile != null && tile.entity instanceof SpawnerTrait){ + this.spawner = (SpawnerTrait)tile.entity; + }else{ + this.spawner = null; + } } } diff --git a/core/src/io/anuke/mindustry/entities/TileEntity.java b/core/src/io/anuke/mindustry/entities/type/TileEntity.java similarity index 92% rename from core/src/io/anuke/mindustry/entities/TileEntity.java rename to core/src/io/anuke/mindustry/entities/type/TileEntity.java index 97fd2beb9c..fa302ada5f 100644 --- a/core/src/io/anuke/mindustry/entities/TileEntity.java +++ b/core/src/io/anuke/mindustry/entities/type/TileEntity.java @@ -1,14 +1,14 @@ -package io.anuke.mindustry.entities; +package io.anuke.mindustry.entities.type; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Events; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectSet; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.impl.BaseEntity; -import io.anuke.arc.entities.trait.HealthTrait; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.impl.BaseEntity; +import io.anuke.mindustry.entities.traits.HealthTrait; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Point2; import io.anuke.arc.math.geom.Vector2; @@ -59,7 +59,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ private boolean sleeping; private float sleepTime; - @Remote(called = Loc.server) + @Remote(called = Loc.server, unreliable = true) public static void onTileDamage(Tile tile, float health){ if(tile.entity != null){ tile.entity.health = health; @@ -151,7 +151,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ if(health <= 0){ Call.onTileDestroyed(tile); - }else if(preHealth >= maxHealth() - 0.00001f && health < maxHealth()){ //when just damaged + }else if(preHealth >= maxHealth() - 0.00001f && health < maxHealth() && world != null){ //when just damaged world.indexer.notifyTileDamaged(this); } } @@ -195,7 +195,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ if(other == null) continue; other = other.target(); - if(other.entity == null || other.getTeamID() != tile.getTeamID()) continue; + if(other.entity == null || !(other.interactable(tile.getTeam()))) continue; other.block().onProximityUpdate(other); @@ -283,7 +283,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ Block previous = tile.block(); tile.block().update(tile); if(tile.block() == previous && cons != null){ - cons.update(this); + cons.update(); } } @@ -291,4 +291,12 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ public EntityGroup targetGroup(){ return tileGroup; } + + @Override + public String toString(){ + return "TileEntity{" + + "tile=" + tile + + ", health=" + health + + '}'; + } } diff --git a/core/src/io/anuke/mindustry/entities/Unit.java b/core/src/io/anuke/mindustry/entities/type/Unit.java similarity index 75% rename from core/src/io/anuke/mindustry/entities/Unit.java rename to core/src/io/anuke/mindustry/entities/type/Unit.java index 8ee287a454..2312d36612 100644 --- a/core/src/io/anuke/mindustry/entities/Unit.java +++ b/core/src/io/anuke/mindustry/entities/type/Unit.java @@ -1,28 +1,33 @@ -package io.anuke.mindustry.entities; +package io.anuke.mindustry.entities.type; import io.anuke.arc.Core; import io.anuke.arc.Events; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.impl.DestructibleEntity; -import io.anuke.arc.entities.trait.DamageTrait; -import io.anuke.arc.entities.trait.DrawTrait; -import io.anuke.arc.entities.trait.SolidTrait; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Fill; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; +import io.anuke.arc.util.Tmp; import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Damage; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Units; +import io.anuke.mindustry.entities.effect.ScorchDecal; +import io.anuke.mindustry.entities.impl.DestructibleEntity; import io.anuke.mindustry.entities.traits.*; +import io.anuke.mindustry.entities.units.Statuses; import io.anuke.mindustry.game.EventType.UnitDestroyEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Teams.TeamData; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.net.Interpolator; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.StatusEffect; import io.anuke.mindustry.type.Weapon; import io.anuke.mindustry.world.Pos; @@ -33,10 +38,9 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import static io.anuke.mindustry.Vars.state; -import static io.anuke.mindustry.Vars.world; +import static io.anuke.mindustry.Vars.*; -public abstract class Unit extends DestructibleEntity implements SaveTrait, TargetTrait, SyncTrait, DrawTrait, TeamTrait, CarriableTrait, InventoryTrait{ +public abstract class Unit extends DestructibleEntity implements SaveTrait, TargetTrait, SyncTrait, DrawTrait, TeamTrait{ /**Total duration of hit flash effect*/ public static final float hitDuration = 9f; /**Percision divisor of velocity, used when writing. For example a value of '2' would mean the percision is 1/2 = 0.5-size chunks.*/ @@ -48,42 +52,25 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ private static final Rectangle queryRect = new Rectangle(); private static final Vector2 moveVector = new Vector2(); - public final UnitInventory inventory = new UnitInventory(this); public float rotation; - public float hitTime; protected final Interpolator interpolator = new Interpolator(); - protected final StatusController status = new StatusController(); - protected Team team = Team.blue; + protected final Statuses status = new Statuses(); + protected final ItemStack item = new ItemStack(content.item(0), 0); - protected CarryTrait carrier; - protected float drownTime; + protected Team team = Team.blue; + protected float drownTime, hitTime; @Override public boolean movable(){ return !isDead(); } - @Override - public UnitInventory getInventory(){ - return inventory; - } - - @Override - public CarryTrait getCarrier(){ - return carrier; - } - @Override public boolean collidesGrid(int x, int y){ return !isFlying(); } - @Override - public void setCarrier(CarryTrait carrier){ - this.carrier = carrier; - } - @Override public Team getTeam(){ return team; @@ -125,7 +112,15 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ @Override public void onDeath(){ - inventory.clear(); + float explosiveness = 2f + item.item.explosiveness * item.amount; + float flammability = item.item.flammability * item.amount; + Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, getSize() / 2f, Pal.darkFlame); + + ScorchDecal.create(x, y); + Effects.effect(Fx.explosion, this); + Effects.shake(2f, 2f, this); + + item.amount = 0; drownTime = 0f; status.clear(); Events.fire(new UnitDestroyEvent(this)); @@ -145,6 +140,11 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } } + @Override + public boolean isValid(){ + return !isDead() && isAdded(); + } + @Override public void writeSave(DataOutput stream) throws IOException{ writeSave(stream, false); @@ -160,9 +160,12 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ byte yv = stream.readByte(); float rotation = stream.readShort() / 2f; int health = stream.readShort(); + byte itemID = stream.readByte(); + short itemAmount = stream.readShort(); this.status.readSave(stream); - this.inventory.readSave(stream); + this.item.amount = itemAmount; + this.item.item = content.item(itemID); this.dead = dead; this.team = Team.all[team]; this.health = health; @@ -181,12 +184,31 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ stream.writeByte((byte) (Mathf.clamp(velocity.y, -maxAbsVelocity, maxAbsVelocity) * velocityPercision)); stream.writeShort((short) (rotation * 2)); stream.writeShort((short) health); + stream.writeByte(item.item.id); + stream.writeShort((short)item.amount); status.writeSave(stream); - inventory.writeSave(stream); + } + + protected void clampPosition(){ + x = Mathf.clamp(x, tilesize, world.width() * tilesize - tilesize); + y = Mathf.clamp(y, tilesize, world.height() * tilesize - tilesize); + } + + public void kill(){ + health = -1; + damage(1); + } + + public boolean isImmune(StatusEffect effect){ + return false; + } + + public boolean isOutOfBounds(){ + return x < -worldBounds || y < -worldBounds || x > world.width() * tilesize + worldBounds || y > world.height() * tilesize + worldBounds; } public float calculateDamage(float amount){ - return amount * Mathf.clamp(1f - getArmor() / 100f * status.getArmorMultiplier()); + return amount * Mathf.clamp(1f - status.getArmorMultiplier() / 100f); } public float getDamageMultipler(){ @@ -197,12 +219,13 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ return status.hasEffect(effect); } + //TODO optimize public void avoidOthers(float scaling){ hitbox(queryRect); queryRect.setSize(queryRect.getWidth() * scaling); Units.getNearby(queryRect, t -> { - if(t == this || t.getCarrier() == this || getCarrier() == t || t.isFlying() != isFlying()) return; + if(t == this || t.isFlying() != isFlying()) return; float dst = dst(t); moveVector.set(x, y).sub(t.getX(), t.getY()).setLength(1f * (1f - (dst / queryRect.getWidth()))); applyImpulse(moveVector.x, moveVector.y); @@ -227,28 +250,22 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ public void onRespawn(Tile tile){} - @Override - public boolean isValid(){ - return !isDead() && isAdded(); - } - /**Updates velocity and status effects.*/ public void updateVelocityStatus(){ Floor floor = getFloorOn(); - if(isCarried()){ //carried units do not take into account velocity normally - set(carrier.getX(), carrier.getY()); - velocity.set(carrier.velocity()); - return; - } - Tile tile = world.tileWorld(x, y); status.update(this); velocity.limit(maxVelocity()).scl(1f + (status.getSpeedMultiplier()-1f) * Time.delta()); + if(x < -finalWorldBounds || y < -finalWorldBounds || x >= world.width() * tilesize + finalWorldBounds || y >= world.height() * tilesize + finalWorldBounds){ + kill(); + } + if(isFlying()){ + drownTime = 0f; move(velocity.x * Time.delta(), velocity.y * Time.delta()); }else{ boolean onLiquid = floor.isLiquid; @@ -296,6 +313,31 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ velocity.scl(Mathf.clamp(1f - drag() * (isFlying() ? 1f : floor.dragMultiplier) * Time.delta())); } + public boolean acceptsItem(Item item){ + return this.item.amount <= 0 || (this.item.item == item && this.item.amount <= getItemCapacity()); + } + + public void addItem(Item item){ + addItem(item, 1); + } + + public void addItem(Item item, int amount){ + this.item.amount = this.item.item == item ? this.item.amount + amount : amount; + this.item.item = item; + } + + public void clearItem(){ + item.amount = 0; + } + + public ItemStack item(){ + return item; + } + + public int maxAccepted(Item item){ + return this.item.item != item && this.item.amount > 0 ? 0 : getItemCapacity() - this.item.amount; + } + public void applyEffect(StatusEffect effect, float duration){ if(dead || Net.client()) return; //effects are synced and thus not applied through clients status.handleApply(this, effect, duration); @@ -323,7 +365,6 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ public void drawStats(){ Draw.color(Color.BLACK, team.color, healthf() + Mathf.absin(Time.time(), healthf()*5f, 1f - healthf())); - Draw.alpha(hitTime); Draw.rect(getPowerCellRegion(), x, y, rotation - 90); Draw.color(); } @@ -343,12 +384,9 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ Draw.rect(getIconRegion(), x + offsetX, y + offsetY, rotation - 90); } - public void drawView(){ - Fill.circle(x, y, getViewDistance()); - } - - public float getViewDistance(){ - return 135f; + public float getSize(){ + hitbox(Tmp.r1); + return Math.max(Tmp.r1.width, Tmp.r1.height) * 2f; } public abstract TextureRegion getIconRegion(); @@ -357,11 +395,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ public abstract int getItemCapacity(); - public abstract float getArmor(); - public abstract float mass(); public abstract boolean isFlying(); - - public abstract float getSize(); } diff --git a/core/src/io/anuke/mindustry/entities/type/base/Crawler.java b/core/src/io/anuke/mindustry/entities/type/base/Crawler.java new file mode 100644 index 0000000000..f3c12c9604 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/Crawler.java @@ -0,0 +1,6 @@ +package io.anuke.mindustry.entities.type.base; + +import io.anuke.mindustry.entities.type.GroundUnit; + +public class Crawler extends GroundUnit{ +} diff --git a/core/src/io/anuke/mindustry/entities/type/base/Dagger.java b/core/src/io/anuke/mindustry/entities/type/base/Dagger.java new file mode 100644 index 0000000000..13bf6021c9 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/Dagger.java @@ -0,0 +1,7 @@ +package io.anuke.mindustry.entities.type.base; + +import io.anuke.mindustry.entities.type.GroundUnit; + +public class Dagger extends GroundUnit{ + +} diff --git a/core/src/io/anuke/mindustry/entities/units/types/Drone.java b/core/src/io/anuke/mindustry/entities/type/base/Drone.java similarity index 91% rename from core/src/io/anuke/mindustry/entities/units/types/Drone.java rename to core/src/io/anuke/mindustry/entities/type/base/Drone.java index 6a7306b950..384d302d84 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Drone.java +++ b/core/src/io/anuke/mindustry/entities/type/base/Drone.java @@ -1,18 +1,18 @@ -package io.anuke.mindustry.entities.units.types; +package io.anuke.mindustry.entities.type.base; import io.anuke.arc.Events; import io.anuke.arc.collection.Queue; -import io.anuke.arc.entities.EntityGroup; +import io.anuke.mindustry.entities.EntityGroup; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.util.Structs; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.BuilderTrait; -import io.anuke.mindustry.entities.units.BaseUnit; -import io.anuke.mindustry.entities.units.FlyingUnit; +import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.entities.type.FlyingUnit; import io.anuke.mindustry.entities.units.UnitState; import io.anuke.mindustry.game.EventType.BuildSelectEvent; import io.anuke.mindustry.gen.Call; @@ -32,8 +32,6 @@ import static io.anuke.mindustry.Vars.unitGroups; import static io.anuke.mindustry.Vars.world; public class Drone extends FlyingUnit implements BuilderTrait{ - protected static int timerRepairEffect = timerIndex++; - protected Item targetItem; protected Tile mineTile; protected Queue placeQueue = new Queue<>(); @@ -135,10 +133,10 @@ public class Drone extends FlyingUnit implements BuilderTrait{ } //if inventory is full, drop it off. - if(inventory.isFull()){ + if(item.amount >= getItemCapacity()){ setState(drop); }else{ - if(targetItem != null && !inventory.canAcceptItem(targetItem)){ + if(targetItem != null && !acceptsItem(targetItem)){ setState(drop); return; } @@ -177,13 +175,13 @@ public class Drone extends FlyingUnit implements BuilderTrait{ } public void update(){ - if(inventory.isEmpty()){ + if(item.amount == 0){ setState(mine); return; } - if(inventory.getItem().item.type != ItemType.material){ - inventory.clearItem(); + if(item.item.type != ItemType.material){ + item.amount = 0; setState(mine); return; } @@ -195,9 +193,9 @@ public class Drone extends FlyingUnit implements BuilderTrait{ TileEntity tile = (TileEntity) target; if(dst(target) < type.range){ - if(tile.tile.block().acceptStack(inventory.getItem().item, inventory.getItem().amount, tile.tile, Drone.this) == inventory.getItem().amount){ - Call.transferItemTo(inventory.getItem().item, inventory.getItem().amount, x, y, tile.tile); - inventory.clearItem(); + if(tile.tile.block().acceptStack(item.item, item.amount, tile.tile, Drone.this) == item.amount){ + Call.transferItemTo(item.item, item.amount, x, y, tile.tile); + item.amount = 0; } setState(repair); @@ -299,7 +297,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ target = null; } - updateBuilding(this); + updateBuilding(); } @Override @@ -326,7 +324,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ @Override public void drawOver(){ - drawBuilding(this); + drawBuilding(); } @Override diff --git a/core/src/io/anuke/mindustry/entities/type/base/Eruptor.java b/core/src/io/anuke/mindustry/entities/type/base/Eruptor.java new file mode 100644 index 0000000000..dfbfe9db39 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/Eruptor.java @@ -0,0 +1,6 @@ +package io.anuke.mindustry.entities.type.base; + +import io.anuke.mindustry.entities.type.GroundUnit; + +public class Eruptor extends GroundUnit{ +} diff --git a/core/src/io/anuke/mindustry/entities/units/types/Fortress.java b/core/src/io/anuke/mindustry/entities/type/base/Fortress.java similarity index 78% rename from core/src/io/anuke/mindustry/entities/units/types/Fortress.java rename to core/src/io/anuke/mindustry/entities/type/base/Fortress.java index c39e356586..06033fcf66 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Fortress.java +++ b/core/src/io/anuke/mindustry/entities/type/base/Fortress.java @@ -1,7 +1,7 @@ -package io.anuke.mindustry.entities.units.types; +package io.anuke.mindustry.entities.type.base; import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.entities.units.GroundUnit; +import io.anuke.mindustry.entities.type.GroundUnit; public class Fortress extends GroundUnit{ diff --git a/core/src/io/anuke/mindustry/entities/type/base/Ghoul.java b/core/src/io/anuke/mindustry/entities/type/base/Ghoul.java new file mode 100644 index 0000000000..bc1f6a5317 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/Ghoul.java @@ -0,0 +1,7 @@ +package io.anuke.mindustry.entities.type.base; + +import io.anuke.mindustry.entities.type.FlyingUnit; + +public class Ghoul extends FlyingUnit{ + +} diff --git a/core/src/io/anuke/mindustry/entities/type/base/Phantom.java b/core/src/io/anuke/mindustry/entities/type/base/Phantom.java new file mode 100644 index 0000000000..516d305b94 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/Phantom.java @@ -0,0 +1,5 @@ +package io.anuke.mindustry.entities.type.base; + +public class Phantom extends Drone{ + +} diff --git a/core/src/io/anuke/mindustry/entities/type/base/Revenant.java b/core/src/io/anuke/mindustry/entities/type/base/Revenant.java new file mode 100644 index 0000000000..9f3c5f2c6e --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/Revenant.java @@ -0,0 +1,35 @@ +package io.anuke.mindustry.entities.type.base; + +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.math.Angles; +import io.anuke.arc.math.Mathf; +import io.anuke.mindustry.entities.Units; +import io.anuke.mindustry.entities.type.FlyingUnit; + +public class Revenant extends FlyingUnit{ + + @Override + public void drawWeapons(){ + for(int i : Mathf.signs){ + float tra = rotation - 90, trY = -getWeapon().getRecoil(this, i > 0) + type.weaponOffsetY; + float w = i > 0 ? -12 : 12; + float wx = x + Angles.trnsx(tra, getWeapon().width * i, trY), wy = y + Angles.trnsy(tra, getWeapon().width * i, trY); + int wi = (i + 1)/2; + Draw.rect(getWeapon().region, wx, wy, w, 12, weaponAngles[wi] - 90); + } + } + + @Override + protected void attack(float circleLength){ + moveTo(circleLength); + } + + @Override + protected void updateRotation(){ + if(!Units.invalidateTarget(target, this)){ + rotation = Mathf.slerpDelta(rotation, angleTo(target), type.rotatespeed); + }else{ + rotation = Mathf.slerpDelta(rotation, velocity.angle(), type.baseRotateSpeed); + } + } +} diff --git a/core/src/io/anuke/mindustry/entities/type/base/Spirit.java b/core/src/io/anuke/mindustry/entities/type/base/Spirit.java new file mode 100644 index 0000000000..f7142e8d6d --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/Spirit.java @@ -0,0 +1,4 @@ +package io.anuke.mindustry.entities.type.base; + +public class Spirit extends Drone{ +} diff --git a/core/src/io/anuke/mindustry/entities/type/base/Titan.java b/core/src/io/anuke/mindustry/entities/type/base/Titan.java new file mode 100644 index 0000000000..1ac30593ac --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/Titan.java @@ -0,0 +1,7 @@ +package io.anuke.mindustry.entities.type.base; + +import io.anuke.mindustry.entities.type.GroundUnit; + +public class Titan extends GroundUnit{ + +} diff --git a/core/src/io/anuke/mindustry/entities/type/base/Wraith.java b/core/src/io/anuke/mindustry/entities/type/base/Wraith.java new file mode 100644 index 0000000000..9123ffcb8d --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/Wraith.java @@ -0,0 +1,7 @@ +package io.anuke.mindustry.entities.type.base; + +import io.anuke.mindustry.entities.type.FlyingUnit; + +public class Wraith extends FlyingUnit{ + +} diff --git a/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java b/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java deleted file mode 100644 index fe1ecd0ff7..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java +++ /dev/null @@ -1,249 +0,0 @@ -package io.anuke.mindustry.entities.units; - -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.math.Angles; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Vector2; -import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.Predict; -import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.entities.bullet.BulletType; -import io.anuke.mindustry.entities.traits.CarriableTrait; -import io.anuke.mindustry.entities.traits.CarryTrait; -import io.anuke.mindustry.graphics.Shaders; -import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockFlag; - -import static io.anuke.mindustry.Vars.world; - -public abstract class FlyingUnit extends BaseUnit implements CarryTrait{ - protected static Vector2 vec = new Vector2(); - - protected CarriableTrait carrying; - protected final UnitState - - idle = new UnitState(){ - public void update(){ - retarget(() -> { - targetClosest(); - targetClosestEnemyFlag(BlockFlag.target); - - if(target != null){ - setState(attack); - } - }); - - target = getClosestCore(); - if(target != null){ - circle(50f); - } - velocity.scl(0.8f); - } - }, - - attack = new UnitState(){ - public void entered(){ - target = null; - } - - public void update(){ - if(Units.invalidateTarget(target, team, x, y)){ - target = null; - } - - if(target == null){ - retarget(() -> { - targetClosest(); - - if(target == null){ - setState(patrol); - return; - } - - if(target == null) targetClosestEnemyFlag(BlockFlag.target); - if(target == null) targetClosestEnemyFlag(BlockFlag.producer); - if(target == null) targetClosestEnemyFlag(BlockFlag.turret); - - if(target == null){ - setState(idle); - } - }); - }else{ - attack(150f); - - if((Angles.near(angleTo(target), rotation, 15f) || !getWeapon().getAmmo().keepVelocity) //bombers don't care about rotation - && dst(target) < Math.max(getWeapon().getAmmo().range(), type.range)){ - BulletType ammo = getWeapon().getAmmo(); - - Vector2 to = Predict.intercept(FlyingUnit.this, target, ammo.speed); - - getWeapon().update(FlyingUnit.this, to.x, to.y); - } - } - } - }, - patrol = new UnitState(){ - public void update(){ - retarget(() -> { - targetClosest(); - - if(target != null){ - setState(attack); - } - - target = getClosestCore(); - }); - - if(target != null){ - circle(60f + Mathf.absin(Time.time() + id * 23525, 70f, 1200f)); - } - } - }, - retreat = new UnitState(){ - public void entered(){ - target = null; - } - - public void update(){ - if(health >= maxHealth()){ - state.set(attack); - }else if(!targetHasFlag(BlockFlag.repair)){ - retarget(() -> { - Tile target = Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair)); - if(target != null) FlyingUnit.this.target = target.entity; - }); - }else{ - circle(20f); - } - } - }; - - @Override - public void move(float x, float y){ - moveBy(x, y); - } - - @Override - public CarriableTrait getCarry(){ - return carrying; - } - - @Override - public void setCarry(CarriableTrait unit){ - this.carrying = unit; - } - - @Override - public float getCarryWeight(){ - return type.carryWeight; - } - - @Override - public void update(){ - super.update(); - - if(!Net.client()){ - updateRotation(); - wobble(); - } - } - - @Override - public void draw(){ - Draw.alpha(Draw.getShader() != Shaders.mix ? 1f : hitTime / hitDuration); - - Draw.rect(type.name, x, y, rotation - 90); - - drawItems(); - - Draw.alpha(1f); - } - - @Override - public void behavior(){ - if(health <= health * type.retreatPercent && - Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair)) != null){ - setState(retreat); - } - - if(squad != null){ - squad.direction.add(velocity.x / squad.units, velocity.y / squad.units); - velocity.setAngle(Mathf.slerpDelta(velocity.angle(), squad.direction.angle(), 0.3f)); - } - } - - @Override - public UnitState getStartState(){ - return attack; - } - - @Override - public float drawSize(){ - return 60; - } - - protected void wobble(){ - if(Net.client()) return; - - x += Mathf.sin(Time.time() + id * 999, 25f, 0.08f)*Time.delta(); - y += Mathf.cos(Time.time() + id * 999, 25f, 0.08f)*Time.delta(); - - if(velocity.len() <= 0.05f){ - rotation += Mathf.sin(Time.time() + id * 99, 10f, 2.5f)*Time.delta(); - } - } - - protected void updateRotation(){ - rotation = velocity.angle(); - } - - protected void circle(float circleLength){ - circle(circleLength, type.speed); - } - - protected void circle(float circleLength, float speed){ - if(target == null) return; - - vec.set(target.getX() - x, target.getY() - y); - - if(vec.len() < circleLength){ - vec.rotate((circleLength - vec.len()) / circleLength * 180f); - } - - vec.setLength(speed * Time.delta()); - - velocity.add(vec); - } - - protected void moveTo(float circleLength){ - if(target == null) return; - - vec.set(target.getX() - x, target.getY() - y); - - float length = circleLength <= 0.001f ? 1f : Mathf.clamp((dst(target) - circleLength) / 100f, -1f, 1f); - - vec.setLength(type.speed * Time.delta() * length); - if(length < 0) vec.rotate(180f); - - velocity.add(vec); - } - - protected void attack(float circleLength){ - vec.set(target.getX() - x, target.getY() - y); - - float ang = angleTo(target); - float diff = Angles.angleDist(ang, rotation); - - if(diff > 100f && vec.len() < circleLength){ - vec.setAngle(velocity.angle()); - }else{ - vec.setAngle(Mathf.slerpDelta(velocity.angle(), vec.angle(), 0.44f)); - } - - vec.setLength(type.speed * Time.delta()); - - velocity.add(vec); - } -} diff --git a/core/src/io/anuke/mindustry/entities/units/Squad.java b/core/src/io/anuke/mindustry/entities/units/Squad.java deleted file mode 100644 index ef5d2b6e01..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/Squad.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.anuke.mindustry.entities.units; - -import io.anuke.arc.Core; -import io.anuke.arc.math.geom.Vector2; - -/** - * Used to group entities together, for formations and such. - * Usually, squads are used by units spawned in the same wave. - */ -public class Squad{ - public Vector2 direction = new Vector2(); - public int units; - - private long lastUpdated; - - protected void update(){ - if(Core.graphics.getFrameId() != lastUpdated){ - direction.setZero(); - lastUpdated = Core.graphics.getFrameId(); - } - } -} diff --git a/core/src/io/anuke/mindustry/entities/units/StateMachine.java b/core/src/io/anuke/mindustry/entities/units/StateMachine.java index a676716693..7ed555e7b6 100644 --- a/core/src/io/anuke/mindustry/entities/units/StateMachine.java +++ b/core/src/io/anuke/mindustry/entities/units/StateMachine.java @@ -14,6 +14,10 @@ public class StateMachine{ if(next != null) next.entered(); } + public UnitState current(){ + return state; + } + public boolean is(UnitState state){ return this.state == state; } diff --git a/core/src/io/anuke/mindustry/entities/StatusController.java b/core/src/io/anuke/mindustry/entities/units/Statuses.java similarity index 86% rename from core/src/io/anuke/mindustry/entities/StatusController.java rename to core/src/io/anuke/mindustry/entities/units/Statuses.java index fa9dd3c12e..ffc4fe8278 100644 --- a/core/src/io/anuke/mindustry/entities/StatusController.java +++ b/core/src/io/anuke/mindustry/entities/units/Statuses.java @@ -1,12 +1,14 @@ -package io.anuke.mindustry.entities; +package io.anuke.mindustry.entities.units; import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.Bits; import io.anuke.arc.graphics.Color; import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.content.StatusEffects; import io.anuke.mindustry.entities.traits.Saveable; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.StatusEffect; @@ -16,18 +18,19 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.content; /** Class for controlling status effects on an entity.*/ -public class StatusController implements Saveable{ +public class Statuses implements Saveable{ private static final StatusEntry globalResult = new StatusEntry(); private static final Array removals = new Array<>(); private Array statuses = new Array<>(); + private Bits applied = new Bits(content.getBy(ContentType.status).size); private float speedMultiplier; private float damageMultiplier; private float armorMultiplier; - public void handleApply(Unit unit, StatusEffect effect, float duration){ - if(effect == StatusEffects.none) return; //don't apply empty effects + public void handleApply(io.anuke.mindustry.entities.type.Unit unit, StatusEffect effect, float duration){ + if(effect == StatusEffects.none || unit.isImmune(effect)) return; //don't apply empty or immune effects if(statuses.size > 0){ //check for opposite effects @@ -75,6 +78,7 @@ public class StatusController implements Saveable{ } public void update(Unit unit){ + applied.clear(); speedMultiplier = damageMultiplier = armorMultiplier = 1f; if(statuses.size == 0) return; @@ -83,6 +87,7 @@ public class StatusController implements Saveable{ for(StatusEntry entry : statuses){ entry.time = Math.max(entry.time - Time.delta(), 0); + applied.set(entry.effect.id); if(entry.time <= 0){ Pools.free(entry); @@ -113,10 +118,7 @@ public class StatusController implements Saveable{ } public boolean hasEffect(StatusEffect effect){ - for(StatusEntry entry : statuses){ - if(entry.effect == effect) return true; - } - return false; + return applied.get(effect.id); } @Override @@ -124,7 +126,7 @@ public class StatusController implements Saveable{ stream.writeByte(statuses.size); for(StatusEntry entry : statuses){ stream.writeByte(entry.effect.id); - stream.writeShort((short) (entry.time * 2)); + stream.writeFloat(entry.time); } } @@ -139,7 +141,7 @@ public class StatusController implements Saveable{ byte amount = stream.readByte(); for(int i = 0; i < amount; i++){ byte id = stream.readByte(); - float time = stream.readShort() / 2f; + float time = stream.readFloat(); StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new); entry.set(content.getByID(ContentType.status, id), time); statuses.add(entry); diff --git a/core/src/io/anuke/mindustry/entities/units/UnitDrops.java b/core/src/io/anuke/mindustry/entities/units/UnitDrops.java index e06104cdd2..84c47a4457 100644 --- a/core/src/io/anuke/mindustry/entities/units/UnitDrops.java +++ b/core/src/io/anuke/mindustry/entities/units/UnitDrops.java @@ -2,7 +2,8 @@ package io.anuke.mindustry.entities.units; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.type.Item; import io.anuke.arc.math.Mathf; diff --git a/core/src/io/anuke/mindustry/entities/units/types/Dagger.java b/core/src/io/anuke/mindustry/entities/units/types/Dagger.java deleted file mode 100644 index aab1b4161b..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/types/Dagger.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.anuke.mindustry.entities.units.types; - -import io.anuke.mindustry.entities.units.GroundUnit; - -public class Dagger extends GroundUnit{ - -} diff --git a/core/src/io/anuke/mindustry/entities/units/types/Ghoul.java b/core/src/io/anuke/mindustry/entities/units/types/Ghoul.java deleted file mode 100644 index bc026434ab..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/types/Ghoul.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.anuke.mindustry.entities.units.types; - -import io.anuke.mindustry.entities.units.FlyingUnit; - -public class Ghoul extends FlyingUnit{ - -} diff --git a/core/src/io/anuke/mindustry/entities/units/types/Phantom.java b/core/src/io/anuke/mindustry/entities/units/types/Phantom.java deleted file mode 100644 index 622a5f245c..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/types/Phantom.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.anuke.mindustry.entities.units.types; - -public class Phantom extends Drone{ - -} diff --git a/core/src/io/anuke/mindustry/entities/units/types/Revenant.java b/core/src/io/anuke/mindustry/entities/units/types/Revenant.java deleted file mode 100644 index b2de68bdce..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/types/Revenant.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.anuke.mindustry.entities.units.types; - -import io.anuke.mindustry.entities.units.FlyingUnit; - -public class Revenant extends FlyingUnit{ - -} diff --git a/core/src/io/anuke/mindustry/entities/units/types/Spirit.java b/core/src/io/anuke/mindustry/entities/units/types/Spirit.java deleted file mode 100644 index 1c535dc3ab..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/types/Spirit.java +++ /dev/null @@ -1,4 +0,0 @@ -package io.anuke.mindustry.entities.units.types; - -public class Spirit extends Drone{ -} diff --git a/core/src/io/anuke/mindustry/entities/units/types/Titan.java b/core/src/io/anuke/mindustry/entities/units/types/Titan.java deleted file mode 100644 index e2c6a845bc..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/types/Titan.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.anuke.mindustry.entities.units.types; - -import io.anuke.mindustry.entities.units.GroundUnit; - -public class Titan extends GroundUnit{ - -} diff --git a/core/src/io/anuke/mindustry/entities/units/types/Wraith.java b/core/src/io/anuke/mindustry/entities/units/types/Wraith.java deleted file mode 100644 index 5033690101..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/types/Wraith.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.anuke.mindustry.entities.units.types; - -import io.anuke.mindustry.entities.units.FlyingUnit; - -public class Wraith extends FlyingUnit{ - -} diff --git a/core/src/io/anuke/mindustry/game/Waves.java b/core/src/io/anuke/mindustry/game/DefaultWaves.java similarity index 81% rename from core/src/io/anuke/mindustry/game/Waves.java rename to core/src/io/anuke/mindustry/game/DefaultWaves.java index 3b6355c2c8..dda11e2c48 100644 --- a/core/src/io/anuke/mindustry/game/Waves.java +++ b/core/src/io/anuke/mindustry/game/DefaultWaves.java @@ -4,23 +4,23 @@ import io.anuke.arc.collection.Array; import io.anuke.mindustry.content.Items; import io.anuke.mindustry.content.StatusEffects; import io.anuke.mindustry.content.UnitTypes; -import io.anuke.mindustry.content.Weapons; import io.anuke.mindustry.type.ItemStack; -public class Waves{ +public class DefaultWaves{ private static Array spawns; public static Array getDefaultSpawns(){ - if(spawns == null){ + if(spawns == null && UnitTypes.dagger != null){ spawns = Array.with( new SpawnGroup(UnitTypes.dagger){{ end = 8; - unitScaling = 3; + unitScaling = 2; }}, new SpawnGroup(UnitTypes.wraith){{ begin = 12; end = 14; + unitScaling = 2; }}, new SpawnGroup(UnitTypes.dagger){{ @@ -49,8 +49,7 @@ public class Waves{ new SpawnGroup(UnitTypes.titan){{ begin = 28; spacing = 3; - unitScaling = 2; - weapon = Weapons.flamethrower; + unitScaling = 1; end = 40; }}, @@ -58,7 +57,6 @@ public class Waves{ begin = 45; spacing = 3; unitScaling = 2; - weapon = Weapons.flamethrower; effect = StatusEffects.overdrive; }}, @@ -67,7 +65,6 @@ public class Waves{ spacing = 2; unitScaling = 3; unitAmount = 5; - weapon = Weapons.flakgun; effect = StatusEffects.overdrive; }}, @@ -142,7 +139,7 @@ public class Waves{ new SpawnGroup(UnitTypes.revenant){{ begin = 50; - unitAmount = 4; + unitAmount = 2; unitScaling = 3; spacing = 5; max = 8; @@ -167,29 +164,6 @@ public class Waves{ }} ); } - return spawns; - } - - public static void testWaves(Array spawns, int from, int to){ - for(int i = from; i <= to; i++){ - System.out.print(i + ": "); - int total = 0; - for(SpawnGroup spawn : spawns){ - int a = spawn.getUnitsSpawned(i); - total += a; - - if(a > 0){ - System.out.print(a + "x" + spawn.type.name); - - if(spawn.weapon != null){ - System.out.print(":" + spawn.weapon.name); - } - - System.out.print(" "); - } - } - System.out.print(" (" + total + ")"); - System.out.println(); - } + return spawns == null ? new Array<>() : spawns; } } diff --git a/core/src/io/anuke/mindustry/game/EventType.java b/core/src/io/anuke/mindustry/game/EventType.java index ef730a377a..c5dc0ba433 100644 --- a/core/src/io/anuke/mindustry/game/EventType.java +++ b/core/src/io/anuke/mindustry/game/EventType.java @@ -2,14 +2,29 @@ package io.anuke.mindustry.game; import io.anuke.arc.Events.Event; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.entities.traits.BuilderTrait; +import io.anuke.mindustry.type.Zone; import io.anuke.mindustry.world.Tile; public class EventType{ - public static class SectorCompleteEvent implements Event{ + /**Called when a zone's requirements are met.*/ + public static class ZoneCompleteEvent implements Event{ + public final Zone zone; + public ZoneCompleteEvent(Zone zone){ + this.zone = zone; + } + } + + /**Called when a zone's requirements are met.*/ + public static class ZoneConfigureCompleteEvent implements Event{ + public final Zone zone; + + public ZoneConfigureCompleteEvent(Zone zone){ + this.zone = zone; + } } /**Called when the game is first loaded.*/ diff --git a/core/src/io/anuke/mindustry/game/GlobalData.java b/core/src/io/anuke/mindustry/game/GlobalData.java index d12c5d1889..6726f6fd7f 100644 --- a/core/src/io/anuke/mindustry/game/GlobalData.java +++ b/core/src/io/anuke/mindustry/game/GlobalData.java @@ -7,14 +7,13 @@ import io.anuke.arc.collection.ObjectMap; import io.anuke.arc.collection.ObjectSet; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.EventType.UnlockEvent; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Zone; -import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.content; +import static io.anuke.mindustry.Vars.state; /**Stores player unlocks. Clientside only.*/ public class GlobalData{ @@ -25,22 +24,19 @@ public class GlobalData{ public GlobalData(){ Core.settings.setSerializer(ContentType.class, (stream, t) -> stream.writeInt(t.ordinal()), stream -> ContentType.values()[stream.readInt()]); Core.settings.setSerializer(Item.class, (stream, t) -> stream.writeUTF(t.name), stream -> content.getByName(ContentType.item, stream.readUTF())); + + Core.settings.setSerializer(ItemStack.class, (stream, t) -> { + stream.writeUTF(t.item.name); + stream.writeInt(t.amount); + }, stream -> { + String name = stream.readUTF(); + int amount = stream.readInt(); + return new ItemStack(content.getByName(ContentType.item, name), amount); + }); } - public void updateWaveScore(Zone zone, int wave){ - int value = Core.settings.getInt(zone.name + "-wave", 0); - if(value < wave){ - Core.settings.put(zone.name + "-wave", wave); - modified = true; - } - } - - public int getWaveScore(Zone zone){ - return Core.settings.getInt(zone.name + "-wave", 0); - } - - public boolean isCompleted(Zone zone){ - return getWaveScore(zone) >= zone.conditionWave; + public void modified(){ + modified = true; } public int getItem(Item item){ @@ -48,6 +44,7 @@ public class GlobalData{ } public void addItem(Item item, int amount){ + unlockContent(item); modified = true; items.getAndIncrement(item, 0, amount); state.stats.itemsDelivered.getAndIncrement(item, 0, amount); @@ -79,7 +76,7 @@ public class GlobalData{ /** Returns whether or not this piece of content is unlocked yet.*/ public boolean isUnlocked(UnlockableContent content){ - return (!state.is(State.menu) && !world.isZone()) || content.alwaysUnlocked() || unlocked.getOr(content.getContentType(), ObjectSet::new).contains(content.getContentName()); + return content.alwaysUnlocked() || unlocked.getOr(content.getContentType(), ObjectSet::new).contains(content.name); } /** @@ -91,11 +88,10 @@ public class GlobalData{ if(content.alwaysUnlocked()) return; //fire unlock event so other classes can use it - if(unlocked.getOr(content.getContentType(), ObjectSet::new).add(content.getContentName())){ + if(unlocked.getOr(content.getContentType(), ObjectSet::new).add(content.name)){ modified = true; content.onUnlock(); Events.fire(new UnlockEvent(content)); - save(); } } @@ -119,8 +115,8 @@ public class GlobalData{ } //set up default values - if(!Core.settings.has("item-" + Items.copper)){ - addItem(Items.copper, 500); + if(!Core.settings.has("item-" + Items.copper.name)){ + addItem(Items.copper, 50); } } diff --git a/core/src/io/anuke/mindustry/game/MappableContent.java b/core/src/io/anuke/mindustry/game/MappableContent.java index 69fff736ec..9b1e7bbc36 100644 --- a/core/src/io/anuke/mindustry/game/MappableContent.java +++ b/core/src/io/anuke/mindustry/game/MappableContent.java @@ -1,15 +1,14 @@ package io.anuke.mindustry.game; public abstract class MappableContent extends Content { - /** - * Returns the unqiue name of this piece of content. - * The name only needs to be unique for all content of this type. - * Do not use IDs for names! Make sure this string stays constant with each update unless removed. - */ - public abstract String getContentName(); + public final String name; + + public MappableContent(String name){ + this.name = name; + } @Override public String toString(){ - return getContentName(); + return name; } } diff --git a/core/src/io/anuke/mindustry/game/RulePreset.java b/core/src/io/anuke/mindustry/game/RulePreset.java index ae76a97430..174f9e0df9 100644 --- a/core/src/io/anuke/mindustry/game/RulePreset.java +++ b/core/src/io/anuke/mindustry/game/RulePreset.java @@ -9,11 +9,13 @@ public enum RulePreset{ waveTimer = true; waves = true; unitDrops = true; + spawns = DefaultWaves.getDefaultSpawns(); }}), sandbox(() -> new Rules(){{ infiniteResources = true; waves = true; waveTimer = false; + spawns = DefaultWaves.getDefaultSpawns(); }}), attack(() -> new Rules(){{ enemyCheat = true; diff --git a/core/src/io/anuke/mindustry/game/Rules.java b/core/src/io/anuke/mindustry/game/Rules.java index ce6d1c7552..a23b15321d 100644 --- a/core/src/io/anuke/mindustry/game/Rules.java +++ b/core/src/io/anuke/mindustry/game/Rules.java @@ -24,9 +24,9 @@ public class Rules{ /**Player respawn time in ticks.*/ public float respawnTime = 60 * 4; /**Time between waves in ticks.*/ - public float waveSpacing = 60 * 60; + public float waveSpacing = 60 * 60 * 2; /**Zone ID, -1 for invalid zone.*/ public byte zone = -1; /**Spawn layout. Since only zones modify this, it should be assigned on save load.*/ - public transient Array spawns = new Array<>(); + public transient Array spawns = DefaultWaves.getDefaultSpawns(); } diff --git a/core/src/io/anuke/mindustry/game/Saves.java b/core/src/io/anuke/mindustry/game/Saves.java index 5555684cef..0142f194f7 100644 --- a/core/src/io/anuke/mindustry/game/Saves.java +++ b/core/src/io/anuke/mindustry/game/Saves.java @@ -197,7 +197,7 @@ public class Saves{ } public boolean isHidden(){ - return false; + return getZone() != null; } public String getPlayTime(){ diff --git a/core/src/io/anuke/mindustry/game/SpawnGroup.java b/core/src/io/anuke/mindustry/game/SpawnGroup.java index 56347177c3..64e399b3db 100644 --- a/core/src/io/anuke/mindustry/game/SpawnGroup.java +++ b/core/src/io/anuke/mindustry/game/SpawnGroup.java @@ -1,11 +1,9 @@ package io.anuke.mindustry.game; -import io.anuke.mindustry.entities.units.BaseUnit; -import io.anuke.mindustry.entities.units.GroundUnit; -import io.anuke.mindustry.entities.units.UnitType; +import io.anuke.mindustry.entities.type.BaseUnit; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.StatusEffect; -import io.anuke.mindustry.type.Weapon; +import io.anuke.mindustry.type.UnitType; /** * A spawn group defines spawn information for a specific type of unit, with optional extra information like @@ -13,22 +11,22 @@ import io.anuke.mindustry.type.Weapon; * Each spawn group can have multiple sub-groups spawned in different areas of the map. */ public class SpawnGroup{ + protected static final int never = Integer.MAX_VALUE; + /**The unit type spawned*/ public final UnitType type; /**When this spawn should end*/ - protected int end = Integer.MAX_VALUE; + protected int end = never; /**When this spawn should start*/ protected int begin; /**The spacing, in waves, of spawns. For example, 2 = spawns every other wave*/ protected int spacing = 1; /**Maximum amount of units that spawn*/ - protected int max = 60; + protected int max = 40; /**How many waves need to pass before the amount of units spawned increases by 1*/ protected float unitScaling = 9999f; /**Amount of enemies spawned initially, with no scaling*/ protected int unitAmount = 1; - /**Weapon used by the spawned unit. Null to disable. Only applicable to ground units.*/ - protected Weapon weapon; /**Status effect applied to the spawned unit. Null to disable.*/ protected StatusEffect effect; /**Items this unit spawns with. Null to disable.*/ @@ -38,9 +36,7 @@ public class SpawnGroup{ this.type = type; } - /** - * Returns the amount of units spawned on a specific wave. - */ + /**Returns the amount of units spawned on a specific wave.*/ public int getUnitsSpawned(int wave){ if(wave < begin || wave > end || (wave - begin) % spacing != 0){ return 0; @@ -57,16 +53,12 @@ public class SpawnGroup{ public BaseUnit createUnit(Team team){ BaseUnit unit = type.create(team); - if(unit instanceof GroundUnit && weapon != null){ - ((GroundUnit) unit).setWeapon(weapon); - } - if(effect != null){ unit.applyEffect(effect, 999999f); } if(items != null){ - unit.inventory.addItem(items.item, items.amount); + unit.addItem(items.item, items.amount); } return unit; @@ -82,7 +74,6 @@ public class SpawnGroup{ ", max=" + max + ", unitScaling=" + unitScaling + ", unitAmount=" + unitAmount + - ", weapon=" + weapon + ", effect=" + effect + ", items=" + items + '}'; diff --git a/core/src/io/anuke/mindustry/game/Stats.java b/core/src/io/anuke/mindustry/game/Stats.java index 49c3427cd0..63e632440c 100644 --- a/core/src/io/anuke/mindustry/game/Stats.java +++ b/core/src/io/anuke/mindustry/game/Stats.java @@ -1,8 +1,12 @@ package io.anuke.mindustry.game; import io.anuke.annotations.Annotations.Serialize; +import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectIntMap; +import io.anuke.arc.math.Mathf; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.ItemType; +import io.anuke.mindustry.type.Zone; @Serialize public class Stats{ @@ -20,4 +24,49 @@ public class Stats{ public int buildingsDeconstructed; /**Friendly buildings destroyed.*/ public int buildingsDestroyed; + + public RankResult calculateRank(Zone zone, boolean launched){ + float score = 0; + + //each new launch period adds onto the rank 1.5 'points' + if(wavesLasted >= zone.conditionWave){ + score += (float)((wavesLasted - zone.conditionWave) / zone.launchPeriod + 1) * 1.5f; + } + + int capacity = zone.loadout.core().itemCapacity; + + //weigh used fractions + float frac = 0f; + Array obtainable = Array.with(zone.resources).select(i -> i.type == ItemType.material); + for(Item item : obtainable){ + frac += Mathf.clamp((float)itemsDelivered.get(item, 0) / capacity) / (float)obtainable.size; + } + + score += frac*2.4f; + + if(!launched){ + score *= 0.5f; + } + + int rankIndex = Mathf.clamp((int)(score), 0, Rank.values().length-1); + Rank rank = Rank.values()[rankIndex]; + String sign = Math.abs((rankIndex + 0.5f) - score) < 0.2f || rank.name().contains("S") ? "" : (rankIndex + 0.5f) < score ? "-" : "+"; + + return new RankResult(rank, sign); + } + + public static class RankResult{ + public final Rank rank; + /**+ or -*/ + public final String modifier; + + public RankResult(Rank rank, String modifier){ + this.rank = rank; + this.modifier = modifier; + } + } + + public enum Rank{ + F, D, C, B, A, S, SS + } } diff --git a/core/src/io/anuke/mindustry/game/Teams.java b/core/src/io/anuke/mindustry/game/Teams.java index 7fac1100ad..28ffdfc2a2 100644 --- a/core/src/io/anuke/mindustry/game/Teams.java +++ b/core/src/io/anuke/mindustry/game/Teams.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.game; +import io.anuke.arc.collection.Array; import io.anuke.arc.collection.EnumSet; import io.anuke.arc.collection.ObjectSet; import io.anuke.mindustry.Vars; @@ -22,12 +23,7 @@ public class Teams{ /**Returns team data by type.*/ public TeamData get(Team team){ if(map[team.ordinal()] == null){ - //By default, a non-defined team will be enemies of everything. - Team[] others = new Team[Team.all.length-1]; - for(int i = 0, j = 0; i < Team.all.length; i++){ - if(Team.all[i] != team) others[j++] = Team.all[i]; - } - add(team, others); + add(team, Array.with(Team.all).select(t -> t != team).toArray(Team.class)); } return map[team.ordinal()]; } diff --git a/core/src/io/anuke/mindustry/game/UnlockableContent.java b/core/src/io/anuke/mindustry/game/UnlockableContent.java index c2bf0caea7..7a843ecdfc 100644 --- a/core/src/io/anuke/mindustry/game/UnlockableContent.java +++ b/core/src/io/anuke/mindustry/game/UnlockableContent.java @@ -1,10 +1,24 @@ package io.anuke.mindustry.game; +import io.anuke.arc.Core; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.Vars; /**Base interface for an unlockable content type.*/ public abstract class UnlockableContent extends MappableContent{ + /**Localized, formal name. Never null. Set to block name if not found in bundle.*/ + public String localizedName; + /**Localized description. May be null.*/ + public String description; + + public UnlockableContent(String name){ + super(name); + + this.localizedName = Core.bundle.get(getContentType() + "." + name + ".name", name); + this.description = Core.bundle.getOrNull(getContentType() + "." + name + ".description"); + } + /**Returns the localized name of this content.*/ public abstract String localizedName(); @@ -26,4 +40,12 @@ public abstract class UnlockableContent extends MappableContent{ public boolean alwaysUnlocked(){ return false; } + + public final boolean unlocked(){ + return Vars.data.isUnlocked(this); + } + + public final boolean locked(){ + return !unlocked(); + } } diff --git a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java index 8da7a2280b..a12ccd624d 100644 --- a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java @@ -4,14 +4,16 @@ import io.anuke.arc.Core; import io.anuke.arc.Events; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.Sort; -import io.anuke.arc.entities.EntityDraw; -import io.anuke.arc.entities.EntityGroup; +import io.anuke.mindustry.entities.EntityDraw; +import io.anuke.mindustry.entities.EntityGroup; import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.Texture.TextureFilter; import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.Fill; import io.anuke.arc.graphics.glutils.FrameBuffer; import io.anuke.arc.util.Tmp; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.EventType.TileChangeEvent; import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.Team; @@ -23,7 +25,7 @@ import static io.anuke.mindustry.Vars.*; public class BlockRenderer{ private final static int initialRequests = 32 * 32; - private final static int expandr = 6; + private final static int expandr = 9; private final static boolean disableShadows = false; private final static Color shadowColor = new Color(0, 0, 0, 0.19f); @@ -34,6 +36,8 @@ public class BlockRenderer{ private int requestidx = 0; private int iterateidx = 0; private FrameBuffer shadows = new FrameBuffer(2, 2); + private FrameBuffer fog = new FrameBuffer(2, 2); + private Array outArray = new Array<>(); public BlockRenderer(){ @@ -43,6 +47,28 @@ public class BlockRenderer{ Events.on(WorldLoadEvent.class, event -> { lastCamY = lastCamX = -99; //invalidate camera position so blocks get updated + + fog.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear); + fog.resize(world.width(), world.height()); + fog.begin(); + Core.graphics.clear(Color.WHITE); + Draw.proj().setOrtho(0, 0, fog.getWidth(), fog.getHeight()); + + //TODO highly inefficient, width*height rectangles isn't great + //TODO handle shadow rotation generation with GPU blur/erode algorithm + for(int x = 0; x < world.width(); x++){ + for(int y = 0; y < world.height(); y++){ + Tile tile = world.rawTile(x, y); + if(tile.getRotation() > 0 && tile.block().solid && tile.block().fillsTile && !tile.block().synthetic()){ + Draw.color(0f, 0f, 0f, Math.min((tile.getRotation() + 0.5f)/4f, 1f)); + Fill.rect(tile.x + 0.5f, tile.y + 0.5f, 1, 1); + } + } + } + + Draw.flush(); + Draw.color(); + fog.end(); }); Events.on(TileChangeEvent.class, event -> { @@ -57,25 +83,44 @@ public class BlockRenderer{ }); } + public void drawFog(){ + float ww = world.width() * tilesize, wh = world.height() * tilesize; + float x = camera.position.x + tilesize/2f, y = camera.position.y + tilesize/2f; + float u = (x - camera.width/2f) / ww, + v = (y - camera.height/2f) / wh, + u2 = (x + camera.width/2f) / ww, + v2 = (y + camera.height/2f) / wh; + + Tmp.tr1.set(fog.getTexture()); + Tmp.tr1.set(u, v2, u2, v); + + Draw.shader(Shaders.fog); + Draw.rect(Tmp.tr1, camera.position.x, camera.position.y, camera.width, camera.height); + Draw.shader(); + } + public void drawShadows(){ if(disableShadows) return; + Draw.color(); + if(!Core.graphics.isHidden() && (shadows.getWidth() != Core.graphics.getWidth() || shadows.getHeight() != Core.graphics.getHeight())){ shadows.resize(Core.graphics.getWidth(), Core.graphics.getHeight()); } Tmp.tr1.set(shadows.getTexture()); - Shaders.outline.color.set(shadowColor); - Shaders.outline.scl = renderer.cameraScale()/3f; - Shaders.outline.region = Tmp.tr1; + Shaders.shadow.color.set(shadowColor); + Shaders.shadow.scl = renderer.cameraScale()/3f; + Shaders.shadow.region = Tmp.tr1; Draw.flush(); shadows.begin(); Core.graphics.clear(Color.CLEAR); - Draw.color(shadowColor); + floor.beginDraw(); floor.drawLayer(CacheLayer.walls); floor.endDraw(); + drawBlocks(Layer.shadow); EntityDraw.drawWith(playerGroup, player -> !player.isDead(), Unit::draw); @@ -87,7 +132,7 @@ public class BlockRenderer{ Draw.flush(); shadows.end(); - Draw.shader(Shaders.outline); + Draw.shader(Shaders.shadow); Draw.rect(Draw.wrap(shadows.getTexture()), camera.position.x, camera.position.y, @@ -120,19 +165,17 @@ public class BlockRenderer{ for(int y = miny; y <= maxy; y++){ boolean expanded = (Math.abs(x - avgx) > rangex || Math.abs(y - avgy) > rangey); Tile tile = world.rawTile(x, y); + if(tile == null) continue; //how is this possible? Block block = tile.block(); - if(!expanded && block != Blocks.air && block.cacheLayer == CacheLayer.normal && world.isAccessible(x, y)){ - tile.block().drawShadow(tile); - } - if(block != Blocks.air && block.cacheLayer == CacheLayer.normal){ if(!expanded){ - addRequest(tile, Layer.shadow); addRequest(tile, Layer.block); } if(block.expanded || !expanded){ + addRequest(tile, Layer.shadow); + if(block.layer != null && block.isLayer(tile)){ addRequest(tile, block.layer); } @@ -140,6 +183,14 @@ public class BlockRenderer{ if(block.layer2 != null && block.isLayer2(tile)){ addRequest(tile, block.layer2); } + + if(tile.entity != null && tile.entity.power != null && tile.entity.power.links.size > 0){ + for(Tile other : block.getPowerConnections(tile, outArray)){ + if(other.block().layer == Layer.power){ + addRequest(other, Layer.power); + } + } + } } } } @@ -151,10 +202,6 @@ public class BlockRenderer{ lastCamY = avgy; lastRangeX = rangex; lastRangeY = rangey; - - floor.beginDraw(); - floor.drawLayer(CacheLayer.walls); - floor.endDraw(); } public void drawBlocks(Layer stopAt){ @@ -173,9 +220,7 @@ public class BlockRenderer{ }else if(req.layer == Layer.block){ block.draw(req.tile); if(block.synthetic() && req.tile.getTeam() != players[0].getTeam()){ - Draw.color(req.tile.getTeam().color); - Draw.rect("block-border", req.tile.drawx() - block.size * tilesize/2f + 4, req.tile.drawy() - block.size * tilesize/2f + 4); - Draw.color(); + block.drawTeam(req.tile); } }else if(req.layer == block.layer){ block.drawLayer(req.tile); diff --git a/core/src/io/anuke/mindustry/graphics/CacheLayer.java b/core/src/io/anuke/mindustry/graphics/CacheLayer.java index dca1a53df7..9c96f4d3c5 100644 --- a/core/src/io/anuke/mindustry/graphics/CacheLayer.java +++ b/core/src/io/anuke/mindustry/graphics/CacheLayer.java @@ -1,18 +1,38 @@ package io.anuke.mindustry.graphics; -//TODO implement effects again +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.glutils.Shader; + +import static io.anuke.arc.Core.camera; +import static io.anuke.mindustry.Vars.renderer; + public enum CacheLayer{ water{ + @Override + public void begin(){ + beginShader(); + } + + @Override + public void end(){ + endShader(Shaders.water); + } }, - lava{ - }, - oil{ - }, - space{ + tar{ + @Override + public void begin(){ + beginShader(); + } + + @Override + public void end(){ + endShader(Shaders.tar); + } }, normal, - walls{ //TODO implement walls - }; + walls; public void begin(){ @@ -22,10 +42,25 @@ public enum CacheLayer{ } - protected void beginShader(){ + void beginShader(){ + if(!Core.settings.getBool("animatedwater")) return; + renderer.blocks.floor.endc(); + renderer.shieldBuffer.begin(); + Core.graphics.clear(Color.CLEAR); + renderer.blocks.floor.beginc(); } - public void endShader(){ + void endShader(Shader shader){ + if(!Core.settings.getBool("animatedwater")) return; + + renderer.blocks.floor.endc(); + renderer.shieldBuffer.end(); + + Draw.shader(shader); + Draw.rect(Draw.wrap(renderer.shieldBuffer.getTexture()), camera.position.x, camera.position.y, camera.width, -camera.height); + Draw.shader(); + + renderer.blocks.floor.beginc(); } } diff --git a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java index 115615b682..7bc7acc202 100644 --- a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java @@ -95,6 +95,14 @@ public class FloorRenderer{ endDraw(); } + public void beginc(){ + cbatch.beginDraw(); + } + + public void endc(){ + cbatch.endDraw(); + } + public void beginDraw(){ if(cache == null){ return; @@ -114,10 +122,6 @@ public class FloorRenderer{ cbatch.endDraw(); } - public void updateFloor(Tile tile){ - //TODO: implement - } - public void drawLayer(CacheLayer layer){ if(cache == null){ return; @@ -190,8 +194,10 @@ public class FloorRenderer{ if(tile.block().cacheLayer == layer && layer == CacheLayer.walls){ tile.block().draw(tile); - }else if(floor.cacheLayer == layer && tile.block().cacheLayer != CacheLayer.walls){ + }else if(floor.cacheLayer == layer && (world.isAccessible(tile.x,tile.y) || tile.block().cacheLayer != CacheLayer.walls || !tile.block().fillsTile)){ floor.draw(tile); + }else if(floor.cacheLayer.ordinal() < layer.ordinal() && layer != CacheLayer.walls){ + floor.drawNonLayer(tile); } } } @@ -205,7 +211,7 @@ public class FloorRenderer{ int chunksx = Mathf.ceil((float) (world.width()) / chunksize), chunksy = Mathf.ceil((float) (world.height()) / chunksize) ; cache = new Chunk[chunksx][chunksy]; - SpriteCache sprites = new SpriteCache(world.width() * world.height(), (world.width() / chunksize) * (world.height() / chunksize) * 2, false); + SpriteCache sprites = new SpriteCache(world.width() * world.height() * 5, (world.width() / chunksize) * (world.height() / chunksize) * 2, false); cbatch = new CacheBatch(sprites); Time.mark(); diff --git a/core/src/io/anuke/mindustry/graphics/IndexedRenderer.java b/core/src/io/anuke/mindustry/graphics/IndexedRenderer.java index c082b7c8a9..ca2e9787b4 100644 --- a/core/src/io/anuke/mindustry/graphics/IndexedRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/IndexedRenderer.java @@ -9,12 +9,43 @@ import io.anuke.arc.graphics.glutils.Shader; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.Matrix3; import io.anuke.arc.util.Disposable; +import io.anuke.arc.util.Strings; //TODO this class is a trainwreck, remove it public class IndexedRenderer implements Disposable{ private final static int vsize = 5; - private Shader program = BatchShader.create(); + private Shader program = new Shader( + Strings.join("\n", + "attribute vec4 " + Shader.POSITION_ATTRIBUTE + ";", + "attribute vec4 " + Shader.COLOR_ATTRIBUTE + ";", + "attribute vec2 " + Shader.TEXCOORD_ATTRIBUTE + "0;", + "uniform mat4 u_projTrans;", + "varying vec4 v_color;", + "varying vec2 v_texCoords;", + "", + "void main(){", + " v_color = " + Shader.COLOR_ATTRIBUTE + ";", + " v_color.a = v_color.a * (255.0/254.0);", + " v_texCoords = " + Shader.TEXCOORD_ATTRIBUTE + "0;", + " gl_Position = u_projTrans * " + Shader.POSITION_ATTRIBUTE + ";", + "}"), + Strings.join("\n", + "#ifdef GL_ES", + "#define LOWP lowp", + "precision mediump float;", + "#else", + "#define LOWP ", + "#endif", + "", + "varying LOWP vec4 v_color;", + "varying vec2 v_texCoords;", + "uniform sampler2D u_texture;", + "", + "void main(){", + " gl_FragColor = v_color * texture2D(u_texture, v_texCoords);", + "}" + )); private Mesh mesh; private float[] tmpVerts = new float[vsize * 6]; private float[] vertices; diff --git a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java index 0f133e6b90..5c938d2b8c 100644 --- a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java @@ -14,11 +14,11 @@ import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.util.Disposable; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.game.EventType.TileChangeEvent; import io.anuke.mindustry.game.EventType.WorldLoadEvent; -import io.anuke.mindustry.world.ColorMapper; +import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.world.Tile; import static io.anuke.mindustry.Vars.tilesize; @@ -137,7 +137,7 @@ public class MinimapRenderer implements Disposable{ private int colorFor(Tile tile){ tile = tile.target(); - return ColorMapper.colorFor(tile.floor(), tile.block(), tile.getTeam()); + return MapIO.colorFor(tile.floor(), tile.block(), tile.getTeam()); } @Override diff --git a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java index 6211e4ee35..af8ad777c2 100644 --- a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java @@ -10,9 +10,10 @@ import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.input.InputHandler; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; import static io.anuke.mindustry.Vars.*; @@ -28,13 +29,7 @@ public class OverlayRenderer{ if(!input.isDrawing() || player.isDead()) continue; - Shaders.outline.color.set(Palette.accent); - //TODO draw outlined version - //Graphics.beginShaders(Shaders.outline); - input.drawOutlined(); - - //Graphics.endShaders(); } } @@ -79,7 +74,7 @@ public class OverlayRenderer{ if(dst < state.rules.enemyCoreBuildRadius * 1.5f){ Draw.color(Color.DARK_GRAY); Lines.poly(core.drawx(), core.drawy() - 2, 200, state.rules.enemyCoreBuildRadius); - Draw.color(Palette.accent, enemy.color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f)); + Draw.color(Pal.accent, enemy.color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f)); Lines.poly(core.drawx(), core.drawy(), 200, state.rules.enemyCoreBuildRadius); } } @@ -102,15 +97,15 @@ public class OverlayRenderer{ if(input.isDroppingItem()){ Vector2 v = Core.input.mouseWorld(input.getMouseX(), input.getMouseY()); float size = 8; - Draw.rect(player.inventory.getItem().item.region, v.x, v.y, size, size); - Draw.color(Palette.accent); + Draw.rect(player.item().item.icon(Item.Icon.large), v.x, v.y, size, size); + Draw.color(Pal.accent); Lines.circle(v.x, v.y, 6 + Mathf.absin(Time.time(), 5f, 1f)); Draw.reset(); Tile tile = world.tileWorld(v.x, v.y); if(tile != null) tile = tile.target(); - if(tile != null && tile.getTeam() == player.getTeam() && tile.block().acceptStack(player.inventory.getItem().item, player.inventory.getItem().amount, tile, player) > 0){ - Draw.color(Palette.place); + if(tile != null && tile.interactable(player.getTeam()) && tile.block().acceptStack(player.item().item, player.item().amount, tile, player) > 0){ + Draw.color(Pal.place); Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f + 1 + Mathf.absin(Time.time(), 5f, 1f)); Draw.color(); } diff --git a/core/src/io/anuke/mindustry/graphics/Palette.java b/core/src/io/anuke/mindustry/graphics/Pal.java similarity index 89% rename from core/src/io/anuke/mindustry/graphics/Palette.java rename to core/src/io/anuke/mindustry/graphics/Pal.java index 4483f9c281..b5c17c8604 100644 --- a/core/src/io/anuke/mindustry/graphics/Palette.java +++ b/core/src/io/anuke/mindustry/graphics/Pal.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.graphics; import io.anuke.arc.graphics.Color; -public class Palette{ +public class Pal{ public static final Color command = Color.valueOf("eab678"), @@ -30,6 +30,7 @@ public class Palette{ lightishGray = Color.valueOf("a2a2a2"), darkishGray = new Color(0.3f, 0.3f, 0.3f, 1f), darkerGray = new Color(0.2f, 0.2f, 0.2f, 1f), + ammo = Color.valueOf("ff8947"), boostTo = Color.valueOf("ffad4d"), boostFrom = Color.valueOf("ff7f57"), @@ -37,6 +38,7 @@ public class Palette{ lancerLaser = Color.valueOf("a9d8ff"), stoneGray = Color.valueOf("8f8f8f"), + engine = Color.valueOf("ffbb64"), health = Color.valueOf("ff341c"), heal = Color.valueOf("98ffa9"), @@ -51,9 +53,13 @@ public class Palette{ breakInvalid = Color.valueOf("d44b3d"), range = Color.valueOf("f4ba6e"), power = Color.valueOf("fbad67"), + powerBar = Color.valueOf("ec7b4c"), powerLight = Color.valueOf("fbd367"), placing = accent, + unitFront = Color.valueOf("ffa665"), + unitBack = Color.valueOf("d06b53"), + lightTrail = Color.valueOf("ffe2a9"), surge = Color.valueOf("f3e979"), diff --git a/core/src/io/anuke/mindustry/graphics/Shaders.java b/core/src/io/anuke/mindustry/graphics/Shaders.java index 2853013ecc..7839716f71 100644 --- a/core/src/io/anuke/mindustry/graphics/Shaders.java +++ b/core/src/io/anuke/mindustry/graphics/Shaders.java @@ -7,38 +7,24 @@ import io.anuke.arc.graphics.glutils.Shader; import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.util.Time; -import static io.anuke.mindustry.Vars.tilesize; -import static io.anuke.mindustry.Vars.world; - public class Shaders{ - public static Outline outline; + public static Shadow shadow; public static BlockBuild blockbuild; - public static BlockPreview blockpreview; public static Shield shield; - public static SurfaceShader water; - public static SurfaceShader lava; - public static SurfaceShader oil; - public static Space space; public static UnitBuild build; - public static MixShader mix; - public static Shader fullMix; public static FogShader fog; public static MenuShader menu; + public static SurfaceShader water, tar; public static void init(){ - outline = new Outline(); + shadow = new Shadow(); blockbuild = new BlockBuild(); - blockpreview = new BlockPreview(); shield = new Shield(); - water = new SurfaceShader("water"); - lava = new SurfaceShader("lava"); - oil = new SurfaceShader("oil"); - space = new Space(); build = new UnitBuild(); - mix = new MixShader(); fog = new FogShader(); - fullMix = new LoadShader("fullmix", "default"); menu = new MenuShader(); + water = new SurfaceShader("water"); + tar = new SurfaceShader("tar"); } public static class MenuShader extends LoadShader{ @@ -66,40 +52,13 @@ public class Shaders{ } } - public static class MixShader extends LoadShader{ - public Color color = new Color(Color.WHITE); - - public MixShader(){ - super("mix", "default"); - } - - @Override - public void apply(){ - super.apply(); - setUniformf("u_color", color); - } - } - - public static class Space extends SurfaceShader{ - - public Space(){ - super("space2"); - } - - @Override - public void apply(){ - super.apply(); - setUniformf("u_center", world.width() * tilesize / 2f, world.height() * tilesize / 2f); - } - } - public static class UnitBuild extends LoadShader{ public float progress, time; public Color color = new Color(); public TextureRegion region; public UnitBuild(){ - super("build", "default"); + super("unitbuild", "default"); } @Override @@ -113,13 +72,13 @@ public class Shaders{ } } - public static class Outline extends LoadShader{ + public static class Shadow extends LoadShader{ public Color color = new Color(); public TextureRegion region = new TextureRegion(); public float scl; - public Outline(){ - super("outline", "default"); + public Shadow(){ + super("shadow", "default"); } @Override @@ -150,23 +109,6 @@ public class Shaders{ } } - public static class BlockPreview extends LoadShader{ - public Color color = new Color(); - public TextureRegion region = new TextureRegion(); - - public BlockPreview(){ - super("blockpreview", "default"); - } - - @Override - public void apply(){ - setUniformf("u_color", color); - setUniformf("u_uv", region.getU(), region.getV()); - setUniformf("u_uv2", region.getU2(), region.getV2()); - setUniformf("u_texsize", region.getTexture().getWidth(), region.getTexture().getHeight()); - } - } - public static class Shield extends LoadShader{ public Shield(){ @@ -193,11 +135,8 @@ public class Shaders{ @Override public void apply(){ - setUniformf("camerapos", - Core.camera.position.x - Core.camera.width / 2 , - Core.camera.position.y - Core.camera.height / 2 ); - setUniformf("screensize", Core.camera.width, - Core.camera.height ); + setUniformf("camerapos", Core.camera.position.x - Core.camera.width / 2, Core.camera.position.y - Core.camera.height / 2); + setUniformf("screensize", Core.camera.width, Core.camera.height); setUniformf("time", Time.time()); } } diff --git a/core/src/io/anuke/mindustry/graphics/Shapes.java b/core/src/io/anuke/mindustry/graphics/Shapes.java index 5d87feaefd..899ed2ae8d 100644 --- a/core/src/io/anuke/mindustry/graphics/Shapes.java +++ b/core/src/io/anuke/mindustry/graphics/Shapes.java @@ -6,6 +6,7 @@ import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Tmp; //TODO remove public class Shapes{ @@ -19,16 +20,16 @@ public class Shapes{ } public static void laser(String line, String edge, float x, float y, float x2, float y2, float rotation, float scale){ - - Lines.stroke(12f * scale); - Lines.line(Core.atlas.find(line), x, y, x2, y2, CapStyle.none, 0f); - Lines.stroke(1f); - TextureRegion region = Core.atlas.find(edge); - Draw.rect(Core.atlas.find(edge), x, y, region.getWidth() * Draw.scl, region.getHeight() * scale * Draw.scl, rotation + 180); + Tmp.v1.trns(rotation, 8f * scale * Draw.scl); - Draw.rect(Core.atlas.find(edge), x2, y2, region.getWidth() * Draw.scl, region.getHeight() * scale * Draw.scl, rotation); + Draw.rect(Core.atlas.find(edge), x, y, region.getWidth() * scale * Draw.scl, region.getHeight() * scale * Draw.scl, rotation + 180); + Draw.rect(Core.atlas.find(edge), x2, y2, region.getWidth() * scale * Draw.scl, region.getHeight() * scale * Draw.scl, rotation); + + Lines.stroke(12f * scale); + Lines.line(Core.atlas.find(line), x + Tmp.v1.x, y + Tmp.v1.y, x2 - Tmp.v1.x, y2 - Tmp.v1.y, CapStyle.none, 0f); + Lines.stroke(1f); } public static void tri(float x, float y, float width, float length, float rotation){ diff --git a/core/src/io/anuke/mindustry/input/Binding.java b/core/src/io/anuke/mindustry/input/Binding.java index 40396ad9b1..5600c5f213 100644 --- a/core/src/io/anuke/mindustry/input/Binding.java +++ b/core/src/io/anuke/mindustry/input/Binding.java @@ -15,22 +15,21 @@ public enum Binding implements KeyBind{ deselect(KeyCode.MOUSE_RIGHT), break_block(KeyCode.MOUSE_RIGHT), rotate(new Axis(KeyCode.SCROLL)), + pick(KeyCode.MOUSE_MIDDLE), dash(KeyCode.SHIFT_LEFT), - drop_unit(KeyCode.SHIFT_LEFT), - gridMode(KeyCode.SPACE), - gridModeShift(KeyCode.SHIFT_LEFT), + gridMode(KeyCode.GRAVE), + gridModeShift(KeyCode.ALT_LEFT), zoom_hold(KeyCode.CONTROL_LEFT, "view"), zoom(new Axis(KeyCode.SCROLL)), - zoom_minimap(new Axis(KeyCode.MINUS, KeyCode.PLUS)), menu(Core.app.getType() == ApplicationType.Android ? KeyCode.BACK : KeyCode.ESCAPE), pause(KeyCode.SPACE), toggle_menus(KeyCode.C), - screenshot(KeyCode.P), player_list(KeyCode.TAB, "multiplayer"), chat(KeyCode.ENTER), chat_history_prev(KeyCode.UP), chat_history_next(KeyCode.DOWN), - chat_scroll(new Axis(KeyCode.SCROLL)) + chat_scroll(new Axis(KeyCode.SCROLL)), + ; private final KeybindValue defaultValue; diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index 02c212da5c..4c22050f54 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -7,10 +7,12 @@ import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Geometry; +import io.anuke.arc.math.geom.Point2; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.input.PlaceUtils.NormalizeDrawResult; import io.anuke.mindustry.input.PlaceUtils.NormalizeResult; import io.anuke.mindustry.net.Net; @@ -22,10 +24,6 @@ import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.input.PlaceMode.*; public class DesktopInput extends InputHandler{ - private final String section; - //controller info - private float controlx, controly; - private boolean controlling; /**Current cursor type.*/ private Cursor cursorType = SystemCursor.arrow; @@ -38,7 +36,6 @@ public class DesktopInput extends InputHandler{ public DesktopInput(Player player){ super(player); - this.section = "player_" + (player.playerIndex + 1); } /**Draws a placement icon for a specific block.*/ @@ -47,13 +44,22 @@ public class DesktopInput extends InputHandler{ Draw.color(); TextureRegion region = block.icon(Icon.full); + Draw.rect(region, x * tilesize + block.offset(), y * tilesize + block.offset(), - region.getWidth() * selectScale * Draw.scl, - region.getHeight() * selectScale * Draw.scl, block.rotate ? rotation * 90 : 0); + region.getWidth() * selectScale * Draw.scl, + region.getHeight() * selectScale * Draw.scl, block.rotate ? rotation * 90 : 0); + + Draw.color(Pal.accent); + for(int i = 0; i < 4; i++){ + Point2 p = Geometry.d8edge[i]; + float offset = -Math.max(block.size-1, 0)/2f * tilesize; + Draw.rect("block-select", x * tilesize + block.offset() + offset * p.x, y * tilesize + block.offset() + offset * p.y, i * 90); + } + Draw.color(); }else{ - Draw.color(Palette.removeBack); + Draw.color(Pal.removeBack); Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset() - 1, block.size * tilesize / 2f); - Draw.color(Palette.remove); + Draw.color(Pal.remove); Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset(), block.size * tilesize / 2f); } } @@ -78,14 +84,14 @@ public class DesktopInput extends InputHandler{ int y = selectY + i * Mathf.sign(cursorY - selectY) * Mathf.num(!result.isX()); if(i + block.size > result.getLength() && block.rotate){ - Draw.color(!validPlace(x, y, block, result.rotation) ? Palette.removeBack : Palette.accentBack); + Draw.color(!validPlace(x, y, block, result.rotation) ? Pal.removeBack : Pal.accentBack); Draw.rect(Core.atlas.find("place-arrow"), x * tilesize + block.offset(), y * tilesize + block.offset() - 1, Core.atlas.find("place-arrow").getWidth() * Draw.scl, Core.atlas.find("place-arrow").getHeight() * Draw.scl, result.rotation * 90 - 90); - Draw.color(!validPlace(x, y, block, result.rotation) ? Palette.remove : Palette.accent); + Draw.color(!validPlace(x, y, block, result.rotation) ? Pal.remove : Pal.accent); Draw.rect(Core.atlas.find("place-arrow"), x * tilesize + block.offset(), y * tilesize + block.offset(), @@ -107,27 +113,27 @@ public class DesktopInput extends InputHandler{ if(tile == null || !validBreak(tile.x, tile.y)) continue; tile = tile.target(); - Draw.color(Palette.removeBack); + Draw.color(Pal.removeBack); Lines.square(tile.drawx(), tile.drawy()-1, tile.block().size * tilesize / 2f - 1); - Draw.color(Palette.remove); + Draw.color(Pal.remove); Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f - 1); } } - Draw.color(Palette.removeBack); + Draw.color(Pal.removeBack); Lines.rect(result.x, result.y - 1, result.x2 - result.x, result.y2 - result.y); - Draw.color(Palette.remove); + Draw.color(Pal.remove); Lines.rect(result.x, result.y, result.x2 - result.x, result.y2 - result.y); }else if(isPlacing()){ if(block.rotate){ - Draw.color(!validPlace(cursorX, cursorY, block, rotation) ? Palette.removeBack : Palette.accentBack); + Draw.color(!validPlace(cursorX, cursorY, block, rotation) ? Pal.removeBack : Pal.accentBack); Draw.rect(Core.atlas.find("place-arrow"), cursorX * tilesize + block.offset(), cursorY * tilesize + block.offset() - 1, Core.atlas.find("place-arrow").getWidth() * Draw.scl, Core.atlas.find("place-arrow").getHeight() * Draw.scl, rotation * 90 - 90); - Draw.color(!validPlace(cursorX, cursorY, block, rotation) ? Palette.remove : Palette.accent); + Draw.color(!validPlace(cursorX, cursorY, block, rotation) ? Pal.remove : Pal.accent); Draw.rect(Core.atlas.find("place-arrow"), cursorX * tilesize + block.offset(), cursorY * tilesize + block.offset(), @@ -158,7 +164,7 @@ public class DesktopInput extends InputHandler{ renderer.scaleCamera(Core.input.axisTap(Binding.zoom)); } - renderer.minimap.zoomBy(-Core.input.axisTap(Binding.zoom_minimap)); + //renderer.minimap.zoomBy(-Core.input.axisTap(Binding.zoom_minimap)); if(player.isDead()) return; @@ -291,12 +297,12 @@ public class DesktopInput extends InputHandler{ @Override public float getMouseX(){ - return !controlling ? Core.input.mouseX() : controlx; + return Core.input.mouseX(); } @Override public float getMouseY(){ - return !controlling ? Core.input.mouseY() : controly; + return Core.input.mouseY(); } @Override diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index 11a1fa8a56..71a0001de8 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -3,7 +3,6 @@ package io.anuke.mindustry.input; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; import io.anuke.arc.graphics.Color; import io.anuke.arc.input.InputProcessor; import io.anuke.arc.math.Angles; @@ -13,9 +12,10 @@ import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.effect.ItemTransfer; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.ValidateException; @@ -52,17 +52,17 @@ public abstract class InputHandler implements InputProcessor{ @Remote(targets = Loc.client, called = Loc.server) public static void dropItem(Player player, float angle){ - if(Net.server() && !player.inventory.hasItem()){ + if(Net.server() && player.item().amount <= 0){ throw new ValidateException(player, "Player cannot drop an item."); } - Effects.effect(Fx.dropItem, Color.WHITE, player.x, player.y, angle, player.inventory.getItem().item); - player.inventory.clearItem(); + Effects.effect(Fx.dropItem, Color.WHITE, player.x, player.y, angle, player.item().item); + player.clearItem(); } @Remote(targets = Loc.both, forward = true, called = Loc.server) public static void transferInventory(Player player, Tile tile){ - if(Net.server() && (!player.inventory.hasItem() || player.isTransferring)){ + if(Net.server() && (player.item().amount <= 0 || player.isTransferring)){ throw new ValidateException(player, "Player cannot transfer an item."); } @@ -70,10 +70,10 @@ public abstract class InputHandler implements InputProcessor{ player.isTransferring = true; - Item item = player.inventory.getItem().item; - int amount = player.inventory.getItem().amount; + Item item = player.item().item; + int amount = player.item().amount; int accepted = tile.block().acceptStack(item, amount, tile, player); - player.inventory.getItem().amount -= accepted; + player.item().amount -= accepted; int sent = Mathf.clamp(accepted / 4, 1, 8); int removed = accepted / sent; @@ -156,7 +156,7 @@ public abstract class InputHandler implements InputProcessor{ boolean consumed = false, showedInventory = false; //check if tapped block is configurable - if(tile.block().configurable && tile.getTeam() == player.getTeam()){ + if(tile.block().configurable && tile.interactable(player.getTeam())){ consumed = true; if(((!frag.config.isShown() && tile.block().shouldShowConfigure(tile, player)) //if the config fragment is hidden, show //alternatively, the current selected block can 'agree' to switch config tiles @@ -177,14 +177,14 @@ public abstract class InputHandler implements InputProcessor{ } //call tapped event - if(!consumed && tile.getTeam() == player.getTeam()){ + if(!consumed && tile.interactable(player.getTeam())){ Call.onTileTapped(player, tile); } //consume tap event if necessary - if(tile.getTeam() == player.getTeam() && tile.block().consumesTap){ + if(tile.interactable(player.getTeam()) && tile.block().consumesTap){ consumed = true; - }else if(tile.getTeam() == player.getTeam() && tile.block().synthetic() && !consumed){ + }else if(tile.interactable(player.getTeam()) && tile.block().synthetic() && !consumed){ if(tile.block().hasItems && tile.entity.items.total() > 0){ frag.inv.showFor(tile); consumed = true; @@ -215,7 +215,7 @@ public abstract class InputHandler implements InputProcessor{ } boolean canTapPlayer(float x, float y){ - return Mathf.dst(x, y, player.x, player.y) <= playerSelectRange && player.inventory.hasItem(); + return Mathf.dst(x, y, player.x, player.y) <= playerSelectRange && player.item().amount > 0; } /**Tries to begin mining a tile, returns true if successful.*/ @@ -232,7 +232,7 @@ public abstract class InputHandler implements InputProcessor{ return !Core.scene.hasMouse() && tile.floor().itemDrop != null && tile.floor().itemDrop.hardness <= player.mech.drillPower && !tile.floor().playerUnmineable - && player.inventory.canAcceptItem(tile.floor().itemDrop) + && player.acceptsItem(tile.floor().itemDrop) && tile.block() == Blocks.air && player.dst(tile.worldx(), tile.worldy()) <= Player.mineDistance; } @@ -287,16 +287,16 @@ public abstract class InputHandler implements InputProcessor{ } public void tryDropItems(Tile tile, float x, float y){ - if(!droppingItem || !player.inventory.hasItem() || canTapPlayer(x, y)){ + if(!droppingItem || player.item().amount <= 0 || canTapPlayer(x, y) || state.isPaused()){ droppingItem = false; return; } droppingItem = false; - ItemStack stack = player.inventory.getItem(); + ItemStack stack = player.item(); - if(tile.block().acceptStack(stack.item, stack.amount, tile, player) > 0 && tile.getTeam() == player.getTeam() && tile.block().hasItems){ + if(tile.block().acceptStack(stack.item, stack.amount, tile, player) > 0 && tile.interactable(player.getTeam()) && tile.block().hasItems){ Call.transferInventory(player, tile); }else{ Call.dropItem(player.angleTo(x, y)); diff --git a/core/src/io/anuke/mindustry/input/MobileInput.java b/core/src/io/anuke/mindustry/input/MobileInput.java index d2a0963c49..0e742a987c 100644 --- a/core/src/io/anuke/mindustry/input/MobileInput.java +++ b/core/src/io/anuke/mindustry/input/MobileInput.java @@ -3,7 +3,6 @@ package io.anuke.mindustry.input; import io.anuke.arc.Core; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectSet; -import io.anuke.arc.entities.Effects; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; @@ -13,21 +12,24 @@ import io.anuke.arc.input.GestureDetector.GestureListener; import io.anuke.arc.input.KeyCode; import io.anuke.arc.math.Interpolation; import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Geometry; +import io.anuke.arc.math.geom.Point2; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Align; import io.anuke.arc.util.Time; +import io.anuke.arc.util.Tmp; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.TargetTrait; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.graphics.Shaders; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.input.PlaceUtils.NormalizeDrawResult; import io.anuke.mindustry.input.PlaceUtils.NormalizeResult; import io.anuke.mindustry.ui.dialogs.FloatingDialog; @@ -173,20 +175,30 @@ public class MobileInput extends InputHandler implements GestureListener{ float offset = request.block.offset(); TextureRegion region = request.block.icon(Icon.full); - Draw.alpha(Mathf.clamp((1f - request.scale) / 0.5f)); - Draw.tint(Color.WHITE, Palette.breakInvalid, request.redness); + Draw.mixcol(Pal.accent, Mathf.clamp((1f - request.scale) / 0.5f)); + Draw.tint(Color.WHITE, Pal.breakInvalid, request.redness); Draw.rect(region, tile.worldx() + offset, tile.worldy() + offset, region.getWidth() * request.scale * Draw.scl, region.getHeight() * request.scale * Draw.scl, request.block.rotate ? request.rotation * 90 : 0); + + Draw.mixcol(Pal.accent, 1f); + for(int i = 0; i < 4; i++){ + Point2 p = Geometry.d8edge[i]; + float poffset = -Math.max(request.block.size-1, 0)/2f * tilesize; + TextureRegion find = Core.atlas.find("block-select"); + Draw.rect("block-select", request.tile().x * tilesize + request.block.offset() + poffset * p.x, request.tile().y * tilesize + request.block.offset() + poffset * p.y, + find.getWidth() * Draw.scl * request.scale, find.getHeight() * Draw.scl * request.scale, i * 90); + } + Draw.color(); }else{ float rad = (tile.block().size * tilesize / 2f - 1) * request.scale; - Draw.alpha(0f); + Draw.mixcol(); //draw removing request - Draw.tint(Palette.removeBack); + Draw.tint(Pal.removeBack); Lines.square(tile.drawx(), tile.drawy()-1, rad); - Draw.tint(Palette.remove); + Draw.tint(Pal.remove); Lines.square(tile.drawx(), tile.drawy(), rad); } } @@ -207,13 +219,30 @@ public class MobileInput extends InputHandler implements GestureListener{ } } + void drawPlaceArrow(Block block, int x, int y, int rotation){ + if(!block.rotate) return; + Draw.color(!validPlace(x, y, block, rotation) ? Pal.removeBack : Pal.accentBack); + Draw.rect(Core.atlas.find("place-arrow"), + x * tilesize + block.offset(), + y * tilesize + block.offset() - 1, + Core.atlas.find("place-arrow").getWidth() * Draw.scl, + Core.atlas.find("place-arrow").getHeight() * Draw.scl, rotation * 90 - 90); + + Draw.color(!validPlace(x, y, block, rotation) ? Pal.remove : Pal.accent); + Draw.rect(Core.atlas.find("place-arrow"), + x * tilesize + block.offset(), + y * tilesize + block.offset(), + Core.atlas.find("place-arrow").getWidth() * Draw.scl, + Core.atlas.find("place-arrow").getHeight() * Draw.scl, rotation * 90 - 90); + } + //endregion //region UI and drawing @Override public void buildUI(Table table){ - table.addImage("blank").color(Palette.accent).height(3f).colspan(4).growX(); + table.addImage("blank").color(Pal.accent).height(3f).colspan(4).growX(); table.row(); table.left().margin(0f).defaults().size(48f); @@ -277,9 +306,6 @@ public class MobileInput extends InputHandler implements GestureListener{ public void drawOutlined(){ Lines.stroke(1f); - Shaders.mix.color.set(Palette.accent); - Draw.shader(Shaders.mix); - //draw removals for(PlaceRequest request : removals){ Tile tile = request.tile(); @@ -303,22 +329,29 @@ public class MobileInput extends InputHandler implements GestureListener{ request.scale = Mathf.lerpDelta(request.scale, 1f, 0.2f); request.redness = Mathf.lerpDelta(request.redness, 0f, 0.2f); }else{ - request.scale = Mathf.lerpDelta(request.scale, 0.5f, 0.1f); - request.redness = Mathf.lerpDelta(request.redness, 1f, 0.2f); + request.scale = Mathf.lerpDelta(request.scale, 0.6f, 0.1f); + request.redness = Mathf.lerpDelta(request.redness, 0.9f, 0.2f); } + Tmp.c1.set(Draw.getMixColor()); + if(!request.remove && request == lastPlaced && request.block != null){ + Draw.mixcol(); + drawPlaceArrow(request.block, tile.x, tile.y, request.rotation); + } + + Draw.mixcol(Tmp.c1, 1f); drawRequest(request); //draw last placed request if(!request.remove && request == lastPlaced && request.block != null){ + Draw.mixcol(); request.block.drawPlace(tile.x, tile.y, rotation, validPlace(tile.x, tile.y, request.block, rotation)); } } - Draw.shader(); - - Draw.color(Palette.accent); + Draw.mixcol(); + Draw.color(Pal.accent); //Draw lines if(lineMode){ @@ -327,12 +360,19 @@ public class MobileInput extends InputHandler implements GestureListener{ //draw placing if(mode == placing && block != null){ + NormalizeDrawResult dresult = PlaceUtils.normalizeDrawArea(block, lineStartX, lineStartY, tileX, tileY, true, maxLength, lineScale); Lines.rect(dresult.x, dresult.y, dresult.x2 - dresult.x, dresult.y2 - dresult.y); NormalizeResult result = PlaceUtils.normalizeArea(lineStartX, lineStartY, tileX, tileY, rotation, true, maxLength); + { + int x = lineStartX + result.getLength() * Mathf.sign(tileX - lineStartX) * Mathf.num(result.isX()); + int y = lineStartY + result.getLength() * Mathf.sign(tileY - lineStartY) * Mathf.num(!result.isX()); + drawPlaceArrow(block, x, y, result.rotation); + } + //go through each cell and draw the block to place if valid for(int i = 0; i <= result.getLength(); i += block.size){ int x = lineStartX + i * Mathf.sign(tileX - lineStartX) * Mathf.num(result.isX()); @@ -347,10 +387,18 @@ public class MobileInput extends InputHandler implements GestureListener{ region.getWidth() * lineScale * Draw.scl, region.getHeight() * lineScale * Draw.scl, block.rotate ? result.rotation * 90 : 0); + + Draw.color(Pal.accent); + for(int j = 0; j < 4; j++){ + Point2 p = Geometry.d8edge[j]; + float offset = -Math.max(block.size-1, 0)/2f * tilesize; + Draw.rect("block-select", x * tilesize + block.offset() + offset * p.x, y * tilesize + block.offset() + offset * p.y,j * 90); + } + Draw.color(); }else{ - Draw.color(Palette.removeBack); + Draw.color(Pal.removeBack); Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset() - 1, block.size * tilesize / 2f); - Draw.color(Palette.remove); + Draw.color(Pal.remove); Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset(), block.size * tilesize / 2f); } } @@ -366,16 +414,16 @@ public class MobileInput extends InputHandler implements GestureListener{ if(other == null || !validBreak(other.x, other.y)) continue; other = other.target(); - Draw.color(Palette.removeBack); + Draw.color(Pal.removeBack); Lines.square(other.drawx(), other.drawy()-1, other.block().size * tilesize / 2f - 1); - Draw.color(Palette.remove); + Draw.color(Pal.remove); Lines.square(other.drawx(), other.drawy(), other.block().size * tilesize / 2f - 1); } } - Draw.color(Palette.removeBack); + Draw.color(Pal.removeBack); Lines.rect(result.x, result.y - 1, result.x2 - result.x, result.y2 - result.y); - Draw.color(Palette.remove); + Draw.color(Pal.remove); Lines.rect(result.x, result.y, result.x2 - result.x, result.y2 - result.y); } @@ -393,7 +441,7 @@ public class MobileInput extends InputHandler implements GestureListener{ crosshairScale = Mathf.lerpDelta(crosshairScale, 1f, 0.2f); - Draw.color(Palette.remove); + Draw.color(Pal.remove); Lines.stroke(1f); float radius = Interpolation.swingIn.apply(crosshairScale); @@ -547,27 +595,8 @@ public class MobileInput extends InputHandler implements GestureListener{ //add to selection queue if it's a valid BREAK position cursor = cursor.target(); selection.add(new PlaceRequest(cursor.worldx(), cursor.worldy())); - }else if(!canTapPlayer(worldx, worldy)){ - boolean consumed = false; - //else, try and carry units - if(player.mech.flying){ - if(player.getCarry() != null){ - consumed = true; - player.dropCarry(); //drop off unit - }else{ - Unit unit = Units.getClosest(player.getTeam(), Core.input.mouseWorld(x, y).x, Core.input.mouseWorld(x, y).y, 4f, u -> !u.isFlying() && u.mass() <= player.mech.carryWeight); - - if(unit != null){ - consumed = true; - player.moveTarget = unit; - Effects.effect(Fx.select, unit.getX(), unit.getY()); - } - } - } - - if(!consumed && !tileTapped(cursor.target())){ - tryBeginMine(cursor); - } + }else if(!canTapPlayer(worldx, worldy) && !tileTapped(cursor.target())){ + tryBeginMine(cursor); } return false; @@ -661,7 +690,8 @@ public class MobileInput extends InputHandler implements GestureListener{ @Override public boolean pan(float x, float y, float deltaX, float deltaY){ - if(!canPan) return false; + if(Core.scene.hasDialog()) return false; + float scale = Core.camera.width / Core.graphics.getWidth(); deltaX *= scale; deltaY *= scale; @@ -690,23 +720,12 @@ public class MobileInput extends InputHandler implements GestureListener{ public boolean zoom(float initialDistance, float distance){ if(lastDistance == -1) lastDistance = initialDistance; - float amount = (distance > lastDistance ? 0.07f : -0.07f) * Time.delta(); + float amount = (Mathf.sign(distance > lastDistance) * 0.07f) * Time.delta(); renderer.scaleCamera(io.anuke.arc.scene.ui.layout.Unit.dp.scl(amount)); lastDistance = distance; return true; } - @Override - public boolean touchDown(float x, float y, int pointer, KeyCode button){ - canPan = !Core.scene.hasMouse(); - return false; - } - - @Override - public boolean fling(float velocityX, float velocityY, KeyCode button){ - return false; - } - //endregion class PlaceRequest{ diff --git a/core/src/io/anuke/mindustry/io/BundleLoader.java b/core/src/io/anuke/mindustry/io/BundleLoader.java index 497d7f14cb..ba11207bf1 100644 --- a/core/src/io/anuke/mindustry/io/BundleLoader.java +++ b/core/src/io/anuke/mindustry/io/BundleLoader.java @@ -39,6 +39,8 @@ public class BundleLoader{ } private static void loadBundle(){ + if(headless) return; + try{ //try loading external bundle FileHandle handle = Core.files.local("bundle"); diff --git a/core/src/io/anuke/mindustry/io/MapIO.java b/core/src/io/anuke/mindustry/io/MapIO.java index 15c8334726..7216e315aa 100644 --- a/core/src/io/anuke/mindustry/io/MapIO.java +++ b/core/src/io/anuke/mindustry/io/MapIO.java @@ -1,96 +1,165 @@ package io.anuke.mindustry.io; +import io.anuke.arc.collection.IntIntMap; import io.anuke.arc.collection.ObjectMap; import io.anuke.arc.collection.ObjectMap.Entry; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.Pixmap; +import io.anuke.arc.graphics.Pixmap.Format; import io.anuke.arc.util.Pack; +import io.anuke.arc.util.Structs; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.game.MappableContent; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.game.Version; import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.BlockPart; +import io.anuke.mindustry.maps.MapMeta; +import io.anuke.mindustry.maps.MapTileData; +import io.anuke.mindustry.maps.MapTileData.DataPosition; +import io.anuke.mindustry.maps.MapTileData.TileDataMarker; +import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.LegacyColorMapper; +import io.anuke.mindustry.world.LegacyColorMapper.LegacyBlock; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; +import java.io.*; import static io.anuke.mindustry.Vars.content; -import static io.anuke.mindustry.Vars.world; -/** Reads and writes map files.*/ +/** + * Reads and writes map files. + */ +//TODO name mapping public class MapIO{ + private static final int[] pngHeader = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}; private static final int version = 0; + private static IntIntMap defaultBlockMap = new IntIntMap(); - //TODO implement - public static Pixmap generatePixmap(Map map){ - return null; - } - - //TODO implement - /**Reads a pixmap in the 3.5 pixmap format.*/ - public static Tile[][] readLegacyPixmap(Pixmap pixmap){ - return null; - } - - //TODO implement - /**Reads a pixmap in the 4.0 .mmap format.*/ - public static Tile[][] readLegacyMmap(DataInputStream stream) throws IOException{ - return null; - } - - public static void writeMap(Map map, Tile[][] tiles, DataOutputStream stream) throws IOException{ - stream.writeInt(version); - stream.writeInt(Version.build); - stream.writeByte((byte) map.tags.size); - - for(Entry entry : map.tags.entries()){ - stream.writeUTF(entry.key); - stream.writeUTF(entry.value); - } - - SaveIO.getSaveWriter().writeContentHeader(stream); - - stream.writeShort(tiles.length); - stream.writeShort(tiles[0].length); - - for(int i = 0; i < tiles.length * tiles[0].length; i++){ - Tile tile = world.tile(i % world.width(), i / world.width()); - - stream.writeByte(tile.getFloorID()); - stream.writeByte(tile.getBlockID()); - - if(tile.block() instanceof BlockPart){ - stream.writeByte(tile.link); - }else if(tile.entity != null){ - stream.writeByte(Pack.byteByte(tile.getTeamID(), tile.getRotation())); //team + rotation - stream.writeShort((short) tile.entity.health); //health - tile.entity.writeConfig(stream); - }else if(tile.block() == Blocks.air){ - int consecutives = 0; - - for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){ - Tile nextTile = world.tile(j % world.width(), j / world.width()); - - if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air){ - break; - } - - consecutives++; + public static boolean isImage(FileHandle file){ + try(InputStream stream = file.read()){ + for(int i1 : pngHeader){ + if(stream.read() != i1){ + return false; } + } + return true; + }catch(IOException e){ + return false; + } + } - stream.writeByte(consecutives); - i += consecutives; + private static void loadDefaultBlocks(){ + for(Block block : content.blocks()){ + defaultBlockMap.put(block.id, block.id); + } + } + + public static Pixmap generatePixmap(MapTileData data){ + Pixmap pixmap = new Pixmap(data.width(), data.height(), Format.RGBA8888); + data.position(0, 0); + + TileDataMarker marker = data.newDataMarker(); + + for(int y = 0; y < data.height(); y++){ + for(int x = 0; x < data.width(); x++){ + data.read(marker); + Block floor = content.block(marker.floor); + Block wall = content.block(marker.wall); + int color = colorFor(floor, wall, Team.all[marker.team]); + pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, color); } } + + data.position(0, 0); + + return pixmap; } - public static Map readMap(String useName, DataInputStream stream) throws IOException{ + /**Reads a pixmap in the old (3.5) map format.*/ + public static MapTileData readLegacyPixmap(Pixmap pixmap){ + MapTileData data = new MapTileData(pixmap.getWidth(), pixmap.getHeight()); + + for(int x = 0; x < data.width(); x++){ + for(int y = 0; y < data.height(); y++){ + int color = pixmap.getPixel(x, pixmap.getHeight() - 1 - y); + LegacyBlock block = LegacyColorMapper.get(color); + + data.write(x, y, DataPosition.floor, block.floor.id); + data.write(x, y, DataPosition.wall, block.wall.id); + + //place core + if(color == Color.rgba8888(Color.GREEN)){ + for(int dx = 0; dx < 3; dx++){ + for(int dy = 0; dy < 3; dy++){ + int worldx = dx - 1 + x; + int worldy = dy - 1 + y; + + if(Structs.inBounds(worldx, worldy, pixmap.getWidth(), pixmap.getHeight())){ + data.write(worldx, worldy, DataPosition.wall, Blocks.part.id); + data.write(worldx, worldy, DataPosition.rotationTeam, Pack.byteByte((byte)0, (byte)Team.blue.ordinal())); + data.write(worldx, worldy, DataPosition.link, Pack.byteByte((byte) (dx - 1 + 8), (byte) (dy - 1 + 8))); + } + } + } + + data.write(x, y, DataPosition.wall, Blocks.coreShard.id); + data.write(x, y, DataPosition.rotationTeam, Pack.byteByte((byte)0, (byte)Team.blue.ordinal())); + } + } + } + + return data; + } + + public static void writeMap(OutputStream stream, ObjectMap tags, MapTileData data) throws IOException{ + if(defaultBlockMap == null){ + loadDefaultBlocks(); + } + + MapMeta meta = new MapMeta(version, tags, data.width(), data.height(), defaultBlockMap); + + DataOutputStream ds = new DataOutputStream(stream); + + writeMapMeta(ds, meta); + ds.write(data.toArray()); + + ds.close(); + } + + /** + * Reads tile data, skipping meta. + */ + public static MapTileData readTileData(DataInputStream stream, boolean readOnly) throws IOException{ + MapMeta meta = readMapMeta(stream); + return readTileData(stream, meta, readOnly); + } + + + /** + * Does not skip meta. Call after reading meta. + */ + public static MapTileData readTileData(DataInputStream stream, MapMeta meta, boolean readOnly) throws IOException{ + byte[] bytes = new byte[stream.available()]; + stream.readFully(bytes); + return new MapTileData(bytes, meta.width, meta.height, meta.blockMap, readOnly); + } + + /** + * Reads tile data, skipping meta tags. + */ + public static MapTileData readTileData(Map map, boolean readOnly){ + try(DataInputStream ds = new DataInputStream(map.stream.get())){ + return MapIO.readTileData(ds, readOnly); + }catch(IOException e){ + throw new RuntimeException(e); + } + } + + public static MapMeta readMapMeta(DataInputStream stream) throws IOException{ ObjectMap tags = new ObjectMap<>(); + IntIntMap map = new IntIntMap(); + + int version = stream.readInt(); - int version = stream.readInt(); //version - int build = stream.readInt(); byte tagAmount = stream.readByte(); for(int i = 0; i < tagAmount; i++){ @@ -99,65 +168,46 @@ public class MapIO{ tags.put(name, value); } - return new Map(useName); - } - - public static Tile[][] readTiles(DataInputStream stream) throws IOException{ - readMap("this map name is utterly irrelevant", stream); - - MappableContent[][] c = SaveIO.getSaveWriter().readContentHeader(stream); + short blocks = stream.readShort(); + for(int i = 0; i < blocks; i++){ + short id = stream.readShort(); + String name = stream.readUTF(); + Block block = content.getByName(ContentType.block, name); + if(block == null){ + block = Blocks.air; + } + map.put(id, block.id); + } int width = stream.readShort(); int height = stream.readShort(); - try{ + return new MapMeta(version, tags, width, height, map); + } - content.setTemporaryMapper(c); + public static void writeMapMeta(DataOutputStream stream, MapMeta meta) throws IOException{ + stream.writeInt(meta.version); + stream.writeByte((byte) meta.tags.size); - Tile[][] tiles = new Tile[width][height]; - - for(int i = 0; i < width * height; i++){ - int x = i % width, y = i / width; - byte floorid = stream.readByte(); - byte wallid = stream.readByte(); - - Tile tile = new Tile(x, y, floorid, wallid); - - if(wallid == Blocks.part.id){ - tile.link = stream.readByte(); - }else if(tile.entity != null){ - byte tr = stream.readByte(); - short health = stream.readShort(); - - byte team = Pack.leftByte(tr); - byte rotation = Pack.rightByte(tr); - - Team t = Team.all[team]; - - tile.setTeam(Team.all[team]); - tile.entity.health = health; - tile.setRotation(rotation); - - tile.entity.readConfig(stream); - }else if(wallid == 0){ - int consecutives = stream.readUnsignedByte(); - - for(int j = i + 1; j < i + 1 + consecutives; j++){ - int newx = j % width, newy = j / width; - Tile newTile = new Tile(newx, newy, floorid, wallid); - tiles[newx][newy] = newTile; - } - - i += consecutives; - } - - tiles[x][y] = tile; - } - - return tiles; - - }finally{ - content.setTemporaryMapper(null); + for(Entry entry : meta.tags.entries()){ + stream.writeUTF(entry.key); + stream.writeUTF(entry.value); } + + stream.writeShort(content.blocks().size); + for(Block block : content.blocks()){ + stream.writeShort(block.id); + stream.writeUTF(block.name); + } + + stream.writeShort(meta.width); + stream.writeShort(meta.height); + } + + public static int colorFor(Block floor, Block wall, Team team){ + if(wall.synthetic()){ + return team.intColor; + } + return Color.rgba8888(wall.solid ? wall.color : floor.color); } } diff --git a/core/src/io/anuke/mindustry/io/SaveFileVersion.java b/core/src/io/anuke/mindustry/io/SaveFileVersion.java index b7f3c2784e..e304816eef 100644 --- a/core/src/io/anuke/mindustry/io/SaveFileVersion.java +++ b/core/src/io/anuke/mindustry/io/SaveFileVersion.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.io; import io.anuke.arc.collection.Array; -import io.anuke.arc.entities.Entities; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.trait.Entity; import io.anuke.arc.util.Pack; import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.entities.Entities; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.traits.Entity; import io.anuke.mindustry.entities.traits.SaveTrait; import io.anuke.mindustry.entities.traits.TypeTrait; import io.anuke.mindustry.game.Content; @@ -16,13 +16,13 @@ import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.BlockPart; -import io.anuke.mindustry.world.blocks.storage.CoreBlock; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.content; +import static io.anuke.mindustry.Vars.world; public abstract class SaveFileVersion{ public final int version; @@ -110,8 +110,6 @@ public abstract class SaveFileVersion{ byte team = Pack.leftByte(tr); byte rotation = Pack.rightByte(tr); - Team t = Team.all[team]; - tile.setTeam(Team.all[team]); tile.entity.health = health; tile.setRotation(rotation); @@ -123,10 +121,6 @@ public abstract class SaveFileVersion{ tile.entity.readConfig(stream); tile.entity.read(stream); - - if(tile.block() instanceof CoreBlock){ - state.teams.get(t).cores.add(tile); - } }else if(wallid == 0){ int consecutives = stream.readUnsignedByte(); @@ -217,7 +211,7 @@ public abstract class SaveFileVersion{ stream.writeByte(arr.first().getContentType().ordinal()); stream.writeShort(arr.size); for(Content c : arr){ - stream.writeUTF(((MappableContent) c).getContentName()); + stream.writeUTF(((MappableContent) c).name); } } } diff --git a/core/src/io/anuke/mindustry/io/TypeIO.java b/core/src/io/anuke/mindustry/io/TypeIO.java index 0d87fb38f3..c88bce34eb 100644 --- a/core/src/io/anuke/mindustry/io/TypeIO.java +++ b/core/src/io/anuke/mindustry/io/TypeIO.java @@ -2,23 +2,24 @@ package io.anuke.mindustry.io; import io.anuke.annotations.Annotations.ReadClass; import io.anuke.annotations.Annotations.WriteClass; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; -import io.anuke.arc.entities.Entities; import io.anuke.arc.graphics.Color; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; +import io.anuke.mindustry.entities.Entities; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; -import io.anuke.mindustry.entities.traits.CarriableTrait; -import io.anuke.mindustry.entities.traits.CarryTrait; import io.anuke.mindustry.entities.traits.ShooterTrait; -import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.net.Packets.AdminAction; import io.anuke.mindustry.net.Packets.KickReason; -import io.anuke.mindustry.type.*; +import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.type.Mech; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Pos; import io.anuke.mindustry.world.Tile; @@ -27,7 +28,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import static io.anuke.mindustry.Vars.*; @@ -92,46 +92,6 @@ public class TypeIO{ return bulletGroup.getByID(id); } - @WriteClass(CarriableTrait.class) - public static void writeCarriable(ByteBuffer buffer, CarriableTrait unit){ - if(unit == null){ - buffer.put((byte) -1); - return; - } - buffer.put((byte) unit.getGroup().getID()); - buffer.putInt(unit.getID()); - } - - @ReadClass(CarriableTrait.class) - public static CarriableTrait readCarriable(ByteBuffer buffer){ - byte gid = buffer.get(); - if(gid == -1){ - return null; - } - int id = buffer.getInt(); - return (CarriableTrait) Entities.getGroup(gid).getByID(id); - } - - @WriteClass(CarryTrait.class) - public static void writeCarry(ByteBuffer buffer, CarryTrait unit){ - if(unit == null || unit.getGroup() == null){ - buffer.put((byte) -1); - return; - } - buffer.put((byte) unit.getGroup().getID()); - buffer.putInt(unit.getID()); - } - - @ReadClass(CarryTrait.class) - public static CarryTrait readCarry(ByteBuffer buffer){ - byte gid = buffer.get(); - if(gid == -1){ - return null; - } - int id = buffer.getInt(); - return (CarryTrait) Entities.getGroup(gid).getByID(id); - } - @WriteClass(BaseUnit.class) public static void writeBaseUnit(ByteBuffer buffer, BaseUnit unit){ buffer.put((byte) unitGroups[unit.getTeam().ordinal()].getID()); @@ -251,16 +211,6 @@ public class TypeIO{ return new Color(buffer.getInt()); } - @WriteClass(Weapon.class) - public static void writeWeapon(ByteBuffer buffer, Weapon weapon){ - buffer.put(weapon.id); - } - - @ReadClass(Weapon.class) - public static Weapon readWeapon(ByteBuffer buffer){ - return content.getByID(ContentType.weapon, buffer.get()); - } - @WriteClass(Mech.class) public static void writeMech(ByteBuffer buffer, Mech mech){ buffer.put(mech.id); @@ -305,7 +255,7 @@ public class TypeIO{ @WriteClass(String.class) public static void writeString(ByteBuffer buffer, String string){ if(string != null){ - byte[] bytes = string.getBytes(StandardCharsets.UTF_8); + byte[] bytes = string.getBytes(charset); buffer.putShort((short) bytes.length); buffer.put(bytes); }else{ @@ -319,7 +269,7 @@ public class TypeIO{ if(slength != -1){ byte[] bytes = new byte[slength]; buffer.get(bytes); - return new String(bytes, StandardCharsets.UTF_8); + return new String(bytes, charset); }else{ return null; } @@ -341,7 +291,7 @@ public class TypeIO{ public static void writeStringData(DataOutput buffer, String string) throws IOException{ if(string != null){ - byte[] bytes = string.getBytes(StandardCharsets.UTF_8); + byte[] bytes = string.getBytes(charset); buffer.writeShort((short) bytes.length); buffer.write(bytes); }else{ @@ -354,7 +304,7 @@ public class TypeIO{ if(slength != -1){ byte[] bytes = new byte[slength]; buffer.readFully(bytes); - return new String(bytes, StandardCharsets.UTF_8); + return new String(bytes, charset); }else{ return null; } diff --git a/core/src/io/anuke/mindustry/io/versions/Save16.java b/core/src/io/anuke/mindustry/io/versions/Save16.java index 3735f3c17c..40c2c2f371 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save16.java +++ b/core/src/io/anuke/mindustry/io/versions/Save16.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.io.versions; +import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Serialization; @@ -34,7 +35,7 @@ public class Save16 extends SaveFileVersion{ } String mapname = stream.readUTF(); Map map = world.maps.getByName(mapname); - if(map == null) map = new Map("unknown", 1, 1); + if(map == null) map = new Map(Strings.capitalize(mapname), 1, 1); world.setMap(map); int wave = stream.readInt(); @@ -43,6 +44,7 @@ public class Save16 extends SaveFileVersion{ state.wave = wave; state.wavetime = wavetime; state.stats = Serialization.readStats(stream); + world.spawner.read(stream); content.setTemporaryMapper(readContentHeader(stream)); @@ -66,6 +68,7 @@ public class Save16 extends SaveFileVersion{ stream.writeFloat(state.wavetime); //wave countdown Serialization.writeStats(stream, state.stats); + world.spawner.write(stream); writeContentHeader(stream); diff --git a/core/src/io/anuke/mindustry/maps/MapException.java b/core/src/io/anuke/mindustry/maps/MapException.java new file mode 100644 index 0000000000..7bc1c76805 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/MapException.java @@ -0,0 +1,10 @@ +package io.anuke.mindustry.maps; + +public class MapException extends RuntimeException{ + public final Map map; + + public MapException(Map map, String s){ + super(s); + this.map = map; + } +} diff --git a/core/src/io/anuke/mindustry/maps/Maps.java b/core/src/io/anuke/mindustry/maps/Maps.java index 51f8b85ec6..2bd7823ad5 100644 --- a/core/src/io/anuke/mindustry/maps/Maps.java +++ b/core/src/io/anuke/mindustry/maps/Maps.java @@ -54,7 +54,7 @@ public class Maps implements Disposable{ /**Returns map by internal name.*/ public Map getByName(String name){ - return maps.get(name.toLowerCase()); + return maps.get(name); } /**Loads a map from the map folder and returns it. Should only be used for zone maps. @@ -136,7 +136,7 @@ public class Maps implements Disposable{ map.texture = new Texture(MapIO.generatePixmap(MapIO.readTileData(ds, meta, true))); } - maps.put(map.name.toLowerCase(), map); + maps.put(map.name, map); allMaps.add(map); } } diff --git a/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java b/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java index 948272bb68..e348bca08b 100644 --- a/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java +++ b/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java @@ -21,7 +21,6 @@ public class BasicGenerator extends RandomGenerator{ @Override public void generate(Tile[][] tiles){ - //todo use set seed int seed = Mathf.random(99999999); sim.setSeed(seed); sim2.setSeed(seed + 1); diff --git a/core/src/io/anuke/mindustry/maps/generators/Generator.java b/core/src/io/anuke/mindustry/maps/generators/Generator.java index dac0b08093..a9d31fe87c 100644 --- a/core/src/io/anuke/mindustry/maps/generators/Generator.java +++ b/core/src/io/anuke/mindustry/maps/generators/Generator.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.maps.generators; +import io.anuke.mindustry.type.Loadout; import io.anuke.mindustry.world.Tile; public abstract class Generator{ @@ -12,7 +13,7 @@ public abstract class Generator{ public Generator(){} - public void init(){ + public void init(Loadout loadout){ } diff --git a/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java b/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java index f2ba259c82..c083662278 100644 --- a/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java +++ b/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java @@ -3,25 +3,41 @@ package io.anuke.mindustry.maps.generators; import io.anuke.arc.collection.Array; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Point2; +import io.anuke.arc.util.Structs; import io.anuke.arc.util.noise.Simplex; import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.content.Items; import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.maps.Map; +import io.anuke.mindustry.maps.MapTileData; +import io.anuke.mindustry.maps.MapTileData.TileDataMarker; +import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.type.Loadout; +import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.Floor; +import io.anuke.mindustry.world.blocks.OreBlock; +import io.anuke.mindustry.world.blocks.StaticWall; import io.anuke.mindustry.world.blocks.storage.CoreBlock; +import io.anuke.mindustry.world.blocks.storage.StorageBlock; -import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.content; +import static io.anuke.mindustry.Vars.world; public class MapGenerator extends Generator{ private Map map; private String mapName; - + private Array decorations = new Array<>(); + private Loadout loadout; /**How much the landscape is randomly distorted.*/ public float distortion = 3; - /**The amount of final enemy spawns used. -1 to use everything in the map. * This amount of enemy spawns is selected randomly from the map.*/ public int enemySpawns = -1; + /**Whether floor is distorted along with blocks.*/ + public boolean distortFloor = false; + /**Items randomly added to containers and vaults.*/ + public ItemStack[] storageDrops = ItemStack.with(Items.copper, 300, Items.lead, 300, Items.silicon, 200, Items.graphite, 200, Items.blastCompound, 200); public MapGenerator(String mapName){ this.mapName = mapName; @@ -32,8 +48,30 @@ public class MapGenerator extends Generator{ this.enemySpawns = enemySpawns; } + public MapGenerator drops(ItemStack[] drops){ + this.storageDrops = drops; + return this; + } + + public MapGenerator decor(Decoration... decor){ + this.decorations.addAll(decor); + return this; + } + + public MapGenerator dist(float distortion){ + this.distortion = distortion; + return this; + } + + public MapGenerator dist(float distortion, boolean floor){ + this.distortion = distortion; + this.distortFloor = floor; + return this; + } + @Override - public void init(){ + public void init(Loadout loadout){ + this.loadout = loadout; map = world.maps.loadInternalMap(mapName); width = map.meta.width; height = map.meta.height; @@ -71,23 +109,64 @@ public class MapGenerator extends Generator{ for(int x = 0; x < data.width(); x++){ for(int y = 0; y < data.height(); y++){ final double scl = 10; + Tile tile = tiles[x][y]; int newX = Mathf.clamp((int)(simplex.octaveNoise2D(1, 1, 1.0 / scl, x, y) * distortion + x), 0, data.width()-1); int newY = Mathf.clamp((int)(simplex.octaveNoise2D(1, 1, 1.0 / scl, x + 9999, y + 9999) * distortion + y), 0, data.height()-1); - if(tiles[newX][newY].block() != Blocks.spawn && !tiles[x][y].block().synthetic()&& !tiles[newX][newY].block().synthetic()){ - tiles[x][y].setBlock(tiles[newX][newY].block()); + + if((tile.block() instanceof StaticWall + && tiles[newX][newY].block() instanceof StaticWall) + || (tile.block() == Blocks.air && !tiles[newX][newY].block().synthetic()) + || (tiles[newX][newY].block() == Blocks.air && tile.block() instanceof StaticWall)){ + tile.setBlock(tiles[newX][newY].block()); + } + + if(distortFloor){ + tile.setFloor(tiles[newX][newY].floor()); + } + + for(Decoration decor : decorations){ + if(tile.block() == Blocks.air && !(decor.wall instanceof Floor) && tile.floor() == decor.floor && Mathf.chance(decor.chance)){ + tile.setBlock(decor.wall); + }else if(tile.floor() == decor.floor && decor.wall instanceof Floor && Mathf.chance(decor.chance)){ + tile.setFloor((Floor)decor.wall); + } + } + + if(tile.block() instanceof StorageBlock && !(tile.block() instanceof CoreBlock)){ + for(ItemStack stack : storageDrops){ + if(Mathf.chance(0.3)){ + tile.entity.items.add(stack.item, Math.min(Mathf.random(stack.amount), tile.block().itemCapacity)); + } + } } } } - if(enemySpawns > enemies.size){ - throw new IllegalArgumentException("Enemy spawn pool greater than map spawn number."); - } - if(enemySpawns != -1){ + if(enemySpawns > enemies.size){ + throw new IllegalArgumentException("Enemy spawn pool greater than map spawn number."); + } + enemies.shuffle(); for(int i = 0; i < enemySpawns; i++){ Point2 point = enemies.get(i); tiles[point.x][point.y].setBlock(Blocks.spawn); + + int rad = 10, frad = 12; + + for(int x = -rad; x <= rad; x++){ + for(int y = -rad; y <= rad; y++){ + int wx = x + point.x, wy = y + point.y; + double dst = Mathf.dst(x, y); + if(dst < frad && Structs.inBounds(wx, wy, tiles) && (dst <= rad || Mathf.chance(0.5))){ + Tile tile = tiles[wx][wy]; + if(tile.floor() instanceof OreBlock){ + OreBlock block = (OreBlock)tile.floor(); + tile.setFloor(block.base); + } + } + } + } } } @@ -96,10 +175,21 @@ public class MapGenerator extends Generator{ throw new IllegalArgumentException("All zone maps must have a core."); } - //TODO set specific core block? - tiles[core.x][core.y].setBlock(Blocks.core, defaultTeam); + loadout.setup(core.x, core.y); world.prepareTiles(tiles); world.setMap(map); } + + public static class Decoration{ + public final Block floor; + public final Block wall; + public final double chance; + + public Decoration(Block floor, Block wall, double chance){ + this.floor = floor; + this.wall = wall; + this.chance = chance; + } + } } diff --git a/core/src/io/anuke/mindustry/maps/generators/RandomGenerator.java b/core/src/io/anuke/mindustry/maps/generators/RandomGenerator.java index 74a51a360c..9692f0dc54 100644 --- a/core/src/io/anuke/mindustry/maps/generators/RandomGenerator.java +++ b/core/src/io/anuke/mindustry/maps/generators/RandomGenerator.java @@ -24,7 +24,7 @@ public abstract class RandomGenerator extends Generator{ } } - tiles[width/2][height/2].setBlock(Blocks.core, Team.blue); + tiles[width/2][height/2].setBlock(Blocks.coreShard, Team.blue); tiles[width/2][height/2 - 6].setBlock(Blocks.launchPad, Team.blue); } diff --git a/core/src/io/anuke/mindustry/net/Administration.java b/core/src/io/anuke/mindustry/net/Administration.java index 5d6745699b..52de0350f5 100644 --- a/core/src/io/anuke/mindustry/net/Administration.java +++ b/core/src/io/anuke/mindustry/net/Administration.java @@ -196,9 +196,9 @@ public class Administration{ return getCreateInfo(uuid).banned; } - public boolean isAdmin(String id, String usip){ + public boolean isAdmin(String id, String usid){ PlayerInfo info = getCreateInfo(id); - return info.admin && usip.equals(info.adminUsid); + return info.admin && usid.equals(info.adminUsid); } /**Finds player info by IP, UUID and name.*/ diff --git a/core/src/io/anuke/mindustry/net/Interpolator.java b/core/src/io/anuke/mindustry/net/Interpolator.java index d4590ecec3..b7b32b321a 100644 --- a/core/src/io/anuke/mindustry/net/Interpolator.java +++ b/core/src/io/anuke/mindustry/net/Interpolator.java @@ -37,13 +37,6 @@ public class Interpolator{ public void update(){ - /* - if(pos.dst(target) > 128){ - pos.set(target); - lastUpdated = 0; - updateSpacing = 16; - }*/ - if(lastUpdated != 0 && updateSpacing != 0){ float timeSinceUpdate = Time.timeSinceMillis(lastUpdated); float alpha = Math.min(timeSinceUpdate / updateSpacing, 2f); diff --git a/core/src/io/anuke/mindustry/net/NetConnection.java b/core/src/io/anuke/mindustry/net/NetConnection.java index 3b572d0bb5..d016c34442 100644 --- a/core/src/io/anuke/mindustry/net/NetConnection.java +++ b/core/src/io/anuke/mindustry/net/NetConnection.java @@ -9,8 +9,6 @@ public abstract class NetConnection{ public boolean modclient; public boolean mobile; - public int lastSentSnapshotID = -1; - /**ID of last recieved client snapshot.*/ public int lastRecievedClientSnapshot = -1; /**Timestamp of last recieved snapshot.*/ diff --git a/core/src/io/anuke/mindustry/net/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java index 09183f4049..8e26a4a701 100644 --- a/core/src/io/anuke/mindustry/net/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -3,9 +3,9 @@ package io.anuke.mindustry.net; import io.anuke.arc.Core; import io.anuke.arc.collection.ObjectMap; import io.anuke.arc.collection.ObjectMap.Entry; -import io.anuke.arc.entities.Entities; import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.Entities; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Teams; import io.anuke.mindustry.game.Teams.TeamData; @@ -17,7 +17,6 @@ import io.anuke.mindustry.world.Tile; import java.io.*; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import static io.anuke.mindustry.Vars.*; @@ -44,6 +43,7 @@ public class NetworkIO{ stream.writeInt(player.id); player.write(stream); + world.spawner.write(stream); SaveIO.getSaveWriter().writeMap(stream); stream.write(Team.all.length); @@ -102,9 +102,8 @@ public class NetworkIO{ player.resetID(id); player.add(); - world.beginMapLoad(); - //map + world.spawner.read(stream); SaveIO.getSaveWriter().readMap(stream); world.setMap(new Map(map, 0, 0)); @@ -133,8 +132,6 @@ public class NetworkIO{ } } - world.endMapLoad(); - }catch(IOException e){ throw new RuntimeException(e); } @@ -151,17 +148,17 @@ public class NetworkIO{ ByteBuffer buffer = ByteBuffer.allocate(128); - buffer.put((byte) host.getBytes(StandardCharsets.UTF_8).length); - buffer.put(host.getBytes(StandardCharsets.UTF_8)); + buffer.put((byte) host.getBytes(charset).length); + buffer.put(host.getBytes(charset)); - buffer.put((byte) map.getBytes(StandardCharsets.UTF_8).length); - buffer.put(map.getBytes(StandardCharsets.UTF_8)); + buffer.put((byte) map.getBytes(charset).length); + buffer.put(map.getBytes(charset)); buffer.putInt(playerGroup.size()); buffer.putInt(state.wave); buffer.putInt(Version.build); - buffer.put((byte)Version.type.getBytes(StandardCharsets.UTF_8).length); - buffer.put(Version.type.getBytes(StandardCharsets.UTF_8)); + buffer.put((byte)Version.type.getBytes(charset).length); + buffer.put(Version.type.getBytes(charset)); return buffer; } @@ -174,8 +171,8 @@ public class NetworkIO{ byte[] mb = new byte[mlength]; buffer.get(mb); - String host = new String(hb, StandardCharsets.UTF_8); - String map = new String(mb, StandardCharsets.UTF_8); + String host = new String(hb, charset); + String map = new String(mb, charset); int players = buffer.getInt(); int wave = buffer.getInt(); @@ -183,7 +180,7 @@ public class NetworkIO{ byte tlength = buffer.get(); byte[] tb = new byte[tlength]; buffer.get(tb); - String vertype = new String(tb, StandardCharsets.UTF_8); + String vertype = new String(tb, charset); return new Host(host, hostAddress, map, wave, players, version, vertype); } diff --git a/core/src/io/anuke/mindustry/net/ValidateException.java b/core/src/io/anuke/mindustry/net/ValidateException.java index 89923702de..08f3f70483 100644 --- a/core/src/io/anuke/mindustry/net/ValidateException.java +++ b/core/src/io/anuke/mindustry/net/ValidateException.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.net; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.type.Player; /** * Thrown when a client sends invalid information. diff --git a/core/src/io/anuke/mindustry/type/ContentType.java b/core/src/io/anuke/mindustry/type/ContentType.java index 1e775dc7e3..c20ff0f310 100644 --- a/core/src/io/anuke/mindustry/type/ContentType.java +++ b/core/src/io/anuke/mindustry/type/ContentType.java @@ -7,10 +7,10 @@ public enum ContentType { mech, bullet, liquid, - weapon, status, unit, weather, effect, - zone + zone, + loadout } diff --git a/core/src/io/anuke/mindustry/type/Item.java b/core/src/io/anuke/mindustry/type/Item.java index 47bf130f3e..986a74a75c 100644 --- a/core/src/io/anuke/mindustry/type/Item.java +++ b/core/src/io/anuke/mindustry/type/Item.java @@ -5,18 +5,13 @@ import io.anuke.arc.collection.Array; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Strings; import io.anuke.mindustry.Vars; import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.ui.ContentDisplay; public class Item extends UnlockableContent implements Comparable{ - public final String name; - public final String description; public final Color color; - public TextureRegion region; + private TextureRegion[] regions; /**type of the item; used for tabs and core acceptance. default value is {@link ItemType#resource}.*/ public ItemType type = ItemType.resource; @@ -26,12 +21,8 @@ public class Item extends UnlockableContent implements Comparable{ public float flammability = 0f; /**how radioactive this item is. 0=none, 1=chernobyl ground zero*/ public float radioactivity; - /**how effective this item is as flux for smelting. 0 = not a flux, 0.5 = normal flux, 1 = very good*/ - public float fluxiness = 0f; /**drill hardness of the item*/ public int hardness = 0; - /**the burning color of this item. TODO unused; implement*/ - public Color flameColor = Palette.darkFlame.cpy(); /** * base material cost of this item, used for calculating place times * 1 cost = 1 tick added to build time @@ -43,18 +34,21 @@ public class Item extends UnlockableContent implements Comparable{ public boolean alwaysUnlocked = false; public Item(String name, Color color){ - this.name = name; + super(name); this.color = color; this.description = Core.bundle.getOrNull("item." + this.name + ".description"); - - if(!Core.bundle.has("item." + this.name + ".name")){ - Log.err("Warning: item '" + name + "' is missing a localized name. Add the following to bundle.properties:"); - Log.err("item." + this.name + ".name = " + Strings.capitalize(name.replace('-', '_'))); - } } public void load(){ - this.region = Core.atlas.find("item-" + name); + regions = new TextureRegion[Icon.values().length]; + for(int i = 0; i < regions.length; i++){ + Icon icon = Icon.values()[i]; + regions[i] = Core.atlas.find(icon == Icon.large ? "item-" + name : "item-" + name + "-" + icon.name()); + } + } + + public TextureRegion icon(Icon icon){ + return regions[icon.ordinal()]; } @Override @@ -74,7 +68,7 @@ public class Item extends UnlockableContent implements Comparable{ @Override public TextureRegion getContentIcon(){ - return region; + return icon(Icon.large); } @Override @@ -87,16 +81,24 @@ public class Item extends UnlockableContent implements Comparable{ return Integer.compare(id, item.id); } - @Override - public String getContentName(){ - return name; - } - @Override public ContentType getContentType(){ return ContentType.item; } + public enum Icon{ + small(8*2), + medium(8*3), + large(8*4), + xlarge(8*5); + + public final int size; + + Icon(int size){ + this.size = size; + } + } + /**Allocates a new array containing all items the generate ores.*/ public static Array getAllOres(){ return Vars.content.items().select(i -> i.genOre); diff --git a/core/src/io/anuke/mindustry/type/ItemStack.java b/core/src/io/anuke/mindustry/type/ItemStack.java index d7455c8d36..47cfc87868 100644 --- a/core/src/io/anuke/mindustry/type/ItemStack.java +++ b/core/src/io/anuke/mindustry/type/ItemStack.java @@ -1,6 +1,8 @@ package io.anuke.mindustry.type; -public class ItemStack{ +import io.anuke.arc.collection.Array; + +public class ItemStack implements Comparable{ public Item item; public int amount; @@ -20,4 +22,25 @@ public class ItemStack{ } return stacks; } + + public static Array list(Object... items){ + Array stacks = new Array<>(items.length/2); + for(int i = 0; i < items.length; i+= 2){ + stacks.add(new ItemStack((Item)items[i], (Integer)items[i + 1])); + } + return stacks; + } + + @Override + public int compareTo(ItemStack itemStack){ + return item.compareTo(itemStack.item); + } + + @Override + public String toString(){ + return "ItemStack{" + + "item=" + item + + ", amount=" + amount + + '}'; + } } diff --git a/core/src/io/anuke/mindustry/type/Liquid.java b/core/src/io/anuke/mindustry/type/Liquid.java index 378a6f4779..2f04dfa787 100644 --- a/core/src/io/anuke/mindustry/type/Liquid.java +++ b/core/src/io/anuke/mindustry/type/Liquid.java @@ -10,8 +10,6 @@ import io.anuke.mindustry.ui.ContentDisplay; public class Liquid extends UnlockableContent{ public final Color color; - public final String name; - public final String description; /**0-1, 0 is completely inflammable, anything above that may catch fire when exposed to heat, 0.5+ is very flammable.*/ public float flammability; @@ -27,13 +25,11 @@ public class Liquid extends UnlockableContent{ public Color flameColor = Color.valueOf("ffb763"); /**The associated status effect.*/ public StatusEffect effect = StatusEffects.none; - /**Pump tier. Controls which pumps can use this liquid.*/ - public int tier; /**Displayed icon. TODO fix it by removing autogen, draw icons manually*/ public TextureRegion iconRegion; public Liquid(String name, Color color){ - this.name = name; + super(name); this.color = new Color(color); this.description = Core.bundle.getOrNull("liquid." + name + ".description"); } @@ -67,11 +63,6 @@ public class Liquid extends UnlockableContent{ return localizedName(); } - @Override - public String getContentName(){ - return name; - } - @Override public ContentType getContentType(){ return ContentType.liquid; diff --git a/core/src/io/anuke/mindustry/type/Loadout.java b/core/src/io/anuke/mindustry/type/Loadout.java new file mode 100644 index 0000000000..312a5b4d4e --- /dev/null +++ b/core/src/io/anuke/mindustry/type/Loadout.java @@ -0,0 +1,118 @@ +package io.anuke.mindustry.type; + +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.IntMap; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.content.Items; +import io.anuke.mindustry.game.Content; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Pos; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.Floor; +import io.anuke.mindustry.world.blocks.OreBlock; +import io.anuke.mindustry.world.blocks.storage.CoreBlock; + +import static io.anuke.mindustry.Vars.defaultTeam; +import static io.anuke.mindustry.Vars.world; + +public class Loadout extends Content{ + private final static Array outArray = new Array<>(); + private final static IntMap entries = new IntMap(){{ + put('>', new BlockEntry(Blocks.conveyor, 0)); + put('^', new BlockEntry(Blocks.conveyor, 1)); + put('<', new BlockEntry(Blocks.conveyor, 2)); + put('v', new BlockEntry(Blocks.conveyor, 3)); + + put('1', new BlockEntry(Blocks.coreShard)); + put('2', new BlockEntry(Blocks.coreFoundation)); + put('3', new BlockEntry(Blocks.coreNucleus)); + + put('C', new BlockEntry(Blocks.mechanicalDrill, Items.copper)); + }}; + + private final IntMap blocks = new IntMap<>(); + private Block core; + + public Loadout(String... layout){ + int coreX = -1, coreY = -1; + + outer: + for(int y = 0; y < layout.length; y ++){ + for(int x = 0; x < layout[0].length(); x++){ + char c = layout[y].charAt(x); + if(entries.get(c) != null && entries.get(c).block instanceof CoreBlock){ + core = entries.get(c).block; + coreX = x; + coreY = y; + break outer; + } + } + } + + if(coreX == -1) throw new IllegalArgumentException("Schematic does not have a core."); + + for(int y = 0; y < layout.length; y ++){ + for(int x = 0; x < layout[0].length(); x++){ + char c = layout[y].charAt(x); + if(entries.containsKey(c)){ + BlockEntry entry = entries.get(c); + blocks.put(Pos.get(x - coreX, -(y - coreY)), entry); + } + } + } + } + + public Loadout(){ + + } + + public Block core(){ + return core; + } + + public void setup(int x, int y){ + for(IntMap.Entry entry : blocks.entries()){ + int rx = Pos.x(entry.key); + int ry = Pos.y(entry.key); + Tile tile = world.tile(x + rx, y + ry); + world.setBlock(tile, entry.value.block, defaultTeam); + tile.setRotation((byte)entry.value.rotation); + if(entry.value.ore != null){ + for(Tile t : tile.getLinkedTiles(outArray)){ + Floor floor = t.floor(); + t.setFloor(OreBlock.get(floor, entry.value.ore) == null ? OreBlock.get(Blocks.stone, entry.value.ore) : OreBlock.get(floor, entry.value.ore)); + } + } + } + } + + @Override + public ContentType getContentType(){ + return ContentType.loadout; + } + + static class BlockEntry{ + final Block block; + final Item ore; + final int rotation; + + BlockEntry(Block block, Item ore){ + this.block = block; + this.ore = ore; + this.rotation = 0; + } + + BlockEntry(Block block, int rotation){ + this.block = block; + this.ore = null; + this.rotation = rotation; + } + + BlockEntry(Block block){ + this.block = block; + this.ore = null; + this.rotation = 0; + } + } + +} diff --git a/core/src/io/anuke/mindustry/type/Mech.java b/core/src/io/anuke/mindustry/type/Mech.java index 7abf1a8e3c..aa56ac67fc 100644 --- a/core/src/io/anuke/mindustry/type/Mech.java +++ b/core/src/io/anuke/mindustry/type/Mech.java @@ -4,16 +4,12 @@ import io.anuke.arc.Core; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.mindustry.content.Weapons; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.ui.ContentDisplay; public class Mech extends UnlockableContent{ - public final String name; - public final String description; - public boolean flying; public float speed = 1.1f; public float maxSpeed = 10f; @@ -21,28 +17,26 @@ public class Mech extends UnlockableContent{ public float drag = 0.4f; public float mass = 1f; public float shake = 0f; - public float armor = 1f; + public float health = 200f; public float hitsize = 6f; public float cellTrnsY = 0f; public float mineSpeed = 1f; public int drillPower = -1; - public float carryWeight = 10f; public float buildPower = 1f; - public Color trailColor = Palette.boostFrom; - public Color trailColorTo = Palette.boostTo; + public Color engineColor = Pal.boostTo; public int itemCapacity = 30; public boolean turnCursor = true; public boolean canHeal = false; - public float weaponOffsetX, weaponOffsetY; - public Weapon weapon = Weapons.blaster; + public float weaponOffsetX, weaponOffsetY, engineOffset = 5f, engineSize = 2.5f; + public Weapon weapon; public TextureRegion baseRegion, legRegion, region, iconRegion; public Mech(String name, boolean flying){ + super(name); this.flying = flying; - this.name = name; this.description = Core.bundle.get("mech." + name + ".description"); } @@ -80,11 +74,6 @@ public class Mech extends UnlockableContent{ return iconRegion; } - @Override - public String getContentName(){ - return name; - } - @Override public ContentType getContentType(){ return ContentType.mech; @@ -92,6 +81,7 @@ public class Mech extends UnlockableContent{ @Override public void load(){ + weapon.load(); if(!flying){ legRegion = Core.atlas.find(name + "-leg"); baseRegion = Core.atlas.find(name + "-base"); diff --git a/core/src/io/anuke/mindustry/type/StatusEffect.java b/core/src/io/anuke/mindustry/type/StatusEffect.java index bb9b1ea82f..3852f0a38e 100644 --- a/core/src/io/anuke/mindustry/type/StatusEffect.java +++ b/core/src/io/anuke/mindustry/type/StatusEffect.java @@ -2,15 +2,15 @@ package io.anuke.mindustry.type; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectMap; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.function.Supplier; import io.anuke.arc.graphics.Color; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.StatusController.StatusEntry; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.units.Statuses.StatusEntry; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.Content; public class StatusEffect extends Content{ @@ -50,7 +50,7 @@ public class StatusEffect extends Content{ } if(effect != Fx.none && Mathf.chance(Time.delta() * 0.15f)){ - Effects.effect(Fx.overdriven, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f)); + Effects.effect(effect, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f)); } } diff --git a/core/src/io/anuke/mindustry/entities/units/UnitType.java b/core/src/io/anuke/mindustry/type/UnitType.java similarity index 67% rename from core/src/io/anuke/mindustry/entities/units/UnitType.java rename to core/src/io/anuke/mindustry/type/UnitType.java index 9552a786cc..d187380fb0 100644 --- a/core/src/io/anuke/mindustry/entities/units/UnitType.java +++ b/core/src/io/anuke/mindustry/type/UnitType.java @@ -1,63 +1,49 @@ -package io.anuke.mindustry.entities.units; +package io.anuke.mindustry.type; import io.anuke.arc.Core; import io.anuke.arc.collection.ObjectSet; import io.anuke.arc.function.Supplier; -import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Strings; import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.Weapons; import io.anuke.mindustry.entities.traits.TypeTrait; +import io.anuke.mindustry.entities.type.BaseUnit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Weapon; import io.anuke.mindustry.ui.ContentDisplay; public class UnitType extends UnlockableContent{ protected final Supplier constructor; - - public final String name; - public final String description; public float health = 60; public float hitsize = 7f; public float hitsizeTile = 4f; public float speed = 0.4f; - public float range = 0; + public float range = 0, attackLength = 150f; public float rotatespeed = 0.2f; public float baseRotateSpeed = 0.1f; + public float shootCone = 15f; public float mass = 1f; public boolean isFlying; public boolean targetAir = true; + public boolean rotateWeapon = false; public float drag = 0.1f; public float maxVelocity = 5f; public float retreatPercent = 0.2f; - public float armor = 0f; - public float carryWeight = 1f; public int itemCapacity = 30; public ObjectSet toMine = ObjectSet.with(Items.lead, Items.copper); public float buildPower = 0.3f, minePower = 0.7f; - public Weapon weapon = Weapons.blaster; - public float weaponOffsetX, weaponOffsetY; - public Color trailColor = Color.valueOf("ffa665"); + public Weapon weapon; + public float weaponOffsetY, engineOffset = 6f, engineSize = 2f; + public ObjectSet immunities = new ObjectSet<>(); public TextureRegion iconRegion, legRegion, baseRegion, region; public UnitType(String name, Class type, Supplier mainConstructor){ - this.name = name; + super(name); this.constructor = mainConstructor; this.description = Core.bundle.getOrNull("unit." + name + ".description"); TypeTrait.registerType(type, mainConstructor); - - if(!Core.bundle.has("unit." + this.name + ".name")){ - Log.err("Warning: unit '" + name + "' is missing a localized name. Add the follow to bundle.properties:"); - Log.err("unit." + this.name + ".name=" + Strings.capitalize(name.replace('-', '_'))); - } } @Override @@ -77,7 +63,8 @@ public class UnitType extends UnlockableContent{ @Override public void load(){ - iconRegion = Core.atlas.find("unit-icon-" + name); + weapon.load(); + iconRegion = Core.atlas.find("unit-icon-" + name, Core.atlas.find(name)); region = Core.atlas.find(name); if(!isFlying){ @@ -91,11 +78,6 @@ public class UnitType extends UnlockableContent{ return ContentType.unit; } - @Override - public String getContentName(){ - return name; - } - public BaseUnit create(Team team){ BaseUnit unit = constructor.get(); unit.init(this, team); diff --git a/core/src/io/anuke/mindustry/type/Weapon.java b/core/src/io/anuke/mindustry/type/Weapon.java index dda242a463..093eda0244 100644 --- a/core/src/io/anuke/mindustry/type/Weapon.java +++ b/core/src/io/anuke/mindustry/type/Weapon.java @@ -3,60 +3,70 @@ package io.anuke.mindustry.type; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.util.Time; +import io.anuke.arc.util.Tmp; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.entities.traits.ShooterTrait; -import io.anuke.mindustry.game.Content; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; -public class Weapon extends Content{ +public class Weapon{ public final String name; /**minimum cursor distance from player, fixes 'cross-eyed' shooting.*/ protected static float minPlayerDist = 20f; - /**ammo type map. set with setAmmo()*/ - protected BulletType ammo; + protected static int sequenceNum = 0; + /**bullet shot*/ + public BulletType bullet; /**shell ejection effect*/ - protected Effect ejectEffect = Fx.none; + public Effect ejectEffect = Fx.none; /**weapon reload in frames*/ - protected float reload; + public float reload; /**amount of shots per fire*/ - protected int shots = 1; + public int shots = 1; /**spacing in degrees between multiple shots, if applicable*/ - protected float spacing = 12f; + public float spacing = 12f; /**inaccuracy of degrees of each shot*/ - protected float inaccuracy = 0f; + public float inaccuracy = 0f; /**intensity and duration of each shot's screen shake*/ - protected float shake = 0f; + public float shake = 0f; /**visual weapon knockback.*/ - protected float recoil = 1.5f; + public float recoil = 1.5f; /**shoot barrel y offset*/ - protected float length = 3f; + public float length = 3f; /**shoot barrel x offset.*/ - protected float width = 4f; + public float width = 4f; /**fraction of velocity that is random*/ - protected float velocityRnd = 0f; + public float velocityRnd = 0f; /**whether to shoot the weapons in different arms one after another, rather than all at once*/ - protected boolean roundrobin = false; - /**vector for vector calulations*/ - protected Vector2 tr = new Vector2(); + public boolean roundrobin = false; + /**randomization of shot length*/ + public float lengthRand = 0f; + /**delay in ticks between shots*/ + public float shotDelay = 0; + /**whether shooter rotation is ignored when shooting.*/ + public boolean ignoreRotation = false; - public TextureRegion equipRegion, region; + public TextureRegion region; protected Weapon(String name){ this.name = name; } + protected Weapon(){ + //no region + this.name = ""; + } + @Remote(targets = Loc.server, called = Loc.both, unreliable = true) public static void onPlayerShootWeapon(Player player, float x, float y, float rotation, boolean left){ if(player == null) return; @@ -81,59 +91,58 @@ public class Weapon extends Content{ Weapon weapon = shooter.getWeapon(); - Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> weapon.bullet(shooter, x, y, f + Mathf.range(weapon.inaccuracy))); - BulletType ammo = weapon.ammo; + sequenceNum = 0; + if(weapon.shotDelay > 0.01f){ + Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> { + Time.run(sequenceNum * weapon.shotDelay, () -> weapon.bullet(shooter, x, y, f + Mathf.range(weapon.inaccuracy))); + sequenceNum ++; + }); + }else{ + Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> weapon.bullet(shooter, x, y, f + Mathf.range(weapon.inaccuracy))); + } - weapon.tr.trns(rotation + 180f, ammo.recoil); + BulletType ammo = weapon.bullet; - shooter.velocity().add(weapon.tr); + Tmp.v1.trns(rotation + 180f, ammo.recoil); - weapon.tr.trns(rotation, 3f); + shooter.velocity().add(Tmp.v1); + + Tmp.v1.trns(rotation, 3f); Effects.shake(weapon.shake, weapon.shake, x, y); Effects.effect(weapon.ejectEffect, x, y, rotation * -Mathf.sign(left)); - Effects.effect(ammo.shootEffect, x + weapon.tr.x, y + weapon.tr.y, rotation, shooter); - Effects.effect(ammo.smokeEffect, x + weapon.tr.x, y + weapon.tr.y, rotation, shooter); + Effects.effect(ammo.shootEffect, x + Tmp.v1.x, y + Tmp.v1.y, rotation, shooter); + Effects.effect(ammo.smokeEffect, x + Tmp.v1.x, y + Tmp.v1.y, rotation, shooter); //reset timer for remote players shooter.getTimer().get(shooter.getShootTimer(left), weapon.reload); } - @Override public void load(){ - equipRegion = Core.atlas.find(name + "-equip"); - region = Core.atlas.find(name); - } - - @Override - public ContentType getContentType(){ - return ContentType.weapon; - } - - public BulletType getAmmo(){ - return ammo; + region = Core.atlas.find(name + "-equip", Core.atlas.find("clear")); } public void update(ShooterTrait shooter, float pointerX, float pointerY){ - update(shooter, true, pointerX, pointerY); - update(shooter, false, pointerX, pointerY); + for(boolean left : Mathf.booleans){ + Tmp.v1.set(pointerX, pointerY).sub(shooter.getX(), shooter.getY()); + if(Tmp.v1.len() < minPlayerDist) Tmp.v1.setLength(minPlayerDist); + + float cx = Tmp.v1.x + shooter.getX(), cy = Tmp.v1.y + shooter.getY(); + + float ang = Tmp.v1.angle(); + Tmp.v1.trns(ang - 90, width * Mathf.sign(left), length + Mathf.range(lengthRand)); + + update(shooter, shooter.getX() + Tmp.v1.x, shooter.getY() + Tmp.v1.y, Angles.angle(shooter.getX() + Tmp.v1.x, shooter.getY() + Tmp.v1.y, cx, cy), left); + } } - private void update(ShooterTrait shooter, boolean left, float pointerX, float pointerY){ + public void update(ShooterTrait shooter, float mountX, float mountY, float angle, boolean left){ if(shooter.getTimer().get(shooter.getShootTimer(left), reload)){ if(roundrobin){ shooter.getTimer().reset(shooter.getShootTimer(!left), reload / 2f); } - tr.set(pointerX, pointerY).sub(shooter.getX(), shooter.getY()); - if(tr.len() < minPlayerDist) tr.setLength(minPlayerDist); - - float cx = tr.x + shooter.getX(), cy = tr.y + shooter.getY(); - - float ang = tr.angle(); - tr.trns(ang - 90, width * Mathf.sign(left), length); - - shoot(shooter, tr.x, tr.y, Angles.angle(shooter.getX() + tr.x, shooter.getY() + tr.y, cx, cy), left); + shoot(shooter, mountX - shooter.getX(), mountY - shooter.getY(), angle, left); } } @@ -141,14 +150,6 @@ public class Weapon extends Content{ return (1f - Mathf.clamp(player.getTimer().getTime(player.getShootTimer(left)) / reload)) * recoil; } - public float getRecoil(){ - return recoil; - } - - public float getReload(){ - return reload; - } - public void shoot(ShooterTrait p, float x, float y, float angle, boolean left){ if(Net.client()){ //call it directly, don't invoke on server @@ -165,8 +166,8 @@ public class Weapon extends Content{ void bullet(ShooterTrait owner, float x, float y, float angle){ if(owner == null) return; - tr.trns(angle, 3f); - Bullet.create(ammo, - owner, owner.getTeam(), x + tr.x, y + tr.y, angle, (1f - velocityRnd) + Mathf.random(velocityRnd)); + Tmp.v1.trns(angle, 3f); + Bullet.create(bullet, + owner, owner.getTeam(), x + Tmp.v1.x, y + Tmp.v1.y, angle, (1f - velocityRnd) + Mathf.random(velocityRnd)); } } diff --git a/core/src/io/anuke/mindustry/type/Zone.java b/core/src/io/anuke/mindustry/type/Zone.java index dabee32514..93b5208c67 100644 --- a/core/src/io/anuke/mindustry/type/Zone.java +++ b/core/src/io/anuke/mindustry/type/Zone.java @@ -1,41 +1,146 @@ package io.anuke.mindustry.type; import io.anuke.arc.Core; +import io.anuke.arc.Events; +import io.anuke.arc.collection.Array; +import io.anuke.arc.function.Consumer; import io.anuke.arc.function.Supplier; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.content.Loadouts; +import io.anuke.mindustry.content.StatusEffects; +import io.anuke.mindustry.game.EventType.ZoneCompleteEvent; +import io.anuke.mindustry.game.EventType.ZoneConfigureCompleteEvent; import io.anuke.mindustry.game.Rules; +import io.anuke.mindustry.game.SpawnGroup; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.maps.generators.Generator; +import io.anuke.mindustry.maps.generators.MapGenerator; import io.anuke.mindustry.world.Block; +import java.util.Arrays; + +import static io.anuke.mindustry.Vars.data; import static io.anuke.mindustry.Vars.state; public class Zone extends UnlockableContent{ - public final String name; public final Generator generator; - public ItemStack[] deployCost = {}; - public ItemStack[] startingItems = {}; public Block[] blockRequirements = {}; public ItemStack[] itemRequirements = {}; public Zone[] zoneRequirements = {}; + public Item[] resources = {}; public Supplier rules = Rules::new; public boolean alwaysUnlocked; public int conditionWave = Integer.MAX_VALUE; + public int configureWave = 40; + public int launchPeriod = 10; + public Loadout loadout = Loadouts.basicShard; - public Zone(String name, Generator generator){ - this.name = name; + protected ItemStack[] baseLaunchCost = {}; + protected Array startingItems = new Array<>(); + protected ItemStack[] launchCost = null; + + public Zone(String name, MapGenerator generator){ + super(name); this.generator = generator; } + protected SpawnGroup bossGroup(UnitType type){ + return new SpawnGroup(type){{ + begin = configureWave-1; + effect = StatusEffects.boss; + unitScaling = 1; + spacing = configureWave; + }}; + } + + public boolean isBossWave(int wave){ + return wave % configureWave == 0 && wave > 0; + } + + public boolean isLaunchWave(int wave){ + return metCondition() && wave % launchPeriod == 0; + } + + public ItemStack[] getLaunchCost(){ + if(launchCost == null){ + updateLaunchCost(); + } + return launchCost; + } + + public Array getStartingItems(){ + return startingItems; + } + + public void updateWave(int wave){ + int value = Core.settings.getInt(name + "-wave", 0); + if(value < wave){ + Core.settings.put(name + "-wave", wave); + data.modified(); + + if(wave == conditionWave + 1){ + Events.fire(new ZoneCompleteEvent(this)); + } + + if(wave == configureWave + 1){ + Events.fire(new ZoneConfigureCompleteEvent(this)); + } + } + } + + public int bestWave(){ + return Core.settings.getInt(name + "-wave", 0); + } + + public boolean isCompleted(){ + return bestWave() >= conditionWave; + } + + public void updateLaunchCost(){ + Array stacks = new Array<>(); + + Consumer adder = stack -> { + for(ItemStack other : stacks){ + if(other.item == stack.item){ + other.amount += stack.amount; + return; + } + } + stacks.add(new ItemStack(stack.item, stack.amount)); + }; + + for(ItemStack stack : baseLaunchCost) adder.accept(stack); + for(ItemStack stack : startingItems) adder.accept(stack); + + for(ItemStack stack : stacks){ + if(stack.amount < 0) stack.amount = 0; + } + + stacks.sort(); + launchCost = stacks.toArray(ItemStack.class); + Core.settings.putObject(name + "-starting-items", startingItems); + data.modified(); + } + /**Whether this zone has met its condition; if true, the player can leave.*/ public boolean metCondition(){ return state.wave >= conditionWave; } + public boolean canConfigure(){ + return bestWave() >= configureWave; + } + @Override public void init(){ - generator.init(); + generator.init(loadout); + Arrays.sort(resources); + + Array arr = Core.settings.getObject(name + "-starting-items", Array.class, () -> null); + if(arr != null){ + startingItems = arr; + } } @Override @@ -55,11 +160,6 @@ public class Zone extends UnlockableContent{ @Override public TextureRegion getContentIcon(){ return null; } - @Override - public String getContentName(){ - return name; - } - @Override public String localizedName(){ return Core.bundle.get("zone."+name+".name"); diff --git a/core/src/io/anuke/mindustry/ui/Bar.java b/core/src/io/anuke/mindustry/ui/Bar.java index bf24bd03f6..cbd2b7b0f9 100644 --- a/core/src/io/anuke/mindustry/ui/Bar.java +++ b/core/src/io/anuke/mindustry/ui/Bar.java @@ -32,8 +32,10 @@ public class Bar extends Element{ public Bar(Supplier name, Supplier color, FloatProvider fraction){ this.fraction = fraction; + lastValue = value = Mathf.clamp(fraction.get()); update(() -> { this.name = name.get(); + this.blinkColor.set(color.get()); setColor(color.get()); }); } @@ -45,13 +47,14 @@ public class Bar extends Element{ @Override public void draw(){ - if(!Mathf.isEqual(lastValue, fraction.get())){ + float computed = Mathf.clamp(fraction.get()); + if(!Mathf.isEqual(lastValue, computed)){ blink = 1f; - lastValue = fraction.get(); + lastValue = computed; } blink = Mathf.lerpDelta(blink, 0f, 0.2f); - value = Mathf.lerpDelta(value, fraction.get(), 0.15f); + value = Mathf.lerpDelta(value, computed, 0.15f); Draw.colorl(0.1f); Draw.drawable("bar", x, y, width, height); @@ -75,6 +78,7 @@ public class Bar extends Element{ GlyphLayout lay = Pools.obtain(GlyphLayout.class, GlyphLayout::new); lay.setText(font, name); + font.setColor(Color.WHITE); font.draw(name, x + width/2f - lay.width/2f, y + height/2f + lay.height/2f + 1); Pools.free(lay); diff --git a/core/src/io/anuke/mindustry/ui/BorderImage.java b/core/src/io/anuke/mindustry/ui/BorderImage.java index 2b479a1980..0db23da2ba 100644 --- a/core/src/io/anuke/mindustry/ui/BorderImage.java +++ b/core/src/io/anuke/mindustry/ui/BorderImage.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.ui; import io.anuke.arc.graphics.Texture; import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.scene.ui.Image; @@ -36,7 +36,7 @@ public class BorderImage extends Image{ float scaleX = getScaleX(); float scaleY = getScaleY(); - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.stroke(Unit.dp.scl(thickness)); Lines.rect(x + imageX, y + imageY, imageWidth * scaleX, imageHeight * scaleY); Draw.reset(); diff --git a/core/src/io/anuke/mindustry/ui/ContentDisplay.java b/core/src/io/anuke/mindustry/ui/ContentDisplay.java index ec7a43fe52..62e571449e 100644 --- a/core/src/io/anuke/mindustry/ui/ContentDisplay.java +++ b/core/src/io/anuke/mindustry/ui/ContentDisplay.java @@ -5,8 +5,8 @@ import io.anuke.arc.collection.OrderedMap; import io.anuke.arc.graphics.Color; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Strings; -import io.anuke.mindustry.entities.units.UnitType; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.type.UnitType; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.type.Mech; @@ -25,7 +25,7 @@ public class ContentDisplay{ int size = 8 * 6; title.addImage(block.icon(Icon.large)).size(size); - title.add("[accent]" + block.formalName).padLeft(5); + title.add("[accent]" + block.localizedName).padLeft(5); }); table.row(); @@ -34,8 +34,8 @@ public class ContentDisplay{ table.row(); - if(block.fullDescription != null){ - table.add(block.fullDescription).padLeft(5).padRight(5).width(400f).wrap().fillX(); + if(block.description != null){ + table.add(block.description).padLeft(5).padRight(5).width(400f).wrap().fillX(); table.row(); table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(8).padLeft(0).padRight(0).fillX(); @@ -49,7 +49,7 @@ public class ContentDisplay{ if(map.size == 0) continue; - table.add("$category." + cat.name()).color(Palette.accent).fillX(); + table.add("$category." + cat.name()).color(Pal.accent).fillX(); table.row(); for(BlockStat stat : map.keys()){ @@ -86,13 +86,11 @@ public class ContentDisplay{ table.left().defaults().fillX(); - table.add(Core.bundle.format("item.explosiveness", (int) (item.explosiveness * 100 * 2f))); + table.add(Core.bundle.format("item.explosiveness", (int) (item.explosiveness * 100))); table.row(); - table.add(Core.bundle.format("item.flammability", (int) (item.flammability * 100 * 2f))); + table.add(Core.bundle.format("item.flammability", (int) (item.flammability * 100))); table.row(); - table.add(Core.bundle.format("item.radioactivity", (int) (item.radioactivity * 100 * 2f))); - table.row(); - table.add(Core.bundle.format("item.fluxiness", (int) (item.fluxiness * 100 * 2f))); + table.add(Core.bundle.format("item.radioactivity", (int) (item.radioactivity * 100))); table.row(); } @@ -119,9 +117,9 @@ public class ContentDisplay{ table.left().defaults().fillX(); - table.add(Core.bundle.format("item.explosiveness", (int) (liquid.explosiveness * 100 * 2f))); + table.add(Core.bundle.format("item.explosiveness", (int) (liquid.explosiveness * 100))); table.row(); - table.add(Core.bundle.format("item.flammability", (int) (liquid.flammability * 100 * 2f))); + table.add(Core.bundle.format("item.flammability", (int) (liquid.flammability * 100))); table.row(); table.add(Core.bundle.format("liquid.heatcapacity", (int) (liquid.heatCapacity * 100))); table.row(); @@ -161,7 +159,7 @@ public class ContentDisplay{ table.add(Core.bundle.format("mech.ability", Core.bundle.get("mech." + mech.name + ".ability"))); table.row(); } - table.add(Core.bundle.format("mech.armor", mech.armor)); + table.add(Core.bundle.format("mech.health", (int)mech.health)); table.row(); table.add(Core.bundle.format("mech.itemcapacity", mech.itemCapacity)); table.row(); diff --git a/core/src/io/anuke/mindustry/ui/ItemImage.java b/core/src/io/anuke/mindustry/ui/ItemImage.java index e13026658f..3e4692c270 100644 --- a/core/src/io/anuke/mindustry/ui/ItemImage.java +++ b/core/src/io/anuke/mindustry/ui/ItemImage.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.ui; import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.mindustry.type.Item.Icon; import io.anuke.mindustry.type.ItemStack; import io.anuke.arc.function.Supplier; import io.anuke.arc.scene.ui.Image; @@ -9,6 +10,14 @@ import io.anuke.arc.scene.ui.layout.Table; public class ItemImage extends Stack{ + public ItemImage(TextureRegion region, int amount){ + Table t = new Table().left().bottom(); + t.add(amount + "").name("item-label"); + + add(new Image(region)); + add(t); + } + public ItemImage(TextureRegion region, Supplier text){ Table t = new Table().left().bottom(); t.label(text).name("item-label"); @@ -18,7 +27,7 @@ public class ItemImage extends Stack{ } public ItemImage(ItemStack stack){ - add(new Image(stack.item.region)); + add(new Image(stack.item.icon(Icon.medium))); if(stack.amount != 0){ Table t = new Table().left().bottom(); diff --git a/core/src/io/anuke/mindustry/ui/ItemsDisplay.java b/core/src/io/anuke/mindustry/ui/ItemsDisplay.java new file mode 100644 index 0000000000..83a42a18b8 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/ItemsDisplay.java @@ -0,0 +1,41 @@ +package io.anuke.mindustry.ui; + +import io.anuke.arc.collection.ObjectIntMap; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Item.Icon; +import io.anuke.mindustry.type.ItemType; + +import java.text.NumberFormat; +import java.util.Locale; + +import static io.anuke.mindustry.Vars.content; +import static io.anuke.mindustry.Vars.data; + +public class ItemsDisplay extends Table{ + private static final NumberFormat format = NumberFormat.getNumberInstance(Locale.getDefault()); + + public ItemsDisplay(){ + rebuild(); + } + + public void rebuild(){ + clear(); + top().left(); + margin(0); + + table("flat", t -> { + t.margin(10).marginLeft(15).marginTop(15f); + ObjectIntMap items = data.items(); + for(Item item : content.items()){ + if(item.type == ItemType.material && data.isUnlocked(item)){ + t.label(() -> format.format(items.get(item, 0))).left(); + t.addImage(item.icon(Icon.medium)).size(8*3).padLeft(4).padRight(4); + t.add(item.localizedName()).color(Color.LIGHT_GRAY).left(); + t.row(); + } + } + }); + } +} diff --git a/core/src/io/anuke/mindustry/ui/Links.java b/core/src/io/anuke/mindustry/ui/Links.java index 8e538759a7..5f47c61a5a 100644 --- a/core/src/io/anuke/mindustry/ui/Links.java +++ b/core/src/io/anuke/mindustry/ui/Links.java @@ -8,7 +8,7 @@ public class Links{ private static void createLinks(){ links = new LinkEntry[]{ - new LinkEntry("discord", "https://discord.gg/BKADYds", Color.valueOf("7289da")), + new LinkEntry("discord", "https://discord.gg/mindustry", Color.valueOf("7289da")), new LinkEntry("trello", "https://trello.com/b/aE2tcUwF", Color.valueOf("026aa7")), new LinkEntry("wiki", "http://mindustry.wikia.com/wiki/Mindustry_Wiki", Color.valueOf("0f142f")), new LinkEntry("itch.io", "https://anuke.itch.io/mindustry", Color.valueOf("fa5c5c")), diff --git a/core/src/io/anuke/mindustry/ui/MultiReqImage.java b/core/src/io/anuke/mindustry/ui/MultiReqImage.java new file mode 100644 index 0000000000..41c9ef2e44 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/MultiReqImage.java @@ -0,0 +1,31 @@ +package io.anuke.mindustry.ui; + +import io.anuke.arc.collection.Array; +import io.anuke.arc.scene.ui.layout.Stack; +import io.anuke.arc.util.Time; + +public class MultiReqImage extends Stack{ + private Array displays = new Array<>(); + private float time; + + public void add(ReqImage display){ + displays.add(display); + super.add(display); + } + + @Override + public void act(float delta){ + super.act(delta); + + time += Time.delta() / 60f; + + displays.each(req -> req.visible(false)); + + ReqImage valid = displays.find(ReqImage::valid); + if(valid != null){ + valid.visible(true); + }else{ + displays.get((int)(time) % displays.size).visible(true); + } + } +} diff --git a/core/src/io/anuke/mindustry/ui/ReqImage.java b/core/src/io/anuke/mindustry/ui/ReqImage.java new file mode 100644 index 0000000000..315ce91211 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/ReqImage.java @@ -0,0 +1,42 @@ +package io.anuke.mindustry.ui; + +import io.anuke.arc.function.BooleanProvider; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.Lines; +import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.scene.Element; +import io.anuke.arc.scene.ui.Image; +import io.anuke.arc.scene.ui.layout.Stack; +import io.anuke.arc.scene.ui.layout.Unit; +import io.anuke.mindustry.graphics.Pal; + +public class ReqImage extends Stack{ + private final BooleanProvider valid; + + public ReqImage(Element image, BooleanProvider valid){ + this.valid = valid; + add(image); + add(new Element(){ + { + visible(() -> !valid.get()); + } + + @Override + public void draw(){ + Lines.stroke(Unit.dp.scl(2f), Pal.removeBack); + Lines.line(x, y - 2f + height, x + width, y - 2f); + Draw.color(Pal.remove); + Lines.line(x, y + height, x + width, y); + Draw.reset(); + } + }); + } + + public ReqImage(TextureRegion region, BooleanProvider valid){ + this(new Image(region), valid); + } + + public boolean valid(){ + return valid.get(); + } +} diff --git a/core/src/io/anuke/mindustry/ui/TreeLayout.java b/core/src/io/anuke/mindustry/ui/TreeLayout.java index 209e3a5110..d5f0db4e8e 100644 --- a/core/src/io/anuke/mindustry/ui/TreeLayout.java +++ b/core/src/io/anuke/mindustry/ui/TreeLayout.java @@ -292,12 +292,12 @@ public class TreeLayout{ center, towardsRoot, awayFromRoot } - public static class TreeNode{ + public static class TreeNode{ public float width, height, x, y; //should be initialized by user - public TreeNode[] children; - public TreeNode parent; + public T[] children; + public T parent; private float mode, prelim, change, shift; private int number = -1; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java index a10edecfa0..af6ddffe1b 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java @@ -4,7 +4,7 @@ import io.anuke.arc.Core; import io.anuke.arc.graphics.Color; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectSet; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.io.Contributors; import io.anuke.mindustry.io.Contributors.Contributor; import io.anuke.mindustry.ui.Links; @@ -103,7 +103,7 @@ public class AboutDialog extends FloatingDialog{ dialog.cont.add("$credits.text"); dialog.cont.row(); if(!contributors.isEmpty()){ - dialog.cont.addImage("blank").color(Palette.accent).fillX().height(3f).pad(3f); + dialog.cont.addImage("blank").color(Pal.accent).fillX().height(3f).pad(3f); dialog.cont.row(); dialog.cont.add("$contributors"); dialog.cont.row(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java index 48fb57029b..2a6db67316 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java @@ -5,7 +5,7 @@ import io.anuke.arc.input.KeyCode; import io.anuke.arc.scene.ui.Image; import io.anuke.arc.scene.ui.KeybindDialog; import io.anuke.arc.util.Align; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; public class ControlsDialog extends KeybindDialog{ @@ -16,7 +16,7 @@ public class ControlsDialog extends KeybindDialog{ title.setAlignment(Align.center); titleTable.row(); titleTable.add(new Image("white")) - .growX().height(3f).pad(4f).get().setColor(Palette.accent); + .growX().height(3f).pad(4f).get().setColor(Pal.accent); } @Override diff --git a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java index 6e1c8add8c..c068eae79d 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java @@ -20,6 +20,7 @@ import static io.anuke.mindustry.Vars.*; public class CustomGameDialog extends FloatingDialog{ Difficulty difficulty = Difficulty.normal; + RulePreset lastPreset = RulePreset.survival; public CustomGameDialog(){ super("$customgame"); @@ -30,6 +31,7 @@ public class CustomGameDialog extends FloatingDialog{ } void setup(){ + state.rules = lastPreset.get(); cont.clear(); Table maps = new Table(); @@ -48,10 +50,10 @@ public class CustomGameDialog extends FloatingDialog{ modes.marginBottom(5); for(RulePreset mode : RulePreset.values()){ - - //todo fix presets - modes.addButton(mode.toString(), "toggle", () -> state.rules = mode.get())/* - .update(b -> b.setChecked(state.rules == mode))*/.group(group).size(140f, 54f); + modes.addButton(mode.toString(), "toggle", () -> { + state.rules = mode.get(); + lastPreset = mode; + }).update(b -> b.setChecked(lastPreset == mode)).group(group).size(140f, 54f); if(i++ % 2 == 1) modes.row(); } selmode.add(modes); @@ -112,7 +114,7 @@ public class CustomGameDialog extends FloatingDialog{ image.clicked(() -> { hide(); - control.playMap(map); + control.playMap(map, lastPreset.get()); }); maps.add(image); @@ -120,14 +122,6 @@ public class CustomGameDialog extends FloatingDialog{ i++; } - /* - ImageButton gen = maps.addImageButton("icon-editor", "clear", 16*4, () -> { - hide(); - world.generator.playRandomMap(); - }).growY().get(); - gen.row(); - gen.add("$map.random");*/ - if(world.maps.all().size == 0){ maps.add("$maps.none").pad(50); } @@ -136,7 +130,7 @@ public class CustomGameDialog extends FloatingDialog{ } private void displayGameModeHelp(){ - FloatingDialog d = new FloatingDialog(Core.bundle.get("mode.text.help.title")); + FloatingDialog d = new FloatingDialog(Core.bundle.get("mode.help.title")); d.setFillParent(false); Table table = new Table(); table.defaults().pad(1f); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java index a4da5816f4..1a6e383dd3 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java @@ -1,24 +1,23 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.collection.Array; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.game.Content; -import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.type.ContentType; import io.anuke.arc.scene.event.HandCursorListener; import io.anuke.arc.scene.ui.Image; import io.anuke.arc.scene.ui.ScrollPane; import io.anuke.arc.scene.ui.Tooltip; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.utils.UIUtils; - -import static io.anuke.mindustry.Vars.*; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.game.Content; +import io.anuke.mindustry.game.UnlockableContent; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.type.ContentType; public class DatabaseDialog extends FloatingDialog{ public DatabaseDialog(){ - super("database"); + super("$database"); shouldPause = true; addCloseButton(); @@ -38,31 +37,29 @@ public class DatabaseDialog extends FloatingDialog{ for(int j = 0; j < allContent.length; j ++){ ContentType type = ContentType.values()[j]; - Array array = allContent[j]; - if(array.size == 0 || !(array.first() instanceof UnlockableContent)) continue; + Array array = allContent[j].select(c -> c instanceof UnlockableContent && !((UnlockableContent)c).isHidden()); + if(array.size == 0) continue; - table.add("$content." + type.name() + ".name").growX().left().color(Palette.accent); + table.add("$content." + type.name() + ".name").growX().left().color(Pal.accent); table.row(); - table.addImage("white").growX().pad(5).padLeft(0).padRight(0).height(3).color(Palette.accent); + table.addImage("white").growX().pad(5).padLeft(0).padRight(0).height(3).color(Pal.accent); table.row(); table.table(list -> { list.left(); int maxWidth = UIUtils.portrait() ? 7 : 13; - int size = 8 * 6; + int size = 8 * 4; int count = 0; for(int i = 0; i < array.size; i++){ UnlockableContent unlock = (UnlockableContent) array.get(i); - if(unlock.isHidden()) continue; - - Image image = data.isUnlocked(unlock) ? new Image(unlock.getContentIcon()) : new Image("icon-tree-locked"); + Image image = unlocked(unlock) ? new Image(unlock.getContentIcon()) : new Image("icon-tree-locked"); image.addListener(new HandCursorListener()); list.add(image).size(size).pad(3); - if(data.isUnlocked(unlock)){ + if(unlocked(unlock)){ image.clicked(() -> Vars.ui.content.show(unlock)); image.addListener(new Tooltip<>(new Table("button"){{ add(unlock.localizedName()); @@ -79,4 +76,8 @@ public class DatabaseDialog extends FloatingDialog{ cont.add(pane); } + + boolean unlocked(UnlockableContent content){ + return (!Vars.world.isZone() && !Vars.state.is(State.menu)) || content.unlocked(); + } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java index f5870712b7..617ad236dc 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java @@ -1,198 +1,102 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; -import io.anuke.arc.collection.ObjectIntMap; -import io.anuke.arc.graphics.Color; -import io.anuke.arc.scene.ui.ScrollPane; +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.ObjectSet; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.Lines; +import io.anuke.arc.scene.Group; import io.anuke.arc.scene.ui.TextButton; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.scene.ui.layout.Unit; +import io.anuke.arc.util.Align; +import io.anuke.arc.util.Structs; +import io.anuke.mindustry.content.Zones; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.Saves.SaveSlot; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.io.SaveIO.SaveException; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.type.Zone; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Block.Icon; +import io.anuke.mindustry.ui.ItemsDisplay; +import io.anuke.mindustry.ui.TreeLayout; +import io.anuke.mindustry.ui.TreeLayout.TreeNode; import static io.anuke.mindustry.Vars.*; public class DeployDialog extends FloatingDialog{ + private final float nodeSize = Unit.dp.scl(210f); + private ObjectSet nodes = new ObjectSet<>(); + private ZoneInfoDialog info = new ZoneInfoDialog(); public DeployDialog(){ - super("$play"); + super(""); - shown(this::setup); - } + ZoneNode root = new ZoneNode(Zones.groundZero, null); - void setup(){ - buttons.clear(); - cont.clear(); + TreeLayout layout = new TreeLayout(); + layout.gapBetweenLevels = layout.gapBetweenNodes = Unit.dp.scl(50f); + layout.layout(root); addCloseButton(); buttons.addImageTextButton("$techtree", "icon-tree", 16 * 2, () -> ui.tech.show()).size(230f, 64f); - cont.stack(new Table(){{ - top().left().margin(10); + shown(this::setup); + } - ObjectIntMap items = data.items(); - for(Item item : content.items()){ - if(item.type == ItemType.material && data.isUnlocked(item)){ - label(() -> items.get(item, 0) + "").left(); - addImage(item.region).size(8*4).pad(4); - add("[LIGHT_GRAY]" + item.localizedName()).left(); - row(); - } - } + public void setup(){ + cont.clear(); + titleTable.remove(); + margin(0f).marginBottom(8); - }}, new ScrollPane(new Table(){{ + if(!Core.settings.getBool("zone-info", false)){ + Core.app.post(() -> ui.showInfoText("TEMPORARY GUIDE ON HOW TO PLAY ZONES", "- deploy to zones by selecting them here\n- most zones require items to deploy\n- once you survive a set amount of waves, you can launch all the resources in your core\n- use these items to research in the tech tree or uncover new zones")); - if(control.saves.getZoneSlot() == null){ + Core.settings.put("zone-info", true); + Core.settings.save(); + } - int i = 0; - for(Zone zone : content.zones()){ - table(t -> { - TextButton button = t.addButton("", () -> { - if(!data.isUnlocked(zone)){ - data.removeItems(zone.itemRequirements); - data.unlockContent(zone); - setup(); - }else{ - data.removeItems(zone.deployCost); - hide(); - world.playZone(zone); - } - }).size(250f).disabled(b -> !canUnlock(zone)).get(); + cont.stack(control.saves.getZoneSlot() == null ? new View() : new Table(){{ + SaveSlot slot = control.saves.getZoneSlot(); - button.clearChildren(); + TextButton[] b = {null}; - if(data.isUnlocked(zone)){ - button.table(title -> { - title.addImage("icon-zone").padRight(3); - title.add(zone.localizedName()); - }); - button.row(); + TextButton button = addButton(Core.bundle.format("resume", slot.getZone().localizedName()), () -> { + if(b[0].childrenPressed()) return; - if(data.getWaveScore(zone) > 0){ - button.add(Core.bundle.format("bestwave", data.getWaveScore(zone))); - } - - button.row(); - - button.add("$launch").color(Color.LIGHT_GRAY).pad(4); - button.row(); - button.table(req -> { - for(ItemStack stack : zone.deployCost){ - req.addImage(stack.item.region).size(8 * 3); - req.add(stack.amount + "").left(); - } - }).pad(3).growX(); - }else{ - button.addImage("icon-zone-locked"); - button.row(); - button.add("$locked").padBottom(6); - - if(!hidden(zone)){ - button.row(); - - button.table(req -> { - req.defaults().left(); - - if(zone.zoneRequirements.length > 0){ - req.table(r -> { - r.add("$complete").colspan(2).left(); - r.row(); - for(Zone other : zone.zoneRequirements){ - r.addImage("icon-zone").padRight(4); - r.add(other.localizedName()).color(Color.LIGHT_GRAY); - r.addImage(data.isCompleted(zone) ? "icon-check-2" : "icon-cancel-2") - .color(data.isCompleted(zone) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3); - r.row(); - } - }); - } - - req.row(); - - if(zone.itemRequirements.length > 0){ - req.table(r -> { - for(ItemStack stack : zone.itemRequirements){ - r.addImage(stack.item.region).size(8 * 3).padRight(4); - r.add(Math.min(data.getItem(stack.item), stack.amount) + "/" + stack.amount) - .color(stack.amount > data.getItem(stack.item) ? Color.SCARLET : Color.LIGHT_GRAY).left(); - r.row(); - } - }).padTop(10); - } - - req.row(); - - if(zone.blockRequirements.length > 0){ - req.table(r -> { - r.add("$research.list").colspan(2).left(); - r.row(); - for(Block block : zone.blockRequirements){ - r.addImage(block.icon(Icon.small)).size(8 * 3).padRight(4); - r.add(block.formalName).color(Color.LIGHT_GRAY); - r.addImage(data.isUnlocked(block) ? "icon-check-2" : "icon-cancel-2") - .color(data.isUnlocked(block) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3); - r.row(); - } - - }).padTop(10); - } - }).growX(); - } - } - }).pad(4); - - if(++i % 2 == 0){ - row(); + hide(); + ui.loadAnd(() -> { + try{ + control.saves.getZoneSlot().load(); + state.set(State.playing); + }catch(SaveException e){ //make sure to handle any save load errors! + e.printStackTrace(); + if(control.saves.getZoneSlot() != null) control.saves.getZoneSlot().delete(); + Core.app.post(() -> ui.showInfo("$save.corrupted")); + show(); } - } - }else{ - SaveSlot slot = control.saves.getZoneSlot(); + }); + }).size(230f).get(); + b[0] = button; - TextButton b[] = {null}; + String color = "[lightgray]"; - TextButton button = addButton(Core.bundle.format("resume", slot.getZone().localizedName()), () -> { - if(b[0].childrenPressed()) return; + button.defaults().colspan(2); + button.row(); + button.add(Core.bundle.format("save.wave", color + slot.getWave())); + button.row(); + button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime())); + button.row(); + button.add().grow(); + button.row(); - hide(); - ui.loadAnd(() -> { - try{ - control.saves.getZoneSlot().load(); - state.set(State.playing); - }catch(SaveException e){ //make sure to handle any save load errors! - e.printStackTrace(); - if(control.saves.getZoneSlot() != null) control.saves.getZoneSlot().delete(); - ui.showInfo("$save.corrupted"); - show(); - } - }); - }).size(200f).get(); - b[0] = button; + button.addButton("$abandon", () -> { + ui.showConfirm("$warning", "$abandon.text", () -> { + slot.delete(); + setup(); + }); + }).growX().height(50f).pad(-12).padTop(10); - String color = "[lightgray]"; - - button.defaults().colspan(2); - button.row(); - button.add(Core.bundle.format("save.wave", color + slot.getWave())); - button.row(); - button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime())); - button.row(); - button.add().grow(); - button.row(); - - button.addButton("$abandon", () -> { - ui.showConfirm("$warning", "$abandon.text", () -> { - slot.delete(); - setup(); - }); - }).growX().height(50f).pad(-12).padTop(10); - } - }})).grow(); + }}, new ItemsDisplay()).grow(); } boolean hidden(Zone zone){ @@ -204,19 +108,81 @@ public class DeployDialog extends FloatingDialog{ return false; } - boolean canUnlock(Zone zone){ - for(Zone other : zone.zoneRequirements){ - if(!data.isCompleted(other)){ - return false; + @Override + protected void drawBackground(float x, float y){ + drawDefaultBackground(x, y); + } + + void buildButton(Zone zone, TextButton button){ + button.setDisabled(() -> hidden(zone)); + button.clicked(() -> info.show(zone)); + + if(zone.unlocked()){ + button.addImage("icon-zone").padRight(3); + button.labelWrap(zone.localizedName()).width(140).growX(); + }else{ + button.addImage("icon-zone-locked"); + button.row(); + button.add("$locked"); + } + } + + //should be static variables of View, but that's impossible + static float panX = 0, panY = -200; + + class View extends Group{ + + { + for(ZoneNode node : nodes){ + TextButton button = new TextButton("", "node"); + button.setSize(node.width, node.height); + button.update(() -> { + button.setPosition(node.x + panX + width/2f, node.y + panY + height/2f, Align.center); + }); + button.clearChildren(); + buildButton(node.zone, button); + addChild(button); } + + dragged((x, y) -> { + panX += x; + panY += y; + }); } - for(Block other : zone.blockRequirements){ - if(!data.isUnlocked(other)){ - return false; + @Override + public void draw(){ + float offsetX = panX + width/2f + x, offsetY = panY + height/2f + y; + + for(ZoneNode node : nodes){ + for(ZoneNode child : node.children){ + Lines.stroke(Unit.dp.scl(3f), node.zone.locked() || child.zone.locked() ? Pal.locked : Pal.accent); + Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY); + } + } + + Draw.reset(); + super.draw(); + } + } + + class ZoneNode extends TreeNode{ + final Array arr = new Array<>(); + final Zone zone; + + ZoneNode(Zone zone, ZoneNode parent){ + this.zone = zone; + this.parent = parent; + this.width = this.height = nodeSize; + this.height /= 2f; + nodes.add(this); + + arr.selectFrom(content.zones(), other -> Structs.contains(other.zoneRequirements, zone)); + + children = new ZoneNode[arr.size]; + for(int i = 0; i < children.length; i++){ + children[i] = new ZoneNode(arr.get(i), this); } } - - return data.hasItems(zone.itemRequirements); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java index c064f59729..b21e875749 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; import io.anuke.arc.graphics.Color; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.arc.scene.ui.Dialog; import static io.anuke.mindustry.Vars.discordURL; @@ -33,7 +33,7 @@ public class DiscordDialog extends Dialog{ i.addImage("icon-discord").size(14 * 3); }).size(h).left(); - t.add("$discord").color(Palette.accent).growX().padLeft(10f); + t.add("$discord").color(Pal.accent).growX().padLeft(10f); }).size(470f, h).pad(10f); buttons.defaults().size(170f, 50); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java index 616780ef95..7e95935bef 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java @@ -5,7 +5,7 @@ import io.anuke.arc.input.KeyCode; import io.anuke.arc.util.Align; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.EventType.ResizeEvent; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.net.Net; import io.anuke.arc.Events; import io.anuke.arc.scene.ui.Dialog; @@ -22,7 +22,7 @@ public class FloatingDialog extends Dialog{ setFillParent(true); this.title.setAlignment(Align.center); titleTable.row(); - titleTable.addImage("white", Palette.accent) + titleTable.addImage("white", Pal.accent) .growX().height(3f).pad(4f); hidden(() -> { @@ -63,7 +63,7 @@ public class FloatingDialog extends Dialog{ @Override public void addCloseButton(){ - buttons.addImageTextButton("$back", "icon-arrow-left", 30f, this::hide).size(230f, 64f); + buttons.addImageTextButton("$back", "icon-arrow-left", 30f, this::hide).size(210f, 64f); keyDown(key -> { if(key == KeyCode.ESCAPE || key == KeyCode.BACK) { diff --git a/core/src/io/anuke/mindustry/ui/dialogs/GameOverDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/GameOverDialog.java index 0d0dfb3d34..f20e225fe2 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/GameOverDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/GameOverDialog.java @@ -2,8 +2,10 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.game.Stats.RankResult; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Item.Icon; import static io.anuke.mindustry.Vars.*; @@ -60,12 +62,18 @@ public class GameOverDialog extends FloatingDialog{ if(state.stats.itemsDelivered.get(item, 0) > 0){ cont.table(items -> { items.add(" [LIGHT_GRAY]" + state.stats.itemsDelivered.get(item, 0)); - items.addImage(item.region).size(8 *3).pad(4); + items.addImage(item.icon(Icon.medium)).size(8 *3).pad(4); }).left(); cont.row(); } } } + + if(world.isZone()){ + RankResult result = state.stats.calculateRank(world.getZone(), state.launched); + cont.add(Core.bundle.format("stat.rank", result.rank + result.modifier)); + cont.row(); + } }).pad(12); if(world.isZone()){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java index 9b4a3cee80..8771012793 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java @@ -6,7 +6,7 @@ import io.anuke.arc.scene.ui.ImageButton; import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.net.Net; import java.io.IOException; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java index 964fc1bf6d..91a263aa7c 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java @@ -14,7 +14,7 @@ import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.Platform; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.net.Host; import io.anuke.mindustry.net.Net; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LocalPlayerDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LocalPlayerDialog.java index 78640d7c2d..59f23e65ec 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LocalPlayerDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LocalPlayerDialog.java @@ -5,7 +5,7 @@ import io.anuke.arc.scene.ui.Image; import io.anuke.arc.scene.ui.layout.Stack; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Scaling; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.type.Player; import static io.anuke.mindustry.Vars.control; import static io.anuke.mindustry.Vars.players; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java index 1e31d68f21..402004af76 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java @@ -87,7 +87,7 @@ public class MapsDialog extends FloatingDialog{ TextButton button = maps.addButton("", "clear", () -> showMapInfo(map)).width(mapsize).pad(8).get(); button.clearChildren(); button.margin(9); - button.add(map.meta.tags.get("name", map.name)).growX().center().get().setEllipsis(true); + button.add(map.meta.tags.get("name", map.name)).width(mapsize - 18f).center().get().setEllipsis(true); button.row(); button.addImage("white").growX().pad(4).color(Color.GRAY); button.row(); @@ -138,8 +138,6 @@ public class MapsDialog extends FloatingDialog{ t.add(map.meta.description()).growX().wrap().padTop(2); t.row(); t.add("$editor.oregen.info").padRight(10).color(Color.GRAY); - t.row(); - t.add(map.meta.hasOreGen() ? "$on" : "$off").padTop(2); }).height(mapsize).width(mapsize); table.row(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java index b2b7068222..77e071c8a6 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java @@ -40,7 +40,11 @@ public class PausedDialog extends FloatingDialog{ cont.addButton("$back", this::hide).colspan(2).width(dw*2 + 20f); cont.row(); - cont.addButton("database", ui.database::show); + if(world.isZone()){ + cont.addButton("$techtree", ui.tech::show); + }else{ + cont.addButton("$database", ui.database::show); + } cont.addButton("$settings", ui.settings::show); if(!world.isZone()){ @@ -76,6 +80,8 @@ public class PausedDialog extends FloatingDialog{ cont.row(); cont.addRowImageTextButton("$load", "icon-load", isize, load::show).disabled(b -> Net.active()); + }else{ + cont.row(); } cont.addRowImageTextButton("$hostserver.mobile", "icon-host", isize, ui.host::show).disabled(b -> Net.active()); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index c54b1c8b3f..60e0ad707e 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -14,7 +14,7 @@ import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Align; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.net.Net; import static io.anuke.mindustry.Vars.*; @@ -49,7 +49,7 @@ public class SettingsMenuDialog extends SettingsDialog{ title.setAlignment(Align.center); titleTable.row(); titleTable.add(new Image("white")) - .growX().height(3f).pad(4f).get().setColor(Palette.accent); + .growX().height(3f).pad(4f).get().setColor(Pal.accent); cont.clearChildren(); cont.remove(); @@ -120,6 +120,7 @@ public class SettingsMenuDialog extends SettingsDialog{ void addSettings(){ //TODO add when sound works again //sound.volumePrefs(); + sound.add("[LIGHT_GRAY]there is no sound implemented in v4 yet"); game.screenshakePref(); game.checkPref("effects", true); @@ -194,8 +195,8 @@ public class SettingsMenuDialog extends SettingsDialog{ graphics.checkPref("fps", false); graphics.checkPref("indicators", true); + graphics.checkPref("animatedwater", !mobile); graphics.checkPref("lasers", true); - graphics.checkPref("minimap", !mobile); //minimap is disabled by default on mobile devices } private void back(){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java index 66e67e6779..d1fb9813fe 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java @@ -4,67 +4,52 @@ import io.anuke.arc.Core; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectSet; import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.input.KeyCode; import io.anuke.arc.math.Interpolation; -import io.anuke.arc.math.geom.Rectangle; -import io.anuke.arc.scene.Element; import io.anuke.arc.scene.Group; import io.anuke.arc.scene.actions.Actions; -import io.anuke.arc.scene.event.InputEvent; -import io.anuke.arc.scene.event.InputListener; import io.anuke.arc.scene.event.Touchable; import io.anuke.arc.scene.style.TextureRegionDrawable; import io.anuke.arc.scene.ui.ImageButton; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.util.Align; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Structs; import io.anuke.mindustry.content.TechTree; import io.anuke.mindustry.content.TechTree.TechNode; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.ui.ItemsDisplay; import io.anuke.mindustry.ui.TreeLayout; import io.anuke.mindustry.ui.TreeLayout.TreeNode; -import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; import static io.anuke.mindustry.Vars.*; public class TechTreeDialog extends FloatingDialog{ + private final float nodeSize = Unit.dp.scl(60f); private ObjectSet nodes = new ObjectSet<>(); private TechTreeNode root = new TechTreeNode(TechTree.root, null); - private static final float nodeSize = 60f; + private ItemsDisplay items; public TechTreeDialog(){ super(""); - cont.setFillParent(true); + titleTable.remove(); + margin(0f).marginBottom(8); + cont.stack(new View(), items = new ItemsDisplay()).grow(); - TreeLayout layout = new TreeLayout(); - layout.gapBetweenLevels = 60f; - layout.gapBetweenNodes = 40f; - layout.layout(root); - - cont.add(new View()).grow(); - - { //debug code; TODO remove - ObjectSet used = new ObjectSet().select(t -> true); - for(TechTreeNode node : nodes){ - used.add(node.node.block); - } - Array recipes = content.blocks().select(r -> r.isVisible() && !used.contains(r)); - recipes.sort(Structs.comparing(r -> r.buildCost)); - - if(recipes.size > 0){ - Log.info("Recipe tree coverage: {0}%", (int)((float)nodes.size / content.blocks().select(Block::isVisible).size * 100)); - Log.info("Missing items: "); - recipes.forEach(r -> Log.info(" {0}", r)); - } - } - - shown(() -> checkNodes(root)); + shown(() -> { + checkNodes(root); + treeLayout(); + }); + hidden(ui.deploy::setup); addCloseButton(); + + buttons.addImageTextButton("$database", "icon-database", 14*2, () -> { + hide(); + ui.database.show(); + }).size(210f, 64f); } @Override @@ -72,52 +57,70 @@ public class TechTreeDialog extends FloatingDialog{ drawDefaultBackground(x, y); } - void checkNodes(TechTreeNode node){ - boolean locked = locked(node); - if(!locked) node.visible = true; - for(TreeNode child : node.children){ - TechTreeNode l = (TechTreeNode)child; - l.visible = !locked && l.node.block.isVisible(); - checkNodes(l); + void treeLayout(){ + TreeLayout layout = new TreeLayout(); + layout.gapBetweenLevels = Unit.dp.scl(60f); + layout.gapBetweenNodes = Unit.dp.scl(40f); + LayoutNode node = new LayoutNode(root, null); + layout.layout(node); + copyInfo(node); + } + + void copyInfo(LayoutNode node){ + node.node.x = node.x; + node.node.y = node.y; + if(node.children != null){ + for(LayoutNode child : node.children){ + copyInfo(child); + } } } - void showToast(String info){ - int maxIndex = 0; - - for(Element e : Core.scene.root.getChildren()){ - if("toast".equals(e.getName())){ - maxIndex = Math.max(maxIndex, (Integer)e.getUserObject() + 1); - } + void checkNodes(TechTreeNode node){ + boolean locked = locked(node.node); + if(!locked) node.visible = true; + for(TechTreeNode l : node.children){ + l.visible = !locked; + checkNodes(l); } - int m = maxIndex; + items.rebuild(); + } + void showToast(String info){ Table table = new Table(); - table.actions(Actions.fadeOut(7f, Interpolation.fade), Actions.removeActor()); + table.actions(Actions.fadeOut(0.5f, Interpolation.fade), Actions.removeActor()); table.top().add(info); table.setName("toast"); - table.setUserObject(maxIndex); table.update(() -> { table.toFront(); - table.setPosition(Core.graphics.getWidth()/2f, Core.graphics.getHeight() - 21 - m*20f, Align.top); + table.setPosition(Core.graphics.getWidth()/2f, Core.graphics.getHeight() - 21, Align.top); }); Core.scene.add(table); } - boolean locked(TreeNode node){ - return locked(((TechTreeNode)node).node); - } - boolean locked(TechNode node){ - return !data.isUnlocked(node.block); + return node.block.locked(); } - class TechTreeNode extends TreeNode{ + class LayoutNode extends TreeNode{ + final TechTreeNode node; + + LayoutNode(TechTreeNode node, LayoutNode parent){ + this.node = node; + this.parent = parent; + this.width = this.height = nodeSize; + if(node.children != null){ + children = Array.with(node.children).select(n -> n.visible).map(t -> new LayoutNode(t, this)).toArray(LayoutNode.class); + } + } + } + + class TechTreeNode extends TreeNode{ final TechNode node; boolean visible = true; - public TechTreeNode(TechNode node, TreeNode parent){ + TechTreeNode(TechNode node, TechTreeNode parent){ this.node = node; this.parent = parent; this.width = this.height = nodeSize; @@ -134,7 +137,6 @@ public class TechTreeDialog extends FloatingDialog{ class View extends Group{ float panX = 0, panY = -200; boolean moved = false; - Rectangle clip = new Rectangle(); ImageButton hoverNode; Table infoTable = new Table(); @@ -143,11 +145,12 @@ public class TechTreeDialog extends FloatingDialog{ for(TechTreeNode node : nodes){ ImageButton button = new ImageButton(node.node.block.icon(Icon.medium), "node"); + button.visible(() -> node.visible); button.clicked(() -> { if(mobile){ hoverNode = button; rebuild(); - }else if(data.hasItems(node.node.requirements) && locked(node)){ + }else if(data.hasItems(node.node.requirements) && locked(node.node)){ unlock(node.node); } }); @@ -158,7 +161,7 @@ public class TechTreeDialog extends FloatingDialog{ } }); button.exited(() -> { - if(hoverNode == button && !infoTable.hasMouse() && !hoverNode.hasMouse()){ + if(!mobile && hoverNode == button && !infoTable.hasMouse() && !hoverNode.hasMouse()){ hoverNode = null; rebuild(); } @@ -166,44 +169,34 @@ public class TechTreeDialog extends FloatingDialog{ button.touchable(() -> !node.visible ? Touchable.disabled : Touchable.enabled); button.setUserObject(node.node); button.tapped(() -> moved = false); - button.setSize(nodeSize, nodeSize); + button.setSize(nodeSize); button.update(() -> { - button.setPosition(node.x + panX + width/2f, node.y + panY + height/2f, Align.center); - button.getStyle().up = Core.scene.skin.getDrawable(!locked(node) ? "content-background" : "content-background-locked"); + float offset = (Core.graphics.getHeight() % 2) / 2f; + button.setPosition(node.x + panX + width/2f, node.y + panY + height/2f + offset, Align.center); + button.getStyle().up = Core.scene.skin.getDrawable(!locked(node.node) ? "content-background" : "content-background-locked"); ((TextureRegionDrawable)button.getStyle().imageUp) .setRegion(node.visible ? node.node.block.icon(Icon.medium) : Core.atlas.find("icon-tree-locked")); - button.getImage().setColor(!locked(node) ? Color.WHITE : Color.GRAY); + button.getImage().setColor(!locked(node.node) ? Color.WHITE : Color.GRAY); }); addChild(button); } - addListener(new InputListener(){ - float lastX, lastY; - @Override - public void touchDragged(InputEvent event, float mx, float my, int pointer){ - panX -= lastX - mx; - panY -= lastY - my; - lastX = mx; - lastY = my; - moved = true; - } - - @Override - public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){ - lastX = x; - lastY = y; - return true; - } + dragged((x, y) -> { + moved = true; + panX += x; + panY += y; }); } void unlock(TechNode node){ data.unlockContent(node.block); data.removeItems(node.requirements); - showToast(Core.bundle.format("researched", node.block.formalName)); + showToast(Core.bundle.format("researched", node.block.localizedName)); checkNodes(root); hoverNode = null; + treeLayout(); rebuild(); + Core.scene.act(); } void rebuild(){ @@ -235,7 +228,7 @@ public class TechTreeDialog extends FloatingDialog{ infoTable.table(desc -> { desc.left().defaults().left(); - desc.add(node.block.formalName); + desc.add(node.block.localizedName); desc.row(); if(locked(node)){ desc.table(t -> { @@ -245,8 +238,8 @@ public class TechTreeDialog extends FloatingDialog{ list.left(); list.addImage(req.item.getContentIcon()).size(8 * 3).padRight(3); list.add(req.item.localizedName()).color(Color.LIGHT_GRAY); - list.add(" " + Math.min(data.items().get(req.item, 0), req.amount) + " / " + req.amount) - .color(data.has(req.item, req.amount) ? Color.LIGHT_GRAY : Color.SCARLET); + list.label(() -> " " + Math.min(data.getItem(req.item), req.amount) + " / " + req.amount) + .update(l -> l.setColor(data.has(req.item, req.amount) ? Color.LIGHT_GRAY : Color.SCARLET)); }).fillX().left(); t.row(); } @@ -270,14 +263,17 @@ public class TechTreeDialog extends FloatingDialog{ public void draw(){ float offsetX = panX + width/2f + x, offsetY = panY + height/2f + y; - for(TreeNode node : nodes){ - for(TreeNode child : node.children){ - Lines.stroke(3f, locked(node) || locked(child) ? Palette.locked : Palette.accent); + for(TechTreeNode node : nodes){ + if(!node.visible) continue; + for(TechTreeNode child : node.children){ + if(!child.visible) continue; + Lines.stroke(Unit.dp.scl(3f), locked(node.node) || locked(child.node) ? Pal.locked : Pal.accent); Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY); } } + Draw.reset(); super.draw(); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/TraceDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/TraceDialog.java index b588d4d7e4..5dd8e13142 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/TraceDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/TraceDialog.java @@ -37,7 +37,7 @@ public class TraceDialog extends FloatingDialog{ table.row(); table.add(Core.bundle.format("trace.structureblocksbroken", info.structureBlocksBroken)); table.row(); - table.add(Core.bundle.format("trace.lastblockbroken", info.lastBlockBroken.formalName)); + table.add(Core.bundle.format("trace.lastblockbroken", info.lastBlockBroken.localizedName)); table.row(); table.add().pad(5); @@ -45,7 +45,7 @@ public class TraceDialog extends FloatingDialog{ table.add(Core.bundle.format("trace.totalblocksplaced", info.totalBlocksPlaced)); table.row(); - table.add(Core.bundle.format("trace.lastblockplaced", info.lastBlockPlaced.formalName)); + table.add(Core.bundle.format("trace.lastblockplaced", info.lastBlockPlaced.localizedName)); table.row(); cont.add(table); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java new file mode 100644 index 0000000000..bb5ef324f5 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java @@ -0,0 +1,221 @@ +package io.anuke.mindustry.ui.dialogs; + +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.scene.ui.Button; +import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.type.ItemType; +import io.anuke.mindustry.type.Zone; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Block.Icon; + +import static io.anuke.mindustry.Vars.*; + +public class ZoneInfoDialog extends FloatingDialog{ + + public ZoneInfoDialog(){ + super(""); + + titleTable.remove(); + addCloseButton(); + } + + @Override + protected void drawBackground(float x, float y){ + drawDefaultBackground(x, y); + } + + public void show(Zone zone){ + setup(zone); + show(); + } + + private void setup(Zone zone){ + cont.clear(); + + Table iteminfo = new Table(); + Runnable rebuildItems = () -> { + int i = 0; + iteminfo.clear(); + ItemStack[] stacks = zone.unlocked() ? zone.getLaunchCost() : zone.itemRequirements; + for(ItemStack stack : stacks){ + if(stack.amount == 0) continue; + + if(i++ % 2 == 0){ + iteminfo.row(); + } + iteminfo.addImage(stack.item.icon(Item.Icon.medium)).size(8*3).padRight(1); + iteminfo.add(stack.amount + "").color(Color.LIGHT_GRAY).padRight(5); + } + }; + + rebuildItems.run(); + + cont.table(cont -> { + if(zone.locked()){ + cont.addImage("icon-zone-locked"); + cont.row(); + cont.add("$locked").padBottom(6); + cont.row(); + + cont.table(req -> { + req.defaults().left(); + + if(zone.zoneRequirements.length > 0){ + req.table(r -> { + r.add("$complete").colspan(2).left(); + r.row(); + for(Zone other : zone.zoneRequirements){ + r.addImage("icon-zone").padRight(4); + r.add(other.localizedName()).color(Color.LIGHT_GRAY); + r.addImage(other.isCompleted() ? "icon-check-2" : "icon-cancel-2") + .color(other.isCompleted() ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3); + r.row(); + } + }); + } + + req.row(); + + if(zone.blockRequirements.length > 0){ + req.table(r -> { + r.add("$research.list").colspan(2).left(); + r.row(); + for(Block block : zone.blockRequirements){ + r.addImage(block.icon(Icon.small)).size(8 * 3).padRight(4); + r.add(block.localizedName).color(Color.LIGHT_GRAY); + r.addImage(data.isUnlocked(block) ? "icon-check-2" : "icon-cancel-2") + .color(data.isUnlocked(block) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3); + r.row(); + } + + }).padTop(10); + } + }).growX(); + + }else{ + cont.add(zone.localizedName()).color(Pal.accent).growX().center(); + cont.row(); + cont.addImage("white").color(Pal.accent).height(3).pad(6).growX(); + cont.row(); + cont.table(res -> { + res.add("$zone.resources").padRight(6); + if(zone.resources.length > 0){ + for(Item item : zone.resources){ + res.addImage(item.icon(Item.Icon.medium)).size(8 * 3); + } + }else{ + res.add("$none"); + } + }); + + if(zone.bestWave() > 0){ + cont.row(); + cont.add(Core.bundle.format("bestwave", zone.bestWave())); + } + + Table load = new Table(); + //thanks java, absolutely brilliant syntax here + Runnable[] rebuildLoadout = {null}; + rebuildLoadout[0] = () -> { + load.clear(); + float bsize = 40f; + int step = 100; + + load.left(); + for(ItemStack stack : zone.getStartingItems()){ + load.addButton("-", () -> { + stack.amount = Math.max(stack.amount - step, 0); + zone.updateLaunchCost(); + rebuildItems.run(); + }).size(bsize).pad(2); + load.addButton("+", () -> { + stack.amount = Math.min(stack.amount + step, zone.loadout.core().itemCapacity); + zone.updateLaunchCost(); + rebuildItems.run(); + }).size(bsize).pad(2); + + load.addImage(stack.item.icon(Item.Icon.medium)).size(8 * 3).padRight(4); + load.label(() -> stack.amount + "").left(); + + load.row(); + } + + load.addButton("$add", () -> { + FloatingDialog dialog = new FloatingDialog(""); + dialog.setFillParent(false); + for(Item item : content.items().select(item -> data.getItem(item) > 0 && item.type == ItemType.material && zone.getStartingItems().find(stack -> stack.item == item) == null)){ + TextButton button = dialog.cont.addButton("", () -> { + zone.getStartingItems().add(new ItemStack(item, 0)); + zone.updateLaunchCost(); + rebuildLoadout[0].run(); + dialog.hide(); + }).size(300f, 35f).pad(1).get(); + button.clearChildren(); + button.left(); + button.addImage(item.icon(Item.Icon.medium)).size(8*3).pad(4); + button.add(item.localizedName); + dialog.cont.row(); + } + dialog.show(); + }).colspan(4).size(100f, bsize).left().disabled(b -> !content.items().contains(item -> data.getItem(item) > 0 && item.type == ItemType.material && !zone.getStartingItems().contains(stack -> stack.item == item))); + }; + + rebuildLoadout[0].run(); + + cont.row(); + cont.table(zone.canConfigure() ? "button" : "button-disabled", t -> { + t.left(); + t.add(!zone.canConfigure() ? Core.bundle.format("configure.locked", zone.configureWave) : "$configure").growX().wrap(); + if(zone.canConfigure()){ + t.row(); + t.pane(load).pad(2).growX().left(); + } + }).width(300f).pad(4).left(); + } + }); + + cont.row(); + + Button button = cont.addButton(zone.locked() ? "$uncover" : "$launch", () -> { + if(!data.isUnlocked(zone)){ + data.removeItems(zone.itemRequirements); + data.unlockContent(zone); + ui.deploy.setup(); + setup(zone); + }else{ + ui.deploy.hide(); + data.removeItems(zone.getLaunchCost()); + hide(); + world.playZone(zone); + } + }).minWidth(150f).margin(13f).padTop(5).disabled(b -> zone.locked() ? !canUnlock(zone) : !data.hasItems(zone.getLaunchCost())).get(); + + button.row(); + button.add(iteminfo); + } + + private boolean canUnlock(Zone zone){ + if(data.isUnlocked(zone)){ + return true; + } + + for(Zone other : zone.zoneRequirements){ + if(!other.isCompleted()){ + return false; + } + } + + for(Block other : zone.blockRequirements){ + if(!data.isUnlocked(other)){ + return false; + } + } + + return data.hasItems(zone.itemRequirements); + } +} diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java index 6617701231..4dc0efa263 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java @@ -29,6 +29,7 @@ public class BlockConfigFragment extends Fragment{ @Override public void build(Group parent){ + table.visible(false); parent.addChild(table); } diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java index e127f8db10..4d65d33136 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java @@ -20,10 +20,11 @@ import io.anuke.arc.util.Align; import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Item.Icon; import io.anuke.mindustry.ui.ItemImage; import io.anuke.mindustry.world.Tile; @@ -49,7 +50,7 @@ public class BlockInventoryFragment extends Fragment{ int removed = tile.block().removeStack(tile, item, amount); - player.inventory.addItem(item, removed); + player.addItem(item, removed); for(int j = 0; j < Mathf.clamp(removed / 3, 1, 8); j++){ Time.run(j * 3f, () -> Call.transferItemEffect(item, tile.drawx(), tile.drawy(), player)); } @@ -65,6 +66,10 @@ public class BlockInventoryFragment extends Fragment{ } public void showFor(Tile t){ + if(this.tile == t.target()){ + hide(); + return; + } this.tile = t.target(); if(tile == null || tile.entity == null || !tile.block().isAccessible() || tile.entity.items.total() == 0) return; @@ -97,7 +102,7 @@ public class BlockInventoryFragment extends Fragment{ holdTime += Time.delta(); if(holdTime >= holdWithdraw){ - int amount = Math.min(tile.entity.items.get(lastItem), player.inventory.itemCapacityUsed(lastItem)); + int amount = Math.min(tile.entity.items.get(lastItem), player.maxAccepted(lastItem)); Call.requestItem(player, tile, lastItem, amount); holding = false; holdTime = 0f; @@ -120,7 +125,7 @@ public class BlockInventoryFragment extends Fragment{ int row = 0; table.margin(6f); - table.defaults().size(16 * 2.5f).space(6f); + table.defaults().size(8 * 5).space(6f); if(tile.block().hasItems){ @@ -130,12 +135,12 @@ public class BlockInventoryFragment extends Fragment{ container.add(i); - BooleanProvider canPick = () -> player.inventory.canAcceptItem(item); + BooleanProvider canPick = () -> player.acceptsItem(item) && !state.isPaused(); HandCursorListener l = new HandCursorListener(); l.setEnabled(canPick); - ItemImage image = new ItemImage(item.region, () -> { + ItemImage image = new ItemImage(item.icon(Icon.xlarge), () -> { if(tile == null || tile.entity == null){ return ""; } @@ -147,11 +152,13 @@ public class BlockInventoryFragment extends Fragment{ @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){ if(!canPick.get() || !tile.entity.items.has(item)) return false; - int amount = Math.min(1, player.inventory.itemCapacityUsed(item)); - Call.requestItem(player, tile, item, amount); - lastItem = item; - holding = true; - holdTime = 0f; + int amount = Math.min(1, player.maxAccepted(item)); + if(amount > 0){ + Call.requestItem(player, tile, item, amount); + lastItem = item; + holding = true; + holdTime = 0f; + } return true; } diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index ee0f2a0e29..fff489d66c 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -15,34 +15,32 @@ import io.anuke.arc.scene.ui.ImageButton; import io.anuke.arc.scene.ui.TextButton; import io.anuke.arc.scene.ui.layout.Stack; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.scene.ui.layout.Unit; +import io.anuke.arc.scene.utils.Elements; import io.anuke.arc.util.Align; import io.anuke.arc.util.Scaling; import io.anuke.arc.util.Time; +import io.anuke.arc.util.Tmp; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.EventType.StateChangeEvent; -import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Packets.AdminAction; +import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.ui.IntFormat; -import io.anuke.mindustry.ui.dialogs.FloatingDialog; import static io.anuke.mindustry.Vars.*; public class HudFragment extends Fragment{ public final PlacementFragment blockfrag = new PlacementFragment(); - private ImageButton menu, flip; - private Stack wavetable; - private Table infolabel; + private ImageButton flip; private Table lastUnlockTable; private Table lastUnlockLayout; private boolean shown = true; - private float dsize = 58; + private float dsize = 59; private float isize = 40; private float coreAttackTime; @@ -53,7 +51,6 @@ public class HudFragment extends Fragment{ //menu at top left parent.fill(cont -> { - cont.top().left().visible(() -> !state.is(State.menu)); if(mobile){ @@ -61,7 +58,7 @@ public class HudFragment extends Fragment{ select.left(); select.defaults().size(dsize).left(); - menu = select.addImageButton("icon-menu", "clear", isize, ui.paused::show).get(); + select.addImageButton("icon-menu", "clear", isize, ui.paused::show); flip = select.addImageButton("icon-arrow-up", "clear", isize, this::toggleMenus).get(); select.addImageButton("icon-pause", "clear", isize, () -> { @@ -86,6 +83,8 @@ public class HudFragment extends Fragment{ }else{ ui.chatfrag.toggle(); } + }else if(world.isZone()){ + ui.tech.show(); }else{ ui.database.show(); } @@ -93,15 +92,15 @@ public class HudFragment extends Fragment{ if(Net.active() && mobile){ i.getStyle().imageUp = Core.scene.skin.getDrawable("icon-chat"); }else{ - i.getStyle().imageUp = Core.scene.skin.getDrawable("icon-unlocks"); + i.getStyle().imageUp = Core.scene.skin.getDrawable("icon-database-small"); } }).get(); - select.addImage("blank").color(Palette.accent).width(6f).fillY(); - }); + select.addImage("blank").color(Pal.accent).width(3f).fillY(); + }).left(); cont.row(); - cont.addImage("blank").height(6f).color(Palette.accent).fillX(); + cont.addImage("blank").height(3f).color(Pal.accent).fillX(); cont.row(); } @@ -111,45 +110,57 @@ public class HudFragment extends Fragment{ } }); - Stack stack = new Stack(); - TextButton waves = new TextButton("", "wave"); - Table btable = new Table().margin(0); + cont.table(stuff -> { + stuff.left(); + Stack stack = new Stack(); + TextButton waves = new TextButton("", "wave"); + Table btable = new Table().margin(0); - stack.add(waves); - stack.add(btable); + stack.add(waves); + stack.add(btable); - wavetable = stack; - - addWaveTable(waves); - addPlayButton(btable); - cont.add(stack).width(dsize * 4 + 6f); - - cont.row(); - - //fps display - infolabel = cont.table(t -> { - IntFormat fps = new IntFormat("fps"); - IntFormat ping = new IntFormat("ping"); - t.label(() -> fps.get(Core.graphics.getFramesPerSecond())).padRight(10); - t.row(); - if(Net.hasClient()){ - t.label(() -> ping.get(Net.getPing())).visible(Net::client).colspan(2); - } - }).size(-1).visible(() -> Core.settings.getBool("fps")).update(t -> t.setTranslation(0, (!waves.isVisible() ? wavetable.getHeight() : Math.min(wavetable.getTranslation().y, wavetable.getHeight())))).get(); - - //make wave box appear below rest of menu - if(mobile){ - cont.swapActor(wavetable, menu.getParent()); - } + addWaveTable(waves); + addPlayButton(btable); + stuff.add(stack).width(dsize * 4 + 3f); + stuff.row(); + stuff.table("button", t -> t.margin(10f).add(new Bar("boss.health", Pal.health, () -> state.boss() == null ? 0f : state.boss().healthf()).blink(Color.WHITE)) + .grow()).fillX().visible(() -> world.isZone() && state.boss() != null).height(60f).get(); + stuff.row(); + }).visible(() -> shown); }); - //minimap - //parent.fill(t -> t.top().right().add(new Minimap()).visible(() -> !state.is(State.menu) && Core.settings.getBool("minimap"))); - //paused table + //fps display + parent.fill(info -> { + info.top().right().margin(4).visible(() -> Core.settings.getBool("fps") && !state.is(State.menu)); + IntFormat fps = new IntFormat("fps"); + IntFormat ping = new IntFormat("ping"); + info.label(() -> fps.get(Core.graphics.getFramesPerSecond())).right(); + info.row(); + info.label(() -> ping.get(Net.getPing())).visible(Net::client).right(); + }); + + //spawner warning parent.fill(t -> { - t.top().visible(() -> state.is(State.paused) && !Net.active()); - t.table("button", top -> top.add("$paused").pad(6f)); + t.touchable(Touchable.disabled); + t.visible(() -> !state.is(State.menu)); + t.table("flat", c -> c.add("$nearpoint") + .update(l -> l.setColor(Tmp.c1.set(Color.WHITE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 10f, 1f)))) + .get().setAlignment(Align.center, Align.center)) + .margin(6).update(u -> u.color.a = Mathf.lerpDelta(u.color.a, Mathf.num(world.spawner.playerNear()), 0.1f)).get().color.a = 0f; + }); + + //out of bounds warning + parent.fill(t -> { + t.touchable(Touchable.disabled); + t.visible(() -> !state.is(State.menu)); + t.table("flat", c -> c.add("") + .update(l ->{ + l.setColor(Tmp.c1.set(Color.WHITE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 10f, 1f))); + l.setText(Core.bundle.format("outofbounds", (int)((boundsCountdown - players[0].destructTime) / 60f))); + }).get().setAlignment(Align.center, Align.center)).margin(6).update(u -> { + u.color.a = Mathf.lerpDelta(u.color.a, Mathf.num(players[0].isOutOfBounds()), 0.1f); + }).get().color.a = 0f; }); parent.fill(t -> { @@ -196,8 +207,45 @@ public class HudFragment extends Fragment{ .update(label -> label.getColor().set(Color.ORANGE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 2f, 1f)))); }); - parent.fill(t -> t.top().right().addRowImageTextButton("$launch", "icon-arrow-up", 8*3, () -> world.launchZone()) - .size(94f, 70f).visible(() -> world.isZone() && world.getZone().metCondition())); + //launch button + parent.fill(t -> { + t.top().visible(() -> !state.is(State.menu)); + + TextButton button = Elements.newButton("$launch", () -> ui.showConfirm("$launch", "$launch.confirm", Call::launchZone)); + + button.getStyle().disabledFontColor = Color.WHITE; + button.visible(() -> + world.isZone() && + world.getZone().metCondition() && + !Net.client() && + state.wave % world.getZone().launchPeriod == 0 && + state.wavetime < state.rules.waveSpacing * launchWaveMultiplier - 70); + + button.update(() -> { + if(world.getZone() == null){ + button.setText(""); + return; + } + + button.setText(state.enemies() > 0 ? Core.bundle.format("launch.unable", state.enemies()) : Core.bundle.get("launch") + "\n" + + Core.bundle.format("launch.next", state.wave + world.getZone().launchPeriod)); + + button.getLabel().setColor(Tmp.c1.set(Color.WHITE).lerp(state.enemies() > 0 ? Color.WHITE : Pal.accent, + Mathf.absin(Time.time(), 7f, 1f))); + }); + + button.setDisabled(() -> state.enemies() > 0); + + button.getLabelCell().left().get().setAlignment(Align.left, Align.left); + + t.add(button).size(350f, 80f); + }); + + //paused table + parent.fill(t -> { + t.top().visible(() -> state.is(State.paused) && !Net.active()); + t.table("button", top -> top.add("$paused").pad(6f)); + }); //'saving' indicator parent.fill(t -> { @@ -229,6 +277,10 @@ public class HudFragment extends Fragment{ Actions.run(() -> container.actions(Actions.translateBy(0, table.getPrefHeight(), 1f, Interpolation.fade), Actions.removeActor()))); } + public boolean shown(){ + return shown; + } + /** Show unlock notification for a new recipe. */ public void showUnlock(UnlockableContent content){ //some content may not have icons... yet @@ -314,38 +366,25 @@ public class HudFragment extends Fragment{ } } - public void showTextDialog(String str){ - new FloatingDialog("$mission.info"){{ - shouldPause = true; - setFillParent(false); - getCell(cont).growX(); - cont.margin(15).add(str).width(400f).wrap().get().setAlignment(Align.left, Align.left); - buttons.addButton("$continue", this::hide).size(140, 60).pad(4); - }}.show(); + public void showLaunch(){ + Image image = new Image("white"); + image.getColor().a = 0f; + image.setFillParent(true); + image.actions(Actions.fadeIn(40f / 60f)); + image.update(() -> { + if(state.is(State.menu)){ + image.remove(); + } + }); + Core.scene.add(image); } private void toggleMenus(){ - wavetable.clearActions(); - infolabel.clearActions(); - - float dur = 0.3f; - Interpolation in = Interpolation.pow3Out; - if(flip != null){ flip.getStyle().imageUp = Core.scene.skin.getDrawable(shown ? "icon-arrow-down" : "icon-arrow-up"); } - if(shown){ - shown = false; - blockfrag.toggle(dur, in); - wavetable.actions(Actions.translateBy(0, (wavetable.getHeight() + Unit.dp.scl(dsize) + Unit.dp.scl(6)) - wavetable.getTranslation().y, dur, in)); - infolabel.actions(Actions.translateBy(0, (wavetable.getHeight()) - wavetable.getTranslation().y, dur, in)); - }else{ - shown = true; - blockfrag.toggle(dur, in); - wavetable.actions(Actions.translateBy(0, -wavetable.getTranslation().y, dur, in)); - infolabel.actions(Actions.translateBy(0, -infolabel.getTranslation().y, dur, in)); - } + shown = !shown; } private void addWaveTable(TextButton table){ @@ -391,12 +430,8 @@ public class HudFragment extends Fragment{ }else{ state.wavetime = 0f; } - }).growY().fillX().right().width(40f).update(l -> { - boolean vis = !state.rules.waveTimer && ((Net.server() || players[0].isAdmin) || !Net.active()); - boolean paused = state.is(State.paused) || !vis; - - l.getStyle().imageUp = Core.scene.skin.getDrawable(vis ? "icon-play" : "clear"); - l.touchable(!paused ? Touchable.enabled : Touchable.disabled); - }).visible(() -> !state.rules.waveTimer && ((Net.server() || players[0].isAdmin) || !Net.active()) && unitGroups[Team.red.ordinal()].size() == 0); + }).growY().fillX().right().width(40f) + .visible(() -> state.rules.waves && ((Net.server() || players[0].isAdmin) || !Net.active()) && state.enemies() == 0 + && (state.wavetime < state.rules.waveSpacing - 60 || !state.rules.waveTimer)); } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java b/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java index 031077b367..2b178a2125 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.ui.fragments; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.arc.scene.Group; import io.anuke.arc.scene.event.Touchable; import io.anuke.arc.scene.ui.Label; @@ -18,11 +18,11 @@ public class LoadingFragment extends Fragment{ t.touchable(Touchable.enabled); t.add().height(70f).row(); - t.addImage("white").growX().height(3f).pad(4f).growX().get().setColor(Palette.accent); + t.addImage("white").growX().height(3f).pad(4f).growX().get().setColor(Pal.accent); t.row(); t.add("$loading").name("namelabel").pad(10f); t.row(); - t.addImage("white").growX().height(3f).pad(4f).growX().get().setColor(Palette.accent); + t.addImage("white").growX().height(3f).pad(4f).growX().get().setColor(Pal.accent); t.row(); button = t.addButton("$cancel", () -> {}).pad(20).size(250f, 70f).visible(false).get(); diff --git a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java index f1bc3facb7..319bdc8ed4 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java @@ -11,6 +11,7 @@ import io.anuke.mindustry.game.EventType.ResizeEvent; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.ui.MenuButton; import io.anuke.mindustry.ui.MobileButton; +import io.anuke.mindustry.ui.dialogs.FloatingDialog; import static io.anuke.mindustry.Vars.*; @@ -42,7 +43,7 @@ public class MenuFragment extends Fragment{ } //version info - parent.fill(c -> c.bottom().left().add(Strings.formatArgs("Mindustry v{0} {1}-{2} {3}{4}", Version.number, Version.modifier, Version.type, + parent.fill(c -> c.bottom().left().add(Strings.format("Mindustry v{0} {1}-{2} {3}{4}", Version.number, Version.modifier, Version.type, (Version.build == -1 ? "custom build" : "build " + Version.build), Version.revision == 0 ? "" : "." + Version.revision)) .visible(() -> state.is(State.menu))); } @@ -56,19 +57,18 @@ public class MenuFragment extends Fragment{ container.defaults().size(size).pad(5).padTop(4f); MobileButton - play = new MobileButton("icon-play-2", isize, "$play", this::showPlaySelect), + play = new MobileButton("icon-play-2", isize, "$play", ui.deploy::show), maps = new MobileButton("icon-map", isize, "$maps", ui.maps::show), - load = new MobileButton("icon-load", isize, "$load", ui.load::show), + custom = new MobileButton("icon-play-custom", isize, "$customgame", this::showCustomSelect), join = new MobileButton("icon-add", isize, "$joingame", ui.join::show), editor = new MobileButton("icon-editor", isize, "$editor", () -> ui.loadAnd(ui.editor::show)), tools = new MobileButton("icon-tools", isize, "$settings", ui.settings::show), - unlocks = new MobileButton("icon-unlocks", isize, "database", ui.database::show), donate = new MobileButton("icon-donate", isize, "$donate", Platform.instance::openDonations); if(Core.graphics.getWidth() > Core.graphics.getHeight()){ container.add(play); container.add(join); - container.add(load); + container.add(custom); container.add(maps); container.row(); @@ -77,7 +77,6 @@ public class MenuFragment extends Fragment{ table.add(editor); table.add(tools); - table.add(unlocks); if(Platform.instance.canDonate()) table.add(donate); }).colspan(4); @@ -85,7 +84,7 @@ public class MenuFragment extends Fragment{ container.add(play); container.add(maps); container.row(); - container.add(load); + container.add(custom); container.add(join); container.row(); container.add(editor); @@ -95,8 +94,6 @@ public class MenuFragment extends Fragment{ container.table(table -> { table.defaults().set(container.defaults()); - table.add(unlocks); - if(Platform.instance.canDonate()) table.add(donate); }).colspan(2); } @@ -111,7 +108,13 @@ public class MenuFragment extends Fragment{ out.margin(16); out.defaults().size(w, 66f).padTop(5).padRight(5); - out.add(new MenuButton("icon-play-2", "$play", MenuFragment.this::showPlaySelect)).width(bw).colspan(2); + out.add(new MenuButton("icon-play-2", "$play", ui.deploy::show)).width(bw).colspan(2); + + out.row(); + + out.add(new MenuButton("icon-add", "$joingame", ui.join::show)); + + out.add(new MenuButton("icon-play-custom", "$customgame", this::showCustomSelect)); out.row(); @@ -131,40 +134,20 @@ public class MenuFragment extends Fragment{ }); } - private void showPlaySelect(){ - ui.deploy.show(); - - /* - float w = 220f; - float bw = w * 2f + 10f; - + private void showCustomSelect(){ FloatingDialog dialog = new FloatingDialog("$play"); + dialog.setFillParent(false); dialog.addCloseButton(); - dialog.cont.defaults().height(66f).width(w).padRight(5f); - - dialog.cont.add(new MenuButton("icon-play-2", "$map.random", () -> { - dialog.hide(); - world.generator.playRandomMap(); - })).width(bw).colspan(2); - dialog.cont.row(); - - dialog.cont.add(new MenuButton("icon-add", "$joingame", () -> { - ui.join.show(); + dialog.cont.defaults().size(230f, 64f); + dialog.cont.add(new MenuButton("icon-editor", "$newgame", () -> { dialog.hide(); + ui.custom.show(); })); - - dialog.cont.add(new MenuButton("icon-editor", "$customgame", () -> { - dialog.hide(); - ui.levels.show(); - })); - dialog.cont.row(); - dialog.cont.add(new MenuButton("icon-load", "$loadgame", () -> { ui.load.show(); dialog.hide(); - })).width(bw).colspan(2); - - dialog.show();*/ + })); + dialog.show(); } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java index 32a3fa7ecb..b4c93d4195 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java @@ -5,22 +5,23 @@ import io.anuke.arc.Events; import io.anuke.arc.collection.Array; import io.anuke.arc.graphics.Color; import io.anuke.arc.input.KeyCode; -import io.anuke.arc.math.Interpolation; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.scene.Group; -import io.anuke.arc.scene.actions.Actions; import io.anuke.arc.scene.event.Touchable; +import io.anuke.arc.scene.style.TextureRegionDrawable; import io.anuke.arc.scene.ui.ButtonGroup; import io.anuke.arc.scene.ui.Image; import io.anuke.arc.scene.ui.ImageButton; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.game.EventType.UnlockEvent; import io.anuke.mindustry.game.EventType.WorldLoadEvent; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.type.Category; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; @@ -33,12 +34,13 @@ public class PlacementFragment extends Fragment{ final int rowWidth = 4; Array returnArray = new Array<>(); + Array returnCatArray = new Array<>(); + boolean[] categoryEmpty = new boolean[Category.values().length]; Category currentCategory = Category.distribution; Block hovered, lastDisplay; Tile lastHover; Tile hoverTile; Table blockTable, toggler, topTable; - boolean shown = true; boolean lastGround; //TODO make this configurable @@ -56,14 +58,41 @@ public class PlacementFragment extends Fragment{ public PlacementFragment(){ Events.on(WorldLoadEvent.class, event -> { - currentCategory = Category.turret; - Group group = toggler.getParent(); - toggler.remove(); - build(group); + control.input(0).block = null; + rebuild(); + }); + + Events.on(UnlockEvent.class, event -> { + if(event.content instanceof Block){ + rebuild(); + } }); } + void rebuild(){ + currentCategory = Category.turret; + Group group = toggler.getParent(); + int index = toggler.getZIndex(); + toggler.remove(); + build(group); + toggler.setZIndex(index); + } + boolean gridUpdate(InputHandler input){ + if(Core.input.keyDown(Binding.pick)){ //mouse eyedropper select + Tile tile = world.tileWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y); + + if(tile != null){ + tile = tile.target(); + Block tryRecipe = tile.block(); + if(tryRecipe.isVisible() && unlocked(tryRecipe)){ + input.block = tryRecipe; + currentCategory = input.block.buildCategory; + return true; + } + } + } + if(!Core.input.keyDown(Binding.gridMode) || ui.chatfrag.chatOpen()) return false; if(Core.input.keyDown(Binding.gridModeShift)){ //select category int i = 0; @@ -75,24 +104,12 @@ public class PlacementFragment extends Fragment{ i++; } return true; - }else if(Core.input.keyDown(Binding.select)){ //mouse eyedropper select - Tile tile = world.tileWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y); - - if(tile != null){ - tile = tile.target(); - Block tryRecipe = tile.block(); - if(tryRecipe.isVisible() && data.isUnlocked(tryRecipe)){ - input.block = tryRecipe; - currentCategory = input.block.buildCategory; - return true; - } - } }else{ //select block int i = 0; Array recipes = getByCategory(currentCategory); for(KeyCode key : inputGrid){ if(Core.input.keyDown(key)) - input.block = (i < recipes.size && data.isUnlocked(recipes.get(i))) ? recipes.get(i) : null; + input.block = (i < recipes.size && unlocked(recipes.get(i))) ? recipes.get(i) : null; i++; } } @@ -103,7 +120,7 @@ public class PlacementFragment extends Fragment{ public void build(Group parent){ parent.fill(full -> { toggler = full; - full.bottom().right().visible(() -> !state.is(State.menu)); + full.bottom().right().visible(() -> !state.is(State.menu) && ui.hudfrag.shown()); full.table(frame -> { InputHandler input = control.input(0); @@ -119,34 +136,28 @@ public class PlacementFragment extends Fragment{ group.setMinCheckCount(0); for(Block block : getByCategory(currentCategory)){ - if(index++ % rowWidth == 0){ blockTable.row(); } - boolean[] unlocked = {false}; + if(!unlocked(block)){ + blockTable.add().size(46); + continue; + } ImageButton button = blockTable.addImageButton("icon-locked", "select", 8 * 4, () -> { - if(data.isUnlocked(block)){ + if(unlocked(block)){ input.block = input.block == block ? null : block; } }).size(46f).group(group).get(); + button.getStyle().imageUp = new TextureRegionDrawable(block.icon(Icon.medium)); + button.update(() -> { //color unplacable things gray - boolean ulock = data.isUnlocked(block); TileEntity core = players[0].getClosestCore(); - Color color = core != null && (core.items.has(block.buildRequirements) || state.rules.infiniteResources) ? Color.WHITE : ulock ? Color.GRAY : Color.WHITE; + Color color = core != null && (core.items.has(block.buildRequirements) || state.rules.infiniteResources) ? Color.WHITE : Color.GRAY; button.forEach(elem -> elem.setColor(color)); button.setChecked(input.block == block); - - if(ulock == unlocked[0]) return; - unlocked[0] = ulock; - - if(!ulock){ - button.replaceImage(new Image("icon-locked")); - }else{ - button.replaceImage(new Image(block.icon(Icon.medium))); - } }); button.hovered(() -> hovered = block); @@ -165,7 +176,7 @@ public class PlacementFragment extends Fragment{ top.add(new Table()).growX().update(topTable -> { //don't refresh unnecessarily if((tileDisplayBlock() == null && lastDisplay == getSelected() && !lastGround) - || (tileDisplayBlock() != null && lastHover == hoverTile && lastGround)) + || (tileDisplayBlock() != null && lastHover == hoverTile && lastDisplay == tileDisplayBlock() && lastGround)) return; topTable.clear(); @@ -181,10 +192,10 @@ public class PlacementFragment extends Fragment{ topTable.table(header -> { header.left(); header.add(new Image(lastDisplay.icon(Icon.medium))).size(8 * 4); - header.labelWrap(() -> !data.isUnlocked(lastDisplay) ? Core.bundle.get("blocks.unknown") : lastDisplay.formalName) + header.labelWrap(() -> !unlocked(lastDisplay) ? Core.bundle.get("blocks.unknown") : lastDisplay.localizedName) .left().width(190f).padLeft(5); header.add().growX(); - if(data.isUnlocked(lastDisplay)){ + if(unlocked(lastDisplay)){ header.addButton("?", "clear-partial", () -> ui.content.show(lastDisplay)) .size(8 * 5).padTop(-5).padRight(-5).right().grow(); } @@ -197,7 +208,7 @@ public class PlacementFragment extends Fragment{ for(ItemStack stack : lastDisplay.buildRequirements){ req.table(line -> { line.left(); - line.addImage(stack.item.region).size(8 * 2); + line.addImage(stack.item.icon(Item.Icon.small)).size(8 * 2); line.add(stack.item.localizedName()).color(Color.LIGHT_GRAY).padLeft(2).left(); line.labelWrap(() -> { TileEntity core = players[0].getClosestCore(); @@ -231,7 +242,7 @@ public class PlacementFragment extends Fragment{ }); }).colspan(3).fillX().visible(() -> getSelected() != null || tileDisplayBlock() != null).touchable(Touchable.enabled); frame.row(); - frame.addImage("blank").color(Palette.accent).colspan(3).height(3).growX(); + frame.addImage("blank").color(Pal.accent).colspan(3).height(3).growX(); frame.row(); frame.table("pane-2", blocksSelect -> { blocksSelect.margin(4).marginTop(0); @@ -244,15 +255,25 @@ public class PlacementFragment extends Fragment{ ButtonGroup group = new ButtonGroup<>(); + //update category empty values for(Category cat : Category.values()){ - if(getByCategory(cat).isEmpty()) continue; + Array blocks = getByCategory(cat); + categoryEmpty[cat.ordinal()] = blocks.isEmpty() || !unlocked(blocks.first()); + } + + int f = 0; + for(Category cat : getCategories()){ + if(f++ % 2 == 0) categories.row(); + + if(categoryEmpty[cat.ordinal()]){ + categories.addImage("flat"); + continue; + } categories.addImageButton("icon-" + cat.name(), "clear-toggle", 16 * 2, () -> { currentCategory = cat; rebuildCategory.run(); }).group(group).update(i -> i.setChecked(currentCategory == cat)); - - if(cat.ordinal() % 2 == 1) categories.row(); } }).touchable(Touchable.enabled); @@ -263,6 +284,13 @@ public class PlacementFragment extends Fragment{ }); }); } + + Array getCategories(){ + returnCatArray.clear(); + returnCatArray.addAll(Category.values()); + returnCatArray.sort((c1, c2) -> Boolean.compare(categoryEmpty[c1.ordinal()], categoryEmpty[c2.ordinal()])); + return returnCatArray; + } Array getByCategory(Category cat){ returnArray.clear(); @@ -271,9 +299,14 @@ public class PlacementFragment extends Fragment{ returnArray.add(block); } } + returnArray.sort((b1, b2) -> -Boolean.compare(unlocked(b1), unlocked(b2))); return returnArray; } + boolean unlocked(Block block){ + return !world.isZone() || data.isUnlocked(block); + } + /** Returns the currently displayed block in the top box. */ Block getSelected(){ Block toDisplay = null; @@ -309,16 +342,4 @@ public class PlacementFragment extends Fragment{ Block tileDisplayBlock(){ return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.floor() instanceof OreBlock ? hoverTile.floor() : null; } - - /** Show or hide the placement menu. */ - void toggle(float t, Interpolation ip){ - toggler.clearActions(); - if(shown){ - shown = false; - toggler.actions(Actions.translateBy(toggler.getTranslation().x + toggler.getWidth(), 0, t, ip)); - }else{ - shown = true; - toggler.actions(Actions.translateBy(-toggler.getTranslation().x, 0, t, ip)); - } - } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java index bea91a8001..dbad24b6a6 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java @@ -11,7 +11,7 @@ import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.util.Interval; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetConnection; import io.anuke.mindustry.net.Packets.AdminAction; @@ -82,7 +82,7 @@ public class PlayerListFragment extends Fragment{ @Override public void draw(){ super.draw(); - Draw.color(Palette.accent); + Draw.color(Pal.accent); Draw.alpha(parentAlpha); Lines.stroke(Unit.dp.scl(3f)); Lines.rect(x, y, width, height); @@ -136,7 +136,7 @@ public class PlayerListFragment extends Fragment{ content.add(button).padBottom(-6).width(350f).maxHeight(h + 14); content.row(); - content.addImage("blank").height(3f).color(state.rules.pvp ? player.getTeam().color : Palette.accent).growX(); + content.addImage("blank").height(3f).color(state.rules.pvp ? player.getTeam().color : Pal.accent).growX(); content.row(); }); diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index e84613a38a..39f013d854 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -5,32 +5,32 @@ import io.anuke.arc.Graphics.Cursor; import io.anuke.arc.Graphics.Cursor.SystemCursor; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.EnumSet; -import io.anuke.arc.collection.IntArray; import io.anuke.arc.function.BooleanProvider; +import io.anuke.arc.function.Function; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; +import io.anuke.arc.graphics.g2d.TextureAtlas.AtlasRegion; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Time; import io.anuke.mindustry.entities.Damage; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.effect.Puddle; import io.anuke.mindustry.entities.effect.RubbleDecal; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.graphics.CacheLayer; import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.type.Category; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.ui.ContentDisplay; +import io.anuke.mindustry.world.consumers.Consume; +import io.anuke.mindustry.world.consumers.ConsumeLiquid; import io.anuke.mindustry.world.consumers.ConsumePower; import io.anuke.mindustry.world.meta.BlockFlag; import io.anuke.mindustry.world.meta.BlockGroup; @@ -42,12 +42,6 @@ import java.util.Arrays; import static io.anuke.mindustry.Vars.*; public class Block extends BlockStorage{ - /** internal name */ - public final String name; - /** display name */ - public String formalName; - /** Detailed description of the block. Can be as long as necesary. */ - public final String fullDescription; /** whether this block has a tile entity that updates */ public boolean update; /** whether this block has health and can be destroyed */ @@ -76,6 +70,8 @@ public class Block extends BlockStorage{ public int timers = 0; /** Cache layer. Only used for 'cached' rendering. */ public CacheLayer cacheLayer = CacheLayer.normal; + /**Special flag; if false, floor will be drawn under this block even if it is cached.*/ + public boolean fillsTile = true; /** Layer to draw extra stuff on. */ public Layer layer = null; /** Extra layer to draw extra extra stuff on. */ @@ -87,17 +83,20 @@ public class Block extends BlockStorage{ /** The block group. Unless {@link #canReplace} is overriden, blocks in the same group can replace each other. */ public BlockGroup group = BlockGroup.none; /** List of block flags. Used for AI indexing. */ - public EnumSet flags; + public EnumSet flags = EnumSet.of(); /** Whether the block can be tapped and selected to configure. */ public boolean configurable; /** Whether this block consumes touchDown events when tapped. */ public boolean consumesTap; - /** The color of this block when displayed on the minimap or map preview. */ - public Color minimapColor = Color.CLEAR; + /** The color of this block when displayed on the minimap or map preview. + * Do not set manually! This is overriden when loading for most blocks.*/ + public Color color = new Color(0, 0, 0, 1); /**Whether units target this block.*/ public boolean targetable = true; /**Whether the overdrive core has any effect on this block.*/ public boolean canOverdrive = true; + /**Whether the icon region has an outline added.*/ + public boolean outlineIcon = false; /**Cost of constructing this block.*/ public ItemStack[] buildRequirements = new ItemStack[]{}; @@ -112,12 +111,12 @@ public class Block extends BlockStorage{ protected Array tempTiles = new Array<>(); protected TextureRegion[] icons = new TextureRegion[Icon.values().length]; protected TextureRegion[] generatedIcons; - protected TextureRegion region; + protected TextureRegion[] variantRegions, editorVariantRegions; + protected TextureRegion region, editorIcon; public Block(String name){ - this.name = name; - this.formalName = Core.bundle.get("block." + name + ".name", name); - this.fullDescription = Core.bundle.getOrNull("block." + name + ".description"); + super(name); + this.description = Core.bundle.getOrNull("block." + name + ".description"); this.solid = false; } @@ -157,6 +156,8 @@ public class Block extends BlockStorage{ public Array getPowerConnections(Tile tile, Array out){ out.clear(); + if(tile == null || tile.entity == null || tile.entity.power == null) return out; + for(Tile other : tile.entity.proximity()){ if(other.entity.power != null && !(consumesPower && other.block().consumesPower && !outputsPower && !other.block().outputsPower) && !tile.entity.power.links.contains(other.pos())){ @@ -209,6 +210,12 @@ public class Block extends BlockStorage{ draw(tile); } + public void drawTeam(Tile tile){ + Draw.color(tile.getTeam().color); + Draw.rect("block-border", tile.drawx() - size * tilesize/2f + 4, tile.drawy() - size * tilesize/2f + 4); + Draw.color(); + } + /** Called after the block is placed by this client. */ public void playerPlaced(Tile tile){ } @@ -224,6 +231,11 @@ public class Block extends BlockStorage{ public void unitOn(Tile tile, Unit unit){ } + /** Called when a unit that spawned at this tile is removed.*/ + public void unitRemoved(Tile tile, Unit unit){ + + } + /** Returns whether ot not this block can be place on the specified tile. */ public boolean canPlaceOn(Tile tile){ return true; @@ -238,7 +250,7 @@ public class Block extends BlockStorage{ @Override public String localizedName(){ - return formalName; + return localizedName; } @Override @@ -256,11 +268,6 @@ public class Block extends BlockStorage{ return ContentType.block; } - @Override - public String getContentName() { - return name; - } - /** Called after all blocks are created. */ @Override public void init(){ @@ -275,6 +282,7 @@ public class Block extends BlockStorage{ } setStats(); + setBars(); consumes.checkRequired(this); } @@ -284,19 +292,6 @@ public class Block extends BlockStorage{ region = Core.atlas.find(name); } - /**Called when the world is resized. - * Call super!*/ - public void transformLinks(Tile tile, int oldWidth, int oldHeight, int newWidth, int newHeight, int shiftX, int shiftY){ - if(tile.entity != null && tile.entity.power != null){ - IntArray links = tile.entity.power.links; - IntArray out = new IntArray(); - for(int i = 0; i < links.size; i++){ - out.add(world.transform(links.get(i), oldWidth, oldHeight, newWidth, shiftX, shiftY)); - } - tile.entity.power.links = out; - } - } - /** Called when the block is tapped. */ public void tapped(Tile tile, Player player){ @@ -337,7 +332,7 @@ public class Block extends BlockStorage{ } public void drawConfigure(Tile tile){ - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.stroke(1f); Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f + 1f); Draw.reset(); @@ -354,6 +349,29 @@ public class Block extends BlockStorage{ if(hasItems) stats.add(BlockStat.itemCapacity, itemCapacity, StatUnit.items); } + public void setBars(){ + bars.add("health", entity -> new Bar("blocks.health", Pal.health, entity::healthf).blink(Color.WHITE)); + + if(hasLiquids){ + Function current; + if(consumes.has(ConsumeLiquid.class)){ + Liquid liquid = consumes.liquid(); + current = entity -> liquid; + }else{ + current = entity -> entity.liquids.current(); + } + bars.add("liquid", entity -> new Bar(() -> entity.liquids.get(current.get(entity)) <= 0.001f ? Core.bundle.get("blocks.liquid") : current.get(entity).localizedName(), () -> current.get(entity).color, () -> entity.liquids.get(current.get(entity)) / liquidCapacity)); + } + + if(hasPower && consumes.has(ConsumePower.class)){ + boolean buffered = consumes.get(ConsumePower.class).isBuffered; + float capacity = consumes.get(ConsumePower.class).powerCapacity; + + bars.add("power", entity -> new Bar(() -> buffered ? Core.bundle.format("blocks.powerbalance", Float.isNaN(entity.power.satisfaction * capacity) ? "" : (int)(entity.power.satisfaction * capacity)) : + Core.bundle.get("blocks.power"), () -> Pal.powerBar, () -> entity.power.satisfaction)); + } + } + public boolean isSolidFor(Tile tile){ return false; } @@ -390,11 +408,10 @@ public class Block extends BlockStorage{ float power = 0f; if(hasItems){ - float scaling = inventoryScaling(tile); for(Item item : content.items()){ int amount = tile.entity.items.get(item); - explosiveness += item.explosiveness * amount * scaling; - flammability += item.flammability * amount * scaling; + explosiveness += item.explosiveness * amount; + flammability += item.flammability * amount; } } @@ -423,17 +440,12 @@ public class Block extends BlockStorage{ }); } - Damage.dynamicExplosion(x, y, flammability, explosiveness, power, tilesize * size / 2f, Palette.darkFlame); + Damage.dynamicExplosion(x, y, flammability, explosiveness, power, tilesize * size / 2f, Pal.darkFlame); if(!tile.floor().solid && !tile.floor().isLiquid){ RubbleDecal.create(tile.drawx(), tile.drawy(), size); } } - /**Returns scaled # of inventories in this block.*/ - public float inventoryScaling(Tile tile){ - return 1f; - } - /** * Returns the flammability of the tile. Used for fire calculations. * Takes flammability of floor liquid into account. @@ -456,7 +468,7 @@ public class Block extends BlockStorage{ } public String getDisplayName(Tile tile){ - return formalName; + return localizedName; } public TextureRegion getDisplayIcon(Tile tile){ @@ -472,30 +484,55 @@ public class Block extends BlockStorage{ displayBars(tile, bars); }).growX(); + table.row(); + table.table(ctable -> { + displayConsumption(tile, ctable); + }).growX(); table.marginBottom(-5); } } - public void displayBars(Tile tile, Table bars){ - TileEntity entity = tile.entity; + public void displayConsumption(Tile tile, Table table){ + table.left(); + for(Consume cons : consumes.all()){ + cons.build(tile, table); + } + } - bars.add(new Bar("blocks.health", Palette.health, entity::healthf).blink(Color.WHITE)); - bars.row(); - - if(entity.liquids != null){ - bars.add(new Bar(() -> entity.liquids.current().localizedName(), () -> entity.liquids.current().color, () -> entity.liquids.total() / liquidCapacity)).growX(); - bars.row(); + public void displayBars(Tile tile, Table table){ + for(Function bar : bars.list()){ + table.add(bar.get(tile.entity)).growX(); + table.row(); } } public TextureRegion icon(Icon icon){ if(icons[icon.ordinal()] == null){ - icons[icon.ordinal()] = Core.atlas.find(name + "-icon-" + icon.name()); + icons[icon.ordinal()] = Core.atlas.find(name + "-icon-" + icon.name(), icon == Icon.full ? getGeneratedIcons()[0] : Core.atlas.find(name + "-icon-full", getGeneratedIcons()[0])); } return icons[icon.ordinal()]; } + /**Never use outside of the editor!*/ + public TextureRegion editorIcon(){ + if(editorIcon == null) editorIcon = Core.atlas.find(name + "-icon-editor"); + return editorIcon; + } + + /**Never use outside of the editor!*/ + public TextureRegion[] editorVariantRegions(){ + if(editorVariantRegions == null){ + variantRegions(); + editorVariantRegions = new TextureRegion[variantRegions.length]; + for(int i = 0; i < variantRegions.length; i ++){ + AtlasRegion region = (AtlasRegion)variantRegions[i]; + editorVariantRegions[i] = Core.atlas.find("editor-" + region.name); + } + } + return editorVariantRegions; + } + protected TextureRegion[] generateIcons(){ return new TextureRegion[]{Core.atlas.find(name)}; } @@ -507,6 +544,13 @@ public class Block extends BlockStorage{ return generatedIcons; } + public TextureRegion[] variantRegions(){ + if(variantRegions == null){ + variantRegions = new TextureRegion[]{icon(Icon.full)}; + } + return variantRegions; + } + public boolean hasEntity(){ return destructible || update; } @@ -528,6 +572,11 @@ public class Block extends BlockStorage{ return buildVisibility.get() && !isHidden(); } + @Override + public boolean isHidden(){ + return !buildVisibility.get(); + } + @Override public boolean alwaysUnlocked(){ return alwaysUnlocked; diff --git a/core/src/io/anuke/mindustry/world/BlockStorage.java b/core/src/io/anuke/mindustry/world/BlockStorage.java index 573aad8593..6232f22e4a 100644 --- a/core/src/io/anuke/mindustry/world/BlockStorage.java +++ b/core/src/io/anuke/mindustry/world/BlockStorage.java @@ -1,21 +1,24 @@ package io.anuke.mindustry.world; import io.anuke.arc.collection.Array; -import io.anuke.arc.entities.Effects; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.effect.Puddle; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.consumers.ConsumeItem; +import io.anuke.mindustry.world.consumers.ConsumeItems; import io.anuke.mindustry.world.consumers.ConsumeLiquid; import io.anuke.mindustry.world.consumers.Consumers; +import io.anuke.mindustry.world.meta.BlockBars; import io.anuke.mindustry.world.meta.BlockStats; import io.anuke.mindustry.world.meta.Producers; @@ -33,9 +36,14 @@ public abstract class BlockStorage extends UnlockableContent{ public float liquidCapacity = 10f; public float liquidFlowFactor = 4.9f; - public BlockStats stats = new BlockStats(); - public Consumers consumes = new Consumers(); - public Producers produces = new Producers(); + public final BlockStats stats = new BlockStats(); + public final BlockBars bars = new BlockBars(); + public final Consumers consumes = new Consumers(); + public final Producers produces = new Producers(); + + public BlockStorage(String name){ + super(name); + } public boolean shouldConsume(Tile tile){ return true; @@ -60,6 +68,7 @@ public abstract class BlockStorage extends UnlockableContent{ /**Remove a stack from this inventory, and return the amount removed.*/ public int removeStack(Tile tile, Item item, int amount){ + amount = Math.min(amount, tile.entity.items.get(item)); tile.entity.noSleep(); tile.entity.items.remove(item, amount); return amount; @@ -89,6 +98,13 @@ public abstract class BlockStorage extends UnlockableContent{ } public boolean acceptItem(Item item, Tile tile, Tile source){ + if(tile.entity != null && consumes.has(ConsumeItems.class)){ + for(ItemStack stack : consumes.items()){ + if(stack.item == item){ + return tile.entity.items.get(item) < getMaximumAccepted(tile, item); + } + } + } return tile.entity != null && consumes.has(ConsumeItem.class) && consumes.item() == item && tile.entity.items.get(item) < getMaximumAccepted(tile, item); } diff --git a/core/src/io/anuke/mindustry/world/Build.java b/core/src/io/anuke/mindustry/world/Build.java index 1e8a5eac5b..cb7785e980 100644 --- a/core/src/io/anuke/mindustry/world/Build.java +++ b/core/src/io/anuke/mindustry/world/Build.java @@ -25,10 +25,15 @@ public class Build{ } Tile tile = world.tile(x, y); + float prevPercent = 1f; //just in case if(tile == null) return; + if(tile.entity != null){ + prevPercent = tile.entity.health(); + } + tile = tile.target(); Block previous = tile.block(); @@ -38,6 +43,7 @@ public class Build{ tile.setBlock(sub); tile.entity().setDeconstruct(previous); tile.setTeam(team); + tile.entity.health = tile.entity.maxHealth() * prevPercent; if(previous.isMultiblock()){ int offsetx = -(previous.size - 1) / 2; @@ -128,7 +134,7 @@ public class Build{ if(tile == null) return false; if(type.isMultiblock()){ - if(type.canReplace(tile.block()) && tile.block().size == type.size && type.canPlaceOn(tile)){ + if(type.canReplace(tile.block()) && tile.block().size == type.size && type.canPlaceOn(tile) && tile.interactable(team)){ return true; } @@ -154,7 +160,7 @@ public class Build{ } return true; }else{ - return (tile.getTeam() == Team.none || tile.getTeam() == team) + return tile.interactable(team) && contactsGround(tile.x, tile.y, type) && (!tile.floor().isLiquid || type.floating) && tile.floor().placeableOn @@ -190,6 +196,6 @@ public class Build{ Tile tile = world.tile(x, y); if(tile != null) tile = tile.target(); - return tile != null && tile.block().canBreak(tile) && tile.breakable() && (!tile.block().synthetic() || tile.getTeam() == team); + return tile != null && tile.block().canBreak(tile) && tile.breakable() && tile.interactable(team); } } diff --git a/core/src/io/anuke/mindustry/world/ColorMapper.java b/core/src/io/anuke/mindustry/world/ColorMapper.java deleted file mode 100644 index e2319a3c64..0000000000 --- a/core/src/io/anuke/mindustry/world/ColorMapper.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.anuke.mindustry.world; - -import io.anuke.arc.collection.IntMap; -import io.anuke.arc.collection.ObjectIntMap; -import io.anuke.arc.graphics.Color; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.game.Team; - -import static io.anuke.mindustry.Vars.content; - -public class ColorMapper implements ContentList{ - private static IntMap blockMap = new IntMap<>(); - private static ObjectIntMap colorMap = new ObjectIntMap<>(); - private static ThreadLocal tmpColors = new ThreadLocal<>(); - - private static int getBlockColor(Block block){ - return colorMap.get(block, 0); - } - - public static int colorFor(Block floor, Block wall, Team team){ - if(wall.synthetic()){ - return team.intColor; - } - int color = getBlockColor(wall); - if(color == 0) color = ColorMapper.getBlockColor(floor); - return color; - } - - @Override - public void load(){ - for(Block block : content.blocks()){ - int color = Color.rgba8888(block.minimapColor); - if(color == 0) continue; //skip blocks that are not mapped - - blockMap.put(color, block); - colorMap.put(block, color); - } - } -} diff --git a/core/src/io/anuke/mindustry/world/LegacyColorMapper.java b/core/src/io/anuke/mindustry/world/LegacyColorMapper.java index 51950441fa..d60122bb85 100644 --- a/core/src/io/anuke/mindustry/world/LegacyColorMapper.java +++ b/core/src/io/anuke/mindustry/world/LegacyColorMapper.java @@ -18,43 +18,47 @@ public class LegacyColorMapper implements ContentList{ @Override public void load(){ - defaultValue = new LegacyBlock(Blocks.stone, 0); + defaultValue = new LegacyBlock(Blocks.stone, Blocks.air); - map("ff0000", Blocks.dirt, 0); - map("00ff00", Blocks.stone, 0); - map("323232", Blocks.stone, 0); - map("646464", Blocks.stone, 1); - map("50965a", Blocks.grass, 0); - map("5ab464", Blocks.grass, 1); - map("506eb4", Blocks.water, 0); - map("465a96", Blocks.deepwater, 0); - map("252525", Blocks.blackstone, 0); - map("575757", Blocks.blackstone, 1); - map("988a67", Blocks.sand, 0); - map("e5d8bb", Blocks.sand, 1); - map("c2d1d2", Blocks.snow, 0); - map("c4e3e7", Blocks.ice, 0); - map("f7feff", Blocks.snow, 1); - map("6e501e", Blocks.dirt, 0); - map("ed5334", Blocks.blackstone, 0); - map("292929", Blocks.tar, 0); - map("c3a490", OreBlock.get(Blocks.stone, Items.copper), 0); - map("161616", OreBlock.get(Blocks.stone, Items.coal), 0); - map("6277bc", OreBlock.get(Blocks.stone, Items.titanium), 0); - map("83bc58", OreBlock.get(Blocks.stone, Items.thorium), 0); + map("ff0000", Blocks.stone, Blocks.spawn); + map("00ff00", Blocks.stone); + map("323232", Blocks.stone); + map("646464", Blocks.stone, Blocks.rocks); + map("50965a", Blocks.grass); + map("5ab464", Blocks.grass, Blocks.stainedRocks); + map("506eb4", Blocks.water); + map("465a96", Blocks.deepwater); + map("252525", Blocks.ignarock); + map("575757", Blocks.ignarock, Blocks.duneRocks); + map("988a67", Blocks.sand); + map("e5d8bb", Blocks.sand, Blocks.duneRocks); + map("c2d1d2", Blocks.snow); + map("c4e3e7", Blocks.ice); + map("f7feff", Blocks.snow, Blocks.snowrocks); + map("6e501e", Blocks.stainedStoneRed); + map("ed5334", Blocks.stainedStoneRed); + map("292929", Blocks.tar); + map("c3a490", OreBlock.get(Blocks.stone, Items.copper)); + map("161616", OreBlock.get(Blocks.stone, Items.coal)); + map("6277bc", OreBlock.get(Blocks.stone, Items.titanium)); + map("83bc58", OreBlock.get(Blocks.stone, Items.thorium)); } - private void map(String color, Block block, int elevation){ - blockMap.put(Color.rgba8888(Color.valueOf(color)), new LegacyBlock(block, elevation)); + private void map(String color, Block block, Block wall){ + blockMap.put(Color.rgba8888(Color.valueOf(color)), new LegacyBlock(block, wall)); + } + + private void map(String color, Block block){ + blockMap.put(Color.rgba8888(Color.valueOf(color)), new LegacyBlock(block, Blocks.air)); } public static class LegacyBlock{ - public final int elevation; public final Floor floor; + public final Block wall; - public LegacyBlock(Block floor, int elevation){ - this.elevation = elevation; + public LegacyBlock(Block floor, Block wall){ this.floor = (Floor) floor; + this.wall = wall; } } diff --git a/core/src/io/anuke/mindustry/world/Pos.java b/core/src/io/anuke/mindustry/world/Pos.java index bdbf3a2f7c..9a2860ee2a 100644 --- a/core/src/io/anuke/mindustry/world/Pos.java +++ b/core/src/io/anuke/mindustry/world/Pos.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.world; /**Methods for a packed position 'struct', contained in an int.*/ public class Pos{ + public static final int invalid = get(-1, -1); /**Returns packed position from an x/y position. The values must be within short limits.*/ public static int get(int x, int y){ diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 7ce5e6453f..5bc7e46926 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -2,13 +2,14 @@ package io.anuke.mindustry.world; import io.anuke.arc.collection.Array; import io.anuke.arc.function.Consumer; +import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Point2; import io.anuke.arc.math.geom.Position; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Pack; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.traits.TargetTrait; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.blocks.BlockPart; @@ -311,6 +312,10 @@ public class Tile implements Position, TargetTrait{ return null; } + public boolean interactable(Team team){ + return getTeam() == Team.none || team == getTeam(); + } + public void updateOcclusion(){ cost = 1; boolean occluded = false; @@ -326,15 +331,15 @@ public class Tile implements Position, TargetTrait{ } if(occluded){ - cost += 1; + cost += 2; } if(target().synthetic()){ - cost += target().block().health / 10f; + cost += Mathf.clamp(target().block().health / 10f, 0, 20); } if(floor.isLiquid){ - cost += 100f; + cost += 10; } } @@ -356,7 +361,7 @@ public class Tile implements Position, TargetTrait{ if(block.hasEntity()){ entity = block.newEntity().init(this, block.update); - entity.cons = new ConsumeModule(); + entity.cons = new ConsumeModule(entity); if(block.hasItems) entity.items = new ItemModule(); if(block.hasLiquids) entity.liquids = new LiquidModule(); if(block.hasPower){ diff --git a/core/src/io/anuke/mindustry/world/blocks/BlockPart.java b/core/src/io/anuke/mindustry/world/blocks/BlockPart.java index 2e06d62177..50ae9a08db 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BlockPart.java +++ b/core/src/io/anuke/mindustry/world/blocks/BlockPart.java @@ -18,6 +18,11 @@ public class BlockPart extends Block{ hasPower = hasItems = hasLiquids = true; } + @Override + public boolean isHidden(){ + return true; + } + @Override public void draw(Tile tile){ //do nothing diff --git a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java index a6ca205ce3..2eaba1415a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java @@ -6,21 +6,21 @@ import io.anuke.arc.Core; import io.anuke.arc.Events; import io.anuke.arc.Graphics.Cursor; import io.anuke.arc.Graphics.Cursor.SystemCursor; -import io.anuke.arc.entities.Effects; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.effect.RubbleDecal; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.EventType.BlockBuildEndEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.world.Block; @@ -39,7 +39,7 @@ public class BuildBlock extends Block{ super(name); update = true; size = Integer.parseInt(name.charAt(name.length() - 1) + ""); - health = 10; + health = 20; layer = Layer.placement; consumesTap = true; solidifes = true; @@ -70,10 +70,15 @@ public class BuildBlock extends Block{ Core.app.post(() -> Events.fire(new BlockBuildEndEvent(tile, team, false))); } + @Override + public boolean isHidden(){ + return true; + } + @Override public String getDisplayName(Tile tile){ BuildEntity entity = tile.entity(); - return Core.bundle.format("block.constructing", entity.block == null ? entity.previous.formalName : entity.block.formalName); + return Core.bundle.format("block.constructing", entity.block == null ? entity.previous.localizedName : entity.block.localizedName); } @Override @@ -124,7 +129,9 @@ public class BuildBlock extends Block{ if(entity.previous == null) return; - Draw.rect(entity.previous.icon(Icon.full), tile.drawx(), tile.drawy(), entity.previous.rotate ? tile.getRotation() * 90 : 0); + if(Core.atlas.isFound(entity.previous.icon(Icon.full))){ + Draw.rect(entity.previous.icon(Icon.full), tile.drawx(), tile.drawy(), entity.previous.rotate ? tile.getRotation() * 90 : 0); + } } @Override @@ -132,7 +139,7 @@ public class BuildBlock extends Block{ BuildEntity entity = tile.entity(); - Shaders.blockbuild.color = Palette.accent; + Shaders.blockbuild.color = Pal.accent; Block target = entity.block == null ? entity.previous : entity.block; @@ -278,7 +285,7 @@ public class BuildBlock extends Block{ public void setDeconstruct(Block previous){ this.previous = previous; this.progress = 1f; - if(previous.buildCost > 1f){ + if(previous.buildCost >= 0.01f){ this.block = previous; this.accumulator = new float[previous.buildRequirements.length]; this.totalAccumulator = new float[previous.buildRequirements.length]; diff --git a/core/src/io/anuke/mindustry/world/blocks/Floor.java b/core/src/io/anuke/mindustry/world/blocks/Floor.java index 247320b172..2bd9db15ac 100644 --- a/core/src/io/anuke/mindustry/world/blocks/Floor.java +++ b/core/src/io/anuke/mindustry/world/blocks/Floor.java @@ -1,19 +1,23 @@ package io.anuke.mindustry.world.blocks; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects.Effect; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Geometry; +import io.anuke.arc.math.geom.Point2; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.content.StatusEffects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.type.StatusEffect; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; +import static io.anuke.mindustry.Vars.tilesize; + public class Floor extends Block{ /** number of different variant regions to use */ public int variants; @@ -45,9 +49,19 @@ public class Floor extends Block{ public boolean hasOres = false; /** whether this block can be drowned in */ public boolean isLiquid; + /** Heat of this block, 0 at baseline. Used for calculating output of thermal generators.*/ + public float heat = 0f; /** if true, this block cannot be mined by players. useful for annoying things like sand. */ public boolean playerUnmineable = false; - protected TextureRegion[] variantRegions; + /**Style of the edge stencil. Loaded by looking up "edge-stencil-{name}".*/ + public String edgeStyle = "smooth"; + /**Group of blocks that this block does not draw edges on.*/ + public Block blendGroup = this; + /**Effect displayed when randomly updated.*/ + public Effect updateEffect = Fx.none; + + protected TextureRegion[][] edges; + protected byte eq = 0; public Floor(String name){ super(name); @@ -70,9 +84,18 @@ public class Floor extends Block{ variantRegions[0] = Core.atlas.find(name); } + int size = (int)(tilesize / Draw.scl); + if(Core.atlas.has(name + "-edge")){ + edges = Core.atlas.find(name + "-edge").split(size, size); + } region = variantRegions[0]; } + @Override + public TextureRegion[] generateIcons(){ + return new TextureRegion[]{Core.atlas.find(Core.atlas.has(name) ? name : name + "1")}; + } + @Override public void init(){ super.init(); @@ -87,11 +110,77 @@ public class Floor extends Block{ Mathf.random.setSeed(tile.pos()); Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); + + drawEdges(tile); } - @Override - public TextureRegion[] generateIcons(){ - return new TextureRegion[]{Core.atlas.find(Core.atlas.has(name) ? name : name + "1")}; + + public void drawNonLayer(Tile tile){ + Mathf.random.setSeed(tile.pos()); + + drawEdges(tile, true); + } + + protected void drawEdges(Tile tile){ + drawEdges(tile, false); + } + + protected void drawEdges(Tile tile, boolean sameLayer){ + eq = 0; + + for(int i = 0; i < 8; i++){ + Point2 point = Geometry.d8[i]; + Tile other = tile.getNearby(point); + if(other != null && doEdge(other.floor(), sameLayer) && other.floor().edges() != null){ + eq |= (1 << i); + } + } + + for(int i = 0; i < 8; i++){ + if(eq(i)){ + Point2 point = Geometry.d8[i]; + Tile other = tile.getNearby(point); + + TextureRegion region = edge(other.floor(), type(i), 2-(point.x + 1), 2-(point.y + 1)); + Draw.rect(region, tile.worldx(), tile.worldy()); + } + } + } + + protected TextureRegion[][] edges(){ + return ((Floor)blendGroup).edges; + } + + protected boolean doEdge(Floor other, boolean sameLayer){ + return (other.blendGroup.id > blendGroup.id || edges() == null) && other.edgeOnto(this) && (other.cacheLayer.ordinal() > this.cacheLayer.ordinal() || !sameLayer); + } + + protected boolean edgeOnto(Floor other){ + return true; + } + + int type(int i){ + if(!eq(i - 1) && !eq(i + 1)){ + //case 0: touching + return 0; + }else if(eq(i - 1) && eq(i - 2) && eq(i + 1) && eq(i + 2)){ + //case 2: surrounded + return 2; + }else if(eq(i - 1) && eq(i + 1)){ + //case 1: flat + return 1; + }else{ + //case 0 is rounded, so it's the safest choice, should work for most possibilities + return 0; + } + } + + boolean eq(int i){ + return (eq & (1 << Mathf.mod(i, 8))) != 0; + } + + TextureRegion edge(Floor block, int type, int x, int y){ + return block.edges()[x + type*3][2-y]; } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/world/blocks/OreBlock.java b/core/src/io/anuke/mindustry/world/blocks/OreBlock.java index 3d64d8509a..5ddcdde94e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/OreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/OreBlock.java @@ -8,22 +8,28 @@ import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; public class OreBlock extends Floor{ - private static final ObjectMap> oreBlockMap = new ObjectMap<>(); + private static final ObjectMap> oreBlockMap = new ObjectMap<>(); public Floor base; public OreBlock(Item ore, Floor base){ super("ore-" + ore.name + "-" + base.name); - this.formalName = ore.localizedName() + " " + base.formalName; + this.localizedName = ore.localizedName() + " " + base.localizedName; this.itemDrop = ore; this.base = base; this.variants = 3; - this.minimapColor = ore.color; this.edge = base.name; + this.blendGroup = base.blendGroup; + this.color.set(ore.color); oreBlockMap.getOr(ore, ObjectMap::new).put(base, this); } + @Override + public void init(){ + super.init(); + } + @Override public String getDisplayName(Tile tile){ return itemDrop.localizedName(); @@ -32,11 +38,22 @@ public class OreBlock extends Floor{ @Override public void draw(Tile tile){ Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); + + drawEdges(tile); } - public static Block get(Block floor, Item item){ - if(!oreBlockMap.containsKey(item)) throw new IllegalArgumentException("Item '" + item + "' is not an ore!"); - if(!oreBlockMap.get(item).containsKey(floor)) throw new IllegalArgumentException("Block '" + floor.name + "' does not support ores!"); + @Override + public boolean doEdge(Floor floor, boolean f){ + return floor != base && super.doEdge(floor, f); + } + + @Override + protected boolean edgeOnto(Floor other){ + return other != base; + } + + public static Floor get(Block floor, Item item){ + if(!oreBlockMap.containsKey(item) || !oreBlockMap.get(item).containsKey(floor)) return null; return oreBlockMap.get(item).get(floor); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/Rock.java b/core/src/io/anuke/mindustry/world/blocks/Rock.java index 65c68a2c27..7f10510e96 100644 --- a/core/src/io/anuke/mindustry/world/blocks/Rock.java +++ b/core/src/io/anuke/mindustry/world/blocks/Rock.java @@ -8,7 +8,6 @@ import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.math.Mathf; public class Rock extends Block{ - protected TextureRegion[] shadowRegions, regions; protected int variants; public Rock(String name){ @@ -19,18 +18,16 @@ public class Rock extends Block{ @Override public void draw(Tile tile){ - Draw.colorl(1f - tile.getRotation() / 4f); if(variants > 0){ - Draw.rect(regions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, regions.length - 1))], tile.worldx(), tile.worldy()); + Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); }else{ Draw.rect(region, tile.worldx(), tile.worldy()); } - Draw.color(); } @Override public TextureRegion[] generateIcons(){ - return new TextureRegion[]{Core.atlas.find(name + "1")}; + return variants == 0 ? super.generateIcons() : new TextureRegion[]{Core.atlas.find(name + "1")}; } @Override @@ -38,12 +35,10 @@ public class Rock extends Block{ super.load(); if(variants > 0){ - shadowRegions = new TextureRegion[variants]; - regions = new TextureRegion[variants]; + variantRegions = new TextureRegion[variants]; for(int i = 0; i < variants; i++){ - shadowRegions[i] = Core.atlas.find(name + "shadow" + (i + 1)); - regions[i] = Core.atlas.find(name + (i + 1)); + variantRegions[i] = Core.atlas.find(name + (i + 1)); } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/SelectionTrait.java b/core/src/io/anuke/mindustry/world/blocks/SelectionTrait.java index 22dbf4c293..ef6d0d5c7c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/SelectionTrait.java +++ b/core/src/io/anuke/mindustry/world/blocks/SelectionTrait.java @@ -8,6 +8,7 @@ import io.anuke.arc.scene.style.TextureRegionDrawable; import io.anuke.arc.scene.ui.ButtonGroup; import io.anuke.arc.scene.ui.ImageButton; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.type.Item.Icon; import static io.anuke.mindustry.Vars.*; @@ -25,11 +26,11 @@ public interface SelectionTrait{ int i = 0; for(Item item : items){ - if(!data.isUnlocked(item)) continue; + if(!data.isUnlocked(item) && world.isZone()) continue; - ImageButton button = cont.addImageButton("white", "clear-toggle", 24, () -> {}).group(group).get(); + ImageButton button = cont.addImageButton("white", "clear-toggle", 24, () -> control.input(0).frag.config.hideConfig()).group(group).get(); button.changed(() -> consumer.accept(button.isChecked() ? item : null)); - button.getStyle().imageUp = new TextureRegionDrawable(item.region); + button.getStyle().imageUp = new TextureRegionDrawable(item.icon(Icon.medium)); button.update(() -> button.setChecked(holder.get() == item)); if(i++ % 4 == 3){ diff --git a/core/src/io/anuke/mindustry/world/blocks/StaticWall.java b/core/src/io/anuke/mindustry/world/blocks/StaticWall.java index df881c880b..cc2d73ce0b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/StaticWall.java +++ b/core/src/io/anuke/mindustry/world/blocks/StaticWall.java @@ -1,8 +1,18 @@ package io.anuke.mindustry.world.blocks; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.math.Mathf; import io.anuke.mindustry.graphics.CacheLayer; +import io.anuke.mindustry.world.Pos; +import io.anuke.mindustry.world.Tile; + +import static io.anuke.mindustry.Vars.tilesize; +import static io.anuke.mindustry.Vars.world; public class StaticWall extends Rock{ + TextureRegion large; public StaticWall(String name){ super(name); @@ -10,4 +20,42 @@ public class StaticWall extends Rock{ solid = true; cacheLayer = CacheLayer.walls; } + + @Override + public void draw(Tile tile){ + int rx = tile.x / 2 * 2; + int ry = tile.y / 2 * 2; + + if(Core.atlas.isFound(large) && eq(rx, ry) && Mathf.randomSeed(Pos.get(rx, ry)) < 0.5){ + if(rx == tile.x && ry == tile.y){ + Draw.rect(large, tile.worldx() + tilesize/2f, tile.worldy() + tilesize/2f); + } + }else if(variants > 0){ + Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); + }else{ + Draw.rect(region, tile.worldx(), tile.worldy()); + } + } + + @Override + public void load(){ + super.load(); + large = Core.atlas.find(name + "-large"); + } + + //two functions for calculating 2x2 tile brightness + int min(int rx, int ry){ + return Math.min(world.tile(rx + 1, ry).getRotation(), Math.min(world.tile(rx, ry).getRotation(), Math.min(world.tile(rx + 1, ry + 1).getRotation(), world.tile(rx, ry + 1).getRotation()))); + } + + int avg(int rx, int ry){ + return (world.tile(rx + 1, ry).getRotation() + world.tile(rx, ry).getRotation() + world.tile(rx + 1, ry + 1).getRotation() + world.tile(rx, ry + 1).getRotation()) / 4; + } + + boolean eq(int rx, int ry){ + return world.tile(rx + 1, ry).block() == this + && world.tile(rx, ry + 1).block() == this + && world.tile(rx, ry).block() == this + && world.tile(rx + 1, ry + 1).block() == this; + } } diff --git a/core/src/io/anuke/mindustry/world/blocks/TreeBlock.java b/core/src/io/anuke/mindustry/world/blocks/TreeBlock.java new file mode 100644 index 0000000000..60534c8be0 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/TreeBlock.java @@ -0,0 +1,32 @@ +package io.anuke.mindustry.world.blocks; + +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.math.Mathf; +import io.anuke.mindustry.graphics.Layer; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; + +public class TreeBlock extends Block{ + static final float shadowOffset = 10f; + + public TreeBlock(String name){ + super(name); + solid = true; + layer = Layer.power; + expanded = true; + } + + @Override + public void draw(Tile tile){} + + @Override + public void drawShadow(Tile tile){ + Draw.rect(region, tile.drawx(), tile.drawy(), Mathf.randomSeed(tile.pos(), 0, 4) * 90); + Draw.rect(region, tile.drawx() - shadowOffset, tile.drawy() - shadowOffset, Mathf.randomSeed(tile.pos(), 0, 4) * 90); + } + + @Override + public void drawLayer(Tile tile){ + Draw.rect(region, tile.drawx(), tile.drawy(), Mathf.randomSeed(tile.pos(), 0, 4) * 90); + } +} diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/DeflectorWall.java b/core/src/io/anuke/mindustry/world/blocks/defense/DeflectorWall.java index 08392d7d32..5d9b9080b9 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/DeflectorWall.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/DeflectorWall.java @@ -8,7 +8,7 @@ import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.Tile; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/Door.java b/core/src/io/anuke/mindustry/world/blocks/defense/Door.java index a85545453c..d4c6fd75cc 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/Door.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/Door.java @@ -3,14 +3,14 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.Core; import io.anuke.arc.Graphics.Cursor; import io.anuke.arc.Graphics.Cursor.SystemCursor; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.geom.Rectangle; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.world.Tile; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java index 5eaa7b6c42..55ecd34d38 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.EntityGroup; -import io.anuke.arc.entities.EntityQuery; -import io.anuke.arc.entities.impl.BaseEntity; -import io.anuke.arc.entities.trait.DrawTrait; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.EntityQuery; +import io.anuke.mindustry.entities.impl.BaseEntity; +import io.anuke.mindustry.entities.traits.DrawTrait; import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; @@ -14,9 +14,9 @@ import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.traits.AbsorbTrait; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; @@ -54,7 +54,7 @@ public class ForceProjector extends Block { canOverdrive = false; hasLiquids = true; hasItems = true; - consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.1f)).optional(true).update(false); + consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.1f)).optional(true).boost(true).update(false); consumePower = new ConsumeForceProjectorPower(60f, 60f); consumes.add(consumePower); } @@ -243,7 +243,7 @@ public class ForceProjector extends Block { @Override public void draw(){ - Draw.color(Palette.accent); + Draw.color(Pal.accent); Fill.poly(x, y, 6, realRadius(entity)); Draw.color(); } @@ -265,7 +265,7 @@ public class ForceProjector extends Block { public class ConsumeForceProjectorPower extends ConsumePower{ public ConsumeForceProjectorPower(float powerCapacity, float ticksToFill){ - super(powerCapacity / ticksToFill, 0.0f, powerCapacity, true); + super(powerCapacity / ticksToFill, powerCapacity, true); } @Override public boolean valid(Block block, TileEntity entity){ diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java index 5877a7b20d..1419f6fd30 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.Core; import io.anuke.arc.collection.IntSet; -import io.anuke.arc.entities.Effects; +import io.anuke.mindustry.entities.Effects; import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; @@ -12,7 +12,7 @@ import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -66,8 +66,6 @@ public class MendProjector extends Block{ if(entity.charge >= reload){ float realRange = range + entity.phaseHeat * phaseRangeBoost; - - Effects.effect(Fx.healWaveMend, Tmp.c1.set(color).lerp(phase, entity.phaseHeat), tile.drawx(), tile.drawy(), realRange); entity.charge = 0f; int tileRange = (int)(realRange / tilesize); diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java index 6e2c303417..e8ce6425a9 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java @@ -2,7 +2,6 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.Core; import io.anuke.arc.collection.IntSet; -import io.anuke.arc.entities.Effects; import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; @@ -10,9 +9,7 @@ import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; -import io.anuke.arc.util.Tmp; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -31,7 +28,7 @@ public class OverdriveProjector extends Block{ protected int timerUse = timers ++; protected TextureRegion topRegion; - protected float reload = 260f; + protected float reload = 60f; protected float range = 80f; protected float speedBoost = 1.5f; protected float speedBoostPhase = 0.75f; @@ -69,7 +66,6 @@ public class OverdriveProjector extends Block{ float realRange = range + entity.phaseHeat * phaseRangeBoost; float realBoost = (speedBoost + entity.phaseHeat*speedBoostPhase) * entity.power.satisfaction; - Effects.effect(Fx.overdriveWave, Tmp.c1.set(color).lerp(phase, entity.phaseHeat), tile.drawx(), tile.drawy(), realRange); entity.charge = 0f; int tileRange = (int)(realRange / tilesize); @@ -87,8 +83,7 @@ public class OverdriveProjector extends Block{ if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.pos()) && other.entity != null){ other.entity.timeScaleDuration = Math.max(other.entity.timeScaleDuration, reload + 1f); other.entity.timeScale = Math.max(other.entity.timeScale, realBoost); - Effects.effect(Fx.overdriveBlockFull, Tmp.c1.set(color).lerp(phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size); - healed.add(other.pos()); + healed.add(other.pos()); } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/ShockMine.java b/core/src/io/anuke/mindustry/world/blocks/defense/ShockMine.java index 63b7001f51..94e8a0590c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/ShockMine.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/ShockMine.java @@ -3,10 +3,10 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Fill; import io.anuke.arc.math.Mathf; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.entities.effect.Lightning; import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -37,6 +37,11 @@ public class ShockMine extends Block{ Draw.color(); } + @Override + public void drawTeam(Tile tile){ + //no + } + @Override public void draw(Tile tile){ //nope @@ -46,7 +51,7 @@ public class ShockMine extends Block{ public void unitOn(Tile tile, Unit unit){ if(unit.getTeam() != tile.getTeam() && tile.entity.timer.get(timerDamage, cooldown)){ for(int i = 0; i < tendrils; i++){ - Lightning.create(tile.getTeam(), Palette.lancerLaser, damage, tile.drawx(), tile.drawy(), Mathf.random(360f), length); + Lightning.create(tile.getTeam(), Pal.lancerLaser, damage, tile.drawx(), tile.drawy(), Mathf.random(360f), length); } tile.entity.damage(tileDamage); } diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/SurgeWall.java b/core/src/io/anuke/mindustry/world/blocks/defense/SurgeWall.java index 5316227bfc..e9a26e505a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/SurgeWall.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/SurgeWall.java @@ -1,9 +1,9 @@ package io.anuke.mindustry.world.blocks.defense; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.effect.Lightning; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.arc.math.Mathf; public class SurgeWall extends Wall{ @@ -19,7 +19,7 @@ public class SurgeWall extends Wall{ public void handleBulletHit(TileEntity entity, Bullet bullet){ super.handleBulletHit(entity, bullet); if(Mathf.chance(lightningChance)){ - Lightning.create(entity.getTeam(), Palette.surge, lightningDamage, bullet.x, bullet.y, bullet.rot() + 180f, lightningLength); + Lightning.create(entity.getTeam(), Pal.surge, lightningDamage, bullet.x, bullet.y, bullet.rot() + 180f, lightningLength); } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/Wall.java b/core/src/io/anuke/mindustry/world/blocks/defense/Wall.java index cd2f2a61d3..3062883588 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/Wall.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/Wall.java @@ -1,9 +1,15 @@ package io.anuke.mindustry.world.blocks.defense; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.math.Mathf; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockGroup; public class Wall extends Block{ + protected int variants = 0; public Wall(String name){ super(name); @@ -12,6 +18,34 @@ public class Wall extends Block{ group = BlockGroup.walls; } + @Override + public void load(){ + super.load(); + + if(variants != 0){ + variantRegions = new TextureRegion[variants]; + + for(int i = 0; i < variants; i++){ + variantRegions[i] = Core.atlas.find(name + (i + 1)); + } + region = variantRegions[0]; + } + } + + @Override + public void draw(Tile tile){ + if(variants == 0){ + Draw.rect(region, tile.drawx(), tile.drawy()); + }else{ + Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.drawx(), tile.drawy()); + } + } + + @Override + public TextureRegion[] generateIcons(){ + return new TextureRegion[]{Core.atlas.find(Core.atlas.has(name) ? name : name + "1")}; + } + @Override public boolean canReplace(Block other){ return super.canReplace(other) && health > other.health; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ChargeTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ChargeTurret.java index 855dc67fb2..47faa0bd91 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ChargeTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ChargeTurret.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.world.blocks.defense.turrets; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.world.Tile; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java index 65053c9284..d81805a721 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java @@ -4,8 +4,8 @@ import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.util.Time; import io.anuke.arc.math.Mathf; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ItemTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ItemTurret.java index f2f41708aa..616ffb0d53 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ItemTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/ItemTurret.java @@ -1,10 +1,14 @@ package io.anuke.mindustry.world.blocks.defense.turrets; import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.bullet.BulletType; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.values.ItemFilterValue; @@ -35,6 +39,17 @@ public class ItemTurret extends CooledTurret{ stats.add(BlockStat.inputItems, new ItemFilterValue(item -> ammo.containsKey(item))); } + + @Override + public void displayBars(Tile tile, Table bars){ + super.displayBars(tile, bars); + + TurretEntity entity = tile.entity(); + + bars.add(new Bar("blocks.ammo", Pal.ammo, () -> (float)entity.totalAmmo / maxAmmo)).growX(); + bars.row(); + } + @Override public int acceptStack(Item item, int amount, Tile tile, Unit source){ TurretEntity entity = tile.entity(); @@ -66,7 +81,6 @@ public class ItemTurret extends CooledTurret{ BulletType type = ammo.get(item); entity.totalAmmo += type.ammoMultiplier; - entity.items.add(item, 1); //find ammo entry by type for(int i = 0; i < entity.ammo.size; i++){ @@ -91,6 +105,11 @@ public class ItemTurret extends CooledTurret{ return ammo != null && ammo.get(item) != null && entity.totalAmmo + ammo.get(item).ammoMultiplier <= maxAmmo; } + @Override + public TileEntity newEntity(){ + return new ItemTurretEntity(); + } + public class ItemTurretEntity extends TurretEntity{ @Override public void write(DataOutput stream) throws IOException{ diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LaserTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LaserTurret.java index ce6414f4ea..3796103fe3 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LaserTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LaserTurret.java @@ -1,10 +1,10 @@ package io.anuke.mindustry.world.blocks.defense.turrets; -import io.anuke.arc.entities.Effects; +import io.anuke.mindustry.entities.Effects; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.type.Liquid; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LiquidTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LiquidTurret.java index e368901395..ee321ac2ed 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LiquidTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LiquidTurret.java @@ -1,8 +1,7 @@ package io.anuke.mindustry.world.blocks.defense.turrets; import io.anuke.arc.collection.ObjectMap; -import io.anuke.arc.entities.Effects; -import io.anuke.mindustry.Vars; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.entities.effect.Fire; import io.anuke.mindustry.type.Item; @@ -11,10 +10,6 @@ import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.values.LiquidFilterValue; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; @@ -112,41 +107,4 @@ public abstract class LiquidTurret extends Turret{ && (tile.entity.liquids.current() == liquid || (ammo.containsKey(tile.entity.liquids.current()) && tile.entity.liquids.get(tile.entity.liquids.current()) <= ammo.get(tile.entity.liquids.current()).ammoMultiplier + 0.001f)); } - public class LiquidTurretEntity extends TurretEntity{ - @Override - public void write(DataOutput stream) throws IOException{ - stream.writeByte(ammo.size); - for(AmmoEntry entry : ammo){ - LiquidEntry i = (LiquidEntry)entry; - stream.writeByte(i.liquid.id); - stream.writeShort(i.amount); - } - } - - @Override - public void read(DataInput stream) throws IOException{ - byte amount = stream.readByte(); - for(int i = 0; i < amount; i++){ - Liquid liquid = Vars.content.liquid(stream.readByte()); - short a = stream.readShort(); - totalAmmo += a; - ammo.add(new LiquidEntry(liquid, a)); - } - } - } - - class LiquidEntry extends AmmoEntry{ - protected Liquid liquid; - - LiquidEntry(Liquid liquid, int amount){ - this.liquid = liquid; - this.amount = amount; - } - - @Override - public BulletType type(){ - return ammo.get(liquid); - } - } - } diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/PowerTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/PowerTurret.java index 7b806c0150..8f3d143a23 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/PowerTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/PowerTurret.java @@ -2,11 +2,11 @@ package io.anuke.mindustry.world.blocks.defense.turrets; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.consumers.ConsumePower; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; public abstract class PowerTurret extends CooledTurret{ - //TODO recode this class, satisfaction must be 100%! /** The percentage of power which will be used per shot. */ protected float powerUsed = 0.5f; protected BulletType shootType; @@ -20,7 +20,7 @@ public abstract class PowerTurret extends CooledTurret{ public void setStats(){ super.setStats(); - stats.add(BlockStat.powerShot, powerUsed, StatUnit.powerUnits); + stats.add(BlockStat.powerShot, powerUsed * consumes.get(ConsumePower.class).powerCapacity, StatUnit.powerUnits); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java index 5b6e97a40f..4b6990d320 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java @@ -3,8 +3,8 @@ package io.anuke.mindustry.world.blocks.defense.turrets; import io.anuke.arc.Core; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.EnumSet; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.function.BiConsumer; import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.Color; @@ -17,13 +17,13 @@ import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Predict; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.entities.traits.TargetTrait; import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockFlag; @@ -38,7 +38,7 @@ public abstract class Turret extends Block{ protected final int timerTarget = timers++; - protected Color heatColor = Palette.turretHeat; + protected Color heatColor = Pal.turretHeat; protected Effect shootEffect = Fx.none; protected Effect smokeEffect = Fx.none; protected Effect ammoUseEffect = Fx.none; @@ -62,9 +62,7 @@ public abstract class Turret extends Block{ protected Vector2 tr = new Vector2(); protected Vector2 tr2 = new Vector2(); - protected TextureRegion baseRegion; - protected TextureRegion heatRegion; - protected TextureRegion baseTopRegion; + protected TextureRegion baseRegion, heatRegion; protected BiConsumer drawer = (tile, entity) -> Draw.rect(region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90); @@ -84,6 +82,7 @@ public abstract class Turret extends Block{ layer = Layer.turret; group = BlockGroup.turrets; flags = EnumSet.of(BlockFlag.turret); + outlineIcon = true; } @Override @@ -91,13 +90,12 @@ public abstract class Turret extends Block{ return false; } - @Override public void load(){ super.load(); + region = Core.atlas.find(name); baseRegion = Core.atlas.find("block-" + size); - baseTopRegion = Core.atlas.find("block-" + size + "-top"); heatRegion = Core.atlas.find(name + "-heat"); } @@ -107,7 +105,7 @@ public abstract class Turret extends Block{ stats.add(BlockStat.shootRange, range, StatUnit.blocks); stats.add(BlockStat.inaccuracy, (int) inaccuracy, StatUnit.degrees); - stats.add(BlockStat.reload, 60f / reload, StatUnit.seconds); + stats.add(BlockStat.reload, 60f / reload, StatUnit.none); stats.add(BlockStat.shots, shots, StatUnit.none); stats.add(BlockStat.targetsAir, targetAir); } @@ -145,7 +143,7 @@ public abstract class Turret extends Block{ @Override public void drawPlace(int x, int y, int rotation, boolean valid){ - Lines.stroke(1f, Palette.placing); + Lines.stroke(1f, Pal.placing); Lines.dashCircle(x * tilesize + offset(), y * tilesize + offset(), range); Draw.color(); } diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/BufferedItemBridge.java b/core/src/io/anuke/mindustry/world/blocks/distribution/BufferedItemBridge.java index 1980195b30..6e833659c5 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/BufferedItemBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/BufferedItemBridge.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.world.blocks.distribution; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.ItemBuffer; import io.anuke.mindustry.world.Tile; diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java index 0115340429..22d9c2e873 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.world.blocks.distribution; import io.anuke.arc.Core; import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.LiquidBlock; diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java index 814352f1bd..3858b02e48 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java @@ -10,8 +10,8 @@ import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Log; import io.anuke.arc.util.Pack; import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; @@ -28,7 +28,6 @@ import static io.anuke.mindustry.Vars.*; public class Conveyor extends Block{ private static final float itemSpace = 0.135f * 3f; - private static final float offsetScl = 128f * 3f; private static final float minmove = 1f / (Short.MAX_VALUE - 2); private static ItemPos drawpos = new ItemPos(); private static ItemPos pos1 = new ItemPos(); @@ -59,7 +58,7 @@ public class Conveyor extends Block{ @Override public void setStats(){ super.setStats(); - stats.add(BlockStat.itemSpeed, speed * 60, StatUnit.pixelsSecond); + stats.add(BlockStat.itemsMoved, speed * 60, StatUnit.itemsSecond); } @Override @@ -140,7 +139,7 @@ public class Conveyor extends Block{ tr1.trns(rotation * 90, tilesize, 0); tr2.trns(rotation * 90, -tilesize / 2f, pos.x * tilesize / 2f); - Draw.rect(pos.item.region, + Draw.rect(pos.item.icon(Item.Icon.medium), (tile.x * tilesize + tr1.x * pos.y + tr2.x), (tile.y * tilesize + tr1.y * pos.y + tr2.y), itemSize, itemSize); } @@ -156,7 +155,7 @@ public class Conveyor extends Block{ entity.noSleep(); - float speed = this.speed * tilesize / 2.3f; + float speed = this.speed * tilesize / 2.4f; float centerSpeed = 0.1f; float centerDstScl = 3f; float tx = Geometry.d4[tile.getRotation()].x, ty = Geometry.d4[tile.getRotation()].y; @@ -172,7 +171,7 @@ public class Conveyor extends Block{ } if(entity.convey.size * itemSpace < 0.9f){ - unit.velocity().add((tx * speed + centerx) * entity.delta(), (ty * speed + centery) * entity.delta()); + unit.applyImpulse((tx * speed + centerx) * entity.delta(), (ty * speed + centery) * entity.delta()); } } @@ -181,7 +180,9 @@ public class Conveyor extends Block{ ConveyorEntity entity = tile.entity(); entity.minitem = 1f; + Tile next = tile.getNearby(tile.getRotation()); + float nextMax = next != null && next.block() instanceof Conveyor ? 1f - Math.max(itemSpace - next.entity().minitem, 0) : 1f; int minremove = Integer.MAX_VALUE; for(int i = entity.convey.size - 1; i >= 0; i--){ @@ -205,10 +206,9 @@ public class Conveyor extends Block{ pos.x = Mathf.lerpDelta(pos.x, 0, 0.1f); } - pos.y = Mathf.clamp(pos.y); + pos.y = Mathf.clamp(pos.y, 0, nextMax); if(pos.y >= 0.9999f && offloadDir(tile, pos.item)){ - Tile next = tile.getNearby(tile.getRotation()); if(next.block() instanceof Conveyor){ ConveyorEntity othere = next.entity(); diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java index 96b3c231c2..20be93efda 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java @@ -7,18 +7,16 @@ import io.anuke.arc.collection.IntArray; import io.anuke.arc.collection.IntSet; import io.anuke.arc.collection.IntSet.IntSetIterator; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.CapStyle; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; +import io.anuke.arc.math.geom.Point2; import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Edges; @@ -34,15 +32,14 @@ import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; public class ItemBridge extends Block{ - protected static int lastPlaced; - protected int timerTransport = timers++; protected int range; protected float transportTime = 2f; protected IntArray removals = new IntArray(); - protected TextureRegion endRegion, bridgeRegion, arrowRegion; + private static int lastPlaced = Pos.invalid; + public ItemBridge(String name){ super(name); update = true; @@ -85,29 +82,46 @@ public class ItemBridge extends Block{ @Override public void playerPlaced(Tile tile){ - Tile last = world.tile(lastPlaced); - if(linkValid(tile, last)){ - ItemBridgeEntity entity = last.entity(); - if(!linkValid(last, world.tile(entity.link))){ - Call.linkItemBridge(null, last, tile); + Tile link = findLink(tile.x, tile.y); + if(linkValid(tile, link)){ + Call.linkItemBridge(null, link, tile); + } + + lastPlaced = tile.pos(); + } + + public Tile findLink(int x, int y){ + if(world.tile(x, y) != null && linkValid(world.tile(x, y), world.tile(lastPlaced)) && lastPlaced != Pos.get(x, y)){ + return world.tile(lastPlaced); + } + + for(int j = 0; j < 4; j ++){ + Point2 p = Geometry.d4(j + 1); + for(int i = 1; i <= range; i++){ + Tile tile = world.tile(x + p.x * i, y + p.y * i); + + if(tile == null) break; + if(tile.block() == this && !(tile.x == x && tile.y == y) && tile.entity != null && tile.entity().link == Pos.invalid){ + return tile; + } } } - lastPlaced = tile.pos(); + return null; } @Override public void drawPlace(int x, int y, int rotation, boolean valid){ - Lines.stroke(2f); - Draw.color(Palette.placing); - for(int i = 0; i < 4; i++){ - Lines.dashLine( - x * tilesize + Geometry.d4[i].x * (tilesize / 2f + 2), - y * tilesize + Geometry.d4[i].y * (tilesize / 2f + 2), - x * tilesize + Geometry.d4[i].x * (range + 0.5f) * tilesize, - y * tilesize + Geometry.d4[i].y * (range + 0.5f) * tilesize, - range); - } + Tile link = findLink(x, y); + Draw.tint(Pal.placing); + Lines.stroke(1f); + if(link != null){ + int rot = link.absoluteRelativeTo(x, y); + float w = (link.x == x ? tilesize : Math.abs(link.x - x) * tilesize - tilesize); + float h = (link.y == y ? tilesize : Math.abs(link.y - y) * tilesize - tilesize); + Lines.rect((x + link.x)/2f * tilesize - w/2f, (y + link.y)/2f * tilesize - h/2f, w, h); + Fill.poly(link.x * tilesize + Geometry.d4[rot].x * tilesize, link.y * tilesize + Geometry.d4[rot].y * tilesize, 3, 2.8f, link.absoluteRelativeTo(x, y)*90); + } Draw.reset(); } @@ -115,7 +129,7 @@ public class ItemBridge extends Block{ public void drawConfigure(Tile tile){ ItemBridgeEntity entity = tile.entity(); - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.stroke(1f); Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f + 1f); @@ -125,7 +139,7 @@ public class ItemBridge extends Block{ Tile other = tile.getNearby(Geometry.d4[j].x * i, Geometry.d4[j].y * i); if(linkValid(tile, other)){ boolean linked = other.pos() == entity.link; - Draw.color(linked ? Palette.place : Palette.breakInvalid); + Draw.color(linked ? Pal.place : Pal.breakInvalid); Lines.square(other.drawx(), other.drawy(), other.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Time.time(), 4f, 1f))); @@ -175,6 +189,7 @@ public class ItemBridge extends Block{ Tile other = world.tile(entity.link); if(!linkValid(tile, other)){ + entity.link = Pos.invalid; tryDump(tile); entity.uptime = 0f; }else{ @@ -287,14 +302,6 @@ public class ItemBridge extends Block{ return rel != rel2; } - @Override - public void transformLinks(Tile tile, int oldWidth, int oldHeight, int newWidth, int newHeight, int shiftX, int shiftY){ - super.transformLinks(tile, oldWidth, oldHeight, newWidth, newHeight, shiftX, shiftY); - - ItemBridgeEntity entity = tile.entity(); - entity.link = world.transform(entity.link, oldWidth, oldHeight, newWidth, shiftX, shiftY); - } - @Override public TileEntity newEntity(){ return new ItemBridgeEntity(); @@ -305,7 +312,7 @@ public class ItemBridge extends Block{ } public boolean linkValid(Tile tile, Tile other, boolean checkDouble){ - if(other == null) return false; + if(other == null || tile == null) return false; if(tile.x == other.x){ if(Math.abs(tile.y - other.y) > range) return false; }else if(tile.y == other.y){ @@ -318,7 +325,7 @@ public class ItemBridge extends Block{ } public static class ItemBridgeEntity extends TileEntity{ - public int link = -1; + public int link = Pos.invalid; public IntSet incoming = new IntSet(); public float uptime; public float time; diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java index 6663da7469..84a6f32c6b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java @@ -3,7 +3,7 @@ package io.anuke.mindustry.world.blocks.distribution; import io.anuke.arc.util.NumberUtils; import io.anuke.arc.util.Pack; import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -74,7 +74,7 @@ public class Junction extends Block{ if(entity == null || relative == -1 || entity.buffers[relative].full()) return false; Tile to = tile.getNearby(relative); - return to != null && to.block().acceptItem(item, to, tile); + return to != null; } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java b/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java index fc24bb7d42..37c059464a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java @@ -4,8 +4,8 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; import io.anuke.arc.collection.ObjectSet; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; @@ -17,12 +17,12 @@ import io.anuke.arc.util.pooling.Pool.Poolable; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.content.Bullets; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -47,8 +47,8 @@ public class MassDriver extends Block{ protected Effect smokeEffect = Fx.shootBigSmoke2; protected Effect recieveEffect = Fx.mineBig; protected float shake = 3f; - protected final static float powerPercentageUsed = 1.0f; - protected TextureRegion turretRegion; + protected float powerPercentageUsed = 0.95f; + protected TextureRegion baseRegion; public MassDriver(String name){ super(name); @@ -59,6 +59,7 @@ public class MassDriver extends Block{ layer = Layer.turret; hasPower = true; consumes.powerBuffered(30f); + outlineIcon = true; } @Remote(targets = Loc.both, called = Loc.server, forward = true) @@ -79,7 +80,7 @@ public class MassDriver extends Block{ entity.reload = 1f; - entity.power.satisfaction -= Math.min(entity.power.satisfaction, powerPercentageUsed); + entity.power.satisfaction -= Math.min(entity.power.satisfaction, driver.powerPercentageUsed); DriverBulletData data = Pools.obtain(DriverBulletData.class, DriverBulletData::new); data.from = entity; @@ -110,14 +111,14 @@ public class MassDriver extends Block{ @Override public TextureRegion[] generateIcons(){ - return new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-turret")}; + return new TextureRegion[]{Core.atlas.find(name + "-base"), Core.atlas.find(name)}; } @Override public void load(){ super.load(); - turretRegion = Core.atlas.find(name + "-turret"); + baseRegion = Core.atlas.find(name + "-base"); } @Override @@ -177,11 +178,16 @@ public class MassDriver extends Block{ entity.waiting.clear(); } + @Override + public void draw(Tile tile){ + Draw.rect(baseRegion, tile.drawx(), tile.drawy()); + } + @Override public void drawLayer(Tile tile){ MassDriverEntity entity = tile.entity(); - Draw.rect(turretRegion, + Draw.rect(region, tile.drawx() + Angles.trnsx(entity.rotation + 180f, entity.reload * knockback), tile.drawy() + Angles.trnsy(entity.rotation + 180f, entity.reload * knockback), entity.rotation - 90); } @@ -190,7 +196,7 @@ public class MassDriver extends Block{ public void drawConfigure(Tile tile){ float sin = Mathf.absin(Time.time(), 6f, 1f); - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.stroke(1f); Lines.poly(tile.drawx(), tile.drawy(), 20, (tile.block().size/2f+1) * tilesize + sin); @@ -199,12 +205,12 @@ public class MassDriver extends Block{ if(linkValid(tile)){ Tile target = world.tile(entity.link); - Draw.color(Palette.place); + Draw.color(Pal.place); Lines.poly(target.drawx(), target.drawy(), 20, (target.block().size/2f+1) * tilesize + sin); Draw.reset(); } - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.dashCircle(tile.drawx(), tile.drawy(), range); Draw.color(); } @@ -231,14 +237,6 @@ public class MassDriver extends Block{ return tile.entity.items.total() < itemCapacity; } - @Override - public void transformLinks(Tile tile, int oldWidth, int oldHeight, int newWidth, int newHeight, int shiftX, int shiftY){ - super.transformLinks(tile, oldWidth, oldHeight, newWidth, newHeight, shiftX, shiftY); - - MassDriverEntity entity = tile.entity(); - entity.link = world.transform(entity.link, oldWidth, oldHeight, newWidth, shiftX, shiftY); - } - @Override public TileEntity newEntity(){ return new MassDriverEntity(); diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Router.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Router.java index fe9ba5f5d5..fd1e3cc499 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Router.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Router.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.world.blocks.distribution; import io.anuke.arc.collection.Array; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Edges; diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java index f4b3697c09..fada43be00 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java @@ -3,8 +3,8 @@ package io.anuke.mindustry.world.blocks.distribution; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; diff --git a/core/src/io/anuke/mindustry/world/blocks/power/BurnerGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/BurnerGenerator.java index 0441f2a876..dba75d1e0c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/BurnerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/BurnerGenerator.java @@ -6,7 +6,7 @@ import io.anuke.mindustry.type.Liquid; public class BurnerGenerator extends ItemLiquidGenerator{ public BurnerGenerator(String name){ - super(InputType.LiquidsAndItems, name); + super(true, false, name); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/power/DecayGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/DecayGenerator.java index 678da93587..18b3cd47df 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/DecayGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/DecayGenerator.java @@ -1,12 +1,11 @@ package io.anuke.mindustry.world.blocks.power; import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Liquid; public class DecayGenerator extends ItemLiquidGenerator{ public DecayGenerator(String name){ - super(InputType.ItemsOnly, name); + super(true, false, name); hasItems = true; hasLiquids = false; } diff --git a/core/src/io/anuke/mindustry/world/blocks/power/DifferentialGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/DifferentialGenerator.java new file mode 100644 index 0000000000..38f20f53db --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/power/DifferentialGenerator.java @@ -0,0 +1,28 @@ +package io.anuke.mindustry.world.blocks.power; + +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.consumers.ConsumeItem; +import io.anuke.mindustry.world.consumers.ConsumeLiquid; + +public class DifferentialGenerator extends TurbineGenerator{ + + public DifferentialGenerator(String name){ + super(name); + + hasLiquids = true; + consumes.require(ConsumeItem.class); + consumes.require(ConsumeLiquid.class); + } + + @Override + public boolean acceptItem(Item item, Tile tile, Tile source){ + return hasItems && consumes.item() == item && tile.entity.items.total() < itemCapacity; + } + + @Override + public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ + return hasLiquids && consumes.liquid() == liquid && tile.entity.liquids.get(liquid) < liquidCapacity; + } +} diff --git a/core/src/io/anuke/mindustry/world/blocks/power/FusionReactor.java b/core/src/io/anuke/mindustry/world/blocks/power/ImpactReactor.java similarity index 58% rename from core/src/io/anuke/mindustry/world/blocks/power/FusionReactor.java rename to core/src/io/anuke/mindustry/world/blocks/power/ImpactReactor.java index 77d36761cd..9a18a8fe4f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/FusionReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ImpactReactor.java @@ -6,67 +6,76 @@ import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.arc.util.Tmp; +import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Damage; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.consumers.ConsumePower; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -public class FusionReactor extends PowerGenerator{ +import static io.anuke.mindustry.Vars.tilesize; + +public class ImpactReactor extends PowerGenerator{ + protected int timerUse = timers++; + protected int plasmas = 4; protected float warmupSpeed = 0.001f; + protected float useTime = 60f; + protected int explosionRadius = 30; + protected int explosionDamage = 180; protected Color plasma1 = Color.valueOf("ffd06b"), plasma2 = Color.valueOf("ff361b"); protected Color ind1 = Color.valueOf("858585"), ind2 = Color.valueOf("fea080"); - public FusionReactor(String name){ + public ImpactReactor(String name){ super(name); hasPower = true; hasLiquids = true; powerProduction = 2.0f; liquidCapacity = 30f; hasItems = true; + outputsPower = consumesPower = true; + } + + @Override + public void setBars(){ + super.setBars(); + + bars.add("poweroutput", entity -> new Bar(() -> + Core.bundle.format("blocks.poweroutput", + Strings.toFixed(Math.max(entity.tile.block().getPowerProduction(entity.tile) - consumes.get(ConsumePower.class).powerPerTick, 0)*60 * entity.delta(), 1)), + () -> Pal.powerBar, + () -> ((GeneratorEntity)entity).productionEfficiency)); } @Override public void update(Tile tile){ FusionReactorEntity entity = tile.entity(); - float increaseOrDecrease = 1.0f; if(entity.cons.valid()){ entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, warmupSpeed); + + if(entity.timer.get(timerUse, useTime)){ + entity.items.remove(consumes.item(), consumes.itemAmount()); + } }else{ entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.01f); - increaseOrDecrease = -1.0f; } - float efficiencyAdded = Mathf.pow(entity.warmup, 4f) * Time.delta(); - entity.productionEfficiency = Mathf.clamp(entity.productionEfficiency + efficiencyAdded * increaseOrDecrease); + entity.productionEfficiency = Mathf.pow(entity.warmup, 5f); super.update(tile); } - @Override - public float handleDamage(Tile tile, float amount){ - FusionReactorEntity entity = tile.entity(); - - if(entity.warmup < 0.4f) return amount; - - float healthFract = tile.entity.health / health; - - //5% chance to explode when hit at <50% HP with a normal bullet - if(amount > 5f && healthFract <= 0.5f && Mathf.chance(0.05)){ - return health; - //10% chance to explode when hit at <25% HP with a powerful bullet - }else if(amount > 8f && healthFract <= 0.2f && Mathf.chance(0.1)){ - return health; - } - - return amount; - } - @Override public void draw(Tile tile){ FusionReactorEntity entity = tile.entity(); @@ -113,7 +122,28 @@ public class FusionReactor extends PowerGenerator{ if(entity.warmup < 0.4f) return; - //TODO catastrophic failure + Effects.shake(6f, 16f, tile.worldx(), tile.worldy()); + Effects.effect(Fx.impactShockwave, tile.worldx(), tile.worldy()); + for(int i = 0; i < 6; i++){ + Time.run(Mathf.random(80), () -> Effects.effect(Fx.impactcloud, tile.worldx(), tile.worldy())); + } + + Damage.damage(tile.worldx(), tile.worldy(), explosionRadius * tilesize, explosionDamage * 4); + + + for(int i = 0; i < 20; i++){ + Time.run(Mathf.random(80), () -> { + Tmp.v1.rnd(Mathf.random(40f)); + Effects.effect(Fx.explosion, Tmp.v1.x + tile.worldx(), Tmp.v1.y + tile.worldy()); + }); + } + + for(int i = 0; i < 70; i++){ + Time.run(Mathf.random(90), () -> { + Tmp.v1.rnd(Mathf.random(120f)); + Effects.effect(Fx.impactsmoke, Tmp.v1.x + tile.worldx(), Tmp.v1.y + tile.worldy()); + }); + } } public static class FusionReactorEntity extends GeneratorEntity{ diff --git a/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java index 44fdd5caf9..6a45c18a4d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java @@ -1,14 +1,14 @@ package io.anuke.mindustry.world.blocks.power; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; +import io.anuke.mindustry.entities.Effects; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; @@ -36,25 +36,18 @@ public class ItemLiquidGenerator extends PowerGenerator{ protected Effects.Effect explodeEffect = Fx.generatespark; protected Color heatColor = Color.valueOf("ff9b59"); protected TextureRegion topRegion; + protected boolean randomlyExplode = false; - public enum InputType{ - ItemsOnly, - LiquidsOnly, - LiquidsAndItems - } - - public ItemLiquidGenerator(InputType inputType, String name){ + public ItemLiquidGenerator(boolean hasItems, boolean hasLiquids, String name){ super(name); - this.hasItems = inputType != InputType.LiquidsOnly; - this.hasLiquids = inputType != InputType.ItemsOnly; + this.hasItems = hasItems; + this.hasLiquids = hasLiquids; if(hasItems){ - itemCapacity = 20; consumes.add(new ConsumeItemFilter(item -> getItemEfficiency(item) >= minItemEfficiency)).update(false).optional(true); } if(hasLiquids){ - liquidCapacity = 10f; consumes.add(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, 0.001f, true)).update(false).optional(true); } } @@ -67,13 +60,12 @@ public class ItemLiquidGenerator extends PowerGenerator{ } } - @Override public void update(Tile tile){ ItemLiquidGeneratorEntity entity = tile.entity(); - // Note: Do not use this delta when calculating the amount of power or the power efficiency, but use it for resource consumption if necessary. - // Power amount is delta'd by PowerGraph class already. + //Note: Do not use this delta when calculating the amount of power or the power efficiency, but use it for resource consumption if necessary. + //Power amount is delta'd by PowerGraph class already. float calculationDelta = entity.delta(); if(!entity.cons.valid()){ @@ -88,6 +80,9 @@ public class ItemLiquidGenerator extends PowerGenerator{ break; } } + + entity.heat = Mathf.lerpDelta(entity.heat, entity.generateTime >= 0.001f ? 1f : 0f, 0.05f); + //liquid takes priority over solids if(hasLiquids && liquid != null && entity.liquids.get(liquid) >= 0.001f){ float baseLiquidEfficiency = getLiquidEfficiency(liquid); @@ -95,9 +90,7 @@ public class ItemLiquidGenerator extends PowerGenerator{ float used = Math.min(entity.liquids.get(liquid) * calculationDelta, maximumPossible); entity.liquids.remove(liquid, used); - - // Note: 0.5 = 100%. PowerGraph will multiply this efficiency by two on its own. - entity.productionEfficiency = Mathf.clamp(baseLiquidEfficiency * used / maximumPossible); + entity.productionEfficiency = baseLiquidEfficiency * used / maximumPossible; if(used > 0.001f && Mathf.chance(0.05 * entity.delta())){ Effects.effect(generateEffect, tile.drawx() + Mathf.range(3f), tile.drawy() + Mathf.range(3f)); @@ -115,9 +108,9 @@ public class ItemLiquidGenerator extends PowerGenerator{ if(entity.generateTime > 0f){ entity.generateTime -= Math.min(1f / itemDuration * entity.delta(), entity.generateTime); - if(Mathf.chance(entity.delta() * 0.06 * Mathf.clamp(entity.explosiveness - 0.25f))){ + if(randomlyExplode && Mathf.chance(entity.delta() * 0.06 * Mathf.clamp(entity.explosiveness - 0.5f))){ //this block is run last so that in the event of a block destruction, no code relies on the block type - entity.damage(Mathf.random(8f)); + entity.damage(Mathf.random(11f)); Effects.effect(explodeEffect, tile.worldx() + Mathf.range(size * tilesize / 2f), tile.worldy() + Mathf.range(size * tilesize / 2f)); } }else{ @@ -142,17 +135,13 @@ public class ItemLiquidGenerator extends PowerGenerator{ public void draw(Tile tile){ super.draw(tile); - GeneratorEntity entity = tile.entity(); + ItemLiquidGeneratorEntity entity = tile.entity(); if(hasItems){ - if(entity.generateTime > 0){ - Draw.color(heatColor); - float alpha = (entity.items.total() > 0 ? 1f : Mathf.clamp(entity.generateTime)); - alpha = alpha * 0.7f + Mathf.absin(Time.time(), 12f, 0.3f) * alpha; - Draw.alpha(alpha); - Draw.rect(topRegion, tile.drawx(), tile.drawy()); - Draw.reset(); - } + Draw.color(heatColor); + Draw.alpha(entity.heat * 0.4f + Mathf.absin(Time.time(), 8f, 0.6f) * entity.heat); + Draw.rect(topRegion, tile.drawx(), tile.drawy()); + Draw.reset(); } if(hasLiquids){ @@ -182,5 +171,6 @@ public class ItemLiquidGenerator extends PowerGenerator{ public static class ItemLiquidGeneratorEntity extends GeneratorEntity{ public float explosiveness; + public float heat; } } diff --git a/core/src/io/anuke/mindustry/world/blocks/power/LiquidHeatGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/LiquidHeatGenerator.java deleted file mode 100644 index fd7a51833a..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/power/LiquidHeatGenerator.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.anuke.mindustry.world.blocks.power; - -import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; - -//TODO remove, as this is no longer a thing -public class LiquidHeatGenerator extends ItemLiquidGenerator{ - - public LiquidHeatGenerator(String name){ - super(InputType.LiquidsOnly, name); - } - - @Override - public void setStats(){ - super.setStats(); - - stats.remove(BlockStat.basePowerGeneration); - // right now, Lava is the only thing that can be used. - stats.add(BlockStat.basePowerGeneration, powerProduction * getLiquidEfficiency(Liquids.slag) / maxLiquidGenerate * 60f, StatUnit.powerSecond); - } - - @Override - protected float getLiquidEfficiency(Liquid liquid){ - return liquid.temperature - 0.5f; - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java b/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java index 91e7fadf75..3300a6cf2e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java @@ -1,22 +1,20 @@ package io.anuke.mindustry.world.blocks.power; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; -import io.anuke.arc.util.Time; import io.anuke.arc.math.geom.Vector2; -import io.anuke.mindustry.content.Items; +import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Damage; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; -import io.anuke.mindustry.world.meta.values.LiquidFilterValue; import java.io.DataInput; import java.io.DataOutput; @@ -32,24 +30,21 @@ public class NuclearReactor extends PowerGenerator{ protected Color coolColor = new Color(1, 1, 1, 0f); protected Color hotColor = Color.valueOf("ff9575a3"); protected int fuelUseTime = 120; //time to consume 1 fuel - protected float heating = 0.013f; //heating per frame - protected float coolantPower = 0.015f; //how much heat decreases per coolant unit + protected float heating = 0.01f; //heating per frame * fullness protected float smokeThreshold = 0.3f; //threshold at which block starts smoking - protected float maxLiquidUse = 2f; //max liquid use per frame protected int explosionRadius = 19; protected int explosionDamage = 135; protected float flashThreshold = 0.46f; //heat threshold at which the lights start flashing + protected float coolantPower = 0.5f; protected TextureRegion topRegion, lightsRegion; public NuclearReactor(String name){ super(name); itemCapacity = 30; - liquidCapacity = 50; + liquidCapacity = 30; hasItems = true; hasLiquids = true; - - consumes.item(Items.thorium); } @Override @@ -61,13 +56,9 @@ public class NuclearReactor extends PowerGenerator{ } @Override - public void setStats(){ - super.setStats(); - stats.add(BlockStat.inputLiquid, new LiquidFilterValue(liquid -> liquid.temperature <= 0.5f)); - - stats.remove(BlockStat.basePowerGeneration); - // Display the power which will be produced at 50% efficiency - stats.add(BlockStat.basePowerGeneration, powerProduction * 60f * 0.5f, StatUnit.powerSecond); + public void setBars(){ + super.setBars(); + bars.add("heat", entity -> new Bar("blocks.heat", Pal.lightOrange, () -> ((NuclearReactorEntity)entity).heat)); } @Override @@ -76,30 +67,23 @@ public class NuclearReactor extends PowerGenerator{ int fuel = entity.items.get(consumes.item()); float fullness = (float) fuel / itemCapacity; - entity.productionEfficiency = fullness / 2.0f; // Currently, efficiency of 0.5 = 100% + entity.productionEfficiency = fullness; if(fuel > 0){ entity.heat += fullness * heating * Math.min(entity.delta(), 4f); if(entity.timer.get(timerFuel, fuelUseTime)){ - entity.items.remove(consumes.item(), 1); + entity.cons.trigger(); } } - if(entity.liquids.total() > 0){ - Liquid liquid = entity.liquids.current(); + Liquid liquid = consumes.liquid(); + float liquidAmount = consumes.liquidAmount(); - if(liquid.temperature <= 0.5f){ //is coolant - float pow = coolantPower * (liquid.heatCapacity + 0.5f / liquid.temperature); //heat depleted per unit of liquid - float maxUsed = Math.min(Math.min(entity.liquids.get(liquid), entity.heat / pow), maxLiquidUse * entity.delta()); //max that can be cooled in terms of liquid - entity.heat -= maxUsed * pow; - entity.liquids.remove(liquid, maxUsed); - }else{ //is heater - float heat = coolantPower * liquid.heatCapacity / 4f; //heat created per unit of liquid - float maxUsed = Math.min(Math.min(entity.liquids.get(liquid), (1f - entity.heat) / heat), maxLiquidUse * entity.delta()); //max liquid used - entity.heat += maxUsed * heat; - entity.liquids.remove(liquid, maxUsed); - } + if(entity.heat > 0){ + float maxUsed = Math.min(Math.min(entity.liquids.get(liquid), entity.heat / coolantPower), liquidAmount * entity.delta()); + entity.heat -= maxUsed * coolantPower; + entity.liquids.remove(liquid, maxUsed); } if(entity.heat > smokeThreshold){ @@ -153,12 +137,6 @@ public class NuclearReactor extends PowerGenerator{ } } - @Override - public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return tile.entity.liquids.get(liquid) + amount < liquidCapacity && liquid.temperature <= 0.5f && - (tile.entity.liquids.current() == liquid || tile.entity.liquids.get(tile.entity.liquids.current()) < 0.01f); - } - @Override public void draw(Tile tile){ super.draw(tile); diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java index b6902c6796..88d7608636 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerGenerator.java @@ -1,8 +1,13 @@ package io.anuke.mindustry.world.blocks.power; +import io.anuke.arc.Core; import io.anuke.arc.collection.EnumSet; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.arc.util.Strings; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.consumers.ConsumePower; import io.anuke.mindustry.world.meta.BlockFlag; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; @@ -12,7 +17,7 @@ import java.io.DataOutput; import java.io.IOException; public class PowerGenerator extends PowerDistributor{ - /** The amount of power produced per tick in case of an efficiency of 1.0, which currently represents 200%. */ + /** The amount of power produced per tick in case of an efficiency of 1.0, which represents 100%. */ protected float powerProduction; public BlockStat generationType = BlockStat.basePowerGeneration; @@ -25,14 +30,24 @@ public class PowerGenerator extends PowerDistributor{ @Override public void setStats(){ super.setStats(); - // Divide power production by two since that is what is produced at an efficiency of 0.5, which currently represents 100% - stats.add(generationType, powerProduction * 60.0f / 2.0f, StatUnit.powerSecond); + stats.add(generationType, powerProduction * 60.0f, StatUnit.powerSecond); + } + + @Override + public void setBars(){ + super.setBars(); + + if(hasPower && outputsPower && !consumes.has(ConsumePower.class)){ + bars.add("power", entity -> new Bar(() -> + Core.bundle.format("blocks.poweroutput", + Strings.toFixed(entity.tile.block().getPowerProduction(entity.tile)*60 * entity.timeScale, 1)), + () -> Pal.powerBar, + () -> ((GeneratorEntity)entity).productionEfficiency)); + } } @Override public float getPowerProduction(Tile tile){ - // While 0.5 efficiency currently reflects 100%, we do not need to multiply by any factor since powerProduction states the - // power which would be produced at 1.0 efficiency return powerProduction * tile.entity().productionEfficiency; } @@ -48,7 +63,7 @@ public class PowerGenerator extends PowerDistributor{ public static class GeneratorEntity extends TileEntity{ public float generateTime; - /** The efficiency of the producer. Currently, an efficiency of 0.5 means 100% */ + /** The efficiency of the producer. An efficiency of 1.0 means 100% */ public float productionEfficiency = 0.0f; @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java index e25e8a649e..19b9c92631 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java @@ -6,6 +6,8 @@ import io.anuke.arc.collection.IntSet; import io.anuke.arc.collection.ObjectSet; import io.anuke.arc.collection.Queue; import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.WindowedMean; +import io.anuke.arc.util.Time; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.consumers.Consume; import io.anuke.mindustry.world.consumers.ConsumePower; @@ -22,7 +24,9 @@ public class PowerGraph{ private final ObjectSet batteries = new ObjectSet<>(); private final ObjectSet all = new ObjectSet<>(); - private long lastFrameUpdated; + private final WindowedMean powerBalance = new WindowedMean(60); + + private long lastFrameUpdated = -1; private final int graphID; private static int lastGraphID; @@ -34,6 +38,10 @@ public class PowerGraph{ return graphID; } + public float getPowerBalance(){ + return powerBalance.getMean(); + } + public float getPowerProduced(){ float powerProduced = 0f; for(Tile producer : producers){ @@ -80,7 +88,7 @@ public class PowerGraph{ public float useBatteries(float needed){ float stored = getBatteryStored(); - if(Mathf.isEqual(stored, 0f)){ return 0f; } + if(Mathf.isEqual(stored, 0f)) return 0f; float used = Math.min(stored, needed); float consumedPowerPercentage = Math.min(1.0f, needed / stored); @@ -98,7 +106,7 @@ public class PowerGraph{ public float chargeBatteries(float excess){ float capacity = getBatteryCapacity(); - if(Mathf.isEqual(capacity, 0f)){ return 0f; } + if(Mathf.isEqual(capacity, 0f)) return 0f; for(Tile battery : batteries){ Consumers consumes = battery.block().consumes; @@ -114,30 +122,28 @@ public class PowerGraph{ } public void distributePower(float needed, float produced){ - if(Mathf.isEqual(needed, 0f)){ return; } - - float coverage = Math.min(1, produced / needed); + //distribute even if not needed. this is because some might be requiring power but not requesting it; it updates consumers + float coverage = Mathf.isZero(needed) ? 1f : Math.min(1, produced / needed); for(Tile consumer : consumers){ Consumers consumes = consumer.block().consumes; if(consumes.has(ConsumePower.class)){ ConsumePower consumePower = consumes.get(ConsumePower.class); - if(!otherConsumersAreValid(consumer, consumePower)){ - consumer.entity.power.satisfaction = 0.0f; // Only supply power if the consumer would get valid that way - }else{ - if(consumePower.isBuffered){ + //currently satisfies power even if it's not required yet + if(consumePower.isBuffered){ + if(!Mathf.isZero(consumePower.powerCapacity)){ // Add an equal percentage of power to all buffers, based on the global power coverage in this graph float maximumRate = consumePower.requestedPower(consumer.block(), consumer.entity()) * coverage * consumer.entity.delta(); consumer.entity.power.satisfaction = Mathf.clamp(consumer.entity.power.satisfaction + maximumRate / consumePower.powerCapacity); - }else{ - consumer.entity.power.satisfaction = coverage; } + }else{ + consumer.entity.power.satisfaction = coverage; } } } } public void update(){ - if(Core.graphics.getFrameId() == lastFrameUpdated || consumers.size == 0 && producers.size == 0 && batteries.size == 0){ + if(Core.graphics.getFrameId() == lastFrameUpdated || (consumers.size == 0 && producers.size == 0 && batteries.size == 0)){ return; } @@ -146,6 +152,8 @@ public class PowerGraph{ float powerNeeded = getPowerNeeded(); float powerProduced = getPowerProduced(); + powerBalance.addValue((powerProduced - powerNeeded) / Time.delta()); + if(!Mathf.isEqual(powerNeeded, powerProduced)){ if(powerNeeded > powerProduced){ powerProduced += useBatteries(powerNeeded - powerProduced); @@ -167,7 +175,10 @@ public class PowerGraph{ tile.entity.power.graph = this; all.add(tile); - if(tile.block().outputsPower && tile.block().consumesPower){ + if(tile.block().outputsPower && tile.block().consumesPower && !tile.block().consumes.get(ConsumePower.class).isBuffered){ + producers.add(tile); + consumers.add(tile); + }else if(tile.block().outputsPower && tile.block().consumesPower){ batteries.add(tile); }else if(tile.block().outputsPower){ producers.add(tile); diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java index c98c9fb952..338b433d9f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java @@ -3,17 +3,21 @@ package io.anuke.mindustry.world.blocks.power; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; +import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Vector2; -import io.anuke.arc.math.Angles; +import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.graphics.Shapes; +import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.PowerBlock; import io.anuke.mindustry.world.meta.BlockStat; @@ -23,9 +27,6 @@ import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; public class PowerNode extends PowerBlock{ - public static final float thicknessScl = 0.7f; - public static final float flashScl = 0.12f; - //last distribution block placed private static int lastPlaced = -1; @@ -89,6 +90,16 @@ public class PowerNode extends PowerBlock{ } } + @Override + public void setBars(){ + super.setBars(); + bars.add("power", entity -> new Bar(() -> + Core.bundle.format("blocks.powerbalance", + entity.power.graph == null ? "+0" : ((entity.power.graph.getPowerBalance() >= 0 ? "+" : "") + Strings.toFixed(entity.power.graph.getPowerBalance()*60, 1))), + () -> Pal.powerBar, + () -> entity.power.graph == null ? 0 : Mathf.clamp(entity.power.graph.getPowerProduced() / entity.power.graph.getPowerNeeded()))); + } + @Override public void playerPlaced(Tile tile){ Tile before = world.tile(lastPlaced); @@ -141,7 +152,7 @@ public class PowerNode extends PowerBlock{ Lines.stroke(1f); - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.poly(tile.drawx(), tile.drawy(), 50, laserRange*tilesize); Draw.reset(); } @@ -150,9 +161,9 @@ public class PowerNode extends PowerBlock{ public void drawConfigure(Tile tile){ TileEntity entity = tile.entity(); - Draw.color(Palette.accent); + Draw.color(Pal.accent); - Lines.stroke(1f); + Lines.stroke(1.5f); Lines.circle(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f + 1f + Mathf.absin(Time.time(), 4f, 1f)); @@ -165,14 +176,15 @@ public class PowerNode extends PowerBlock{ if(link != tile && linkValid(tile, link, false)){ boolean linked = linked(tile, link); - Draw.color(linked ? Palette.place : Palette.breakInvalid); + Draw.color(linked ? Pal.place : Pal.breakInvalid); Lines.circle(link.drawx(), link.drawy(), link.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Time.time(), 4f, 1f))); if((entity.power.links.size >= maxNodes || (link.block() instanceof PowerNode && link.entity.power.links.size >= ((PowerNode) link.block()).maxNodes)) && !linked){ + Draw.color(Pal.breakInvalid); + Lines.lineAngleCenter(link.drawx(), link.drawy(), 45, link.block().size * Mathf.sqrt2 * tilesize * 0.9f); Draw.color(); - Draw.rect("cross-" + link.block().size, link.drawx(), link.drawy()); } } } @@ -184,7 +196,7 @@ public class PowerNode extends PowerBlock{ @Override public void drawPlace(int x, int y, int rotation, boolean valid){ Lines.stroke(1f); - Draw.color(Palette.placing); + Draw.color(Pal.placing); Lines.poly(x * tilesize + offset(), y * tilesize + offset(), 50, laserRange*tilesize); Draw.reset(); } @@ -197,8 +209,7 @@ public class PowerNode extends PowerBlock{ for(int i = 0; i < entity.power.links.size; i++){ Tile link = world.tile(entity.power.links.get(i)); - if(linkValid(tile, link) && (!(link.block() instanceof PowerNode) - || ((tile.block().size > link.block().size) || (tile.block().size == link.block().size && tile.pos() < link.pos())))){ + if(linkValid(tile, link)){ drawLaser(tile, link); } } @@ -231,6 +242,7 @@ public class PowerNode extends PowerBlock{ } protected void drawLaser(Tile tile, Tile target){ + float x1 = tile.drawx(), y1 = tile.drawy(), x2 = target.drawx(), y2 = target.drawy(); @@ -245,9 +257,11 @@ public class PowerNode extends PowerBlock{ x2 += t2.x; y2 += t2.y; - Draw.color(Palette.powerLight, Palette.power, Mathf.absin(Time.time(), 8f, 1f)); - Lines.stroke(2f); - Lines.line(x1, y1, x2, y2); + Draw.color(Pal.powerLight, Color.WHITE, Mathf.absin(Time.time(), 8f, 0.3f) + 0.2f); + //Lines.stroke(2f); + //Lines.line(x1, y1, x2, y2); + + Shapes.laser("laser", "laser-end", x1, y1, x2, y2, 0.6f); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/power/SolarGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/SolarGenerator.java index 3090c389f3..96f3109fc9 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/SolarGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/SolarGenerator.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.world.blocks.power; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.world.meta.StatUnit; import io.anuke.arc.collection.EnumSet; diff --git a/core/src/io/anuke/mindustry/world/blocks/power/ThermalGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/ThermalGenerator.java new file mode 100644 index 0000000000..b0f79b0035 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/power/ThermalGenerator.java @@ -0,0 +1,55 @@ +package io.anuke.mindustry.world.blocks.power; + +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; +import io.anuke.arc.math.Mathf; +import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.world.Tile; + +public class ThermalGenerator extends PowerGenerator{ + protected Effect generateEffect = Fx.none; + + public ThermalGenerator(String name){ + super(name); + } + + @Override + public void update(Tile tile){ + GeneratorEntity entity = tile.entity(); + + if(entity.productionEfficiency > 0.1f && Mathf.chance(0.05 * entity.delta())){ + Effects.effect(generateEffect, tile.drawx() + Mathf.range(3f), tile.drawy() + Mathf.range(3f)); + } + + super.update(tile); + } + + @Override + public void placed(Tile tile){ + super.placed(tile); + } + + @Override + public void onProximityAdded(Tile tile){ + super.onProximityAdded(tile); + + GeneratorEntity entity = tile.entity(); + entity.productionEfficiency = 0f; + for(Tile other : tile.getLinkedTiles(tempTiles)){ + entity.productionEfficiency += other.floor().heat; + } + } + + @Override + public float getPowerProduction(Tile tile){ + //in this case, productionEfficiency means 'total heat' + //thus, it may be greater than 1.0 + return powerProduction * tile.entity().productionEfficiency; + } + + @Override + public boolean canPlaceOn(Tile tile){ + //make sure there's heat at this location + return tile.getLinkedTilesAs(this, tempTiles).sum(other -> other.floor().heat) > 0.01f; + } +} diff --git a/core/src/io/anuke/mindustry/world/blocks/power/TurbineGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/TurbineGenerator.java index 05f8daad7d..ed485d9492 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/TurbineGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/TurbineGenerator.java @@ -15,6 +15,6 @@ public class TurbineGenerator extends BurnerGenerator{ @Override public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return super.acceptLiquid(tile, source, liquid, amount) || liquid == consumes.liquid() && tile.entity.liquids.get(consumes.liquid()) < liquidCapacity; + return (liquid == consumes.liquid() && tile.entity.liquids.get(consumes.liquid()) < liquidCapacity); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java b/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java index 59cd3d8da9..6a5ac51af7 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java @@ -8,43 +8,26 @@ import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.RandomXS128; import io.anuke.arc.util.Time; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockStat; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -public class Cultivator extends Drill{ - protected Color plantColor = Color.valueOf("648b55"); - protected Color plantColorLight = Color.valueOf("73a75f"); - protected Color bottomColor = Color.valueOf("474747"); +public class Cultivator extends GenericCrafter{ + protected static final Color plantColor = Color.valueOf("5541b1"); + protected static final Color plantColorLight = Color.valueOf("7457ce"); + protected static final Color bottomColor = Color.valueOf("474747"); + protected TextureRegion middleRegion, topRegion; - - protected Item result; - protected RandomXS128 random = new RandomXS128(0); protected float recurrence = 6f; public Cultivator(String name){ super(name); - drillEffect = Fx.none; - } - - @Override - public void setStats(){ - super.setStats(); - - stats.remove(BlockStat.drillTier); - stats.add(BlockStat.drillTier, table -> { - table.addImage("grass1").size(8 * 3).padBottom(3).padTop(3); - table.add(Blocks.grass.formalName).padLeft(3); - }); + craftEffect = Fx.none; } @Override @@ -101,17 +84,7 @@ public class Cultivator extends Drill{ return new CultivatorEntity(); } - @Override - public boolean isValid(Tile tile){ - return tile != null && tile.floor() == Blocks.grass; - } - - @Override - public Item getDrop(Tile tile){ - return Items.biomatter; - } - - public static class CultivatorEntity extends DrillEntity{ + public static class CultivatorEntity extends GenericCrafterEntity{ public float warmup; @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Drill.java b/core/src/io/anuke/mindustry/world/blocks/production/Drill.java index 61600aa5fe..572eb8d48f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Drill.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Drill.java @@ -3,8 +3,9 @@ package io.anuke.mindustry.world.blocks.production; import io.anuke.arc.Core; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectIntMap; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.arc.util.Strings; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; @@ -13,9 +14,11 @@ import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.graphics.Layer; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.consumers.ConsumeLiquid; @@ -72,7 +75,18 @@ public class Drill extends Block{ liquidCapacity = 5f; hasItems = true; - consumes.add(new ConsumeLiquid(Liquids.water, 0.05f)).optional(true); + consumes.liquid(Liquids.water, 0.05f).optional(true); + } + + @Override + public void setBars(){ + super.setBars(); + + bars.add("drillspeed", e -> { + DrillEntity entity = (DrillEntity)e; + + return new Bar(() -> Core.bundle.format("blocks.outputspeed", Strings.toFixed(entity.lastDrillSpeed * 60 * entity.timeScale, 2)), () -> Pal.ammo, () -> entity.warmup); + }); } @Override @@ -146,7 +160,7 @@ public class Drill extends Block{ } }); - stats.add(BlockStat.drillSpeed, 60f / drillTime, StatUnit.itemsSecond); + stats.add(BlockStat.drillSpeed, 60f / drillTime * size * size, StatUnit.itemsSecond); } @Override @@ -197,6 +211,7 @@ public class Drill extends Block{ speed *= entity.power.satisfaction; // Drill slower when not at full power } + entity.lastDrillSpeed = (speed * entity.dominantItems * entity.warmup) / (drillTime + hardnessDrillMultiplier * Math.max(totalHardness, 1f) / entity.dominantItems); entity.warmup = Mathf.lerpDelta(entity.warmup, speed, warmupSpeed); entity.progress += entity.delta() * entity.dominantItems * speed * entity.warmup; @@ -204,6 +219,7 @@ public class Drill extends Block{ if(Mathf.chance(Time.delta() * updateEffectChance * entity.warmup)) Effects.effect(updateEffect, entity.x + Mathf.range(size * 2f), entity.y + Mathf.range(size * 2f)); }else{ + entity.lastDrillSpeed = 0f; entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, warmupSpeed); return; } @@ -257,6 +273,7 @@ public class Drill extends Block{ public int index; public float warmup; public float drillTime; + public float lastDrillSpeed; public int dominantItems; public Item dominantItem; diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java b/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java index cc1e4c4830..2f6e2609a0 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.world.blocks.production; import io.anuke.arc.Core; import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.consumers.ConsumeItem; diff --git a/core/src/io/anuke/mindustry/world/blocks/production/GenericCrafter.java b/core/src/io/anuke/mindustry/world/blocks/production/GenericCrafter.java index eab07cc6c4..68b40ea6cc 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/GenericCrafter.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/GenericCrafter.java @@ -1,16 +1,15 @@ package io.anuke.mindustry.world.blocks.production; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.ConsumeItem; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; @@ -22,6 +21,7 @@ public class GenericCrafter extends Block{ protected final int timerDump = timers++; protected Item output; + protected float craftTime = 80; protected Effect craftEffect = Fx.purify; protected Effect updateEffect = Fx.none; @@ -77,11 +77,9 @@ public class GenericCrafter extends Block{ } if(entity.progress >= 1f){ - - if(consumes.has(ConsumeItem.class)) tile.entity.items.remove(consumes.item(), consumes.itemAmount()); + entity.cons.trigger(); useContent(tile, output); - offloadNear(tile, output); Effects.effect(craftEffect, tile.drawx(), tile.drawy()); entity.progress = 0f; @@ -92,6 +90,11 @@ public class GenericCrafter extends Block{ } } + @Override + public boolean canProduce(Tile tile){ + return super.canProduce(tile); + } + @Override public TileEntity newEntity(){ return new GenericCrafterEntity(); diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Incinerator.java b/core/src/io/anuke/mindustry/world/blocks/production/Incinerator.java index 28574e24d0..23825bf5a8 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Incinerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Incinerator.java @@ -1,14 +1,14 @@ package io.anuke.mindustry.world.blocks.production; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Fill; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Block; @@ -24,9 +24,6 @@ public class Incinerator extends Block{ hasLiquids = true; update = true; solid = true; - - // Incinerator has no speed which could be adjusted, so it will only operate fully powered for now - consumes.power(0.05f, 1.0f); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/production/LiquidMixer.java b/core/src/io/anuke/mindustry/world/blocks/production/LiquidMixer.java index 00767ef304..9f0cb76b22 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/LiquidMixer.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/LiquidMixer.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.world.blocks.production; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.LiquidBlock; diff --git a/core/src/io/anuke/mindustry/world/blocks/production/PhaseWeaver.java b/core/src/io/anuke/mindustry/world/blocks/production/PhaseWeaver.java index 2881afc5a6..ae7b2e3530 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/PhaseWeaver.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/PhaseWeaver.java @@ -6,7 +6,7 @@ import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.world.Tile; @@ -41,7 +41,7 @@ public class PhaseWeaver extends PowerSmelter{ Shaders.build.region = weaveRegion; Shaders.build.progress = progress; - Shaders.build.color.set(Palette.accent); + Shaders.build.color.set(Pal.accent); Shaders.build.color.a = entity.heat; Shaders.build.time = -entity.time / 10f; @@ -50,7 +50,7 @@ public class PhaseWeaver extends PowerSmelter{ Draw.rect(weaveRegion, tile.drawx(), tile.drawy(), entity.time); Draw.shader(); - Draw.color(Palette.accent); + Draw.color(Pal.accent); Draw.alpha(entity.heat); Lines.lineAngleCenter( diff --git a/core/src/io/anuke/mindustry/world/blocks/production/PowerCrafter.java b/core/src/io/anuke/mindustry/world/blocks/production/PowerCrafter.java index 787b705453..c57831f628 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/PowerCrafter.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/PowerCrafter.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.world.blocks.production; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Block; @@ -8,6 +8,8 @@ import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.production.GenericCrafter.GenericCrafterEntity; import io.anuke.mindustry.world.meta.BlockStat; +/**Similar to GenericCrafter, but also optionally outputs liquids. + * TODO consolidate into one class*/ public class PowerCrafter extends Block{ protected final int timerDump = timers++; protected final int timerContentCheck = timers++; diff --git a/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java b/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java index bf2db8d3c4..b6d39ad5f9 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/PowerSmelter.java @@ -1,17 +1,16 @@ package io.anuke.mindustry.world.blocks.production; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Fill; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; -import io.anuke.mindustry.content.Items; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.world.Tile; @@ -23,19 +22,10 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import static io.anuke.mindustry.Vars.content; - public class PowerSmelter extends PowerBlock{ protected final int timerDump = timers++; - protected final int timerCraft = timers++; - protected Item result; - - protected float minFlux = 0.2f; - protected int fluxNeeded = 1; - protected float fluxSpeedMult = 0.75f; - protected float baseFluxChance = 0.25f; - protected boolean useFlux = false; + protected Item output; protected float heatUpTime = 80f; protected float minHeat = 0.5f; @@ -57,13 +47,9 @@ public class PowerSmelter extends PowerBlock{ @Override public void init(){ - if(useFlux){ - consumes.item(Items.sand).optional(true); - } - super.init(); - produces.set(result); + produces.set(output); } @Override @@ -76,7 +62,7 @@ public class PowerSmelter extends PowerBlock{ public void setStats(){ super.setStats(); - stats.add(BlockStat.outputItem, result); + stats.add(BlockStat.outputItem, output); stats.add(BlockStat.craftSpeed, 60f / craftTime, StatUnit.itemsSecond); stats.add(BlockStat.inputItemCapacity, itemCapacity, StatUnit.items); stats.add(BlockStat.outputItemCapacity, itemCapacity, StatUnit.items); @@ -87,8 +73,8 @@ public class PowerSmelter extends PowerBlock{ PowerSmelterEntity entity = tile.entity(); - if(entity.timer.get(timerDump, 5) && entity.items.has(result)){ - tryDump(tile, result); + if(entity.timer.get(timerDump, 5) && entity.items.has(output)){ + tryDump(tile, output); } //heat it up if there's enough power @@ -107,46 +93,21 @@ public class PowerSmelter extends PowerBlock{ return; } - float baseSmeltSpeed = 1f; - for(Item item : content.items()){ - if(item.fluxiness >= minFlux && tile.entity.items.get(item) > 0){ - baseSmeltSpeed = fluxSpeedMult; - break; - } - } - entity.craftTime += entity.delta() * entity.power.satisfaction; - if(entity.items.get(result) >= itemCapacity //output full + if(entity.items.get(output) >= itemCapacity //output full || entity.heat <= minHeat //not burning - || entity.craftTime < craftTime*baseSmeltSpeed){ //not yet time + || entity.craftTime < craftTime){ //not yet time return; } entity.craftTime = 0f; - boolean consumeInputs = true; - - if(useFlux){ - //remove flux materials if present - for(Item item : content.items()){ - if(item.fluxiness >= minFlux && tile.entity.items.get(item) >= fluxNeeded){ - tile.entity.items.remove(item, fluxNeeded); - - //chance of not consuming inputs if flux material present - consumeInputs = !Mathf.chance(item.fluxiness * baseFluxChance); - break; - } - } + for(ItemStack item : consumes.items()){ + entity.items.remove(item.item, item.amount); } - if(consumeInputs){ - for(ItemStack item : consumes.items()){ - entity.items.remove(item.item, item.amount); - } - } - - offloadNear(tile, result); + offloadNear(tile, output); Effects.effect(craftEffect, flameColor, tile.drawx(), tile.drawy()); } @@ -159,8 +120,7 @@ public class PowerSmelter extends PowerBlock{ } } - return useFlux && item.fluxiness >= minFlux && tile.entity.items.get(item) < itemCapacity; - + return false; } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Pump.java b/core/src/io/anuke/mindustry/world/blocks/production/Pump.java index 75c168cc74..e788e380fb 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Pump.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Pump.java @@ -19,10 +19,8 @@ public class Pump extends LiquidBlock{ protected final int timerContentCheck = timers++; - /**Pump amount per tile this block is on.*/ + /**Pump amount, total.*/ protected float pumpAmount = 1f; - /**Maximum liquid tier this pump can use.*/ - protected int tier = 0; public Pump(String name){ super(name); @@ -95,7 +93,7 @@ public class Pump extends LiquidBlock{ } if(tile.entity.cons.valid() && liquidDrop != null){ - float maxPump = Math.min(liquidCapacity - tile.entity.liquids.total(), tiles * pumpAmount * tile.entity.delta()); + float maxPump = Math.min(liquidCapacity - tile.entity.liquids.total(), tiles * pumpAmount * tile.entity.delta() / size / size); if(hasPower){ maxPump *= tile.entity.power.satisfaction; // Produce slower if not at full power } @@ -115,7 +113,7 @@ public class Pump extends LiquidBlock{ } protected boolean isValid(Tile tile){ - return tile != null && tile.floor().liquidDrop != null && tier >= tile.floor().liquidDrop.tier; + return tile != null && tile.floor().liquidDrop != null; } } diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Separator.java b/core/src/io/anuke/mindustry/world/blocks/production/Separator.java index d1cdccf51a..160a5cb240 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Separator.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Separator.java @@ -6,7 +6,7 @@ import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.world.Block; @@ -32,8 +32,6 @@ public class Separator extends Block{ protected Color color = Color.valueOf("858585"); protected TextureRegion liquidRegion; - protected boolean offloading = false; - public Separator(String name){ super(name); update = true; @@ -113,9 +111,7 @@ public class Separator extends Block{ } if(item != null && entity.items.get(item) < itemCapacity){ - offloading = true; offloadNear(tile, item); - offloading = false; } } @@ -124,11 +120,6 @@ public class Separator extends Block{ } } - @Override - public boolean canDump(Tile tile, Tile to, Item item){ - return offloading || item != consumes.item(); - } - @Override public TileEntity newEntity(){ return new GenericCrafterEntity(); diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java b/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java index 68be2ba020..c73732cace 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Smelter.java @@ -1,8 +1,14 @@ package io.anuke.mindustry.world.blocks.production; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.Fill; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.world.Block; @@ -11,25 +17,12 @@ import io.anuke.mindustry.world.consumers.ConsumeItem; import io.anuke.mindustry.world.consumers.ConsumeItems; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; -import io.anuke.arc.util.Time; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Fill; -import io.anuke.arc.math.Mathf; - -import static io.anuke.mindustry.Vars.*; public class Smelter extends Block{ protected final int timerDump = timers++; protected Item result; - protected float minFlux = 0.2f; - protected float fluxSpeedMult = 0.75f; - protected float baseFluxChance = 0.25f; - protected boolean useFlux = false; - protected float craftTime = 20f; protected float burnDuration = 50f; protected Effect craftEffect = Fx.smelt, burnEffect = Fx.fuelburn; @@ -49,8 +42,6 @@ public class Smelter extends Block{ public void setStats(){ super.setStats(); - //TODO - //stats.add(BlockStat.inputFuel, fuel); stats.add(BlockStat.fuelBurnTime, burnDuration / 60f, StatUnit.seconds); stats.add(BlockStat.outputItem, result); stats.add(BlockStat.craftSpeed, 60f / craftTime, StatUnit.itemsSecond); @@ -61,13 +52,6 @@ public class Smelter extends Block{ @Override public void init(){ super.init(); - - for(ItemStack item : consumes.items()){ - if(item.item.fluxiness >= minFlux && useFlux){ - throw new IllegalArgumentException("'" + name + "' has input item '" + item.item.name + "', which is a flux, when useFlux is enabled. To prevent ambiguous item use, either remove this flux item from the inputs, or set useFlux to false."); - } - } - produces.set(result); } @@ -99,43 +83,17 @@ public class Smelter extends Block{ return; } - float baseSmeltSpeed = 1f; - for(Item item : content.items()){ - if(item.fluxiness >= minFlux && tile.entity.items.get(item) > 0){ - baseSmeltSpeed = fluxSpeedMult; - break; - } - } - entity.craftTime += entity.delta(); if(entity.items.get(result) >= itemCapacity //output full || entity.burnTime <= 0 //not burning - || entity.craftTime < craftTime*baseSmeltSpeed){ //not yet time + || entity.craftTime < craftTime){ //not yet time return; } entity.craftTime = 0f; - - boolean consumeInputs = true; - - if(useFlux){ - //remove flux materials if present - for(Item item : content.items()){ - if(item.fluxiness >= minFlux && tile.entity.items.get(item) > 0){ - tile.entity.items.remove(item, 1); - - //chance of not consuming inputs if flux material present - consumeInputs = !Mathf.chance(item.fluxiness * baseFluxChance); - break; - } - } - } - - if(consumeInputs){ - for(ItemStack item : consumes.items()){ - entity.items.remove(item.item, item.amount); - } + for(ItemStack item : consumes.items()){ + entity.items.remove(item.item, item.amount); } offloadNear(tile, result); @@ -153,8 +111,7 @@ public class Smelter extends Block{ } } - return (isInput && tile.entity.items.get(item) < itemCapacity) || (item == consumes.item() && tile.entity.items.get(consumes.item()) < itemCapacity) || - (useFlux && item.fluxiness >= minFlux && tile.entity.items.get(item) < itemCapacity); + return (isInput && tile.entity.items.get(item) < itemCapacity) || (item == consumes.item() && tile.entity.items.get(consumes.item()) < itemCapacity); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/production/SolidPump.java b/core/src/io/anuke/mindustry/world/blocks/production/SolidPump.java index 89d0635583..226933c355 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/SolidPump.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/SolidPump.java @@ -4,12 +4,12 @@ import io.anuke.arc.Core; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.mindustry.content.Liquids; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.math.Mathf; @@ -69,7 +69,7 @@ public class SolidPump extends Pump{ if(isMultiblock()){ for(Tile other : tile.getLinkedTiles(tempTiles)){ if(isValid(other)){ - fraction += 1f / size; + fraction += 1f / (size * size); } } }else{ diff --git a/core/src/io/anuke/mindustry/world/blocks/sandbox/LiquidSource.java b/core/src/io/anuke/mindustry/world/blocks/sandbox/LiquidSource.java index 26cb7fd389..86d189c639 100644 --- a/core/src/io/anuke/mindustry/world/blocks/sandbox/LiquidSource.java +++ b/core/src/io/anuke/mindustry/world/blocks/sandbox/LiquidSource.java @@ -4,22 +4,24 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.collection.Array; import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.scene.style.TextureRegionDrawable; import io.anuke.arc.scene.ui.ButtonGroup; import io.anuke.arc.scene.ui.ImageButton; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.gen.Call; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.content; +import static io.anuke.mindustry.Vars.control; public class LiquidSource extends Block{ @@ -33,6 +35,13 @@ public class LiquidSource extends Block{ outputsLiquid = true; } + @Override + public void setBars(){ + super.setBars(); + + bars.remove("liquid"); + } + @Override public void update(Tile tile){ LiquidSourceEntity entity = tile.entity(); @@ -62,11 +71,12 @@ public class LiquidSource extends Block{ Table cont = new Table(); for(int i = 0; i < items.size; i++){ - if(!data.isUnlocked(items.get(i))) continue; - final int f = i; - ImageButton button = cont.addImageButton("liquid-icon-" + items.get(i).name, "clear-toggle", 24, - () -> Call.setLiquidSourceLiquid(null, tile, items.get(f))).size(38).group(group).get(); + ImageButton button = cont.addImageButton("clear", "clear-toggle", 24, () -> { + Call.setLiquidSourceLiquid(null, tile, items.get(f)); + control.input(0).frag.config.hideConfig(); + }).size(38).group(group).get(); + button.getStyle().imageUp = new TextureRegionDrawable(items.get(i).iconRegion); button.setChecked(entity.source.id == f); if(i % 4 == 3){ diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java index a62b7e30f3..7bb4946473 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -4,31 +4,30 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; import io.anuke.arc.collection.EnumSet; -import io.anuke.arc.entities.Effects; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.traits.SpawnerTrait; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockFlag; import static io.anuke.mindustry.Vars.*; -public class CoreBlock extends LaunchPad{ +public class CoreBlock extends StorageBlock{ protected TextureRegion topRegion; - protected int launchThreshold; - protected int launchChunkSize; public CoreBlock(String name){ super(name); @@ -36,19 +35,18 @@ public class CoreBlock extends LaunchPad{ solid = true; update = true; hasItems = true; - size = 3; - flags = EnumSet.of(BlockFlag.resupplyPoint, BlockFlag.target); + flags = EnumSet.of(BlockFlag.target, BlockFlag.producer); } @Remote(called = Loc.server) - public static void onUnitRespawn(Tile tile, Unit player){ + public static void onUnitRespawn(Tile tile, Player player){ if(player == null || tile.entity == null) return; CoreEntity entity = tile.entity(); Effects.effect(Fx.spawn, entity); entity.progress = 0; - entity.currentUnit.onRespawn(tile); entity.currentUnit = player; + entity.currentUnit.onRespawn(tile); entity.currentUnit.heal(); entity.currentUnit.rotation = 90f; entity.currentUnit.applyImpulse(0, 8f); @@ -56,14 +54,12 @@ public class CoreBlock extends LaunchPad{ entity.currentUnit.add(); entity.currentUnit = null; - if(player instanceof Player){ - ((Player) player).endRespawning(); - } + player.endRespawning(); } @Override public int getMaximumAccepted(Tile tile, Item item){ - return itemCapacity * state.teams.get(tile.getTeam()).cores.size; + return item.type == ItemType.material ? itemCapacity * state.teams.get(tile.getTeam()).cores.size : 0; } @Override @@ -78,7 +74,7 @@ public class CoreBlock extends LaunchPad{ @Override public boolean canBreak(Tile tile){ - return state.teams.get(tile.getTeam()).cores.size > 1; + return false; } @Override @@ -109,9 +105,11 @@ public class CoreBlock extends LaunchPad{ Draw.rect(region, tile.drawx(), tile.drawy()); - Draw.alpha(entity.heat); - Draw.rect(topRegion, tile.drawx(), tile.drawy()); - Draw.color(); + if(Core.atlas.isFound(topRegion)){ + Draw.alpha(entity.heat); + Draw.rect(topRegion, tile.drawx(), tile.drawy()); + Draw.color(); + } if(entity.currentUnit != null){ Unit player = entity.currentUnit; @@ -120,14 +118,14 @@ public class CoreBlock extends LaunchPad{ Shaders.build.region = region; Shaders.build.progress = entity.progress; - Shaders.build.color.set(Palette.accent); + Shaders.build.color.set(Pal.accent); Shaders.build.time = -entity.time / 10f; Draw.shader(Shaders.build, true); Draw.rect(region, tile.drawx(), tile.drawy()); Draw.shader(); - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.lineAngleCenter( tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 3f * size), @@ -148,20 +146,12 @@ public class CoreBlock extends LaunchPad{ public void update(Tile tile){ CoreEntity entity = tile.entity(); - for(Item item : Vars.content.items()){ - if(entity.items.get(item) >= launchThreshold + launchChunkSize && entity.timer.get(timerLaunch, launchTime)){ - //TODO play animation of some sort - Effects.effect(Fx.dooropenlarge, tile); - data.addItem(item, launchChunkSize); - entity.items.remove(item, launchChunkSize); - } - } - if(entity.currentUnit != null){ - if(!entity.currentUnit.isDead()){ + if(!entity.currentUnit.isDead() || !entity.currentUnit.isAdded()){ entity.currentUnit = null; return; } + entity.heat = Mathf.lerpDelta(entity.heat, 1f, 0.1f); entity.time += entity.delta(); entity.progress += 1f / state.rules.respawnTime * entity.delta(); @@ -169,6 +159,8 @@ public class CoreBlock extends LaunchPad{ if(entity.progress >= 1f){ Call.onUnitRespawn(tile, entity.currentUnit); } + }else{ + entity.heat = Mathf.lerpDelta(entity.heat, 0f, 0.1f); } } @@ -178,23 +170,18 @@ public class CoreBlock extends LaunchPad{ } public class CoreEntity extends TileEntity implements SpawnerTrait{ - public Unit currentUnit; + public Player currentUnit; float progress; float time; float heat; @Override - public void updateSpawning(Unit unit){ + public void updateSpawning(Player unit){ if(!netServer.isWaitingForPlayers() && currentUnit == null){ currentUnit = unit; progress = 0f; unit.set(tile.drawx(), tile.drawy()); } } - - @Override - public float getSpawnProgress(){ - return progress; - } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java b/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java index 5647974149..94875bac5b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java @@ -1,14 +1,15 @@ package io.anuke.mindustry.world.blocks.storage; -import io.anuke.arc.entities.Effects; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.world.Tile; import static io.anuke.mindustry.Vars.data; +import static io.anuke.mindustry.Vars.world; public class LaunchPad extends StorageBlock{ protected final int timerLaunch = timers++; @@ -31,7 +32,7 @@ public class LaunchPad extends StorageBlock{ public void update(Tile tile){ TileEntity entity = tile.entity; - if(entity.cons.valid()){ + if(entity.cons.valid() && world.isZone()){ for(Item item : Vars.content.items()){ if(entity.items.get(item) >= itemCapacity && entity.timer.get(timerLaunch, launchTime)){ //TODO play animation of some sort diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java index 08148c65e6..58739c63c5 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.world.blocks.storage; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/SortedUnloader.java b/core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java similarity index 89% rename from core/src/io/anuke/mindustry/world/blocks/storage/SortedUnloader.java rename to core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java index 90b0ca917f..3707752cf9 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/SortedUnloader.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java @@ -1,18 +1,18 @@ package io.anuke.mindustry.world.blocks.storage; -import io.anuke.arc.Core; -import io.anuke.arc.graphics.Color; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.SelectionTrait; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.scene.ui.layout.Table; import java.io.DataInput; import java.io.DataOutput; @@ -20,13 +20,13 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.content; -public class SortedUnloader extends Block implements SelectionTrait{ +public class Unloader extends Block implements SelectionTrait{ protected float speed = 1f; protected final int timerUnload = timers++; private static Item lastItem; - public SortedUnloader(String name){ + public Unloader(String name){ super(name); update = true; solid = true; @@ -59,7 +59,7 @@ public class SortedUnloader extends Block implements SelectionTrait{ if(tile.entity.timer.get(timerUnload, speed) && tile.entity.items.total() == 0){ for(Tile other : tile.entity.proximity()){ - if(other.getTeam() == tile.getTeam() && other.block() instanceof StorageBlock && entity.items.total() == 0 && + if(other.interactable(tile.getTeam()) && other.block() instanceof StorageBlock && entity.items.total() == 0 && ((entity.sortItem == null && other.entity.items.total() > 0) || ((StorageBlock) other.block()).hasItem(other, entity.sortItem))){ offloadNear(tile, ((StorageBlock) other.block()).removeItem(other, entity.sortItem)); } @@ -77,7 +77,7 @@ public class SortedUnloader extends Block implements SelectionTrait{ SortedUnloaderEntity entity = tile.entity(); - Draw.color(entity.sortItem == null ? Color.WHITE : entity.sortItem.color); + Draw.color(entity.sortItem == null ? Color.CLEAR : entity.sortItem.color); Draw.rect("blank", tile.worldx(), tile.worldy(), 2f, 2f); Draw.color(); } diff --git a/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java b/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java index 38257657d4..92a8e9212c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/MechPad.java @@ -3,7 +3,6 @@ package io.anuke.mindustry.world.blocks.units; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.graphics.g2d.TextureRegion; @@ -11,15 +10,15 @@ import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.content.Mechs; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.SpawnerTrait; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.type.Mech; import io.anuke.mindustry.world.Block; @@ -58,7 +57,7 @@ public class MechPad extends Block{ @Remote(targets = Loc.both, called = Loc.server) public static void onMechFactoryTap(Player player, Tile tile){ - if(player == null || !checkValidTap(tile, player) || !(tile.block() instanceof MechPad)) return; + if(player == null || !(tile.block() instanceof MechPad) || !checkValidTap(tile, player)) return; MechFactoryEntity entity = tile.entity(); MechPad pad = (MechPad)tile.block(); @@ -82,7 +81,12 @@ public class MechPad extends Block{ Mech result = ((MechPad) tile.block()).mech; if(entity.player.mech == result){ - entity.player.mech = (entity.player.isMobile ? Mechs.starterMobile : Mechs.starterDesktop); + Mech target = (entity.player.isMobile ? Mechs.starterMobile : Mechs.starterDesktop); + if(entity.player.mech == target){ + entity.player.mech = (entity.player.isMobile ? Mechs.starterDesktop : Mechs.starterMobile); + }else{ + entity.player.mech = target; + } }else{ entity.player.mech = result; } @@ -92,7 +96,7 @@ public class MechPad extends Block{ entity.player.endRespawning(); entity.open = true; entity.player.setDead(false); - entity.player.inventory.clear(); + entity.player.clearItem(); entity.player = null; } @@ -104,7 +108,7 @@ public class MechPad extends Block{ @Override public void drawSelect(Tile tile){ - Draw.color(Palette.accent); + Draw.color(Pal.accent); for(int i = 0; i < 4; i ++){ float length = tilesize * size/2f + 3 + Mathf.absin(Time.time(), 5f, 2f); Draw.rect("transfer-arrow", tile.drawx() + Geometry.d4[i].x * length, tile.drawy() + Geometry.d4[i].y * length, (i+2) * 90); @@ -144,20 +148,19 @@ public class MechPad extends Block{ TextureRegion region = mech.iconRegion; if(entity.player.mech == mech){ - region = (entity.player.isMobile ? Mechs.starterMobile : Mechs.starterDesktop).iconRegion; + region = (entity.player.mech == Mechs.starterDesktop ? Mechs.starterMobile : Mechs.starterDesktop).iconRegion; } Shaders.build.region = region; Shaders.build.progress = entity.progress; - Shaders.build.time = -entity.time / 4f; - Shaders.build.color.set(Palette.accent); + Shaders.build.time = -entity.time / 5f; + Shaders.build.color.set(Pal.accent); - Draw.shader(Shaders.build, false); - Shaders.build.apply(); + Draw.shader(Shaders.build); Draw.rect(region, tile.drawx(), tile.drawy()); Draw.shader(); - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.lineAngleCenter( tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 3f * size), @@ -212,26 +215,18 @@ public class MechPad extends Block{ boolean open; @Override - public void updateSpawning(Unit unit){ - if(!(unit instanceof Player)) - throw new IllegalArgumentException("Mech factories only accept player respawners."); - + public void updateSpawning(Player unit){ if(player == null){ progress = 0f; - player = (Player) unit; + player = unit; player.rotation = 90f; player.baseRotation = 90f; - player.set(x, y); + player.setNet(x, y); player.beginRespawning(this); } } - @Override - public float getSpawnProgress(){ - return progress; - } - @Override public void write(DataOutput stream) throws IOException{ stream.writeFloat(progress); diff --git a/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java b/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java deleted file mode 100644 index de7753e644..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java +++ /dev/null @@ -1,339 +0,0 @@ -package io.anuke.mindustry.world.blocks.units; - -import io.anuke.annotations.Annotations.Loc; -import io.anuke.annotations.Annotations.Remote; -import io.anuke.arc.Core; -import io.anuke.arc.entities.Effects; -import io.anuke.arc.entities.Effects.Effect; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.util.Time; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; -import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.entities.traits.SpawnerTrait; -import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.graphics.Shaders; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import static io.anuke.mindustry.Vars.tilesize; -import static io.anuke.mindustry.Vars.world; - -//TODO re-implement properly -public class Reconstructor extends Block{ - protected float departTime = 30f; - protected float arriveTime = 40f; - /** Stores the percentage of buffered power to be used upon teleporting. */ - protected float powerPerTeleport = 0.5f; - protected Effect arriveEffect = Fx.spawn; - protected TextureRegion openRegion; - - public Reconstructor(String name){ - super(name); - update = true; - solidifes = true; - hasPower = true; - configurable = true; - consumes.powerBuffered(30f); - } - - protected static boolean checkValidTap(Tile tile, ReconstructorEntity entity, Player player){ - return validLink(tile, entity.link) && - Math.abs(player.x - tile.drawx()) <= tile.block().size * tilesize / 2f && - Math.abs(player.y - tile.drawy()) <= tile.block().size * tilesize / 2f && - entity.current == null && entity.power.satisfaction >= ((Reconstructor) tile.block()).powerPerTeleport; - } - - protected static boolean validLink(Tile tile, int position){ - Tile other = world.tile(position); - return other != tile && other != null && other.block() instanceof Reconstructor; - } - - protected static void unlink(ReconstructorEntity entity){ - Tile other = world.tile(entity.link); - - if(other != null && other.block() instanceof Reconstructor){ - ReconstructorEntity oe = other.entity(); - if(oe.link == entity.tile.pos()){ - oe.link = -1; - } - } - - entity.link = -1; - } - - @Remote(targets = Loc.both, called = Loc.server, forward = true) - public static void reconstructPlayer(Player player, Tile tile){ - ReconstructorEntity entity = tile.entity(); - - if(!checkValidTap(tile, entity, player) || entity.power.satisfaction < ((Reconstructor) tile.block()).powerPerTeleport) - return; - - entity.departing = true; - entity.current = player; - entity.solid = false; - entity.power.satisfaction -= Math.min(entity.power.satisfaction, ((Reconstructor) tile.block()).powerPerTeleport); - entity.updateTime = 1f; - entity.set(tile.drawx(), tile.drawy()); - player.rotation = 90f; - player.baseRotation = 90f; - player.setDead(true); - // player.setRespawning(true); - //player.setRespawning(); - } - - @Remote(targets = Loc.both, called = Loc.server, forward = true) - public static void linkReconstructor(Player player, Tile tile, Tile other){ - //just in case the client has invalid data - if(!(tile.entity instanceof ReconstructorEntity) || !(other.entity instanceof ReconstructorEntity)) return; - - ReconstructorEntity entity = tile.entity(); - ReconstructorEntity oe = other.entity(); - - unlink(entity); - unlink(oe); - - entity.link = other.pos(); - oe.link = tile.pos(); - } - - @Remote(targets = Loc.both, called = Loc.server, forward = true) - public static void unlinkReconstructor(Player player, Tile tile, Tile other){ - //just in case the client has invalid data - if(!(tile.entity instanceof ReconstructorEntity) || !(other.entity instanceof ReconstructorEntity)) return; - - ReconstructorEntity entity = tile.entity(); - ReconstructorEntity oe = other.entity(); - - //called in main thread to prevent issues - unlink(entity); - unlink(oe); - } - - @Override - public void load(){ - super.load(); - openRegion = Core.atlas.find(name + "-open"); - } - - @Override - public boolean isSolidFor(Tile tile){ - ReconstructorEntity entity = tile.entity(); - - return entity.solid; - } - - @Override - public void drawConfigure(Tile tile){ - super.drawConfigure(tile); - - ReconstructorEntity entity = tile.entity(); - - if(validLink(tile, entity.link)){ - Tile target = world.tile(entity.link); - - Draw.color(Palette.place); - Lines.square(target.drawx(), target.drawy(), - target.block().size * tilesize / 2f + 1f); - Draw.reset(); - } - - Draw.color(Palette.accent); - Draw.color(); - } - - @Override - public boolean onConfigureTileTapped(Tile tile, Tile other){ - if(tile == other) return false; - - ReconstructorEntity entity = tile.entity(); - - if(entity.link == other.pos()){ - Call.unlinkReconstructor(null, tile, other); - return false; - }else if(other.block() instanceof Reconstructor){ - Call.linkReconstructor(null, tile, other); - return false; - } - - return true; - } - - @Override - public boolean shouldShowConfigure(Tile tile, Player player){ - ReconstructorEntity entity = tile.entity(); - return !checkValidTap(tile, entity, player); - } - - @Override - public boolean shouldHideConfigure(Tile tile, Player player){ - ReconstructorEntity entity = tile.entity(); - return checkValidTap(tile, entity, player); - } - - @Override - public void draw(Tile tile){ - ReconstructorEntity entity = tile.entity(); - - if(entity.solid){ - Draw.rect(region, tile.drawx(), tile.drawy()); - }else{ - Draw.rect(openRegion, tile.drawx(), tile.drawy()); - } - - if(entity.current != null){ - float progress = entity.departing ? entity.updateTime : (1f - entity.updateTime); - - //Player player = entity.current; - - TextureRegion region = entity.current.getIconRegion(); - - Shaders.build.region = region; - Shaders.build.progress = progress; - Shaders.build.color.set(Palette.accent); - Shaders.build.time = -entity.time / 10f; - - Draw.shader(Shaders.build, false); - Shaders.build.apply(); - Draw.rect(region, tile.drawx(), tile.drawy()); - Draw.shader(); - - Draw.color(Palette.accent); - - Lines.lineAngleCenter( - tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 3f * size), - tile.drawy(), - 90, - size * Vars.tilesize / 2f); - - Draw.reset(); - } - } - - @Override - public void update(Tile tile){ - ReconstructorEntity entity = tile.entity(); - - boolean stayOpen = false; - - if(entity.current != null){ - entity.time += Time.delta(); - - entity.solid = true; - - if(entity.departing){ - //force respawn if there's suddenly nothing to link to - if(!validLink(tile, entity.link)){ - //entity.current.setRespawning(false); - return; - } - - ReconstructorEntity other = world.tile(entity.link).entity(); - - entity.updateTime -= Time.delta() / departTime; - if(entity.updateTime <= 0f){ - //no power? death. - if(other.power.satisfaction < powerPerTeleport){ - entity.current.setDead(true); - //entity.current.setRespawning(false); - entity.current = null; - return; - } - other.power.satisfaction -= Math.min(other.power.satisfaction, powerPerTeleport); - other.current = entity.current; - other.departing = false; - other.current.set(other.x, other.y); - other.updateTime = 1f; - entity.current = null; - } - }else{ //else, arriving - entity.updateTime -= Time.delta() / arriveTime; - - if(entity.updateTime <= 0f){ - entity.solid = false; - entity.current.setDead(false); - - Effects.effect(arriveEffect, entity.current); - - entity.current = null; - } - } - - }else{ - - if(validLink(tile, entity.link)){ - Tile other = world.tile(entity.link); - if(other.entity.power.satisfaction >= powerPerTeleport && Units.anyEntities(tile, 4f, unit -> unit.getTeam() == entity.getTeam() && unit instanceof Player) && - entity.power.satisfaction >= powerPerTeleport){ - entity.solid = false; - stayOpen = true; - } - } - - if(!stayOpen && !entity.solid && !Units.anyEntities(tile)){ - entity.solid = true; - } - } - } - - @Override - public void tapped(Tile tile, Player player){ - ReconstructorEntity entity = tile.entity(); - - if(!checkValidTap(tile, entity, player)) return; - - Call.reconstructPlayer(player, tile); - } - - @Override - public void transformLinks(Tile tile, int oldWidth, int oldHeight, int newWidth, int newHeight, int shiftX, int shiftY){ - super.transformLinks(tile, oldWidth, oldHeight, newWidth, newHeight, shiftX, shiftY); - - ReconstructorEntity entity = tile.entity(); - entity.link = world.transform(entity.link, oldWidth, oldHeight, newWidth, shiftX, shiftY); - } - - @Override - public TileEntity newEntity(){ - return new ReconstructorEntity(); - } - - public class ReconstructorEntity extends TileEntity implements SpawnerTrait{ - Unit current; - float updateTime; - float time; - int link; - boolean solid = true, departing; - - @Override - public void updateSpawning(Unit unit){ - - } - - @Override - public float getSpawnProgress(){ - return 0; - } - - @Override - public void write(DataOutput stream) throws IOException{ - stream.writeInt(link); - } - - @Override - public void read(DataInput stream) throws IOException{ - link = stream.readInt(); - } - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/units/RepairPoint.java b/core/src/io/anuke/mindustry/world/blocks/units/RepairPoint.java index f213ebf15a..7b3beb34c6 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/RepairPoint.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/RepairPoint.java @@ -10,11 +10,11 @@ import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.util.Time; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Shapes; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -33,7 +33,7 @@ public class RepairPoint extends Block{ protected float powerPerEvent = 0.06f; protected ConsumePower consumePower; - protected TextureRegion topRegion; + protected TextureRegion baseRegion; public RepairPoint(String name){ super(name); @@ -44,13 +44,14 @@ public class RepairPoint extends Block{ layer2 = Layer.laser; hasPower = true; consumePower = consumes.powerBuffered(20f); + outlineIcon = true; } @Override public void load(){ super.load(); - topRegion = Core.atlas.find(name + "-turret"); + baseRegion = Core.atlas.find(name + "-base"); } @Override @@ -61,16 +62,21 @@ public class RepairPoint extends Block{ @Override public void drawSelect(Tile tile){ - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.dashCircle(tile.drawx(), tile.drawy(), repairRadius); Draw.color(); } + @Override + public void draw(Tile tile){ + Draw.rect(baseRegion, tile.drawx(), tile.drawy()); + } + @Override public void drawLayer(Tile tile){ RepairPointEntity entity = tile.entity(); - Draw.rect(topRegion, tile.drawx(), tile.drawy(), entity.rotation - 90); + Draw.rect(region, tile.drawx(), tile.drawy(), entity.rotation - 90); } @Override @@ -90,6 +96,11 @@ public class RepairPoint extends Block{ } } + @Override + public TextureRegion[] generateIcons(){ + return new TextureRegion[]{Core.atlas.find(name + "-base"), Core.atlas.find(name)}; + } + @Override public void update(Tile tile){ RepairPointEntity entity = tile.entity(); diff --git a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java b/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java index e8d6a7f1e3..d831e44595 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java @@ -4,22 +4,24 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; import io.anuke.arc.collection.EnumSet; -import io.anuke.arc.entities.Effects; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.units.BaseUnit; -import io.anuke.mindustry.entities.units.UnitType; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.type.UnitType; +import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.consumers.ConsumeItems; @@ -41,6 +43,7 @@ public class UnitFactory extends Block{ protected float produceTime = 1000f; protected float launchVelocity = 0f; protected TextureRegion topRegion; + protected int maxSpawn = 2; public UnitFactory(String name){ super(name); @@ -48,7 +51,7 @@ public class UnitFactory extends Block{ hasPower = true; hasItems = true; solid = false; - flags = EnumSet.of(BlockFlag.producer, BlockFlag.target); + flags = EnumSet.of(BlockFlag.producer); consumes.require(ConsumeItems.class); } @@ -61,6 +64,7 @@ public class UnitFactory extends Block{ UnitFactory factory = (UnitFactory) tile.block(); entity.buildTime = 0f; + entity.spawned ++; Effects.shake(2f, 3f, entity); Effects.effect(Fx.producesmoke, tile.drawx(), tile.drawy()); @@ -81,6 +85,13 @@ public class UnitFactory extends Block{ topRegion = Core.atlas.find(name + "-top"); } + @Override + public void setBars(){ + super.setBars(); + bars.add("progress", entity -> new Bar("blocks.progress", Pal.ammo, () -> ((UnitFactoryEntity)entity).buildTime / produceTime)); + bars.add("spawned", entity -> new Bar(() -> Core.bundle.format("blocks.spawned", ((UnitFactoryEntity)entity).spawned, maxSpawn), () -> Pal.command, () -> (float)((UnitFactoryEntity)entity).spawned / maxSpawn)); + } + @Override public boolean outputsItems(){ return false; @@ -91,6 +102,13 @@ public class UnitFactory extends Block{ super.setStats(); stats.add(BlockStat.craftSpeed, produceTime / 60f, StatUnit.seconds); + stats.add(BlockStat.maxUnits, maxSpawn, StatUnit.none); + } + + @Override + public void unitRemoved(Tile tile, Unit unit){ + UnitFactoryEntity entity = tile.entity(); + entity.spawned --; } @Override @@ -107,16 +125,15 @@ public class UnitFactory extends Block{ Shaders.build.region = region; Shaders.build.progress = entity.buildTime / produceTime; - Shaders.build.color.set(Palette.accent); + Shaders.build.color.set(Pal.accent); Shaders.build.color.a = entity.speedScl; Shaders.build.time = -entity.time / 10f; - Draw.shader(Shaders.build, false); - Shaders.build.apply(); + Draw.shader(Shaders.build); Draw.rect(region, tile.drawx(), tile.drawy()); Draw.shader(); - Draw.color(Palette.accent); + Draw.color(Pal.accent); Draw.alpha(entity.speedScl); Lines.lineAngleCenter( @@ -134,7 +151,9 @@ public class UnitFactory extends Block{ public void update(Tile tile){ UnitFactoryEntity entity = tile.entity(); - entity.time += entity.delta() * entity.speedScl; + if(entity.spawned >= maxSpawn){ + return; + } if(tile.isEnemyCheat()){ entity.warmup += entity.delta(); @@ -142,9 +161,8 @@ public class UnitFactory extends Block{ if(!tile.isEnemyCheat()){ //player-made spawners have default behavior - if(hasRequirements(entity.items, entity.buildTime / produceTime) && entity.cons.valid()){ - + entity.time += entity.delta() * entity.speedScl; entity.buildTime += entity.delta() * entity.power.satisfaction; entity.speedScl = Mathf.lerpDelta(entity.speedScl, 1f, 0.05f); }else{ @@ -153,6 +171,7 @@ public class UnitFactory extends Block{ //check if grace period had passed }else if(entity.warmup > produceTime*gracePeriodMultiplier){ float speedMultiplier = Math.min(0.1f + (entity.warmup - produceTime * gracePeriodMultiplier) / speedupTime, maxSpeedup); + entity.time += entity.delta() * entity.speedScl; //otherwise, it's an enemy, cheat by not requiring resources entity.buildTime += entity.delta() * speedMultiplier; entity.speedScl = Mathf.lerpDelta(entity.speedScl, 1f, 0.05f); @@ -197,6 +216,12 @@ public class UnitFactory extends Block{ return new UnitFactoryEntity(); } + @Override + public boolean canProduce(Tile tile){ + UnitFactoryEntity entity = tile.entity(); + return entity.spawned < maxSpawn; + } + protected boolean hasRequirements(ItemModule inv, float fraction){ for(ItemStack stack : consumes.items()){ if(!inv.has(stack.item, (int) (fraction * stack.amount))){ @@ -211,17 +236,20 @@ public class UnitFactory extends Block{ public float time; public float speedScl; public float warmup; //only for enemy spawners + public int spawned; @Override public void write(DataOutput stream) throws IOException{ stream.writeFloat(buildTime); stream.writeFloat(warmup); + stream.writeInt(spawned); } @Override public void read(DataInput stream) throws IOException{ buildTime = stream.readFloat(); warmup = stream.readFloat(); + spawned = stream.readInt(); } } } diff --git a/core/src/io/anuke/mindustry/world/consumers/Consume.java b/core/src/io/anuke/mindustry/world/consumers/Consume.java index 3902245284..1baea5fd3a 100644 --- a/core/src/io/anuke/mindustry/world/consumers/Consume.java +++ b/core/src/io/anuke/mindustry/world/consumers/Consume.java @@ -1,18 +1,15 @@ package io.anuke.mindustry.world.consumers; -import io.anuke.arc.graphics.Color; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.meta.BlockStats; -import io.anuke.arc.scene.ui.Tooltip; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.meta.BlockStats; -import static io.anuke.mindustry.Vars.mobile; - +/**An abstract class that defines a type of resource that a block can consume.*/ public abstract class Consume{ protected boolean optional; - protected boolean update = true; + protected boolean update = true, boost = false; public Consume optional(boolean optional){ this.optional = optional; @@ -24,6 +21,11 @@ public abstract class Consume{ return this; } + public Consume boost(boolean boost){ + this.boost = boost; + return this; + } + public boolean isOptional(){ return optional; } @@ -32,7 +34,8 @@ public abstract class Consume{ return update; } - public void build(Table table){ + public abstract void build(Tile tile, Table table);/*{ + Table t = new Table("flat"); t.margin(4); buildTooltip(t); @@ -41,12 +44,15 @@ public abstract class Consume{ table.table(out -> { out.addImage(getIcon()).size(10 * scale).color(Color.DARK_GRAY).padRight(-10 * scale).padBottom(-scale * 2); - out.addImage(getIcon()).size(10 * scale).color(Palette.accent); - out.addImage("icon-missing").size(10 * scale).color(Palette.remove).padLeft(-10 * scale); + out.addImage(getIcon()).size(10 * scale).color(Pal.accent); + out.addImage("icon-missing").size(10 * scale).color(Pal.remove).padLeft(-10 * scale); }).size(10 * scale).get().addListener(new Tooltip<>(t)); - } + }*/ - public abstract void buildTooltip(Table table); + /**Called when a consumption is triggered manually.*/ + public void trigger(Block block, TileEntity entity){ + + } public abstract String getIcon(); diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeItem.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeItem.java index 76e659759a..d6806db4c5 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeItem.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeItem.java @@ -1,13 +1,16 @@ package io.anuke.mindustry.world.consumers; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Item.Icon; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.ui.ItemImage; +import io.anuke.mindustry.ui.ReqImage; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.BlockStats; -import io.anuke.arc.scene.ui.layout.Table; public class ConsumeItem extends Consume{ private final Item item; @@ -32,8 +35,13 @@ public class ConsumeItem extends Consume{ } @Override - public void buildTooltip(Table table){ - table.add(new ItemImage(new ItemStack(item, amount))).size(8 * 4); + public void trigger(Block block, TileEntity entity){ + entity.items.remove(item, amount); + } + + @Override + public void build(Tile tile, Table table){ + table.add(new ReqImage(new ItemImage(item.icon(Icon.large), amount), () -> valid(tile.block(), tile.entity))).size(8*4); } @Override @@ -53,6 +61,6 @@ public class ConsumeItem extends Consume{ @Override public void display(BlockStats stats){ - stats.add(optional ? BlockStat.boostItem : BlockStat.inputItem, item); + stats.add(boost ? BlockStat.boostItem : BlockStat.inputItem, new ItemStack(item, amount)); } } diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeItemFilter.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeItemFilter.java index 155a54e6ec..597a4a7b77 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeItemFilter.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeItemFilter.java @@ -1,15 +1,21 @@ package io.anuke.mindustry.world.consumers; import io.anuke.arc.collection.Array; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.arc.function.Predicate; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Item.Icon; +import io.anuke.mindustry.ui.ItemImage; +import io.anuke.mindustry.ui.MultiReqImage; +import io.anuke.mindustry.ui.ReqImage; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.BlockStats; import io.anuke.mindustry.world.meta.values.ItemFilterValue; -import io.anuke.arc.function.Predicate; -import io.anuke.arc.scene.ui.layout.Table; -import static io.anuke.mindustry.Vars.*; + +import static io.anuke.mindustry.Vars.content; public class ConsumeItemFilter extends Consume{ private final Predicate filter; @@ -19,20 +25,12 @@ public class ConsumeItemFilter extends Consume{ } @Override - public void buildTooltip(Table table){ - Array list = new Array<>(); + public void build(Tile tile, Table table){ + Array list = content.items().select(filter); + MultiReqImage image = new MultiReqImage(); + list.each(item -> image.add(new ReqImage(new ItemImage(item.icon(Icon.large), 1), () -> tile.entity != null && tile.entity.items != null && tile.entity.items.has(item)))); - for(Item item : content.items()){ - if(filter.test(item)) list.add(item); - } - - for(int i = 0; i < list.size; i++){ - Item item = list.get(i); - table.addImage(item.region).size(8 * 4).padRight(2).padLeft(2); - if(i != list.size - 1){ - table.add("/"); - } - } + table.add(image).size(8*4); } @Override @@ -45,6 +43,17 @@ public class ConsumeItemFilter extends Consume{ } + @Override + public void trigger(Block block, TileEntity entity){ + for(int i = 0; i < content.items().size; i++){ + Item item = content.item(i); + if(entity.items != null && entity.items.has(item) && this.filter.test(item)){ + entity.items.remove(item, 1); + break; + } + } + } + @Override public boolean valid(Block block, TileEntity entity){ for(int i = 0; i < content.items().size; i++){ @@ -58,6 +67,6 @@ public class ConsumeItemFilter extends Consume{ @Override public void display(BlockStats stats){ - stats.add(optional ? BlockStat.boostItem : BlockStat.inputItem, new ItemFilterValue(filter)); + stats.add(boost ? BlockStat.boostItem : BlockStat.inputItem, new ItemFilterValue(filter)); } } diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeItems.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeItems.java index 8ba9fdbb64..517e29956d 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeItems.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeItems.java @@ -1,13 +1,16 @@ package io.anuke.mindustry.world.consumers; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.type.Item.Icon; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.ui.ItemImage; +import io.anuke.mindustry.ui.ReqImage; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.BlockStats; import io.anuke.mindustry.world.meta.values.ItemListValue; -import io.anuke.arc.scene.ui.layout.Table; public class ConsumeItems extends Consume{ private ItemStack[] items; @@ -21,9 +24,9 @@ public class ConsumeItems extends Consume{ } @Override - public void buildTooltip(Table table){ + public void build(Tile tile, Table table){ for(ItemStack stack : items){ - table.add(new ItemImage(stack)).size(8 * 4).padRight(5); + table.add(new ReqImage(new ItemImage(stack.item.icon(Icon.large), stack.amount), () -> tile.entity != null && tile.entity.items != null && tile.entity.items.has(stack.item, stack.amount))).size(8*4).padRight(5); } } @@ -37,6 +40,13 @@ public class ConsumeItems extends Consume{ } + @Override + public void trigger(Block block, TileEntity entity){ + for(ItemStack stack : items){ + entity.items.remove(stack); + } + } + @Override public boolean valid(Block block, TileEntity entity){ return entity.items != null && entity.items.has(items); @@ -44,6 +54,6 @@ public class ConsumeItems extends Consume{ @Override public void display(BlockStats stats){ - stats.add(optional ? BlockStat.boostItem : BlockStat.inputItems, new ItemListValue(items)); + stats.add(boost ? BlockStat.boostItem : BlockStat.inputItems, new ItemListValue(items)); } } diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquid.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquid.java index c5ee119a8f..3ebeae1509 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquid.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquid.java @@ -1,12 +1,14 @@ package io.anuke.mindustry.world.consumers; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.ui.ReqImage; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.BlockStats; import io.anuke.mindustry.world.meta.StatUnit; -import io.anuke.arc.scene.ui.layout.Table; public class ConsumeLiquid extends Consume{ protected final float use; @@ -26,8 +28,8 @@ public class ConsumeLiquid extends Consume{ } @Override - public void buildTooltip(Table table){ - table.addImage(liquid.getContentIcon()).size(8 * 3); + public void build(Tile tile, Table table){ + table.add(new ReqImage(liquid.getContentIcon(), () -> valid(tile.block(), tile.entity))).size(8*4); } @Override @@ -47,7 +49,7 @@ public class ConsumeLiquid extends Consume{ @Override public void display(BlockStats stats){ - if(!optional){ + if(!boost){ stats.add(BlockStat.liquidUse, use * 60f, StatUnit.liquidSecond); stats.add(BlockStat.inputLiquid, liquid); }else{ diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java index 9a663b4c6d..bb3accfefe 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java @@ -1,15 +1,18 @@ package io.anuke.mindustry.world.consumers; import io.anuke.arc.collection.Array; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.arc.function.Predicate; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.ui.MultiReqImage; +import io.anuke.mindustry.ui.ReqImage; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.BlockStats; import io.anuke.mindustry.world.meta.StatUnit; import io.anuke.mindustry.world.meta.values.LiquidFilterValue; -import io.anuke.arc.function.Predicate; -import io.anuke.arc.scene.ui.layout.Table; import static io.anuke.mindustry.Vars.content; @@ -29,20 +32,12 @@ public class ConsumeLiquidFilter extends Consume{ } @Override - public void buildTooltip(Table table){ - Array list = new Array<>(); + public void build(Tile tile, Table table){ + Array list = content.liquids().select(l -> !l.isHidden() && filter.test(l)); + MultiReqImage image = new MultiReqImage(); + list.each(liquid -> image.add(new ReqImage(liquid.getContentIcon(), () -> tile.entity != null && tile.entity.liquids != null && tile.entity.liquids.get(liquid) >= use(tile.block(), tile.entity)))); - for(Liquid item : content.liquids()){ - if(!item.isHidden() && filter.test(item)) list.add(item); - } - - for(int i = 0; i < list.size; i++){ - Liquid item = list.get(i); - table.addImage(item.getContentIcon()).size(8 * 3).padRight(2).padLeft(2).padTop(2).padBottom(2); - if(i != list.size - 1){ - table.add("/"); - } - } + table.add(image).size(8*4); } @Override @@ -57,12 +52,12 @@ public class ConsumeLiquidFilter extends Consume{ @Override public boolean valid(Block block, TileEntity entity){ - return entity.liquids != null && filter.test(entity.liquids.current()) && entity.liquids.currentAmount() >= use(block, entity); + return entity != null && entity.liquids != null && filter.test(entity.liquids.current()) && entity.liquids.currentAmount() >= use(block, entity); } @Override public void display(BlockStats stats){ - if(optional){ + if(boost){ stats.add(BlockStat.boostLiquid, new LiquidFilterValue(filter)); }else if(isFuel){ stats.add(BlockStat.inputLiquidFuel, new LiquidFilterValue(filter)); diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumePower.java b/core/src/io/anuke/mindustry/world/consumers/ConsumePower.java index 18b9d57c40..a88b09a929 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumePower.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumePower.java @@ -2,8 +2,9 @@ package io.anuke.mindustry.world.consumers; import io.anuke.arc.math.Mathf; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.BlockStats; import io.anuke.mindustry.world.meta.StatUnit; @@ -11,43 +12,21 @@ import io.anuke.mindustry.world.meta.StatUnit; /** Consumer class for blocks which consume power while being connected to a power graph. */ public class ConsumePower extends Consume{ /** The maximum amount of power which can be processed per tick. This might influence efficiency or load a buffer. */ - protected final float powerPerTick; - /** The minimum power satisfaction (fraction of powerPerTick) which must be achieved before the module may work. */ - public final float minimumSatisfaction; + public final float powerPerTick; /** The maximum power capacity in power units. */ public final float powerCapacity; /** True if the module can store power. */ public final boolean isBuffered; - protected ConsumePower(float powerPerTick, float minimumSatisfaction, float powerCapacity, boolean isBuffered){ + public ConsumePower(float powerPerTick, float powerCapacity, boolean isBuffered){ this.powerPerTick = powerPerTick; - this.minimumSatisfaction = minimumSatisfaction; this.powerCapacity = powerCapacity; this.isBuffered = isBuffered; } - /** - * Makes the owner consume powerPerTick each tick and disables it unless minimumSatisfaction (1.0 = 100%) of that power is being supplied. - * @param powerPerTick The maximum amount of power which is required per tick for 100% efficiency. - * @param minimumSatisfaction The percentage of powerPerTick which must be available for the module to work. - */ - public static ConsumePower consumePowerDirect(float powerPerTick, float minimumSatisfaction){ - return new ConsumePower(powerPerTick, minimumSatisfaction, 0.0f, false); - } - - /** - * Adds a power buffer to the owner which takes ticksToFill number of ticks to be filled. - * Note that this object does not remove power from the buffer. - * @param powerCapacity The maximum capacity in power units. - * @param ticksToFill The number of ticks it shall take to fill the buffer. - */ - public static ConsumePower consumePowerBuffered(float powerCapacity, float ticksToFill){ - return new ConsumePower(powerCapacity / ticksToFill, 0.0f, powerCapacity, true); - } - @Override - public void buildTooltip(Table table){ - // No tooltip for power + public void build(Tile tile, Table table){ + //No tooltip for power, for now } @Override @@ -65,14 +44,14 @@ public class ConsumePower extends Consume{ if(isBuffered){ return true; }else{ - return entity.power.satisfaction >= minimumSatisfaction; + return entity.power.satisfaction >= 0.9999f; } } @Override public void display(BlockStats stats){ if(isBuffered){ - stats.add(BlockStat.powerCapacity, powerCapacity, StatUnit.powerSecond); + stats.add(BlockStat.powerCapacity, powerCapacity, StatUnit.none); }else{ stats.add(BlockStat.powerUse, powerPerTick * 60f, StatUnit.powerSecond); } diff --git a/core/src/io/anuke/mindustry/world/consumers/Consumers.java b/core/src/io/anuke/mindustry/world/consumers/Consumers.java index f4ffaa27a8..0616e8ea80 100644 --- a/core/src/io/anuke/mindustry/world/consumers/Consumers.java +++ b/core/src/io/anuke/mindustry/world/consumers/Consumers.java @@ -36,22 +36,13 @@ public class Consumers{ return c; } - /** - * Creates a consumer which directly uses power without buffering it. The module will work while at least 50% of power is supplied. - * @param powerPerTick The amount of power which is required each tick for 100% efficiency. - * @return the created consumer object. - */ - public ConsumePower power(float powerPerTick){ - return power(powerPerTick, 0.5f); - } - /** * Creates a consumer which directly uses power without buffering it. The module will work while the available power is greater than or equal to the minimumSatisfaction percentage (0..1). * @param powerPerTick The amount of power which is required each tick for 100% efficiency. * @return the created consumer object. */ - public ConsumePower power(float powerPerTick, float minimumSatisfaction){ - ConsumePower c = ConsumePower.consumePowerDirect(powerPerTick, minimumSatisfaction); + public ConsumePower power(float powerPerTick){ + ConsumePower c = new ConsumePower(powerPerTick, 0.0f, false); add(c); return c; } @@ -62,7 +53,7 @@ public class Consumers{ * @param powerCapacity The maximum capacity in power units. */ public ConsumePower powerBuffered(float powerCapacity){ - return powerBuffered(powerCapacity, 1f); + return powerBuffered(powerCapacity, 60f * 3); } /** @@ -71,7 +62,7 @@ public class Consumers{ * @param ticksToFill The number of ticks it shall take to fill the buffer. */ public ConsumePower powerBuffered(float powerCapacity, float ticksToFill){ - ConsumePower c = ConsumePower.consumePowerBuffered(powerCapacity, ticksToFill); + ConsumePower c = new ConsumePower(powerCapacity / ticksToFill, powerCapacity, true); add(c); return c; } @@ -108,6 +99,10 @@ public class Consumers{ return get(ConsumeLiquid.class).get(); } + public float liquidAmount(){ + return get(ConsumeLiquid.class).use; + } + public Consume add(Consume consume){ map.put((consume instanceof ConsumePower ? ConsumePower.class : consume.getClass()), consume); return consume; diff --git a/core/src/io/anuke/mindustry/world/meta/BlockBars.java b/core/src/io/anuke/mindustry/world/meta/BlockBars.java new file mode 100644 index 0000000000..c47211181f --- /dev/null +++ b/core/src/io/anuke/mindustry/world/meta/BlockBars.java @@ -0,0 +1,23 @@ +package io.anuke.mindustry.world.meta; + +import io.anuke.arc.collection.OrderedMap; +import io.anuke.arc.function.Function; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.ui.Bar; + +public class BlockBars{ + private OrderedMap> bars = new OrderedMap<>(); + + public void add(String name,Function sup){ + bars.put(name, sup); + } + + public void remove(String name){ + if(!bars.containsKey(name)) throw new RuntimeException("No bar with name '" + name + "' found; current bars: " + bars.keys().toArray()); + bars.remove(name); + } + + public Iterable> list(){ + return bars.values(); + } +} diff --git a/core/src/io/anuke/mindustry/world/meta/BlockFlag.java b/core/src/io/anuke/mindustry/world/meta/BlockFlag.java index a57e765414..b5c8339854 100644 --- a/core/src/io/anuke/mindustry/world/meta/BlockFlag.java +++ b/core/src/io/anuke/mindustry/world/meta/BlockFlag.java @@ -1,24 +1,16 @@ package io.anuke.mindustry.world.meta; -//TODO fix flagging system, currently doesn't really work public enum BlockFlag{ /**General important target for all types of units.*/ target(0), - /**Point to resupply resources.*/ - resupplyPoint(Float.MAX_VALUE), - /**Point to drop off resources.*/ - dropPoint(Float.MAX_VALUE), /**Producer of important goods.*/ producer(Float.MAX_VALUE), - /**Just a turret.*/ + /**A turret.*/ turret(Float.MAX_VALUE), - /**Producer or storage unit of volatile materials.*/ - explosive(Float.MAX_VALUE), /**Repair point.*/ repair(Float.MAX_VALUE); public final static BlockFlag[] all = values(); - public final float cost; BlockFlag(float cost){ diff --git a/core/src/io/anuke/mindustry/world/meta/BlockStat.java b/core/src/io/anuke/mindustry/world/meta/BlockStat.java index a78bcc0166..21fa588ea0 100644 --- a/core/src/io/anuke/mindustry/world/meta/BlockStat.java +++ b/core/src/io/anuke/mindustry/world/meta/BlockStat.java @@ -12,7 +12,7 @@ public enum BlockStat{ itemCapacity(StatCategory.items), inputItemCapacity(StatCategory.items), outputItemCapacity(StatCategory.items), - itemSpeed(StatCategory.items), + itemsMoved(StatCategory.items), liquidCapacity(StatCategory.liquids), liquidOutput(StatCategory.liquids), @@ -39,6 +39,7 @@ public enum BlockStat{ outputItem(StatCategory.crafting), drillTier(StatCategory.crafting), drillSpeed(StatCategory.crafting), + maxUnits(StatCategory.crafting), shootRange(StatCategory.shooting), inaccuracy(StatCategory.shooting), diff --git a/core/src/io/anuke/mindustry/world/meta/BlockStats.java b/core/src/io/anuke/mindustry/world/meta/BlockStats.java index 9dcd09db5e..d094b16672 100644 --- a/core/src/io/anuke/mindustry/world/meta/BlockStats.java +++ b/core/src/io/anuke/mindustry/world/meta/BlockStats.java @@ -1,20 +1,14 @@ package io.anuke.mindustry.world.meta; -import io.anuke.arc.Core; import io.anuke.arc.collection.ObjectMap.Entry; import io.anuke.arc.collection.OrderedMap; -import io.anuke.arc.util.Log; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.meta.values.*; -import java.util.Locale; - /**Hold and organizes a list of block stats.*/ public class BlockStats{ - private static final boolean errorWhenMissing = false; - private final OrderedMap> map = new OrderedMap<>(); private boolean dirty; @@ -50,22 +44,6 @@ public class BlockStats{ /**Adds a stat value.*/ public void add(BlockStat stat, StatValue value){ - if(!Core.bundle.has("blocks." + stat.name().toLowerCase(Locale.ROOT))){ - if(!errorWhenMissing){ - Log.err("Warning: No bundle entry for stat type \"" + stat + "\"!"); - }else{ - throw new RuntimeException("No bundle entry for stat type \"" + stat + "\"!"); - } - } - - if(!Core.bundle.has("category." + stat.category.name().toLowerCase(Locale.ROOT))){ - if(!errorWhenMissing){ - Log.err("Warning: No bundle entry for stat category \"" + stat.category + "\"!"); - }else{ - throw new RuntimeException("No bundle entry for stat category \"" + stat.category + "\"!"); - } - } - if(map.containsKey(stat.category) && map.get(stat.category).containsKey(stat)){ throw new RuntimeException("Duplicate stat entry: \"" + stat + "\" in block."); } diff --git a/core/src/io/anuke/mindustry/world/meta/StatUnit.java b/core/src/io/anuke/mindustry/world/meta/StatUnit.java index 8951339b1c..5dc4e2d2f2 100644 --- a/core/src/io/anuke/mindustry/world/meta/StatUnit.java +++ b/core/src/io/anuke/mindustry/world/meta/StatUnit.java @@ -12,7 +12,6 @@ public enum StatUnit{ powerSecond, liquidSecond, itemsSecond, - pixelsSecond, liquidUnits, powerUnits, degrees, diff --git a/core/src/io/anuke/mindustry/world/meta/values/ItemFilterValue.java b/core/src/io/anuke/mindustry/world/meta/values/ItemFilterValue.java index 4aa7d9aef8..8bb1ecb6a0 100644 --- a/core/src/io/anuke/mindustry/world/meta/values/ItemFilterValue.java +++ b/core/src/io/anuke/mindustry/world/meta/values/ItemFilterValue.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.world.meta.values; import io.anuke.arc.collection.Array; +import io.anuke.arc.function.Predicate; +import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.ui.ItemDisplay; import io.anuke.mindustry.world.meta.StatValue; -import io.anuke.arc.function.Predicate; -import io.anuke.arc.scene.ui.layout.Table; import static io.anuke.mindustry.Vars.content; @@ -18,11 +18,7 @@ public class ItemFilterValue implements StatValue{ @Override public void display(Table table){ - Array list = new Array<>(); - - for(Item item : content.items()){ - if(filter.test(item)) list.add(item); - } + Array list = content.items().select(filter); for(int i = 0; i < list.size; i++){ Item item = list.get(i); diff --git a/core/src/io/anuke/mindustry/world/meta/values/NumberValue.java b/core/src/io/anuke/mindustry/world/meta/values/NumberValue.java index 8c8a058297..620bfc1186 100644 --- a/core/src/io/anuke/mindustry/world/meta/values/NumberValue.java +++ b/core/src/io/anuke/mindustry/world/meta/values/NumberValue.java @@ -16,10 +16,6 @@ public class NumberValue implements StatValue{ public NumberValue(float value, StatUnit unit){ this.unit = unit; this.value = value; - - if(unit != StatUnit.none && unit.localized().contains("???")){ - throw new RuntimeException("No bundle definition found for unit: '" + unit + "'"); - } } @Override diff --git a/core/src/io/anuke/mindustry/world/meta/values/StringValue.java b/core/src/io/anuke/mindustry/world/meta/values/StringValue.java index f51884621a..830d897ab6 100644 --- a/core/src/io/anuke/mindustry/world/meta/values/StringValue.java +++ b/core/src/io/anuke/mindustry/world/meta/values/StringValue.java @@ -8,7 +8,7 @@ public class StringValue implements StatValue{ private final String value; public StringValue(String value, Object... args){ - this.value = Strings.formatArgs(value, args); + this.value = Strings.format(value, args); } @Override diff --git a/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java b/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java index 68f8585b55..9643377a7b 100644 --- a/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java +++ b/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.world.modules; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.world.consumers.Consume; import java.io.DataInput; @@ -9,10 +9,13 @@ import java.io.IOException; public class ConsumeModule extends BlockModule{ private boolean valid; - private TileEntity entity; + private final TileEntity entity; - public void update(TileEntity entity){ + public ConsumeModule(TileEntity entity){ this.entity = entity; + } + + public void update(){ boolean prevValid = valid(); valid = true; @@ -27,8 +30,14 @@ public class ConsumeModule extends BlockModule{ } } + public void trigger(){ + for(Consume cons : entity.tile.block().consumes.all()){ + cons.trigger(entity.tile.block(), entity); + } + } + public boolean valid(){ - return valid && (entity == null || entity.tile.block().canProduce(entity.tile)); + return valid && entity.tile.block().canProduce(entity.tile); } @Override diff --git a/core/src/io/anuke/mindustry/world/modules/PowerModule.java b/core/src/io/anuke/mindustry/world/modules/PowerModule.java index 7e601394a1..265724c974 100644 --- a/core/src/io/anuke/mindustry/world/modules/PowerModule.java +++ b/core/src/io/anuke/mindustry/world/modules/PowerModule.java @@ -24,6 +24,7 @@ public class PowerModule extends BlockModule{ for(int i = 0; i < links.size; i++){ stream.writeInt(links.get(i)); } + stream.writeFloat(satisfaction); } @Override @@ -32,5 +33,7 @@ public class PowerModule extends BlockModule{ for(int i = 0; i < amount; i++){ links.add(stream.readInt()); } + satisfaction = stream.readFloat(); + if(Float.isNaN(satisfaction) || Float.isInfinite(satisfaction)) satisfaction = 0f; } } diff --git a/core/src/io/anuke/mindustry/world/producers/Produce.java b/core/src/io/anuke/mindustry/world/producers/Produce.java new file mode 100644 index 0000000000..c055f50645 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/producers/Produce.java @@ -0,0 +1,4 @@ +package io.anuke.mindustry.world.producers; + +public class Produce{ +} diff --git a/core/src/io/anuke/mindustry/world/producers/ProduceItem.java b/core/src/io/anuke/mindustry/world/producers/ProduceItem.java new file mode 100644 index 0000000000..f1083e17ed --- /dev/null +++ b/core/src/io/anuke/mindustry/world/producers/ProduceItem.java @@ -0,0 +1,4 @@ +package io.anuke.mindustry.world.producers; + +public class ProduceItem{ +} diff --git a/desktop/build.gradle b/desktop/build.gradle index 24358df109..48aa4e3236 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -6,25 +6,24 @@ sourceSets.main.java.srcDirs = ["src/"] project.ext.mainClassName = "io.anuke.mindustry.desktop.DesktopLauncher" project.ext.assetsDir = new File("../core/assets") -def PACKR_DIR = "$System.env.PACKR_DIR" +import com.badlogicgames.packr.PackrConfig +import com.badlogicgames.packr.Packr + +def JDK_DIR = "$System.env.PACKR_DIR" def ICON_DIR = new File("core/assets/sprites/icon.icns") ext.getPlatform = { - if(project.hasProperty("platform")){ - def lc = platform.toLowerCase() - if(lc == "windows64"){ - return "windows64" - }else if(lc == "windows32"){ - return "windows32" - }else if(lc == "linux"){ - return "linux64" - }else if(lc == "mac"){ - return "mac" - }else{ - throw new InvalidUserDataException("Invalid platform. Set platform with -Pplatform=windows/linux/mac") - } + def lc = project.hasProperty("platform") ? platform.toLowerCase() : "" + if(lc == "windows64"){ + return PackrConfig.Platform.Windows64 + }else if(lc == "windows32"){ + return PackrConfig.Platform.Windows32 + }else if(lc == "linux"){ + return PackrConfig.Platform.Linux64 + }else if(lc == "mac"){ + return PackrConfig.Platform.MacOS }else{ - throw new InvalidUserDataException("No platform defined. Set platform with -Pplatform=windows/linux/mac") + throw new InvalidUserDataException("Invalid platform. Set platform with -Pplatform=windows64/windows32/linux/mac") } } @@ -70,69 +69,68 @@ task dist(type: Jar){ } } -task clearOut(type: Delete){ - doLast{ - delete "packr-out/" - } -} - //note: call desktop:dist beforehand task packrCmd(){ doLast{ + def config = new PackrConfig() + config.with{ + config.executable = appName + verbose = true + platform = getPlatform() + bundleIdentifier = getPackage() + ".mac" + iconResource = ICON_DIR + outDir = file("packr-out/") + mainClass = project.ext.mainClassName + classpath = ["desktop/build/libs/desktop-release.jar"] + vmArgs = ["Djava.net.preferIPv4Stack=true"] + minimizeJre = "desktop/packr_minimize.json" + jdk = JDK_DIR + "jdk-${getPlatform().toString().toLowerCase()}.zip" - copy{ - into PACKR_DIR - from "build/libs/desktop-release.jar" + if(getPlatform() == PackrConfig.Platform.MacOS){ + vmArgs += "XstartOnFirstThread" + } } - exec{ - - commandLine("java", "-jar", PACKR_DIR + "packr.jar", - "--verbose", - "--bundle", getPackage() + ".mac", - "--platform", getPlatform(), - "--executable", appName, - "--output", "packr-out/", - "--mainclass", project.ext.mainClassName, - "--jdk", PACKR_DIR + "jdk-" + getPlatform() + ".zip", - "--icon", ICON_DIR.getAbsolutePath(), - "--vmargs", (getPlatform() == "mac" ? "XstartOnFirstThread" : "Xms256m"), - "Djava.net.preferIPv4Stack=true", - "--classpath", "--", PACKR_DIR + "config.json") - } - } -} - -task fixMac(type: Copy){ - dependsOn "packrCmd" - - into "packr-out/" + appName + ".app/Contents/" - from "packr-out/Contents/" - - doLast{ - delete{ - delete "packr-out/Contents/" - } - } -} - -task fixWindows32(type: Copy){ - dependsOn "packrCmd" - - into "packr-out/jre/bin/" - from PACKR_DIR + "zip.dll" - rename("zip.dll", "ojdkbuild_zlib.dll") - - doLast{ - copy{ - into "packr-out/jre/bin/" - from PACKR_DIR + "zip.dll" - } + new Packr().pack(config) } } task packrZip(){ + task clearOut(type: Delete){ + doLast{ + delete "packr-out/" + } + } + + task fixMac(type: Copy){ + dependsOn "packrCmd" + + into "packr-out/" + appName + ".app/Contents/" + from "packr-out/Contents/" + + doLast{ + delete{ + delete "packr-out/Contents/" + } + } + } + + task fixWindows32(type: Copy){ + dependsOn "packrCmd" + + into "packr-out/jre/bin/" + from JDK_DIR + "zip.dll" + rename("zip.dll", "ojdkbuild_zlib.dll") + + doLast{ + copy{ + into "packr-out/jre/bin/" + from JDK_DIR + "zip.dll" + } + } + } + dependsOn "packrCmd" finalizedBy "clearOut" @@ -146,12 +144,12 @@ task packrZip(){ dependsOn "fixWindows32" } - task zip(type: Zip){ + task rzip(type: Zip){ from "packr-out/" archiveName "$appName-${getPlatform()}-${getVersionString()}.zip" destinationDir(file("packr-export")) } - finalizedBy 'zip' + finalizedBy 'rzip' } } diff --git a/desktop/packr_minimize.json b/desktop/packr_minimize.json new file mode 100644 index 0000000000..0887fdf720 --- /dev/null +++ b/desktop/packr_minimize.json @@ -0,0 +1,82 @@ +{ + "reduce": [ + { + "archive": "jre/lib/rt.jar", + "paths": [ + + "javax/transaction", + "javax/tools", + "javax/swing", + "javax/sql", + "javax/smartcardio", + "javax/rmi", + "javax/print", + "javax/naming", + "javax/management", + "javax/lang", + "javax/jws", + "javax/swing", + "javax/imageio", + "javax/annotation", + "javax/activity", + "javax/activation", + "javax/accessibility", + "com/sun/corba", + "com/sun/jmx", + "com/sun/jndi", + "com/sun/xml", + "com/sun/script", + "com/sun/media", + "com/sun/naming", + "java/awt", + + "com/sun/org/apache/xpath", + + "com/sun/rowset", + "com/sun/script", + "sun/applet", + "sun/corba", + "sun/management" + ] + }, + { + "archive": "jre/lib/charsets.jar", + "paths": [ + ] + }, + { + "archive": "jre/lib/jsse.jar", + "paths": [ + ] + }, + { + "archive": "jre/lib/resources.jar", + "paths": [ + ] + } + ], + "remove": [ + { + "platform": "*", + "paths": [ + "jre/lib/rhino.jar" + ] + }, + { + "platform": "linux", + "paths": [ + "jre/lib/amd64/libawt.so", + "jre/lib/amd64/libawt_xawt.so", + "jre/lib/amd64/libjawt.so" + ] + }, + { + "platform": "windows", + "paths": [ + "jre/bin/*.exe", + "jre/bin/client", + "jre/bin/awt.dll" + ] + } + ] +} diff --git a/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java b/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java index c2e23ee01b..1de445dfc3 100644 --- a/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java +++ b/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java @@ -9,6 +9,7 @@ import io.anuke.arc.util.serialization.JsonWriter.OutputType; import io.anuke.mindustry.Vars; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.net.Net; +import org.lwjgl.util.tinyfd.TinyFileDialogs; import java.io.PrintWriter; import java.io.StringWriter; @@ -25,34 +26,24 @@ public class CrashHandler{ try{ //check crash report setting - if(!Core.settings.getBool("crashreport")){ + if(!Core.settings.getBool("crashreport", true)){ return; } }catch(Throwable ignored){ - //don't send since we don't know if the user has the setting set - return; - } - - if(!OS.isMac){ - try{ - javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName()); - }catch(Throwable ignored){} + //if there's no settings init we don't know what the user wants but chances are it's an important crash, so send it anyway } boolean badGPU = false; - if(!OS.isMac && e.getMessage() != null && (e.getMessage().contains("Couldn't create window") || e.getMessage().contains("OpenGL 2.0 or higher"))){ - try{ - javax.swing.JOptionPane.showMessageDialog(null, "Your graphics card does not support OpenGL 2.0!\n" + - "Try to update your graphics drivers.\n\n" + - "(If that doesn't work, your computer just doesn't support Mindustry.)", - "oh no", javax.swing.JOptionPane.INFORMATION_MESSAGE); - badGPU = true; - }catch(Throwable ignored){} + if(e.getMessage() != null && (e.getMessage().contains("Couldn't create window") || e.getMessage().contains("OpenGL 2.0 or higher"))){ + + dialog(() -> TinyFileDialogs.tinyfd_messageBox("oh no", "Your graphics card does not support OpenGL 2.0!\n" + + "Try to update your graphics drivers.\n\n" + + "(If that doesn't work, your computer just doesn't support Mindustry.)", "ok", "error", true)); + badGPU = true; } - //don't create crash logs for me (anuke), as it's expected - //also don't create logs for custom builds + //don't create crash logs for me (anuke) or custom builds, as it's expected if(System.getProperty("user.name").equals("anuke") || Version.build == -1) return; boolean netActive = false, netServer = false; @@ -83,14 +74,12 @@ public class CrashHandler{ try{ Path path = Paths.get(OS.getAppDataDirectoryString(Vars.appName), "crashes", - "crash-report-" + DateTimeFormatter.ofPattern("MM dd yyyy HH mm ss").format(LocalDateTime.now()) + ".txt"); + "crash-report-" + DateTimeFormatter.ofPattern("MM_dd_yyyy_HH_mm_ss").format(LocalDateTime.now()) + ".txt"); Files.createDirectories(Paths.get(OS.getAppDataDirectoryString(Vars.appName), "crashes")); - Files.write(path, parseException(e).getBytes()); if(!badGPU){ - javax.swing.JOptionPane.showMessageDialog(null, "A crash has occured. It has been saved in:\n" + path.toAbsolutePath().toString(), - "oh no", javax.swing.JOptionPane.INFORMATION_MESSAGE); + dialog(() -> TinyFileDialogs.tinyfd_messageBox("oh no", "A crash has occured. It has been saved in:\n" + path.toAbsolutePath().toString(), "ok", "error", true)); } }catch(Throwable t){ Log.err("Failed to save local crash report."); @@ -107,8 +96,12 @@ public class CrashHandler{ System.exit(1); }); - //sleep forever - try{ Thread.sleep(Long.MAX_VALUE); }catch(InterruptedException ignored){} + //sleep for 10 seconds or until crash report is sent + try{ Thread.sleep(10000); }catch(InterruptedException ignored){} + } + + private static void dialog(Runnable r){ + new Thread(r).start(); } private static String parseException(Throwable e){ diff --git a/ios/src/io/anuke/mindustry/IOSLauncher.java b/ios/src/io/anuke/mindustry/IOSLauncher.java index b8bdb66dda..cc7d8dd154 100644 --- a/ios/src/io/anuke/mindustry/IOSLauncher.java +++ b/ios/src/io/anuke/mindustry/IOSLauncher.java @@ -101,10 +101,10 @@ public class IOSLauncher extends IOSApplication.Delegate { SaveSlot slot = control.saves.importSave(file); ui.load.runLoadSave(slot); }catch (IOException e){ - ui.showError(Core.bundle.format("text.save.import.fail", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, false))); } }else{ - ui.showError("$text.save.import.invalid"); + ui.showError("save.import.invalid"); } }else if(file.extension().equalsIgnoreCase(mapExtension)){ //open map diff --git a/net/src/io/anuke/net/KryoServer.java b/net/src/io/anuke/net/KryoServer.java index 0f37c80e19..47b495958a 100644 --- a/net/src/io/anuke/net/KryoServer.java +++ b/net/src/io/anuke/net/KryoServer.java @@ -61,7 +61,7 @@ public class KryoServer implements ServerProvider{ c.id = kn.id; c.addressTCP = ip; - Log.info("&bRecieved connection: {0}", c.addressTCP); + Log.debug("&bRecieved connection: {0}", c.addressTCP); connections.add(kn); Core.app.post(() -> Net.handleServerReceived(kn.id, c)); @@ -90,7 +90,7 @@ public class KryoServer implements ServerProvider{ try{ Net.handleServerReceived(k.id, object); }catch(ValidateException e){ - Log.err("Validate failed: {0} ({1})", e.player.name, e.getMessage()); + Log.err("Validation failed: {0} ({1})", e.player.name, e.getMessage()); }catch(Exception e){ e.printStackTrace(); } @@ -249,7 +249,6 @@ public class KryoServer implements ServerProvider{ @Override public void dispose(){ close(); - Log.info("Disposed server."); } private void handleException(Throwable e){ diff --git a/server/build.gradle b/server/build.gradle index 6f22ffa04c..51240b5170 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -31,6 +31,10 @@ task dist(type: Jar) { from files(sourceSets.main.output.resourcesDir) from {configurations.compile.collect {zipTree(it)}} from files(project.assetsDir) + exclude("sprites/**") + exclude("fonts/**") + exclude("com/badlogic/gdx/**") + exclude("bundles/**") writeVersion() diff --git a/server/src/io/anuke/mindustry/server/MindustryServer.java b/server/src/io/anuke/mindustry/server/MindustryServer.java index 7bf7f08298..94a3a01587 100644 --- a/server/src/io/anuke/mindustry/server/MindustryServer.java +++ b/server/src/io/anuke/mindustry/server/MindustryServer.java @@ -28,11 +28,12 @@ public class MindustryServer implements ApplicationListener{ BundleLoader.load(); content.verbose(false); content.load(); - content.initialize(Content::init); Core.app.addListener(logic = new Logic()); Core.app.addListener(world = new World()); Core.app.addListener(netServer = new NetServer()); Core.app.addListener(new ServerControl(args)); + + content.initialize(Content::init); } } diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java index 8717c54f44..fd97296a70 100644 --- a/server/src/io/anuke/mindustry/server/ServerControl.java +++ b/server/src/io/anuke/mindustry/server/ServerControl.java @@ -5,7 +5,7 @@ import io.anuke.arc.Core; import io.anuke.arc.Events; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectSet; -import io.anuke.arc.entities.Effects; +import io.anuke.mindustry.entities.Effects; import io.anuke.arc.files.FileHandle; import io.anuke.arc.util.*; import io.anuke.arc.util.CommandHandler.Command; @@ -13,14 +13,13 @@ import io.anuke.arc.util.CommandHandler.Response; import io.anuke.arc.util.CommandHandler.ResponseType; import io.anuke.arc.util.Timer.Task; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.game.Difficulty; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.EventType.GameOverEvent; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.maps.Map; +import io.anuke.mindustry.maps.MapException; import io.anuke.mindustry.net.Administration.PlayerInfo; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Packets.KickReason; @@ -28,6 +27,7 @@ import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemType; import java.io.IOException; +import java.net.BindException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Scanner; @@ -46,7 +46,7 @@ public class ServerControl implements ApplicationListener{ private FileHandle currentLogFile; private boolean inExtraRound; private Task lastTask; - + private RulePreset lastPreset; public ServerControl(String[] args){ Core.settings.defaults( @@ -62,6 +62,11 @@ public class ServerControl implements ApplicationListener{ Log.setLogger(new LogHandler(){ DateTimeFormatter dateTime = DateTimeFormatter.ofPattern("MM-dd-yyyy | HH:mm:ss"); + @Override + public void debug(String text, Object... args){ + print("&lc&fb" + "[DEBUG] " + text, args); + } + @Override public void info(String text, Object... args){ print("&lg&fb" + "[INFO] " + text, args); @@ -112,6 +117,8 @@ public class ServerControl implements ApplicationListener{ } }); + customMapDirectory.mkdirs(); + Thread thread = new Thread(this::readCommands, "Server Controls"); thread.setDaemon(true); thread.start(); @@ -184,7 +191,7 @@ public class ServerControl implements ApplicationListener{ info("Stopped server."); }); - handler.register("host", "[mapname]", "Open the server with a specific map.", arg -> { + handler.register("host", " [mode]", "Open the server with a specific map.", arg -> { if(state.is(State.playing)){ err("Already hosting. Type 'stop' to stop hosting first."); return; @@ -192,36 +199,38 @@ public class ServerControl implements ApplicationListener{ if(lastTask != null) lastTask.cancel(); - Map result = null; + Map result = world.maps.all().find(map -> map.name.equalsIgnoreCase(arg[0])); - if(arg.length > 0){ + if(result == null){ + err("No map with name &y'{0}'&lr found.", arg[0]); + return; + } - String search = arg[0]; - for(Map map : world.maps.all()){ - if(map.name.equalsIgnoreCase(search)) result = map; - } + RulePreset preset = RulePreset.survival; - if(result == null){ - err("No map with name &y'{0}'&lr found.", search); + if(arg.length > 1){ + try{ + preset = RulePreset.valueOf(arg[1]); + }catch(IllegalArgumentException e){ + err("No gamemode '{0}' found.", arg[1]); return; } + } + info("Loading map..."); - info("Loading map..."); - err("TODO select gamemode"); - - logic.reset(); + logic.reset(); + state.rules = preset.get(); + try{ world.loadMap(result); logic.play(); - }else{ - //TODO - err("TODO play generated map"); + info("Map loaded."); + + host(); + }catch(MapException e){ + Log.err(e.map.getDisplayName() + ": " + e.getMessage()); } - - info("Map loaded."); - - host(); }); handler.register("port", "[port]", "Sets or displays the port for hosting the server.", arg -> { @@ -240,10 +249,15 @@ public class ServerControl implements ApplicationListener{ }); handler.register("maps", "Display all available maps.", arg -> { - info("Maps:"); - for(Map map : world.maps.all()){ - info(" &ly{0}: &lb&fi{1} / {2}x{3}", map.name, map.custom ? "Custom" : "Default", map.meta.width, map.meta.height); + if(!world.maps.all().isEmpty()){ + info("Maps:"); + for(Map map : world.maps.all()){ + info(" &ly{0}: &lb&fi{1} / {2}x{3}", map.name, map.custom ? "Custom" : "Default", map.meta.width, map.meta.height); + } + }else{ + info("No maps found."); } + info("&lyMap directory: &lb&fi{0}", customMapDirectory.file().getAbsoluteFile().toString()); }); handler.register("status", "Display server status.", arg -> { @@ -251,16 +265,15 @@ public class ServerControl implements ApplicationListener{ info("Status: &rserver closed"); }else{ info("Status:"); - info(" &lyPlaying on map &fi{0}&fb &lb/&ly Wave {1} &lb/&ly {2} &lb/&ly {3}", Strings.capitalize(world.getMap().name), state.wave); + info(" &lyPlaying on map &fi{0}&fb &lb/&ly Wave {1}", Strings.capitalize(world.getMap().name), state.wave); - if(!state.rules.waves){ + if(state.rules.waves){ info("&ly {0} enemies.", unitGroups[Team.red.ordinal()].size()); }else{ info("&ly {0} seconds until next wave.", (int) (state.wavetime / 60)); } - info(" &ly{0} FPS.", (int) (60f / Time.delta())); - info(" &ly{0} MB used.", Core.app.getJavaHeap() / 1024 / 1024); + info(" &ly{0} FPS, {1} MB used.", (int)(60f/Time.delta()), Core.app.getJavaHeap() / 1024 / 1024); if(playerGroup.size() > 0){ info(" &lyPlayers: {0}", playerGroup.size()); @@ -293,7 +306,7 @@ public class ServerControl implements ApplicationListener{ } }); - handler.register("fillitems", "[team]", "Fill the core with 2000 items.", arg -> { + handler.register("fillitems", "[team]", "Fill the core with items.", arg -> { if(!state.is(State.playing)){ err("Not playing. Host first."); return; @@ -309,7 +322,7 @@ public class ServerControl implements ApplicationListener{ for(Item item : content.items()){ if(item.type == ItemType.material){ - state.teams.get(team).cores.first().entity.items.add(item, 2000); + state.teams.get(team).cores.first().entity.items.set(item, state.teams.get(team).cores.first().block().itemCapacity); } } @@ -632,7 +645,9 @@ public class ServerControl implements ApplicationListener{ players.add(p); p.setDead(true); } + Rules rules = state.rules; logic.reset(); + state.rules = rules; Call.onWorldDataBegin(); run.run(); logic.play(); @@ -647,7 +662,12 @@ public class ServerControl implements ApplicationListener{ lastTask = new Task(){ @Override public void run(){ - r.run(); + try{ + r.run(); + }catch(MapException e){ + Log.err(e.map.getDisplayName() + ": " + e.getMessage()); + Net.closeServer(); + } } }; @@ -661,6 +681,8 @@ public class ServerControl implements ApplicationListener{ try{ Net.host(Core.settings.getInt("port")); info("&lcOpened a server on port {0}.", Core.settings.getInt("port")); + }catch(BindException e){ + Log.err("Unable to host: Port already in use! Make sure no other servers are running on the same port in your network."); }catch(IOException e){ err(e); state.set(State.menu); diff --git a/settings.gradle b/settings.gradle index cb3b08c8fe..2f0aa64e78 100644 --- a/settings.gradle +++ b/settings.gradle @@ -25,6 +25,7 @@ if(System.properties["release"] == null || System.properties["release"] == "fals use(':Arc:arc-core', '../Arc/arc-core') use(':Arc:extensions', '../Arc/extensions') use(':Arc:extensions:freetype', '../Arc/extensions/freetype') + use(':Arc:extensions:recorder', '../Arc/extensions/recorder') use(':Arc:backends', '../Arc/backends') use(':Arc:backends:backend-lwjgl3', '../Arc/backends/backend-lwjgl3') use(':Arc:backends:backend-android', '../Arc/backends/backend-android') diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index 0c90191680..f67122d9a7 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -1,6 +1,7 @@ import io.anuke.arc.ApplicationCore; import io.anuke.arc.backends.headless.HeadlessApplication; import io.anuke.arc.backends.headless.HeadlessApplicationConfiguration; +import io.anuke.arc.collection.Array; import io.anuke.arc.math.geom.Point2; import io.anuke.arc.util.Log; import io.anuke.arc.util.Time; @@ -13,15 +14,17 @@ import io.anuke.mindustry.core.Logic; import io.anuke.mindustry.core.NetServer; import io.anuke.mindustry.core.World; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; -import io.anuke.mindustry.entities.units.BaseUnit; -import io.anuke.mindustry.entities.units.types.Spirit; +import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.entities.type.base.Spirit; import io.anuke.mindustry.game.Content; +import io.anuke.mindustry.game.SpawnGroup; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.io.BundleLoader; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Zone; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Edges; import io.anuke.mindustry.world.Tile; @@ -105,8 +108,6 @@ public class ApplicationTests{ @Test void playMap(){ - assertTrue(world.maps.all().size > 0); - world.loadMap(testMap); } @@ -114,14 +115,17 @@ public class ApplicationTests{ void spawnWaves(){ world.loadMap(testMap); logic.runWave(); + //force trigger delayed spawns + Time.setDeltaProvider(() -> 1000f); + Time.update(); + Time.update(); + Time.setDeltaProvider(() -> 1f); unitGroups[waveTeam.ordinal()].updateEvents(); assertFalse(unitGroups[waveTeam.ordinal()].isEmpty()); } @Test void createMap(){ - assertTrue(world.maps.all().size > 0); - Tile[][] tiles = world.createTiles(8, 8); world.beginMapLoad(); @@ -138,12 +142,12 @@ public class ApplicationTests{ createMap(); int bx = 4; int by = 4; - world.setBlock(world.tile(bx, by), Blocks.core, Team.blue); + world.setBlock(world.tile(bx, by), Blocks.coreShard, Team.blue); assertEquals(world.tile(bx, by).getTeam(), Team.blue); for(int x = bx-1; x <= bx + 1; x++){ for(int y = by-1; y <= by + 1; y++){ if(x == bx && by == y){ - assertEquals(world.tile(x, y).block(), Blocks.core); + assertEquals(world.tile(x, y).block(), Blocks.coreShard); }else{ assertTrue(world.tile(x, y).block() == Blocks.part && world.tile(x, y).getLinked() == world.tile(bx, by)); } @@ -176,16 +180,13 @@ public class ApplicationTests{ @Test void save(){ - assertTrue(world.maps.all().size > 0); - world.loadMap(testMap); + assertTrue(state.teams.get(defaultTeam).cores.size > 0); SaveIO.saveToSlot(0); } @Test void load(){ - assertTrue(world.maps.all().size > 0); - world.loadMap(testMap); Map map = world.getMap(); @@ -193,9 +194,9 @@ public class ApplicationTests{ resetWorld(); SaveIO.loadFromSlot(0); - assertEquals(world.getMap().name, map.name); assertEquals(world.width(), map.meta.width); assertEquals(world.height(), map.meta.height); + assertTrue(state.teams.get(defaultTeam).cores.size > 0); } @Test @@ -231,14 +232,47 @@ public class ApplicationTests{ d2.addBuildRequest(new BuildRequest(1, 1, 0, Blocks.copperWallLarge)); Time.setDeltaProvider(() -> 9999999f); - d1.updateBuilding(d1); - d2.updateBuilding(d2); + d1.updateBuilding(); + d2.updateBuilding(); assertEquals(Blocks.copperWallLarge, world.tile(0, 0).block()); assertEquals(Blocks.air, world.tile(2, 2).block()); assertEquals(Blocks.part, world.tile(1, 1).block()); } + @Test + void zoneEmptyWaves(){ + for(Zone zone : content.zones()){ + Array spawns = zone.rules.get().spawns; + for(int i = 1; i <= 100; i++){ + int total = 0; + for(SpawnGroup spawn : spawns){ + total += spawn.getUnitsSpawned(i); + } + + assertNotEquals(0, total, "Zone " + zone + " has no spawned enemies at wave " + i); + } + } + } + + @Test + void zoneOverflowWaves(){ + for(Zone zone : content.zones()){ + Array spawns = zone.rules.get().spawns; + + for(int i = 1; i <= 40; i++){ + int total = 0; + for(SpawnGroup spawn : spawns){ + total += spawn.getUnitsSpawned(i); + } + + if(total >= 140){ + fail("Zone '" + zone + "' has too many spawned enemies at wave " + i + " : " + total); + } + } + } + } + @Test void buildingDestruction(){ initBuilding(); @@ -253,16 +287,16 @@ public class ApplicationTests{ d2.addBuildRequest(new BuildRequest(1, 1)); Time.setDeltaProvider(() -> 3f); - d1.updateBuilding(d1); + d1.updateBuilding(); Time.setDeltaProvider(() -> 1f); - d2.updateBuilding(d2); + d2.updateBuilding(); assertEquals(content.getByName(ContentType.block, "build2"), world.tile(0, 0).block()); Time.setDeltaProvider(() -> 9999f); - d1.updateBuilding(d1); - d2.updateBuilding(d2); + d1.updateBuilding(); + d2.updateBuilding(); assertEquals(Blocks.air, world.tile(0, 0).block()); assertEquals(Blocks.air, world.tile(2, 2).block()); @@ -273,7 +307,7 @@ public class ApplicationTests{ createMap(); Tile core = world.tile(5, 5); - world.setBlock(core, Blocks.core, Team.blue); + world.setBlock(core, Blocks.coreShard, Team.blue); for(Item item : content.items()){ core.entity.items.set(item, 3000); } diff --git a/tests/src/test/java/IOTests.java b/tests/src/test/java/IOTests.java index 5357bb515e..7a75b81d16 100644 --- a/tests/src/test/java/IOTests.java +++ b/tests/src/test/java/IOTests.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test; import java.nio.ByteBuffer; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; public class IOTests{ @@ -28,7 +29,7 @@ public class IOTests{ ByteBuffer buffer = ByteBuffer.allocate(500); TypeIO.writeString(buffer, null); buffer.position(0); - assertEquals(TypeIO.readString(buffer), null); + assertNull(TypeIO.readString(buffer)); } } diff --git a/tests/src/test/java/power/DirectConsumerTests.java b/tests/src/test/java/power/DirectConsumerTests.java index e6081f7258..5298c27fde 100644 --- a/tests/src/test/java/power/DirectConsumerTests.java +++ b/tests/src/test/java/power/DirectConsumerTests.java @@ -16,13 +16,13 @@ public class DirectConsumerTests extends PowerTestFixture{ @Test void noPowerRequestedWithNoItems(){ - testUnitFactory(0, 0, 0.08f, 0.08f, 0.0f); + testUnitFactory(0, 0, 0.08f, 0.08f, 1f); } @Test void noPowerRequestedWithInsufficientItems(){ - testUnitFactory(30, 0, 0.08f, 0.08f, 0.0f); - testUnitFactory(0, 30, 0.08f, 0.08f, 0.0f); + testUnitFactory(30, 0, 0.08f, 0.08f, 1f); + testUnitFactory(0, 30, 0.08f, 0.08f, 1f); } @Test @@ -41,7 +41,7 @@ public class DirectConsumerTests extends PowerTestFixture{ consumerTile.entity.items.add(Items.lead, leadAmount); Tile producerTile = createFakeTile(2, 0, createFakeProducerBlock(producedPower)); - producerTile.entity().productionEfficiency = 0.5f; // 100% + producerTile.entity().productionEfficiency = 1f; PowerGraph graph = new PowerGraph(); graph.add(producerTile); diff --git a/tests/src/test/java/power/FakeGraphics.java b/tests/src/test/java/power/FakeGraphics.java new file mode 100644 index 0000000000..3006810379 --- /dev/null +++ b/tests/src/test/java/power/FakeGraphics.java @@ -0,0 +1,222 @@ +package power; + +import io.anuke.arc.Graphics; +import io.anuke.arc.Graphics.Cursor.SystemCursor; +import io.anuke.arc.graphics.GL20; +import io.anuke.arc.graphics.GL30; +import io.anuke.arc.graphics.Pixmap; +import io.anuke.arc.graphics.glutils.GLVersion; + +public class FakeGraphics extends Graphics{ + static int frame; + + @Override + public boolean isGL30Available(){ + return false; + } + + @Override + public GL20 getGL20(){ + return null; + } + + @Override + public void setGL20(GL20 gl20){ + + } + + @Override + public GL30 getGL30(){ + return null; + } + + @Override + public void setGL30(GL30 gl30){ + + } + + @Override + public int getWidth(){ + return 0; + } + + @Override + public int getHeight(){ + return 0; + } + + @Override + public int getBackBufferWidth(){ + return 0; + } + + @Override + public int getBackBufferHeight(){ + return 0; + } + + @Override + public long getFrameId(){ + return frame++; + } + + @Override + public float getDeltaTime(){ + return 0; + } + + @Override + public float getRawDeltaTime(){ + return 0; + } + + @Override + public int getFramesPerSecond(){ + return 0; + } + + @Override + public GLVersion getGLVersion(){ + return null; + } + + @Override + public float getPpiX(){ + return 0; + } + + @Override + public float getPpiY(){ + return 0; + } + + @Override + public float getPpcX(){ + return 0; + } + + @Override + public float getPpcY(){ + return 0; + } + + @Override + public float getDensity(){ + return 0; + } + + @Override + public boolean supportsDisplayModeChange(){ + return false; + } + + @Override + public Monitor getPrimaryMonitor(){ + return null; + } + + @Override + public Monitor getMonitor(){ + return null; + } + + @Override + public Monitor[] getMonitors(){ + return new Monitor[0]; + } + + @Override + public DisplayMode[] getDisplayModes(){ + return new DisplayMode[0]; + } + + @Override + public DisplayMode[] getDisplayModes(Monitor monitor){ + return new DisplayMode[0]; + } + + @Override + public DisplayMode getDisplayMode(){ + return null; + } + + @Override + public DisplayMode getDisplayMode(Monitor monitor){ + return null; + } + + @Override + public boolean setFullscreenMode(DisplayMode displayMode){ + return false; + } + + @Override + public boolean setWindowedMode(int width, int height){ + return false; + } + + @Override + public void setTitle(String title){ + + } + + @Override + public void setUndecorated(boolean undecorated){ + + } + + @Override + public void setResizable(boolean resizable){ + + } + + @Override + public void setVSync(boolean vsync){ + + } + + @Override + public BufferFormat getBufferFormat(){ + return null; + } + + @Override + public boolean supportsExtension(String extension){ + return false; + } + + @Override + public boolean isContinuousRendering(){ + return false; + } + + @Override + public void setContinuousRendering(boolean isContinuous){ + + } + + @Override + public void requestRendering(){ + + } + + @Override + public boolean isFullscreen(){ + return false; + } + + @Override + public Cursor newCursor(Pixmap pixmap, int xHotspot, int yHotspot){ + return null; + } + + @Override + protected void setCursor(Cursor cursor){ + + } + + @Override + protected void setSystemCursor(SystemCursor systemCursor){ + + } +} diff --git a/tests/src/test/java/power/ItemLiquidGeneratorTests.java b/tests/src/test/java/power/ItemLiquidGeneratorTests.java index 83f58a3e49..153b9ead50 100644 --- a/tests/src/test/java/power/ItemLiquidGeneratorTests.java +++ b/tests/src/test/java/power/ItemLiquidGeneratorTests.java @@ -7,12 +7,14 @@ import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.power.ItemLiquidGenerator; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestFactory; import java.util.ArrayList; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; /** @@ -30,8 +32,8 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ private final float fakeItemDuration = 60f; // 60 ticks private final float maximumLiquidUsage = 0.5f; - public void createGenerator(ItemLiquidGenerator.InputType inputType){ - generator = new ItemLiquidGenerator(inputType, "fakegen"){ + public void createGenerator(InputType inputType){ + generator = new ItemLiquidGenerator(inputType != InputType.liquids, inputType != InputType.items, "fakegen"){ { powerProduction = 0.1f; itemDuration = 60f; @@ -59,13 +61,13 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ DynamicTest[] generatorWorksProperlyWithLiquidInput(){ // Execute all tests for the case where only liquids are accepted and for the case where liquids and items are accepted (but supply only liquids) - ItemLiquidGenerator.InputType[] inputTypesToBeTested = new ItemLiquidGenerator.InputType[]{ - ItemLiquidGenerator.InputType.LiquidsOnly, - ItemLiquidGenerator.InputType.LiquidsAndItems + InputType[] inputTypesToBeTested = new InputType[]{ + InputType.liquids, + InputType.any }; ArrayList tests = new ArrayList<>(); - for(ItemLiquidGenerator.InputType inputType : inputTypesToBeTested){ + for(InputType inputType : inputTypesToBeTested){ tests.add(dynamicTest("01", () -> simulateLiquidConsumption(inputType, Liquids.oil, 0.0f, "No liquids provided"))); tests.add(dynamicTest("02", () -> simulateLiquidConsumption(inputType, Liquids.oil, maximumLiquidUsage / 4.0f, "Low oil provided"))); tests.add(dynamicTest("03", () -> simulateLiquidConsumption(inputType, Liquids.oil, maximumLiquidUsage * 1.0f, "Sufficient oil provided"))); @@ -77,7 +79,7 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ return testArray; } - void simulateLiquidConsumption(ItemLiquidGenerator.InputType inputType, Liquid liquid, float availableLiquidAmount, String parameterDescription){ + void simulateLiquidConsumption(InputType inputType, Liquid liquid, float availableLiquidAmount, String parameterDescription){ final float baseEfficiency = liquid.flammability; final float expectedEfficiency = Math.min(1.0f, availableLiquidAmount / maximumLiquidUsage) * baseEfficiency; final float expectedConsumptionPerTick = Math.min(maximumLiquidUsage, availableLiquidAmount); @@ -87,7 +89,7 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ assertTrue(generator.acceptLiquid(tile, null, liquid, availableLiquidAmount), inputType + " | " + parameterDescription + ": Liquids which will be declined by the generator don't need to be tested - The code won't be called for those cases."); entity.liquids.add(liquid, availableLiquidAmount); - entity.cons.update(tile.entity); + entity.cons.update(); assertTrue(entity.cons.valid()); // Perform an update on the generator once - This should use up any resource up to the maximum liquid usage @@ -102,19 +104,19 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ DynamicTest[] generatorWorksProperlyWithItemInput(){ // Execute all tests for the case where only items are accepted and for the case where liquids and items are accepted (but supply only items) - ItemLiquidGenerator.InputType[] inputTypesToBeTested = new ItemLiquidGenerator.InputType[]{ - ItemLiquidGenerator.InputType.ItemsOnly, - ItemLiquidGenerator.InputType.LiquidsAndItems + InputType[] inputTypesToBeTested = new InputType[]{ + InputType.items, + InputType.any }; ArrayList tests = new ArrayList<>(); - for(ItemLiquidGenerator.InputType inputType : inputTypesToBeTested){ + for(InputType inputType : inputTypesToBeTested){ tests.add(dynamicTest("01", () -> simulateItemConsumption(inputType, Items.coal, 0, "No items provided"))); tests.add(dynamicTest("02", () -> simulateItemConsumption(inputType, Items.coal, 1, "Sufficient coal provided"))); tests.add(dynamicTest("03", () -> simulateItemConsumption(inputType, Items.coal, 10, "Excess coal provided"))); tests.add(dynamicTest("04", () -> simulateItemConsumption(inputType, Items.blastCompound, 1, "Blast compound provided"))); //dynamicTest("03", () -> simulateItemConsumption(inputType, Items.plastanium, 1, "Plastanium provided")), // Not accepted by generator due to low flammability - tests.add(dynamicTest("05", () -> simulateItemConsumption(inputType, Items.biomatter, 1, "Biomatter provided"))); + tests.add(dynamicTest("05", () -> simulateItemConsumption(inputType, Items.sporePod, 1, "Biomatter provided"))); tests.add(dynamicTest("06", () -> simulateItemConsumption(inputType, Items.pyratite, 1, "Pyratite provided"))); } DynamicTest[] testArray = new DynamicTest[tests.size()]; @@ -122,8 +124,8 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ return testArray; } - void simulateItemConsumption(ItemLiquidGenerator.InputType inputType, Item item, int amount, String parameterDescription){ - final float expectedEfficiency = Math.min(1.0f, amount > 0 ? item.flammability : 0f); + void simulateItemConsumption(InputType inputType, Item item, int amount, String parameterDescription){ + final float expectedEfficiency = amount > 0 ? item.flammability : 0f; final float expectedRemainingItemAmount = Math.max(0, amount - 1); createGenerator(inputType); @@ -132,7 +134,7 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ if(amount > 0){ entity.items.add(item, amount); } - entity.cons.update(tile.entity); + entity.cons.update(); assertTrue(entity.cons.valid()); // Perform an update on the generator once - This should use up one or zero items - dependent on if the item is accepted and available or not. @@ -145,21 +147,21 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ /** Makes sure the efficiency stays equal during the item duration. */ @Test void efficiencyRemainsConstantWithinItemDuration_ItemsOnly(){ - testItemDuration(ItemLiquidGenerator.InputType.ItemsOnly); + testItemDuration(InputType.items); } /** Makes sure the efficiency stays equal during the item duration. */ @Test void efficiencyRemainsConstantWithinItemDuration_ItemsAndLiquids(){ - testItemDuration(ItemLiquidGenerator.InputType.LiquidsAndItems); + testItemDuration(InputType.any); } - void testItemDuration(ItemLiquidGenerator.InputType inputType){ + void testItemDuration(InputType inputType){ createGenerator(inputType); // Burn a single coal and test for the duration entity.items.add(Items.coal, 1); - entity.cons.update(tile.entity); + entity.cons.update(); generator.update(tile); float expectedEfficiency = entity.productionEfficiency; @@ -172,4 +174,10 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ generator.update(tile); assertEquals(0.0f, entity.productionEfficiency, "Duration: " + String.valueOf(currentDuration)); } + + enum InputType{ + items, + liquids, + any + } } diff --git a/tests/src/test/java/power/PowerTestFixture.java b/tests/src/test/java/power/PowerTestFixture.java index 38db7cc8a6..e94a52ac55 100644 --- a/tests/src/test/java/power/PowerTestFixture.java +++ b/tests/src/test/java/power/PowerTestFixture.java @@ -1,5 +1,6 @@ package power; +import io.anuke.arc.Core; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; @@ -24,22 +25,21 @@ import java.lang.reflect.Field; * Note: All tests which subclass this will run with a fixed delta of 0.5! * */ public class PowerTestFixture{ - public static final float smallRoundingTolerance = Mathf.FLOAT_ROUNDING_ERROR; public static final float mediumRoundingTolerance = Mathf.FLOAT_ROUNDING_ERROR * 10; public static final float highRoundingTolerance = Mathf.FLOAT_ROUNDING_ERROR * 100; @BeforeAll static void initializeDependencies(){ + Core.graphics = new FakeGraphics(); Vars.content = new ContentLoader(); Vars.content.load(); Time.setDeltaProvider(() -> 0.5f); } protected static PowerGenerator createFakeProducerBlock(float producedPower){ - // Multiply produced power by 2 since production efficiency is defined to be 0.5 = 100% return new PowerGenerator("fakegen"){{ - powerProduction = producedPower * 2.0f; + powerProduction = producedPower; }}; } @@ -49,9 +49,9 @@ public class PowerTestFixture{ }}; } - protected static Block createFakeDirectConsumer(float powerPerTick, float minimumSatisfaction){ + protected static Block createFakeDirectConsumer(float powerPerTick){ return new PowerBlock("fakedirectconsumer"){{ - consumes.power(powerPerTick, minimumSatisfaction); + consumes.power(powerPerTick); }}; } @@ -85,7 +85,7 @@ public class PowerTestFixture{ // Simulate the "changed" method. Calling it through reflections would require half the game to be initialized. tile.entity = block.newEntity().init(tile, false); - tile.entity.cons = new ConsumeModule(); + tile.entity.cons = new ConsumeModule(tile.entity); if(block.hasItems) tile.entity.items = new ItemModule(); if(block.hasLiquids) tile.entity.liquids = new LiquidModule(); if(block.hasPower){ @@ -99,7 +99,7 @@ public class PowerTestFixture{ return tile; }catch(Exception ex){ - return null; + throw new RuntimeException(ex); } } } diff --git a/tests/src/test/java/power/PowerTests.java b/tests/src/test/java/power/PowerTests.java index db37e3668a..a722e4ed69 100644 --- a/tests/src/test/java/power/PowerTests.java +++ b/tests/src/test/java/power/PowerTests.java @@ -1,5 +1,6 @@ package power; +import io.anuke.arc.Core; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.world.Tile; @@ -21,8 +22,9 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest; */ public class PowerTests extends PowerTestFixture{ - @BeforeEach - void initTest(){ + @BeforeAll + static void init(){ + Core.graphics = new FakeGraphics(); } @Nested @@ -39,8 +41,8 @@ public class PowerTests extends PowerTestFixture{ // That's why we inject the description into the test method for now. // Additional Note: If you don't see any labels in front of the values supplied as function parameters, use a better IDE like IntelliJ IDEA. dynamicTest("01", () -> simulateDirectConsumption(0.0f, 1.0f, 0.0f, "0.0 produced, 1.0 consumed (no power available)")), - dynamicTest("02", () -> simulateDirectConsumption(0.0f, 0.0f, 0.0f, "0.0 produced, 0.0 consumed (no power anywhere)")), - dynamicTest("03", () -> simulateDirectConsumption(1.0f, 0.0f, 0.0f, "1.0 produced, 0.0 consumed (no power requested)")), + dynamicTest("02", () -> simulateDirectConsumption(0.0f, 0.0f, 1.0f, "0.0 produced, 0.0 consumed (no power anywhere)")), + dynamicTest("03", () -> simulateDirectConsumption(1.0f, 0.0f, 1.0f, "1.0 produced, 0.0 consumed (no power requested)")), dynamicTest("04", () -> simulateDirectConsumption(1.0f, 1.0f, 1.0f, "1.0 produced, 1.0 consumed (stable consumption)")), dynamicTest("05", () -> simulateDirectConsumption(0.5f, 1.0f, 0.5f, "0.5 produced, 1.0 consumed (power shortage)")), dynamicTest("06", () -> simulateDirectConsumption(1.0f, 0.5f, 1.0f, "1.0 produced, 0.5 consumed (power excess)")), @@ -49,8 +51,8 @@ public class PowerTests extends PowerTestFixture{ } void simulateDirectConsumption(float producedPower, float requiredPower, float expectedSatisfaction, String parameterDescription){ Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower)); - producerTile.entity().productionEfficiency = 0.5f; // Currently, 0.5f = 100% - Tile directConsumerTile = createFakeTile(0, 1, createFakeDirectConsumer(requiredPower, 0.6f)); + producerTile.entity().productionEfficiency = 1f; + Tile directConsumerTile = createFakeTile(0, 1, createFakeDirectConsumer(requiredPower)); PowerGraph powerGraph = new PowerGraph(); powerGraph.add(producerTile); @@ -89,7 +91,7 @@ public class PowerTests extends PowerTestFixture{ } void simulateBufferedConsumption(float producedPower, float maxBuffer, float powerConsumedPerTick, float initialSatisfaction, float expectedSatisfaction, String parameterDescription){ Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower)); - producerTile.entity().productionEfficiency = 0.5f; // Currently, 0.5 = 100% + producerTile.entity().productionEfficiency = 1f; Tile bufferedConsumerTile = createFakeTile(0, 1, createFakeBufferedConsumer(maxBuffer, maxBuffer > 0.0f ? maxBuffer/powerConsumedPerTick : 1.0f)); bufferedConsumerTile.entity.power.satisfaction = initialSatisfaction; @@ -134,12 +136,12 @@ public class PowerTests extends PowerTestFixture{ if(producedPower > 0.0f){ Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(producedPower)); - producerTile.entity().productionEfficiency = 0.5f; + producerTile.entity().productionEfficiency = 1f; powerGraph.add(producerTile); } Tile directConsumerTile = null; if(requestedPower > 0.0f){ - directConsumerTile = createFakeTile(0, 1, createFakeDirectConsumer(requestedPower, 0.6f)); + directConsumerTile = createFakeTile(0, 1, createFakeDirectConsumer(requestedPower)); powerGraph.add(directConsumerTile); } float maxCapacity = 100f; @@ -160,7 +162,7 @@ public class PowerTests extends PowerTestFixture{ void directConsumptionStopsWithNoPower(){ Tile producerTile = createFakeTile(0, 0, createFakeProducerBlock(10.0f)); producerTile.entity().productionEfficiency = 1.0f; - Tile consumerTile = createFakeTile(0, 1, createFakeDirectConsumer(5.0f, 0.6f)); + Tile consumerTile = createFakeTile(0, 1, createFakeDirectConsumer(5.0f)); PowerGraph powerGraph = new PowerGraph(); powerGraph.add(producerTile); diff --git a/tools/build.gradle b/tools/build.gradle index e0a9db056c..dd9ecd0cbb 100644 --- a/tools/build.gradle +++ b/tools/build.gradle @@ -11,15 +11,23 @@ import java.awt.image.BufferedImage def outFolder = "../core/assets-raw/sprites_out/" def genFolder = "../core/assets-raw/sprites_out/generated/" +def packFile = "../core/assets-raw/sprites/pack.json" +def doAntialias = !project.hasProperty("disableAntialias") + def antialias = {File file -> + if(!doAntialias || file.lastModified() <= 1000) return + def image = ImageIO.read(file) def out = ImageIO.read(file) def getRGB = { int ix, int iy -> + //if(ix <= 0 || iy <= 0 || ix >= image.width || iy >= image.height) return 0 return image.getRGB(Math.max(Math.min(ix, image.width - 1), 0), Math.max(Math.min(iy, image.height - 1), 0)) } def color = new Color() + def color2 = new Color() def sum = new Color() + def suma = new Color() for (int x = 0; x < image.getWidth(); x++){ for(int y = 0; y < image.getHeight(); y++){ @@ -45,18 +53,30 @@ def antialias = {File file -> if ((F==H && F!=B && H!=D && E!=G) || (H==D && H!=F && D!=B && E!=I)) p8=H if (F==H && F!=B && H!=D) p9=F - int total = 0 + suma.set(0) [p1, p2, p3, p4, p5, p6, p7, p8, p9].each{ val -> Color.argb8888ToColor(color, val) + suma.r += color.r*color.a + suma.g += color.g*color.a + suma.b += color.b*color.a + suma.a += color.a + } - if(color.a > 0.1){ - sum.r += color.r - sum.g += color.g - sum.b += color.b - sum.a += color.a - total++ - } + suma.mul(suma.a <= 0.001f ? 0f : (float)(1f / suma.a)) + + float total = 0 + sum.set(0) + + [p1, p2, p3, p4, p5, p6, p7, p8, p9].each{ val -> + Color.argb8888ToColor(color, val) + float a = color.a + color.lerp(suma, (float)(1f - a)) + sum.r += color.r + sum.g += color.g + sum.b += color.b + sum.a += a + total += 1f } sum.mul((float)(1f / total)) @@ -68,7 +88,6 @@ def antialias = {File file -> ImageIO.write(out, "png", file) } - task swapColors(){ doLast{ if (project.hasProperty("colors")) { @@ -112,6 +131,7 @@ task scaleSprites4x(){ def scaled = new BufferedImage(image.getWidth() * 2, image.getHeight() * 2, BufferedImage.TYPE_INT_ARGB) def getRGB = { int ix, int iy -> + //if(ix <= 0 || iy <= 0 || ix >= image.width || iy >= image.height) return 0 return image.getRGB(Math.max(Math.min(ix, image.width - 1), 0), Math.max(Math.min(iy, image.height - 1), 0)) } @@ -154,7 +174,6 @@ task scaleSprites4x(){ } } - task scaleSprites(){ finalizedBy 'genSprites' diff --git a/tools/src/io/anuke/mindustry/Generators.java b/tools/src/io/anuke/mindustry/Generators.java index cac0ece66d..7e1f0106e5 100644 --- a/tools/src/io/anuke/mindustry/Generators.java +++ b/tools/src/io/anuke/mindustry/Generators.java @@ -2,15 +2,22 @@ package io.anuke.mindustry; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Log; -import io.anuke.mindustry.entities.units.UnitType; +import io.anuke.mindustry.ImagePacker.GenRegion; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Mech; +import io.anuke.mindustry.type.UnitType; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; +import io.anuke.mindustry.world.blocks.Floor; import io.anuke.mindustry.world.blocks.OreBlock; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.tilesize; @@ -19,34 +26,126 @@ public class Generators { public static void generate(){ ImagePacker.generate("block-icons", () -> { + Image colors = new Image(256, 1); + Color outlineColor = new Color(0, 0, 0, 0.3f); + for(Block block : content.blocks()){ TextureRegion[] regions = block.getGeneratedIcons(); + try{ + if(block instanceof Floor){ + block.load(); + for(TextureRegion region : block.variantRegions()){ + GenRegion gen = (GenRegion)region; + if(gen.path == null) continue; + Files.copy(gen.path, Paths.get("../editor/editor-" + gen.path.getFileName())); + } + } + }catch(IOException e){ + throw new RuntimeException(e); + } + if(regions.length == 0){ continue; } try{ - Image image = ImagePacker.get(regions[0]); + Image last = null; + if(block.outlineIcon){ + int radius = 3; + GenRegion region = (GenRegion)regions[regions.length-1]; + Image base = ImagePacker.get(region); + Image out = last = new Image(region.getWidth(), region.getHeight()); + for(int x = 0; x < out.width(); x++){ + for(int y = 0; y < out.height(); y++){ - for(TextureRegion region : regions){ - image.draw(region); + Color color = base.getColor(x, y); + if(color.a >= 0.01f){ + out.draw(x, y, color); + }else{ + boolean found = false; + outer: + for(int rx = -radius; rx <= radius; rx++){ + for(int ry = -radius; ry <= radius; ry++){ + if(Mathf.dst(rx, ry) <= radius && base.getColor(rx + x, ry + y).a > 0.01f){ + found = true; + break outer; + } + } + } + if(found){ + out.draw(x, y, outlineColor); + } + } + } + } + + try{ + Files.delete(region.path); + }catch(IOException e){ + e.printStackTrace(); + } + + out.save(block.name); } - image.save(block.name + "-icon-full"); + Image image = ImagePacker.get(regions[0]); + + int i = 0; + for(TextureRegion region : regions){ + i ++; + if(i != regions.length || last == null){ + image.draw(region); + }else{ + image.draw(last); + } + } + + if(regions.length > 1){ + image.save(block.name + "-icon-full"); + } + + image.save("../editor/" + block.name + "-icon-editor"); for(Icon icon : Icon.values()){ - if(icon.size == 0) continue; + if(icon.size == 0 || (icon.size == image.width() && icon.size == image.height())) continue; Image scaled = new Image(icon.size, icon.size); scaled.drawScaled(image); scaled.save(block.name + "-icon-" + icon.name()); } + + Color average = new Color(); + for(int x = 0; x < image.width(); x++){ + for(int y = 0; y < image.height(); y++){ + Color color = image.getColor(x, y); + average.r += color.r; + average.g += color.g; + average.b += color.b; + } + } + average.mul(1f / (image.width() * image.height())); + average.a = 1f; + colors.draw(block.id, 0, average); }catch(IllegalArgumentException e){ Log.info("Skipping &ly'{0}'", block.name); }catch(NullPointerException e){ Log.err("Block &ly'{0}'&lr has an null region!"); } } + + colors.save("../../../assets/sprites/block_colors"); + }); + + ImagePacker.generate("item-icons", () -> { + for(Item item : content.items()){ + Image base = ImagePacker.get("item-" + item.name); + for(Item.Icon icon : Item.Icon.values()){ + if(icon.size == base.width()) continue; + Image image = new Image(icon.size, icon.size); + image.drawScaled(base); + image.save("item-" + item.name + "-" + icon.name(), false); + } + } }); ImagePacker.generate("mech-icons", () -> { @@ -64,10 +163,10 @@ public class Generators { image.drawCenter(mech.region); } - int off = (image.width() - mech.weapon.equipRegion.getWidth())/2; + int off = image.width()/2 - mech.weapon.region.getWidth()/2; - image.draw(mech.weapon.equipRegion, -(int)mech.weaponOffsetX + off, (int)mech.weaponOffsetY + off, false, false); - image.draw(mech.weapon.equipRegion, (int)mech.weaponOffsetX + off, (int)mech.weaponOffsetY + off, true, false); + image.draw(mech.weapon.region, -(int)mech.weaponOffsetX + off, (int)mech.weaponOffsetY + off + 4, false, false); + image.draw(mech.weapon.region, (int)mech.weaponOffsetX + off, (int)mech.weaponOffsetY + off + 4, true, false); image.save("mech-icon-" + mech.name); @@ -76,27 +175,26 @@ public class Generators { ImagePacker.generate("unit-icons", () -> { for(UnitType type : content.getBy(ContentType.unit)){ + if(type.isFlying) continue; type.load(); type.weapon.load(); Image image = ImagePacker.get(type.region); - if(!type.isFlying){ - image.draw(type.baseRegion); - image.draw(type.legRegion); - image.draw(type.legRegion, true, false); - image.draw(type.region); + image.draw(type.baseRegion); + image.draw(type.legRegion); + image.draw(type.legRegion, true, false); + image.draw(type.region); - image.draw(type.weapon.equipRegion, - -(int)type.weaponOffsetX + (image.width() - type.weapon.equipRegion.getWidth())/2, - (int)type.weaponOffsetY - (image.height() - type.weapon.equipRegion.getHeight())/2 + 1, - false, false); - image.draw(type.weapon.equipRegion, - (int)type.weaponOffsetX + (image.width() - type.weapon.equipRegion.getWidth())/2, - (int)type.weaponOffsetY - (image.height() - type.weapon.equipRegion.getHeight())/2 + 1, - true, false); - } + image.draw(type.weapon.region, + -(int)type.weapon.width + image.width()/2 - type.weapon.region.getWidth()/2, + (int)type.weaponOffsetY - image.height()/2 - type.weapon.region.getHeight()/2 + 1, + false, false); + image.draw(type.weapon.region, + (int)type.weapon.width + image.width()/2 - type.weapon.region.getWidth()/2, + (int)type.weaponOffsetY - image.height()/2 - type.weapon.region.getHeight()/2 + 1, + true, false); image.save("unit-icon-" + type.name); } @@ -130,7 +228,8 @@ public class Generators { } image.draw(ImagePacker.get(item.name + (i+1))); - image.save("ore-" + item.name + "-" + base.name + (i+1)); + image.save("../blocks/environment/ore-" + item.name + "-" + base.name + (i+1)); + image.save("../editor/editor-ore-" + item.name + "-" + base.name + (i+1)); //save icons image.save(block.name + "-icon-full"); @@ -143,6 +242,33 @@ public class Generators { } } }); + + ImagePacker.generate("edges", () -> { + for(Block block : content.blocks()){ + if(!(block instanceof Floor)) continue; + + Floor floor = (Floor)block; + + if(ImagePacker.has(floor.name + "-edge") || floor.blendGroup != floor){ + continue; + } + + try{ + Image image = ImagePacker.get(floor.generateIcons()[0]); + Image edge = ImagePacker.get("edge-stencil-" + floor.edgeStyle); + Image result = new Image(edge.width(), edge.height()); + + for(int x = 0; x < edge.width(); x++){ + for(int y = 0; y < edge.height(); y++){ + result.draw(x, y, edge.getColor(x, y).mul(image.getColor(x % image.width(), y % image.height()))); + } + } + + result.save("../blocks/environment/" + floor.name + "-edge"); + + }catch(Exception ignored){} + } + }); } } diff --git a/tools/src/io/anuke/mindustry/Image.java b/tools/src/io/anuke/mindustry/Image.java index e97babec9b..d64214501c 100644 --- a/tools/src/io/anuke/mindustry/Image.java +++ b/tools/src/io/anuke/mindustry/Image.java @@ -52,6 +52,7 @@ class Image { } Color getColor(int x, int y){ + if(!Structs.inBounds(x, y, width(), height())) return color.set(0, 0, 0, 0); int i = image.getRGB(x, y); Color.argb8888ToColor(color, i); return color; @@ -100,21 +101,11 @@ class Image { int ofx = 0, ofy = 0; - if(x < 0){ - ofx = x; - x = 0; - } - - if(y < 0){ - ofy = y; - y = 0; - } - graphics.drawImage(ImagePacker.get(region).image, x, y, x + region.getWidth(), y + region.getHeight(), - (flipx ? region.getWidth() : 0) + ofx, + (flipx ? region.getWidth() : 0) + ofx, (flipy ? region.getHeight() : 0) + ofy, (flipx ? 0 : region.getWidth()) + ofx, (flipy ? 0 : region.getHeight()) + ofy, @@ -130,6 +121,13 @@ class Image { } } + void save(String name, boolean antialias){ + save(name); + if(!antialias){ + new File(name + ".png").setLastModified(0); + } + } + static int total(){ return toDispose.size(); } diff --git a/tools/src/io/anuke/mindustry/ImagePacker.java b/tools/src/io/anuke/mindustry/ImagePacker.java index 2b696bbea5..2d0e683a7f 100644 --- a/tools/src/io/anuke/mindustry/ImagePacker.java +++ b/tools/src/io/anuke/mindustry/ImagePacker.java @@ -16,6 +16,7 @@ import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; public class ImagePacker{ @@ -38,7 +39,7 @@ public class ImagePacker{ fname = fname.substring(0, fname.length() - 4); BufferedImage image = ImageIO.read(path.toFile()); - GenRegion region = new GenRegion(fname){ + GenRegion region = new GenRegion(fname, path){ @Override public int getX(){ @@ -73,13 +74,21 @@ public class ImagePacker{ @Override public AtlasRegion find(String name){ if(!regionCache.containsKey(name)){ - GenRegion region = new GenRegion(name); + GenRegion region = new GenRegion(name, null); region.invalid = true; return region; } return (AtlasRegion)regionCache.get(name); } + @Override + public AtlasRegion find(String name, TextureRegion def){ + if(!regionCache.containsKey(name)){ + return (AtlasRegion)def; + } + return (AtlasRegion)regionCache.get(name); + } + @Override public boolean has(String s) { return regionCache.containsKey(s); @@ -111,6 +120,10 @@ public class ImagePacker{ return get(Core.atlas.find(name)); } + static boolean has(String name){ + return Core.atlas.has(name); + } + static Image get(TextureRegion region){ GenRegion.validate(region); @@ -118,15 +131,17 @@ public class ImagePacker{ } static void err(String message, Object... args){ - throw new IllegalArgumentException(Strings.formatArgs(message, args)); + throw new IllegalArgumentException(Strings.format(message, args)); } static class GenRegion extends AtlasRegion{ String name; boolean invalid; + Path path; - GenRegion(String name){ + GenRegion(String name, Path path){ this.name = name; + this.path = path; } static void validate(TextureRegion region){