diff --git a/.gitignore b/.gitignore index 611dd73e9a..b33484f175 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -##Packr, build stuff - logs/ /core/assets/mindustry-saves/ /core/assets/mindustry-maps/ @@ -13,8 +11,10 @@ logs/ /desktop/gifexport/ /core/lib/ /core/assets-raw/sprites/generated/ +/core/assets-raw/sprites_out/ /annotations/build/ -/kryonet/build/ +/annotations/out/ +/net/build/ /tools/build/ /tests/build/ /server/build/ diff --git a/README.md b/README.md index f6fbd91e13..30591a6ed7 100644 --- a/README.md +++ b/README.md @@ -3,25 +3,24 @@ [![Build Status](https://travis-ci.org/Anuken/Mindustry.svg?branch=master)](https://travis-ci.org/Anuken/Mindustry) [![Discord](https://img.shields.io/discord/391020510269669376.svg)](https://discord.gg/mindustry) -A pixelated sandbox tower defense game made using [LibGDX](https://libgdx.badlogicgames.com/). Winner of the [GDL Metal Monstrosity Jam](https://itch.io/jam/gdl---metal-monstrosity-jam). +A sandbox tower defense game written in Java. _[Trello Board](https://trello.com/b/aE2tcUwF/mindustry-40-plans)_ -_[Wiki](http://mindustry.wikia.com/wiki/Mindustry_Wiki)_ -_[Discord](https://discord.gg/r8BkXNd)_ +_[Wiki](http://mindustry.wikia.com/wiki/Mindustry_Wiki)_ ### Building 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` diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index b0e4475812..989b5dd893 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -17,6 +17,7 @@ android:appCategory="game" android:label="@string/app_name" android:theme="@style/GdxTheme" android:fullBackupContent="@xml/backup_rules"> + (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/res/values-ru/strings.xml b/android/res/values-ru/strings.xml index 686a1ea4c7..6eb672b67a 100644 --- a/android/res/values-ru/strings.xml +++ b/android/res/values-ru/strings.xml @@ -5,7 +5,7 @@ 1 Доллар 2 Доллара - 5 Доллара + 5 Долларов 10 Долларов 15 Долларов 25 Долларов diff --git a/android/res/values-uk/strings.xml b/android/res/values-uk/strings.xml new file mode 100644 index 0000000000..f1303715ff --- /dev/null +++ b/android/res/values-uk/strings.xml @@ -0,0 +1,15 @@ + + + + Mindustry + + 1 Доллар + 2 Доллара + 5 Долларів + 10 Долларів + 15 Долларів + 25 Долларів + 50 Долларів + + + diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java index c75b6af249..8fbb105dc4 100644 --- a/android/src/io/anuke/mindustry/AndroidLauncher.java +++ b/android/src/io/anuke/mindustry/AndroidLauncher.java @@ -11,25 +11,25 @@ import android.os.Bundle; import android.provider.Settings.Secure; import android.telephony.TelephonyManager; import android.util.Log; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.utils.Base64Coder; import com.google.android.gms.common.GoogleApiAvailability; import com.google.android.gms.common.GooglePlayServicesNotAvailableException; import com.google.android.gms.common.GooglePlayServicesRepairableException; import com.google.android.gms.security.ProviderInstaller; -import io.anuke.kryonet.KryoClient; -import io.anuke.kryonet.KryoServer; +import io.anuke.arc.Core; +import io.anuke.arc.backends.android.surfaceview.AndroidApplication; +import io.anuke.arc.backends.android.surfaceview.AndroidApplicationConfiguration; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.scene.ui.layout.Unit; +import io.anuke.arc.util.Strings; +import io.anuke.arc.util.serialization.Base64Coder; +import io.anuke.net.KryoClient; +import io.anuke.net.KryoServer; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.game.Saves.SaveSlot; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.ui.dialogs.FileChooser; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Strings; import java.io.File; import java.io.FileInputStream; @@ -39,7 +39,7 @@ import java.util.ArrayList; import static io.anuke.mindustry.Vars.*; -public class AndroidLauncher extends PatchedAndroidApplication{ +public class AndroidLauncher extends AndroidApplication{ public static final int PERMISSION_REQUEST_CODE = 1; boolean doubleScaleTablets = true; FileChooser chooser; @@ -49,6 +49,7 @@ public class AndroidLauncher extends PatchedAndroidApplication{ super.onCreate(savedInstanceState); AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); config.useImmersiveMode = true; + config.depth = 0; Platform.instance = new Platform(){ @Override @@ -161,23 +162,23 @@ public class AndroidLauncher extends PatchedAndroidApplication{ InputStream inStream; if(myFile != null) inStream = new FileInputStream(myFile); else inStream = getContentResolver().openInputStream(uri); - Gdx.app.postRunnable(() -> { + Core.app.post(() -> { if(save){ //open save System.out.println("Opening save."); - FileHandle file = Gdx.files.local("temp-save." + saveExtension); + FileHandle file = Core.files.local("temp-save." + saveExtension); file.write(inStream, false); if(SaveIO.isSaveValid(file)){ try{ SaveSlot slot = control.saves.importSave(file); ui.load.runLoadSave(slot); }catch(IOException e){ - ui.showError(Bundles.format("text.save.import.fail", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("text.save.import.fail", Strings.parseException(e, false))); } }else{ ui.showError("$text.save.import.invalid"); } }else if(map){ //open map - Gdx.app.postRunnable(() -> { + Core.app.post(() -> { System.out.println("Opening map."); if(!ui.editor.isShown()){ ui.editor.show(); diff --git a/android/src/io/anuke/mindustry/PatchedAndroidApplication.java b/android/src/io/anuke/mindustry/PatchedAndroidApplication.java deleted file mode 100644 index 3ed0df141e..0000000000 --- a/android/src/io/anuke/mindustry/PatchedAndroidApplication.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.anuke.mindustry; - -import com.badlogic.gdx.backends.android.AndroidApplication; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -public class PatchedAndroidApplication extends AndroidApplication { - private final ExecutorService exec = Executors.newSingleThreadExecutor(); - - @Override - protected void onPause () { - if(useImmersiveMode) { - exec.submit(() -> { - try {Thread.sleep(100);} catch (InterruptedException ignored) {} - graphics.onDrawFrame(null); - }); - } - super.onPause(); - } -} \ No newline at end of file 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/RemoteMethodAnnotationProcessor.java b/annotations/src/main/java/io/anuke/annotations/RemoteMethodAnnotationProcessor.java index 2762b03a8e..1c5bb5301d 100644 --- a/annotations/src/main/java/io/anuke/annotations/RemoteMethodAnnotationProcessor.java +++ b/annotations/src/main/java/io/anuke/annotations/RemoteMethodAnnotationProcessor.java @@ -28,6 +28,8 @@ import java.util.stream.Collectors; public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ /** Maximum size of each event packet. */ public static final int maxPacketSize = 4096; + /** Warning on top of each autogenerated file.*/ + public static final String autogenWarning = "Autogenerated file. Do not modify!\n"; /** Name of the base package to put all the generated classes. */ private static final String packageName = "io.anuke.mindustry.gen"; @@ -136,6 +138,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ //create class for storing unique method hash TypeSpec.Builder hashBuilder = TypeSpec.classBuilder("MethodHash").addModifiers(Modifier.PUBLIC); + hashBuilder.addJavadoc(autogenWarning); hashBuilder.addField(FieldSpec.builder(int.class, "HASH", Modifier.STATIC, Modifier.PUBLIC, Modifier.FINAL) .initializer("$1L", Objects.hash(methods)).build()); diff --git a/annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java b/annotations/src/main/java/io/anuke/annotations/RemoteReadGenerator.java index 524e590847..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; @@ -28,7 +26,7 @@ public class RemoteReadGenerator{ /** * Generates a class for reading remote invoke packets. * - * @param entries List of methods to use/ + * @param entries List of methods to use. * @param className Simple target class name. * @param packageName Full target package name. * @param needsPlayer Whether this read method requires a reference to the player sender. @@ -37,6 +35,7 @@ public class RemoteReadGenerator{ throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException{ TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC); + classBuilder.addJavadoc(RemoteMethodAnnotationProcessor.autogenWarning); //create main method builder MethodSpec.Builder readMethod = MethodSpec.methodBuilder("readPacket") @@ -51,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 51845d0900..2f195aa896 100644 --- a/annotations/src/main/java/io/anuke/annotations/RemoteWriteGenerator.java +++ b/annotations/src/main/java/io/anuke/annotations/RemoteWriteGenerator.java @@ -29,6 +29,7 @@ public class RemoteWriteGenerator{ for(ClassEntry entry : entries){ //create builder TypeSpec.Builder classBuilder = TypeSpec.classBuilder(entry.name).addModifiers(Modifier.PUBLIC); + classBuilder.addJavadoc(RemoteMethodAnnotationProcessor.autogenWarning); //add temporary write buffer classBuilder.addField(FieldSpec.builder(ByteBuffer.class, "TEMP_BUFFER", Modifier.STATIC, Modifier.PRIVATE, Modifier.FINAL) @@ -79,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; } @@ -129,7 +130,7 @@ public class RemoteWriteGenerator{ method.beginControlFlow("if(" + getCheckString(methodEntry.where) + ")"); //add statement to create packet from pool - method.addStatement("$1N packet = $2N.obtain($1N.class, $1N::new)", "io.anuke.mindustry.net.Packets.InvokePacket", "io.anuke.ucore.util.Pooling"); + method.addStatement("$1N packet = $2N.obtain($1N.class, $1N::new)", "io.anuke.mindustry.net.Packets.InvokePacket", "io.anuke.arc.util.pooling.Pools"); //assign buffer method.addStatement("packet.writeBuffer = TEMP_BUFFER"); //assign priority diff --git a/annotations/src/main/java/io/anuke/annotations/SerializeAnnotationProcessor.java b/annotations/src/main/java/io/anuke/annotations/SerializeAnnotationProcessor.java index e42b877495..1f8450cd13 100644 --- a/annotations/src/main/java/io/anuke/annotations/SerializeAnnotationProcessor.java +++ b/annotations/src/main/java/io/anuke/annotations/SerializeAnnotationProcessor.java @@ -12,6 +12,7 @@ import javax.lang.model.util.ElementFilter; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.lang.reflect.Field; import java.util.List; import java.util.Set; @@ -46,6 +47,7 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{ TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC); classBuilder.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"unchecked\"").build()); + classBuilder.addJavadoc(RemoteMethodAnnotationProcessor.autogenWarning); MethodSpec.Builder method = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC); for(TypeElement elem : elements){ @@ -53,20 +55,18 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{ TypeSpec.Builder serializer = TypeSpec.anonymousClassBuilder("") .addSuperinterface(ParameterizedTypeName.get( - ClassName.bestGuess("io.anuke.ucore.io.TypeSerializer"), type)); + ClassName.bestGuess("io.anuke.arc.Settings.TypeSerializer"), type)); MethodSpec.Builder writeMethod = MethodSpec.methodBuilder("write") .returns(void.class) .addParameter(DataOutput.class, "stream") .addParameter(type, "object") - .addAnnotation(Override.class) .addException(IOException.class) .addModifiers(Modifier.PUBLIC); MethodSpec.Builder readMethod = MethodSpec.methodBuilder("read") .returns(type) .addParameter(DataInput.class, "stream") - .addAnnotation(Override.class) .addException(IOException.class) .addModifiers(Modifier.PUBLIC); @@ -84,8 +84,8 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{ writeMethod.addStatement("stream.write" + capName + "(object." + name + ")"); readMethod.addStatement("object." + name + "= stream.read" + capName + "()"); }else{ - writeMethod.addStatement("io.anuke.ucore.core.Settings.getSerializer(" + typeName+ ".class).write(stream, object." + name + ")"); - readMethod.addStatement("object." + name + " = (" +typeName+")io.anuke.ucore.core.Settings.getSerializer(" + typeName+ ".class).read(stream)"); + writeMethod.addStatement("io.anuke.arc.Core.settings.getSerializer(" + typeName+ ".class).write(stream, object." + name + ")"); + readMethod.addStatement("object." + name + " = (" +typeName+")io.anuke.arc.Core.settings.getSerializer(" + typeName+ ".class).read(stream)"); } } @@ -94,7 +94,18 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{ serializer.addMethod(writeMethod.build()); serializer.addMethod(readMethod.build()); - method.addStatement("io.anuke.ucore.core.Settings.setSerializer($N, $L)", Utils.elementUtils.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build()); + method.addStatement("io.anuke.arc.Core.settings.setSerializer($N, $L)", Utils.elementUtils.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build()); + + String sname = type.toString().substring(type.toString().lastIndexOf('.') + 1); + + name(writeMethod, "write" + sname); + name(readMethod, "read" + sname); + + writeMethod.addModifiers(Modifier.STATIC); + readMethod.addModifiers(Modifier.STATIC); + + classBuilder.addMethod(writeMethod.build()); + classBuilder.addMethod(readMethod.build()); } classBuilder.addMethod(method.build()); @@ -108,4 +119,14 @@ public class SerializeAnnotationProcessor extends AbstractProcessor{ throw new RuntimeException(e); } } + + static void name(MethodSpec.Builder builder, String name){ + try{ + Field field = builder.getClass().getDeclaredField("name"); + field.setAccessible(true); + field.set(builder, name); + }catch(Exception e){ + throw new RuntimeException(e); + } + } } 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 abaf08b053..8fb24f284b 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ buildscript{ maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" } jcenter() } + dependencies{ classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.5' classpath "com.badlogicgames.gdx:gdx-tools:1.9.9" @@ -24,7 +25,38 @@ allprojects{ appName = 'Mindustry' gdxVersion = '1.9.9' roboVMVersion = '2.3.0' - uCoreVersion = '7ffeb2a9c754f4d31ca13e02dd857876b0707dc5' + 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() + } + + getArcHash = { + //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] + }catch(e){ + e.printStackTrace() + arcHash = "-SNAPSHOT"; + } + } + return arcHash + } + + arcModule = { String name -> + if(localArc()){ + return project(":Arc:$name") + }else{ + //skip to last submodule + if(name.contains(':')) name = name.split(':').last() + return "com.github.Anuken.Arc:$name:${getArcHash()}" + } + } getVersionString = { String buildVersion = getBuildVersion() @@ -59,7 +91,6 @@ allprojects{ }catch(Exception ignored){} if(pfile.exists()){ - props.load(new FileInputStream(pfile)) String buildid = getBuildVersion() @@ -88,13 +119,14 @@ project(":desktop"){ dependencies{ compile project(":core") - compile project(":kryonet") - if(new File(projectDir.parent, '../debug').exists() && System.properties["release"] == null) compile project(":debug") + compile project(":net") + + if(debugged()) compile project(":debug") - compile "com.badlogicgames.gdx:gdx-backend-lwjgl3:$gdxVersion" compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" - compile "com.badlogicgames.gdx:gdx-controllers-lwjgl3:$gdxVersion" compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop" + + compile arcModule("backends:backend-lwjgl3") compile 'com.github.MinnDevelopment:java-discord-rpc:v2.0.0' } } @@ -103,24 +135,6 @@ project(":ios"){ apply plugin: "java" apply plugin: "robovm" - task copyGen{ - doLast{ - copy{ - from("../core/build/classes/java/main/io/anuke/mindustry/gen/"){ - include "**/*.java" - } - - into "../core/src/io/anuke/mindustry/gen" - } - } - - doFirst{ - delete{ - delete "../core/src/io/anuke/mindustry/gen/" - } - } - } - task incrementConfig{ def vfile = file('robovm.properties') @@ -138,18 +152,14 @@ project(":ios"){ props.store(vfile.newWriter(), null) } - build.dependsOn(incrementConfig) - if(file('robovm.properties').exists()){ - build.dependsOn(copyGen) - } - dependencies{ compile project(":core") - implementation project(":kryonet") + compile project(":net") + compile arcModule("backends:backend-robovm") + compile "com.mobidevelop.robovm:robovm-rt:$roboVMVersion" compile "com.mobidevelop.robovm:robovm-cocoatouch:$roboVMVersion" - compile "com.badlogicgames.gdx:gdx-backend-robovm:$gdxVersion" compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-ios" compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-ios" } @@ -162,25 +172,33 @@ project(":core"){ generateLocales() } + task cleanGen{ + doFirst{ + delete{ + delete "../core/src/io/anuke/mindustry/gen/" + } + } + } + + task copyGen{ + doLast{ + copy{ + from("../core/build/classes/java/main/io/anuke/mindustry/gen/"){ + include "**/*.java" + } + + into "../core/src/io/anuke/mindustry/gen" + } + } + } + dependencies{ - build.finalizedBy(finish) + compileJava.dependsOn(cleanGen) + compileJava.finalizedBy(copyGen) - def comp = System.properties["release"] == null || System.properties["release"] == "false" - if(!comp) println("Note: Compiling release build.") - - if(new File(projectDir.parent, '../uCore').exists() && comp){ - compile project(":uCore") - }else{ - compile "com.github.anuken:ucore:$uCoreVersion" - } - - if(new File(projectDir.parent, '../GDXGifRecorder').exists() && comp){ - compile project(":GDXGifRecorder") - } - - compile "com.badlogicgames.gdx:gdx:$gdxVersion" - compile "com.badlogicgames.gdx:gdx-controllers:$gdxVersion" - compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion" + compile arcModule("arc-core") + compile arcModule("extensions:freetype") + if(localArc() && debugged()) compile arcModule("extensions:recorder") compileOnly project(":annotations") annotationProcessor project(":annotations") @@ -190,18 +208,10 @@ project(":core"){ project(":server"){ apply plugin: "java" - configurations{ - if(findProject(":android") != null){ - compile.exclude module: android - } - } - dependencies{ - compile project(":core") - compile project(":kryonet") - compile "com.badlogicgames.gdx:gdx-backend-headless:$gdxVersion" - compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" + compile project(":net") + compile arcModule("backends:backend-headless") } } @@ -210,10 +220,10 @@ project(":tests"){ dependencies{ testImplementation project(":core") - testImplementation('org.junit.jupiter:junit-jupiter-api:5.1.0') - testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.1.0') - testImplementation "com.badlogicgames.gdx:gdx-backend-headless:$gdxVersion" - testImplementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" + testImplementation "org.junit.jupiter:junit-jupiter-params:5.3.1" + testImplementation "org.junit.jupiter:junit-jupiter-api:5.3.1" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.3.1" + compile arcModule("backends:backend-headless") } test{ @@ -238,13 +248,13 @@ project(":annotations"){ } } -project(":kryonet"){ +project(":net"){ apply plugin: "java" dependencies{ compile project(":core") compile "org.lz4:lz4-java:1.4.1" - compile 'com.github.Anuken:kryonet:53b10247b1' + compile 'com.github.Anuken:kryonet:a64d2280880e80566ca1bdaffa55de43e51cad38' compile 'com.github.Anuken:WaifUPnP:05eb46bc577fd7674596946ba288c96c0cedd893' } -} \ No newline at end of file +} diff --git a/core/assets-raw/sprites/blocks/distribution/mass-driver.png b/core/assets-raw/sprites/blocks/distribution/mass-driver-base.png similarity index 100% rename from core/assets-raw/sprites/blocks/distribution/mass-driver.png rename to core/assets-raw/sprites/blocks/distribution/mass-driver-base.png 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/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/blackrockshadow1.png b/core/assets-raw/sprites/blocks/environment/blackrockshadow1.png deleted file mode 100644 index 11730b4576..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/blackrockshadow1.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 new file mode 100644 index 0000000000..e819484335 Binary files /dev/null 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 new file mode 100644 index 0000000000..f33ee31d60 Binary files /dev/null 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 new file mode 100644 index 0000000000..36a73ab5a5 Binary files /dev/null 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/differential-generator-top.png b/core/assets-raw/sprites/blocks/environment/differential-generator-top.png new file mode 100644 index 0000000000..a540f2b93c Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/differential-generator-top.png differ diff --git a/core/assets-raw/sprites/blocks/environment/differential-generator.png b/core/assets-raw/sprites/blocks/environment/differential-generator.png new file mode 100644 index 0000000000..adf332a1e9 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/differential-generator.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/grass-cliff-edge-1.png b/core/assets-raw/sprites/blocks/environment/grass-cliff-edge-1.png deleted file mode 100644 index 38f7011a99..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/grass-cliff-edge-1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/grass-cliff-edge-2.png b/core/assets-raw/sprites/blocks/environment/grass-cliff-edge-2.png deleted file mode 100644 index 4625d77cfb..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/grass-cliff-edge-2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/grass-cliff-edge.png b/core/assets-raw/sprites/blocks/environment/grass-cliff-edge.png deleted file mode 100644 index 5d93602184..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/grass-cliff-edge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/grass-cliff-side.png b/core/assets-raw/sprites/blocks/environment/grass-cliff-side.png deleted file mode 100644 index a165417491..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/grass-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 d024726eba..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 0271e2c0c9..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 37457a6ad2..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 fdf155f66f..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/icerockshadow1.png b/core/assets-raw/sprites/blocks/environment/icerockshadow1.png deleted file mode 100644 index daa90b6e0d..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/icerockshadow1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/icerockshadow2.png b/core/assets-raw/sprites/blocks/environment/icerockshadow2.png deleted file mode 100644 index 1bbc0af176..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/icerockshadow2.png and /dev/null 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/pine.png b/core/assets-raw/sprites/blocks/environment/pine.png new file mode 100644 index 0000000000..3e6f3c7ef8 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 5af09f9483..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 1b1c8cf620..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 new file mode 100644 index 0000000000..907519e3a9 Binary files /dev/null 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 new file mode 100644 index 0000000000..e9b0151176 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/rocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/rockshadow1.png b/core/assets-raw/sprites/blocks/environment/rockshadow1.png deleted file mode 100644 index daa90b6e0d..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/rockshadow1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/rockshadow2.png b/core/assets-raw/sprites/blocks/environment/rockshadow2.png deleted file mode 100644 index 1bbc0af176..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/rockshadow2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/sand1.png b/core/assets-raw/sprites/blocks/environment/sand1.png index 6ef1e28bc0..f6259baf64 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..ce03f296ba 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..7ff6f2e9f0 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/scrap1.png b/core/assets-raw/sprites/blocks/environment/scrap1.png new file mode 100644 index 0000000000..2a72eb2a06 Binary files /dev/null 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 new file mode 100644 index 0000000000..dd2503dfce Binary files /dev/null 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 new file mode 100644 index 0000000000..39c65cc1b0 Binary files /dev/null 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 6a7bad1a80..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/shrubshadow.png b/core/assets-raw/sprites/blocks/environment/shrubshadow.png deleted file mode 100644 index 7c22d939de..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/shrubshadow.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..a32936fdb2 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..7269b8fd14 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..c2a6b18117 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/stained-stone1.png b/core/assets-raw/sprites/blocks/environment/stained-stone1.png new file mode 100644 index 0000000000..464ac94806 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-stone1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone2.png b/core/assets-raw/sprites/blocks/environment/stained-stone2.png new file mode 100644 index 0000000000..36a8896dd8 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-stone2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone3.png b/core/assets-raw/sprites/blocks/environment/stained-stone3.png new file mode 100644 index 0000000000..092ec5dac7 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/stained-stone3.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 c6a2777a84..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 1f65657224..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 b3b7d0833f..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 58c5afd372..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/block-elevation.png b/core/assets-raw/sprites/blocks/extra/block-elevation.png deleted file mode 100644 index 6f47e65204..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/block-elevation.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/block-slope.png b/core/assets-raw/sprites/blocks/extra/block-slope.png deleted file mode 100644 index c37587f765..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/block-slope.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/border.png b/core/assets-raw/sprites/blocks/extra/border.png deleted file mode 100644 index 6d848e1b72..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/border.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/cross-1.png b/core/assets-raw/sprites/blocks/extra/cross-1.png deleted file mode 100644 index 1c3aa8ae22..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/cross-1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/cross-2.png b/core/assets-raw/sprites/blocks/extra/cross-2.png deleted file mode 100644 index 3aa3ceb32b..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/cross-2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/cross-3.png b/core/assets-raw/sprites/blocks/extra/cross-3.png deleted file mode 100644 index 9aacfbb93d..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/cross-3.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/cross-4.png b/core/assets-raw/sprites/blocks/extra/cross-4.png deleted file mode 100644 index a1247aeafb..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/cross-4.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/nuclearreactor-shadow.png b/core/assets-raw/sprites/blocks/extra/nuclearreactor-shadow.png deleted file mode 100644 index 176497866c..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/nuclearreactor-shadow.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/place-arrow.png b/core/assets-raw/sprites/blocks/extra/place-arrow.png index 84f4b22895..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/ripples.png b/core/assets-raw/sprites/blocks/extra/ripples.png deleted file mode 100644 index d416708543..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/ripples.png and /dev/null 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/extra/shadow-1.png b/core/assets-raw/sprites/blocks/extra/shadow-1.png deleted file mode 100644 index edc6cdf9bb..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/shadow-2.png b/core/assets-raw/sprites/blocks/extra/shadow-2.png deleted file mode 100644 index 7b3cbfdc75..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/shadow-3.png b/core/assets-raw/sprites/blocks/extra/shadow-3.png deleted file mode 100644 index 0bc358b1db..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-3.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/shadow-4.png b/core/assets-raw/sprites/blocks/extra/shadow-4.png deleted file mode 100644 index 6bb965642b..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-4.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/shadow-5.png b/core/assets-raw/sprites/blocks/extra/shadow-5.png deleted file mode 100644 index e0020cbf44..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-5.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/shadow-6.png b/core/assets-raw/sprites/blocks/extra/shadow-6.png deleted file mode 100644 index b9c81ea3bc..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-6.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/shadow-corner.png b/core/assets-raw/sprites/blocks/extra/shadow-corner.png deleted file mode 100644 index 9f27566504..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-corner.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/shadow-round-1.png b/core/assets-raw/sprites/blocks/extra/shadow-round-1.png deleted file mode 100644 index 18db67b552..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-round-1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/shadow-round-2.png b/core/assets-raw/sprites/blocks/extra/shadow-round-2.png deleted file mode 100644 index 5a6c5c4aa3..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-round-2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/shadow-round-3.png b/core/assets-raw/sprites/blocks/extra/shadow-round-3.png deleted file mode 100644 index 2bda3d966b..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-round-3.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/shadow-round-4.png b/core/assets-raw/sprites/blocks/extra/shadow-round-4.png deleted file mode 100644 index 2d9ddf0d3d..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-round-4.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/shadow-rounded-2.png b/core/assets-raw/sprites/blocks/extra/shadow-rounded-2.png deleted file mode 100644 index 9faec224c2..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-rounded-2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/extra/shadow-shock-mine.png b/core/assets-raw/sprites/blocks/extra/shadow-shock-mine.png deleted file mode 100644 index fed06b8960..0000000000 Binary files a/core/assets-raw/sprites/blocks/extra/shadow-shock-mine.png and /dev/null 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..3e98ba5081 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/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/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/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/fusion-reactor-top.png b/core/assets-raw/sprites/blocks/power/impact-reactor-top.png similarity index 100% rename from core/assets-raw/sprites/blocks/power/fusion-reactor-top.png rename to core/assets-raw/sprites/blocks/power/impact-reactor-top.png 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 ee60b08d68..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 2191ac583c..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 new file mode 100644 index 0000000000..079397e307 Binary files /dev/null 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 new file mode 100644 index 0000000000..4506ce2f99 Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/power-void.png differ diff --git a/core/assets-raw/sprites/blocks/power/powerinfinite.png b/core/assets-raw/sprites/blocks/power/powerinfinite.png deleted file mode 100644 index 5a14712e46..0000000000 Binary files a/core/assets-raw/sprites/blocks/power/powerinfinite.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/power/powervoid.png b/core/assets-raw/sprites/blocks/power/powervoid.png deleted file mode 100644 index 5634353f59..0000000000 Binary files a/core/assets-raw/sprites/blocks/power/powervoid.png and /dev/null 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 0150f3a516..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.png b/core/assets-raw/sprites/blocks/production/biomattercompressor.png index 5af8cffe15..0ab39ff8a2 100644 Binary files a/core/assets-raw/sprites/blocks/production/biomattercompressor.png and b/core/assets-raw/sprites/blocks/production/biomattercompressor.png 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/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/itemsource.png b/core/assets-raw/sprites/blocks/production/item-source.png similarity index 100% rename from core/assets-raw/sprites/blocks/production/itemsource.png rename to core/assets-raw/sprites/blocks/production/item-source.png diff --git a/core/assets-raw/sprites/blocks/production/item-void.png b/core/assets-raw/sprites/blocks/production/item-void.png new file mode 100644 index 0000000000..ebd286c3ac Binary files /dev/null and b/core/assets-raw/sprites/blocks/production/item-void.png differ diff --git a/core/assets-raw/sprites/blocks/production/itemvoid.png b/core/assets-raw/sprites/blocks/production/itemvoid.png deleted file mode 100644 index e6f9836868..0000000000 Binary files a/core/assets-raw/sprites/blocks/production/itemvoid.png and /dev/null 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/liquidsource.png b/core/assets-raw/sprites/blocks/production/liquid-source.png similarity index 100% rename from core/assets-raw/sprites/blocks/production/liquidsource.png rename to core/assets-raw/sprites/blocks/production/liquid-source.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/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..d8afadff79 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 cb4d3c93d3..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/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 new file mode 100644 index 0000000000..cc192f5edb Binary files /dev/null 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 a1c8e9c7d1..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 ada915bfac..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 8882265fbc..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 d59ea008e6..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/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/reconstructor.png b/core/assets-raw/sprites/blocks/units/reconstructor.png deleted file mode 100644 index 144156ae68..0000000000 Binary files a/core/assets-raw/sprites/blocks/units/reconstructor.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.png b/core/assets-raw/sprites/blocks/units/repair-point.png deleted file mode 100644 index 8357f55dd6..0000000000 Binary files a/core/assets-raw/sprites/blocks/units/repair-point.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/walls/deflector-wall-large.png b/core/assets-raw/sprites/blocks/walls/deflector-wall-large.png deleted file mode 100644 index abbce58e93..0000000000 Binary files a/core/assets-raw/sprites/blocks/walls/deflector-wall-large.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/walls/deflector-wall.png b/core/assets-raw/sprites/blocks/walls/deflector-wall.png deleted file mode 100644 index 4e234bd1d0..0000000000 Binary files a/core/assets-raw/sprites/blocks/walls/deflector-wall.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/walls/dense-alloy-wall-large.png b/core/assets-raw/sprites/blocks/walls/dense-alloy-wall-large.png deleted file mode 100644 index 3db17bbac3..0000000000 Binary files a/core/assets-raw/sprites/blocks/walls/dense-alloy-wall-large.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/walls/dense-alloy-wall.png b/core/assets-raw/sprites/blocks/walls/dense-alloy-wall.png deleted file mode 100644 index a725f20c37..0000000000 Binary files a/core/assets-raw/sprites/blocks/walls/dense-alloy-wall.png and /dev/null 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 new file mode 100644 index 0000000000..d6f6fc4644 Binary files /dev/null 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 new file mode 100644 index 0000000000..effbf52069 Binary files /dev/null and b/core/assets-raw/sprites/blocks/walls/titanium-wall.png 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/clear.png b/core/assets-raw/sprites/effects/scale_marker.png similarity index 100% rename from core/assets-raw/sprites/effects/clear.png rename to core/assets-raw/sprites/effects/scale_marker.png 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-dense-alloy.png b/core/assets-raw/sprites/items/item-dense-alloy.png deleted file mode 100644 index 84831fe96c..0000000000 Binary files a/core/assets-raw/sprites/items/item-dense-alloy.png and /dev/null differ diff --git a/core/assets-raw/sprites/items/item-graphite.png b/core/assets-raw/sprites/items/item-graphite.png new file mode 100644 index 0000000000..bacdf52b8a Binary files /dev/null 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 new file mode 100644 index 0000000000..3ccccbf1ca Binary files /dev/null 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 new file mode 100644 index 0000000000..d39570505b Binary files /dev/null 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 new file mode 100644 index 0000000000..8fb5c04279 Binary files /dev/null and b/core/assets-raw/sprites/items/liquid-cryofluid.png differ diff --git a/core/assets-raw/sprites/items/liquid-icon.png b/core/assets-raw/sprites/items/liquid-icon.png deleted file mode 100644 index e4a367b63b..0000000000 Binary files a/core/assets-raw/sprites/items/liquid-icon.png and /dev/null differ diff --git a/core/assets-raw/sprites/items/liquid-oil.png b/core/assets-raw/sprites/items/liquid-oil.png new file mode 100644 index 0000000000..897050ec04 Binary files /dev/null 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 new file mode 100644 index 0000000000..e3387f557a Binary files /dev/null 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 new file mode 100644 index 0000000000..c51264d09b Binary files /dev/null and b/core/assets-raw/sprites/items/liquid-water.png differ diff --git a/core/assets-raw/sprites/mechs/mechs/chaos-array-base.png b/core/assets-raw/sprites/mechs/mechs/chaos-array-base.png new file mode 100644 index 0000000000..b1174913d6 Binary files /dev/null and b/core/assets-raw/sprites/mechs/mechs/chaos-array-base.png differ diff --git a/core/assets-raw/sprites/mechs/mechs/chaos-array-leg.png b/core/assets-raw/sprites/mechs/mechs/chaos-array-leg.png new file mode 100644 index 0000000000..7269601fcf Binary files /dev/null and b/core/assets-raw/sprites/mechs/mechs/chaos-array-leg.png differ diff --git a/core/assets-raw/sprites/mechs/mechs/chaos-array.png b/core/assets-raw/sprites/mechs/mechs/chaos-array.png new file mode 100644 index 0000000000..afd96f43dc Binary files /dev/null and b/core/assets-raw/sprites/mechs/mechs/chaos-array.png differ diff --git a/core/assets-raw/sprites/mechs/mechs/eradicator-base.png b/core/assets-raw/sprites/mechs/mechs/eradicator-base.png new file mode 100644 index 0000000000..24b5cdb446 Binary files /dev/null and b/core/assets-raw/sprites/mechs/mechs/eradicator-base.png differ diff --git a/core/assets-raw/sprites/mechs/mechs/eradicator-leg.png b/core/assets-raw/sprites/mechs/mechs/eradicator-leg.png new file mode 100644 index 0000000000..3a503a2e6a Binary files /dev/null and b/core/assets-raw/sprites/mechs/mechs/eradicator-leg.png differ diff --git a/core/assets-raw/sprites/mechs/mechs/eradicator.png b/core/assets-raw/sprites/mechs/mechs/eradicator.png new file mode 100644 index 0000000000..c620aa3d0f Binary files /dev/null and b/core/assets-raw/sprites/mechs/mechs/eradicator.png differ diff --git a/core/assets-raw/sprites/pack.json b/core/assets-raw/sprites/pack.json index abd5ae6584..91480ffa76 100644 --- a/core/assets-raw/sprites/pack.json +++ b/core/assets-raw/sprites/pack.json @@ -2,5 +2,7 @@ duplicatePadding: true, combineSubdirectories: true, flattenPaths: true, - fast: true + maxWidth: 2048, + maxHeight: 2048, + fast: true, } diff --git a/core/assets-raw/sprites/shapes/circle.png b/core/assets-raw/sprites/shapes/circle.png deleted file mode 100644 index 459e48082a..0000000000 Binary files a/core/assets-raw/sprites/shapes/circle.png and /dev/null differ diff --git a/core/assets-raw/sprites/shapes/shape-3.png b/core/assets-raw/sprites/shapes/shape-3.png deleted file mode 100644 index 358facf7db..0000000000 Binary files a/core/assets-raw/sprites/shapes/shape-3.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/bar-top.9.png b/core/assets-raw/sprites/ui/bar-top.9.png new file mode 100644 index 0000000000..e06822ecf0 Binary files /dev/null and b/core/assets-raw/sprites/ui/bar-top.9.png differ diff --git a/core/assets-raw/sprites/ui/bar.9.png b/core/assets-raw/sprites/ui/bar.9.png new file mode 100644 index 0000000000..5e9ab3f2a0 Binary files /dev/null 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 de800bf233..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 5833e18f2f..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 40ef1bad93..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 bc63ca5beb..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 0d1aac1186..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 e274175562..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..7f2a96cd21 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..732a0d4797 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..dfb9888a2d 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 8011cad610..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 f982c6939b..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 new file mode 100644 index 0000000000..60e1941d4f Binary files /dev/null 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 new file mode 100644 index 0000000000..7e1a6e6c2d Binary files /dev/null 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 new file mode 100644 index 0000000000..cdd8df0abc Binary files /dev/null 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-cancel-2.png b/core/assets-raw/sprites/ui/icons/icon-cancel-2.png new file mode 100644 index 0000000000..5b14e4c468 Binary files /dev/null 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 new file mode 100644 index 0000000000..ec0bb3cb8e Binary files /dev/null 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-info.png b/core/assets-raw/sprites/ui/icons/icon-info.png index d3af92f26d..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-nullitem.png b/core/assets-raw/sprites/ui/icons/icon-nullitem.png deleted file mode 100644 index 1897820730..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-nullitem.png and /dev/null 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-spray.png b/core/assets-raw/sprites/ui/icons/icon-spray.png new file mode 100644 index 0000000000..17198d657b Binary files /dev/null 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 new file mode 100644 index 0000000000..5c9678c8a9 Binary files /dev/null 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 new file mode 100644 index 0000000000..0731f6a7e5 Binary files /dev/null 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 new file mode 100644 index 0000000000..b0b184918c Binary files /dev/null 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 new file mode 100644 index 0000000000..2496b1bc79 Binary files /dev/null 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 bc40afe85a..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 bf9ca991b5..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 56c69a8dd8..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 efb573acb3..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 a8936dca95..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 700f69c594..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/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/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.png b/core/assets-raw/sprites_replacement/blocks/distribution/bridge-conveyor.png new file mode 100644 index 0000000000..76b29569ea Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/distribution/bridge-conveyor.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 new file mode 100644 index 0000000000..2e55ce429a Binary files /dev/null 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 new file mode 100644 index 0000000000..34a281b719 Binary files /dev/null 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 new file mode 100644 index 0000000000..0b7db4da5c Binary files /dev/null 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 new file mode 100644 index 0000000000..a85cfdad60 Binary files /dev/null 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 new file mode 100644 index 0000000000..18736adf66 Binary files /dev/null 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 new file mode 100644 index 0000000000..807b2bf17d Binary files /dev/null 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 new file mode 100644 index 0000000000..faf67a8736 Binary files /dev/null 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 new file mode 100644 index 0000000000..edbb81841f Binary files /dev/null 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 new file mode 100644 index 0000000000..ffd0e24f58 Binary files /dev/null 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 new file mode 100644 index 0000000000..f249623779 Binary files /dev/null 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 new file mode 100644 index 0000000000..3c04427e1a Binary files /dev/null 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 new file mode 100644 index 0000000000..439afb9c4b Binary files /dev/null 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 new file mode 100644 index 0000000000..2485ac23b6 Binary files /dev/null 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 new file mode 100644 index 0000000000..c7997843d0 Binary files /dev/null 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 new file mode 100644 index 0000000000..22e6868cce Binary files /dev/null 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 new file mode 100644 index 0000000000..7a94546637 Binary files /dev/null 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 new file mode 100644 index 0000000000..3563503f6f Binary files /dev/null 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 new file mode 100644 index 0000000000..83c49920b4 Binary files /dev/null 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 new file mode 100644 index 0000000000..c89f011734 Binary files /dev/null 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 new file mode 100644 index 0000000000..acfe7e8136 Binary files /dev/null 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 new file mode 100644 index 0000000000..29af97eb5c Binary files /dev/null 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 new file mode 100644 index 0000000000..ecd054afa6 Binary files /dev/null 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 new file mode 100644 index 0000000000..7dc49bd440 Binary files /dev/null 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 new file mode 100644 index 0000000000..97e31e5722 Binary files /dev/null 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 new file mode 100644 index 0000000000..7e7bb86c62 Binary files /dev/null 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 new file mode 100644 index 0000000000..ffbafc5cdf Binary files /dev/null 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 new file mode 100644 index 0000000000..f9dd561d6d Binary files /dev/null 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 new file mode 100644 index 0000000000..5377953723 Binary files /dev/null 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 new file mode 100644 index 0000000000..2f53cd53fd Binary files /dev/null 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 new file mode 100644 index 0000000000..29727566b0 Binary files /dev/null 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 new file mode 100644 index 0000000000..464a7d4cf8 Binary files /dev/null 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 new file mode 100644 index 0000000000..53c6124f64 Binary files /dev/null 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 new file mode 100644 index 0000000000..aee4b266b2 Binary files /dev/null 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 new file mode 100644 index 0000000000..a547a7790f Binary files /dev/null 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 new file mode 100644 index 0000000000..0dafebb699 Binary files /dev/null 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 new file mode 100644 index 0000000000..ae7bad0c38 Binary files /dev/null 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 new file mode 100644 index 0000000000..e001d5f945 Binary files /dev/null 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 new file mode 100644 index 0000000000..992e544fc7 Binary files /dev/null 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 new file mode 100644 index 0000000000..9c26ceef47 Binary files /dev/null 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 new file mode 100644 index 0000000000..09db7b8269 Binary files /dev/null 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/distribution/junction.png b/core/assets-raw/sprites_replacement/blocks/distribution/junction.png new file mode 100644 index 0000000000..e84244e630 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/distribution/junction.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..65a450a798 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/sand-water.png b/core/assets-raw/sprites_replacement/blocks/environment/sand-water.png new file mode 100644 index 0000000000..0144066175 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/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/liquid/conduit-top-0.png b/core/assets-raw/sprites_replacement/blocks/liquid/conduit-top-0.png new file mode 100644 index 0000000000..9dc9384971 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/liquid/conduit-top-0.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/liquid/conduit-top-1.png b/core/assets-raw/sprites_replacement/blocks/liquid/conduit-top-1.png new file mode 100644 index 0000000000..e219a5751d Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/liquid/conduit-top-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/liquid/conduit-top-5.png b/core/assets-raw/sprites_replacement/blocks/liquid/conduit-top-5.png new file mode 100644 index 0000000000..72461ba0b6 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/liquid/conduit-top-5.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/liquid/pulse-conduit-top-0.png b/core/assets-raw/sprites_replacement/blocks/liquid/pulse-conduit-top-0.png new file mode 100644 index 0000000000..c6a453fed9 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/liquid/pulse-conduit-top-0.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/liquid/pulse-conduit-top-1.png b/core/assets-raw/sprites_replacement/blocks/liquid/pulse-conduit-top-1.png new file mode 100644 index 0000000000..62f03471c4 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/liquid/pulse-conduit-top-1.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/power/power-node-large.png b/core/assets-raw/sprites_replacement/blocks/power/power-node-large.png new file mode 100644 index 0000000000..0a76d7e1a7 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/power/power-node-large.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/power/power-node.png b/core/assets-raw/sprites_replacement/blocks/power/power-node.png new file mode 100644 index 0000000000..0e7296b98f Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/power/power-node.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/power/powerinfinite.png b/core/assets-raw/sprites_replacement/blocks/power/powerinfinite.png new file mode 100644 index 0000000000..f4c6473df4 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/power/powerinfinite.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/power/powervoid.png b/core/assets-raw/sprites_replacement/blocks/power/powervoid.png new file mode 100644 index 0000000000..fee2a2b3e8 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/power/powervoid.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/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/items/item-biomatter.png b/core/assets-raw/sprites_replacement/items/item-biomatter.png new file mode 100644 index 0000000000..bb8217c746 Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/item-biomatter.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..821b27f468 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..1c78141fda 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..5d8e353603 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-surge-alloy.png b/core/assets-raw/sprites_replacement/items/item-surge-alloy.png new file mode 100644 index 0000000000..aed11704ab 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..b67f2789f8 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..e07bd283ad 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..209bb76894 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..c687ef4fbb 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..778c87479a 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..8e9df22eef Binary files /dev/null and b/core/assets-raw/sprites_replacement/items/liquid-water.png differ diff --git a/core/assets-raw/sprites/effects/blank.png b/core/assets-raw/sprites_replacement/shapes/blank.png similarity index 100% rename from core/assets-raw/sprites/effects/blank.png rename to core/assets-raw/sprites_replacement/shapes/blank.png diff --git a/core/assets-raw/sprites_replacement/shapes/circle.png b/core/assets-raw/sprites_replacement/shapes/circle.png new file mode 100644 index 0000000000..e2e6c0b2ec Binary files /dev/null and b/core/assets-raw/sprites_replacement/shapes/circle.png differ diff --git a/core/assets-raw/sprites_replacement/shapes/clear.png b/core/assets-raw/sprites_replacement/shapes/clear.png new file mode 100644 index 0000000000..dc8beb206c Binary files /dev/null and b/core/assets-raw/sprites_replacement/shapes/clear.png differ diff --git a/core/assets-raw/sprites_replacement/shapes/shape-3.png b/core/assets-raw/sprites_replacement/shapes/shape-3.png new file mode 100644 index 0000000000..5e98717513 Binary files /dev/null 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 cc0c45f925..0f353e46be 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1,356 +1,368 @@ -text.credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[] -text.credits = Credits -text.contributors = Translators and Contributors -text.discord = Join the mindustry discord! -text.link.discord.description = The official Mindustry discord chatroom -text.link.github.description = Game source code -text.link.dev-builds.description = Unstable development builds -text.link.trello.description = Official trello board for planned features -text.link.itch.io.description = itch.io page with PC downloads and web version -text.link.google-play.description = Google Play store listing -text.link.wiki.description = Official Mindustry wiki -text.linkfail = Failed to open link!\nThe URL has been copied to your clipboard. -text.screenshot = Screenshot saved to {0} -text.gameover = Game Over -text.gameover.pvp = The[accent] {0}[] team is victorious! -text.sector.gameover = This sector has been lost. Re-deploy? -text.sector.retry = Retry -text.highscore = [accent]New highscore! -text.wave.lasted = You lasted until wave [accent]{0}[]. -text.level.highscore = High Score: [accent]{0} -text.level.delete.title = Confirm Delete -text.map.delete = Are you sure you want to delete the map "[accent]{0}[]"? -text.level.select = Level Select -text.level.mode = Gamemode: -text.construction.desktop = To deselect a block or stop building, [accent]use space[]. -text.construction.title = Block Construction Guide -text.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. -text.deconstruction.title = Block Deconstruction Guide -text.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. -text.showagain = Don't show again next session -text.coreattack = < Core is under attack! > -text.unlocks = Unlocks -text.savegame = Save Game -text.loadgame = Load Game -text.joingame = Join Game -text.addplayers = Add/Remove Players -text.customgame = Custom Game -text.sectors = Sectors -text.sector = Sector: [LIGHT_GRAY]{0} -text.sector.time = Time: [LIGHT_GRAY]{0} -text.sector.deploy = Deploy -text.sector.abandon = Abandon -text.sector.abandon.confirm = Are you sure you want to abandon all progress at this sector?\nThis cannot be undone! -text.sector.resume = Resume -text.sector.locked = [scarlet][[Incomplete] -text.sector.unexplored = [accent][[Unexplored] -text.missions = Missions:[LIGHT_GRAY] {0} -text.mission = Mission:[LIGHT_GRAY] {0} -text.mission.main = Main Mission:[LIGHT_GRAY] {0} -text.mission.info = Mission Info -text.mission.complete = Mission complete! -text.mission.complete.body = Sector {0},{1} has been conquered. -text.mission.wave = Survive[accent] {0}/{1} []waves\nWave in {2} -text.mission.wave.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies -text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy -text.mission.wave.menu = Survive[accent] {0}[] waves -text.mission.battle = Destroy enemy core -text.mission.resource.menu = Obtain {0} x{1} -text.mission.resource = Obtain {0}:\n[accent]{1}/{2}[] -text.mission.block = Create {0} -text.mission.unit = Create {0} Unit -text.mission.command = Send Command {0} To Units -text.mission.linknode = Link Power Node -text.mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -text.mission.mech = Switch to mech[accent] {0}[] -text.mission.create = Create[accent] {0}[] -text.none = -text.close = Close -text.quit = Quit -text.maps = Maps -text.continue = Continue -text.nextmission = Next Mission -text.maps.none = [LIGHT_GRAY]No maps found! -text.about.button = About -text.name = Name: -text.noname = Pick a[accent] player name[] first. -text.filename = File Name: -text.unlocked = New Block Unlocked! -text.unlocked.plural = New Blocks Unlocked! -text.players = {0} players online -text.players.single = {0} player online -text.server.closing = [accent]Closing server... -text.server.kicked.kick = You have been kicked from the server! -text.server.kicked.serverClose = Server closed. -text.server.kicked.sectorComplete = Sector completed. -text.server.kicked.sectorComplete.text = Your mission is complete.\nThe server will now continue at the next sector. -text.server.kicked.clientOutdated = Outdated client! Update your game! -text.server.kicked.serverOutdated = Outdated server! Ask the host to update! -text.server.kicked.banned = You are banned on this server. -text.server.kicked.recentKick = You have been kicked recently.\nWait before connecting again. -text.server.kicked.nameInUse = There is someone with that name\nalready on this server. -text.server.kicked.nameEmpty = Your chosen name is invalid. -text.server.kicked.idInUse = You are already on this server! Connecting with two accounts is not permitted. -text.server.kicked.customClient = This server does not support custom builds. Download an official version. -text.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. -text.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. -text.hostserver = Host Game -text.hostserver.mobile = Host\nGame -text.host = Host -text.hosting = [accent]Opening server... -text.hosts.refresh = Refresh -text.hosts.discovering = Discovering LAN games -text.server.refreshing = Refreshing server -text.hosts.none = [lightgray]No local games found! -text.host.invalid = [scarlet]Can't connect to host. -text.trace = Trace Player -text.trace.playername = Player name: [accent]{0} -text.trace.ip = IP: [accent]{0} -text.trace.id = Unique ID: [accent]{0} -text.trace.android = Android Client: [accent]{0} -text.trace.modclient = Custom Client: [accent]{0} -text.trace.totalblocksbroken = Total blocks broken: [accent]{0} -text.trace.structureblocksbroken = Structure blocks broken: [accent]{0} -text.trace.lastblockbroken = Last block broken: [accent]{0} -text.trace.totalblocksplaced = Total blocks placed: [accent]{0} -text.trace.lastblockplaced = Last block placed: [accent]{0} -text.invalidid = Invalid client ID! Submit a bug report. -text.server.bans = Bans -text.server.bans.none = No banned players found! -text.server.admins = Admins -text.server.admins.none = No admins found! -text.server.add = Add Server -text.server.delete = Are you sure you want to delete this server? -text.server.hostname = Host: {0} -text.server.edit = Edit Server -text.server.outdated = [crimson]Outdated Server![] -text.server.outdated.client = [crimson]Outdated Client![] -text.server.version = [lightgray]Version: {0} {1} -text.server.custombuild = [yellow]Custom Build -text.confirmban = Are you sure you want to ban this player? -text.confirmkick = Are you sure you want to kick this player? -text.confirmunban = Are you sure you want to unban this player? -text.confirmadmin = Are you sure you want to make this player an admin? -text.confirmunadmin = Are you sure you want to remove admin status from this player? -text.joingame.title = Join Game -text.joingame.ip = Address: -text.disconnect = Disconnected. -text.disconnect.data = Failed to load world data! -text.connecting = [accent]Connecting... -text.connecting.data = [accent]Loading world data... -text.server.port = Port: -text.server.addressinuse = Address already in use! -text.server.invalidport = Invalid port number! -text.server.error = [crimson]Error hosting server: [accent]{0} -text.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. -text.save.new = New Save -text.save.overwrite = Are you sure you want to overwrite\nthis save slot? -text.overwrite = Overwrite -text.save.none = No saves found! -text.saveload = [accent]Saving... -text.savefail = Failed to save game! -text.save.delete.confirm = Are you sure you want to delete this save? -text.save.delete = Delete -text.save.export = Export Save -text.save.import.invalid = [accent]This save is invalid! -text.save.import.fail = [crimson]Failed to import save: [accent]{0} -text.save.export.fail = [crimson]Failed to export save: [accent]{0} -text.save.import = Import Save -text.save.newslot = Save name: -text.save.rename = Rename -text.save.rename.text = New name: -text.selectslot = Select a save. -text.slot = [accent]Slot {0} -text.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. -text.sector.corrupted = [accent]A save file for this sector was found, but loading failed.\nA new one has been created. -text.empty = -text.on = On -text.off = Off -text.save.autosave = Autosave: {0} -text.save.map = Map: {0} -text.save.wave = Wave {0} -text.save.difficulty = Difficulty: {0} -text.save.date = Last Saved: {0} -text.save.playtime = Playtime: {0} -text.confirm = Confirm -text.delete = Delete -text.ok = OK -text.open = Open -text.cancel = Cancel -text.openlink = Open Link -text.copylink = Copy Link -text.back = Back -text.quit.confirm = Are you sure you want to quit? -text.changelog.title = Changelog -text.changelog.loading = Getting changelog... -text.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. -text.changelog.error.ios = [accent]The changelog is currently not supported in iOS. -text.changelog.error = [scarlet]Error getting changelog!\nCheck your internet connection. -text.changelog.current = [yellow][[Current version] -text.changelog.latest = [accent][[Latest version] -text.loading = [accent]Loading... -text.saving = [accent]Saving... -text.wave = [accent]Wave {0} -text.wave.waiting = [LIGHT_GRAY]Wave in {0} -text.waiting = [LIGHT_GRAY]Waiting... -text.waiting.players = Waiting for players... -text.wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining -text.wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining -text.loadimage = Load Image -text.saveimage = Save Image -text.unknown = Unknown -text.custom = Custom -text.builtin = Built-In -text.map.delete.confirm = Are you sure you want to delete this map? This action cannot be undone! -text.map.random = [accent]Random Map -text.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. -text.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. -text.map.invalid = Error loading map: corrupted or invalid map file. -text.editor.brush = Brush -text.editor.slope = \\ -text.editor.openin = Open In Editor -text.editor.oregen = Ore Generation -text.editor.oregen.info = Ore Generation: -text.editor.mapinfo = Map Info -text.editor.author = Author: -text.editor.description = Description: -text.editor.name = Name: -text.editor.teams = Teams -text.editor.elevation = Elevation -text.editor.errorimageload = Error loading file:\n[accent]{0} -text.editor.errorimagesave = Error saving file:\n[accent]{0} -text.editor.generate = Generate -text.editor.resize = Resize -text.editor.loadmap = Load Map -text.editor.savemap = Save Map -text.editor.saved = Saved! -text.editor.save.noname = Your map does not have a name! Set one in the 'map info' menu. -text.editor.save.overwrite = Your map overwrites a built-in map! Pick a different name in the 'map info' menu. -text.editor.import.exists = [scarlet]Unable to import:[] a built-in map named '{0}' already exists! -text.editor.import = Import... -text.editor.importmap = Import Map -text.editor.importmap.description = Import an already existing map -text.editor.importfile = Import File -text.editor.importfile.description = Import an external map file -text.editor.importimage = Import Legacy Image -text.editor.importimage.description = Import an external map image file -text.editor.export = Export... -text.editor.exportfile = Export File -text.editor.exportfile.description = Export a map file -text.editor.exportimage = Export Terrain Image -text.editor.exportimage.description = Export a map image file -text.editor.loadimage = Import Terrain -text.editor.saveimage = Export Terrain -text.editor.unsaved = [scarlet]You have unsaved changes![]\nAre you sure you want to exit? -text.editor.resizemap = Resize Map -text.editor.mapname = Map Name: -text.editor.overwrite = [accent]Warning!\nThis overwrites an existing map. -text.editor.overwrite.confirm = [scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? -text.editor.selectmap = Select a map to load: -text.width = Width: -text.height = Height: -text.menu = Menu -text.play = Play -text.load = Load -text.save = Save -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Ping: {0}ms -text.language.restart = Please restart your game for the language settings to take effect. -text.settings = Settings -text.tutorial = Tutorial -text.editor = Editor -text.mapeditor = Map Editor -text.donate = Donate +credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[] +credits = Credits +contributors = Translators and Contributors +discord = Join the mindustry discord! +link.discord.description = The official Mindustry discord chatroom +link.github.description = Game source code +link.dev-builds.description = Unstable development builds +link.trello.description = Official trello board for planned features +link.itch.io.description = itch.io page with PC downloads and web version +link.google-play.description = Google Play store listing +link.wiki.description = Official Mindustry wiki +linkfail = Failed to open link!\nThe URL has been copied to your clipboard. +screenshot = Screenshot saved to {0} +gameover = Game Over +gameover.pvp = The[accent] {0}[] team is victorious! +highscore = [accent]New highscore! -text.connectfail = [crimson]Failed to connect to server:\n\n[accent]{0} -text.error.unreachable = Server unreachable.\nIs the address spelled correctly? -text.error.invalidaddress = Invalid address. -text.error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! -text.error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! -text.error.alreadyconnected = Already connected. -text.error.mapnotfound = Map file not found! -text.error.any = Unknown network error. +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: -text.settings.language = Language -text.settings.reset = Reset to Defaults -text.settings.rebind = Rebind -text.settings.controls = Controls -text.settings.game = Game -text.settings.sound = Sound -text.settings.graphics = Graphics -text.settings.cleardata = Clear Game Data... -text.settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! -text.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. -text.settings.clearsectors = Clear Sectors -text.settings.clearunlocks = Clear Unlocks -text.settings.clearall = Clear All -text.paused = [accent]< Paused > -text.yes = Yes -text.no = No -text.info.title = Info -text.error.title = [crimson]An error has occured -text.error.crashtitle = An error has occured -text.blocks.unknown=[LIGHT_GRAY]??? -text.blocks.blockinfo = Block Info -text.blocks.powercapacity = Power Capacity -text.blocks.powershot = Power/Shot -text.blocks.targetsair = Targets Air -text.blocks.itemspeed = Units Moved -text.blocks.shootrange = Range -text.blocks.size = Size -text.blocks.liquidcapacity = Liquid Capacity -text.blocks.maxitemssecond = Max Items -text.blocks.powerrange = Power Range -text.blocks.poweruse = Power Use -text.blocks.powerdamage = Power/Damage -text.blocks.inputitemcapacity = Input Item Capacity -text.blocks.outputitemcapacity = Output Item Capacity -text.blocks.itemcapacity = Item Capacity -text.blocks.basepowergeneration = Base Power Generation -text.blocks.powertransferspeed = Power Transfer -text.blocks.craftspeed = Production Speed -text.blocks.inputliquid = Input Liquid -text.blocks.inputliquidaux = Aux Liquid -text.blocks.inputitem = Input Item -text.blocks.inputitems = Input Items -text.blocks.outputitem = Output Item -text.blocks.drilltier = Drillables -text.blocks.drillspeed = Base Drill Speed -text.blocks.liquidoutput = Liquid Output -text.blocks.liquidoutputspeed = Liquid Output Speed -text.blocks.liquiduse = Liquid Use -text.blocks.coolant = Coolant -text.blocks.coolantuse = Coolant Use -text.blocks.inputliquidfuel = Fuel Liquid -text.blocks.liquidfueluse = Liquid Fuel Use -text.blocks.boostitem = Boost Item -text.blocks.boostliquid = Boost Liquid -text.blocks.health = Health -text.blocks.inaccuracy = Inaccuracy -text.blocks.shots = Shots -text.blocks.reload = Shots/Second -text.blocks.inputfuel = Fuel -text.blocks.fuelburntime = Fuel Burn Time -text.blocks.inputcapacity = Input capacity -text.blocks.outputcapacity = Output capacity -text.unit.blocks = blocks -text.unit.powersecond = power units/second -text.unit.liquidsecond = liquid units/second -text.unit.itemssecond = items/second -text.unit.pixelssecond = pixels/second -text.unit.liquidunits = liquid units -text.unit.powerunits = power units -text.unit.degrees = degrees -text.unit.seconds = seconds -text.unit.items = items -text.category.general = General -text.category.power = Power -text.category.liquids = Liquids -text.category.items = Items -text.category.crafting = Crafting -text.category.shooting = Shooting -text.category.optional = Optional Enhancements +map.delete = Are you sure you want to delete the map "[accent]{0}[]"? +level.highscore = High Score: [accent]{0} +level.select = Level Select +level.mode = Gamemode: +construction.desktop = To deselect a block or stop building, [accent]use space[]. +construction.title = Block Construction Guide +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.slope = \\ +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.[] Enemies. +launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. +uncover = Uncover +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +zone.complete = Zone conditions met. +zone.resources = Resources Detected: + +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.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Block Info +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.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.power = Power +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 @@ -377,7 +389,7 @@ setting.mutemusic.name = Mute Music setting.sfxvol.name = SFX Volume setting.mutesound.name = Mute Sound setting.crashreport.name = Send Anonymous Crash Reports -text.keybind.title = Rebind Keys +keybind.title = Rebind Keys category.general.name = General category.view.name = View category.multiplayer.name = Multiplayer @@ -392,6 +404,7 @@ 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.name = Break keybind.deselect.name = Deselect keybind.shoot.name = Shoot @@ -410,9 +423,9 @@ 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.text.help.title = Description of modes -mode.waves.name = Waves -mode.waves.description = The normal mode. Limited resources and automatic incoming waves. +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 @@ -424,18 +437,15 @@ mode.attack.descrption = 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 = Stone -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 = Coal 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 @@ -456,8 +466,12 @@ 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.lava.name = Lava +liquid.slag.name = Slag liquid.oil.name = Oil liquid.cryofluid.name = Cryofluid mech.alpha-mech.name = Alpha @@ -489,24 +503,29 @@ 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 -text.item.explosiveness = [LIGHT_GRAY]Explosiveness: {0}% -text.item.flammability = [LIGHT_GRAY]Flammability: {0}% -text.item.radioactivity = [LIGHT_GRAY]Radioactivity: {0}% -text.item.fluxiness = [LIGHT_GRAY]Flux Power: {0}% -text.unit.health = [LIGHT_GRAY]Health: {0} -text.unit.speed = [LIGHT_GRAY]Speed: {0} -text.mech.weapon = [LIGHT_GRAY]Weapon: {0} -text.mech.armor = [LIGHT_GRAY]Armor: {0} -text.mech.itemcapacity = [LIGHT_GRAY]Item Capacity: {0} -text.mech.minespeed = [LIGHT_GRAY]Mining Speed: {0} -text.mech.minepower = [LIGHT_GRAY]Mining Power: {0} -text.mech.ability = [LIGHT_GRAY]Ability: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]Heat Capacity: {0} -text.liquid.viscosity = [LIGHT_GRAY]Viscosity: {0} -text.liquid.temperature = [LIGHT_GRAY]Temperature: {0} +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.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.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = Metal Floor block.deepwater.name = deepwater block.water.name = water @@ -515,7 +534,7 @@ 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 @@ -523,10 +542,40 @@ 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 Boulde +block.metal-floor.name = Metal Floor +block.metal-floor-1.name = Metal Floor 1 +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 @@ -559,17 +608,19 @@ 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 @@ -578,11 +629,11 @@ 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.itemsource.name = Item Source -block.itemvoid.name = Item Void -block.liquidsource.name = Liquid Source -block.powervoid.name = Power Void -block.powerinfinite.name = Power Infinite +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 @@ -634,7 +685,7 @@ 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 team.blue.name = blue team.red.name = red team.orange.name = orange @@ -648,6 +699,7 @@ 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 @@ -657,7 +709,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. @@ -707,7 +763,7 @@ 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. Moved items forward and automatically deposits them into turrets or crafters. Rotatable. +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. @@ -726,7 +782,7 @@ 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.separator.description = Exposes stone to water pressure in order to obtain various minerals contained in the stone. +block.separator.description = Extracts useful minerals from slag. 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. @@ -734,7 +790,7 @@ block.battery.description = Stores power whenever there is an abundance and prov 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. @@ -780,11 +836,11 @@ block.router.description = Accepts items from one direction and outputs them to 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.itemsource.description = Infinitely outputs items. Sandbox only. -block.liquidsource.description = Infinitely outputs liquids. Sandbox only. -block.itemvoid.description = Destroys any items which go into it without using power. Sandbox only. -block.powerinfinite.description = Infinitely outputs power. Sandbox only. -block.powervoid.description = Voids all power inputted into it. Sandbox only. +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. diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties new file mode 100644 index 0000000000..c5cd86c905 --- /dev/null +++ b/core/assets/bundles/bundle_cs.properties @@ -0,0 +1,807 @@ +credits.text = Vytvořil [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[] +credits = Kredity +contributors = Překladatelé a Sponzoři +discord = Připoj se k Mindustry na Discordu! +link.discord.description = Oficiální Mindustry chatroom na Discordu! +link.github.description = Zdrojový kód hry +link.dev-builds.description = Nestabilní verze vývoje hry +link.trello.description = Oficiální Trello board pro plánované funkce +link.itch.io.description = itch.io stránka pro stažení PC nebo webové verze +link.google-play.description = Google Play store +link.wiki.description = Oficiální Mindustry wiki +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! +highscore = [accent]Nový Rekord! +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: +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[]. +construction.title = Návod ke stavbě bloků +construction = Právě jsi vybral [accent]mód stavby bloků[].\n\nK pokládání, jednoduše klikni na vhodnou lokaci poblíž tvé lodi.\nJakmile jsis vybral nějaké bloky, stiskni pole potvrzení, a tvoje loď je začne sama stavět.\n\n- [accent]Odstranění bloků[] z tvého výběru kliknutím na ně.\n- [accent]Formace výběru[] provedeš podržením a táhnutím do libovolného směru.\n- [accent]Položení bloků v řadě[] Provedeš stisknutím na prázdné pole a tažením do libovolného směru.\n- [accent]Zrušení stavby nebo výběru[] provedeš stisknutím X v levém dolním rohu. +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! > +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 +newgame = New Game +none = +close = Zavřít +quit = Ukončit +maps = Mapy +continue = Pokračovat +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! +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.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. +server.kicked.recentKick = Před nedávnem jsi byl vykopnut.\nPočkej než se znovu připojíš. +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 +hostserver.mobile = Hostovat\nHru +host = Hostitel +hosting = [accent]Otevírám server... +hosts.refresh = Obnovit +hosts.discovering = Hledám hry LAN +server.refreshing = Obnovuji servery +hosts.none = [lightgray]Žádné místní hry nebyly nalezeny! +host.invalid = [scarlet]Nejde se připojit k hostiteli. +trace = Vystopovat hráče +trace.playername = Jméno hráče: [accent]{0} +trace.ip = IP: [accent]{0} +trace.id = Unikátní ID: [accent]{0} +trace.android = Android Klient: [accent]{0} +trace.modclient = Vlastní Klient: [accent]{0} +trace.totalblocksbroken = Bloků zničeno celkem: [accent]{0} +trace.structureblocksbroken = Bloky struktůr zničeno : [accent]{0} +trace.lastblockbroken = Poslední zničený blok: [accent]{0} +trace.totalblocksplaced = Bloků položeno celkem: [accent]{0} +trace.lastblockplaced = Poslední blok položen: [accent]{0} +invalidid = Neplatná IP klienta! Poslat zprávu o chybě. +server.bans = Bany. +server.bans.none = Žádní hráči s banem nebyli nalezeni. +server.admins = Admini +server.admins.none = Žádní admini nebyli nalezeni. +server.add = Přidat server +server.delete = Jsi si jistý že chceš smazat tento server? +server.hostname = Hostitel: {0} +server.edit = Upravit server +server.outdated = [crimson]Zastaralý server![] +server.outdated.client = [crimson]Zastaralý klient![] +server.version = [lightgray]Verze: {0} {1} +server.custombuild = [yellow]Vlastní verze +confirmban = Jsi si jistý že chceš zabanovat tohoto hráče? +confirmkick = Jsi si jistý že chceš vykopnout tohoto hráče? +confirmunban = Jsi si jistý že chceš odbanovat tohoto hráče +confirmadmin = Jsi si jistý že chceš tohoto hráče pasovat na admina? +confirmunadmin = Jsi si jistý že chceš odebrat práva tomuto hráči? +joingame.title = Připojit se ke hře +joingame.ip = Adresa: +disconnect = Odpojen. +disconnect.data = Chyba načtení dat světa! +connecting = [accent]Připojuji se... +connecting.data = [accent]Načítám data světa... +server.port = Port: +server.addressinuse = Adresu již někdo používá! +server.invalidport = Neplatné číslo portu! +server.error = [crimson]Chyba při hostování serveru: [accent]{0} +save.old = Tato uložená pozice je pro starší verzi hry a již není možno jí použít.\n\n[LIGHT_GRAY]Zpětná kompatibilita bude implementována v plné verzi 4.0. +save.new = Nové uložení +save.overwrite = Jsi si jistý že chceš přepsat\ntento ukládaci slot? +overwrite = Přepsat +save.none = Žádné uložené pozice nebyly nalezeny +saveload = [accent]Ukládám... +savefail = Nepodařilo se uložit hru! +save.delete.confirm = Jsi si jistý že chceš smazat toto uložení? +save.delete = Smazat +save.export = Exportovat uložení +save.import.invalid = [accent]Toto uložení je neplatné! +save.import.fail = [crimson]Nepodařilo se importovat uložení: [accent]{0} +save.export.fail = [crimson]Nepodařilo se exportovat uložení: [accent]{0} +save.import = Importovat uložení +save.newslot = Uložit hru: +save.rename = Přejmenovat +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. +empty = +on = On +off = Off +save.autosave = Automatické uložení: {0} +save.map = Mapa: {0} +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 +open = Otevřít +cancel = Zrušit +openlink = Otevřít Odkaz +copylink = Zkopírovat Odkaz +back = Zpět +quit.confirm = Jsi si jistý že chceš ukončit ? +changelog.title = Záznam změn +changelog.loading = Načítání záznamu změn... +changelog.error.android = [accent]Berte v potaz že záznam změn někdy nefunguje na Android 4.4 a níž!\nJe to kvůli interní chybě v systému Android. +changelog.error.ios = [accent]Záznam změn nění aktuálně podporován v systému IOS. +changelog.error = [scarlet]Chyba v načítání záznamu změn!\nZkontrolujte své připojení k internetu. +changelog.current = [yellow][[Aktuální verze] +changelog.latest = [accent][[nejnovější verze] +loading = [accent]Načítám... +saving = [accent]Ukládám... +wave = [accent]Vlna {0} +wave.waiting = [LIGHT_GRAY]Vlna za {0} +waiting = [LIGHT_GRAY]Čekám... +waiting.players = Čekání na hráče... +wave.enemies = [LIGHT_GRAY]{0} Nepřátel zbývá +wave.enemy = [LIGHT_GRAY]{0} Nepřítel zbývá +loadimage = Nahrát obrázek +saveimage = Uložit obrázek +unknown = Neznámý +custom = Vlastní +builtin = Zabudovaný +map.delete.confirm = Jsi si jistý žechceš tuto mapu smazat? tato akce je nevratná! +map.random = [accent]Náhodná mapa +map.nospawn = Tato mapa nemá žádná jádra pro hráče ke spawnutí! přidej[ROYAL] blue[] jádro na tuto mapu v editoru. +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ů: +editor.mapinfo = Informace o mapě +editor.author = Autor: +editor.description = Popis: +editor.name = Jméno: +editor.teams = Týmy +editor.elevation = Výška +editor.errorimageload = Chyba při načítání souboru:\n[accent]{0} +editor.errorimagesave = Chyba při ukládání souboru:\n[accent]{0} +editor.generate = Generovat +editor.resize = Změnit velikost +editor.loadmap = Načíst mapu +editor.savemap = Uložit mapu +editor.saved = Uloženo! +editor.save.noname = Tvoje mapa nemá jméno! Jméno nastavíš v Informacích o mapě. +editor.save.overwrite = Tvoje mapa přepisuje vestavěnou mapu! Vyber odlišné jméno v Informacích o mapě. +editor.import.exists = [scarlet]Není možno importovat:[] vestavěná mapa jménem '{0}' již existuje! +editor.import = Import +editor.importmap = Importovat mapu +editor.importmap.description = Importovat již existující mapu +editor.importfile = Importovat soubor +editor.importfile.description = Importovat externí soubor mapy +editor.importimage = Importovat Legacy Obrázek +editor.importimage.description = Importovat exrerní obrázek mapy +editor.export = Export +editor.exportfile = Exportovat soubor +editor.exportfile.description = Exportovat soubor mapy +editor.exportimage = Exportovat obrázek terénu +editor.exportimage.description = Exportovat obrázek souboru mapy +editor.loadimage = Importovat terén +editor.saveimage = Exportovat terén +editor.unsaved = [scarlet]Máš neuložené změny![]\nPřesto chceš ukončit? +editor.resizemap = Změnit velikost mapy +editor.mapname = Jméno mapy: +editor.overwrite = [accent]Varování!\nToto přepíše již existující mapu. +editor.overwrite.confirm = [scarlet]Varování![] Mapa s tímto jménem již existuje. Jsi si jistý že ji chceš přepsat? +editor.selectmap = Vyber mapu k načtení: +width = Šířka: +height = Výška: +menu = Hlavní menu +play = Hrát +load = Načíst +save = Uložit +fps = FPS: {0} +tps = TPS: {0} +ping = Odezva: {0}ms +language.restart = Prosím restartuj hru aby se provedla změna jazyka! +settings = Nastavení +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +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. +error.timedout = Čas vypršel!\nUjisti se že hostitel má nastavené přesměrování portů a adresa je napsaná správně! +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 +settings.controls = Ovládání +settings.game = Hra +settings.sound = zvuky +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.clearunlocks = Vymazání odemykatelných +settings.clearall = Vymazat všechno +paused = [accent]< Pauza > +yes = Ano +no = Ne +info.title = Informace +error.title = [crimson]Objevila se chyba +error.crashtitle = Objevila se chyba +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Informace o bloku +blocks.powercapacity = Kapacita energie +blocks.powershot = Energie na výstřel +blocks.targetsair = Zaměřuje vzdušné jednotky +blocks.itemspeed = Zpracování +blocks.shootrange = Dostřel +blocks.size = velikost +blocks.liquidcapacity = Kapacita tekutin +blocks.maxitemssecond = Max předmětů +blocks.powerrange = Rozsah energie +blocks.poweruse = Spotřebuje energie +blocks.powerdamage = Energie na poškození +blocks.inputitemcapacity = Kapacita vstupních předmětů +blocks.outputitemcapacity = Kapacita výstupních předmětů +blocks.itemcapacity = kapacita předmětů +blocks.basepowergeneration = Základní generování energie +blocks.powertransferspeed = Přenos energie +blocks.craftspeed = Rychlost produkce +blocks.inputliquid = Vstupní tekutiny +blocks.inputliquidaux = Aux tekutina +blocks.inputitem = Vstupní předmět +blocks.inputitems = Vstupní předměty +blocks.outputitem = Výstupní předmět +blocks.drilltier = Vrtatelné +blocks.drillspeed = Základní rychlost vrtu +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.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = Nepřesnost/výchylka +blocks.shots = Střely +blocks.reload = Střely za sekundu +blocks.inputfuel = Palivo +blocks.fuelburntime = Čas spalování paliva +blocks.inputcapacity = Vstupní kapacita +blocks.outputcapacity = Výstupní kapacita +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 +unit.seconds = sekundy +unit.items = předměty +category.general = Všeobecné +category.power = Energie +category.liquids = Tekutiny +category.items = Předměty +category.crafting = Vyžaduje +category.shooting = Střílí +category.optional = Volitelné vylepšení +setting.indicators.name = Indikátor pro spojence +setting.autotarget.name = Automaticky zaměřuje +setting.fpscap.name = Max FPS +setting.fpscap.none = žádný +setting.fpscap.text = {0} FPS +setting.difficulty.training = Trénink +setting.difficulty.easy = lehká +setting.difficulty.normal = normální +setting.difficulty.hard = težká +setting.difficulty.insane = šílená +setting.difficulty.name = Obtížnost: +setting.screenshake.name = Třes obrazu +setting.effects.name = Zobrazit efekty +setting.sensitivity.name = Citlivost ovladače +setting.saveinterval.name = Interval automatického ukládání +setting.seconds = {0} Sekund +setting.fullscreen.name = Celá obrazovka +setting.fps.name = Ukázat snímky/sekundu +setting.vsync.name = Vertikální synchronizace +setting.lasers.name = Ukázat laser energie +setting.minimap.name = Ukázat minimapu +setting.musicvol.name = Hlasitost hudby +setting.mutemusic.name = Ztišit hudbu +setting.sfxvol.name = SFX hlasitost +setting.mutesound.name = Ztišit zvuky +setting.crashreport.name = Poslat anonymní spis o zhroucení hry +keybind.title = Přenastavit klávesy +category.general.name = Všeobecné +category.view.name = Pohled +category.multiplayer.name = Multiplayer +command.attack = Útok +command.retreat = Ústup +command.patrol = Hlídkovat +keybind.gridMode.name = Výběr bloků +keybind.gridModeShift.name = Výběr kategorie +keybind.press = Stiskni klívesu... +keybind.press.axis = Stiskni osu nebo klávesu... +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.pick.name = Pick Block +keybind.break.name = Ničit +keybind.deselect.name = Odznačit +keybind.shoot.name = Střílet +keybind.zoom_hold.name = Přiblížení-podržení +keybind.zoom.name = přiblížení +keybind.menu.name = Hlavní nabídka +keybind.pause.name = pauza +keybind.dash.name = Sprint +keybind.chat.name = Chat +keybind.player_list.name = Seznam hráčů +keybind.console.name = Konzole +keybind.rotate.name = Otočit +keybind.toggle_menus.name = Přepínání nabídek +keybind.chat_history_prev.name = Předchozí historie chatu +keybind.chat_history_next.name = Další historie chatu +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.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 +mode.freebuild.description = Limitované zdroje a žádný čas pro vlny nepřátel. +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. +content.item.name = Předměty +content.liquid.name = Tekutiny +content.unit.name = jednotky +content.block.name = Blocks +content.mech.name = Mechy +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.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 +item.thorium.description = Hustý, radioaktivní materiál, používá se jako strukturální podpora a jako nuklearní palivo. +item.silicon.name = Křemík +item.silicon.description = Extrémně užitečný polovodič, aplikuje se v solárních panelech a v komplexní elektronice. +item.plastanium.name = Plastanium +item.plastanium.description = Lehký, kujný materiál, používá se v pokročilém letectví a jako fragmentační střelivo. +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.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.oil.name = Ropa +liquid.cryofluid.name = Cryofluid +mech.alpha-mech.name = Alfa +mech.alpha-mech.weapon = Těžký Opakovač +mech.alpha-mech.ability = Roj dronů +mech.alpha-mech.description = Standartní mech. Má slušnou rychlost a poškození; Může vytvořit až 3 drony Pro zvýšenou ofenzivní způsobilost. +mech.delta-mech.name = Delta +mech.delta-mech.weapon = Obloukový generátor +mech.delta-mech.ability = Průtok +mech.delta-mech.description = Rychlý, Lehce obrněný mech vytvořený pro udeř a uteč akce. Působí malé poškození vůči struktůrám, ale může zneškodnit velkou skupinu nepřátelských jednotek velmi rychle svýmy elektro-obloukovými zbraněmi +mech.tau-mech.name = Tau +mech.tau-mech.weapon = Restruktní Laser +mech.tau-mech.ability = Opravná dávka +mech.tau-mech.description = Podpůrný mech. Léčí spojenecké stavby a jednotky střelbou do nich. Může léčit i spojence ve svém poli působení. +mech.omega-mech.name = Omega +mech.omega-mech.weapon = Rojové střely +mech.omega-mech.ability = Obrněná Konfigurace +mech.omega-mech.description = Objemný a velice dovře obrněný mech, určen pro útok v přední linii. Jeho schopnost obrnění blokuje až 90% příchozího poškození. +mech.dart-ship.name = Šipka +mech.dart-ship.weapon = Opakovač +mech.dart-ship.description = Standartní loď. Poměrně rychlý a lehký, má malou ofenzívu a pomalou rychlost těžení. +mech.javelin-ship.name = Oštěp +mech.javelin-ship.description = Loď stylu udeř a uteč. Zpočátku pomalý ale umí akcelerovat do obrovské rychlosti a létat u nepřátelských základen a působit značné škody svými elektrickými zbraněmi a raketami. +mech.javelin-ship.weapon = Dávka Raket +mech.javelin-ship.ability = Výbojový Posilovač +mech.trident-ship.name = Trojzubec +mech.trident-ship.description = Těžký bombardér. Docela dobře obrněný. +mech.trident-ship.weapon = Bombová zátoka +mech.glaive-ship.name = Glaiva +mech.glaive-ship.description = Obrovská, Dobře obrněná střelecká loď. Vybavena zápalným opakovačem. Dobrá akcelerace a maximální rychlost. +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}% +unit.health = [LIGHT_GRAY]Životy: {0} +unit.speed = [LIGHT_GRAY]Rychlost: {0} +mech.weapon = [LIGHT_GRAY]Zbraň: {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} +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.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-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus +block.metalfloor.name = Kovová podlaha +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.copper-wall.name = Měděná zeď +block.copper-wall-large.name = Velká měděná zeď +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 +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 +block.titanium-conveyor.name = Titániový dopravník +block.junction.name = Křižovatka +block.router.name = Směrovač +block.distributor.name = Distributor +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.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-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 +block.glaive-ship-pad.name = Plošina pro loď Glaiva +block.omega-mech-pad.name = Plošina pro Omega Mech +block.tau-mech-pad.name = Plošina pro Tau Mech +block.conduit.name = Potrubí +block.mechanical-pump.name = Mechanická pumpa +block.item-source.name = Zdroj předmětů +block.item-void.name = Prázdnota pro předměty +block.liquid-source.name = Zdroj tekutin +block.power-void.name = Prázdnota pro energii +block.power-source.name = Nekonečný zdroj energie +block.unloader.name = Odbavovač +block.vault.name = Trezor +block.wave.name = Vlna +block.swarmer.name = Rojiště +block.salvo.name = Salva +block.ripple.name = Vlnění +block.phase-conveyor.name = Fázový přepravník +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 +block.spirit-factory.name = Továrna na Spirit Drony +block.phantom-factory.name = Továrna na Fantom Drony +block.wraith-factory.name = Továrna na Wraithy +block.ghoul-factory.name = Továrna na Ghůl Bombardéry +block.dagger-factory.name = Továrna na Dagger Mechy +block.titan-factory.name = Továrna na Titán Mechy +block.fortress-factory.name = Továrna na Fortress Mechy +block.revenant-factory.name = Továrna na Revenanty +block.repair-point.name = Opravný Bod +block.pulse-conduit.name = Pulzní potrubí +block.phase-conduit.name = Fázové potrubí +block.liquid-router.name = Směrovač tekutin +block.liquid-tank.name = Nádrž na tekutiny +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 +block.thermal-generator.name = Termální Generátor +block.alloy-smelter.name = Slitinová pec +block.mend-projector.name = Opravný projektor +block.surge-wall.name = Impulzní stěna +block.surge-wall-large.name = Velká Impulzní stěna +block.cyclone.name = Cyklón +block.fuse.name = Fůze +block.shock-mine.name = Šoková mina +block.overdrive-projector.name = Vysokorychlostní projektor +block.force-projector.name = Silový projektor +block.arc.name = Oblouk +block.rtg-generator.name = RTG Generátor +block.spectre.name = Spektr +block.meltdown.name = Meltdown +block.container.name = Kontejnér +block.launch-pad.name = Launch Pad +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 +unit.ghoul.description = Těžký, kobercový bombardér. +unit.wraith.name = Bojovník Wraith +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.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. +tutorial.morecopper = Je za potřebí více mědi.\n\nBuď ho můžeš natěžit manuáně nebo polož více vrtů. +tutorial.turret = Defenzivní stavby musí být postaveny za účelem obrany vůči[LIGHT_GRAY] nepříteli[].\nPostav střílnu Duo blízko svého jádra. +tutorial.drillturret = Duo střílny požadují[accent] měd jako střelivo []ke střelbě.\nPolož vrt blízko střílny pro zásobování mědí. +tutorial.waves = [LIGHT_GRAY] nepřítel[] je přibližuje.\n\nBraň své jádro po dobu dvou vln, postav více střílen. +tutorial.lead = Více rud je zde dostupných. Najdi a těž[accent] Olovo[].\n\nPřetáhni od tvojí jednotky k jádru pro přesun materiálu. +tutorial.smelter = Měd a olovo jsou slabé materiály.\nLepší[accent] hustá slitina[] může být vytvořena v peci.\n\npostav si jednu pec. +tutorial.densealloy = Pec teď bude produkovat slitinu.\nVyráběj si ji.\nZvyš počet produkce pokud je nutno. +tutorial.siliconsmelter = Jádro teď vytvoří[accent] spirit drona[] pro těžení a opravu bloků.\n\nTovárny pro ostatní jednotky mohou být vytvořeny za pomocí [accent] Křemíku.\nPostav Křemíkovou pec. +tutorial.silicondrill = Křemík vyžaduje[accent] uhlí[] a[accent] písek[].\nZačni tím že položíš pár vrtů. +tutorial.generator = Tato technologie vyžaduje energii k provozu.\nVytvoř[accent] spalovací generátor[]k produkci energie. +tutorial.generatordrill = Spalovací generátory vyžadujou palivo.\nZásobuj ho uhlím z vrtu. +tutorial.node = Energie vyžaduje přenos.\nVytvoř[accent] energetický uzel[] vedle svého generátoru pro přenos energie. +tutorial.nodelink = Energie může být přenášena zkrz kontakt s energetickými bloky a generátory, nebo propojením zkrze energetické uzly.\n\nPropoj energii kliknutím na uzel a následným výběrem generátoru a křemíkovou pecí. +tutorial.silicon = Křemík se teď produkuje. Vyráběj si.\n\nJe doporučeno zvýšit produkci. +tutorial.daggerfactory = Postav[accent] Továrnu na Dagger mechy.[]\n\nToto bude využito pro konstrukci útočné síly. +tutorial.router = Továrny potřebujou k provozu materiál.\nPolož na dopravník směrovač pro oddělení části nákladu k továrně. +tutorial.dagger = Propoj energetické uzly s továrnou.\nJakmile jsou požadavky splněny, Mechy se začnou stavět.\n\nPokládej vrty, generátory a dopravníky dle libosti. +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é. +block.phase-wall-large.description = Né tak silná jako zeď Thoria ale odráží nepřátelské projektily dokud nejsou moc silné.\nZabírá více polí. +block.surge-wall.description = Nejsilnější defenzivní blok.\nMá malou šanci vystřelit elektrický paprsek vůči útočníkovi. +block.surge-wall-large.description = Nejsilnější defenzivní blok.\nMá malou šanci vystřelit elektrický paprsek vůči útočníkovi.\nZabírá více polí. +block.door.description = Malé dveře, které se dají otevřít nebo zavřít kliknutím na ně.\nKdyž otevřené nepřátelé mohou střílet a dostat se skrz. +block.door-large.description = Velké dveře, které se dají otevřít nebo zavřít kliknutím na ně.\nKdyž otevřené nepřátelé mohou střílet a dostat se skrz.\nZabírá více polí. +block.mend-projector.description = Kontinuálně léčí bloky ve poli svého působení. +block.overdrive-projector.description = Zrychluje funkce blízkých struktůr jako jsou vrty a dopravníky. +block.force-projector.description = Vytvoří okolo sebe šestihrané silové pole, chrání jednotky a budovy uvnitř sebe vůči střelám. +block.shock-mine.description = Působí poškození nepřátelským jednotkám při sešlápnutí. Skoro neviditelné nepřáteli. +block.duo.description = Malá, levná střílna. +block.arc.description = Malá střílna, která střílí elektřinu v náhodném oblouku po nepřátelských jednotkách. +block.hail.description = Malá artilérní střílna. +block.lancer.description = Středně velká střílna, která střílí nabité elektrické paprsky. +block.wave.description = Středně vělká, rychle pálící střílna, která střílí krystalizované bubliny. +block.salvo.description = Středně velká střílna, která střílí v salvách. +block.swarmer.description = Středně velká střílna, která střílí rakety v dávkách. +block.ripple.description = Velká artilérní střílna, která vystřelí několik projektilů najednou. +block.cyclone.description = Velká rychle pálící střílna. +block.fuse.description = Velká střílna, která střílí paprsky krátkého dosahu. +block.spectre.description = Velká střílna, která vystřelí dva mocné projektily naráz. +block.meltdown.description = Velká střílna, která vystřelí mocný paprsek dalekého dosahu. +block.conveyor.description = Základní blok přepravy předmětů. Nese předměty kupředu a automaticky plní střílny nebo bloky výroby do kterých směřují. dá se otáčet do různých směrů. +block.titanium-conveyor.description = Pokročilý blok přepravy předmětů. Nese předměty rychleji jak standartní dopravníky. +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. +block.alloy-smelter.description = Produkuje impulzní slitinu z titánia, olova, křemíku a mědi. +block.pulverizer.description = Drtí kámen na písek. Užitečné když se v oblasti nenalézá písek. +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.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. +block.battery-large.description = Uloží více energie než standartní baterie. +block.combustion-generator.description = Generuje energii spalováním ropy nebo jinných hořlavých materiálů. +block.turbine-generator.description = Více efektivní než spalovací generátor, ale vyžaduje dodatečný přísun vody. +block.thermal-generator.description = Generuje obrovské množství energie z lávy. +block.solar-panel.description = Poskytuje malé množství energie ze slunce. +block.solar-panel-large.description = Poskytuje mnohem lepší zdroj energie než standartní solární panel, za to je mnohem nákladnější na stavbu. +block.thorium-reactor.description = Generuje obrovské množství energie z radioaktivního thoria. Vyžaduje konstantní chlazení. Způsobí velikou explozi je-li zásobován nedostatečným množstvím chlazení. Výstup energie závisí na plnosti obsahu generátoru, základní generování energie se aktivuje při poloviční kapacitě. +block.rtg-generator.description = Rádioizotopní Termoelektrický Generátor nevyžaduje chlazení, za to generuje méně energie než Thoriový generátor. +block.unloader.description = Vykládá předměty z kontejnéru, trezoru nebo jádra na dopravník nebo přímo do produktivních bloků. Druh předmětu pro vykládání lze měti kliknutím na odbavovač. +block.container.description = Ukládá malé množství předmětů každého typu. Připojené kontejnéry, trezory nebo jádra se budou chovat jako samostatné skladovací jednotky. [LIGHT_GRAY] Odbavovač[] lze použít pro odbavení předmětů z kontejnéru. +block.vault.description = Ukládá velké množství předmětů každého typu. Připojené kontejnéry, trezory nebo jádra se budou chovat jako samostatné skladovací jednotky. [LIGHT_GRAY] Odbavovač[] lže použít pro odbavení předmětů z trezoru. +block.mechanical-drill.description = Levný vrt. Při položení na vhodné pole, natrvalo a pomalu produkuje materiál na který byl položen. +block.pneumatic-drill.description = Vylepšený vrt, který je rychlejší a je schopen zpracovat trdší materiály za pomocí tlaku. +block.laser-drill.description = Dovoluje vrtat ještě rychleji díky laserové technologii, požaduje energii k provozu. Dodatečně, dokáže vrtat žíly radioaktivního thoria. +block.blast-drill.description = Ultimátní vrt, vyžaduje velké množství energie k provozu. +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. +block.tau-mech-pad.description = Zanech zde své aktuální plavidlo a změn ho na na podpůrného mecha, který léčí spojenecké budovy a jednotky.\nPoužíj ho poklikáním když se nacházíš nad ním. +block.delta-mech-pad.description = Zanech zde své aktuální plavidlo a změn ho na rychlého, lehce obrněného mecha určeného pro udeř a uteč operace.\nPoužíj ho poklikáním když se nacházíš nad ním. +block.omega-mech-pad.description = Zanech zde své aktuální plavidlo a změn ho na objemného dobře obrněného mecha, určeného pro útok v přední linii.\nPoužíj ho poklikáním když se nacházíš nad ním. +block.spirit-factory.description = Produkuje lehké drony, kteří teží minerály a opravují budovy +block.phantom-factory.description = Produkuje pokročilé drony kteří jsou podstatně efektivnější jak spirit droni. +block.wraith-factory.description = Produkuje rychlé, udeř a uteč stíhače. +block.ghoul-factory.description = Produkuje těžké kobercové bombardéry. +block.dagger-factory.description = Produkuje standartní pozemní jednotky. +block.titan-factory.description = Produkuje pokročilé, orněné pozemní jednotky. +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í. +block.liquid-router.description = Příjmá tekutiny z jednoho směru a vypouští je rovnoměrně do zbylých tří směrů. Dokáže uložit na krátkou dobu nějaký obsah tekutin. Užitečný při rozdělení jednoho zdroje směřující do různých cílů. +block.liquid-tank.description = Uloží velké množství tekutin. Použíj ho pro vyrovnávací zásoby vody když je příděl nestabilní nebo jako záložní chlazení pro generátory. +block.liquid-junction.description = Chová se jako most pro dvě křížící se potrubí. Užitečný v situacích když dvě rozdílné potrubí nesou rozdílný obsah na rozdílná místa. +block.bridge-conduit.description = Pokročilý blok přepravy tekutin. Dovoluje transportovat tekutiny až přez tři pole jakéhokoliv terénu nebo budovy. +block.mechanical-pump.description = Levná pumpa s pomalým tokem, ale nevyžaduje nergii k provozu. +block.rotary-pump.description = Pokročilá pumpa která, zdvojnásobuje přísun tekutin za použití energie. +block.thermal-pump.description = Ultimátní pumpa. Trojnásobně rychlejší než mechanická pumpa a jediná pumpa která dokáže pracovat s lávou. +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 d7840e685c..098e4ebdc1 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -1,351 +1,359 @@ -text.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!) -text.credits = Danksagungen -text.discord = Trete dem Mindustry Discord bei! -text.link.discord.description = Der offizielle Mindustry Discord Chatroom -text.link.github.description = Quellcode des Spiels -text.link.dev-builds.description = Entwicklungs-Builds (instabil) -text.link.trello.description = Offizielles Trello Board für geplante Features -text.link.itch.io.description = itch.io Seite mit Downloads und der Web-Version des Spiels -text.link.google-play.description = Google Play Store Seite -text.link.wiki.description = Offizelles Mindustry Wiki -text.linkfail = Fehler beim Öffnen des Links!\nDie URL wurde in die Zwischenablage kopiert. -text.gameover = Der Kern wurde zerstört. -text.gameover.pvp = Das[accent] {0}[] Team ist siegreich! -text.sector.gameover = Du hast diesen Sektor verloren. Erneuter Einsatz? -text.sector.retry = Erneut versuchen -text.highscore = [YELLOW] Neuer Highscore! -text.wave.lasted = Du hast es bis Welle [accent]{0}[] ausgehalten. -text.level.highscore = High Score: [accent]{0} -text.level.delete.title = Löschen bestätigen -text.map.delete = Bist du sicher, dass du die Karte "[accent]{0}[]" löschen möchtest? -text.level.select = Level Auswahl -text.level.mode = Spielmodus: -text.construction.desktop = Um einen Block zu deselektieren oder den Bau abzubrechen, [accent]verwende die Leertaste[]. -text.construction.title = Bauanleitung für Blöcke. -text.construction = Du hast soeben den [accent]Block-Baumodus[] ausgewählt.\n\nTippe einfach auf einen gültigen Platz in der Nähe deines Schiffs, um den Bau zu planen.\nSobald du einige Blöcke platziert hast, drücke zum Bestätigen auf den Haken, und dein Schiff wird mit dem Bau beginnen.\n\n- [accent]Entferne Blöcke[] von deiner Auswahl, indem du darauf tippst.\n- [accent]Verschiebe die Selektion[], indem du einen beliebigen Block in der Auswahl gedrückt hältst und verschiebst.\n- [accent]Platziere Blöcke in einer Linie[], indem du einen leeren Platz gedrückt hältst, und in eine Richtung ziehst.\n- [accent]Breche den Bau oder die Auswahl ab[], indem du das X links unten drückst. -text.deconstruction.title = Abbruchanleitung für Blöcke -text.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. -text.showagain = Nächstes mal nicht mehr anzeigen -text.coreattack = < Die Basis wird angegriffen! > -text.unlocks = Freigeschaltet -text.savegame = Spiel speichern -text.loadgame = Spiel laden -text.joingame = Spiel beitreten -text.addplayers = Hinzufügen/Entfernen von Spielern -text.customgame = Benutzerdefiniertes Spiel -text.sectors = Sektoren -text.sector = Sektor: [LIGHT_GRAY]{0} -text.sector.time = Zeit: [LIGHT_GRAY]{0} -text.sector.deploy = Einsatz -text.sector.abandon = Aufgeben -text.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! -text.sector.resume = Fortsetzen -text.sector.locked = [scarlet][[Unvollständig] -text.sector.unexplored = [accent][[Unerforscht] -text.missions = Missionen:[LIGHT_GRAY] {0} -text.mission = Mission:[LIGHT_GRAY] {0} -text.mission.main = Hauptmission:[LIGHT_GRAY] {0} -text.mission.info = Missionsbeschreibung -text.mission.complete = Mission erfolgreich! -text.mission.complete.body = Sektor {0},{1} wurde erobert. -text.mission.wave = Überlebe [accent]{0}/{1}[] Wellen\nWelle in {2} -text.mission.wave.enemies = Überlebe[accent] {0}/{1} []Wellen\n{2} Gegner -text.mission.wave.enemy = Überlebe[accent] {0}/{1} []Wellen\n{2} Gegner -text.mission.wave.menu = Überlebe[accent] {0} []Wellen -text.mission.battle = Zerstöre die gegnerische Basis. -text.mission.resource.menu = Erlange {0} x{1} -text.mission.resource = Sammele {0}:\n[accent]{1}/{2}[] -text.mission.block = Erstelle {0} -text.mission.unit = Erstelle {0} Einheiten -text.mission.command = Sende {0}-Kommando an Einheiten -text.mission.linknode = Verbinde Stromknoten -text.mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -text.mission.mech = Wechsle zum [accent] {0}[]-Mech -text.mission.create = Platziere[accent] {0}[] -text.none = -text.close = Schließen -text.quit = Verlassen -text.maps = Karten -text.continue = Weiter -text.nextmission = Nächste Mission -text.maps.none = [LIGHT_GRAY]Keine Karten gefunden! -text.about.button = Info -text.name = Name: -text.filename = File Name: -text.unlocked = Neuen Block freigeschaltet! -text.unlocked.plural = Neue Blöcke freigeschaltet! -text.players = {0} Spieler online -text.players.single = {0} Spieler online -text.server.closing = [accent]Schließe den Server... -text.server.kicked.kick = Du wurdest vom Server gekickt! -text.server.kicked.serverClose = Server geschlossen. -text.server.kicked.sectorComplete = Sektor abgeschlossen. -text.server.kicked.sectorComplete.text = Deine Mission ist abgeschlossen.\nDer Server wird nun in einen neuen Sektor wechseln. -text.server.kicked.clientOutdated = Veralteter Client! Aktualisiere dein Spiel! -text.server.kicked.serverOutdated = Veralteter Server! Bitte den Host um ein Update! -text.server.kicked.banned = Du wurdest vom Server verbannt. -text.server.kicked.recentKick = Du wurdest gerade gekickt.\nWarte bevor du dich wieder verbindest. -text.server.kicked.nameInUse = Es ist bereits ein Spieler \nmit diesem Namen auf dem Server. -text.server.kicked.nameEmpty = Dein Name muss zumindest einen Buchstaben oder eine Zahl enthalten. -text.server.kicked.idInUse = Du bist bereits auf dem Server! Anmeldungen mit zwei Accounts sind nicht gestattet. -text.server.kicked.customClient = Der Server akzeptiert keine Custom Builds von Mindustry. Lade dir die offizielle Version herunter. -text.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. -text.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. -text.hostserver = Server hosten -text.hostserver.mobile = Host\nGame -text.host = Host -text.hosting = [accent] Server wird geöffnet... -text.hosts.refresh = Aktualisieren -text.hosts.discovering = Suche nach LAN-Spielen -text.server.refreshing = Server wird aktualisiert -text.hosts.none = [lightgray] Keine LAN Spiele gefunden! -text.host.invalid = [scarlet] Kann keine Verbindung zum Host herstellen. -text.trace = Spieler verfolgen -text.trace.playername = Spielername: [accent]{0} -text.trace.ip = IP: [accent]{0} -text.trace.id = Eindeutige ID: [accent]{0} -text.trace.android = Android Client: [accent]{0} -text.trace.modclient = Custom Client: [accent]{0} -text.trace.totalblocksbroken = Anzahl zerstörter Blöcke: [accent]{0} -text.trace.structureblocksbroken = Anzahl zerstörter Gebäude-Blöcke: [accent]{0} -text.trace.lastblockbroken = Letzter zerstörter Block: [accent]{0} -text.trace.totalblocksplaced = Anzahl platzierter Blöcke: [accent]{0} -text.trace.lastblockplaced = Letzter platzierter Block: [accent]{0} -text.invalidid = Ungültige Client ID! Berichte den Bug. -text.server.bans = Bans -text.server.bans.none = Keine gebannten Spieler gefunden! -text.server.admins = Admins -text.server.admins.none = Keine Admins gefunden! -text.server.add = Server hinzufügen -text.server.delete = Bist du dir sicher, dass du diesen Server löschen möchtest? -text.server.hostname = Host: {0} -text.server.edit = Server bearbeiten -text.server.outdated = [crimson]Veralteter Server![] -text.server.outdated.client = [crimson]Veralteter Client![] -text.server.version = [lightgray]Version: {0} -text.server.custombuild = [yellow]Custom Build -text.confirmban = Bist du sicher, dass du diesen Spieler verbannen möchtest? -text.confirmkick = Bist du sicher, dass du diesen Spieler kicken willst? -text.confirmunban = Bist du sicher, dass du die Verbannung des Spielers rückgängig machen willst? -text.confirmadmin = Bist du sicher, dass du diesen Spieler zu einem Admin machen möchtest? -text.confirmunadmin = Bis du sicher, dass dieser Spieler kein Admin mehr sein soll? -text.joingame.title = Spiel beitreten -text.joingame.ip = IP: -text.disconnect = Verbindung unterbrochen. -text.disconnect.data = Fehler beim Laden der Welt! -text.connecting = [accent] Verbinde... -text.connecting.data = [accent] Welt wird geladen... -text.server.port = Port: -text.server.addressinuse = Adresse bereits in Verwendung! -text.server.invalidport = Falscher Port! -text.server.error = [crimson] Fehler beim Hosten des Servers: [accent] {0} -text.save.old = Dieser Spielstand ist von einer älteren Version des Spiels, und kann nicht mehr verwendet werden.\n\n[LIGHT_GRAY]Abwärtskompatibilität von Speicherständen wird in der 4.0 Vollversion hinzugefügt. -text.save.new = Neuer Spielstand -text.save.overwrite = Möchtest du diesen Spielstand wirklich überschreiben? -text.overwrite = Überschreiben -text.save.none = Keine Spielstände gefunden! -text.saveload = [accent] Speichern ... -text.savefail = Fehler beim Speichern des Spiels! -text.save.delete.confirm = Möchtest du diesen Spielstand wirklich löschen? -text.save.delete = Löschen -text.save.export = Spielstand exportieren -text.save.import.invalid = [accent] Dieser Spielstand ist ungültig! -text.save.import.fail = [crimson] Spielstand konnte nicht importiert werden: [accent] {0} -text.save.export.fail = [crimson] Spielstand konnte nicht exportiert werden: [accent] {0} -text.save.import = Spielstand importieren -text.save.newslot = Name speichern: -text.save.rename = Umbenennen -text.save.rename.text = Neuer Name -text.selectslot = Wähle einen Spielstand -text.slot = [accent] Platz {0} -text.save.corrupted = [accent] Datei beschädigt oder ungültig! -text.sector.corrupted = [accent]Ein Spielstand für diesen Sektor wurde nicht gefunden.\nEin neuer Spielstand wurde erstellt. -text.empty = -text.on = An -text.off = Aus -text.save.autosave = Automatisches Speichern: {0} -text.save.map = Karte: {0} -text.save.wave = Welle: {0} -text.save.difficulty = Schwierigkeitsgrad: {0} -text.save.date = Zuletzt gespeichert: {0} -text.save.playtime = Spielzeit: {0} -text.confirm = Bestätigen -text.delete = Löschen -text.ok = OK -text.open = Öffnen -text.cancel = Abbruch -text.openlink = Link öffnen -text.copylink = Kopiere Link -text.back = Zurück -text.quit.confirm = Willst du wirklich aufhören? -text.changelog.title = Changelog -text.changelog.loading = Lade Änderungshistorie... -text.changelog.error.android = [accent]Beachte: Die Änderungshistorie funktioniert manchmal nicht auf Android 4.4 (und älter)!\nDies liegt an einem Android bug. -text.changelog.error.ios = [accent]Die Änderungshistorie wird aktuell nicht von IOS unterstützt. -text.changelog.error = [scarlet]Fehler beim Laden der Änderungshistorie!\nPrüfe deine Internetverbindung. -text.changelog.current = [yellow][[Current version] -text.changelog.latest = [accent][[Latest version] -text.loading = [accent]Wird geladen ... -text.saving = [accent]Speichere... -text.wave = [accent]Welle {0} -text.wave.waiting = Welle in {0} -text.waiting = Warten... -text.waiting.players = Warte auf Spieler... -text.wave.enemies = [LIGHT_GRAY]{0} Gegner verbleiben -text.wave.enemy = [LIGHT_GRAY]{0} Gegner verbleiben -text.loadimage = Bild laden -text.saveimage = Bild speichern -text.unknown = Unbekannt -text.custom = Benutzerdefiniert -text.builtin = Enthalten -text.map.delete.confirm = Bist du sicher, dass du diese Karte löschen willst? Die Aktion kann nicht rückgänig gemacht werden! -text.map.random = [accent]Zufällige Karte -text.map.nospawn = Diese Karte hat keine Kerne in denen die Spieler beginnen können! Füge einen [ROYAL]blue[] Kern zu dieser Karte im Editor hinzu. -text.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. -text.map.invalid = Fehler beim Laden der Karte: Beschädigtes oder invalide Karten Datei. -text.editor.brush = Pinsel -text.editor.slope = \\ -text.editor.openin = Öffne im Editor -text.editor.oregen = Erze generieren -text.editor.oregen.info = Erze generiert: -text.editor.mapinfo = Karten Info -text.editor.author = Author: -text.editor.description = Beschreibung: -text.editor.name = Name: -text.editor.teams = Teams -text.editor.elevation = Höhe -text.editor.errorimageload = Fehler beim Laden des Bildes: [accent] {0} -text.editor.errorimagesave = Fehler beim Speichern des Bildes: [accent] {0} -text.editor.generate = Generieren -text.editor.resize = Grösse\nanpassen -text.editor.loadmap = Karte\nladen -text.editor.savemap = Karte\nspeichern -text.editor.saved = Gespeichert! -text.editor.save.noname = Deine Karte hat keinen Namen! Setze einen Namen im [accent]Karten Info[] Menu. -text.editor.save.overwrite = Deine Karte überschreibt eine built-in Karte! Wähle einen anderen Karten Namen im [accent]'Karten info'[] Menu. -text.editor.import.exists = [scarlet]Fehler beim Import:[] Ein built-in Karte namens '{0}' existiert bereits! -text.editor.import = Import... -text.editor.importmap = Importiere Karte -text.editor.importmap.description = Importiere von einer bestehende Karte -text.editor.importfile = Importiere Datei -text.editor.importfile.description = Importiere aus einer Karten Datei -text.editor.importimage = Importiere Terrain Bild -text.editor.importimage.description = Importiere aus einer Terrain Bild Datei -text.editor.export = Export... -text.editor.exportfile = Export in Datei -text.editor.exportfile.description = Exportiere in eine Karten Datei -text.editor.exportimage = Export in Terrain Bild Datei -text.editor.exportimage.description = Exportiere in eine Karten Bild Datei -text.editor.loadimage = Bild\nladen -text.editor.saveimage = Bild\nspeichern -text.editor.unsaved = [crimson] Du hast Änderungen nicht gespeichert [] Möchtest du wirklich aufhören? -text.editor.resizemap = Grösse der Karte ändern -text.editor.mapname = Karten Name -text.editor.overwrite = [accent] Warnung! Dies überschreibt eine vorhandene Karte. -text.editor.overwrite.confirm = [scarlet]Warnung![] Eine Karte mit diesem Namen existiert bereits. Bist du sicher, dass du sie überschreiben willst? -text.editor.selectmap = Wähle eine Karte zum Laden: -text.width = Breite: -text.height = Höhe: -text.menu = Menü -text.play = Spielen -text.load = Laden -text.save = Speichern -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Ping: {0}ms -text.language.restart = Bitte Starte dein Spiel neu, damit die Sprach-Einstellung aktiv werden. -text.settings = Einstellungen -text.tutorial = Tutorial -text.editor = Editor -text.mapeditor = Karten Editor -text.donate = Spenden -text.connectfail = [crimson] Verbindung zum Server konnte nicht hergestellt werden: [accent]{0} -text.error.unreachable = Server nicht erreichbar. -text.error.invalidaddress = Ungültige Adresse. -text.error.timedout = Zeitüberschreitung!\nStelle sicher, dass die Portweiterleitung auf dem Host richtig eingerichtet ist, und die Adresse stimmt! -text.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! -text.error.alreadyconnected = Bereits verbunden. -text.error.mapnotfound = Map file not found! -text.error.any = Unbekannter Netzwerkfehler. -text.settings.language = Sprache -text.settings.reset = Auf Standard zurücksetzen -text.settings.rebind = Zuweisen -text.settings.controls = Steuerung -text.settings.game = Spiel -text.settings.sound = Audio -text.settings.graphics = Grafiken -text.settings.cleardata = Spieldaten zurücksetzen... -text.settings.clear.confirm = Bist du sicher, dass du die Spieldaten zurücksetzen willst?\n Diese Aktion kann nicht rückgänig gemacht werden! -text.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. -text.settings.clearsectors = Sektoren zurücksetzen -text.settings.clearunlocks = Freischaltungen zurücksetzen -text.settings.clearall = Alles zurücksetzen -text.paused = Pausiert -text.yes = Ja -text.no = Nein -text.info.title = [accent]Info -text.error.title = [crimson] Ein Fehler ist aufgetreten -text.error.crashtitle = Ein Fehler ist aufgetreten! -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = Blockinfo: -text.blocks.powercapacity = Kapazität -text.blocks.powershot = Stromverbrauch/Schuss -text.blocks.targetsair = Visiert Luft Einheiten an -text.blocks.itemspeed = Beförderte Materialien -text.blocks.shootrange = Reichweite -text.blocks.size = Größe -text.blocks.liquidcapacity = Flüssigkeitskapazität -text.blocks.maxitemssecond = Max Materialien -text.blocks.powerrange = Stromreichweite -text.blocks.poweruse = Stromverbrauch -text.blocks.powerdamage = Stromverbrauch/Schadenspunkt -text.blocks.inputitemcapacity = Annahmekapazität -text.blocks.outputitemcapacity = Ausgabekapazität -text.blocks.itemcapacity = Materialkapazität -text.blocks.basepowergeneration = Basis-Stromerzeugung -text.blocks.powertransferspeed = Stromübertragung -text.blocks.craftspeed = Produktionsgeschwindigkeit -text.blocks.inputliquid = Benötigte Flüssigkeit -text.blocks.inputliquidaux = Optionale Flüssigkeit -text.blocks.inputitem = Akzeptiertes Material -text.blocks.inputitems = Akzeptierte Materialien -text.blocks.outputitem = Erzeugtes Material -text.blocks.drilltier = Abbaubare Erze -text.blocks.drillspeed = Bohrgeschwindigkeit -text.blocks.liquidoutput = Erzeugte Flüssigkeit -text.blocks.liquidoutputspeed = Ausgabegeschwindigkeit -text.blocks.liquiduse = Flüssigkeitsverbrauch -text.blocks.coolant = Kühlmittel -text.blocks.coolantuse = Kühlmittelverbrauch -text.blocks.inputliquidfuel = Kraftstoff -text.blocks.liquidfueluse = Kraftstoffverbrauch -text.blocks.boostitem = Boost Item -text.blocks.boostliquid = Boost Liquid -text.blocks.health = Lebenspunkte -text.blocks.inaccuracy = Ungenauigkeit -text.blocks.shots = Schüsse -text.blocks.reload = Schüsse/Sekunde -text.blocks.inputfuel = Kraftstoff -text.blocks.fuelburntime = Kraftstoff Verbrennungs-Zeit -text.blocks.inputcapacity = Annahmekapazität -text.blocks.outputcapacity = Ausgabekapazität -text.unit.blocks = Blöcke -text.unit.powersecond = Stromeinheiten/Sekunde -text.unit.liquidsecond = Flüssigkeitseinheiten/Sekunde -text.unit.itemssecond = Materialeinheiten/Sekunde -text.unit.pixelssecond = Pixel/Sekunde -text.unit.liquidunits = Flüssigkeitseinheiten -text.unit.powerunits = Stromeinheiten -text.unit.degrees = Grad -text.unit.seconds = Sekunden -text.unit.items = Materialeinheiten -text.category.general = Generell -text.category.power = Strom -text.category.liquids = Flüssigkeiten -text.category.items = Materialien -text.category.crafting = Erzeugung -text.category.shooting = Schießen -text.category.optional = Optional Enhancements +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 +link.dev-builds.description = Entwicklungs-Builds (instabil) +link.trello.description = Offizielles Trello Board für geplante Features +link.itch.io.description = itch.io Seite mit Downloads und der Web-Version des Spiels +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! +highscore = [YELLOW] Neuer Highscore! +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: +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[]. +construction.title = Bauanleitung für Blöcke. +construction = Du hast soeben den [accent]Block-Baumodus[] ausgewählt.\n\nTippe einfach auf einen gültigen Platz in der Nähe deines Schiffs, um den Bau zu planen.\nSobald du einige Blöcke platziert hast, drücke zum Bestätigen auf den Haken, und dein Schiff wird mit dem Bau beginnen.\n\n- [accent]Entferne Blöcke[] von deiner Auswahl, indem du darauf tippst.\n- [accent]Verschiebe die Selektion[], indem du einen beliebigen Block in der Auswahl gedrückt hältst und verschiebst.\n- [accent]Platziere Blöcke in einer Linie[], indem du einen leeren Platz gedrückt hältst, und in eine Richtung ziehst.\n- [accent]Breche den Bau oder die Auswahl ab[], indem du das X links unten drückst. +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! > +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 +newgame = New Game +none = +close = Schließen +quit = Verlassen +maps = Karten +continue = Weiter +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! +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.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. +server.kicked.recentKick = Du wurdest gerade gekickt.\nWarte bevor du dich wieder verbindest. +server.kicked.nameInUse = Es ist bereits ein Spieler \nmit diesem Namen auf dem Server. +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 +hostserver.mobile = Host\nGame +host = Host +hosting = [accent] Server wird geöffnet... +hosts.refresh = Aktualisieren +hosts.discovering = Suche nach LAN-Spielen +server.refreshing = Server wird aktualisiert +hosts.none = [lightgray] Keine LAN Spiele gefunden! +host.invalid = [scarlet] Kann keine Verbindung zum Host herstellen. +trace = Spieler verfolgen +trace.playername = Spielername: [accent]{0} +trace.ip = IP: [accent]{0} +trace.id = Eindeutige ID: [accent]{0} +trace.android = Android Client: [accent]{0} +trace.modclient = Custom Client: [accent]{0} +trace.totalblocksbroken = Anzahl zerstörter Blöcke: [accent]{0} +trace.structureblocksbroken = Anzahl zerstörter Gebäude-Blöcke: [accent]{0} +trace.lastblockbroken = Letzter zerstörter Block: [accent]{0} +trace.totalblocksplaced = Anzahl platzierter Blöcke: [accent]{0} +trace.lastblockplaced = Letzter platzierter Block: [accent]{0} +invalidid = Ungültige Client ID! Berichte den Bug. +server.bans = Bans +server.bans.none = Keine gebannten Spieler gefunden! +server.admins = Admins +server.admins.none = Keine Admins gefunden! +server.add = Server hinzufügen +server.delete = Bist du dir sicher, dass du diesen Server löschen möchtest? +server.hostname = Host: {0} +server.edit = Server bearbeiten +server.outdated = [crimson]Veralteter Server![] +server.outdated.client = [crimson]Veralteter Client![] +server.version = [lightgray]Version: {0} +server.custombuild = [yellow]Custom Build +confirmban = Bist du sicher, dass du diesen Spieler verbannen möchtest? +confirmkick = Bist du sicher, dass du diesen Spieler kicken willst? +confirmunban = Bist du sicher, dass du die Verbannung des Spielers rückgängig machen willst? +confirmadmin = Bist du sicher, dass du diesen Spieler zu einem Admin machen möchtest? +confirmunadmin = Bis du sicher, dass dieser Spieler kein Admin mehr sein soll? +joingame.title = Spiel beitreten +joingame.ip = IP: +disconnect = Verbindung unterbrochen. +disconnect.data = Fehler beim Laden der Welt! +connecting = [accent] Verbinde... +connecting.data = [accent] Welt wird geladen... +server.port = Port: +server.addressinuse = Adresse bereits in Verwendung! +server.invalidport = Falscher Port! +server.error = [crimson] Fehler beim Hosten des Servers: [accent] {0} +save.old = Dieser Spielstand ist von einer älteren Version des Spiels, und kann nicht mehr verwendet werden.\n\n[LIGHT_GRAY]Abwärtskompatibilität von Speicherständen wird in der 4.0 Vollversion hinzugefügt. +save.new = Neuer Spielstand +save.overwrite = Möchtest du diesen Spielstand wirklich überschreiben? +overwrite = Überschreiben +save.none = Keine Spielstände gefunden! +saveload = [accent] Speichern ... +savefail = Fehler beim Speichern des Spiels! +save.delete.confirm = Möchtest du diesen Spielstand wirklich löschen? +save.delete = Löschen +save.export = Spielstand exportieren +save.import.invalid = [accent] Dieser Spielstand ist ungültig! +save.import.fail = [crimson] Spielstand konnte nicht importiert werden: [accent] {0} +save.export.fail = [crimson] Spielstand konnte nicht exportiert werden: [accent] {0} +save.import = Spielstand importieren +save.newslot = Name speichern: +save.rename = Umbenennen +save.rename.text = Neuer Name +selectslot = Wähle einen Spielstand +slot = [accent] Platz {0} +save.corrupted = [accent] Datei beschädigt oder ungültig! +empty = +on = An +off = Aus +save.autosave = Automatisches Speichern: {0} +save.map = Karte: {0} +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 +open = Öffnen +cancel = Abbruch +openlink = Link öffnen +copylink = Kopiere Link +back = Zurück +quit.confirm = Willst du wirklich aufhören? +changelog.title = Changelog +changelog.loading = Lade Änderungshistorie... +changelog.error.android = [accent]Beachte: Die Änderungshistorie funktioniert manchmal nicht auf Android 4.4 (und älter)!\nDies liegt an einem Android bug. +changelog.error.ios = [accent]Die Änderungshistorie wird aktuell nicht von IOS unterstützt. +changelog.error = [scarlet]Fehler beim Laden der Änderungshistorie!\nPrüfe deine Internetverbindung. +changelog.current = [yellow][[Current version] +changelog.latest = [accent][[Latest version] +loading = [accent]Wird geladen ... +saving = [accent]Speichere... +wave = [accent]Welle {0} +wave.waiting = Welle in {0} +waiting = Warten... +waiting.players = Warte auf Spieler... +wave.enemies = [LIGHT_GRAY]{0} Gegner verbleiben +wave.enemy = [LIGHT_GRAY]{0} Gegner verbleiben +loadimage = Bild laden +saveimage = Bild speichern +unknown = Unbekannt +custom = Benutzerdefiniert +builtin = Enthalten +map.delete.confirm = Bist du sicher, dass du diese Karte löschen willst? Die Aktion kann nicht rückgänig gemacht werden! +map.random = [accent]Zufällige Karte +map.nospawn = Diese Karte hat keine Kerne in denen die Spieler beginnen können! Füge einen [ROYAL]blue[] Kern zu dieser Karte im Editor hinzu. +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: +editor.mapinfo = Karten Info +editor.author = Author: +editor.description = Beschreibung: +editor.name = Name: +editor.teams = Teams +editor.elevation = Höhe +editor.errorimageload = Fehler beim Laden des Bildes: [accent] {0} +editor.errorimagesave = Fehler beim Speichern des Bildes: [accent] {0} +editor.generate = Generieren +editor.resize = Grösse\nanpassen +editor.loadmap = Karte\nladen +editor.savemap = Karte\nspeichern +editor.saved = Gespeichert! +editor.save.noname = Deine Karte hat keinen Namen! Setze einen Namen im [accent]Karten Info[] Menu. +editor.save.overwrite = Deine Karte überschreibt eine built-in Karte! Wähle einen anderen Karten Namen im [accent]'Karten info'[] Menu. +editor.import.exists = [scarlet]Fehler beim Import:[] Ein built-in Karte namens '{0}' existiert bereits! +editor.import = Import... +editor.importmap = Importiere Karte +editor.importmap.description = Importiere von einer bestehende Karte +editor.importfile = Importiere Datei +editor.importfile.description = Importiere aus einer Karten Datei +editor.importimage = Importiere Terrain Bild +editor.importimage.description = Importiere aus einer Terrain Bild Datei +editor.export = Export... +editor.exportfile = Export in Datei +editor.exportfile.description = Exportiere in eine Karten Datei +editor.exportimage = Export in Terrain Bild Datei +editor.exportimage.description = Exportiere in eine Karten Bild Datei +editor.loadimage = Bild\nladen +editor.saveimage = Bild\nspeichern +editor.unsaved = [crimson] Du hast Änderungen nicht gespeichert [] Möchtest du wirklich aufhören? +editor.resizemap = Grösse der Karte ändern +editor.mapname = Karten Name +editor.overwrite = [accent] Warnung! Dies überschreibt eine vorhandene Karte. +editor.overwrite.confirm = [scarlet]Warnung![] Eine Karte mit diesem Namen existiert bereits. Bist du sicher, dass du sie überschreiben willst? +editor.selectmap = Wähle eine Karte zum Laden: +width = Breite: +height = Höhe: +menu = Menü +play = Spielen +load = Laden +save = Speichern +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0}ms +language.restart = Bitte Starte dein Spiel neu, damit die Sprach-Einstellung aktiv werden. +settings = Einstellungen +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson] Verbindung zum Server konnte nicht hergestellt werden: [accent]{0} +error.unreachable = Server nicht erreichbar. +error.invalidaddress = Ungültige Adresse. +error.timedout = Zeitüberschreitung!\nStelle sicher, dass die Portweiterleitung auf dem Host richtig eingerichtet ist, und die Adresse stimmt! +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 +settings.controls = Steuerung +settings.game = Spiel +settings.sound = Audio +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.clearunlocks = Freischaltungen zurücksetzen +settings.clearall = Alles zurücksetzen +paused = Pausiert +yes = Ja +no = Nein +info.title = [accent]Info +error.title = [crimson] Ein Fehler ist aufgetreten +error.crashtitle = Ein Fehler ist aufgetreten! +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Blockinfo: +blocks.powercapacity = Kapazität +blocks.powershot = Stromverbrauch/Schuss +blocks.targetsair = Visiert Luft Einheiten an +blocks.itemspeed = Beförderte Materialien +blocks.shootrange = Reichweite +blocks.size = Größe +blocks.liquidcapacity = Flüssigkeitskapazität +blocks.maxitemssecond = Max Materialien +blocks.powerrange = Stromreichweite +blocks.poweruse = Stromverbrauch +blocks.powerdamage = Stromverbrauch/Schadenspunkt +blocks.inputitemcapacity = Annahmekapazität +blocks.outputitemcapacity = Ausgabekapazität +blocks.itemcapacity = Materialkapazität +blocks.basepowergeneration = Basis-Stromerzeugung +blocks.powertransferspeed = Stromübertragung +blocks.craftspeed = Produktionsgeschwindigkeit +blocks.inputliquid = Benötigte Flüssigkeit +blocks.inputliquidaux = Optionale Flüssigkeit +blocks.inputitem = Akzeptiertes Material +blocks.inputitems = Akzeptierte Materialien +blocks.outputitem = Erzeugtes Material +blocks.drilltier = Abbaubare Erze +blocks.drillspeed = Bohrgeschwindigkeit +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.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = Ungenauigkeit +blocks.shots = Schüsse +blocks.reload = Schüsse/Sekunde +blocks.inputfuel = Kraftstoff +blocks.fuelburntime = Kraftstoff Verbrennungs-Zeit +blocks.inputcapacity = Annahmekapazität +blocks.outputcapacity = Ausgabekapazität +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 +unit.seconds = Sekunden +unit.items = Materialeinheiten +category.general = Generell +category.power = Strom +category.liquids = Flüssigkeiten +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 @@ -371,18 +379,22 @@ setting.mutemusic.name = Musik stummschalten setting.sfxvol.name = Audioeffekt-Lautstärke setting.mutesound.name = Audioeffekte stummschalten setting.crashreport.name = Send Anonymous Crash Reports -text.keybind.title = Tasten zuweisen +keybind.title = Tasten zuweisen category.general.name = Allgemein category.view.name = Ansicht 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.pick.name = Pick Block keybind.break.name = Abreißen keybind.deselect.name = Auswahl aufheben keybind.shoot.name = Schießen @@ -401,30 +413,29 @@ keybind.chat_history_next.name = Chat Historie vor keybind.chat_scroll.name = Chat scrollen keybind.drop_unit.name = Einheit absetzen keybind.zoom_minimap.name = Minimap-Zoom -mode.text.help.title = Beschreibung der Modi -mode.waves.name = Wellen -mode.waves.description = Der normale Modus. Begrenzte Ressourcen und automatische Wellen. +mode.help.title = Beschreibung der Modi +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.descrption = 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 @@ -445,6 +456,10 @@ 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.oil.name = Öl @@ -478,24 +493,29 @@ mech.trident-ship.weapon = Bombenschacht mech.glaive-ship.name = Glaive mech.glaive-ship.description = Ein großes, gut gepanzertes Gunship. Ausgerüstet mit einer Brandwaffe. Gute Beschleunigung und maximale Geschwindigkeit. mech.glaive-ship.weapon = Flammen-Mehrlader -text.item.explosiveness = [LIGHT_GRAY]Explosivität: {0} -text.item.flammability = [LIGHT_GRAY]Entflammbarkeit: {0} -text.item.radioactivity = [LIGHT_GRAY]Radioaktivität: {0} -text.item.fluxiness = [LIGHT_GRAY]Strömungskraft: {0} -text.unit.health = [LIGHT_GRAY]Lebenskraft: {0} -text.unit.speed = [LIGHT_GRAY]Geschwindigkeit: {0} -text.mech.weapon = [LIGHT_GRAY]Waffe: {0} -text.mech.armor = [LIGHT_GRAY]Rüstung: {0} -text.mech.itemcapacity = [LIGHT_GRAY]Materialkapazität: {0} -text.mech.minespeed = [LIGHT_GRAY]Erzabbaugeschwindigkeit: {0} -text.mech.minepower = [LIGHT_GRAY]Erzabbaukraft: {0} -text.mech.ability = [LIGHT_GRAY]Fähigkeit: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]Wärmekapazität: {0} -text.liquid.viscosity = [LIGHT_GRAY]Viskosität: {0} -text.liquid.temperature = [LIGHT_GRAY]Temperatur: {0} +item.explosiveness = [LIGHT_GRAY]Explosivität: {0} +item.flammability = [LIGHT_GRAY]Entflammbarkeit: {0} +item.radioactivity = [LIGHT_GRAY]Radioaktivität: {0} +unit.health = [LIGHT_GRAY]Lebenskraft: {0} +unit.speed = [LIGHT_GRAY]Geschwindigkeit: {0} +mech.weapon = [LIGHT_GRAY]Waffe: {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} +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.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.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = Metallboden block.deepwater.name = Tiefes Wasser block.water.name = Wasser @@ -514,8 +534,8 @@ block.blackrock.name = Schwarzer Fels block.icerock.name = Eisfels 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 @@ -548,17 +568,19 @@ 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 @@ -567,11 +589,11 @@ block.omega-mech-pad.name = Omega Mech Pad block.tau-mech-pad.name = Tau Mech Pad block.conduit.name = Leitungsrohr block.mechanical-pump.name = Mechanische Pumpe -block.itemsource.name = Materialquelle -block.itemvoid.name = Materialschlucker -block.liquidsource.name = Flüssigkeitsquelle -block.powervoid.name = Stromsenke -block.powerinfinite.name = Unendliche Stromquelle +block.item-source.name = Materialquelle +block.item-void.name = Materialschlucker +block.liquid-source.name = Flüssigkeitsquelle +block.power-void.name = Stromsenke +block.power-source.name = Unendliche Stromquelle block.unloader.name = Entlader block.vault.name = Tresor block.wave.name = Welle @@ -623,7 +645,7 @@ 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 team.blue.name = Blau team.red.name = Rot team.orange.name = Orange @@ -637,6 +659,7 @@ 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 +669,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. @@ -769,11 +796,11 @@ block.router.description = Akzeptiert Materialien aus einer Richtung und leitet 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.itemsource.description = Produziert unendlich items. Nur im Sandkasten verfügbar. -block.liquidsource.description = Produziert unendlich Flüssigkeiten. Nur im Sandkasten verfügbar. -block.itemvoid.description = Zerstört Materialien, die hereingegeben werden, ohne Strom zu verbrauchen. Nur im Sandkasten verfügbar. -block.powerinfinite.description = Erzeugt unendlich viel Strom. Nur im Sandkasten verfügbar. -block.powervoid.description = Verschlingt den kompletten übrigen Strom. Nur im Sandkasten verfügbar. +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. diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index cd975d0fb1..f0f25c6bac 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -1,351 +1,359 @@ -text.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!) -text.credits = Créditos -text.discord = ¡Únete al Discord de Mindustry! -text.link.discord.description = La sala oficial del Discord de Mindustry -text.link.github.description = Código fuente del juego -text.link.dev-builds.description = Versiones de desarrollo inestable -text.link.trello.description = Tablero de Trello oficial para las características planificadas -text.link.itch.io.description = itch.io es la página donde podes descargar las versiones para PC y web -text.link.google-play.description = Ficha en la Google Play Store -text.link.wiki.description = Wiki oficial de Mindustry -text.linkfail = ¡Error al abrir el enlace!\nLa URL ha sido copiada a su portapapeles. -text.gameover = Tu núcleo ha sido destruido. -text.gameover.pvp = ¡El equipo[accent] {0}[] ha ganado! -text.sector.gameover = Este sector ha sido perdido. ¿Re-desplegar? -text.sector.retry = Reintentar -text.highscore = [accent]¡Nueva mejor puntuación! -text.wave.lasted = Duraste hasta la ronda [accent]{0}[]. -text.level.highscore = Puntuación más alta: [accent]{0} -text.level.delete.title = Confirmar Eliminación -text.map.delete = ¿Estás seguro que quieres borrar el mapa "[accent]{0}[]"? -text.level.select = Selección de nivel -text.level.mode = Modo de juego: -text.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[]. -text.construction.title = Guía de Construcción de Bloques -text.construction = Acaba de seleccionar el [accent]modo de construcción de bloques[].\n\nPara empezar a colocar, simplemente presione en una localización valida cerca de su nave.\nCuando haya terminado de seleccionar algunos bloques, presiona la casilla para confirmar, y su nave empezara a construirlos.\n\n- [accent]Remueve bloques[] de tu selección presionando en ellos.\n- [accent]Cambia tu selección de lugar[] manteniendo y arrastrando cualquier bloque en la selección.\n- [accent]Coloca bloques en línea[] presionando y manteniendo en un espacio vacío, y arrastrando hacia cualquier dirección.\n- [accent]Cancela la construcción o selección[] presionando la X abajo a la izquierda. -text.deconstruction.title = Guía de Deconstrucción de Bloques -text.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. -text.showagain = No mostrar otra vez en la próxima sesión -text.coreattack = < ¡El núcleo está bajo ataque! > -text.unlocks = Desbloqueos -text.savegame = Guardar Partida -text.loadgame = Cargar Partida -text.joingame = Unirse a la Partida -text.addplayers = Agregar/Quitar Jugadores -text.customgame = Partida personalizada -text.sectors = Sectores -text.sector = Sector: [LIGHT_GRAY]{0} -text.sector.time = Tiempo: [LIGHT_GRAY]{0} -text.sector.deploy = Desplegar -text.sector.abandon = Abandonar -text.sector.abandon.confirm = ¿Realmente quieres abandonar todo el progreso hecho en este sector?\n¡Esto no se puede deshacer! -text.sector.resume = Continuar -text.sector.locked = [scarlet][[Incompleto] -text.sector.unexplored = [accent][[No explorado] -text.missions = Misiones:[LIGHT_GRAY] {0} -text.mission = Misión:[LIGHT_GRAY] {0} -text.mission.main = Misión Principal:[LIGHT_GRAY] {0} -text.mission.info = Información de la Misión -text.mission.complete = ¡Misión completada! -text.mission.complete.body = El Sector {0},{1} ha sido conquistado. -text.mission.wave = Sobrevive [accent]{0}/{1}[] hordas\nHordas en {2} -text.mission.wave.enemies = Sobrevive[accent] {0}/{1} []hordas\n{2} Enemigas -text.mission.wave.enemy = Sobrevive[accent] {0}/{1} []hordas\n{2} Enemigas -text.mission.wave.menu = Sobrevive[accent] {0} []hordas -text.mission.battle = Destruye la base enemiga. -text.mission.resource.menu = Obtener {0} x{1} -text.mission.resource = Obtén {0} x{1} -text.mission.block = Crear {0} -text.mission.unit = Crear {0} -text.mission.command = Envía Comando {0} a las unidades -text.mission.linknode = Conecta nodo de energía -text.mission.display = [accent]Misión:\n[LIGHT_GRAY]{0} -text.mission.mech = Cambiar a mecanoide[accent] {0}[] -text.mission.create = Crear[accent] {0}[] -text.none = -text.close = Cerrar -text.quit = Salir -text.maps = Mapas -text.continue = Continuar -text.nextmission = Próxima Misión -text.maps.none = [LIGHT_GRAY]¡No se han encontrado mapas! -text.about.button = Acerca de -text.name = Nombre: -text.filename = Nombre del archivo: -text.unlocked = ¡Nuevo Bloque Desbloqueado! -text.unlocked.plural = ¡Nuevos Bloques Desbloqueados! -text.players = {0} jugadores online -text.players.single = {0} jugador online -text.server.closing = [accent]Cerrando servidor... -text.server.kicked.kick = ¡Has sido expulsado del servidor! -text.server.kicked.serverClose = El servidor ha cerrado. -text.server.kicked.sectorComplete = Sector completado. -text.server.kicked.sectorComplete.text = Tu misión ha sido completada.\nEl servidor ahora continuará con el próximo sector. -text.server.kicked.clientOutdated = ¡Cliente desactualizado! ¡Actualiza tu juego! -text.server.kicked.serverOutdated = ¡Servidor desactualizado! ¡Pídele al anfitrión que lo actualice! -text.server.kicked.banned = Has sido baneado del servidor. -text.server.kicked.recentKick = Has sido expulsado recientemente.\nEspera para poder conectarte de nuevo. -text.server.kicked.nameInUse = Ya hay alguien con ese\nnombre en el servidor. -text.server.kicked.nameEmpty = Tu nombre debe por lo menos contener un carácter o número. -text.server.kicked.idInUse = ¡Ya estás en el servidor! Conectarse con dos cuentas no está permitido. -text.server.kicked.customClient = Este servidor no soporta versiones personalizadas. Descarga una versión oficial. -text.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. -text.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. -text.hostserver = Hostear Servidor -text.hostserver.mobile = Hostear\nJuego -text.host = Hostear -text.hosting = [accent]Abriendo servidor... -text.hosts.refresh = Actualizar -text.hosts.discovering = Descubrir partidas LAN -text.server.refreshing = Actualizando servidor... -text.hosts.none = [lightgray]¡No se han encontrado partidas LAN! -text.host.invalid = [scarlet]No se ha podido conectar al anfitrión. -text.trace = Rastrear Jugador -text.trace.playername = Nombre de jugador: [accent]{0} -text.trace.ip = IP: [accent]{0} -text.trace.id = ID Única: [accent]{0} -text.trace.android = Cliente de Android: [accent]{0} -text.trace.modclient = Cliente Personalizado: [accent]{0} -text.trace.totalblocksbroken = Total de bloques quitados: [accent]{0} -text.trace.structureblocksbroken = Bloques de estructura quitados: [accent]{0} -text.trace.lastblockbroken = Último bloque quitado: [accent]{0} -text.trace.totalblocksplaced = Total de bloques colocados: [accent]{0} -text.trace.lastblockplaced = Último bloque colocado: [accent]{0} -text.invalidid = ¡ID de cliente inválida! Envía un informe del error. -text.server.bans = Baneos -text.server.bans.none = ¡Ningún usuario ha sido baneado! -text.server.admins = Administradores -text.server.admins.none = ¡Ningún administrador ha sido encontrado! -text.server.add = Agregar Servidor -text.server.delete = ¿Estás seguro de querer borrar este servidor? -text.server.hostname = Anfitrión: {0} -text.server.edit = Editar Servidor -text.server.outdated = [crimson]¡Servidor desactualizado![] -text.server.outdated.client = [crimson]¡Cliente desactualizado![] -text.server.version = [lightgray]Versión: {0} -text.server.custombuild = [yellow]Versión personalizada -text.confirmban = ¿Estás seguro de querer banear este jugador? -text.confirmkick = ¿Estás seguro de querer expulsar este jugador? -text.confirmunban = ¿Estás seguro de querer desbanear este jugador? -text.confirmadmin = ¿Estás seguro de querer hacer administrador a este jugador? -text.confirmunadmin = ¿Estás seguro de querer quitar los permisos de administrador a este jugador? -text.joingame.title = Unirse a la partida -text.joingame.ip = IP: -text.disconnect = Desconectado. -text.disconnect.data = ¡Se ha fallado la carga de datos del mundo! -text.connecting = [accent]Conectando... -text.connecting.data = [accent]Cargando datos del mundo... -text.server.port = Puerto: -text.server.addressinuse = ¡La dirección ya está en uso! -text.server.invalidport = ¡El número de puerto es invalido! -text.server.error = [crimson]Error hosteando el servidor: error [accent]{0} -text.save.old = Este punto de guardado es de una versión más antigua de este juego, y ya no puede ser usada.\n\n[LIGHT_GRAY]La retrocmpatibilidad de los puntos de guardado estará completamente implementada en la versión 4.0. -text.save.new = Nuevo Punto de Guardado -text.save.overwrite = ¿Estás seguro de querer sobrescribir\neste punto de guardado? -text.overwrite = Sobrescribir -text.save.none = ¡No se ha encontrado ningún punto de guardado! -text.saveload = [accent]Guardando... -text.savefail = ¡No se ha podido guardar la partida! -text.save.delete.confirm = ¿Estás seguro de querer borrar este punto de guardado? -text.save.delete = Borrar -text.save.export = Exportar Punto de Guardado -text.save.import.invalid = [accent]¡Este punto de guardado es inválido! -text.save.import.fail = [crimson]La importación del punto de guardado ha fallado: error [accent]{0} -text.save.export.fail = [crimson]La exportación del punto de guardado ha fallado: error [accent]{0} -text.save.import = Importar Punto de Guardado -text.save.newslot = Nombre del Punto de Guardado: -text.save.rename = Renombrar -text.save.rename.text = Nuevo nombre: -text.selectslot = Selecciona un Punto de Guardado. -text.slot = [accent]Casilla {0} -text.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. -text.sector.corrupted = [accent]El punto de guardado de este sector fue encontrado, pero su carga ha fallado.\nUn nuevo punto ha sido creado. -text.empty = -text.on = Encendido -text.off = Apagado -text.save.autosave = Autoguardado: {0} -text.save.map = Mapa: {0} -text.save.wave = Horda {0} -text.save.difficulty = Dificultad: {0} -text.save.date = Última vez guardado: {0} -text.save.playtime = Tiempo de juego: {0} -text.confirm = Confirmar -text.delete = Borrar -text.ok = OK -text.open = Abrir -text.cancel = Cancelar -text.openlink = Abrir Enlace -text.copylink = Copiar Enlace -text.back = Atrás -text.quit.confirm = ¿Estás seguro de querer salir de la partida? -text.changelog.title = Registro de Parches -text.changelog.loading = Consiguiendo el registro de parches... -text.changelog.error.android = [accent]¡Nota: el registro de parches a veces no funciona en Android 4.4 o inferior!\nEsto es por un error interno de Android. -text.changelog.error.ios = [accent]El registro de parches no está actualmente soportado para iOS. -text.changelog.error = [scarlet]¡Error consiguiendo el registro de parches!Comprueba tu conexión a Internet. -text.changelog.current = [yellow][[Versión actual] -text.changelog.latest = [accent][[Última version] -text.loading = [accent]Cargando... -text.saving = [accent]Guardando... -text.wave = [accent]Horda {0} -text.wave.waiting = Horda en {0} -text.waiting = Esperando... -text.waiting.players = Esperando jugadores... -text.wave.enemies = [LIGHT_GRAY]{0} Enemigos Restantes -text.wave.enemy = [LIGHT_GRAY]{0} Enemigo Restante -text.loadimage = Cargar Imagen -text.saveimage = Guardar Imagen -text.unknown = Desconocido -text.custom = Personalizado -text.builtin = Incorporado -text.map.delete.confirm = ¿Estás seguro de querer borrar este mapa? ¡Recuerda que está acción no puede sdeshacerse! -text.map.random = [accent]Mapa Aleatorio -text.map.nospawn = ¡Este mapa no tiene ningún núcleo en el cual pueda aparecer el jugador! Agrega un núcleo[ROYAL] blue[] al mapa con el editor. -text.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. -text.map.invalid = Error cargando el mapa: archivo corrupto o inválido. -text.editor.brush = Pincel -text.editor.slope = \\ -text.editor.openin = Abrir en el Editor -text.editor.oregen = Generación de Minerales -text.editor.oregen.info = Generación de Minerales: -text.editor.mapinfo = Info del Mapa -text.editor.author = Autor: -text.editor.description = Descripción: -text.editor.name = Nombre: -text.editor.teams = Equipos -text.editor.elevation = Elevación -text.editor.errorimageload = Error cargando el archivo:\n[accent] {0} -text.editor.errorimagesave = Error guardando el archivo:\n[accent] {0} -text.editor.generate = Generar -text.editor.resize = Cambiar Tamaño -text.editor.loadmap = Cargar Mapa -text.editor.savemap = Guardar Mapa -text.editor.saved = ¡Guardado! -text.editor.save.noname = ¡Tu mapa no tiene un nombre! Pon uno en el menú 'Info del Mapa'. -text.editor.save.overwrite = ¡Tu mapa sobrescribe uno ya incorporado! Elige un nombre diferente en el menú 'Info del Mapa'. -text.editor.import.exists = [scarlet]¡No se ha podido importar:[] un mapa incorporado con el nombre '{0}' ya existe! -text.editor.import = Importar... -text.editor.importmap = Importar Mapa -text.editor.importmap.description = Importar un mapa ya existente -text.editor.importfile = Importar Archivo -text.editor.importfile.description = Importar un archivo externo del mapa -text.editor.importimage = Importar Imagen del Terreno -text.editor.importimage.description = Importar archivo externo de imagen del mapa -text.editor.export = Exportar... -text.editor.exportfile = Exportar Archivo -text.editor.exportfile.description = Exportar archivo del mapa -text.editor.exportimage = Exportar Imagen del Terreno -text.editor.exportimage.description = Exportar archivo de imagen del mapa -text.editor.loadimage = Importar Terreno -text.editor.saveimage = Exportar Terreno -text.editor.unsaved = [scarlet]¡Tienes cambios sin guardar![]\n¿Estás seguro de querer salir? -text.editor.resizemap = Cambiar Tamaño del Mapa -text.editor.mapname = Nombre del Mapa: -text.editor.overwrite = [accent]¡Advertencia!\nEsto sobrescribe un mapa ya existente. -text.editor.overwrite.confirm = [scarlet]¡Advertencia![] Un mapa con ese nombre ya existe. ¿Estás seguro de querer sobrescribirlo? -text.editor.selectmap = Selecciona un mapa para cargar: -text.width = Ancho: -text.height = Alto: -text.menu = Menu -text.play = Jugar -text.load = Cargar -text.save = Guardar -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Ping: {0} ms -text.language.restart = Por favor reinicie el juego para que los cambios del lenguaje surjan efecto. -text.settings = Ajustes -text.tutorial = Tutorial -text.editor = Editor -text.mapeditor = Editor de Mapa -text.donate = Donar -text.connectfail = [crimson]Ha fallado la conexión con el servidor: [accent]{0} -text.error.unreachable = Servidor inaccesible. -text.error.invalidaddress = Dirección inválida. -text.error.timedout = ¡Se acabó el tiempo!\n¡Asegúrate que el host ha hecho el port forwarding, y que la dirección es correcta! -text.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. -text.error.alreadyconnected = Ya estás conectado. -text.error.mapnotfound = ¡Archivo de mapa no encontrado! -text.error.any = Error de red desconocido. -text.settings.language = Lenguaje -text.settings.reset = Reiniciar por los de defecto -text.settings.rebind = Reasignar -text.settings.controls = Controles -text.settings.game = Juego -text.settings.sound = Sonido -text.settings.graphics = Gráficos -text.settings.cleardata = Limpiar Datos del Juego... -text.settings.clear.confirm = ¿Estas seguro de querer limpiar estos datos?\n¡Esta acción no puede deshacerse! -text.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. -text.settings.clearsectors = Eliminar Sectores -text.settings.clearunlocks = Eliminar Desbloqueos -text.settings.clearall = Eliminar Todo -text.paused = Pausado -text.yes = Sí -text.no = No -text.info.title = [accent]Información -text.error.title = [crimson]Un error ha ocurrido. -text.error.crashtitle = Un error ha ocurrido. -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = Información del Bloque -text.blocks.powercapacity = Capacidad de Energía -text.blocks.powershot = Energía/Disparo -text.blocks.targetsair = Apunta al Aire -text.blocks.itemspeed = Unidades Movidas -text.blocks.shootrange = Rango -text.blocks.size = Tamaño -text.blocks.liquidcapacity = Capacidad de Líquidos -text.blocks.maxitemssecond = Máximo de Objetos -text.blocks.powerrange = Rango de Energía -text.blocks.poweruse = Consumo de Energía -text.blocks.powerdamage = Energía/Daño -text.blocks.inputitemcapacity = Capacidad de Entrada de los Objetos -text.blocks.outputitemcapacity = Capacidad de Salida de los Objetos -text.blocks.itemcapacity = Capacidad de Objetos -text.blocks.basepowergeneration = Generación de energía base -text.blocks.powertransferspeed = Transferencia de Energía -text.blocks.craftspeed = Velocidad de Producción -text.blocks.inputliquid = Líquidos de Entrada -text.blocks.inputliquidaux = Líquido Auxiliar -text.blocks.inputitem = Objeto de Entrada -text.blocks.inputitems = Objetos de Entrada -text.blocks.outputitem = Objeto de Salida -text.blocks.drilltier = Taladrables -text.blocks.drillspeed = Velocidad Base del Taladro -text.blocks.liquidoutput = Líquido de Salida -text.blocks.liquidoutputspeed = Velocidad de Salida del Líquido -text.blocks.liquiduse = Uso de Líquido -text.blocks.coolant = Refrigerante -text.blocks.coolantuse = Uso del Refrigerante -text.blocks.inputliquidfuel = Combustible Líquido -text.blocks.liquidfueluse = Uso del Combustible Líquido -text.blocks.boostitem = Boost Item -text.blocks.boostliquid = Boost Liquid -text.blocks.health = Vida -text.blocks.inaccuracy = Imprecisión -text.blocks.shots = Disparos -text.blocks.reload = Recarga -text.blocks.inputfuel = Combustible -text.blocks.fuelburntime = Tiempo de Quemado del Combustible -text.blocks.inputcapacity = Capacidad de entrada -text.blocks.outputcapacity = Capacidad de salida -text.unit.blocks = bloques -text.unit.powersecond = unidades de energía/segundo -text.unit.liquidsecond = unidades de líquido/segundo -text.unit.itemssecond = objetos/segundo -text.unit.pixelssecond = píxeles/segundo -text.unit.liquidunits = unidades de líquido -text.unit.powerunits = unidades de energía -text.unit.degrees = grados -text.unit.seconds = segundos -text.unit.items = objetos -text.category.general = General -text.category.power = Energía -text.category.liquids = Líquidos -text.category.items = Objetos -text.category.crafting = Fabricación -text.category.shooting = Disparo -text.category.optional = Mejoras Opcionales +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 +link.dev-builds.description = Versiones de desarrollo inestable +link.trello.description = Tablero de Trello oficial para las características planificadas +link.itch.io.description = itch.io es la página donde podes descargar las versiones para PC y web +link.google-play.description = Ficha en la Google Play Store +link.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! +highscore = [accent]¡Nueva mejor puntuació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: +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[]. +construction.title = Guía de Construcción de Bloques +construction = Acaba de seleccionar el [accent]modo de construcción de bloques[].\n\nPara empezar a colocar, simplemente presione en una localización valida cerca de su nave.\nCuando haya terminado de seleccionar algunos bloques, presiona la casilla para confirmar, y su nave empezara a construirlos.\n\n- [accent]Remueve bloques[] de tu selección presionando en ellos.\n- [accent]Cambia tu selección de lugar[] manteniendo y arrastrando cualquier bloque en la selección.\n- [accent]Coloca bloques en línea[] presionando y manteniendo en un espacio vacío, y arrastrando hacia cualquier dirección.\n- [accent]Cancela la construcción o selección[] presionando la X abajo a la izquierda. +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! > +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 +newgame = New Game +none = +close = Cerrar +quit = Salir +maps = Mapas +continue = Continuar +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! +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.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. +server.kicked.recentKick = Has sido expulsado recientemente.\nEspera para poder conectarte de nuevo. +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 +hostserver.mobile = Hostear\nJuego +host = Hostear +hosting = [accent]Abriendo servidor... +hosts.refresh = Actualizar +hosts.discovering = Descubrir partidas LAN +server.refreshing = Actualizando servidor... +hosts.none = [lightgray]¡No se han encontrado partidas LAN! +host.invalid = [scarlet]No se ha podido conectar al anfitrión. +trace = Rastrear Jugador +trace.playername = Nombre de jugador: [accent]{0} +trace.ip = IP: [accent]{0} +trace.id = ID Única: [accent]{0} +trace.android = Cliente de Android: [accent]{0} +trace.modclient = Cliente Personalizado: [accent]{0} +trace.totalblocksbroken = Total de bloques quitados: [accent]{0} +trace.structureblocksbroken = Bloques de estructura quitados: [accent]{0} +trace.lastblockbroken = Último bloque quitado: [accent]{0} +trace.totalblocksplaced = Total de bloques colocados: [accent]{0} +trace.lastblockplaced = Último bloque colocado: [accent]{0} +invalidid = ¡ID de cliente inválida! Envía un informe del error. +server.bans = Baneos +server.bans.none = ¡Ningún usuario ha sido baneado! +server.admins = Administradores +server.admins.none = ¡Ningún administrador ha sido encontrado! +server.add = Agregar Servidor +server.delete = ¿Estás seguro de querer borrar este servidor? +server.hostname = Anfitrión: {0} +server.edit = Editar Servidor +server.outdated = [crimson]¡Servidor desactualizado![] +server.outdated.client = [crimson]¡Cliente desactualizado![] +server.version = [lightgray]Versión: {0} +server.custombuild = [yellow]Versión personalizada +confirmban = ¿Estás seguro de querer banear este jugador? +confirmkick = ¿Estás seguro de querer expulsar este jugador? +confirmunban = ¿Estás seguro de querer desbanear este jugador? +confirmadmin = ¿Estás seguro de querer hacer administrador a este jugador? +confirmunadmin = ¿Estás seguro de querer quitar los permisos de administrador a este jugador? +joingame.title = Unirse a la partida +joingame.ip = IP: +disconnect = Desconectado. +disconnect.data = ¡Se ha fallado la carga de datos del mundo! +connecting = [accent]Conectando... +connecting.data = [accent]Cargando datos del mundo... +server.port = Puerto: +server.addressinuse = ¡La dirección ya está en uso! +server.invalidport = ¡El número de puerto es invalido! +server.error = [crimson]Error hosteando el servidor: error [accent]{0} +save.old = Este punto de guardado es de una versión más antigua de este juego, y ya no puede ser usada.\n\n[LIGHT_GRAY]La retrocmpatibilidad de los puntos de guardado estará completamente implementada en la versión 4.0. +save.new = Nuevo Punto de Guardado +save.overwrite = ¿Estás seguro de querer sobrescribir\neste punto de guardado? +overwrite = Sobrescribir +save.none = ¡No se ha encontrado ningún punto de guardado! +saveload = [accent]Guardando... +savefail = ¡No se ha podido guardar la partida! +save.delete.confirm = ¿Estás seguro de querer borrar este punto de guardado? +save.delete = Borrar +save.export = Exportar Punto de Guardado +save.import.invalid = [accent]¡Este punto de guardado es inválido! +save.import.fail = [crimson]La importación del punto de guardado ha fallado: error [accent]{0} +save.export.fail = [crimson]La exportación del punto de guardado ha fallado: error [accent]{0} +save.import = Importar Punto de Guardado +save.newslot = Nombre del Punto de Guardado: +save.rename = Renombrar +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. +empty = +on = Encendido +off = Apagado +save.autosave = Autoguardado: {0} +save.map = Mapa: {0} +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 +open = Abrir +cancel = Cancelar +openlink = Abrir Enlace +copylink = Copiar Enlace +back = Atrás +quit.confirm = ¿Estás seguro de querer salir de la partida? +changelog.title = Registro de Parches +changelog.loading = Consiguiendo el registro de parches... +changelog.error.android = [accent]¡Nota: el registro de parches a veces no funciona en Android 4.4 o inferior!\nEsto es por un error interno de Android. +changelog.error.ios = [accent]El registro de parches no está actualmente soportado para iOS. +changelog.error = [scarlet]¡Error consiguiendo el registro de parches!Comprueba tu conexión a Internet. +changelog.current = [yellow][[Versión actual] +changelog.latest = [accent][[Última version] +loading = [accent]Cargando... +saving = [accent]Guardando... +wave = [accent]Horda {0} +wave.waiting = Horda en {0} +waiting = Esperando... +waiting.players = Esperando jugadores... +wave.enemies = [LIGHT_GRAY]{0} Enemigos Restantes +wave.enemy = [LIGHT_GRAY]{0} Enemigo Restante +loadimage = Cargar Imagen +saveimage = Guardar Imagen +unknown = Desconocido +custom = Personalizado +builtin = Incorporado +map.delete.confirm = ¿Estás seguro de querer borrar este mapa? ¡Recuerda que está acción no puede sdeshacerse! +map.random = [accent]Mapa Aleatorio +map.nospawn = ¡Este mapa no tiene ningún núcleo en el cual pueda aparecer el jugador! Agrega un núcleo[ROYAL] blue[] al mapa con el editor. +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: +editor.mapinfo = Info del Mapa +editor.author = Autor: +editor.description = Descripción: +editor.name = Nombre: +editor.teams = Equipos +editor.elevation = Elevación +editor.errorimageload = Error cargando el archivo:\n[accent] {0} +editor.errorimagesave = Error guardando el archivo:\n[accent] {0} +editor.generate = Generar +editor.resize = Cambiar Tamaño +editor.loadmap = Cargar Mapa +editor.savemap = Guardar Mapa +editor.saved = ¡Guardado! +editor.save.noname = ¡Tu mapa no tiene un nombre! Pon uno en el menú 'Info del Mapa'. +editor.save.overwrite = ¡Tu mapa sobrescribe uno ya incorporado! Elige un nombre diferente en el menú 'Info del Mapa'. +editor.import.exists = [scarlet]¡No se ha podido importar:[] un mapa incorporado con el nombre '{0}' ya existe! +editor.import = Importar... +editor.importmap = Importar Mapa +editor.importmap.description = Importar un mapa ya existente +editor.importfile = Importar Archivo +editor.importfile.description = Importar un archivo externo del mapa +editor.importimage = Importar Imagen del Terreno +editor.importimage.description = Importar archivo externo de imagen del mapa +editor.export = Exportar... +editor.exportfile = Exportar Archivo +editor.exportfile.description = Exportar archivo del mapa +editor.exportimage = Exportar Imagen del Terreno +editor.exportimage.description = Exportar archivo de imagen del mapa +editor.loadimage = Importar Terreno +editor.saveimage = Exportar Terreno +editor.unsaved = [scarlet]¡Tienes cambios sin guardar![]\n¿Estás seguro de querer salir? +editor.resizemap = Cambiar Tamaño del Mapa +editor.mapname = Nombre del Mapa: +editor.overwrite = [accent]¡Advertencia!\nEsto sobrescribe un mapa ya existente. +editor.overwrite.confirm = [scarlet]¡Advertencia![] Un mapa con ese nombre ya existe. ¿Estás seguro de querer sobrescribirlo? +editor.selectmap = Selecciona un mapa para cargar: +width = Ancho: +height = Alto: +menu = Menu +play = Jugar +load = Cargar +save = Guardar +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0} ms +language.restart = Por favor reinicie el juego para que los cambios del lenguaje surjan efecto. +settings = Ajustes +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson]Ha fallado la conexión con el servidor: [accent]{0} +error.unreachable = Servidor inaccesible. +error.invalidaddress = Dirección inválida. +error.timedout = ¡Se acabó el tiempo!\n¡Asegúrate que el host ha hecho el port forwarding, y que la dirección es correcta! +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 +settings.controls = Controles +settings.game = Juego +settings.sound = Sonido +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.clearunlocks = Eliminar Desbloqueos +settings.clearall = Eliminar Todo +paused = Pausado +yes = Sí +no = No +info.title = [accent]Información +error.title = [crimson]Un error ha ocurrido. +error.crashtitle = Un error ha ocurrido. +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Información del Bloque +blocks.powercapacity = Capacidad de Energía +blocks.powershot = Energía/Disparo +blocks.targetsair = Apunta al Aire +blocks.itemspeed = Unidades Movidas +blocks.shootrange = Rango +blocks.size = Tamaño +blocks.liquidcapacity = Capacidad de Líquidos +blocks.maxitemssecond = Máximo de Objetos +blocks.powerrange = Rango de Energía +blocks.poweruse = Consumo de Energía +blocks.powerdamage = Energía/Daño +blocks.inputitemcapacity = Capacidad de Entrada de los Objetos +blocks.outputitemcapacity = Capacidad de Salida de los Objetos +blocks.itemcapacity = Capacidad de Objetos +blocks.basepowergeneration = Generación de energía base +blocks.powertransferspeed = Transferencia de Energía +blocks.craftspeed = Velocidad de Producción +blocks.inputliquid = Líquidos de Entrada +blocks.inputliquidaux = Líquido Auxiliar +blocks.inputitem = Objeto de Entrada +blocks.inputitems = Objetos de Entrada +blocks.outputitem = Objeto de Salida +blocks.drilltier = Taladrables +blocks.drillspeed = Velocidad Base del Taladro +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.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = Imprecisión +blocks.shots = Disparos +blocks.reload = Recarga +blocks.inputfuel = Combustible +blocks.fuelburntime = Tiempo de Quemado del Combustible +blocks.inputcapacity = Capacidad de entrada +blocks.outputcapacity = Capacidad de salida +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 +unit.seconds = segundos +unit.items = objetos +category.general = General +category.power = Energía +category.liquids = Líquidos +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 @@ -371,18 +379,22 @@ setting.mutemusic.name = Silenciar Musica setting.sfxvol.name = Volumen de los efectos de sonido setting.mutesound.name = Silenciar Sonido setting.crashreport.name = Enviar informes de fallos anónimos -text.keybind.title = Reasignar Teclas +keybind.title = Reasignar Teclas category.general.name = General category.view.name = Visión 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.pick.name = Pick Block keybind.break.name = Romper keybind.deselect.name = Deseleccionar keybind.shoot.name = Disparar @@ -401,30 +413,29 @@ keybind.chat_history_next.name = Historial de chat siguiente keybind.chat_scroll.name = Chat scroll keybind.drop_unit.name = drop unit keybind.zoom_minimap.name = Zoom minimapa -mode.text.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.help.title = Descripción de modos +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.descrption = 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 @@ -445,6 +456,10 @@ 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.oil.name = Petróleo @@ -478,24 +493,29 @@ mech.trident-ship.weapon = Bomb Bay mech.glaive-ship.name = Glaive mech.glaive-ship.description = Una nave pistolera grande y bien armada. Equipada con un repetidor incendiario. Buena aceleración y velocidad máxima. mech.glaive-ship.weapon = Flame Repeater -text.item.explosiveness = [LIGHT_GRAY]Explosividad: {0} -text.item.flammability = [LIGHT_GRAY]Inflamabilidad: {0} -text.item.radioactivity = [LIGHT_GRAY]Radioactividad: {0} -text.item.fluxiness = [LIGHT_GRAY]Poder como Fundente: {0} -text.unit.health = [LIGHT_GRAY]Vida: {0} -text.unit.speed = [LIGHT_GRAY]Velocidad: {0} -text.mech.weapon = [LIGHT_GRAY]Arma: {0} -text.mech.armor = [LIGHT_GRAY]Armadura: {0} -text.mech.itemcapacity = [LIGHT_GRAY]Capacidad de objetos: {0} -text.mech.minespeed = [LIGHT_GRAY]Velocidad de minado: {0} -text.mech.minepower = [LIGHT_GRAY]Potencia de minado: {0} -text.mech.ability = [LIGHT_GRAY]Hablidad: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]Capacidad Térmica: {0} -text.liquid.viscosity = [LIGHT_GRAY]Viscosidad: {0} -text.liquid.temperature = [LIGHT_GRAY]Temperatura: {0} +item.explosiveness = [LIGHT_GRAY]Explosividad: {0} +item.flammability = [LIGHT_GRAY]Inflamabilidad: {0} +item.radioactivity = [LIGHT_GRAY]Radioactividad: {0} +unit.health = [LIGHT_GRAY]Vida: {0} +unit.speed = [LIGHT_GRAY]Velocidad: {0} +mech.weapon = [LIGHT_GRAY]Arma: {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} +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.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.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = Suelo de Metal block.deepwater.name = Aguas profundas block.water.name = Agua @@ -514,8 +534,8 @@ block.blackrock.name = Roca negra block.icerock.name = Roca de hielo 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 @@ -548,17 +568,19 @@ 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 @@ -567,11 +589,11 @@ block.omega-mech-pad.name = Pad de mecanoide Omega block.tau-mech-pad.name = Pad de mecanoide Tau block.conduit.name = Conducto block.mechanical-pump.name = Bomba Mecánica -block.itemsource.name = Fuente de objetos -block.itemvoid.name = Vacío de objetos -block.liquidsource.name = Fuente de líquidos -block.powervoid.name = Vacío de energía -block.powerinfinite.name = Energía Infinita +block.item-source.name = Fuente de objetos +block.item-void.name = Vacío de objetos +block.liquid-source.name = Fuente de líquidos +block.power-void.name = Vacío de energía +block.power-source.name = Energía Infinita block.unloader.name = Descargador block.vault.name = Bóveda block.wave.name = Horda @@ -623,7 +645,7 @@ 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 team.blue.name = Azul team.red.name = Rojo team.orange.name = Naranja @@ -637,6 +659,7 @@ 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 +669,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. @@ -769,11 +796,11 @@ block.router.description = Acepta objetos de una dirección y deja objetos equit 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.itemsource.description = Da objetos infinitos. Solo en sandbox. -block.liquidsource.description = Da líquido infinito. Solo en sandbox. -block.itemvoid.description = Destruye cuanquier objeto que va a él sin necesitar energía. Solo en sandbox. -block.powerinfinite.description = Da energía infinita. Solo en sandbox. -block.powervoid.description = Elimina toda la energía que se le da. Solo en sandbox. +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. diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index f8351c8f7b..436c82e65b 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -1,351 +1,359 @@ -text.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!) -text.credits = Crédits -text.discord = Rejoignez le discord de Mindustry -text.link.discord.description = Le discord officiel de mindustry -text.link.github.description = Code source du jeu -text.link.dev-builds.description = Versions instables du jeu -text.link.trello.description = Trello officiel pour les futurs ajouts . -text.link.itch.io.description = page itch.io avec le lien du téléchargement pour PC et la version web . -text.link.google-play.description = listing par le store google play -text.link.wiki.description = wiki officiel de mindustry . -text.linkfail = Erreur lors de l'ouverture du lien !\nL'URL a été copié avec succès. -text.gameover = Partie terminée. -text.gameover.pvp = L'équipe [accent] {0}[] a gagnée ! -text.sector.gameover = Ce secteur a été perdu. Réessayer? -text.sector.retry = Réessayer -text.highscore = [YELLOW]Nouveau meilleur score! -text.wave.lasted = Vous avez survécu jusqu'à la vague [accent]{0}[]. -text.level.highscore = Meilleur score: [accent]{0} -text.level.delete.title = Confirmer -text.map.delete = Êtes-vous sûr de supprimer cette carte"[accent]{0}[]"? -text.level.select = Sélection de niveau -text.level.mode = Mode de jeu : -text.construction.desktop = Pour désélectionner un bloc ou arrêter de construire, appuyer sur [accent]espace[]. -text.construction.title = Guide de construction des blocs -text.construction = Vous venez de sélectionner le mode [accent]construction de blocs[].\n\nPour commencez à placer des blocs, appuyez simplement sur un emplacement valide proche de votre vaisseau.\nUne fois que vous avez sélectionné quelques emplacements, Appuyez sur le bouton valider pour confirmer, et votre vaisseau commencera à construire.\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. -text.deconstruction.title = Block Deconstruction Guide -text.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. -text.showagain = Ne pas montrer la prochaine fois -text.coreattack = [scarlet] -text.unlocks = Débloqué -text.savegame = Sauvegarder la partie -text.loadgame = Charger la partie -text.joingame = Rejoindre une partie -text.addplayers = Ajouter/Enlever des joueurs -text.customgame = Partie personnalisée -text.sectors = Secteurs -text.sector = Secteur: [LIGHT_GRAY]{0} -text.sector.time = Temps: [LIGHT_GRAY]{0} -text.sector.deploy = Se déployer -text.sector.abandon = Abandonner -text.sector.abandon.confirm = Êtes-vous sûr d'abandonner ce secteur ?\nCe choix ne peut être annulé! -text.sector.resume = Reprendre -text.sector.locked = [scarlet][[Incomplet] -text.sector.unexplored = [accent][[Inexploré] -text.missions = Missions:[LIGHT_GRAY] {0} -text.mission = Mission:[LIGHT_GRAY] {0} -text.mission.main = Main Mission:[LIGHT_GRAY] {0} -text.mission.info = Infos sur la Mission -text.mission.complete = Mission terminée! -text.mission.complete.body = Le secteur {0},{1} a été conquis. -text.mission.wave = Survivez à[accent] {0}/{1} []vague\nLa vague commence dans {2} -text.mission.wave.enemies = Survivez à[accent] {0}/{1} []vagues\n{2} Ennemis -text.mission.wave.enemy = Survivez à[accent] {0}/{1} []vagues\n{2} Ennemi -text.mission.wave.menu = Survivez à[accent] {0} []vagues -text.mission.battle = Détruisez la base ennemie -text.mission.resource.menu = Obtenez {0} x{1} -text.mission.resource = Obtenez {0}:\n[accent]{1}/{2}[] -text.mission.block = Créez {0} -text.mission.unit = Créez {0} unités -text.mission.command = Envoyer une commande à {0} unités -text.mission.linknode = Reliez un transmetteur -text.mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -text.mission.mech = Équiper ce mécha[accent] {0}[] -text.mission.create = Créez[accent] {0}[] -text.none = -text.close = Fermer -text.quit = Quitter -text.maps = Cartes -text.continue = Continuer -text.nextmission = Prochaine mission -text.maps.none = [LIGHT_GRAY]Aucune carte trouvée! -text.about.button = À propos -text.name = Nom: -text.filename = File Name: -text.unlocked = Nouveau bloc débloqué! -text.unlocked.plural = Nouveaux blocs débloqués! -text.players = {0} joueurs en ligne -text.players.single = {0} joueur en ligne -text.server.closing = [accent]Fermeture du serveur... -text.server.kicked.kick = Vous avez été expulsé du serveur! -text.server.kicked.serverClose = Server closed. -text.server.kicked.sectorComplete = Secteur terminé. -text.server.kicked.sectorComplete.text = Votre mission est complète .\nLe serveur va maintenant aller au prochain secteur . -text.server.kicked.clientOutdated = Client dépassé! Mettez à jour votre jeu! -text.server.kicked.serverOutdated = Serveur dépassé! Demandez à l'hôte de le mettre à jour! -text.server.kicked.banned = Vous êtes banni sur ce serveur. -text.server.kicked.recentKick = Vous avez été expulsé récemment.\nAttendez avant de vous connecter à nouveau. -text.server.kicked.nameInUse = Il y a déjà quelqu'un avec ce nom\nsur ce serveur. -text.server.kicked.nameEmpty = Votre nom doit contenir au moins une lettre ou un chiffre. -text.server.kicked.idInUse = Vous êtes déjà sur ce serveur ! Se connecter avec deux comptes n'est pas permis ! -text.server.kicked.customClient = Ce serveur ne supporte pas les versions personnalisées (Custom builds). Téléchargez une version officielle. -text.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. -text.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. -text.hostserver = Héberger une partie -text.hostserver.mobile = Héberger\nune partie -text.host = Héberger -text.hosting = [accent]Ouverture du serveur... -text.hosts.refresh = Actualiser -text.hosts.discovering = Découverte de jeux en LAN -text.server.refreshing = Actualisation du serveur -text.hosts.none = [lightgray]Aucun jeu en LAN trouvé! -text.host.invalid = [scarlet]Impossible de se connecter à l'hôte. -text.trace = Suivre le joueur -text.trace.playername = Nom du joueur : [accent]{0} -text.trace.ip = IP: [accent]{0} -text.trace.id = ID Unique : [accent]{0} -text.trace.android = Client Android : [accent]{0} -text.trace.modclient = Client personnalisé: [accent]{0} -text.trace.totalblocksbroken = Total de blocs détruits: [accent]{0} -text.trace.structureblocksbroken = Structure de blocs détruites : [accent]{0} -text.trace.lastblockbroken = Dernier bloc détruit: [accent]{0} -text.trace.totalblocksplaced = Total de blocs placés: [accent]{0} -text.trace.lastblockplaced = Dernier bloc placé: [accent]{0} -text.invalidid = text.invalidid=ID du client invalide! Soumettre un rapport d'erreur -text.server.bans = Bannis -text.server.bans.none = Aucun joueur banni trouvé! -text.server.admins = Administrateurs -text.server.admins.none = Pas d'administrateurs trouvés! -text.server.add = Ajouter un serveur -text.server.delete = Êtes-vous sûr de supprimer ce serveur ? -text.server.hostname = Héberger: {0} -text.server.edit = Modifier le serveur -text.server.outdated = [crimson]Serveur obsolète![] -text.server.outdated.client = [crimson]Client obsolète![] -text.server.version = [lightgray]Version: {0} {1} -text.server.custombuild = [yellow]Version personnalisée -text.confirmban = Êtes-vous sûr de bannir ce joueur? -text.confirmkick = Êtes-vous sûr d'expulser ce joueur? -text.confirmunban = Êtes-vous sûr de réintégrer ce joueur ? -text.confirmadmin = Êtes-vous sûr de faire de ce joueur un administrateur? -text.confirmunadmin = Êtes-vous sûr d'enlever le statut d'administrateur à ce joueur? -text.joingame.title = Rejoindre une partie -text.joingame.ip = IP: -text.disconnect = Déconnecté. -text.disconnect.data = Les données du monde n'ont pas pu être chargées ! -text.connecting = [accent]Connexion... -text.connecting.data = [accent]Chargement des données du monde... -text.server.port = Port: -text.server.addressinuse = Addresse déjà utilisée! -text.server.invalidport = numéro de port invalide! -text.server.error = [crimson]Erreur d'hébergement: [accent]{0} -text.save.old = Cette sayvegarde provient d'une ancienne version du jeu, et ne peut plus être utilisée.\n\n[LIGHT_GRAY]la compabilité des anciennes sauvegardes sera bientôt ajoutée dans la version 4.0 stable. -text.save.new = Nouvelle sauvegarde -text.save.overwrite = Êtes-vous sûr d'écraser\ncette sauvegarde ? -text.overwrite = Écraser -text.save.none = Aucune sauvegarde trouvée ! -text.saveload = [accent]Sauvegarde... -text.savefail = Échec de la sauvegarde! -text.save.delete.confirm = Êtes-vous sûr de supprimer cette sauvegarde? -text.save.delete = supprimer -text.save.export = Exporter une\nSauvegarde -text.save.import.invalid = [accent]Cette sauvegarde est invalide! -text.save.import.fail = [crimson]L'importation de la sauvegarde\na échoué: [accent]{0} -text.save.export.fail = [crimson]L'exportation de la sauvegarde\na échoué [accent]{0} -text.save.import = Importer une sauvegarde -text.save.newslot = Nom de la sauvegarde: -text.save.rename = Renommer -text.save.rename.text = Nouveau nom: -text.selectslot = Sélectionner une sauvegarde. -text.slot = [accent]Emplacement {0} -text.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. -text.sector.corrupted = [accent]Une sauvegarde pour ce secteur a été trouvé, mais son chargement a raté.\nUne nouvelle sauvegarde a été créé. -text.empty = -text.on = On -text.off = Off -text.save.autosave = Sauvegarde automatique: {0} -text.save.map = Carte: {0} -text.save.wave = Vague {0} -text.save.difficulty = Difficulté: {0} -text.save.date = Dernière sauvegarde: {0} -text.save.playtime = Temps de jeu: {0} -text.confirm = Confirmer -text.delete = Supprimer -text.ok = OK -text.open = Ouverture -text.cancel = Annuler -text.openlink = Ouvrir le lien -text.copylink = Copier le lien -text.back = Retour -text.quit.confirm = Êtes-vous sûr de partir? -text.changelog.title = Notes de mise à jour -text.changelog.loading = Récupération des notes de mise à jour... -text.changelog.error.android = [accent]Remarquez que les notes de mise à jour peuvent ne pas marcher sur Android 4.4 et inférieur!\nC'est dû à un bug interne d'Android . -text.changelog.error.ios = [accent]Les notes de mise à jour ne sont pas suppporté sur iOS. -text.changelog.error = [scarlet]Erreur lors de la récupération des notes de mises à jour!\nVérifiez votre connexion internet. -text.changelog.current = [yellow][[Version actuelle] -text.changelog.latest = [accent][[Dernière version] -text.loading = [accent]Chargement... -text.saving = [accent]Sauvegarde... -text.wave = [accent]Vague {0} -text.wave.waiting = [LIGHT_GRAY]Vague dans {0} -text.waiting = [LIGHT_GRAY]En attente... -text.waiting.players = En attente de joueurs... -text.wave.enemies = [LIGHT_GRAY]{0} Ennemis restants -text.wave.enemy = [LIGHT_GRAY]{0} Ennemi restant -text.loadimage = Charger l'image -text.saveimage = Sauvegarder l'image -text.unknown = Inconnu -text.custom = Personnalisé -text.builtin = Pré-fait -text.map.delete.confirm = Êtes-vous sûr de supprimer cette carte? Cette action ne peut pas être défaite! -text.map.random = [accent]Carte aléatoire -text.map.nospawn = Cette carte n'a pas de base pour que le joueur y apparaisse! Ajouter une [ROYAL]base bleue[] sur cette carte dans l'éditeur. -text.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. -text.map.invalid = Erreur lors du chargement de la carte: carte corrompue ou invalide. -text.editor.brush = Pinceau -text.editor.slope = \\ -text.editor.openin = Ouvrir dans l'éditeur -text.editor.oregen = Génération de minerais -text.editor.oregen.info = Génération de minerais: -text.editor.mapinfo = Info de la carte -text.editor.author = Auteur: -text.editor.description = Description: -text.editor.name = Nom: -text.editor.teams = Équipe -text.editor.elevation = Élevation -text.editor.errorimageload = Erreur lors du chargement du fichier:\n[accent]{0} -text.editor.errorimagesave = Erreur lors de la sauvegarde du fichier:\n[accent]{0} -text.editor.generate = Générer -text.editor.resize = Redimensionner -text.editor.loadmap = Charger une carte -text.editor.savemap = Sauvegarder une carte -text.editor.saved = Sauvegardé! -text.editor.save.noname = Votre carte n'a pas de nom ! Définissez-en un sur le menu 'info de la carte'. -text.editor.save.overwrite = Votre carte réécrit une carte préfaite! Choisissez un nom différent dans le menu 'info de la carte' . -text.editor.import.exists = [scarlet]Importation impossible :[] Une carte préfaite nommé '{0}' existe déjà! -text.editor.import = Importation... -text.editor.importmap = Importer une carte -text.editor.importmap.description = Importer une carte existante -text.editor.importfile = Importer un fichier -text.editor.importfile.description = Importer un fichier de carte extérieur . -text.editor.importimage = Importer l'image du terrain -text.editor.importimage.description = Importer une image de la carte extérieure -text.editor.export = Exporter... -text.editor.exportfile = Exporter un fichier -text.editor.exportfile.description = Exporter une fichier de carte -text.editor.exportimage = Exporter l'image du terrain -text.editor.exportimage.description = Exporter une image de la carte -text.editor.loadimage = Importer le terrain -text.editor.saveimage = Exportr le terrain -text.editor.unsaved = [scarlet]Vous avez des changements non sauvegardés ![]\nÊtes-vous sûr de partir -text.editor.resizemap = Redimensionner\nla carte -text.editor.mapname = Nom de la carte²: -text.editor.overwrite = [accent]Attention !\nCeci réécrit une carte existante . -text.editor.overwrite.confirm = [scarlet]Attention ![] Une carte avec ce nom existe déjà. Êtes-vous sûr de vouloir la réécrire? -text.editor.selectmap = Séléctionnez une carte: -text.width = Largeur: -text.height = Hauteur: -text.menu = Menu -text.play = Jouer -text.load = Charger -text.save = Sauvegarder -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Ping: {0}ms -text.language.restart = Veuillez redémarrez votre jeu pour le changement de langage prenne effet. -text.settings = Paramètres -text.tutorial = Tutoriel -text.editor = Éditeur -text.mapeditor = Éditeur de carte -text.donate = Faire un\ndon -text.connectfail = [crimson]Échec de la connexion au serveur : [accent]{0} -text.error.unreachable = Server injoignable. -text.error.invalidaddress = Adresse invalide. -text.error.timedout = Délai de connexion dépassé!\nAssurez-vous que l'hôte a autorisé l'accès au port, et que l'adresse soit correcte! -text.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 ! -text.error.alreadyconnected = Déjà connecté. -text.error.mapnotfound = Fichier de la carte introuvable! -text.error.any = Erreur réseau inconnue. -text.settings.language = Langage -text.settings.reset = Valeur par défaut. -text.settings.rebind = Réatttribuer -text.settings.controls = Contrôles -text.settings.game = Jeu -text.settings.sound = Son -text.settings.graphics = Graphiques -text.settings.cleardata = Effacer les données du jeu... -text.settings.clear.confirm = Êtes-vous sûr d'effacer ces données ?\nCe qui est fait ne peut être défait ! -text.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. -text.settings.clearsectors = Effacer les données des secteurs -text.settings.clearunlocks = Effacer les déblocages -text.settings.clearall = Tout effacer -text.paused = En pause -text.yes = Oui -text.no = Non -text.info.title = Info -text.error.title = [crimson]Une erreur s'est produite -text.error.crashtitle = Une erreur s'est produite -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = Info sur le bloc -text.blocks.powercapacity = capacité d'énergie -text.blocks.powershot = Énergie/Tir -text.blocks.targetsair = Cible les unités aériennes -text.blocks.itemspeed = Objets déplacés -text.blocks.shootrange = Portée -text.blocks.size = Taille -text.blocks.liquidcapacity = Capacité en liquide -text.blocks.maxitemssecond = Production maximale -text.blocks.powerrange = Distance de transmission -text.blocks.poweruse = Énergie utilisée -text.blocks.powerdamage = Énergie/Dégâts -text.blocks.inputitemcapacity = Capacité d'entrée -text.blocks.outputitemcapacity = Capacité de sortie -text.blocks.itemcapacity = Stockage -text.blocks.basepowergeneration = Base Power Generation -text.blocks.powertransferspeed = Vitesse de transfert d'énergie -text.blocks.craftspeed = Vitesse de production -text.blocks.inputliquid = Liquide requis -text.blocks.inputliquidaux = Liquide optionnel -text.blocks.inputitem = Input Item -text.blocks.inputitems = objets utilisés -text.blocks.outputitem = Objet produit -text.blocks.drilltier = Forable -text.blocks.drillspeed = Vitesse de forage de base -text.blocks.liquidoutput = Liquide en sortie -text.blocks.liquidoutputspeed = Vitesse de production de liquide -text.blocks.liquiduse = Quantité de liquide utilisée -text.blocks.coolant = Liquide de refroidissement -text.blocks.coolantuse = Quantité de liquide de refroidissement utilisée -text.blocks.inputliquidfuel = Carburant liquide -text.blocks.liquidfueluse = Quantité de carburant liquide utilisé -text.blocks.boostitem = Boost Item -text.blocks.boostliquid = Boost Liquid -text.blocks.health = Santé -text.blocks.inaccuracy = Précision -text.blocks.shots = Tir -text.blocks.reload = Tirs/Seconde -text.blocks.inputfuel = Carburant -text.blocks.fuelburntime = Durée du carburant -text.blocks.inputcapacity = Capacité d'entrée -text.blocks.outputcapacity = Capacité de production -text.unit.blocks = blocs -text.unit.powersecond = Énergie/seconde -text.unit.liquidsecond = Liquides/seconde -text.unit.itemssecond = Objets/seconde -text.unit.pixelssecond = Pixels/seconde -text.unit.liquidunits = Unité de liquide -text.unit.powerunits = Unité d'énergie -text.unit.degrees = degrés -text.unit.seconds = secondes -text.unit.items = Objets -text.category.general = Général -text.category.power = Énergie -text.category.liquids = Liquides -text.category.items = Objets -text.category.crafting = Fabrication -text.category.shooting = Défense -text.category.optional = Optional Enhancements +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 +link.dev-builds.description = Versions instables du jeu +link.trello.description = Trello officiel pour les futurs ajouts . +link.itch.io.description = Page itch.io avec le lien du téléchargement pour PC et la version web . +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 ! +highscore = [YELLOW]Nouveau meilleur score! +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: +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[]. +construction.title = Guide de construction des blocs +construction = Vous venez de sélectionner le mode [accent]construction de blocs[].\n\nPour commencez à placer des blocs, appuyez simplement sur un emplacement valide proche de votre vaisseau.\nUne fois que vous avez sélectionné quelques emplacements, Appuyez sur le bouton valider pour confirmer, et votre vaisseau commencera à construire.\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. +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] +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 +newgame = New Game +none = +close = Fermer +quit = Quitter +maps = Cartes +continue = Continuer +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é! +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.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. +server.kicked.recentKick = Vous avez été expulsé récemment.\nAttendez avant de vous connecter à nouveau. +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 +hostserver.mobile = Héberger\nune partie +host = Héberger +hosting = [accent]Ouverture du serveur... +hosts.refresh = Actualiser +hosts.discovering = Découverte de jeux en LAN +server.refreshing = Actualisation du serveur +hosts.none = [lightgray]Aucun jeu en LAN trouvé! +host.invalid = [scarlet]Impossible de se connecter à l'hôte. +trace = Suivre le joueur +trace.playername = Nom du joueur : [accent]{0} +trace.ip = IP: [accent]{0} +trace.id = ID Unique : [accent]{0} +trace.android = Client Android : [accent]{0} +trace.modclient = Client personnalisé: [accent]{0} +trace.totalblocksbroken = Total de blocs détruits: [accent]{0} +trace.structureblocksbroken = Structure de blocs détruites : [accent]{0} +trace.lastblockbroken = Dernier bloc détruit: [accent]{0} +trace.totalblocksplaced = Total de blocs placés: [accent]{0} +trace.lastblockplaced = Dernier bloc placé: [accent]{0} +invalidid = invalidid=ID du client invalide! Soumettre un rapport d'erreur +server.bans = Bannis +server.bans.none = Aucun joueur banni trouvé! +server.admins = Administrateurs +server.admins.none = Pas d'administrateurs trouvés! +server.add = Ajouter un serveur +server.delete = Êtes-vous sûr de supprimer ce serveur ? +server.hostname = Héberger: {0} +server.edit = Modifier le serveur +server.outdated = [crimson]Serveur obsolète![] +server.outdated.client = [crimson]Client obsolète![] +server.version = [lightgray]Version: {0} {1} +server.custombuild = [yellow]Version personnalisée +confirmban = Êtes-vous sûr de bannir ce joueur? +confirmkick = Êtes-vous sûr d'expulser ce joueur? +confirmunban = Êtes-vous sûr de réintégrer ce joueur ? +confirmadmin = Êtes-vous sûr de faire de ce joueur un administrateur? +confirmunadmin = Êtes-vous sûr d'enlever le statut d'administrateur à ce joueur? +joingame.title = Rejoindre une partie +joingame.ip = IP: +disconnect = Déconnecté. +disconnect.data = Les données du monde n'ont pas pu être chargées ! +connecting = [accent]Connexion... +connecting.data = [accent]Chargement des données du monde... +server.port = Port: +server.addressinuse = Addresse déjà utilisée! +server.invalidport = numéro de port invalide! +server.error = [crimson]Erreur d'hébergement: [accent]{0} +save.old = Cette sayvegarde provient d'une ancienne version du jeu, et ne peut plus être utilisée.\n\n[LIGHT_GRAY]la compabilité des anciennes sauvegardes sera bientôt ajoutée dans la version 4.0 stable. +save.new = Nouvelle sauvegarde +save.overwrite = Êtes-vous sûr d'écraser\ncette sauvegarde ? +overwrite = Écraser +save.none = Aucune sauvegarde trouvée ! +saveload = [accent]Sauvegarde... +savefail = Échec de la sauvegarde! +save.delete.confirm = Êtes-vous sûr de supprimer cette sauvegarde? +save.delete = supprimer +save.export = Exporter une\nSauvegarde +save.import.invalid = [accent]Cette sauvegarde est invalide! +save.import.fail = [crimson]L'importation de la sauvegarde\na échoué: [accent]{0} +save.export.fail = [crimson]L'exportation de la sauvegarde\na échoué [accent]{0} +save.import = Importer une sauvegarde +save.newslot = Nom de la sauvegarde: +save.rename = Renommer +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. +empty = +on = On +off = Off +save.autosave = Sauvegarde automatique: {0} +save.map = Carte: {0} +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 +open = Ouverture +cancel = Annuler +openlink = Ouvrir le lien +copylink = Copier le lien +back = Retour +quit.confirm = Êtes-vous sûr de partir? +changelog.title = Notes de mise à jour +changelog.loading = Récupération des notes de mise à jour... +changelog.error.android = [accent]Remarquez que les notes de mise à jour peuvent ne pas marcher sur Android 4.4 et inférieur!\nC'est dû à un bug interne d'Android . +changelog.error.ios = [accent]Les notes de mise à jour ne sont pas suppporté sur iOS. +changelog.error = [scarlet]Erreur lors de la récupération des notes de mises à jour!\nVérifiez votre connexion internet. +changelog.current = [yellow][[Version actuelle] +changelog.latest = [accent][[Dernière version] +loading = [accent]Chargement... +saving = [accent]Sauvegarde... +wave = [accent]Vague {0} +wave.waiting = [LIGHT_GRAY]Vague dans {0} +waiting = [LIGHT_GRAY]En attente... +waiting.players = En attente de joueurs... +wave.enemies = [LIGHT_GRAY]{0} Ennemis restants +wave.enemy = [LIGHT_GRAY]{0} Ennemi restant +loadimage = Charger l'image +saveimage = Sauvegarder l'image +unknown = Inconnu +custom = Personnalisé +builtin = Pré-fait +map.delete.confirm = Êtes-vous sûr de supprimer cette carte? Cette action ne peut pas être défaite! +map.random = [accent]Carte aléatoire +map.nospawn = Cette carte n'a pas de base pour que le joueur y apparaisse! Ajouter une [ROYAL]base bleue[] sur cette carte dans l'éditeur. +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: +editor.mapinfo = Infos sur la carte +editor.author = Auteur: +editor.description = Description: +editor.name = Nom: +editor.teams = Équipe +editor.elevation = Élevation +editor.errorimageload = Erreur lors du chargement du fichier:\n[accent]{0} +editor.errorimagesave = Erreur lors de la sauvegarde du fichier:\n[accent]{0} +editor.generate = Générer +editor.resize = Redimensionner +editor.loadmap = Charger une carte +editor.savemap = Sauvegarder une carte +editor.saved = Sauvegardé! +editor.save.noname = Votre carte n'a pas de nom ! Définissez-en un sur le menu 'info de la carte'. +editor.save.overwrite = Votre carte réécrit une carte préfaite! Choisissez un nom différent dans le menu 'info de la carte' . +editor.import.exists = [scarlet]Importation impossible :[] Une carte préfaite nommé '{0}' existe déjà! +editor.import = Importation... +editor.importmap = Importer une carte +editor.importmap.description = Importer une carte existante +editor.importfile = Importer un fichier +editor.importfile.description = Importer un fichier de carte extérieur . +editor.importimage = Importer l'image du terrain +editor.importimage.description = Importer une image de la carte extérieure +editor.export = Exporter... +editor.exportfile = Exporter un fichier +editor.exportfile.description = Exporter une fichier de carte +editor.exportimage = Exporter l'image du terrain +editor.exportimage.description = Exporter une image de la carte +editor.loadimage = Importer le terrain +editor.saveimage = Exportr le terrain +editor.unsaved = [scarlet]Vous avez des changements non sauvegardés ![]\nÊtes-vous sûr de partir +editor.resizemap = Redimensionner\nla carte +editor.mapname = Nom de la carte²: +editor.overwrite = [accent]Attention !\nCeci réécrit une carte existante . +editor.overwrite.confirm = [scarlet]Attention ![] Une carte avec ce nom existe déjà. Êtes-vous sûr de vouloir la réécrire? +editor.selectmap = Séléctionnez une carte: +width = Largeur: +height = Hauteur: +menu = Menu +play = Jouer +load = Charger +save = Sauvegarder +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0}ms +language.restart = Veuillez redémarrez votre jeu pour le changement de langage prenne effet. +settings = Paramètres +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson]Échec de la connexion au serveur : [accent]{0} +error.unreachable = Server injoignable. +error.invalidaddress = Adresse invalide. +error.timedout = Délai de connexion dépassé!\nAssurez-vous que l'hôte a autorisé l'accès au port, et que l'adresse soit correcte! +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 +settings.controls = Contrôles +settings.game = Jeu +settings.sound = Son +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.clearunlocks = Effacer les déblocages +settings.clearall = Tout effacer +paused = En pause +yes = Oui +no = Non +info.title = Info +error.title = [crimson]Une erreur s'est produite +error.crashtitle = Une erreur s'est produite +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Info sur le bloc +blocks.powercapacity = capacité d'énergie +blocks.powershot = Énergie/Tir +blocks.targetsair = Cible les unités aériennes +blocks.itemspeed = Objets déplacés +blocks.shootrange = Portée +blocks.size = Taille +blocks.liquidcapacity = Capacité en liquide +blocks.maxitemssecond = Production maximale +blocks.powerrange = Distance de transmission +blocks.poweruse = Énergie utilisée +blocks.powerdamage = Énergie/Dégâts +blocks.inputitemcapacity = Capacité d'entrée +blocks.outputitemcapacity = Capacité de sortie +blocks.itemcapacity = Stockage +blocks.basepowergeneration = Generation d'énergie minimale +blocks.powertransferspeed = Vitesse de transfert d'énergie +blocks.craftspeed = Vitesse de production +blocks.inputliquid = Liquide requis +blocks.inputliquidaux = Liquide optionnel +blocks.inputitem = Objets en entrée +blocks.inputitems = Objets utilisés +blocks.outputitem = Objet produit +blocks.drilltier = Forable +blocks.drillspeed = Vitesse de forage de base +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.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = Précision +blocks.shots = Tir +blocks.reload = Tirs/Seconde +blocks.inputfuel = Carburant +blocks.fuelburntime = Durée du carburant +blocks.inputcapacity = Capacité d'entrée +blocks.outputcapacity = Capacité de production +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 +unit.seconds = secondes +unit.items = Objets +category.general = Général +category.power = Énergie +category.liquids = Liquides +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 @@ -356,7 +364,7 @@ setting.difficulty.normal = normal setting.difficulty.hard = difficile setting.difficulty.insane = Extreme setting.difficulty.name = Difficulté: -setting.screenshake.name = Tremblement d'écran +setting.screenshake.name = Tremblement de l'écran setting.effects.name = Montrer les effets setting.sensitivity.name = Sensibilité de la manette setting.saveinterval.name = Intervalle des sauvegardes auto @@ -371,18 +379,22 @@ setting.mutemusic.name = Couper la musique setting.sfxvol.name = Volume des SFX setting.mutesound.name = Couper les SFX setting.crashreport.name = Send Anonymous Crash Reports -text.keybind.title = Paramétrer les touches +keybind.title = Paramétrer les touches category.general.name = General category.view.name = Voir 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.pick.name = Pick Block keybind.break.name = Pause keybind.deselect.name = Déselectionner keybind.shoot.name = tirer @@ -401,41 +413,40 @@ keybind.chat_history_next.name = descendre l'historique du chat keybind.chat_scroll.name = Chat scroll keybind.drop_unit.name = drop unit keybind.zoom_minimap.name = Zoom minimap -mode.text.help.title = Description des modes de jeu -mode.waves.name = Vagues -mode.waves.description = le mode de jeu normal. Ressource limitée et vagues d'ennemis. +mode.help.title = Description des modes de jeu +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 = Ressource limitée et pas de timer pour les vagues. +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.descrption = 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.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.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 +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 -item.thorium.description = Un métal dense, et radioactif utilisé comme support structurel et comme carburant nucléaire. +item.thorium.description = Un métal dense et radioactif utilisé comme support structurel et comme carburant nucléaire. item.silicon.name = Silicone -item.silicon.description = Un matériau semi-conducteur extrêmement utile, avec des utilisations dans les panneaux solaires et beaucoup d'autre composants électroniques complexes. +item.silicon.description = Un matériau semi-conducteur extrêmement utile, avec des utilisations dans les panneaux solaires et dans beaucoup d'autre composants électroniques complexes. item.plastanium.name = Plastanium item.plastanium.description = Un matériau léger et docile utilisé dans l'aviation avancée et dans les munitions à fragmentation. 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.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. @@ -445,77 +456,86 @@ 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.oil.name = Pétrole -liquid.cryofluid.name = liquide cryogénique +liquid.cryofluid.name = Liquide cryogénique mech.alpha-mech.name = Alpha -mech.alpha-mech.weapon = fusil automatique +mech.alpha-mech.weapon = Fusil automatique mech.alpha-mech.ability = Essaim de drone -mech.alpha-mech.description = Le mécha standard.A une vitesse et des dégâts décents; Il peut aussi créer jusqu'à 3 drones pour des faire des dégâts supplémentaires. +mech.alpha-mech.description = Le mécha standard. À une vitesse et des dégâts décents; Il peut aussi créer jusqu'à 3 drones pour infliger des dégâts supplémentaires. mech.delta-mech.name = Delta mech.delta-mech.weapon = Arc électrique mech.delta-mech.ability = Décharge -mech.delta-mech.description = Un mécha rapide avec une armure légère fait pour des tactiques de harcèlements. Il fait par contre peu de dégâts au structures, néanmoins il peut tuer de grand groupes d'ennemis très rapidement avec ses arcs électriques . +mech.delta-mech.description = Un mécha rapide, avec une armure légère, fait pour des tactiques de harcèlements. Il inflige, par contre, peu de dégâts aux structures, néanmoins il peut tuer de grand groupes d'ennemis très rapidement avec ses arcs électriques. mech.tau-mech.name = Tau mech.tau-mech.weapon = Laser restructurant -mech.tau-mech.ability = explosion réparante -mech.tau-mech.description = Un mécha de support . Soigne les blocs alliés en tirant dessus. Il peut aussi éteindre les feux et soigner ses alliés en zone avec sa Compétence . +mech.tau-mech.ability = Explosion réparante +mech.tau-mech.description = Un mécha de support. Soigne les blocs alliés en tirant dessus. Il peut aussi éteindre les feux et soigner ses alliés en zone avec sa compétence. mech.omega-mech.name = Omega mech.omega-mech.weapon = Essaim de missiles auto-guidés mech.omega-mech.ability = Armure -mech.omega-mech.description = Un mécha cuirassé et large fait pour les assauts frontaux . Sa Compétence "Armure" lui permet de bloquer 90% des dégâts. +mech.omega-mech.description = Un mécha cuirassé et large fait pour les assauts frontaux. Sa compétence "Armure" lui permet de bloquer 90% des dégâts. mech.dart-ship.name = Dard -mech.dart-ship.weapon = pistolet automatique -mech.dart-ship.description = Le vaisseau standard. Raisonnablement rapide et léger , Il a néanmoins peu d'attaque et une faible vitesse de minage. +mech.dart-ship.weapon = Pistolet automatique +mech.dart-ship.description = Le vaisseau standard. Raisonnablement rapide et léger. Il a néanmoins peu d'attaque et une faible vitesse de minage. mech.javelin-ship.name = Javelin -mech.javelin-ship.description = Un vaisseau qui bien que lent au départ peut accélerer pour atteindre de très grandes vitesses et voler jusqu'au avant-postes ennemis, faisant d'énormes dégâts avec ses arc électriques obtenus à vitesse maximum et ses missiles. +mech.javelin-ship.description = Un vaisseau qui, bien que lent au départ, peut accélerer pour atteindre de très grandes vitesses et voler jusqu'aux avant-postes ennemis, faisant d'énormes dégâts avec ses arc électriques obtenus à vitesse maximum et ses missiles. mech.javelin-ship.weapon = Missiles explosifs autoguidés mech.javelin-ship.ability = Décharge de propulseur mech.trident-ship.name = Trident mech.trident-ship.description = Un bombardier lourd raisonnablement cuirassé. -mech.trident-ship.weapon = Largage de bombe +mech.trident-ship.weapon = Largage de bombes mech.glaive-ship.name = Glaive -mech.glaive-ship.description = Un grand vaisseau de combat cuirassé . Equipé avec un fusil automatique à munitions incendiaires . Il a aussi une bonne accéleration ainsi qu'une bonne Vitesse maximale. +mech.glaive-ship.description = Un grand vaisseau de combat cuirassé. Equipé avec un fusil automatique à munitions incendiaires. Il a aussi une bonne accéleration ainsi qu'une bonne vitesse maximale. mech.glaive-ship.weapon = Fusil automatique incendiaire -text.item.explosiveness = [LIGHT_GRAY]Explosivité: {0} -text.item.flammability = [LIGHT_GRAY]Inflammabilité: {0} -text.item.radioactivity = [LIGHT_GRAY]Radioactivité: {0} -text.item.fluxiness = [LIGHT_GRAY]Flux de Puissance: {0} -text.unit.health = [LIGHT_GRAY]Health: {0} -text.unit.speed = [LIGHT_GRAY]Speed: {0} -text.mech.weapon = [LIGHT_GRAY]Arme: {0} -text.mech.armor = [LIGHT_GRAY]Armure: {0} -text.mech.itemcapacity = [LIGHT_GRAY]Capacité de stockage: {0} -text.mech.minespeed = [LIGHT_GRAY]Vitesse de minage: {0} -text.mech.minepower = [LIGHT_GRAY]Puissance du minage: {0} -text.mech.ability = [LIGHT_GRAY]Compétence: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]Capacité Thermique: {0} -text.liquid.viscosity = [LIGHT_GRAY]Viscosité: {0} -text.liquid.temperature = [LIGHT_GRAY]Température: {0} -block.constructing = {0}\n[LIGHT_GRAY](Constructing) -block.spawn.name = Générateur d'ennemi -block.core.name = Base +item.explosiveness = [LIGHT_GRAY]Explosivité: {0} +item.flammability = [LIGHT_GRAY]Inflammabilité: {0} +item.radioactivity = [LIGHT_GRAY]Radioactivité: {0} +unit.health = [LIGHT_GRAY]Santé: {0} +unit.speed = [LIGHT_GRAY]Rapidité: {0} +mech.weapon = [LIGHT_GRAY]Arme: {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} +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.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-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = Sol en métal -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.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.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.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 @@ -548,17 +568,19 @@ 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" @@ -567,18 +589,18 @@ block.omega-mech-pad.name = Reconstructeur de mécha "Oméga" block.tau-mech-pad.name = Reconstructeur de mécha "Tau" block.conduit.name = Conduit block.mechanical-pump.name = Pompe mécanique -block.itemsource.name = Source d'objets -block.itemvoid.name = Destructeur d'objets -block.liquidsource.name = Source de liquide -block.powervoid.name = absorbeur énergétique -block.powerinfinite.name = Puissance infinie +block.item-source.name = Source d'objets +block.item-void.name = Destructeur d'objets +block.liquid-source.name = Source de liquide +block.power-void.name = absorbeur énergétique +block.power-source.name = Puissance infinie block.unloader.name = Déchargeur block.vault.name = Coffre-Fort block.wave.name = Vague block.swarmer.name = Essaim block.salvo.name = Salve block.ripple.name = Ripple -block.phase-conveyor.name = convoyeur phasé +block.phase-conveyor.name = Convoyeur phasé block.bridge-conveyor.name = Pont block.plastanium-compressor.name = Compresseur de Plastanium block.pyratite-mixer.name = Mixeur à Pyratite @@ -623,20 +645,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 . -team.blue.name = bleu -team.red.name = rouge -team.orange.name = orange -team.none.name = gris -team.green.name = vert -team.purple.name = violet +block.launch-pad.name = Launch Pad +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.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 +669,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 . @@ -769,11 +796,11 @@ block.router.description = Accepte les objets depuis une ou plus directions et l 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.itemsource.description = Produit des objets à l'infini. Bac à sable uniquement . -block.liquidsource.description = Source de liquide infinie . Bac à sable uniquement. -block.itemvoid.description = Désintègre n'importe quel objet qui va à l'intérieur sans utiliser d'énergie. Bac à sable uniquement. -block.powerinfinite.description = Produit de l'énergie à l'infini. Bac à sable uniquement. -block.powervoid.description = Supprime toute l'énergie allant à l'intérieur.Bac à sable uniquement +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. diff --git a/core/assets/bundles/bundle_fr_BE.properties b/core/assets/bundles/bundle_fr_BE.properties index 0dc8fba05b..cea1692a02 100644 --- a/core/assets/bundles/bundle_fr_BE.properties +++ b/core/assets/bundles/bundle_fr_BE.properties @@ -1,354 +1,358 @@ -text.credits.text = Créé par [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[] -text.credits = Crédits -text.contributors = Traducteurs et contributeurs -text.discord = Rejoignez le discord de Mindustry ! -text.link.discord.description = Le discord officiel de Mindustry -text.link.github.description = Code source du jeu -text.link.dev-builds.description = Versions instables de développement -text.link.trello.description = Planning Trello officiel pour les fonctionnalités planifiées. -text.link.itch.io.description = Page web itch.io avec les versions ordinateurs téléchargeables et la version web -text.link.google-play.description = Page Google Play du jeu -text.link.wiki.description = Wiki officiel de Mindustry -text.linkfail = L'ouverture du lien a échoué!\nL'URL a été copiée dans votre presse-papier. -text.screenshot = Capture d'écran enregistrée sur {0} -text.gameover = Le base a été détruit. -text.gameover.pvp = L'équipe[accent] {0}[] a gagnée ! -text.sector.gameover = Ce secteur a été perdu. Réessayer ? -text.sector.retry = Réessayer -text.highscore = [accent]Nouveau meilleur score ! -text.wave.lasted = Tu as survécu jusqu'à la vagues [accent]{0}[]. -text.level.highscore = Meilleur score: [accent]{0} -text.level.delete.title = Confirmer -text.map.delete = Êtes-vous sûr de vouloir supprimer cette carte ?"[accent]{0}[]"? -text.level.select = Sélection de niveau -text.level.mode = Mode de jeu: -text.construction.desktop = Désélectionner un bloc ou arrêter la construction, [accent]utiliser la touche espace[]. -text.construction.title = Guide de construction de blocs -text.construction = Vous venez de sélectionner le mode [accent]construction de blocs[].\n\nPour commencez à placer des blocs, appuyez simplement sur un emplacement valide proche de votre vaisseau.\nUne fois que vous avez sélectionné quelques emplacements, Appuyez sur le bouton valider pour confirmer, et votre vaisseau commencera à construire.\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. -text.deconstruction.title = Guide de déconstruction de blocs -text.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. -text.showagain = Ne plus montrer la prochaine fois. -text.coreattack = -text.unlocks = Débloqués -text.savegame = Sauvegarder la partie -text.loadgame = Charger la partie -text.joingame = Rejoindre la partie -text.addplayers = Ajouter/Enlever des joueurs -text.customgame = Partie personnalisée -text.sectors = Secteurs -text.sector = Secteur sélectionné: [LIGHT_GRAY]{0} -text.sector.time = Temps: [LIGHT_GRAY]{0} -text.sector.deploy = Déployer -text.sector.abandon = Abandonner -text.sector.abandon.confirm = Êtes-vous sûr de vouloir abandonner tout progrès dans ce secteur?\nCette action ne peut être annulée! -text.sector.resume = Reprendre -text.sector.locked = [scarlet][[Incomplet] -text.sector.unexplored = [accent][[Inexploré] -text.missions = Missions:[LIGHT_GRAY] {0} -text.mission = Mission:[LIGHT_GRAY] {0} -text.mission.main = Mission principale:[LIGHT_GRAY] {0} -text.mission.info = Mission info -text.mission.complete = Mission terminée ! -text.mission.complete.body = Le secteur {0},{1} a été conquis. -text.mission.wave = Survivez[accent] {0}/{1} []vagues\nProchaine vague dans {2} -text.mission.wave.enemies = Survivez[accent] {0}/{1} []vagues\n{2} Ennemis -text.mission.wave.enemy = Survivez[accent] {0}/{1} []vagues\n{2} Ennemi -text.mission.wave.menu = Survivez[accent] {0} []vagues -text.mission.battle = Détruire la base ennemie. -text.mission.resource.menu = Obtenez {0} x{1} -text.mission.resource = Obtenez {0}:\n[accent]{1}/{2}[] -text.mission.block = Créez {0} -text.mission.unit = Créez {0} unité -text.mission.command = Envoyer une commande à {0} unités -text.mission.linknode = Reliez le transmetteur énergétique -text.mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -text.mission.mech = Changer de mécha[accent] {0}[] -text.mission.create = Créez[accent] {0}[] -text.none = -text.close = Fermer -text.quit = Quitter -text.maps = Cartes -text.continue = Continue -text.nextmission = Prochaine Mission -text.maps.none = [LIGHT_GRAY]Aucune carte trouvée! -text.about.button = À propos -text.name = Nom: -text.noname = Choisissez d'abord [accent]un pseudo[]. -text.filename = Nom du fichier: -text.unlocked = Nouveau bloc debloqué! -text.unlocked.plural = Nouveaux blocs débloqués! -text.players = {0} joueurs en ligne -text.players.single = {0} joueur en ligne -text.server.closing = [accent]Fermeture du serveur ... -text.server.kicked.kick = Vous avez été expulsé du serveur ! -text.server.kicked.serverClose = Serveur fermé. -text.server.kicked.sectorComplete = Secteur terminée. -text.server.kicked.sectorComplete.text = Votre mission est complète.\nLe serveur va maintenant passer au prochain secteur. -text.server.kicked.clientOutdated = Client dépassé! Mettez à jour votre jeu ! -text.server.kicked.serverOutdated = Serveur dépassé! Demandez à l'hôte de le mettre à jour ! -text.server.kicked.banned = Vous êtes banni de ce serveur. -text.server.kicked.recentKick = Vous avez été expulsé récemment.\nAttendez avant de vous connecter à nouveau. -text.server.kicked.nameInUse = Il y a déjà quelqu'un avec ce nom\nsur ce serveur. -text.server.kicked.nameEmpty = Votre nom doit contenir au moins une lettre ou un chiffre. -text.server.kicked.idInUse = Vous êtes déjà sur ce serveur ! Se connecter avec deux comptes n'est pas permis ! -text.server.kicked.customClient = Ce serveur ne supporte pas les versions personnalisées (Custom builds). Télécharger une version officielle. -text.host.info = Le bouton [accent]héberger[] héberge un serveur sur les ports [scarlet]6567[] et [scarlet]6568.[]\nN'importe qui sur le même [LIGHT_GRAY]réseau wifi ou local[] devrait pouvoir voir votre serveur dans sa liste de serveurs.\n\nSi vous voulez que les gens puissent se connecter de n'importe où grâce à l'IP, [accent]rediriger les ports[] est requis.\n\n[LIGHT_GRAY]Note:Si quelqu'un éprouve des difficultés à se connecter à votre partie LAN, assurez-vous que vous avez autorisé Mindustry à accéder à votre réseau local dans les paramètres de votre pare-feu. -text.join.info = Ici, vous pouvez entrer l' [accent]IP d'un serveur[] pour s'y connecter, ou découvrir les serveurs[accent]sur votre réseau local[] pour s'y connecter.\nLes parties multijoueur LAN et WAN sont toutes deux supportées.\n\n[LIGHT_GRAY]Note: Aucune liste globale des serveurs n'est génerée automatiquement: si vous voulez vous connecter à un serveur par IP, vous devrez demander l'IP à l'hébergeur. -text.hostserver = Héberger un serveur -text.hostserver.mobile = Héberger\nUne partie -text.host = Héberger -text.hosting = [accent]Ouverture du serveur ... -text.hosts.refresh = Actualiser -text.hosts.discovering = Recherche de parties en LAN -text.server.refreshing = Actualisation du serveur -text.hosts.none = [lightgray]Aucun jeu en LAN trouvé ! -text.host.invalid = [scarlet]Impossible de se\nconnecter à l'hôte. -text.trace = Suivre le joueur -text.trace.playername = Nom du joueur: [accent]{0} -text.trace.ip = IP: [accent]{0} -text.trace.id = ID Unique: [accent]{0} -text.trace.android = Client Android: [accent]{0} -text.trace.modclient = Client personnalisé: [accent]{0} -text.trace.totalblocksbroken = Total des blocs détruits: [accent]{0} -text.trace.structureblocksbroken = Structure de blocs détruites: [accent]{0} -text.trace.lastblockbroken = Dernier bloc détruit: [accent]{0} -text.trace.totalblocksplaced = Total de blocs placés: [accent]{0} -text.trace.lastblockplaced = Dernier bloc placé: [accent]{0} -text.invalidid = ID client invalide ! Soumettre un rapport de bug -text.server.bans = Bannis -text.server.bans.none = Aucun joueurs bannis trouvés ! -text.server.admins = Administrateurs -text.server.admins.none = Aucun administrateurs trouvé ! -text.server.add = Ajouter un serveur -text.server.delete = Êtes-vous sûr de vouloir supprimer ce serveur ? -text.server.hostname = Hôte: {0} -text.server.edit = Modifier le serveur -text.server.outdated = [crimson]Serveur obsolète ![] -text.server.outdated.client = [crimson]Client obsolète ![] -text.server.version = [lightgray]Version: {0} {1} -text.server.custombuild = [yellow]Version personnalisée -text.confirmban = Êtes-vous sûr de vouloir bannir ce joueur ? -text.confirmkick = Êtes-vous sûr de vouloir expulser ce joueur? -text.confirmunban = Êtes-vous sûr de vouloir annuler le ban de ce joueur ? -text.confirmadmin = Êtes-vous sûr de vouloir faire de ce joueur un administrateur ? -text.confirmunadmin = Êtes-vous sûr de vouloir supprimer le statut d'administrateur de ce joueur ? -text.joingame.title = Rejoindre une partie -text.joingame.ip = IP: -text.disconnect = Déconnecté. -text.disconnect.data = Les données du monde n'ont pas pu être chargées ! -text.connecting = [accent]Connexion... -text.connecting.data = [accent]Chargement des données du monde... -text.server.port = Port: -text.server.addressinuse = Adresse déjà utilisée ! -text.server.invalidport = Numéro de port incorrect ! -text.server.error = [crimson]Erreur lors de l'hébergement du serveur: [accent]{0} -text.save.old = Cette sauvegarde correspond à une ancienne version du jeu et ne peut donc plus être utilisée.\n\n[LIGHT_GRAY]La rétrocompatibilité des sauvegardes va être implémentée dans la version finale de la 4.0. -text.save.new = Nouvelle sauvegarde -text.save.overwrite = Êtes-vous sûr de vouloir\nécraser cette sauvegarde ? -text.overwrite = Écraser -text.save.none = Aucune sauvegarde trouvée ! -text.saveload = [accent]Sauvegarde... -text.savefail = Échec de la sauvegarde ! -text.save.delete.confirm = Êtes-vous sûr de supprimer cette sauvegarde ? -text.save.delete = Supprimer -text.save.export = Exporter une\nSauvegarde -text.save.import.invalid = [accent]Cette sauvegarde est invalide! -text.save.import.fail = [crimson]L'importation de la sauvegarde\na échouée: [accent]{0} -text.save.export.fail = [crimson]L'exportation de la sauvegarde\na échouée: [accent]{0} -text.save.import = Importer une sauvegarde -text.save.newslot = Nom de la sauvegarde: -text.save.rename = Renommer -text.save.rename.text = Nouveau nom: -text.selectslot = Sélectionnez une sauvegarde. -text.slot = [accent]Emplacement {0} -text.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. -text.sector.corrupted = [accent]Une sauvegarde pour ce secteur a été trouvé, mais son chargement a raté.\nUne nouvelle sauvegarde a été créé. -text.empty = -text.on = Allumer -text.off = Éteint -text.save.autosave = Sauvegarde automatique {0} -text.save.map = Carte: {0} -text.save.wave = Vague {0} -text.save.difficulty = Difficulté: {0} -text.save.date = Dernière sauvegarde: {0} -text.save.playtime = Temps de jeu: {0} -text.confirm = Confirmer -text.delete = Supprimer -text.ok = OK -text.open = Ouvrir -text.cancel = Annuler -text.openlink = Ouvrir le lien -text.copylink = Copier le lien -text.back = Retour -text.quit.confirm = Êtes-vous sûr de vouloir quitter? -text.changelog.title = Notes de mise à jour -text.changelog.loading = Récupération des notes de mise à jour... -text.changelog.error.android = [accent]Notez que les notes de mise à jour ne marchent pas, certaines fois, sur Android 4.4 et versions antérieures!\nCeci est dû à un bug interne à Android. -text.changelog.error.ios = [accent]Les notes de mise à jour ne sont actuellement pas supportée sur IOS. -text.changelog.error = [scarlet]Erreur lors de la récupération des notes de mises à jour!\nVérifiez votre connexion internet. -text.changelog.current = [yellow][[Version actuelle] -text.changelog.latest = [accent][[Dernière version] -text.loading = [accent]Chargement... -text.saving = [accent]Sauvegarde... -text.wave = [accent]Vague {0} -text.wave.waiting = [LIGHT_GRAY]Prochaine vague dans {0} -text.waiting = [LIGHT_GRAY]En attente... -text.waiting.players = En attente de joueurs ... -text.wave.enemies = [LIGHT_GRAY]{0} Ennemis restants -text.wave.enemy = [LIGHT_GRAY]{0} Ennemi restant -text.loadimage = Charger l'image -text.saveimage = Sauvegarder l'image -text.unknown = Inconnu -text.custom = Personnalisé -text.builtin = Pré-fait -text.map.delete.confirm = Êtes-vous sûr de vouloir effacer cette carte ? Cette action est irréversible ! -text.map.random = [accent]Carte aléatoire -text.map.nospawn = Cette carte ne possède pas de base pour que le joueur puisse apparaître !Ajouter un [ROYAL]base bleue[] sur cette carte dans l'éditeur. -text.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. -text.map.invalid = Erreur lors du chargement de la carte: carte corrompue ou invalide. -text.editor.brush = Pinceau -text.editor.slope = \\ -text.editor.openin = Ouvrir dans l'éditeur -text.editor.oregen = Génération des minerais -text.editor.oregen.info = Génération de minerais: -text.editor.mapinfo = Infos sur la carte -text.editor.author = Auteur: -text.editor.description = Description: -text.editor.name = Nom: -text.editor.teams = Équipes -text.editor.elevation = Élévation -text.editor.errorimageload = Erreur lors du chargement du fichier image:\n[accent]{0} -text.editor.errorimagesave = Erreur lors de la sauvegarde du fichier image:\n[accent]{0} -text.editor.generate = Générer -text.editor.resize = Redimensionner -text.editor.loadmap = Charger une carte -text.editor.savemap = Sauvegarder une carte -text.editor.saved = Sauvegardé ! -text.editor.save.noname = Votre carte ne possède pas de nom ! Ajouter en un dans le menu 'Infos sur la carte'. -text.editor.save.overwrite = Une carte posséde déjà ce nom ! Choisissez un nom différent dans le menu 'Infos sur la carte'. -text.editor.import.exists = [scarlet]Importation impossible :[] Une carte nommé '{0}' existe déjà! -text.editor.import = Importation... -text.editor.importmap = Importer une carte -text.editor.importmap.description = Importer une carte déjà existante -text.editor.importfile = Importer un fichier -text.editor.importfile.description = Importer une carte à partir d'un fichier externe -text.editor.importimage = Importer l'image du terrain -text.editor.importimage.description = Importer une image de terrain à partir d'un fichier externe -text.editor.export = Exportation en cours... -text.editor.exportfile = Exporter un fichier -text.editor.exportfile.description = Exporter une carte -text.editor.exportimage = Exporter l'image du terrain -text.editor.exportimage.description = Exporter la carte sous forme d'image -text.editor.loadimage = Importer le terrain -text.editor.saveimage = Exportr le terrain -text.editor.unsaved = [scarlet] Vous avez des changements non sauvegardés ![] Êtes-vous sûr de vouloir quitter ? -text.editor.resizemap = Redimensionner\nla carte -text.editor.mapname = Nom de la carte: -text.editor.overwrite = [accent]Attention!\nCela écrasera une carte existante. -text.editor.overwrite.confirm = [scarlet]Attention ![] Une carte avec ce nom existe déjà. Êtes-vous sûr de vouloir la réécrire? -text.editor.selectmap = Sélectionnez une carte à charger: -text.width = Largeur: -text.height = Hauteur: -text.menu = Menu -text.play = Jouer -text.load = Charger -text.save = Sauvegarder -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Ping: {0}ms -text.language.restart = Veuillez redémarrez votre jeu pour le changement de langage prenne effet. -text.settings = Paramètres -text.tutorial = Tutoriel -text.editor = Éditeur -text.mapeditor = Éditeur de carte -text.donate = Faire un\ndon -text.connectfail = [crimson]Échec de la connexion au serveur: [accent]{0} -text.error.unreachable = Serveur inaccessible. -text.error.invalidaddress = Adresse invalide. -text.error.timedout = Expiration du délai !\nAssurez-vous que la redirection de port est configurée sur l'hôte et que l'adresse est correcte ! -text.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 ! -text.error.alreadyconnected = Déjà connecté. -text.error.mapnotfound = Fichier de carte introuvable ! -text.error.any = Erreur réseau inconnue. -text.settings.language = Langage -text.settings.reset = Valeur par défaut. -text.settings.rebind = Réatttribuer -text.settings.controls = Contrôles -text.settings.game = Jeu -text.settings.sound = Son -text.settings.graphics = Graphiques -text.settings.cleardata = Effacer les données du jeu... -text.settings.clear.confirm = Êtes-vous sûr d'effacer ces données ?\n[scarlet]Ceci est irréversible -text.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. -text.settings.clearsectors = Éffacer les données des secteurs -text.settings.clearunlocks = Éffacer les déblocages -text.settings.clearall = Tout effacer -text.paused = En pause -text.yes = Oui -text.no = Non -text.info.title = Info -text.error.title = [crimson]Une erreur s'est produite -text.error.crashtitle = Une erreur s'est produite -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = Info sur le bloc -text.blocks.powercapacity = Capacité d'énergie -text.blocks.powershot = Énergie/Tir -text.blocks.targetsair = Cible les unités aériennes -text.blocks.itemspeed = Objets déplacés -text.blocks.shootrange = Portée -text.blocks.size = Taille -text.blocks.liquidcapacity = Capacité en liquide -text.blocks.maxitemssecond = Production maximale -text.blocks.powerrange = Distance de transmission -text.blocks.poweruse = Énergie utilisée -text.blocks.powerdamage = Énergie/Dégâts -text.blocks.inputitemcapacity = Capacité d'entrée -text.blocks.outputitemcapacity = Capacité de sortie -text.blocks.itemcapacity = Stockage -text.blocks.basepowergeneration = Production d'énergie de base -text.blocks.powertransferspeed = Vitesse de transfert d'énergie -text.blocks.craftspeed = Vitesse de production -text.blocks.inputliquid = Liquide requis -text.blocks.inputliquidaux = Liquide optionnel -text.blocks.inputitem = Objet utilisé -text.blocks.inputitems = Objets utilisés -text.blocks.outputitem = Objet produit -text.blocks.drilltier = Forable -text.blocks.drillspeed = Vitesse de forage de base -text.blocks.liquidoutput = Liquide en sortie -text.blocks.liquidoutputspeed = Vitesse de sortie du liquide -text.blocks.liquiduse = Quantité de liquide utilisé -text.blocks.coolant = Liquide de refroidissement -text.blocks.coolantuse = Quantité de liquide de refroidissement utilisé -text.blocks.inputliquidfuel = Carburant liquide -text.blocks.liquidfueluse = Quantité de carburant liquide utilisé -text.blocks.boostitem = Objet boostant la production -text.blocks.boostliquid = Liquide boostant la production -text.blocks.health = Santé -text.blocks.inaccuracy = Précision -text.blocks.shots = Tirs -text.blocks.reload = Tirs/Seconde -text.blocks.inputfuel = Carburant -text.blocks.fuelburntime = Durée du carburant -text.blocks.inputcapacity = Capacité d'entrée -text.blocks.outputcapacity = Capacité de sortie -text.unit.blocks = Blocs -text.unit.powersecond = Énergie/seconde -text.unit.liquidsecond = Liquides/seconde -text.unit.itemssecond = Objets/seconde -text.unit.pixelssecond = Pixels/seconde -text.unit.liquidunits = Unité de liquide -text.unit.powerunits = Unité d'énergie -text.unit.degrees = degrés -text.unit.seconds = secondes -text.unit.items = Objets -text.category.general = Général -text.category.power = Énergie -text.category.liquids = Liquides -text.category.items = Objets -text.category.crafting = Fabrication -text.category.shooting = Défense -text.category.optional = Améliorations facultatives +credits.text = Créé par [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[] +credits = Crédits +contributors = Traducteurs et contributeurs +discord = Rejoignez le discord de Mindustry ! +link.discord.description = Le discord officiel de Mindustry +link.github.description = Code source du jeu +link.dev-builds.description = Versions instables de développement +link.trello.description = Planning Trello officiel pour les fonctionnalités planifiées. +link.itch.io.description = Page web itch.io avec les versions ordinateurs téléchargeables et la version web +link.google-play.description = Page Google Play du jeu +link.wiki.description = Wiki officiel de Mindustry +linkfail = L'ouverture du lien a échoué!\nL'URL a été copiée dans votre presse-papier. +screenshot = Capture d'écran enregistrée sur {0} +gameover = Le base a été détruit. +gameover.pvp = L'équipe[accent] {0}[] a gagnée ! +highscore = [accent]Nouveau meilleur score ! +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: +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[]. +construction.title = Guide de construction de blocs +construction = Vous venez de sélectionner le mode [accent]construction de blocs[].\n\nPour commencez à placer des blocs, appuyez simplement sur un emplacement valide proche de votre vaisseau.\nUne fois que vous avez sélectionné quelques emplacements, Appuyez sur le bouton valider pour confirmer, et votre vaisseau commencera à construire.\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. +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 = +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 +newgame = New Game +none = +close = Fermer +quit = Quitter +maps = Cartes +continue = Continue +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é! +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.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. +server.kicked.recentKick = Vous avez été expulsé récemment.\nAttendez avant de vous connecter à nouveau. +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écharger une version officielle. +server.kicked.gameover = Vous avez perdu ! +host.info = Le bouton [accent]héberger[] héberge un serveur sur les ports [scarlet]6567[] et [scarlet]6568.[]\nN'importe qui sur le même [LIGHT_GRAY]réseau wifi ou local[] devrait pouvoir voir votre serveur dans sa liste de serveurs.\n\nSi vous voulez que les gens puissent se connecter de n'importe où grâce à l'IP, [accent]rediriger les ports[] est requis.\n\n[LIGHT_GRAY]Note:Si quelqu'un éprouve des difficultés à se connecter à votre partie LAN, assurez-vous que vous avez autorisé Mindustry à accéder à votre réseau local dans les paramètres de votre pare-feu. +join.info = Ici, vous pouvez entrer l' [accent]IP d'un serveur[] pour s'y connecter, ou découvrir les serveurs[accent]sur votre réseau local[] pour s'y connecter.\nLes parties multijoueur LAN et WAN sont toutes deux supportées.\n\n[LIGHT_GRAY]Note: Aucune liste globale des serveurs n'est génerée automatiquement: si vous voulez vous connecter à un serveur par IP, vous devrez demander l'IP à l'hébergeur. +hostserver = Héberger un serveur +hostserver.mobile = Héberger\nUne partie +host = Héberger +hosting = [accent]Ouverture du serveur ... +hosts.refresh = Actualiser +hosts.discovering = Recherche de parties en LAN +server.refreshing = Actualisation du serveur +hosts.none = [lightgray]Aucun jeu en LAN trouvé ! +host.invalid = [scarlet]Impossible de se\nconnecter à l'hôte. +trace = Suivre le joueur +trace.playername = Nom du joueur: [accent]{0} +trace.ip = IP: [accent]{0} +trace.id = ID Unique: [accent]{0} +trace.android = Client Android: [accent]{0} +trace.modclient = Client personnalisé: [accent]{0} +trace.totalblocksbroken = Total des blocs détruits: [accent]{0} +trace.structureblocksbroken = Structure de blocs détruites: [accent]{0} +trace.lastblockbroken = Dernier bloc détruit: [accent]{0} +trace.totalblocksplaced = Total de blocs placés: [accent]{0} +trace.lastblockplaced = Dernier bloc placé: [accent]{0} +invalidid = ID client invalide ! Soumettre un rapport de bug +server.bans = Bannis +server.bans.none = Aucun joueurs bannis trouvés ! +server.admins = Administrateurs +server.admins.none = Aucun administrateurs trouvé ! +server.add = Ajouter un serveur +server.delete = Êtes-vous sûr de vouloir supprimer ce serveur ? +server.hostname = Hôte: {0} +server.edit = Modifier le serveur +server.outdated = [crimson]Serveur obsolète ![] +server.outdated.client = [crimson]Client obsolète ![] +server.version = [lightgray]Version: {0} {1} +server.custombuild = [yellow]Version personnalisée +confirmban = Êtes-vous sûr de vouloir bannir ce joueur ? +confirmkick = Êtes-vous sûr de vouloir expulser ce joueur? +confirmunban = Êtes-vous sûr de vouloir annuler le ban de ce joueur ? +confirmadmin = Êtes-vous sûr de vouloir faire de ce joueur un administrateur ? +confirmunadmin = Êtes-vous sûr de vouloir supprimer le statut d'administrateur de ce joueur ? +joingame.title = Rejoindre une partie +joingame.ip = IP: +disconnect = Déconnecté. +disconnect.data = Les données du monde n'ont pas pu être chargées ! +connecting = [accent]Connexion... +connecting.data = [accent]Chargement des données du monde... +server.port = Port: +server.addressinuse = Adresse déjà utilisée ! +server.invalidport = Numéro de port incorrect ! +server.error = [crimson]Erreur lors de l'hébergement du serveur: [accent]{0} +save.old = Cette sauvegarde correspond à une ancienne version du jeu et ne peut donc plus être utilisée.\n\n[LIGHT_GRAY]La rétrocompatibilité des sauvegardes va être implémentée dans la version finale de la 4.0. +save.new = Nouvelle sauvegarde +save.overwrite = Êtes-vous sûr de vouloir\nécraser cette sauvegarde ? +overwrite = Écraser +save.none = Aucune sauvegarde trouvée ! +saveload = [accent]Sauvegarde... +savefail = Échec de la sauvegarde ! +save.delete.confirm = Êtes-vous sûr de supprimer cette sauvegarde ? +save.delete = Supprimer +save.export = Exporter une\nSauvegarde +save.import.invalid = [accent]Cette sauvegarde est invalide! +save.import.fail = [crimson]L'importation de la sauvegarde\na échouée: [accent]{0} +save.export.fail = [crimson]L'exportation de la sauvegarde\na échouée: [accent]{0} +save.import = Importer une sauvegarde +save.newslot = Nom de la sauvegarde: +save.rename = Renommer +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. +empty = +on = Allumer +off = Éteint +save.autosave = Sauvegarde automatique {0} +save.map = Carte: {0} +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 +open = Ouvrir +cancel = Annuler +openlink = Ouvrir le lien +copylink = Copier le lien +back = Retour +quit.confirm = Êtes-vous sûr de vouloir quitter? +changelog.title = Notes de mise à jour +changelog.loading = Récupération des notes de mise à jour... +changelog.error.android = [accent]Notez que les notes de mise à jour ne marchent pas, certaines fois, sur Android 4.4 et versions antérieures!\nCeci est dû à un bug interne à Android. +changelog.error.ios = [accent]Les notes de mise à jour ne sont actuellement pas supportée sur IOS. +changelog.error = [scarlet]Erreur lors de la récupération des notes de mises à jour!\nVérifiez votre connexion internet. +changelog.current = [yellow][[Version actuelle] +changelog.latest = [accent][[Dernière version] +loading = [accent]Chargement... +saving = [accent]Sauvegarde... +wave = [accent]Vague {0} +wave.waiting = [LIGHT_GRAY]Prochaine vague dans {0} +waiting = [LIGHT_GRAY]En attente... +waiting.players = En attente de joueurs ... +wave.enemies = [LIGHT_GRAY]{0} Ennemis restants +wave.enemy = [LIGHT_GRAY]{0} Ennemi restant +loadimage = Charger l'image +saveimage = Sauvegarder l'image +unknown = Inconnu +custom = Personnalisé +builtin = Pré-fait +map.delete.confirm = Êtes-vous sûr de vouloir effacer cette carte ? Cette action est irréversible ! +map.random = [accent]Carte aléatoire +map.nospawn = Cette carte ne possède pas de base pour que le joueur puisse apparaître !Ajouter un [ROYAL]base bleue[] sur cette carte dans l'éditeur. +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: +editor.mapinfo = Infos sur la carte +editor.author = Auteur: +editor.description = Description: +editor.name = Nom: +editor.teams = Équipes +editor.elevation = Élévation +editor.errorimageload = Erreur lors du chargement du fichier image:\n[accent]{0} +editor.errorimagesave = Erreur lors de la sauvegarde du fichier image:\n[accent]{0} +editor.generate = Générer +editor.resize = Redimensionner +editor.loadmap = Charger une carte +editor.savemap = Sauvegarder une carte +editor.saved = Sauvegardé ! +editor.save.noname = Votre carte ne possède pas de nom ! Ajouter en un dans le menu 'Infos sur la carte'. +editor.save.overwrite = Une carte posséde déjà ce nom ! Choisissez un nom différent dans le menu 'Infos sur la carte'. +editor.import.exists = [scarlet]Importation impossible :[] Une carte nommé '{0}' existe déjà! +editor.import = Importation... +editor.importmap = Importer une carte +editor.importmap.description = Importer une carte déjà existante +editor.importfile = Importer un fichier +editor.importfile.description = Importer une carte à partir d'un fichier externe +editor.importimage = Importer l'image du terrain +editor.importimage.description = Importer une image de terrain à partir d'un fichier externe +editor.export = Exportation en cours... +editor.exportfile = Exporter un fichier +editor.exportfile.description = Exporter une carte +editor.exportimage = Exporter l'image du terrain +editor.exportimage.description = Exporter la carte sous forme d'image +editor.loadimage = Importer le terrain +editor.saveimage = Exportr le terrain +editor.unsaved = [scarlet] Vous avez des changements non sauvegardés ![] Êtes-vous sûr de vouloir quitter ? +editor.resizemap = Redimensionner\nla carte +editor.mapname = Nom de la carte: +editor.overwrite = [accent]Attention!\nCela écrasera une carte existante. +editor.overwrite.confirm = [scarlet]Attention ![] Une carte avec ce nom existe déjà. Êtes-vous sûr de vouloir la réécrire? +editor.selectmap = Sélectionnez une carte à charger: +width = Largeur: +height = Hauteur: +menu = Menu +play = Jouer +load = Charger +save = Sauvegarder +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0}ms +language.restart = Veuillez redémarrez votre jeu pour le changement de langage prenne effet. +settings = Paramètres +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson]Échec de la connexion au serveur: [accent]{0} +error.unreachable = Serveur inaccessible. +error.invalidaddress = Adresse invalide. +error.timedout = Expiration du délai !\nAssurez-vous que la redirection de port est configurée sur l'hôte et que l'adresse est correcte ! +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 ! +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 +settings.controls = Contrôles +settings.game = Jeu +settings.sound = Son +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.clearunlocks = Éffacer les déblocages +settings.clearall = Tout effacer +paused = En pause +yes = Oui +no = Non +info.title = Info +error.title = [crimson]Une erreur s'est produite +error.crashtitle = Une erreur s'est produite +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Info sur le bloc +blocks.powercapacity = Capacité d'énergie +blocks.powershot = Énergie/Tir +blocks.targetsair = Cible les unités aériennes +blocks.itemspeed = Objets déplacés +blocks.shootrange = Portée +blocks.size = Taille +blocks.liquidcapacity = Capacité en liquide +blocks.maxitemssecond = Production maximale +blocks.powerrange = Distance de transmission +blocks.poweruse = Énergie utilisée +blocks.powerdamage = Énergie/Dégâts +blocks.inputitemcapacity = Capacité d'entrée +blocks.outputitemcapacity = Capacité de sortie +blocks.itemcapacity = Stockage +blocks.basepowergeneration = Production d'énergie de base +blocks.powertransferspeed = Vitesse de transfert d'énergie +blocks.craftspeed = Vitesse de production +blocks.inputliquid = Liquide requis +blocks.inputliquidaux = Liquide optionnel +blocks.inputitem = Objet utilisé +blocks.inputitems = Objets utilisés +blocks.outputitem = Objet produit +blocks.drilltier = Forable +blocks.drillspeed = Vitesse de forage de base +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.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = Précision +blocks.shots = Tirs +blocks.reload = Tirs/Seconde +blocks.inputfuel = Carburant +blocks.fuelburntime = Durée du carburant +blocks.inputcapacity = Capacité d'entrée +blocks.outputcapacity = Capacité de sortie +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 +unit.seconds = secondes +unit.items = Objets +category.general = Général +category.power = Énergie +category.liquids = Liquides +category.items = Objets +category.crafting = Fabrication +category.shooting = Défense +category.optional = Améliorations facultatives setting.indicators.name = Indicateurs d'alliés setting.autotarget.name = Visée automatique setting.fpscap.name = Max FPS @@ -375,18 +379,22 @@ setting.mutemusic.name = Couper la musique setting.sfxvol.name = Volume des SFX setting.mutesound.name = Couper les SFX setting.crashreport.name = Envoyer des rapports d'incident anonymement. -text.keybind.title = Paramétrer les touches +keybind.title = Paramétrer les touches category.general.name = Général category.view.name = Voir category.multiplayer.name = Multijoueur command.attack = Attaquer command.retreat = Retraite command.patrol = Patrouiller +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.select.name = Sélectionner/Tirer +keybind.pick.name = Pick Block keybind.break.name = Pause keybind.deselect.name = Déselectionner keybind.shoot.name = Tirer @@ -405,9 +413,9 @@ keybind.chat_history_next.name = Suite de l'historique du tchat keybind.chat_scroll.name = Faire défiler le tchat keybind.drop_unit.name = Larguer une unité keybind.zoom_minimap.name = Zoomer la minimap -mode.text.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.help.title = Description des modes de jeu +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,18 +427,15 @@ mode.attack.descrption = Pas de vagues, le but est de détruire la base ennemie. 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 @@ -451,6 +456,10 @@ 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.oil.name = Pétrole @@ -484,24 +493,29 @@ mech.trident-ship.weapon = Largage de bombe mech.glaive-ship.name = Glaive mech.glaive-ship.description = Un grand vaisseau de combat cuirassé. Equipé avec un fusil automatique à munitions incendiaires. Il a aussi une bonne accéleration ainsi qu'une bonne vitesse maximale. mech.glaive-ship.weapon = Fusil automatique incendiaire -text.item.explosiveness = [LIGHT_GRAY]Explosivité: {0} -text.item.flammability = [LIGHT_GRAY]Inflammabilité: {0} -text.item.radioactivity = [LIGHT_GRAY]Radioactivité: {0} -text.item.fluxiness = [LIGHT_GRAY]Flux de Puissance: {0} -text.unit.health = [LIGHT_GRAY]Santé: {0} -text.unit.speed = [LIGHT_GRAY]Vitesse: {0} -text.mech.weapon = [LIGHT_GRAY]Arme: {0} -text.mech.armor = [LIGHT_GRAY]Armure: {0} -text.mech.itemcapacity = [LIGHT_GRAY]Capacité de stockage: {0} -text.mech.minespeed = [LIGHT_GRAY]Vitesse de minage: {0} -text.mech.minepower = [LIGHT_GRAY]Puissance du minage: {0} -text.mech.ability = [LIGHT_GRAY]Compétence: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]Capacité Thermique {0} -text.liquid.viscosity = [LIGHT_GRAY]Viscosité: {0} -text.liquid.temperature = [LIGHT_GRAY]Température: {0} +item.explosiveness = [LIGHT_GRAY]Explosivité: {0} +item.flammability = [LIGHT_GRAY]Inflammabilité: {0} +item.radioactivity = [LIGHT_GRAY]Radioactivité: {0} +unit.health = [LIGHT_GRAY]Santé: {0} +unit.speed = [LIGHT_GRAY]Vitesse: {0} +mech.weapon = [LIGHT_GRAY]Arme: {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} +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.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.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = Sol en métal block.deepwater.name = Eau profonde block.water.name = Eau @@ -520,8 +534,8 @@ block.blackrock.name = Pierre sombre block.icerock.name = Pierre gelée 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 @@ -554,17 +568,19 @@ 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 @@ -573,11 +589,11 @@ block.omega-mech-pad.name = Omega Mech Pad block.tau-mech-pad.name = Tau Mech Pad block.conduit.name = Conduit block.mechanical-pump.name = Pompe Méchanique -block.itemsource.name = Source d'objets -block.itemvoid.name = Destructeur d'objets -block.liquidsource.name = Source de liquide -block.powervoid.name = Absorbeur énergétique -block.powerinfinite.name = Puissance infinie +block.item-source.name = Source d'objets +block.item-void.name = Destructeur d'objets +block.liquid-source.name = Source de liquide +block.power-void.name = Absorbeur énergétique +block.power-source.name = Puissance infinie block.unloader.name = Déchargeur block.vault.name = Coffre-Fort block.wave.name = Vague @@ -629,7 +645,7 @@ 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 team.blue.name = Bleu team.red.name = Rouge team.orange.name = Orange @@ -643,6 +659,7 @@ 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 @@ -652,7 +669,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 . @@ -775,11 +796,11 @@ block.router.description = Accepte les éléments d'une direction et les envoie 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.itemsource.description = Sort infiniment les articles. Bac à sable seulement. -block.liquidsource.description = Débit infini de liquides. Bac à sable seulement. -block.itemvoid.description = Détruit tous les objets qui y entrent sans utiliser d'énergie. Bac à sable seulement. -block.powerinfinite.description = Débit infini d'énergie. Bac à sable seulement. -block.powervoid.description = Annule toute l'énergie qui y est introduite. Bac à sable seulement. +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. diff --git a/core/assets/bundles/bundle_in_ID.properties b/core/assets/bundles/bundle_in_ID.properties index 387e2f6bf3..d1604949cd 100644 --- a/core/assets/bundles/bundle_in_ID.properties +++ b/core/assets/bundles/bundle_in_ID.properties @@ -1,351 +1,359 @@ -text.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!) -text.credits = Credits -text.discord = Bergabunglah dengan Discord Mindustry! -text.link.discord.description = the official Mindustry discord chatroom -text.link.github.description = Game source code -text.link.dev-builds.description = Unstable development builds -text.link.trello.description = Official trello board for planned features -text.link.itch.io.description = itch.io page with PC downloads and web version -text.link.google-play.description = Google Play store listing -text.link.wiki.description = official Mindustry wiki -text.linkfail = Failed to open link!\nThe URL has been copied to your cliboard. -text.gameover = Intinya hancur. -text.gameover.pvp = The[accent] {0}[] team is victorious! -text.sector.gameover = This sector has been lost. Re-deploy? -text.sector.retry = Retry -text.highscore = [YELLOW]Rekor baru! -text.wave.lasted = You lasted until wave [accent]{0}[]. -text.level.highscore = Skor Tinggi: [accent]{0} -text.level.delete.title = Konfirmasi Hapus -text.map.delete = Are you sure you want to delete the map "[accent]{0}[]"? -text.level.select = Pilih Level -text.level.mode = Modus permainan: -text.construction.desktop = Desktop controls have been changed.\nTo deselect a block or stop building, [accent]use space[]. -text.construction.title = Block Construction Guide -text.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. -text.deconstruction.title = Block Deconstruction Guide -text.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. -text.showagain = Don't show again next session -text.coreattack = < Core is under attack! > -text.unlocks = Unlocks -text.savegame = Simpan Permainan -text.loadgame = Lanjutkan -text.joingame = Bermain Bersama -text.addplayers = Add/Remove Players -text.customgame = Custom Game -text.sectors = Sectors -text.sector = Selected Sector: [LIGHT_GRAY]{0} -text.sector.time = Time: [LIGHT_GRAY]{0} -text.sector.deploy = Deploy -text.sector.abandon = Abandon -text.sector.abandon.confirm = Are you sure you want to abandon all progress at this sector?\nThis cannot be undone! -text.sector.resume = Resume -text.sector.locked = [scarlet][[Incomplete] -text.sector.unexplored = [accent][[Unexplored] -text.missions = Missions:[LIGHT_GRAY] {0} -text.mission = Mission:[LIGHT_GRAY] {0} -text.mission.main = Main Mission:[LIGHT_GRAY] {0} -text.mission.info = Mission Info -text.mission.complete = Mission complete! -text.mission.complete.body = Sector {0},{1} has been conquered. -text.mission.wave = Survive[accent] {0}/{1} []waves\nWave in {2} -text.mission.wave.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies -text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy -text.mission.wave.menu = Survive[accent] {0} []waves -text.mission.battle = Destroy the enemy base. -text.mission.resource.menu = Obtain {0} x{1} -text.mission.resource = Obtain {0}:\n[accent]{1}/{2}[] -text.mission.block = Create {0} -text.mission.unit = Create {0} Unit -text.mission.command = Send Command {0} To Units -text.mission.linknode = Link Power Node -text.mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -text.mission.mech = Switch to mech[accent] {0}[] -text.mission.create = Create[accent] {0}[] -text.none = -text.close = Close -text.quit = Keluar -text.maps = Maps -text.continue = Continue -text.nextmission = Next Mission -text.maps.none = [LIGHT_GRAY]No maps found! -text.about.button = Tentang -text.name = Nama: -text.filename = File Name: -text.unlocked = New Block Unlocked! -text.unlocked.plural = New Blocks Unlocked! -text.players = {0} pemain online -text.players.single = {0} pemain online -text.server.closing = [accent]Menutup server... -text.server.kicked.kick = Anda telah dikeluarkan dari server! -text.server.kicked.serverClose = Server closed. -text.server.kicked.sectorComplete = Sector completed. -text.server.kicked.sectorComplete.text = Your mission is complete.\nThe server will now continue at the next sector. -text.server.kicked.clientOutdated = Client versi lama! Update game Anda! -text.server.kicked.serverOutdated = Server versi lama! Tanyakan host untuk mengupdate! -text.server.kicked.banned = You are banned on this server. -text.server.kicked.recentKick = You have been kicked recently.\nWait before connecting again. -text.server.kicked.nameInUse = There is someone with that name\nalready on this server. -text.server.kicked.nameEmpty = Your name must contain at least one character or number. -text.server.kicked.idInUse = You are already on this server! Connecting with two accounts is not permitted. -text.server.kicked.customClient = This server does not support custom builds. Download an official version. -text.host.info = The [accent]host[] button hosts a server on ports [scarlet]6567[] and [scarlet]6568.[]\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. -text.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. -text.hostserver = Host Server -text.hostserver.mobile = Host\nGame -text.host = Host -text.hosting = [accent]Membuka server... -text.hosts.refresh = Segarkan -text.hosts.discovering = Mencari game LAN -text.server.refreshing = Menyegarkan server -text.hosts.none = [lightgray]Tidak ada game LAN yang ditemukan! -text.host.invalid = [scarlet]Tidak dapat terhubung ke host. -text.trace = Trace Player -text.trace.playername = Player name: [accent]{0} -text.trace.ip = IP: [accent]{0} -text.trace.id = Unique ID: [accent]{0} -text.trace.android = Android Client: [accent]{0} -text.trace.modclient = Custom Client: [accent]{0} -text.trace.totalblocksbroken = Total blocks broken: [accent]{0} -text.trace.structureblocksbroken = Structure blocks broken: [accent]{0} -text.trace.lastblockbroken = Last block broken: [accent]{0} -text.trace.totalblocksplaced = Total blocks placed: [accent]{0} -text.trace.lastblockplaced = Last block placed: [accent]{0} -text.invalidid = Invalid client ID! Submit a bug report. -text.server.bans = Bans -text.server.bans.none = No banned players found! -text.server.admins = Admins -text.server.admins.none = No admins found! -text.server.add = Tambahkan Server -text.server.delete = Yakin ingin menghapus server ini? -text.server.hostname = Host: {0} -text.server.edit = Sunting Server -text.server.outdated = [crimson]Outdated Server![] -text.server.outdated.client = [crimson]Outdated Client![] -text.server.version = [lightgray]Version: {0} -text.server.custombuild = [yellow]Custom Build -text.confirmban = Are you sure you want to ban this player? -text.confirmkick = Are you sure you want to kick this player? -text.confirmunban = Are you sure you want to unban this player? -text.confirmadmin = Are you sure you want to make this player an admin? -text.confirmunadmin = Are you sure you want to remove admin status from this player? -text.joingame.title = Bermain Bersama -text.joingame.ip = IP: -text.disconnect = Sambungan terputus. -text.disconnect.data = Failed to load world data! -text.connecting = [accent]Menghubungkan... -text.connecting.data = [accent]Memuat data level... -text.server.port = Port: -text.server.addressinuse = Alamat sudah di pakai! -text.server.invalidport = Nomor port salah! -text.server.error = [crimson]Kesalahan server hosting: [accent]{0} -text.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. -text.save.new = Simpan Baru -text.save.overwrite = Yakin ingin mengganti slot simpan ini? -text.overwrite = Ganti -text.save.none = Tidak ada simpanan ditemukan! -text.saveload = [accent]Menyimpan... -text.savefail = Gagal menyimpan game! -text.save.delete.confirm = Yakin ingin menghapus save ini? -text.save.delete = Hapus -text.save.export = Ekspor Simpanan -text.save.import.invalid = [accent]Simpanan ini tidak valid! -text.save.import.fail = [crimson]Gagal mengimpor: [accent]{0} -text.save.export.fail = [crimson]Gagal mengekspor save: [accent]{0} -text.save.import = Impor Simpanan -text.save.newslot = Nama simpanan: -text.save.rename = Ganti nama -text.save.rename.text = Nama baru: -text.selectslot = Pilih simpanan. -text.slot = [accent]Slot{0} -text.save.corrupted = [accent]Simpanan rusak atau tidak valid! -text.sector.corrupted = [accent]A save file for this sector was found, but loading failed.\nA new one has been created. -text.empty = -text.on = Hidup -text.off = Mati -text.save.autosave = Simpan otomatis: {0} -text.save.map = Peta: {0} -text.save.wave = Gelombang {0} -text.save.difficulty = Difficulty: {0} -text.save.date = Terakhir Disimpan: {0} -text.save.playtime = Playtime: {0} -text.confirm = Konfirmasi -text.delete = Hapus -text.ok = OK -text.open = Buka -text.cancel = Batal -text.openlink = Buka tautan -text.copylink = Copy Link -text.back = Kembali -text.quit.confirm = Anda yakin ingin berhenti? -text.changelog.title = Changelog -text.changelog.loading = Getting changelog... -text.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. -text.changelog.error.ios = [accent]The changelog is currently not supported in iOS. -text.changelog.error = [scarlet]Error getting changelog!\nCheck your internet connection. -text.changelog.current = [yellow][[Current version] -text.changelog.latest = [accent][[Latest version] -text.loading = [accent]Memuat... -text.saving = [accent]Saving... -text.wave = [accent]Gelombang {0} -text.wave.waiting = Gelombang dimulai {0} -text.waiting = Menunggu... -text.waiting.players = Waiting for players... -text.wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining -text.wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining -text.loadimage = Buka Gambar -text.saveimage = Simpan Gambar -text.unknown = Unknown -text.custom = Custom -text.builtin = Built-In -text.map.delete.confirm = Are you sure you want to delete this map? This action cannot be undone! -text.map.random = [accent]Random Map -text.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. -text.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. -text.map.invalid = Error loading map: corrupted or invalid map file. -text.editor.brush = Brush -text.editor.slope = \\ -text.editor.openin = Open In Editor -text.editor.oregen = Ore Generation -text.editor.oregen.info = Ore Generation: -text.editor.mapinfo = Map Info -text.editor.author = Author: -text.editor.description = Description: -text.editor.name = Name: -text.editor.teams = Teams -text.editor.elevation = Elevation -text.editor.errorimageload = Kesalahan saat memuat file gambar:\n[accent]{0} -text.editor.errorimagesave = Kesalahan saat menyimpan file gambar:\n[accent]{0} -text.editor.generate = Hasilkan -text.editor.resize = Ubah ukuran -text.editor.loadmap = Buka Peta -text.editor.savemap = Simpan Peta -text.editor.saved = Saved! -text.editor.save.noname = Your map does not have a name! Set one in the 'map info' menu. -text.editor.save.overwrite = Your map overwrites a built-in map! Pick a different name in the 'map info' menu. -text.editor.import.exists = [scarlet]Unable to import:[] a built-in map named '{0}' already exists! -text.editor.import = Import... -text.editor.importmap = Import Map -text.editor.importmap.description = Import an already existing map -text.editor.importfile = Import File -text.editor.importfile.description = Import an external map file -text.editor.importimage = Import Terrain Image -text.editor.importimage.description = Import an external map image file -text.editor.export = Export... -text.editor.exportfile = Export File -text.editor.exportfile.description = Export a map file -text.editor.exportimage = Export Terrain Image -text.editor.exportimage.description = Export a map image file -text.editor.loadimage = Buka Gambar -text.editor.saveimage = Simpan Gambar -text.editor.unsaved = [scarlet]Anda memiliki perubahan yang belum disimpan![]\nYakin ingin keluar? -text.editor.resizemap = Ubah ukuran peta -text.editor.mapname = Nama Peta: -text.editor.overwrite = [accent]Peringatan!\nIni akan mengganti peta yang ada. -text.editor.overwrite.confirm = [scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? -text.editor.selectmap = Pilih peta yang akan dimuat: -text.width = Lebar: -text.height = Tinggi: -text.menu = Menu -text.play = Main -text.load = Buka -text.save = Simpan -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Ping: {0}ms -text.language.restart = Silakan mulai ulang permainan Anda agar pengaturan bahasa mulai berlaku. -text.settings = Pengaturan -text.tutorial = Tutorial -text.editor = Pengedit -text.mapeditor = Pengedit Peta -text.donate = Sumbangkan -text.connectfail = [crimson]Gagal terhubung ke server: [accent]{0} -text.error.unreachable = Server unreachable. -text.error.invalidaddress = Invalid address. -text.error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! -text.error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! -text.error.alreadyconnected = Already connected. -text.error.mapnotfound = Map file not found! -text.error.any = Unkown network error. -text.settings.language = Bahasa -text.settings.reset = Atur ulang ke Default -text.settings.rebind = Rebind -text.settings.controls = Kontrol -text.settings.game = Permainan -text.settings.sound = Suara -text.settings.graphics = Grafis -text.settings.cleardata = Clear Game Data... -text.settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! -text.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. -text.settings.clearsectors = Clear Sectors -text.settings.clearunlocks = Clear Unlocks -text.settings.clearall = Clear All -text.paused = Jeda -text.yes = Yes -text.no = No -text.info.title = [accent]Info -text.error.title = [crimson]Telah terjadi kesalahan -text.error.crashtitle = Telah terjadi kesalahan -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = Info Blok -text.blocks.powercapacity = Kapasitas Tenaga -text.blocks.powershot = Tenaga/tembakan -text.blocks.targetsair = Targets Air -text.blocks.itemspeed = Units Moved -text.blocks.shootrange = Range -text.blocks.size = Ukuran -text.blocks.liquidcapacity = Kapasitas cairan -text.blocks.maxitemssecond = Batas barang/detik -text.blocks.powerrange = Jangkauan tenaga -text.blocks.poweruse = Power Use -text.blocks.powerdamage = Power/Damage -text.blocks.inputitemcapacity = Input Item Capacity -text.blocks.outputitemcapacity = Input Item Capacity -text.blocks.itemcapacity = Kapasitas Barang -text.blocks.basepowergeneration = Base Power Generation -text.blocks.powertransferspeed = Power Transfer -text.blocks.craftspeed = Production Speed -text.blocks.inputliquid = Cairan yang Masuk -text.blocks.inputliquidaux = Aux Liquid -text.blocks.inputitem = Barang yang Masuk -text.blocks.inputitems = Input Items -text.blocks.outputitem = Output Item -text.blocks.drilltier = Drillables -text.blocks.drillspeed = Base Drill Speed -text.blocks.liquidoutput = Liquid Output -text.blocks.liquidoutputspeed = Liquid Output Speed -text.blocks.liquiduse = Liquid Use -text.blocks.coolant = Coolant -text.blocks.coolantuse = Coolant Use -text.blocks.inputliquidfuel = Fuel Liquid -text.blocks.liquidfueluse = Liquid Fuel Use -text.blocks.boostitem = Boost Item -text.blocks.boostliquid = Boost Liquid -text.blocks.health = Darah -text.blocks.inaccuracy = Ketidaktelitian -text.blocks.shots = Tembakan -text.blocks.reload = Reload -text.blocks.inputfuel = Fuel -text.blocks.fuelburntime = Fuel Burn Time -text.blocks.inputcapacity = Kapasitas masuk -text.blocks.outputcapacity = Kapasitas keluar -text.unit.blocks = blocks -text.unit.powersecond = power units/second -text.unit.liquidsecond = liquid units/second -text.unit.itemssecond = items/second -text.unit.pixelssecond = pixels/second -text.unit.liquidunits = liquid units -text.unit.powerunits = power units -text.unit.degrees = degrees -text.unit.seconds = seconds -text.unit.items = items -text.category.general = General -text.category.power = Power -text.category.liquids = Liquids -text.category.items = Items -text.category.crafting = Crafting -text.category.shooting = Shooting -text.category.optional = Optional Enhancements +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 +link.dev-builds.description = Bentukan pengembang (kurang stabil) +link.trello.description = Papan trello resmi untuk fitur-fitur terencana +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! +highscore = [YELLOW]Rekor baru! +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: +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[]. +construction.title = Block Construction Guide +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 = Jangan tampilkan lagi di sesi berikutnya +coreattack = < Intinya sedang diserang! > +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 +newgame = New Game +none = +close = Tutup +quit = Keluar +maps = Peta +continue = Lanjutkan +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! +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.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. +server.kicked.recentKick = Kamu baru saja dikeluarkan.\nTunggu sebentar sebelum terhubung kembali. +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 +hostserver.mobile = Host\nPermainan +host = Host +hosting = [accent]Membuka server... +hosts.refresh = Segarkan +hosts.discovering = Mencari game LAN +server.refreshing = Menyegarkan server +hosts.none = [lightgray]Tidak ada game LAN yang ditemukan! +host.invalid = [scarlet]Tidak dapat terhubung ke host. +trace = Lacak Pemain +trace.playername = Nama pemain: [accent]{0} +trace.ip = IP: [accent]{0} +trace.id = ID Unik: [accent]{0} +trace.android = Klien Android: [accent]{0} +trace.modclient = Klien Khusus: [accent]{0} +trace.totalblocksbroken = Jumlah blok dihancurkan: [accent]{0} +trace.structureblocksbroken = Blok struktur dihancurkan: [accent]{0} +trace.lastblockbroken = Blok terakhir dihancurkan: [accent]{0} +trace.totalblocksplaced = Jumlah dipasang: [accent]{0} +trace.lastblockplaced = Blok terakhir dipasang: [accent]{0} +invalidid = ID klien tidak valid! Kirim laporan bug. +server.bans = Ban +server.bans.none = Tidak ada pemain di-ban! +server.admins = Admin +server.admins.none = Tidak ada admin yang ditemukan! +server.add = Tambahkan Server +server.delete = Yakin ingin menghapus server ini? +server.hostname = Host: {0} +server.edit = Sunting Server +server.outdated = [crimson]Server kedaluarsa![] +server.outdated.client = [crimson]Klien kedaluarsa![] +server.version = [lightgray]Versi: {0} +server.custombuild = [yellow]Bentukan khusus +confirmban = Apakah Anda yakin ingin melarang pemain ini? +confirmkick = Apakah Anda yakin ingin mengeluarkan pemain ini? +confirmunban = Apakah Anda yakin ingin mengizinkan pemain ini? +confirmadmin = Apakah Anda yakin ingin menjadikan pemain ini sebagai admin? +confirmunadmin = Are you sure you want to remove admin status from this player? +joingame.title = Bermain Bersama +joingame.ip = IP: +disconnect = Sambungan terputus. +disconnect.data = Failed to load world data! +connecting = [accent]Menghubungkan... +connecting.data = [accent]Memuat data level... +server.port = Port: +server.addressinuse = Alamat sudah di pakai! +server.invalidport = Nomor port salah! +server.error = [crimson]Kesalahan server hosting: [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 = Simpan Baru +save.overwrite = Yakin ingin mengganti slot simpan ini? +overwrite = Ganti +save.none = Tidak ada simpanan ditemukan! +saveload = [accent]Menyimpan... +savefail = Gagal menyimpan game! +save.delete.confirm = Yakin ingin menghapus save ini? +save.delete = Hapus +save.export = Ekspor Simpanan +save.import.invalid = [accent]Simpanan ini tidak valid! +save.import.fail = [crimson]Gagal mengimpor: [accent]{0} +save.export.fail = [crimson]Gagal mengekspor save: [accent]{0} +save.import = Impor Simpanan +save.newslot = Nama simpanan: +save.rename = Ganti nama +save.rename.text = Nama baru: +selectslot = Pilih simpanan. +slot = [accent]Slot{0} +save.corrupted = [accent]Simpanan rusak atau tidak valid! +empty = +on = Hidup +off = Mati +save.autosave = Simpan otomatis: {0} +save.map = Peta: {0} +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 +open = Buka +cancel = Batal +openlink = Buka tautan +copylink = Copy Link +back = Kembali +quit.confirm = Anda yakin ingin berhenti? +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]Memuat... +saving = [accent]Saving... +wave = [accent]Gelombang {0} +wave.waiting = Gelombang dimulai {0} +waiting = Menunggu... +waiting.players = Waiting for players... +wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining +wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining +loadimage = Buka Gambar +saveimage = Simpan Gambar +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.slope = \\ +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 = Kesalahan saat memuat file gambar:\n[accent]{0} +editor.errorimagesave = Kesalahan saat menyimpan file gambar:\n[accent]{0} +editor.generate = Hasilkan +editor.resize = Ubah ukuran +editor.loadmap = Buka Peta +editor.savemap = Simpan Peta +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 Terrain 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 = Buka Gambar +editor.saveimage = Simpan Gambar +editor.unsaved = [scarlet]Anda memiliki perubahan yang belum disimpan![]\nYakin ingin keluar? +editor.resizemap = Ubah ukuran peta +editor.mapname = Nama Peta: +editor.overwrite = [accent]Peringatan!\nIni akan mengganti peta yang ada. +editor.overwrite.confirm = [scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? +editor.selectmap = Pilih peta yang akan dimuat: +width = Lebar: +height = Tinggi: +menu = Menu +play = Main +load = Buka +save = Simpan +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0}ms +language.restart = Silakan mulai ulang permainan Anda agar pengaturan bahasa mulai berlaku. +settings = Pengaturan +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson]Gagal terhubung ke server: [accent]{0} +error.unreachable = Server unreachable. +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 = 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 +settings.controls = Kontrol +settings.game = Permainan +settings.sound = Suara +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.clearunlocks = Clear Unlocks +settings.clearall = Clear All +paused = Jeda +yes = Yes +no = No +info.title = [accent]Info +error.title = [crimson]Telah terjadi kesalahan +error.crashtitle = Telah terjadi kesalahan +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Info Blok +blocks.powercapacity = Kapasitas Tenaga +blocks.powershot = Tenaga/tembakan +blocks.targetsair = Targets Air +blocks.itemspeed = Units Moved +blocks.shootrange = Range +blocks.size = Ukuran +blocks.liquidcapacity = Kapasitas cairan +blocks.maxitemssecond = Batas barang/detik +blocks.powerrange = Jangkauan tenaga +blocks.poweruse = Power Use +blocks.powerdamage = Power/Damage +blocks.inputitemcapacity = Input Item Capacity +blocks.outputitemcapacity = Input Item Capacity +blocks.itemcapacity = Kapasitas Barang +blocks.basepowergeneration = Base Power Generation +blocks.powertransferspeed = Power Transfer +blocks.craftspeed = Production Speed +blocks.inputliquid = Cairan yang Masuk +blocks.inputliquidaux = Aux Liquid +blocks.inputitem = Barang yang Masuk +blocks.inputitems = Input Items +blocks.outputitem = Output Item +blocks.drilltier = Drillables +blocks.drillspeed = Base Drill Speed +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.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = Ketidaktelitian +blocks.shots = Tembakan +blocks.reload = Reload +blocks.inputfuel = Fuel +blocks.fuelburntime = Fuel Burn Time +blocks.inputcapacity = Kapasitas masuk +blocks.outputcapacity = Kapasitas keluar +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 +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 @@ -371,18 +379,22 @@ setting.mutemusic.name = Bisukan Musik setting.sfxvol.name = Volume Suara setting.mutesound.name = Bisukan Suara setting.crashreport.name = Send Anonymous Crash Reports -text.keybind.title = Rebind Keys +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 = gerak_x keybind.move_y.name = gerak_y keybind.select.name = pilih +keybind.pick.name = Pick Block keybind.break.name = hapus keybind.deselect.name = Deselect keybind.shoot.name = tembak @@ -401,30 +413,29 @@ 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.text.help.title = Description of modes -mode.waves.name = gelombang -mode.waves.description = the normal mode. limited resources and automatic incoming waves. +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.descrption = 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 @@ -445,6 +456,10 @@ 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.oil.name = minyak @@ -478,24 +493,29 @@ 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 -text.item.explosiveness = [LIGHT_GRAY]Explosiveness: {0} -text.item.flammability = [LIGHT_GRAY]Flammability: {0} -text.item.radioactivity = [LIGHT_GRAY]Radioactivity: {0} -text.item.fluxiness = [LIGHT_GRAY]Flux Power: {0} -text.unit.health = [LIGHT_GRAY]Health: {0} -text.unit.speed = [LIGHT_GRAY]Speed: {0} -text.mech.weapon = [LIGHT_GRAY]Weapon: {0} -text.mech.armor = [LIGHT_GRAY]Armor: {0} -text.mech.itemcapacity = [LIGHT_GRAY]Item Capacity: {0} -text.mech.minespeed = [LIGHT_GRAY]Mining Speed: {0} -text.mech.minepower = [LIGHT_GRAY]Mining Power: {0} -text.mech.ability = [LIGHT_GRAY]Ability: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]Heat Capacity: {0} -text.liquid.viscosity = [LIGHT_GRAY]Viscosity: {0} -text.liquid.temperature = [LIGHT_GRAY]Temperature: {0} +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.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.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = Metal Floor block.deepwater.name = deepwater block.water.name = water @@ -514,8 +534,8 @@ block.blackrock.name = blackrock block.icerock.name = icerock 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 @@ -548,17 +568,19 @@ 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 @@ -567,11 +589,11 @@ block.omega-mech-pad.name = Omega Mech Pad block.tau-mech-pad.name = Tau Mech Pad block.conduit.name = saluran block.mechanical-pump.name = Mechanical Pump -block.itemsource.name = Item Source -block.itemvoid.name = Item Void -block.liquidsource.name = Liquid Source -block.powervoid.name = Power Void -block.powerinfinite.name = Power Infinite +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 @@ -623,7 +645,7 @@ 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 team.blue.name = blue team.red.name = red team.orange.name = orange @@ -637,6 +659,7 @@ 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 +669,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. @@ -769,11 +796,11 @@ block.router.description = Accepts items from one direction and outputs them to 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.itemsource.description = Infinitely outputs items. Sandbox only. -block.liquidsource.description = Infinitely outputs liquids. Sandbox only. -block.itemvoid.description = Destroys any items which go into it without using power. Sandbox only. -block.powerinfinite.description = Infinitely outputs power. Sandbox only. -block.powervoid.description = Voids all power inputted into it. Sandbox only. +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. diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties index 514ff0569f..45c352c10a 100644 --- a/core/assets/bundles/bundle_it.properties +++ b/core/assets/bundles/bundle_it.properties @@ -1,351 +1,359 @@ -text.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!) -text.credits = Crediti -text.discord = Unisciti sul server discord di mindustry! -text.link.discord.description = la chatroom ufficiale del server discord di Mindustry -text.link.github.description = Codice sorgente del gioco -text.link.dev-builds.description = Build di sviluppo versioni instabili -text.link.trello.description = Scheda ufficiale trello per funzionalità pianificate -text.link.itch.io.description = pagina di itch.io con download per PC e versione web -text.link.google-play.description = Elenco di Google Play Store -text.link.wiki.description = wiki ufficiale di Mindustry -text.linkfail = Impossibile aprire il link! L'URL è stato copiato nella tua bacheca. -text.gameover = Il nucleo è stato distrutto. -text.gameover.pvp = The[accent] {0}[] team is victorious! -text.sector.gameover = Hai perso questo settore. Attaccare di nuovo? -text.sector.retry = Riprova -text.highscore = [YELLOW]Nuovo record! -text.wave.lasted = Sei sopravvissuto fino all'onda [accent]{0}[]. -text.level.highscore = Miglior punteggio: [accent]{0} -text.level.delete.title = Conferma Eliminazione -text.map.delete = Sei sicuro di voler eliminare questa mappa"[accent]{0}[]"? -text.level.select = Selezione del livello -text.level.mode = Modalità di gioco: -text.construction.desktop = Desktop controls have been changed.\nTo deselect a block or stop building, [accent]use space[]. -text.construction.title = Guida blocchi da costruzione -text.construction = Hai appena selezzionato la [accent]modalità di distruzione blocchi[].\n\nPer iniziare a piazzare, clicca in intorno appa tua navicella\nUna volta che sei soddisfatto del posizionamento, premi il conferma(✔), e la tua navicella inizierà a costruire il tutto.\n\n- [accentRimuovi i blocck[] dalla selezione cliccandoci sopra.\n- [accent]Sposta la selezione[] tenendo premuto e trascinando il tutto sullo schermo\n- [accent]Piazza i blocchi in linea[] Tenendo premuto nel punto d'inizio e poi trascinando il tutto nella direzione desiderata.\n- [accent]Cancella la selezione[] premendo la X in basso a sinistra. -text.deconstruction.title = Guida distruzione blocchi -text.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. -text.showagain = non mostrare più -text.coreattack = < Il nucleo è sotto attacco! > -text.unlocks = Sblocchi -text.savegame = Salva -text.loadgame = Carica -text.joingame = Unisciti al gioco -text.addplayers = Aggiungi/rimuovi giocatori -text.customgame = Gioco personalizzato -text.sectors = Settori -text.sector = Settori Selezionati: [LIGHT_GRAY]{0} -text.sector.time = Tempo: [LIGHT_GRAY]{0} -text.sector.deploy = Schiera -text.sector.abandon = Abandon -text.sector.abandon.confirm = Are you sure you want to abandon all progress at this sector?\nThis cannot be undone! -text.sector.resume = Riprendi -text.sector.locked = [scarlet][[Incomplete] -text.sector.unexplored = [accent][[Unexplored] -text.missions = Missions:[LIGHT_GRAY] {0} -text.mission = Mission:[LIGHT_GRAY] {0} -text.mission.main = Main Mission:[LIGHT_GRAY] {0} -text.mission.info = Mission Info -text.mission.complete = Missione completata! -text.mission.complete.body = Il settore {0},{1} è stato conquistato. -text.mission.wave = Sopravvivi a [accent]{0}/{1][] onda/e.Onda in {2} -text.mission.wave.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies -text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy -text.mission.wave.menu = Survive[accent] {0} []waves -text.mission.battle = Distruggi la base del nemico. -text.mission.resource.menu = Obtain {0} x{1} -text.mission.resource = Ottieni {0} x{1} -text.mission.block = Create {0} -text.mission.unit = Create {0} Unit -text.mission.command = Send Command {0} To Units -text.mission.linknode = Link Power Node -text.mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -text.mission.mech = Switch to mech[accent] {0}[] -text.mission.create = Create[accent] {0}[] -text.none = -text.close = Chiuso -text.quit = Esci -text.maps = Mappe -text.continue = Continua -text.nextmission = Missione successiva -text.maps.none = [LIGHT_GRAY]Nessuna mappa trovata! -text.about.button = Info -text.name = Nome: -text.filename = File Name: -text.unlocked = Nuovo blocco scoperto! -text.unlocked.plural = Nuovi blocchi scoperti! -text.players = {0} giocatori online -text.players.single = {0} giocatori online -text.server.closing = [accent]Chiusura server ... -text.server.kicked.kick = Sei stato cacciato dal server! -text.server.kicked.serverClose = Server chiuso. -text.server.kicked.sectorComplete = Settore completato. -text.server.kicked.sectorComplete.text = La tua misione è completata.\nOra il server continuerà al settore successivo. -text.server.kicked.clientOutdated = Versione del client obsoleta! Aggiorna il tuo gioco! -text.server.kicked.serverOutdated = Server obsoleto! Chiedi all'host di aggiornare! -text.server.kicked.banned = Sei bannato da questo server. -text.server.kicked.recentKick = Sei stato cacciato di recente.\nAspetta prima di riconnetterti. -text.server.kicked.nameInUse = C'è già qualcuno con il tuo nome\nsu questo server. -text.server.kicked.nameEmpty = Il tuo nome deve contenere almeno un carattere. -text.server.kicked.idInUse = Sei già su questo server! Non è permesso connettersi con due account. -text.server.kicked.customClient = Questo server non supporta le build personalizzate. Scarica la versione ufficiale dal sito. -text.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. -text.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. -text.hostserver = Host Server -text.hostserver.mobile = Host\nGame -text.host = Host -text.hosting = [accent] Apertura del server ... -text.hosts.refresh = Aggiorna -text.hosts.discovering = Ricerca partite LAN -text.server.refreshing = Aggiornamento del server -text.hosts.none = [lightgray]Nessuna partita LAN trovata! -text.host.invalid = [scarlet]Impossibile connettersi all'host. -text.trace = Trace Player -text.trace.playername = Nome del giocatore: [accent]{0} -text.trace.ip = IP: [accent]{0} -text.trace.id = ID univoco: [accent]{0} -text.trace.android = Client Android: [accent] {0} -text.trace.modclient = Client personalizzato: [accent]{0} -text.trace.totalblocksbroken = Totale blocchi distrutti: [accent]{0} -text.trace.structureblocksbroken = Blocchi strutturali distrutti: [accent]{0} -text.trace.lastblockbroken = Ultimo blocco distrutto: [accent]{0} -text.trace.totalblocksplaced = Totale blocchi posizionati: [accent]{0} -text.trace.lastblockplaced = Ultimo blocco posizionato: [accent]{0} -text.invalidid = ID client non valido! Invia una segnalazione di bug. -text.server.bans = Lista Ban -text.server.bans.none = Nessun giocatore bandito trovato! Finora tutto liscio. -text.server.admins = Amministratori -text.server.admins.none = Nessun amministratore trovato! -text.server.add = Aggiungi server -text.server.delete = Sei sicuro di voler eliminare questo server? -text.server.hostname = Host: {0} -text.server.edit = Modifica server -text.server.outdated = [crimson]Server obsoleto![] -text.server.outdated.client = [crimson]Client obsoleto![] -text.server.version = [lightgray]Versione: {0} -text.server.custombuild = [yellow] Costruzione personalizzata -text.confirmban = Sei sicuro di voler bandire questo giocatore? -text.confirmkick = Are you sure you want to kick this player? -text.confirmunban = Sei sicuro di voler riammettere questo giocatore? -text.confirmadmin = Sei sicuro di voler rendere questo giocatore un amministratore? -text.confirmunadmin = Sei sicuro di voler rimuovere lo stato di amministratore da questo giocatore? -text.joingame.title = Unisciti alla Partita -text.joingame.ip = IP: -text.disconnect = Disconnesso. -text.disconnect.data = Il mondo non si vuole caricare, mi dispiace! -text.connecting = [accent]Connessione in corso ... -text.connecting.data = [accent]Caricamento dei dati del mondo ... -text.server.port = Porta: -text.server.addressinuse = Indirizzo già in uso! -text.server.invalidport = Numero di porta non valido! -text.server.error = [crimson]Errore nell'hosting del server: [accent] {0} -text.save.old = Questo salvataggio è per una versione precedente di mindustry e non può attualmente essere utilizzato .\n\n[LIGHT_GRAY]La cvompatibilità con i salvataggi precedenti verrà abilitata nella versione definitiva di mindustry 4.0. -text.save.new = Nuovo Salvataggio -text.save.overwrite = Sei sicuro di voler sovrascrivere questo salvataggio? -text.overwrite = Sovrascrivi -text.save.none = Nessun salvataggio trovato! -text.saveload = [Accent]Salvataggio ... -text.savefail = Salvataggio del gioco non riuscito! -text.save.delete.confirm = Sei sicuro di voler eliminare questo salvataggio? -text.save.delete = Elimina -text.save.export = Esporta Salvataggio -text.save.import.invalid = [accent]Questo salvataggio non è valido! -text.save.import.fail = [crimson]Impossibile importare salvataggio: [accent]{0} -text.save.export.fail = [crimson]Impossibile esportare il salvataggio: [accent]{0} -text.save.import = Importa Salvataggio -text.save.newslot = Salva nome: -text.save.rename = Rinomina -text.save.rename.text = Nuovo nome: -text.selectslot = Seleziona un salvataggio. -text.slot = [accent]Slot {0} -text.save.corrupted = [orang]Salvataggio corrotto o non valido! -text.sector.corrupted = [accent]Un file per questo settore è stato trovato, ma è fallito il caricamnto.\nQuindi ne è stato creato uno nuovo. -text.empty = -text.on = On -text.off = Off -text.save.autosave = Salvataggio automatico: {0} -text.save.map = Mappa: {0} -text.save.wave = Ondata: {0} -text.save.difficulty = Difficoltà: {0} -text.save.date = Ultimo salvataggio: {0} -text.save.playtime = Tempo di gioco: {0} -text.confirm = Conferma -text.delete = Elimina -text.ok = OK -text.open = Apri -text.cancel = Annulla -text.openlink = Apri Link -text.copylink = Copia link -text.back = Indietro -text.quit.confirm = Sei sicuro di voler uscire? -text.changelog.title = Registro modifiche -text.changelog.loading = Ottenendo il registro delle modifiche ... -text.changelog.error.android = [accent]Nota che il registro delle modifiche non funziona su Android 4.4 e versioni precedenti! Ciò è dovuto a un bug interno di Android. -text.changelog.error.ios = [accent]Il registro delle modifiche non è ancora supportato su IoS -text.changelog.error = [scarlet]Errore durante il recupero del registro delle modifiche! Controlla la tua connessione Internet. -text.changelog.current = [yellow][[Current version] -text.changelog.latest = [accent][[Latest version] -text.loading = [accent]Caricamento in corso ... -text.saving = [accent]Salvando . . . -text.wave = [accent]Ondata {0} -text.wave.waiting = Ondata in {0} -text.waiting = In attesa... -text.waiting.players = Waiting for players... -text.wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining -text.wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining -text.loadimage = Carica immagine -text.saveimage = Salva Immagine -text.unknown = Sconosciuto -text.custom = Personalizzato -text.builtin = Incluso -text.map.delete.confirm = Sei sicuro di voler eliminare questa mappa? Non potrai tornare indietro! -text.map.random = [accent]Mappa casuale -text.map.nospawn = Questa mappa non possiede un nucleo dove spawnare! Aggiungine uno nell'editor. -text.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. -text.map.invalid = Errore nel caricamento della mappa: file mappa corrotto o non valido. -text.editor.brush = Pennello -text.editor.slope = \\ -text.editor.openin = Apri nell'editor -text.editor.oregen = Generazione dei minerali -text.editor.oregen.info = Generazione dei minerali: -text.editor.mapinfo = Informazioni mappa -text.editor.author = Autore: -text.editor.description = Descrizione: -text.editor.name = Nome: -text.editor.teams = Squadre -text.editor.elevation = Elevazione -text.editor.errorimageload = Errore durante il caricamento del file immagine:\n [accent]{0} -text.editor.errorimagesave = Errore durante il salvataggio del file immagine:\n [accent]{0} -text.editor.generate = Genera -text.editor.resize = Ridimensiona -text.editor.loadmap = Carica\nmappa -text.editor.savemap = Salva\nla mappa -text.editor.saved = Salvato! -text.editor.save.noname = La tua mappa non ha un nome! Impostane uno nelle informazioni della mappa. -text.editor.save.overwrite = La tua mappa sovrascrive quelle incluse! Imposta un nome diverso nelle informazioni della mappa. -text.editor.import.exists = [scarlet]Impossibile importare:[] esiste già una mappa chiamata '{0}' che non può essere svrascritta! -text.editor.import = Importando... -text.editor.importmap = Importa mappa -text.editor.importmap.description = Importa mappa preesistente -text.editor.importfile = Importa file -text.editor.importfile.description = Importa un file mappa esterno -text.editor.importimage = Importa mappa terreno -text.editor.importimage.description = Importa immagine esterna terreno -text.editor.export = Esportazione... -text.editor.exportfile = Esporta file -text.editor.exportfile.description = Esporta file mappa -text.editor.exportimage = Esporta immagine terreno -text.editor.exportimage.description = Esporta file immagine mappa -text.editor.loadimage = Carica\nimmagine -text.editor.saveimage = Salva\nImmagine -text.editor.unsaved = [scarlet]Hai modifiche non salvate![]\nSei sicuro di voler uscire? -text.editor.resizemap = Ridimensiona la mappa -text.editor.mapname = Nome Mappa: -text.editor.overwrite = [Accent]Attenzione!\nQuesto sovrascrive una mappa esistente. -text.editor.overwrite.confirm = [scarlet]Attenzione![] Una mappa con questo nome esiste già. Sei sicuro di volerla sovrascrivere? -text.editor.selectmap = Seleziona una mappa da caricare: -text.width = Larghezza: -text.height = Altezza: -text.menu = Menu -text.play = Gioca -text.load = Carica -text.save = Salva -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Ping: {0}ms -text.language.restart = Riavvia il gioco affinché il cambiamento della lingua abbia effetto. -text.settings = Impostazioni -text.tutorial = Tutorial -text.editor = Editor -text.mapeditor = Editor Mappe -text.donate = Dona -text.connectfail = [crimson] Impossibile connettersi al server: [accent] {0} -text.error.unreachable = Server unreachable. -text.error.invalidaddress = Invalid address. -text.error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! -text.error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! -text.error.alreadyconnected = Already connected. -text.error.mapnotfound = Map file not found! -text.error.any = Unkown network error. -text.settings.language = Lingua -text.settings.reset = Resetta Alle Impostazioni Predefinite -text.settings.rebind = Reinposta -text.settings.controls = Controlli -text.settings.game = Gioco -text.settings.sound = Suono -text.settings.graphics = Grafica -text.settings.cleardata = Clear Game Data... -text.settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! -text.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. -text.settings.clearsectors = Clear Sectors -text.settings.clearunlocks = Clear Unlocks -text.settings.clearall = Clear All -text.paused = In pausa -text.yes = Si -text.no = No -text.info.title = [accent] Info -text.error.title = [crimson]Si è verificato un errore -text.error.crashtitle = Si è verificato un errore -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = info sul blocco -text.blocks.powercapacity = Capacità Energetica -text.blocks.powershot = Danno/Colpo -text.blocks.targetsair = Attacca nemici aerei -text.blocks.itemspeed = Unità spostate -text.blocks.shootrange = Raggio -text.blocks.size = Grandezza -text.blocks.liquidcapacity = Capacità del liquido -text.blocks.maxitemssecond = Oggetti massimi/secondo -text.blocks.powerrange = Raggio Energia -text.blocks.poweruse = Utilizzo energia -text.blocks.powerdamage = Power/Damage -text.blocks.inputitemcapacity = Capacità oggetti in entrata -text.blocks.outputitemcapacity = Capacità oggetti in uscità -text.blocks.itemcapacity = Capacità -text.blocks.basepowergeneration = Base Power Generation -text.blocks.powertransferspeed = Velocità trasferimento energia -text.blocks.craftspeed = Velocità produzione -text.blocks.inputliquid = Input del liquido -text.blocks.inputliquidaux = Liquidi extra -text.blocks.inputitem = Input Oggetto -text.blocks.inputitems = Oggetti in entrata -text.blocks.outputitem = Oggetti in uscita -text.blocks.drilltier = Scavabili -text.blocks.drillspeed = Velocità scavo stbile -text.blocks.liquidoutput = Uscita liquidi -text.blocks.liquidoutputspeed = Liquid Output Speed -text.blocks.liquiduse = Uso liquidi -text.blocks.coolant = Refrigerante -text.blocks.coolantuse = uso refrigerante -text.blocks.inputliquidfuel = carburante liquido -text.blocks.liquidfueluse = Utilizzo carburante liquido -text.blocks.boostitem = Boost Item -text.blocks.boostliquid = Boost Liquid -text.blocks.health = Salute -text.blocks.inaccuracy = Inaccuratezza -text.blocks.shots = Colpi -text.blocks.reload = Ricarica -text.blocks.inputfuel = Carburante -text.blocks.fuelburntime = Tempo combustione carburante -text.blocks.inputcapacity = Capacità di ingresso -text.blocks.outputcapacity = Capacità di uscita -text.unit.blocks = blocchi -text.unit.powersecond = unità energia/secondo -text.unit.liquidsecond = unità liquide/secondo -text.unit.itemssecond = oggetti/secondo -text.unit.pixelssecond = pixel/secondo -text.unit.liquidunits = unità liquidi -text.unit.powerunits = unità energia -text.unit.degrees = gradi -text.unit.seconds = secondi -text.unit.items = oggetti -text.category.general = Generali -text.category.power = Energia -text.category.liquids = Liquidi -text.category.items = Oggetti -text.category.crafting = Produzione -text.category.shooting = Potenza di fuoco -text.category.optional = Optional Enhancements +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 +link.dev-builds.description = Build di sviluppo versioni instabili +link.trello.description = Scheda ufficiale trello per funzionalità pianificate +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! +highscore = [YELLOW]Nuovo record! +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: +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[]. +construction.title = Guida blocchi da costruzione +construction = Hai appena selezzionato la [accent]modalità di distruzione blocchi[].\n\nPer iniziare a piazzare, clicca in intorno appa tua navicella\nUna volta che sei soddisfatto del posizionamento, premi il conferma(✔), e la tua navicella inizierà a costruire il tutto.\n\n- [accentRimuovi i blocck[] dalla selezione cliccandoci sopra.\n- [accent]Sposta la selezione[] tenendo premuto e trascinando il tutto sullo schermo\n- [accent]Piazza i blocchi in linea[] Tenendo premuto nel punto d'inizio e poi trascinando il tutto nella direzione desiderata.\n- [accent]Cancella la selezione[] premendo la X in basso a sinistra. +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! > +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 +newgame = New Game +none = +close = Chiuso +quit = Esci +maps = Mappe +continue = Continua +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! +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.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. +server.kicked.recentKick = Sei stato cacciato di recente.\nAspetta prima di riconnetterti. +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 +hostserver.mobile = Host\nGame +host = Host +hosting = [accent] Apertura del server ... +hosts.refresh = Aggiorna +hosts.discovering = Ricerca partite LAN +server.refreshing = Aggiornamento del server +hosts.none = [lightgray]Nessuna partita LAN trovata! +host.invalid = [scarlet]Impossibile connettersi all'host. +trace = Trace Player +trace.playername = Nome del giocatore: [accent]{0} +trace.ip = IP: [accent]{0} +trace.id = ID univoco: [accent]{0} +trace.android = Client Android: [accent] {0} +trace.modclient = Client personalizzato: [accent]{0} +trace.totalblocksbroken = Totale blocchi distrutti: [accent]{0} +trace.structureblocksbroken = Blocchi strutturali distrutti: [accent]{0} +trace.lastblockbroken = Ultimo blocco distrutto: [accent]{0} +trace.totalblocksplaced = Totale blocchi posizionati: [accent]{0} +trace.lastblockplaced = Ultimo blocco posizionato: [accent]{0} +invalidid = ID client non valido! Invia una segnalazione di bug. +server.bans = Lista Ban +server.bans.none = Nessun giocatore bandito trovato! Finora tutto liscio. +server.admins = Amministratori +server.admins.none = Nessun amministratore trovato! +server.add = Aggiungi server +server.delete = Sei sicuro di voler eliminare questo server? +server.hostname = Host: {0} +server.edit = Modifica server +server.outdated = [crimson]Server obsoleto![] +server.outdated.client = [crimson]Client obsoleto![] +server.version = [lightgray]Versione: {0} +server.custombuild = [yellow] Costruzione personalizzata +confirmban = Sei sicuro di voler bandire questo giocatore? +confirmkick = Are you sure you want to kick this player? +confirmunban = Sei sicuro di voler riammettere questo giocatore? +confirmadmin = Sei sicuro di voler rendere questo giocatore un amministratore? +confirmunadmin = Sei sicuro di voler rimuovere lo stato di amministratore da questo giocatore? +joingame.title = Unisciti alla Partita +joingame.ip = IP: +disconnect = Disconnesso. +disconnect.data = Il mondo non si vuole caricare, mi dispiace! +connecting = [accent]Connessione in corso ... +connecting.data = [accent]Caricamento dei dati del mondo ... +server.port = Porta: +server.addressinuse = Indirizzo già in uso! +server.invalidport = Numero di porta non valido! +server.error = [crimson]Errore nell'hosting del server: [accent] {0} +save.old = Questo salvataggio è per una versione precedente di mindustry e non può attualmente essere utilizzato .\n\n[LIGHT_GRAY]La cvompatibilità con i salvataggi precedenti verrà abilitata nella versione definitiva di mindustry 4.0. +save.new = Nuovo Salvataggio +save.overwrite = Sei sicuro di voler sovrascrivere questo salvataggio? +overwrite = Sovrascrivi +save.none = Nessun salvataggio trovato! +saveload = [Accent]Salvataggio ... +savefail = Salvataggio del gioco non riuscito! +save.delete.confirm = Sei sicuro di voler eliminare questo salvataggio? +save.delete = Elimina +save.export = Esporta Salvataggio +save.import.invalid = [accent]Questo salvataggio non è valido! +save.import.fail = [crimson]Impossibile importare salvataggio: [accent]{0} +save.export.fail = [crimson]Impossibile esportare il salvataggio: [accent]{0} +save.import = Importa Salvataggio +save.newslot = Salva nome: +save.rename = Rinomina +save.rename.text = Nuovo nome: +selectslot = Seleziona un salvataggio. +slot = [accent]Slot {0} +save.corrupted = [orang]Salvataggio corrotto o non valido! +empty = +on = On +off = Off +save.autosave = Salvataggio automatico: {0} +save.map = Mappa: {0} +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 +open = Apri +cancel = Annulla +openlink = Apri Link +copylink = Copia link +back = Indietro +quit.confirm = Sei sicuro di voler uscire? +changelog.title = Registro modifiche +changelog.loading = Ottenendo il registro delle modifiche ... +changelog.error.android = [accent]Nota che il registro delle modifiche non funziona su Android 4.4 e versioni precedenti! Ciò è dovuto a un bug interno di Android. +changelog.error.ios = [accent]Il registro delle modifiche non è ancora supportato su IoS +changelog.error = [scarlet]Errore durante il recupero del registro delle modifiche! Controlla la tua connessione Internet. +changelog.current = [yellow][[Current version] +changelog.latest = [accent][[Latest version] +loading = [accent]Caricamento in corso ... +saving = [accent]Salvando . . . +wave = [accent]Ondata {0} +wave.waiting = Ondata in {0} +waiting = In attesa... +waiting.players = Waiting for players... +wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining +wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining +loadimage = Carica immagine +saveimage = Salva Immagine +unknown = Sconosciuto +custom = Personalizzato +builtin = Incluso +map.delete.confirm = Sei sicuro di voler eliminare questa mappa? Non potrai tornare indietro! +map.random = [accent]Mappa casuale +map.nospawn = Questa mappa non possiede un nucleo dove spawnare! Aggiungine uno nell'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 = 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: +editor.mapinfo = Informazioni mappa +editor.author = Autore: +editor.description = Descrizione: +editor.name = Nome: +editor.teams = Squadre +editor.elevation = Elevazione +editor.errorimageload = Errore durante il caricamento del file immagine:\n [accent]{0} +editor.errorimagesave = Errore durante il salvataggio del file immagine:\n [accent]{0} +editor.generate = Genera +editor.resize = Ridimensiona +editor.loadmap = Carica\nmappa +editor.savemap = Salva\nla mappa +editor.saved = Salvato! +editor.save.noname = La tua mappa non ha un nome! Impostane uno nelle informazioni della mappa. +editor.save.overwrite = La tua mappa sovrascrive quelle incluse! Imposta un nome diverso nelle informazioni della mappa. +editor.import.exists = [scarlet]Impossibile importare:[] esiste già una mappa chiamata '{0}' che non può essere svrascritta! +editor.import = Importando... +editor.importmap = Importa mappa +editor.importmap.description = Importa mappa preesistente +editor.importfile = Importa file +editor.importfile.description = Importa un file mappa esterno +editor.importimage = Importa mappa terreno +editor.importimage.description = Importa immagine esterna terreno +editor.export = Esportazione... +editor.exportfile = Esporta file +editor.exportfile.description = Esporta file mappa +editor.exportimage = Esporta immagine terreno +editor.exportimage.description = Esporta file immagine mappa +editor.loadimage = Carica\nimmagine +editor.saveimage = Salva\nImmagine +editor.unsaved = [scarlet]Hai modifiche non salvate![]\nSei sicuro di voler uscire? +editor.resizemap = Ridimensiona la mappa +editor.mapname = Nome Mappa: +editor.overwrite = [Accent]Attenzione!\nQuesto sovrascrive una mappa esistente. +editor.overwrite.confirm = [scarlet]Attenzione![] Una mappa con questo nome esiste già. Sei sicuro di volerla sovrascrivere? +editor.selectmap = Seleziona una mappa da caricare: +width = Larghezza: +height = Altezza: +menu = Menu +play = Gioca +load = Carica +save = Salva +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0}ms +language.restart = Riavvia il gioco affinché il cambiamento della lingua abbia effetto. +settings = Impostazioni +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson] Impossibile connettersi al server: [accent] {0} +error.unreachable = Server unreachable. +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 = 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 +settings.controls = Controlli +settings.game = Gioco +settings.sound = Suono +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.clearunlocks = Clear Unlocks +settings.clearall = Clear All +paused = In pausa +yes = Si +no = No +info.title = [accent] Info +error.title = [crimson]Si è verificato un errore +error.crashtitle = Si è verificato un errore +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = info sul blocco +blocks.powercapacity = Capacità Energetica +blocks.powershot = Danno/Colpo +blocks.targetsair = Attacca nemici aerei +blocks.itemspeed = Unità spostate +blocks.shootrange = Raggio +blocks.size = Grandezza +blocks.liquidcapacity = Capacità del liquido +blocks.maxitemssecond = Oggetti massimi/secondo +blocks.powerrange = Raggio Energia +blocks.poweruse = Utilizzo energia +blocks.powerdamage = Power/Damage +blocks.inputitemcapacity = Capacità oggetti in entrata +blocks.outputitemcapacity = Capacità oggetti in uscità +blocks.itemcapacity = Capacità +blocks.basepowergeneration = Base Power Generation +blocks.powertransferspeed = Velocità trasferimento energia +blocks.craftspeed = Velocità produzione +blocks.inputliquid = Input del liquido +blocks.inputliquidaux = Liquidi extra +blocks.inputitem = Input Oggetto +blocks.inputitems = Oggetti in entrata +blocks.outputitem = Oggetti in uscita +blocks.drilltier = Scavabili +blocks.drillspeed = Velocità scavo stbile +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.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = Inaccuratezza +blocks.shots = Colpi +blocks.reload = Ricarica +blocks.inputfuel = Carburante +blocks.fuelburntime = Tempo combustione carburante +blocks.inputcapacity = Capacità di ingresso +blocks.outputcapacity = Capacità di uscita +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 +unit.seconds = secondi +unit.items = oggetti +category.general = Generali +category.power = Energia +category.liquids = Liquidi +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 @@ -371,18 +379,22 @@ setting.mutemusic.name = Silenzia musica setting.sfxvol.name = Volume SFX setting.mutesound.name = Togli suoni setting.crashreport.name = Send Anonymous Crash Reports -text.keybind.title = Configurazione Tasti +keybind.title = Configurazione Tasti category.general.name = Generale category.view.name = Visualizzazione 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.pick.name = Pick Block keybind.break.name = rompi keybind.deselect.name = Deselect keybind.shoot.name = spara @@ -401,30 +413,29 @@ keybind.chat_history_next.name = Scorri chatt verso il basso keybind.chat_scroll.name = Scorri chat keybind.drop_unit.name = droppa materiali keybind.zoom_minimap.name = Zomma minimappa -mode.text.help.title = Descrizione delle modalità -mode.waves.name = ondate -mode.waves.description = modalità normale. risorse limitate e ondate automatiche. +mode.help.title = Descrizione delle modalità +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.descrption = 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 @@ -445,6 +456,10 @@ 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.oil.name = petrolio @@ -478,24 +493,29 @@ mech.trident-ship.weapon = Valle delle bombe mech.glaive-ship.name = Glaive mech.glaive-ship.description = Una grande e ben armata macchina da guerra. Equipaggiato con ripetitore di fiamma e con alta accellerazione e velocità massima. mech.glaive-ship.weapon = Ripetitore di fiamma -text.item.explosiveness = [LIGHT_GRAY]Esplosività: {0} -text.item.flammability = [LIGHT_GRAY]Infiammabilità: {0} -text.item.radioactivity = [LIGHT_GRAY]Radioattività: {0} -text.item.fluxiness = [LIGHT_GRAY]Portata: {0} -text.unit.health = [LIGHT_GRAY]Vita: {0} -text.unit.speed = [LIGHT_GRAY]Velocità: {0} -text.mech.weapon = [LIGHT_GRAY]Armi: {0} -text.mech.armor = [LIGHT_GRAY]Protezione: {0} -text.mech.itemcapacity = [LIGHT_GRAY]Capacità oggetti: {0} -text.mech.minespeed = [LIGHT_GRAY]Velocità di scavo: {0} -text.mech.minepower = [LIGHT_GRAY]Potenza di scavo: {0} -text.mech.ability = [LIGHT_GRAY]Abilità: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]Capacità calorifica: {0} -text.liquid.viscosity = [LIGHT_GRAY]Viscosità: {0} -text.liquid.temperature = [LIGHT_GRAY]Temperatura: {0} +item.explosiveness = [LIGHT_GRAY]Esplosività: {0} +item.flammability = [LIGHT_GRAY]Infiammabilità: {0} +item.radioactivity = [LIGHT_GRAY]Radioattività: {0} +unit.health = [LIGHT_GRAY]Vita: {0} +unit.speed = [LIGHT_GRAY]Velocità: {0} +mech.weapon = [LIGHT_GRAY]Armi: {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} +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.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.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = Pavimento di ferro block.deepwater.name = acqua profonda block.water.name = acqua @@ -514,8 +534,8 @@ block.blackrock.name = roccia nera block.icerock.name = roccia di ghiaccio 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 @@ -548,17 +568,19 @@ 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 @@ -567,11 +589,11 @@ block.omega-mech-pad.name = Omega Mech Pad block.tau-mech-pad.name = Tau Mech Pad block.conduit.name = Condotto block.mechanical-pump.name = Pompa meccanica -block.itemsource.name = Sorgente oggetti -block.itemvoid.name = Vuoto oggetti -block.liquidsource.name = Sorgente liquida -block.powervoid.name = Energia nulla -block.powerinfinite.name = Energia infinita +block.item-source.name = Sorgente oggetti +block.item-void.name = Vuoto oggetti +block.liquid-source.name = Sorgente liquida +block.power-void.name = Energia nulla +block.power-source.name = Energia infinita block.unloader.name = Scaricatore block.vault.name = Deposito block.wave.name = Idrogetto @@ -623,7 +645,7 @@ 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 team.blue.name = blue team.red.name = red team.orange.name = orange @@ -637,6 +659,7 @@ 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 +669,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. @@ -769,11 +796,11 @@ block.router.description = Accepts items from one direction and outputs them to 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.itemsource.description = Infinitely outputs items. Sandbox only. -block.liquidsource.description = Infinitely outputs liquids. Sandbox only. -block.itemvoid.description = Destroys any items which go into it without using power. Sandbox only. -block.powerinfinite.description = Infinitely outputs power. Sandbox only. -block.powervoid.description = Voids all power inputted into it. Sandbox only. +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. diff --git a/core/assets/bundles/bundle_ja.properties b/core/assets/bundles/bundle_ja.properties index ad32034bc4..71fbbd507e 100644 --- a/core/assets/bundles/bundle_ja.properties +++ b/core/assets/bundles/bundle_ja.properties @@ -1,3 +1,4 @@ +<<<<<<< HEAD text.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!) text.credits = クレジット text.contributors = 翻訳や協力してくださった方々 @@ -349,6 +350,363 @@ text.category.items = アイテム text.category.crafting = 製作速度 text.category.shooting = 攻撃速度 text.category.optional = 機能強化オプション +======= +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 = DiscordのMindustryに参加! +link.discord.description = Mindustryの公式Discordグループ +link.github.description = ゲームのソースコード +link.dev-builds.description = 不安定な開発ビルド +link.trello.description = 公式 Trelloボード の実装予定の機能をチェック +link.itch.io.description = itch.ioでPC版のダウンロードやweb版をプレイ +link.google-play.description = Google Playのストア +link.wiki.description = 公式 Mindustry Wiki +linkfail = リンクを開けませんでした!\nURLをクリップボードにコピーしました。 +screenshot = スクリーンショットを {0} に保存しました。 +gameover = ゲームオーバー +gameover.pvp = [accent] {0}[] チームの勝利! +highscore = [accent]ハイスコアを記録! +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: +map.delete = マップ "[accent]{0}[]" を削除してもよろしいですか? +level.highscore = ハイスコア: [accent]{0} +level.select = レベル選択 +level.mode = ゲームモード: +construction.desktop = ブロックの選択や建設を止めるには、[accent]スペースを使用[]してください。 +construction.title = ブロック建設ガイド +construction = [accent]ブロック建設モード[]になりました。\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 ボタンを押してください。 +showagain = 次回以降表示しない +coreattack = < コアが攻撃を受けています! > +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 = カスタムゲーム +newgame = New Game +none = <なし> +close = 閉じる +quit = 終了 +maps = マップ +continue = 続ける +maps.none = [LIGHT_GRAY]マップが存在しません! +about.button = About +name = 名前: +noname = 先に[accent]プレイヤー名[]を決めてください。 +filename = ファイル名: +unlocked = 新しいブロックをアンロック! +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.clientOutdated = 古いクライアントです! ゲームをアップデートしてください! +server.kicked.serverOutdated = 古いサーバーです! ホストに更新してもらってください! +server.kicked.banned = サーバーからBanされています。 +server.kicked.recentKick = 直前にキックされています。\nもう一度接続できるまでお待ちください。 +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 = ゲームをホスト +hostserver.mobile = ホスト +host = ホスト +hosting = [accent]サーバーを開いています... +hosts.refresh = リフレッシュ +hosts.discovering = LAN上のサーバーを探しています +server.refreshing = サーバーをリフレッシュ +hosts.none = [lightgray]ローカルゲームが見つかりません! +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です! バグ報告してください。 +server.bans = Ban +server.bans.none = Banされたプレイヤーはいません! +server.admins = 管理者 +server.admins.none = 管理者はいません! +server.add = サーバーを追加 +server.delete = サーバーを削除しますか? +server.hostname = ホスト: {0} +server.edit = サーバーを編集 +server.outdated = [crimson]古いサーバー![] +server.outdated.client = [crimson]古いクライアント![] +server.version = [lightgray]バージョン: {0} {1} +server.custombuild = [yellow]カスタムビルド +confirmban = このプレイヤーを Ban しますか? +confirmkick = このプレイヤーをキックしますか? +confirmunban = このプレイヤーの Ban を解除しますか? +confirmadmin = このプレイヤーを管理者にしますか? +confirmunadmin = このプレイヤーを管理者から削除しますか? +joingame.title = サーバーに参加 +joingame.ip = アドレス: +disconnect = 接続が切断されました。 +disconnect.data = ワールドデータの読み込みに失敗しました! +connecting = [accent]接続中... +connecting.data = [accent]ワールドデータを読み込んでいます... +server.port = ポート: +server.addressinuse = アドレスがすでに使用されています。! +server.invalidport = 無効なポート番号です。! +server.error = [crimson]サーバーエラー: [accent]{0} +save.old = これは古いバージョンのセーブデータで、使用することができません。\n\n[LIGHT_GRAY]下位互換性の実装は正式版の4.0行われます。 +save.new = 新しく保存 +save.overwrite = このスロットに上書きしてよろしいですか? +overwrite = 上書き +save.none = セーブデータがありません! +saveload = [accent]セーブしています... +savefail = ゲームの保存に失敗しました。! +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 = セーブデータを読み込む +save.newslot = セーブデータ名: +save.rename = リネーム +save.rename.text = 新しい名前: +selectslot = セーブデータを選択 +slot = [accent]スロット {0} +save.corrupted = [accent]セーブファイルが無効、または破損しました!\nゲームのアップデート直後の場合、恐らくセーブデータのフォーマットの変更によるもので、バグではありません。 +empty = <空> +on = オン +off = オフ +save.autosave = 自動保存: {0} +save.map = マップ: {0} +save.wave = ウェーブ {0} +save.difficulty = 難易度: {0} +save.date = 最終保存: {0} +save.playtime = プレイ時間: {0} +warning = Warning. +confirm = 確認 +delete = 削除 +ok = OK +open = 開く +cancel = キャンセル +openlink = リンクを開く +copylink = リンクをコピー +back = 戻る +quit.confirm = 終了してもよろしいですか? +changelog.title = 変更履歴 +changelog.loading = 変更履歴を取得しています... +changelog.error.android = [accent]Android4.4または、それ以下では変更履歴が動作しない場合があります。!\nこれはAndroidの内部バグによるものです。 +changelog.error.ios = [accent]iOSは変更履歴に対応していません。 +changelog.error = [scarlet]変更履歴の取得エラー!\nインターネット接続を確認してください。 +changelog.current = [yellow][[現在のバージョン] +changelog.latest = [accent][[最新バージョン] +loading = [accent]読み込み中... +saving = [accent]保存中... +wave = [accent]ウェーブ {0} +wave.waiting = [LIGHT_GRAY]次のウェーブまで {0} 秒 +waiting = [LIGHT_GRAY]待機中... +waiting.players = プレイヤーを待っています... +wave.enemies = [LIGHT_GRAY]残り {0} 体 +wave.enemy = [LIGHT_GRAY]残り {0} 体 +loadimage = イメージを読み込む +saveimage = イメージを保存 +unknown = 不明 +custom = カスタム +builtin = 組み込み +map.delete.confirm = マップを削除してもよろしいですか? これは戻すことができません! +map.random = [accent]ランダムマップ +map.nospawn = このマップにはスポーンするためのプレイヤーのコアがありません! [ROYAL]青い[]コアをエディターでマップに追加してください。 +map.nospawn.pvp = このマップには敵がスポーンするためのプレイヤーのコアがありません! [SCARLET]赤い[]コアをエディターでマップに追加してください。 +map.invalid = マップの読み込みエラー: ファイルが無効、または破損しています。 +editor.brush = ブラシ +editor.slope = \\ +editor.openin = エディターで開く +editor.oregen = 鉱石の生成 +editor.oregen.info = 鉱石の生成: +editor.mapinfo = マップ情報 +editor.author = 作者: +editor.description = 説明: +editor.name = 名前: +editor.teams = チーム +editor.elevation = 標高 +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.import = インポート... +editor.importmap = マップをインポート +editor.importmap.description = すでに存在しているマップをインポート +editor.importfile = ファイルをインポート +editor.importfile.description = 外部マップファイルをインポート +editor.importimage = 古いイメージをインポート +editor.importimage.description = 外部イメージファイルをインポート +editor.export = エクスポート... +editor.exportfile = ファイルをエクスポート +editor.exportfile.description = マップファイルをエクスポート +editor.exportimage = 地形イメージをエクスポート +editor.exportimage.description = イメージファイルをエクスポート +editor.loadimage = 地形をインポート +editor.saveimage = 地形をエクスポート +editor.unsaved = [scarlet]保存されていない変更があります![]\n終了してもよろしいですか? +editor.resizemap = マップをリサイズ +editor.mapname = マップ名: +editor.overwrite = [accent]警告!\n存在するマップを上書きします。 +editor.overwrite.confirm = [scarlet]警告![] この名前のマップがすでに存在します。上書きしてもよろしいですか? +editor.selectmap = 読み込むマップを選択: +width = 幅: +height = 高さ: +menu = メニュー +play = プレイ +load = 読み込む +save = 保存 +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0}ms +language.restart = 言語設定を有効にするにはゲームを再起動してください。 +settings = 設定 +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson]サーバーへの接続できませんでした:\n\n[accent]{0} +error.unreachable = サーバーに到達できません。\nアドレスは正しいですか? +error.invalidaddress = 無効なアドレスです。 +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 = 再設定 +settings.controls = コントロール +settings.game = ゲーム +settings.sound = サウンド +settings.graphics = グラフィック +settings.cleardata = データを削除... +settings.clear.confirm = データを削除してもよろしいですか?\n元に戻すことはできません! +settings.clearall.confirm = [scarlet]警告![]\nこれはすべてのデータが削除されます。これにはセーブデータ、マップ、アンロック、キーバインドが含まれます。\n「ok」 を押すと、すべてのデータが削除され、自動的に終了します。 +settings.clearunlocks = アンロックを削除 +settings.clearall = すべてを削除 +paused = [accent]< ポーズ > +yes = はい +no = いいえ +info.title = 情報 +error.title = [crimson]エラーが発生しました +error.crashtitle = エラーが発生しました +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = ブロック情報 +blocks.powercapacity = 電力容量 +blocks.powershot = 電力/ショット +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.liquid = Liquid +blocks.coolantuse = 冷却使用量 +blocks.inputliquidfuel = 液体燃料 +blocks.liquidfueluse = 液体燃料使用量 +blocks.boostitem = 加速アイテム +blocks.boostliquid = 加速液体 +blocks.health = 耐久値 +blocks.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = 精度のずれ +blocks.shots = ショット +blocks.reload = ショット/秒 +blocks.inputfuel = 燃料 +blocks.fuelburntime = 燃焼時間 +blocks.inputcapacity = 搬入容量 +blocks.outputcapacity = 搬出容量 +unit.blocks = ブロック +unit.powersecond = 電力/秒 +unit.liquidsecond = 液体/秒 +unit.itemssecond = アイテム/秒 +unit.pixelssecond = ピクセル/秒 +unit.liquidunits = 液体 +unit.powerunits = 電力 +unit.degrees = 度 +unit.seconds = 秒 +unit.items = アイテム +category.general = 一般 +category.power = 電力 +category.liquids = 液体 +category.items = アイテム +category.crafting = 製作速度 +category.shooting = 攻撃速度 +category.optional = 機能強化オプション +>>>>>>> upstream/master setting.indicators.name = 味方の方角表示 setting.autotarget.name = 自動ターゲット setting.fpscap.name = 最大FPS @@ -375,7 +733,7 @@ setting.mutemusic.name = 音楽をミュート setting.sfxvol.name = 効果音 音量 setting.mutesound.name = 効果音をミュート setting.crashreport.name = 匿名でクラッシュレポートを送信する -text.keybind.title = キーバインド +keybind.title = キーバインド category.general.name = 一般 category.view.name = 表示 category.multiplayer.name = マルチプレイ @@ -390,6 +748,7 @@ keybind.screenshot.name = スクリーンショット keybind.move_x.name = 左右移動 keybind.move_y.name = 上下移動 keybind.select.name = 選択/ショット +keybind.pick.name = Pick Block keybind.break.name = 破壊 keybind.deselect.name = 選択解除 keybind.shoot.name = ショット @@ -408,9 +767,15 @@ keybind.chat_history_next.name = 次のチャット履歴 keybind.chat_scroll.name = チャットスクロール keybind.drop_unit.name = ドロップユニット keybind.zoom_minimap.name = ミニマップのズーム +<<<<<<< HEAD mode.text.help.title = モード説明 mode.waves.name = ウェーブ mode.waves.description = 通常モードです。限られた資源の中でウェーブが自動的に進行します。 +======= +mode.help.title = モード説明 +mode.survival.name = Survival +mode.survival.description = The normal mode. Limited resources and automatic incoming waves. +>>>>>>> upstream/master mode.sandbox.name = サンドボックス mode.sandbox.description = 無限の資源でウェーブを自由に進行できます。 mode.freebuild.name = フリービルド @@ -422,18 +787,20 @@ mode.attack.descrption = ウェーブはなく、敵基地の破壊を目指し 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 = 一般的で有用な燃料です。 +<<<<<<< HEAD item.dense-alloy.name = 高密度合金 item.dense-alloy.description = 銅と鉛でできた丈夫な合金です。高性能な輸送ブロックやドリルに使われます。 +======= +item.graphite.name = Graphite +>>>>>>> upstream/master item.titanium.name = チタン item.titanium.description = 希少で非常に軽量な金属です。液体輸送やドリル、航空機などで使われます。 item.thorium.name = トリウム @@ -454,6 +821,13 @@ item.blast-compound.name = 爆発性化合物 item.blast-compound.description = 爆弾や爆発物に使われる揮発性の化合物です。燃料として燃やすこともできますが、お勧めしません。 item.pyratite.name = ピラタイト item.pyratite.description = 兵器などに使われる非常に燃えやすい物質です。 +<<<<<<< HEAD +======= +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. +>>>>>>> upstream/master liquid.water.name = 水 liquid.lava.name = 溶岩 liquid.oil.name = 石油 @@ -487,6 +861,7 @@ mech.trident-ship.weapon = 爆弾 mech.glaive-ship.name = グライブ mech.glaive-ship.description = 重武装された大型攻撃機です。焼夷弾が装備され、機体の中でも優れた加速と最高速度を有しています。 mech.glaive-ship.weapon = 焼夷弾 +<<<<<<< HEAD text.item.explosiveness = [LIGHT_GRAY]爆発性: {0}% text.item.flammability = [LIGHT_GRAY]可燃性: {0}% text.item.radioactivity = [LIGHT_GRAY]放射能: {0}% @@ -502,9 +877,31 @@ text.mech.ability = [LIGHT_GRAY]能力: {0} text.liquid.heatcapacity = [LIGHT_GRAY]熱容量: {0} text.liquid.viscosity = [LIGHT_GRAY]粘度: {0} text.liquid.temperature = [LIGHT_GRAY]温度: {0} +======= +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]Health: {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.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 +>>>>>>> upstream/master block.constructing = {0}\n[LIGHT_GRAY](建設中) block.spawn.name = エネミースポーン -block.core.name = コア +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = 金属製の床 block.deepwater.name = 深層水 block.water.name = 水 @@ -523,8 +920,8 @@ block.blackrock.name = 黒い岩 block.icerock.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 = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = フェーズファイバーの壁 block.phase-wall-large.name = 大きなフェーズファイバーの壁 block.thorium-wall.name = トリウムの壁 @@ -557,17 +954,24 @@ 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 = 耕作機 +<<<<<<< HEAD block.alpha-mech-pad.name = アルファパッド block.dart-ship-pad.name = ダーツパッド +======= +block.alpha-dart-mech-pad.name = Alpha-Dart Mech Pad +>>>>>>> upstream/master block.delta-mech-pad.name = デルタパッド block.javelin-ship-pad.name = ジャベリンパッド block.trident-ship-pad.name = トライデントパッド @@ -576,11 +980,11 @@ block.omega-mech-pad.name = オメガパッド block.tau-mech-pad.name = タウパッド block.conduit.name = パイプ block.mechanical-pump.name = 機械ポンプ -block.itemsource.name = アイテムソース -block.itemvoid.name = アイテムボイド -block.liquidsource.name = 液体ソース -block.powervoid.name = 電力ボイド -block.powerinfinite.name = 無限電源 +block.item-source.name = アイテムソース +block.item-void.name = アイテムボイド +block.liquid-source.name = 液体ソース +block.power-void.name = 電力ボイド +block.power-source.name = 無限電源 block.unloader.name = アンローダー block.vault.name = ボールト block.wave.name = ウェーブ @@ -632,7 +1036,7 @@ block.rtg-generator.name = RTG発電機 block.spectre.name = スペクター block.meltdown.name = メルトダウン block.container.name = コンテナー -block.core.description = ゲームで最も重要な建物です。 +block.launch-pad.name = Launch Pad team.blue.name = ブルー team.red.name = レッド team.orange.name = オレンジ @@ -646,6 +1050,7 @@ 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 +1060,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ドリルからコアまでコンベアー作りましょう。 @@ -778,11 +1187,19 @@ block.router.description = 一つの方向から受け取ったアイテムを block.distributor.description = 高度なルーターです。アイテムを7方向に均等に分けて搬出します。 block.bridge-conveyor.description = 高度な輸送ブロックです。地形や建物を超えて、3ブロック離れた場所にアイテムを輸送することができます。 block.alpha-mech-pad.description = 電力を使用して、機体を[accent]アルファ[]機体に作り替えます。 +<<<<<<< HEAD block.itemsource.description = アイテムを無限に搬出します。サンドボックスのみ。 block.liquidsource.description = 液体を無限に搬出します。サンドボックスのみ。 block.itemvoid.description = 電力なしでアイテムを廃棄します。サンドボックスのみ。 block.powerinfinite.description = 無限に電力を搬出します。サンドボックスのみ。 block.powervoid.description = 入力されたすべての電力を破棄します。サンドボックスのみ。 +======= +block.item-source.description = アイテムを無限に搬出します。サンドボックスのみ。 +block.liquid-source.description = 液体を無限に搬出します。サンドボックスのみ。 +block.item-void.description = 電力なしでアイテムを廃棄します。サンドボックスのみ。 +block.power-source.description = 無限に電力を搬出します。サンドボックスのみ。 +block.power-void.description = 入力されたすべての電力を破棄します。サンドボックスのみ。 +>>>>>>> upstream/master liquid.water.description = 一般的に機械の冷却や廃棄物の処理などに使用されます。 liquid.lava.description = 冷却して石にしたり、発電や一部ターレットの弾薬として使用することができます。 liquid.oil.description = 燃焼させたり、爆発させたり、冷却水としても使われます。 diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index e72a97601e..8e4ea16128 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -1,351 +1,359 @@ -text.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!) -text.credits = 제작자 -text.discord = Mindustry Discord 에 참여하세요! -text.link.discord.description = 공식 Mindustry Discord 채팅방 -text.link.github.description = 게임 소스코드 -text.link.dev-builds.description = 개발중인 빌드 -text.link.trello.description = 다음 출시될 기능들을 게시한 공식 Trello 보드 -text.link.itch.io.description = PC 버전 다운로드와 HTML5 버전이 있는 itch.io 사이트 -text.link.google-play.description = Google Play 스토어 정보 -text.link.wiki.description = 공식 Mindustry 위키 (영어) -text.linkfail = 링크를 여는데 실패했습니다! URL이 기기의 클립보드에 복사되었습니다. -text.gameover = 코어가 터졌습니다. 게임 오버! -text.gameover.pvp = [accent]{0}[] 팀이 승리했습니다! -text.sector.gameover = 이 지역을 공략하는데 실패했습니다. 포기 하시겠습니까? -text.sector.retry = 아니오 -text.highscore = [YELLOW]최고점수 달성! -text.wave.lasted = [accent]{0}[] 까지 버티셨습니다. -text.level.highscore = 최고 점수 : [accent]{0} -text.level.delete.title = 삭제 확인 -text.map.delete = 정말로 "[accent]{0}[]" 맵을 삭제하시겠습니까? -text.level.select = 맵 선택 -text.level.mode = 게임모드 : -text.construction.desktop = PC 에서의 조작 방법이 변경되었습니다.\n블록 선택을 해제하거나 건설을 중지하려면 [accent]스페이스 바[]를 누르세요. -text.construction.title = 블록 배치 안내서 -text.construction = [accent]블록 배치 모드[]를 선택하셨습니다.\n\n블록을 설치하고 싶으면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 배치 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요. \n- [accent]블록을 넓게 배치[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록을 한줄로 배치[]하고 싶다면 배치하고 싶은 시작 영역을 한번 탭 하고 길게 누르면서 드래그 하면 됩니다. \n- [accent]블록 배치 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. -text.deconstruction.title = 블록 삭제 안내서 -text.deconstruction = [accent]블록 삭제 모드[]를 선택하셨습니다\n\n블록을 삭제하고 싶다면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 파괴 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요\n- [accent]블록을 넓은 범위로 삭제[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록 삭제 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. -text.showagain = 다음 세션에서 이 메세지를 표시하지 않습니다 -text.coreattack = < 코어가 공격받고 있습니다! > -text.unlocks = 아이템들 -text.savegame = 게임 저장 -text.loadgame = 게임 불러오기 -text.joingame = 멀티플레이 -text.addplayers = 플레이어 추가/제거 -text.customgame = 커스텀 게임 -text.sectors = 지역 플레이 -text.sector = 지역 : [LIGHT_GRAY]{0} -text.sector.time = 시간 : [LIGHT_GRAY]{0} -text.sector.deploy = 시작 -text.sector.abandon = 초기화 -text.sector.abandon.confirm = 정말로 이 지역의 모든 진행상황을 초기화 하겠습니까?\n이 작업은 되돌릴 수 없습니다! -text.sector.resume = 계속하기 -text.sector.locked = [scarlet][[완료안됨] -text.sector.unexplored = [accent][[탐색안됨] -text.missions = 목표 : [LIGHT_GRAY] {0} -text.mission = 목표 : [LIGHT_GRAY] {0} -text.mission.main = 주요 목표 : [LIGHT_GRAY]{0} -text.mission.info = 미션 정보 -text.mission.complete = 미션 성공! -text.mission.complete.body = 지역 {0},{1} 클리어. -text.mission.wave = [accent]{0}/{1}[] 단계 생존\n{2}초 남음 -text.mission.wave.enemies = [accent]{0}/{1} []단계 생존\n{2}마리 남음 -text.mission.wave.enemy = [accent]{0}/{1} []단계 생존\n{2}마리 남음 -text.mission.wave.menu = [accent]{0}[] 단계 -text.mission.battle = 적 코어를 파괴하세요 -text.mission.resource.menu = {0} {1}개 수집 -text.mission.resource = {0} 을(를) 수집하세요\n[accent]{1}/{2} -text.mission.block = {0} 를 만드세요 -text.mission.unit = {0} 유닛을 만드세요 -text.mission.command = 유닛에게 {0} 명령을 보내세요 -text.mission.linknode = 전력 노드를 연결하세요 -text.mission.display = [accent]목표 : [LIGHT_GRAY]{0} -text.mission.mech = [accent]{0}[] 기체로 바꾸세요 -text.mission.create = [accent]{0}[] 을(를)설치하세요. -text.none = <없음> -text.close = 닫기 -text.quit = 나가기 -text.maps = 맵 -text.continue = 계속하기 -text.nextmission = 다음 임무 -text.maps.none = [LIGHT_GRAY]맵을 찾을 수 없습니다! -text.about.button = 정보 -text.name = 이름 : -text.filename = 파일 이름 : -text.unlocked = 새 블록 잠금 해제됨 -text.unlocked.plural = 잠금 해제 -text.players = 현재 {0}명 접속중 -text.players.single = 현재 {0}명만 있음. -text.server.closing = [accent]서버 닫는중... -text.server.kicked.kick = 서버에서 추방되었습니다! -text.server.kicked.serverClose = 서버 종료됨. -text.server.kicked.sectorComplete = 지역 클리어. -text.server.kicked.sectorComplete.text = 임무 성공.\n서버가 다음지역 맵으로 이동되었습니다. -text.server.kicked.clientOutdated = 오래된 버전의 클라이언트 입니다! 게임을 업데이트 하세요! -text.server.kicked.serverOutdated = 오래된 버전의 서버입니다! 서버 호스트 관리자에게 문의하세요! -text.server.kicked.banned = 뭘 하셨는지는 모르겠지만, 이제 영원히 서버에 접속할 수 없습니다. -text.server.kicked.recentKick = 방금 추방처리 되었습니다. 잠시 기다린 후에 접속 해 주세요. -text.server.kicked.nameInUse = 이 닉네임이 이미 서버에서 사용중입니다. -text.server.kicked.nameEmpty = 닉네임에는 반드시 영어 또는 숫자가 있어야 합니다. -text.server.kicked.idInUse = 이미 서버에 접속중입니다! 다중 계정은 허용되지 않습니다. -text.server.kicked.customClient = 이 서버는 직접 빌드한 버전을 지원하지 않습니다. 공식 버전을 사용하세요. -text.host.info = [accent]호스트[] 버튼은 현재 네트워크의 [scarlet]6567[] 포트를 사용합니다.\n[LIGHY_GRAY]같은 Wi-Fi 또는 로컬 네트워크[] 에서 서버 목록을 볼 수 있습니다.\n\n만약 플레이어들이 이 IP를 통해 어디에서나 연결할 수 있게 하고 싶다면, 공유기 설정에서 [accent]포트 포워딩[]을 해야 합니다.\n\n[LIGHT_GRAY]참고 : LAN 게임 연결에 문제가 있는 사람이 있다면, 방화벽 설정에서 Mindustry 가 로컬 네트워크에 액세스하도록 허용했는지 확인 해 주세요. -text.join.info = 여기서 [accent]서버 IP[]를 입력하여 다른 서버에 접속할 수 있습니다.\n또는 [accent]로컬 네트워크(LAN)[] 서버를 검색하여 접속할 수 있습니다.\nLAN 및 WAN 멀티 플레이어 모두 지원됩니다.\n\n[LIGHT_GRAY]참고:여기에서는 자동으로 글로벌 서버를 추가하지 않습니다. IP로 다른 사람의 서버에 접속할려면 서버장에게 IP를 요청해야 합니다. -text.hostserver = 서버 열기 -text.hostserver.mobile = 서버\n열기 -text.host = 서버 열기 -text.hosting = [accent]서버 여는중... -text.hosts.refresh = 새로고침 -text.hosts.discovering = LAN 게임 찾기 -text.server.refreshing = 서버 목록 새로고치는중... -text.hosts.none = [lightgray]LAN 게임을 찾을 수 없습니다! -text.host.invalid = [scarlet]서버에 연결할 수 없습니다! -text.trace = 플레이어 정보 보기 -text.trace.playername = 이름 : [accent]{0} -text.trace.ip = IP : [accent]{0} -text.trace.id = 고유 ID : [accent]{0} -text.trace.android = Android 클라이언트 : [accent]{0} -text.trace.modclient = 수정된 클라이언트 : [accent]{0} -text.trace.totalblocksbroken = 총 블록 파괴 개수 : [accent]{0} -text.trace.structureblocksbroken = 구조 블록 파괴 수 : [accent]{0} -text.trace.lastblockbroken = 마지막으로 파괴한 블록 : [accent]{0} -text.trace.totalblocksplaced = 총 설치한 블록 개수 : [accent]{0} -text.trace.lastblockplaced = 마지막으로 설치한 블록 : [accent]{0} -text.invalidid = 잘못된 클라이언트 ID 입니다! 공식 Mindustry Discord 으로 버그 보고서를 제출 해 주세요. -text.server.bans = 차단된 유저 -text.server.bans.none = 차단된 플레이어가 없습니다. -text.server.admins = 관리자 -text.server.admins.none = 관리자가 없습니다! -text.server.add = 서버 추가 -text.server.delete = 이 서버를 삭제 하시겠습니까? -text.server.hostname = 호스트 : {0} -text.server.edit = 서버 수정 -text.server.outdated = [crimson]서버 버전이 낮습니다![] -text.server.outdated.client = [Crimson]클라이언트 버전이 낮습니다![] -text.server.version = [lightgray]서버 버전 : {0} -text.server.custombuild = [yellow]커스텀 서버 -text.confirmban = 이 플레이어를 차단하시겠습니까? -text.confirmkick = 정말로 이 플레이어를 추방시키겠습니까? -text.confirmunban = 이 플레이어를 차단해제 하시겠습니까? -text.confirmadmin = 이 플레이어를 관리자로 만들겠습니까? -text.confirmunadmin = 이 플레이어를 일반 유저로 만들겠습니까? -text.joingame.title = 게임 참가 -text.joingame.ip = IP : -text.disconnect = 서버와 연결이 해제되었습니다. -text.disconnect.data = 맵 데이터를 받아오는데 실패했습니다. -text.connecting = [accent]연결중... -text.connecting.data = [accent]맵 데이터 다운로드중... -text.server.port = 포트 : -text.server.addressinuse = 이 주소는 이미 사용중입니다! -text.server.invalidport = 포트 번호가 잘못되었습니다. -text.server.error = [crimson]{0}[accent]서버를 여는데 오류가 발생했습니다.[] -text.save.old = 이 저장파일은 이전 버전의 게임용이며, 지금은 사용할 수 없습니다. \n\n[LIGHT_GRAY]4.0 정식때 이전 게임버전에서 만든 저장파일과 호환됩니다. -text.save.new = 새로 저장 -text.save.overwrite = 이 저장 슬롯을 덮어씌우겠습니까? -text.overwrite = 덮어쓰기 -text.save.none = 저장 파일을 찾지 못했습니다! -text.saveload = [accent]저장중... -text.savefail = 게임을 저장하지 못했습니다! -text.save.delete.confirm = 이 저장파일을 삭제 하시겠습니까? -text.save.delete = 삭제 -text.save.export = 저장파일 내보내기 -text.save.import.invalid = [accent]파일이 잘못되었습니다! -text.save.import.fail = [crimson]저장파일을 불러오지 못함 : [accent]{0} -text.save.export.fail = [crimson]저장파일을 내보내지 못함 : [accent]{0} -text.save.import = 저장파일 불러오기 -text.save.newslot = 저장 파일이름 : -text.save.rename = 이름 변경 -text.save.rename.text = 새 이름 : -text.selectslot = 저장슬롯을 선택하십시오. -text.slot = [accent]{0}번째 슬롯 -text.save.corrupted = [accent]세이브 파일이 손상되었거나 잘못된 파일입니다! 만약 게임을 업데이트 했다면 이것은 아마 저장 형식 변경일 것이고, 이것은 버그가 [scarlet]아닙니다[]. -text.sector.corrupted = [accent]저장 파일에서 지역을 발견했으나 불러오지 못했습니다.\n새로 생성되었습니다. -text.empty = <비어있음> -text.on = 켜기 -text.off = 끄기 -text.save.autosave = 자동저장 : {0} -text.save.map = 맵 : {0} -text.save.wave = {0}단계[] -text.save.difficulty = 난이도 : {0} -text.save.date = 마지막 저장날짜 : {0} -text.save.playtime = 플레이시간 : {0} -text.confirm = 확인 -text.delete = 삭제 -text.ok = 확인 -text.open = 열기 -text.cancel = 취소 -text.openlink = 링크 열기 -text.copylink = 링크 복사 -text.back = 뒤로가기 -text.quit.confirm = 정말로 종료하시겠습니까? -text.changelog.title = 변경사항 -text.changelog.loading = 변경사항 가져오는중... -text.changelog.error.android = [accent]게임 변경사항은 가끔 Android 4.4 이하에서 작동하지 않습니다. 이것은 내부 Android 버그 때문입니다. -text.changelog.error.ios = [accent]현재 iOS에서는 변경 사항을 지원하지 않습니다. -text.changelog.error = [scarlet]게임 변경사항을 가져오는 중 오류가 발생했습니다![]\n인터넷 연결을 확인하십시오. -text.changelog.current = [accent][[현재 버전] -text.changelog.latest = [accent][[최신 버전] -text.loading = [accent]불러오는중... -text.saving = [accent]저장중... -text.wave = [accent]{0}단계 -text.wave.waiting = 남은 시간 : [green]{0}초[] -text.waiting = [LIGHT_GRAY]대기중... -text.waiting.players = 다른 플레이어를 기다리는 중.. -text.wave.enemies = [LIGHT_GRAY]{0} 마리 남았음 -text.wave.enemy = [LIGHT_GRAY]{0} 마리 남음 -text.loadimage = 사진 불러오기 -text.saveimage = 사진 저장 -text.unknown = 알 수 없음 -text.custom = 커스텀 -text.builtin = 기본맵 -text.map.delete.confirm = 이 맵을 삭제하시겠습니까? 이 명령은 취소할 수 없습니다! -text.map.random = [accent]랜덤 맵 -text.map.nospawn = 이 맵에 플레이어가 스폰 할 코어가 없습니다! 맵 편집기에서 [ROYAL]파란색[]코어를 맵에 추가하세요. -text.map.nospawn.pvp = 이 맵에는 적팀 코어가 없습니다! 에디터에서 [scarlet]빨간팀[] 코어를 추가하세요. -text.map.invalid = 파일이 잘못되었거나 손상되어 맵을 열 수 없습니다. -text.editor.brush = 브러쉬 -text.editor.slope = \\ -text.editor.openin = 편집기 열기 -text.editor.oregen = 광물 무작위 생성 -text.editor.oregen.info = 광물 무작위 생성 : -text.editor.mapinfo = 맵 정보 -text.editor.author = 만든이 : -text.editor.description = 설명 : -text.editor.name = 이름 : -text.editor.teams = 팀 -text.editor.elevation = 지형 높이 -text.editor.errorimageload = [accent]{0}[] 파일을 불러오는데 오류가 발생했습니다. -text.editor.errorimagesave = [accent]{0}[] 파일 저장중 오류가 발생했습니다. -text.editor.generate = 생성 -text.editor.resize = 맵 크기조정 -text.editor.loadmap = 맵 불러오기 -text.editor.savemap = 맵 저장 -text.editor.saved = 저장됨! -text.editor.save.noname = 지도에 이름이 없습니다! 메뉴 -> '맵 정보' 에서 설정하세요. -text.editor.save.overwrite = 이 맵의 이름은 기존에 있던 맵을 덮어씁니다! '맵 정보' 메뉴에서 다른 이름을 선택하세요. -text.editor.import.exists = [scarlet]맵을 불러올 수 없음 : [] 기존에 있던 '{0}' 맵이 이미 존재합니다! -text.editor.import = 가져오기 -text.editor.importmap = 맵 가져오기 -text.editor.importmap.description = 이미 존재하는 맵 가져오기 -text.editor.importfile = 파일 가져오기 -text.editor.importfile.description = 외부 맵 파일 가져오기 -text.editor.importimage = 지형 사진 가져오기 -text.editor.importimage.description = 외부 맵 이미지 파일 가져오기 -text.editor.export = 내보내기 -text.editor.exportfile = 파일 내보내기 -text.editor.exportfile.description = 맵 파일 내보내기 -text.editor.exportimage = 지형 이미지 내보내기 -text.editor.exportimage.description = 맵 이미지 파일 내보내기 -text.editor.loadimage = 지형 가져오기 -text.editor.saveimage = 지형 내보내기 -text.editor.unsaved = [scarlet]변경사항을 저장하지 않았습니다![]\n정말로 나가시겠습니까? -text.editor.resizemap = 맵 크기 조정 -text.editor.mapname = 맵 이름 : -text.editor.overwrite = [accept]경고!이 명령은 기존 맵을 덮어씌우게 됩니다. -text.editor.overwrite.confirm = [scarlet]경고![] 이 이름을 가진 맵이 이미 있습니다. 덮어 쓰시겠습니까? -text.editor.selectmap = 불러올 맵 선택 : -text.width = 넓이 : -text.height = 높이 : -text.menu = 메뉴 -text.play = 플레이 -text.load = 불러오기 -text.save = 저장 -text.fps = {0}FPS -text.tps = {0}TPS -text.ping = ping : {0}ms -text.language.restart = 언어를 변경하려면 게임을 다시시작 해 주세요. -text.settings = 설정 -text.tutorial = 게임 방법 -text.editor = 편집기 -text.mapeditor = 맵 편집기 -text.donate = 기부 -text.connectfail = [crimson]{0}[accent] 서버에 연결하지 못했습니다.[] -text.error.unreachable = 서버에 연결하지 못했습니다. -text.error.invalidaddress = 잘못된 주소입니다. -text.error.timedout = 시간 초과!\n서버에 포트 포워딩이 설정되어 있고 주소가 올바른지 확인하십시오. -text.error.mismatch = 패킷 오류:\n클라이언트/서버 버전이 일치하지 않습니다.\n접속할려는 서버가 최신 버전의 Mindustry 인지 확인하세요! -text.error.alreadyconnected = 이미 접속중입니다. -text.error.mapnotfound = 맵 파일을 찾을 수 없습니다! -text.error.any = 알 수 없는 네트워크 오류. -text.settings.language = 언어 -text.settings.reset = 설정 초기화 -text.settings.rebind = 키 재설정 -text.settings.controls = 컨트롤 -text.settings.game = 게임 -text.settings.sound = 소리 -text.settings.graphics = 그래픽 -text.settings.cleardata = 게임 데이터 초기화... -text.settings.clear.confirm = 정말로 초기화 하겠습니까?\n이 작업을 되돌릴 수 없습니다! -text.settings.clearall.confirm = [scarlet]경고![]\n이 작업은 저장된 맵, 맵파일, 잠금 해제된 목록과 키 매핑, 그리고 모든 데이터를 삭제합니다.\n확인 버튼을 다시 눌러 모든 데이터를 삭제하고 게임에서 나갑니다. -text.settings.clearsectors = 지역 초기화 -text.settings.clearunlocks = 잠금 해제 초기화 -text.settings.clearall = 모두 초기화 -text.paused = 일시 정지 -text.yes = 예 -text.no = 아니오 -text.info.title = [accent]정보 -text.error.title = [crimson]오류가 발생했습니다. -text.error.crashtitle = 오류가 발생했습니다. -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = 블록 정보 -text.blocks.powercapacity = 최대 전력 용량 -text.blocks.powershot = 1발당 전력 소모량 -text.blocks.targetsair = 공중공격 가능 -text.blocks.itemspeed = 유닛 이동 속도 -text.blocks.shootrange = 사거리 -text.blocks.size = 블록 크기 -text.blocks.liquidcapacity = 최대 액체 용량 -text.blocks.maxitemssecond = 최대 아이템 보관량 -text.blocks.powerrange = 전력 범위 -text.blocks.poweruse = 전력 사용 -text.blocks.powerdamage = 전력/데미지 -text.blocks.inputitemcapacity = 입력 아이템 용량 -text.blocks.outputitemcapacity = 출력 아이템 용량 -text.blocks.itemcapacity = 저장 용량 -text.blocks.basepowergeneration = 기지 전력 생성기 -text.blocks.powertransferspeed = 전력 전송량 -text.blocks.craftspeed = 생산 속도 -text.blocks.inputliquid = 사용되는 액체 -text.blocks.inputliquidaux = 보조 액체 -text.blocks.inputitem = 사용되는 아이템 -text.blocks.inputitems = 사용되는 아이템들 -text.blocks.outputitem = 출력 아이템 -text.blocks.drilltier = 드릴 -text.blocks.drillspeed = 기본 드릴 속도 -text.blocks.liquidoutput = 액체 출력 -text.blocks.liquidoutputspeed = 액체 출력속도 -text.blocks.liquiduse = 액체 사용량 -text.blocks.coolant = 냉각제 -text.blocks.coolantuse = 냉각수 사용 -text.blocks.inputliquidfuel = 연료 액 -text.blocks.liquidfueluse = 액체 연료 사용 -text.blocks.boostitem = 가속 아이템 -text.blocks.boostliquid = 가속 액체 -text.blocks.health = 체력 -text.blocks.inaccuracy = 오차각 -text.blocks.shots = 발포 횟수 -text.blocks.reload = 재장전 -text.blocks.inputfuel = 연료 -text.blocks.fuelburntime = 연료 연소 시간 -text.blocks.inputcapacity = 입력 용량 -text.blocks.outputcapacity = 출력 용량 -text.unit.blocks = 블록 -text.unit.powersecond = 전력/초 -text.unit.liquidsecond = 액체/초 -text.unit.itemssecond = 개/초 -text.unit.pixelssecond = 초당 픽셀 -text.unit.liquidunits = 액체 -text.unit.powerunits = 전력 -text.unit.degrees = 도 -text.unit.seconds = 초 -text.unit.items = 아이템 -text.category.general = 일반 -text.category.power = 전력 -text.category.liquids = 액체 -text.category.items = 아이템 -text.category.crafting = 제작 -text.category.shooting = 사격 -text.category.optional = 선택적 향상 +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 = Translators and Contributors +discord = Mindustry Discord 에 참여하세요! +link.discord.description = 공식 Mindustry Discord 채팅방 +link.github.description = 게임 소스코드 +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이 기기의 클립보드에 복사되었습니다. +screenshot = Screenshot saved to {0} +gameover = 코어가 터졌습니다. 게임 오버! +gameover.pvp = [accent]{0}[] 팀이 승리했습니다! +highscore = [YELLOW]최고점수 달성! +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: +map.delete = 정말로 "[accent]{0}[]" 맵을 삭제하시겠습니까? +level.highscore = 최고 점수 : [accent]{0} +level.select = 맵 선택 +level.mode = 게임모드 : +construction.desktop = PC 에서의 조작 방법이 변경되었습니다.\n블록 선택을 해제하거나 건설을 중지하려면 [accent]스페이스 바[]를 누르세요. +construction.title = 블록 배치 안내서 +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 버튼을 누르면 됩니다. +showagain = 다음 세션에서 이 메세지를 표시하지 않습니다 +coreattack = < 코어가 공격받고 있습니다! > +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 = 커스텀 게임 +newgame = New Game +none = <없음> +close = 닫기 +quit = 나가기 +maps = 맵 +continue = 계속하기 +maps.none = [LIGHT_GRAY]맵을 찾을 수 없습니다! +about.button = 정보 +name = 이름 : +noname = Pick a[accent] player name[] first. +filename = 파일 이름 : +unlocked = 새 블록 잠금 해제됨 +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.clientOutdated = 오래된 버전의 클라이언트 입니다! 게임을 업데이트 하세요! +server.kicked.serverOutdated = 오래된 버전의 서버입니다! 서버 호스트 관리자에게 문의하세요! +server.kicked.banned = 뭘 하셨는지는 모르겠지만, 이제 영원히 서버에 접속할 수 없습니다. +server.kicked.recentKick = 방금 추방처리 되었습니다.\n잠시 기다린 후에 접속 해 주세요.\n참고 : [accent]계속해서 접속을 시도하면 강퇴 시간이 길어집니다. +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 가 로컬 네트워크에 액세스하도록 허용했는지 확인 해 주세요. +join.info = 여기서 [accent]서버 IP[]를 입력하여 다른 서버에 접속할 수 있습니다.\n또는 [accent]로컬 네트워크(LAN)[] 서버를 검색하여 접속할 수 있습니다.\nLAN 및 WAN 멀티 플레이어 모두 지원됩니다.\n\n[LIGHT_GRAY]참고:여기에서는 자동으로 글로벌 서버를 추가하지 않습니다. IP로 다른 사람의 서버에 접속할려면 서버장에게 IP를 요청해야 합니다. +hostserver = 서버 열기 +hostserver.mobile = 서버\n열기 +host = 서버 열기 +hosting = [accent]서버 여는중... +hosts.refresh = 새로고침 +hosts.discovering = LAN 게임 찾기 +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 으로 버그 보고서를 제출 해 주세요. +server.bans = 차단된 유저 +server.bans.none = 차단된 플레이어가 없습니다. +server.admins = 관리자 +server.admins.none = 관리자가 없습니다! +server.add = 서버 추가 +server.delete = 이 서버를 삭제 하시겠습니까? +server.hostname = 호스트 : {0} +server.edit = 서버 수정 +server.outdated = [crimson]서버 버전이 낮습니다![] +server.outdated.client = [Crimson]클라이언트 버전이 낮습니다![] +server.version = [lightgray]서버 버전 : {0} +server.custombuild = [yellow]커스텀 서버 +confirmban = 이 플레이어를 차단하시겠습니까? +confirmkick = 정말로 이 플레이어를 추방시키겠습니까? +confirmunban = 이 플레이어를 차단해제 하시겠습니까? +confirmadmin = 이 플레이어를 관리자로 만들겠습니까? +confirmunadmin = 이 플레이어를 일반 유저로 만들겠습니까? +joingame.title = 게임 참가 +joingame.ip = IP : +disconnect = 서버와 연결이 해제되었습니다. +disconnect.data = 맵 데이터를 받아오는데 실패했습니다. +connecting = [accent]연결중... +connecting.data = [accent]맵 데이터 다운로드중... +server.port = 포트 : +server.addressinuse = 이 주소는 이미 사용중입니다! +server.invalidport = 포트 번호가 잘못되었습니다. +server.error = [crimson]{0}[accent]서버를 여는데 오류가 발생했습니다.[] +save.old = 이 저장파일은 이전 버전의 게임용이며, 지금은 사용할 수 없습니다. \n\n[LIGHT_GRAY]4.0 정식때 이전 게임버전에서 만든 저장파일과 호환됩니다. +save.new = 새로 저장 +save.overwrite = 이 저장 슬롯을 덮어씌우겠습니까? +overwrite = 덮어쓰기 +save.none = 저장 파일을 찾지 못했습니다! +saveload = [accent]저장중... +savefail = 게임을 저장하지 못했습니다! +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 = 저장파일 불러오기 +save.newslot = 저장 파일이름 : +save.rename = 이름 변경 +save.rename.text = 새 이름 : +selectslot = 저장슬롯을 선택하십시오. +slot = [accent]{0}번째 슬롯 +save.corrupted = [accent]세이브 파일이 손상되었거나 잘못된 파일입니다! 만약 게임을 업데이트 했다면 이것은 아마 저장 형식 변경일 것이고, 이것은 버그가 [scarlet]아닙니다[]. +empty = <비어있음> +on = 켜기 +off = 끄기 +save.autosave = 자동저장 : {0} +save.map = 맵 : {0} +save.wave = {0}단계[] +save.difficulty = 난이도 : {0} +save.date = 마지막 저장날짜 : {0} +save.playtime = 플레이시간 : {0} +warning = Warning. +confirm = 확인 +delete = 삭제 +ok = 확인 +open = 열기 +cancel = 취소 +openlink = 링크 열기 +copylink = 링크 복사 +back = 뒤로가기 +quit.confirm = 정말로 종료하시겠습니까? +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.latest = [accent][[최신 버전] +loading = [accent]불러오는중... +saving = [accent]저장중... +wave = [accent]{0}단계 +wave.waiting = 남은 시간 : [green]{0}초[] +waiting = [LIGHT_GRAY]대기중... +waiting.players = 다른 플레이어를 기다리는 중.. +wave.enemies = [LIGHT_GRAY]{0} 마리 남았음 +wave.enemy = [LIGHT_GRAY]{0} 마리 남음 +loadimage = 사진 불러오기 +saveimage = 사진 저장 +unknown = 알 수 없음 +custom = 커스텀 +builtin = 기본맵 +map.delete.confirm = 이 맵을 삭제하시겠습니까? 이 명령은 취소할 수 없습니다! +map.random = [accent]랜덤 맵 +map.nospawn = 이 맵에 플레이어가 스폰 할 코어가 없습니다! 맵 편집기에서 [ROYAL]파란색[]코어를 맵에 추가하세요. +map.nospawn.pvp = 이 맵에는 적팀 코어가 없습니다! 에디터에서 [scarlet]빨간팀[] 코어를 추가하세요. +map.invalid = 파일이 잘못되었거나 손상되어 맵을 열 수 없습니다. +editor.brush = 브러쉬 +editor.slope = \\ +editor.openin = 편집기 열기 +editor.oregen = 광물 무작위 생성 +editor.oregen.info = 광물 무작위 생성 : +editor.mapinfo = 맵 정보 +editor.author = 만든이 : +editor.description = 설명 : +editor.name = 이름 : +editor.teams = 팀 +editor.elevation = 지형 높이 +editor.errorimageload = [accent]{0}[] 파일을 불러오는데 오류가 발생했습니다. +editor.errorimagesave = [accent]{0}[] 파일 저장중 오류가 발생했습니다. +editor.generate = 생성 +editor.resize = 맵 크기조정 +editor.loadmap = 맵 불러오기 +editor.savemap = 맵 저장 +editor.saved = 저장됨! +editor.save.noname = 지도에 이름이 없습니다! 메뉴 -> '맵 정보' 에서 설정하세요. +editor.save.overwrite = 이 맵의 이름은 기존에 있던 맵을 덮어씁니다! '맵 정보' 메뉴에서 다른 이름을 선택하세요. +editor.import.exists = [scarlet]맵을 불러올 수 없음 : [] 기존에 있던 '{0}' 맵이 이미 존재합니다! +editor.import = 가져오기 +editor.importmap = 맵 가져오기 +editor.importmap.description = 이미 존재하는 맵 가져오기 +editor.importfile = 파일 가져오기 +editor.importfile.description = 외부 맵 파일 가져오기 +editor.importimage = 지형 사진 가져오기 +editor.importimage.description = 외부 맵 이미지 파일 가져오기 +editor.export = 내보내기 +editor.exportfile = 파일 내보내기 +editor.exportfile.description = 맵 파일 내보내기 +editor.exportimage = 지형 이미지 내보내기 +editor.exportimage.description = 맵 이미지 파일 내보내기 +editor.loadimage = 지형 가져오기 +editor.saveimage = 지형 내보내기 +editor.unsaved = [scarlet]변경사항을 저장하지 않았습니다![]\n정말로 나가시겠습니까? +editor.resizemap = 맵 크기 조정 +editor.mapname = 맵 이름 : +editor.overwrite = [accept]경고!이 명령은 기존 맵을 덮어씌우게 됩니다. +editor.overwrite.confirm = [scarlet]경고![] 이 이름을 가진 맵이 이미 있습니다. 덮어 쓰시겠습니까? +editor.selectmap = 불러올 맵 선택 : +width = 넓이 : +height = 높이 : +menu = 메뉴 +play = 플레이 +load = 불러오기 +save = 저장 +fps = {0}FPS +tps = {0}TPS +ping = ping : {0}ms +language.restart = 언어를 변경하려면 게임을 다시시작 해 주세요. +settings = 설정 +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson]{0}[accent] 서버에 연결하지 못했습니다.[] +error.unreachable = 서버에 연결하지 못했습니다. +error.invalidaddress = 잘못된 주소입니다. +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 = 키 재설정 +settings.controls = 컨트롤 +settings.game = 게임 +settings.sound = 소리 +settings.graphics = 그래픽 +settings.cleardata = 게임 데이터 초기화... +settings.clear.confirm = 정말로 초기화 하겠습니까?\n이 작업을 되돌릴 수 없습니다! +settings.clearall.confirm = [scarlet]경고![]\n이 작업은 저장된 맵, 맵파일, 잠금 해제된 목록과 키 매핑, 그리고 모든 데이터를 삭제합니다.\n확인 버튼을 다시 눌러 모든 데이터를 삭제하고 게임에서 나갑니다. +settings.clearunlocks = 잠금 해제 초기화 +settings.clearall = 모두 초기화 +paused = 일시 정지 +yes = 예 +no = 아니오 +info.title = [accent]정보 +error.title = [crimson]오류가 발생했습니다. +error.crashtitle = 오류가 발생했습니다. +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.liquid = Liquid +blocks.coolantuse = 냉각수 사용 +blocks.inputliquidfuel = 연료 액 +blocks.liquidfueluse = 액체 연료 사용 +blocks.boostitem = 가속 아이템 +blocks.boostliquid = 가속 액체 +blocks.health = 체력 +blocks.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = 오차각 +blocks.shots = 발포 횟수 +blocks.reload = 재장전 +blocks.inputfuel = 연료 +blocks.fuelburntime = 연료 연소 시간 +blocks.inputcapacity = 입력 용량 +blocks.outputcapacity = 출력 용량 +unit.blocks = 블록 +unit.powersecond = 전력/초 +unit.liquidsecond = 액체/초 +unit.itemssecond = 개/초 +unit.pixelssecond = 초당 픽셀 +unit.liquidunits = 액체 +unit.powerunits = 전력 +unit.degrees = 도 +unit.seconds = 초 +unit.items = 아이템 +category.general = 일반 +category.power = 전력 +category.liquids = 액체 +category.items = 아이템 +category.crafting = 제작 +category.shooting = 사격 +category.optional = 선택적 가속 +setting.indicators.name = 인디게이터 표시 setting.autotarget.name = 자동 조준 setting.fpscap.name = 최대 FPS setting.fpscap.none = 없음 @@ -371,18 +379,22 @@ setting.mutemusic.name = 음소거 setting.sfxvol.name = 효과음 크기 setting.mutesound.name = 소리 끄기 setting.crashreport.name = 오류 보고서 보내기 -text.keybind.title = 조작키 설정 +keybind.title = 조작키 설정 category.general.name = 일반 category.view.name = 보기 category.multiplayer.name = 멀티플레이 command.attack = 공격 command.retreat = 후퇴 command.patrol = 순찰 +keybind.gridMode.name = 블록 선택 +keybind.gridModeShift.name = 카테고리 선택 keybind.press = 키를 누르세요... keybind.press.axis = 축 또는 키를 누르세요... +keybind.screenshot.name = Map Screenshot keybind.move_x.name = 오른쪽/왼쪽 이동 keybind.move_y.name = 위쪽/아래쪽 이동 keybind.select.name = 선택 +keybind.pick.name = Pick Block keybind.break.name = 파괴 keybind.deselect.name = 선택해제 keybind.shoot.name = 사격 @@ -401,50 +413,53 @@ keybind.chat_history_next.name = 다음 채팅기록 keybind.chat_scroll.name = 채팅 스크롤 keybind.drop_unit.name = 유닛 드롭 keybind.zoom_minimap.name = 미니맵 확대 -mode.text.help.title = 도움말 -mode.waves.name = 단계 -mode.waves.description = 이것은 일반 모드입니다. 제한된 자원과 자동으로 다음 단계가 시작됩니다. +mode.help.title = 도움말 +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 = 자유 건축 mode.freebuild.description = 제한된 자원과 다음단계 시작을 위한 타이머가 없습니다. mode.pvp.name = PvP mode.pvp.description = 몹이 아닌 실제 플레이어와 PvP를 합니다. +mode.attack.name = Attack +mode.attack.descrption = 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.copper.description = 모든 종류의 블록에서 광범위하게 사용되는 자원입니다. item.lead.name = 납 item.lead.description = 쉽게 구할 수 있으며, 전자 및 액체 수송 블록에서 광범위하게 사용되는 자원입니다. item.coal.name = 석탄 item.coal.description = 쉽게 구할 수 있으며, 주로 제련소 등에서 연료로 사용됩니다. -item.dense-alloy.name = 고밀도 합금 -item.dense-alloy.description = 납과 구리로 만든 튼튼한 고밀도 합금.\n고급 수송 블록이나 상위 티어 블록을 건설하는데 사용됩니다. +item.graphite.name = Graphite item.titanium.name = 티타늄 item.titanium.description = 파이프 재료나 고급 드릴, 비행기/기체 등에서 재료로 사용되는 자원입니다. item.thorium.name = 토륨 item.thorium.description = 건물의 재료, 포탑의 탄약 또는 핵연료로 사용되는 방사성 금속입니다. item.silicon.name = 실리콘 -item.silicon.description = 매우 유용한 반도체로, 태양 전지판과 복잡한 전자 제품에 사용할 수 있습니다. +item.silicon.description = 매우 유용한 반도체로, 기체를 만들거나 태양 전지판 등 전자 건물에 사용할 수 있습니다. item.plastanium.name = 플라스터늄 item.plastanium.description = 고급 항공기 및 분열 탄약에 사용되는 가벼운 연성 재료. item.phase-fabric.name = 메타 item.phase-fabric.description = 최첨단 전자 제품과 자기수리 기술에 사용되는 거의 무중력에 가까운 물질입니다. item.surge-alloy.name = 설금 -item.surge-alloy.description = 주로 건물의 재료로 사용되는 자원입니다 +item.surge-alloy.description = 독특한 전기 특성을 가진 고급 합금입니다. item.biomatter.name = 바이오메터 item.biomatter.description = 이것은 유기농 덤불입니다!\n압축기에 넣어 석유로 바꿀 수 있습니다. item.sand.name = 모래 -item.sand.description = 고밀도 합금이나 플럭스 등에서 제련시 광범위하게 사용되는 일반적인 재료입니다. +item.sand.description = 고밀도 합금 제작이나 제련시 이 광물을 사용하여 소모 재료를 줄이는 등 광범위하게 사용되는 일반적인 재료입니다. item.blast-compound.name = 폭발물 item.blast-compound.description = 포탑 및 건설의 재료로 사용되는 휘발성 폭발물.\n연료로도 사용할 수 있지만, 별로 추천하지는 않습니다. 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.oil.name = 석유 @@ -464,38 +479,43 @@ mech.tau-mech.description = 지원형 기체.\n총을 발사하여 건물을 치 mech.omega-mech.name = 오메가 mech.omega-mech.weapon = 전방 유도미사일 mech.omega-mech.ability = 방어모드 -mech.omega-mech.description = 지상 기체 최종판이자 건물 파괴용으로 적합한 부피가 크고 튼튼한 기체. 방어 모드는 최대 90% 의 피해를 줄일 수 있습니다. +mech.omega-mech.description = 지상 기체 최종판이자 건물 파괴용으로 적합한 부피가 크고 튼튼한 기체.\n방어 모드는 최대 90% 의 피해를 줄일 수 있습니다. mech.dart-ship.name = 다트 mech.dart-ship.weapon = 소총 -mech.dart-ship.description = 표준 비행선. 빠르고 가볍지만 공격력이 거의 없고 채광 속도가 느립니다. +mech.dart-ship.description = 표준 비행선.\n빠르고 가볍지만 공격력이 거의 없고 채광 속도가 느립니다. mech.javelin-ship.name = 자비린 -mech.javelin-ship.description = 치고 빠지는 공격을 위한 비행선. 처음에는 느리지만, 가속도가 붙어 엄청난 속도로 미사일 피해를 입힐 수 있으며, 전격 능력을 사용할 수 있습니다. +mech.javelin-ship.description = 치고 빠지는 공격을 위한 비행선.\n처음에는 느리지만, 가속도가 붙어 엄청난 속도로 미사일 피해를 입힐 수 있으며, 전격 능력을 사용할 수 있습니다. mech.javelin-ship.weapon = 유도 미사일 mech.javelin-ship.ability = 가속 전격 생성기 mech.trident-ship.name = 삼지창 -mech.trident-ship.description = 대형 공중 폭격기. 당연하게도 엄청 단단합니다. +mech.trident-ship.description = 대형 공중 폭격기.\n당연하게도 엄청 단단합니다. mech.trident-ship.weapon = 폭탄 저장고 mech.glaive-ship.name = 글레브 -mech.glaive-ship.description = 크고 잘 무장된 총을 가진 비행선. 방화용 리피터가 장착되어 있으며, 가속도와 최대속도가 높습니다. +mech.glaive-ship.description = 크고 잘 무장된 총을 가진 비행선.\n방화용 리피터가 장착되어 있으며, 가속도와 최대속도가 높습니다. mech.glaive-ship.weapon = 방화총 -text.item.explosiveness = [LIGHT_GRAY]폭발력 : {0} -text.item.flammability = [LIGHT_GRAY]인화성 : {0} -text.item.radioactivity = [LIGHT_GRAY]방사능 : {0} -text.item.fluxiness = [LIGHT_GRAY]플럭스 파워 : {0} -text.unit.health = [LIGHT_GRAY]체력 : {0} -text.unit.speed = [LIGHT_GRAY]속도 : {0} -text.mech.weapon = [LIGHT_GRAY]무기 : {0} -text.mech.armor = [LIGHT_GRAY]방어력 : {0} -text.mech.itemcapacity = [LIGHT_GRAY]아이템 수용 용량 : {0} -text.mech.minespeed = [LIGHT_GRAY]채광 속도 : {0} -text.mech.minepower = [LIGHT_GRAY]채광 레벨 : {0} -text.mech.ability = [LIGHT_GRAY]능력 : {0} -text.liquid.heatcapacity = [LIGHT_GRAY]발열량 : {0} -text.liquid.viscosity = [LIGHT_GRAY]점도 : {0} -text.liquid.temperature = [LIGHT_GRAY]온도 : {0} +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]Health: {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.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](만드는중) block.spawn.name = 적 스폰지점 -block.core.name = 코어 +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = 철판 block.deepwater.name = 깊은물 block.water.name = 물 @@ -514,8 +534,8 @@ block.blackrock.name = 검은바위 block.icerock.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 = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = 메타벽 block.phase-wall-large.name = 큰 메타벽 block.thorium-wall.name = 토륨벽 @@ -548,17 +568,19 @@ 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 = 삼지창 비행선 패드 @@ -567,11 +589,11 @@ block.omega-mech-pad.name = 오메가 기체 패드 block.tau-mech-pad.name = 타우 기체 패드 block.conduit.name = 파이프 block.mechanical-pump.name = 기계식 펌프 -block.itemsource.name = 아이템 소스 -block.itemvoid.name = 아이템 삭제 장치 -block.liquidsource.name = 무한 액체공급 장치 -block.powervoid.name = 방전장치 -block.powerinfinite.name = 무한 전력공급 장치 +block.item-source.name = 아이템 소스 +block.item-void.name = 아이템 삭제 장치 +block.liquid-source.name = 무한 액체공급 장치 +block.power-void.name = 방전장치 +block.power-source.name = 무한 전력공급 장치 block.unloader.name = 언로더 block.vault.name = 창고 block.wave.name = 파도 @@ -605,7 +627,7 @@ block.bridge-conduit.name = 다리 파이프 block.rotary-pump.name = 동력 펌프 block.thorium-reactor.name = 토륨 원자로 block.command-center.name = 명령 본부 -block.mass-driver.name = 물질 이동기 +block.mass-driver.name = 자원 발사기 block.blast-drill.name = 고속 발열 드릴 block.thermal-pump.name = 화력 펌프 block.thermal-generator.name = 열발전기 @@ -618,11 +640,12 @@ block.fuse.name = 퓨즈 block.shock-mine.name = 전격 지뢰 block.overdrive-projector.name = 오버드라이브 프로젝터 block.force-projector.name = 보호막 프로젝터 -block.arc.name = Arc +block.arc.name = 아크 block.rtg-generator.name = 토륨 발전소 block.spectre.name = 스펙터 block.meltdown.name = 멜트다운 block.container.name = 컨테이너 +block.launch-pad.name = Launch Pad team.blue.name = 블루팀 team.red.name = 레드팀 team.orange.name = 오렌지팀 @@ -631,21 +654,26 @@ team.green.name = 그린팀 team.purple.name = 보라색팀 unit.alpha-drone.name = 알파 드론 unit.spirit.name = 스피릿 드론 -unit.spirit.description = 기본 드론 유닛. 기본적으로 코어에서 1개가 스폰됩니다. 자동으로 채광하며 아이템을 수집하고, 블록을 수리합니다. +unit.spirit.description = 기본 드론 유닛. 기본적으로 코어에서 1개가 스폰됩니다.\n자동으로 채광하며 아이템을 수집하고, 블록을 수리합니다. unit.phantom.name = 팬텀 드론 -unit.phantom.description = 첨단 드론 유닛. 광석을 자동으로 채광하며, 아이템을 수집하고 블록을 수리합니다. 일반 드론보다 훨씬 효과적입니다. +unit.phantom.description = 첨단 드론 유닛.\n광석을 자동으로 채광하며, 아이템을 수집하고 블록을 수리합니다. 일반 드론보다 훨씬 효과적입니다. unit.dagger.name = 디거 -unit.dagger.description = 기본 지상 유닛입니다. 스웜과 같이 쓰면 유용합니다. +unit.dagger.description = 기본 지상 유닛입니다.\n플레이어 기체처럼 드론을 소환하지는 않습니다. +unit.crawler.name = Crawler unit.titan.name = 타이탄 -unit.titan.description = 고급 지상 유닛입니다. 고밀도 합금을 탄약으로 사용하며 지상과 공중 둘다 공격할 수 있습니다. +unit.titan.description = 고급 지상 유닛입니다.\n원거리 총 대신에 근접 화염 방사기를 가지고 있으며, 지상과 공중 둘다 공격할 수 있습니다. unit.ghoul.name = 구울 폭격기 -unit.ghoul.description = 무거운 지상 폭격기 입니다. 폭발물 또는 피라테를 탄약으로 사용합니다. +unit.ghoul.description = 무겁고 튼튼한 지상 폭격기 입니다.\n주로 적 건물로 이동하여 엄청난 폭격을 가합니다. unit.wraith.name = 유령 전투기 -unit.wraith.description = 코어를 집중적으로 공격하는 방식을 사용하는 전투기 입니다. +unit.wraith.description = 적 핵심 건물 및 유닛을 집중적으로 공격하는 방식을 사용하는 전투기 입니다. unit.fortress.name = 포트리스 -unit.fortress.description = 중포 지상 유닛. 높은 공격력과 체력을 가지고 있습니다. +unit.fortress.description = 중포 지상 유닛.\n높은 공격력을 가진 총과 높은 체력을 가지고 있습니다. 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]구리를 채광[]하는 것으로 시작합니다.\n이것을 하기 위해 플레이어의 중심부 근처에 있는 구리 광맥을 누르세요. tutorial.drill = 수동으로 채광하는 것은 효율이 낮습니다.\n[accent]드릴[]은 자동으로 채광 작업을 합니다.\n구리 광맥에 표시된 영역에 드릴을 하나를 놓으세요. tutorial.conveyor = [accent]컨베이어[]를 사용하여 아이템을 코어로 운반합니다.\n드릴에서 코어까지 컨베이어 라인을 만드세요. @@ -667,38 +695,37 @@ tutorial.daggerfactory = 이[accent] 디거 기체 공장[]은\n\n공격하는 tutorial.router = 공장을 작동시키기 위해 자원이 필요합니다.\n컨베이어에 운반되고 있는 자원을 분할할 분배기를 만드세요. tutorial.dagger = 전력 노드를 공장에 연결하세요.\n일단 요구 사항이 충족되면 기체 생산을 시작합니다.\n\n필요에 따라 드릴 및 발전기, 컨베이어를 더 많이 만들 수 있습니다. tutorial.battle = [LIGHT_GRAY]적[]의 코어가 드러났습니다.\n당신의 부대와 디거를 사용하여 파괴하세요. -block.core.description = 게임에서 가장 중요한 건물.\n파괴되면 게임이 끝납니다. -block.copper-wall.description = 구리로 만든 벽. -block.copper-wall-large.description = 구리로 만든 큰 벽. -block.dense-alloy-wall.description = 고밀도 합금으로 만든 벽. 구리벽보다 체력이 높습니다. -block.dense-alloy-wall-large.description = 고밀도 합금으로 만든 큰 벽. -block.thorium-wall.description = 토륨으로 만든 벽. -block.thorium-wall-large.description = 토륨으로 만든 큰 벽. -block.phase-wall.description = 날라오는 모든 총알을 튕겨내고 데미지를 입는 특수한 벽입니다. -block.phase-wall-large.description = 메타로 제작한 큰 벽. 날라오는 총알을 모두 튕겨냅니다. +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 = 유닛이 지나갈 수 있도록 만든 문. 클릭하면 열고 닫습니다. -block.door-large.description = 유닛이 자나갈 수 있도록 만든 큰 문. 클릭하면 열고 닫습니다. -block.mend-projector.description = 주위 건물을 치료하는 건물입니다. -block.overdrive-projector.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.duo.description = 범용성을 가진 터렛.\n지상 및 공중공격을 하며, 초반에 유용합니다. block.arc.description = 목표 방향으로 전격 공격을 하는 포탑입니다. -block.hail.description = 장거리 지상 공격을 하는 터렛입니다.\n적이 오기 전에 쓸어버릴 수 있습니다. +block.hail.description = 장거리 지상 공격을 하는 터렛입니다.\n적이 공격하기 전에 쓸어버릴 수 있습니다. block.lancer.description = 중거리 레이져 포탑입니다.\n적을 관통하기 때문에 뭉쳐있는 적들에게 매우 효과적입니다. -block.wave.description = 적이 있는 자리에 액체를 뿌립니다.\n이 포탑을 활용하여 액체를 뿌린 곳에 불을 붙이거나 적을 느리게 할 수 있습니다. +block.wave.description = 적이 있는 자리에 액체를 뿌립니다.\n이 포탑을 활용하여 액체를 뿌린 곳에 불을 붙이거나 적을 느리게 할 수 있습니다. block.salvo.description = 명중률이 높고, 3발씩 끊어 발사하는 포탑입니다. block.swarmer.description = 4발씩 끊어서 유도체를 발사하는 포탑입니다 block.ripple.description = 4개의 탄약으로 나눠 발사하여 명중률이 낮지만, 사거리가 매우 긴 포탑입니다. -block.cyclone.description = 낮은 명중률과 높은 RPM 을 가진 포탑입니다.\n탄약이 남아있는 한 멈추지 않고 계속 연사합니다. +block.cyclone.description = 낮은 명중률과 높은 RPM 을 가진 포탑입니다.\n사격하는데 쿨타임이 거의 없습니다. block.fuse.description = 단거리에서 범위형 레이저를 발사하는 포탑입니다. block.spectre.description = 높은 명중률과 RPM 을 가진 포탑입니다.\n탄약이 남아있는 한 멈추지 않고 계속 연사합니다. -block.meltdown.description = 목표를 따라 초대형 레이져를 발사하는 포탑입니다.\n뭉쳐있는 몹에게 매우 효과가 좋습니다. +block.meltdown.description = 목표를 따라 초대형 레이져를 발사하는 포탑입니다.\n조준 시간이 길어 공중에는 적합하지 않지만 뭉쳐있는 몹에게 매우 효과가 좋습니다. block.conveyor.description = 느린 속도로 자원을 수송할 수 있는 컨베이어. block.titanium-conveyor.description = 빠른 속도로 자원을 수송할 수 있는 컨베이어. -block.phase-conveyor.description = 자원을 순간이동 시켜 주는 컨베이어 입니다. +block.phase-conveyor.description = 자원을 지정된 방향으로 바로 이동시켜 주는 컨베이어 입니다. block.junction.description = 컨베이어를 교차시켜 자원을 수송할 때 사용할 수 있는 블록입니다. block.mass-driver.description = 자원을 받아서 다른 물질 이동기로 전달할 수 있는 블록입니다.\n엄청난 사거리를 가지고 있으며, 주로 컨베이어가 접근할 수 없는 곳에 유용하게 사용됩니다. block.smelter.description = 고밀도 합금을 제작할 수 있는 건물입니다. @@ -714,8 +741,8 @@ block.cryofluidmixer.description = 냉각수를 제작할 수 있는 건물입 block.solidifer.description = 용암을 돌로 만들 수 있는 건물입니다. block.melter.description = 돌로 용암을 만들 수 있는 건물입니다. block.incinerator.description = 불필요한 아이템을 소각시켜 줄 수 있는 건물입니다. -block.biomattercompressor.description = 잔디밭에서 바이오메터를 추출할 수 있는 건물입니다. -block.separator.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물입니다. +block.biomattercompressor.description = 잔디밭에서 바이오메터를 추출할 수 있는 건물입니다. +block.separator.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물입니다. block.centrifuge.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물이지만, 이 건물은 좀 더 다양한 자원을 얻을 수 있게 해 줍니다. block.power-node.description = 생성된 전력를 다른 건물로 전달하기 위한 전력 노드입니다. block.power-node-large.description = 생성된 전력를 다른 건물로 전달하기 위한 건물이며, 일반 노드보다 더 많은 전력을 이동시킬 수 있습니다. @@ -729,33 +756,33 @@ block.solar-panel-large.description = 태양열을 받아 자기 스스로 전 block.thorium-reactor.description = 토륨을 원료로 하는 토륨 원자로 입니다.\n많은 전력을 생산하지만 엄청난 열을 발생시키기 때문에, 많은 량의 물 또는 냉각수가 있어야 터지지 않고 작동합니다. block.rtg-generator.description = 냉각은 필요 없지만 토륨 원자로보다 적은량의 전력을 생산하는 방사선 동위원소 열전자 발전기. block.unloader.description = 해당 창고 및 코어에서 자원을 빼내는데 사용됩니다. -block.container.description = 아이템을 임시로 저장할 수 있는 소형 창고입니다. -block.vault.description = 아이템을 임시로 저장할 수 있는 대형 창고입니다. +block.container.description = 아이템을 저장할 수 있는 소형 창고입니다. +block.vault.description = 아이템을 저장할 수 있는 대형 창고입니다. block.mechanical-drill.description = 구리로 제작할 수 있는 기본 드릴입니다. block.pneumatic-drill.description = 돌, 티타늄을 채광할 수 있는 고급 드릴입니다. block.laser-drill.description = 토륨을 채광할 수 있는 최고급 드릴입니다.\n전력과 물을 공급하여 빠른 속도로 채광할 수 있습니다. -block.blast-drill.description = 최상위 드릴입니다. 엄청난 양의 전력과 물을 소모하는 대신, 매우 빠른 속도로 채광합니다. +block.blast-drill.description = 최상위 드릴입니다.\n엄청난 양의 전력과 물을 소모하는 대신, 매우 빠른 속도로 채광합니다. block.water-extractor.description = 바닥에서 물을 추출하여 건물에 공급할 수 있는 건물입니다. block.cultivator.description = 잔디에서 바이오메터를 추출할 수 있는 건물입니다. block.oil-extractor.description = 석유를 추출 해 주는 건물입니다. -block.dart-ship-pad.description = 다트 비행선으로 바꿀 수 있는 패드입니다. -block.trident-ship-pad.description = 삼지창 비행선으로 바꿀 수 있는 패드입니다. -block.javelin-ship-pad.description = 자비린 비행선으로 바꿀 수 있는 패드입니다. -block.glaive-ship-pad.description = 글레브 비행선으로 바꿀 수 있는 패드입니다. -block.tau-mech-pad.description = 타우 기체로 바꿀 수 있는 패드 -block.delta-mech-pad.description = 델타 기체로 바꿀 수 있는 패드입니다. -block.omega-mech-pad.description = 오메가 기체로 바꿀 수 있는 패드 -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.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.conduit.description = 일반 파이프. 액체가 지나갈 수 있도록 해 줍니다. +block.conduit.description = 일반 파이프.\n액체가 지나갈 수 있도록 해 줍니다. block.pulse-conduit.description = 티타늄으로 만들어 졌으며, 일반 파이프보다 액체 수용량이 높습니다. block.phase-conduit.description = 물을 먼거리로 순간이동 시켜 주는 장치입니다. block.liquid-router.description = 물펌프를 다른 방향으로 분배할 수 있게 하는 블럭입니다. @@ -767,13 +794,13 @@ block.rotary-pump.description = 일반 물 펌프보다 더 빠른 속도로 물 block.thermal-pump.description = 기계식 펌프보다 3배 빠른 속도로 액체를 퍼올릴 수 있는 펌프이며, 용암도 퍼올릴 수 있는 유일한 펌프입니다. block.router.description = 한 방향에서 아이템을 받은 후 최대 3개의 다른 방향으로 동일하게 출력합니다.\n재료를 한곳에서 여러 대상으로 분할하여 운반하는데 유용합니다. block.distributor.description = 아이템을 최대 7개의 다른 방향으로 똑같이 분할하는 고급 분배기. -block.bridge-conveyor.description = 고급 자원 수송 블록.\n지형이나 건물을 넘어 최대 3개 타일을 건너뛰고 자원을 운송할 수 있습니다. +block.bridge-conveyor.description = 고급 자원 수송 블록.\n지형이나 건물을 넘어 최대 3개 타일을 건너뛰고 자원을 운송할 수 있습니다. block.alpha-mech-pad.description = 알파 기체로 바꿀 수 있는 패드입니다. -block.itemsource.description = 자원을 선택하면 그 자원이 무한하게 생성되는 블록입니다. -block.liquidsource.description = 무한한 액체를 출력해냅니다. -block.itemvoid.description = 아이템을 사라지게 만듭니다. -block.powerinfinite.description = 무한한 전력을 공급해주는 블록입니다. -block.powervoid.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 = 일부 조합 블록에서 사용되는 자원입니다. diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index 93a78942b5..ca030d032f 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -1,356 +1,364 @@ -text.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!) -text.credits = Zasłużeni -text.discord = Odwiedź nasz serwer Discord -text.link.discord.description = Oficjalny serwer Discord Mindustry -text.link.github.description = Kod Gry -text.link.dev-builds.description = Niestabilne wersje gry -text.link.trello.description = Oficjalna tablica Trello z planowanym funkcjami -text.link.itch.io.description = Strona itch.io z oficjanymi wersjami do pobrania -text.link.google-play.description = Google Play store listing -text.link.wiki.description = Oficjana Wiki Mindustry -text.linkfail = Nie udało się otworzyć linku!\nURL został skopiowany. -text.gameover = Rdzeń został zniszczony. -text.gameover.pvp = The[accent] {0}[] team is victorious! -text.sector.gameover = This sector has been lost. Re-deploy? -text.sector.retry = Retry -text.highscore = [YELLOW] Nowy rekord! -text.wave.lasted = You lasted until wave [accent]{0}[]. -text.level.highscore = Rekord: [accent]{0} -text.level.delete.title = Potwierdź usuwanie -text.map.delete = Jesteś pewny, że chcesz usunąć "[accent]{0}[]"? -text.level.select = Wybrany poziom -text.level.mode = Tryb gry: -text.construction.desktop = Desktop controls have been changed.\nTo deselect a block or stop building, [accent]use space[]. -text.construction.title = Poradnik tworzenia bloków -text.construction = Wybrałeś [accent]tryb tworzenia bloków[].\n\nAby zacząć stawiać bloki, po prostu kliknij na dostępne pole obok twojego statku.\nKiedy wybrałeś kilka bloków, kliknij ptaszek i twój statek zacznie budować bloki.\n\n- [accent]Anuluj bloki[] z twojej kolekcji przez klikanie ich(?).\n- [accent]Przesuwaj bloki w kolekcji[] przez przeciąganie ich w opowiednim kierunku.\n- [accent]Stawiaj bloki w lini[] przez kliknięcie w wybranym miejscu i przesuięcie palca.\n- [accent]Anuluj konstrukcję lub kolekcję [] przez kliknięcie X w lewym dolnym rogu. -text.deconstruction.title = Poradnik niszczenia bloków -text.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. -text.showagain = Nie pokazuj tego więcej -text.coreattack = < Core is under attack! > -text.unlocks = Lista przedmiotów -text.savegame = Zapisz Grę -text.loadgame = Wczytaj grę -text.joingame = Gra wieloosobowa -text.addplayers = Dodaj/Usuń graczy -text.customgame = Własna Gra -text.sectors = Sektory -text.sector = Wybrany Sektor: [LIGHT_GRAY]{0} -text.sector.time = Czas: [LIGHT_GRAY]{0} -text.sector.deploy = Wejdź -text.sector.abandon = Abandon -text.sector.abandon.confirm = Are you sure you want to abandon all progress at this sector?\nThis cannot be undone! -text.sector.resume = Wznów -text.sector.locked = [scarlet][[Niegotowy] -text.sector.unexplored = [accent][[Nieodkryty] -text.missions = Missions:[LIGHT_GRAY] {0} -text.mission = Mission:[LIGHT_GRAY] {0} -text.mission.main = Main Mission:[LIGHT_GRAY] {0} -text.mission.info = Mission Info -text.mission.complete = Mission complete! -text.mission.complete.body = Sector {0},{1} has been conquered. -text.mission.wave = Survive[accent] {0}/{1} []waves\nWave in {2} -text.mission.wave.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies -text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy -text.mission.wave.menu = Survive[accent] {0} []waves -text.mission.battle = Destroy the enemy base. -text.mission.resource.menu = Obtain {0} x{1} -text.mission.resource = Obtain {0}:\n[accent]{1}/{2}[] -text.mission.block = Create {0} -text.mission.unit = Create {0} Unit -text.mission.command = Send Command {0} To Units -text.mission.linknode = Link Power Node -text.mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -text.mission.mech = Switch to mech[accent] {0}[] -text.mission.create = Create[accent] {0}[] -text.none = -text.close = Zamknij -text.quit = Wyjdź -text.maps = Mapy -text.continue = Continue -text.nextmission = Next Mission -text.maps.none = [LIGHT_GRAY]Nie znaleziono żadnych map! -text.about.button = O grze -text.name = Nazwa: -text.filename = File Name: -text.unlocked = Odblokowano nowy blok! -text.unlocked.plural = Odblokowano nowe bloki! -text.players = {0} graczy online -text.players.single = {0} gracz online -text.server.closing = [accent] Zamykanie serwera... -text.server.kicked.kick = Zostałeś wyrzucony z serwera! -text.server.kicked.serverClose = Server closed. -text.server.kicked.sectorComplete = Sector completed. -text.server.kicked.sectorComplete.text = Your mission is complete.\nThe server will now continue at the next sector. -text.server.kicked.clientOutdated = Nieaktualna gra! Zaktualizują ją! -text.server.kicked.serverOutdated = Nieaktualny serwer! -text.server.kicked.banned = Zostałeś zbanowany na tym serwerze. -text.server.kicked.recentKick = Zostałeś niedawno wyrzucony.\nPoczekaj chwilę przed ponownym połączniem. -text.server.kicked.nameInUse = Ta nazwa jest już zajęta na tym serwerze. -text.server.kicked.nameEmpty = Nazwa musi zawierać przynajmniej 1 literę lub cyfrę. -text.server.kicked.idInUse = Jesteś już na serwerze! Używanie tego samego konta na 2 urządzeniach jest zabronione. -text.server.kicked.customClient = Ten serwer nie wspomaga wersji deweloperskich. Pobierz oryginalną wersję. -text.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. -text.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. -text.hostserver = Stwórz Serwer -text.hostserver.mobile = Host\nGame -text.host = Host -text.hosting = [accent] Otwieranie serwera... -text.hosts.refresh = Odśwież -text.hosts.discovering = Wyszukiwanie gier w sieci LAN -text.server.refreshing = Odświeżanie serwera -text.hosts.none = [lightgray] Brak serwerów w sieci LAN! -text.host.invalid = [scarlet] Nie można połączyć się z hostem. -text.trace = Zlokalizuj gracza -text.trace.playername = Nazwa gracza: [accent]{0} -text.trace.ip = IP: [accent]{0} -text.trace.id = Wyjątkowae ID: [accent]{0} -text.trace.android = Klient Androida: [accent]{0} -text.trace.modclient = Zmodowany klient: [accent]{0} -text.trace.totalblocksbroken = Łączna liczba zniszczonych bloków: [accent]{0} -text.trace.structureblocksbroken = Zniszczone bloki struktur: [accent]{0} -text.trace.lastblockbroken = Ostatni zniszczony blok: [accent]{0} -text.trace.totalblocksplaced = Łączna liczba zbudowanych bloków: [accent]{0} -text.trace.lastblockplaced = Ostatni postawiony blok: [accent]{0} -text.invalidid = Złe ID klienta! Udostępnij report błędu. -text.server.bans = Bany -text.server.bans.none = Nie znaleziono zbanowanych osób! -text.server.admins = Admini -text.server.admins.none = Nie znaleziono adminów! -text.server.add = Dodaj serwer -text.server.delete = Czy na pewno chcesz usunąć ten serwer? -text.server.hostname = Host: {0} -text.server.edit = Edytuj serwer -text.server.outdated = [crimson]Przestarzały serwer![] -text.server.outdated.client = [crimson]Przestarzały klient![] -text.server.version = [lightgray]Wersja: {0} -text.server.custombuild = [yellow]Zmodowany klient -text.confirmban = Jesteś pewny, że chcesz zbanować tego gracza? -text.confirmkick = Are you sure you want to kick this player? -text.confirmunban = Jesteś pewny, że chcesz odbanować tego gracza? -text.confirmadmin = Jesteś pewny, że chcesz dać rangę admina temu graczowi? -text.confirmunadmin = Jesteś pewny, że chcesz zabrać rangę admina temu graczowi? -text.joingame.title = Dołącz do gry -text.joingame.ip = IP: -text.disconnect = Rozłączono. -text.disconnect.data = Nie udało się załadować mapy! -text.connecting = [accent]Łączenie... -text.connecting.data = [accent]Ładowanie danych świata... -text.server.port = Port: -text.server.addressinuse = Adres jest już w użyciu! -text.server.invalidport = Nieprawidłowy numer portu. -text.server.error = [crimson]Błąd hostowania serwera: [accent] {0} -text.save.old = Ten zapis jest ze starej wersji i gra nie może go teraz wczytać.\n\n[LIGHT_GRAY]Wsparcie starych zapisów będzie w pełnej wersji 4.0. -text.save.new = Nowy zapis -text.save.overwrite = Czy na pewno chcesz nadpisać zapis gry? -text.overwrite = Nadpisz -text.save.none = Nie znaleziono zapisów gry! -text.saveload = [accent]Zapisywanie... -text.savefail = Nie udało się zapisać gry! -text.save.delete.confirm = Czy na pewno chcesz usunąć ten zapis gry? -text.save.delete = Usuń -text.save.export = Eksportuj -text.save.import.invalid = [accent]Zapis gry jest niepoprawny! -text.save.import.fail = [crimson]Nie udało się zaimportować zapisu: [accent] {0} -text.save.export.fail = [crimson]Nie można wyeksportować zapisu: [accent] {0} -text.save.import = Importuj -text.save.newslot = Zapisz nazwę: -text.save.rename = Zmień nazwę -text.save.rename.text = Zmień nazwę -text.selectslot = Wybierz zapis. -text.slot = [accent]Slot {0} -text.save.corrupted = [accent]Zapis gry jest uszkodzony lub nieprawidłowy! -text.sector.corrupted = [accent]A save file for this sector was found, but loading failed.\nA new one has been created. -text.empty = -text.on = Włączone -text.off = Wyłączone -text.save.autosave = Zapisywanie automatyczne -text.save.map = Mapa: {0} -text.save.wave = Fala: {0} -text.save.difficulty = Poziom trudności: {0} -text.save.date = Ostatnio zapisano: {0} -text.save.playtime = Czas gry: {0} -text.confirm = Potwierdź -text.delete = Usuń -text.ok = Ok -text.open = Otwórz -text.cancel = Anuluj -text.openlink = Otwórz link -text.copylink = Kopiuj link -text.back = Wróć -text.quit.confirm = Czy na pewno chcesz wyjść? -text.changelog.title = Lista Zmian -text.changelog.loading = Pobieranie listy zmian... -text.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. -text.changelog.error.ios = [accent]Lista zmian nie wspiera IOS. -text.changelog.error = [scarlet]Bład w pobieraniu listy zmian!\nSprawdź połączenie z internetem. -text.changelog.current = [yellow][[Twoja wersja] -text.changelog.latest = [accent][[Najnowsza wersja] -text.loading = [accent]Ładowanie... -text.saving = [accent]Zapisywanie... -text.wave = [accent]Fala {0} -text.wave.waiting = Fala za {0} -text.waiting = Oczekiwanie... -text.waiting.players = Waiting for players... -text.wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining -text.wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining -text.loadimage = Załaduj obraz -text.saveimage = Zapisz obraz -text.unknown = Nieznane -text.custom = Własne -text.builtin = Wbudowane -text.map.delete.confirm = Jesteś pewny, że chcesz usunąć tę mapę? Nie będzie można jej przywrócić. -text.map.random = [accent]Losowa mapa -text.map.nospawn = Ta mapa nie zawiera żadnego rdzenia! Musisz dodać [ROYAL]niebieski[] rdzeń do tej mapy. -text.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. -text.map.invalid = Error loading map: corrupted or invalid map file. -text.editor.brush = Pędzel -text.editor.slope = \\ -text.editor.openin = Otwórz w edytorze -text.editor.oregen = Generacja złóż -text.editor.oregen.info = Generacja złóż: -text.editor.mapinfo = Informacje o mapie -text.editor.author = Autor: -text.editor.description = Opis: -text.editor.name = Nazwa: -text.editor.teams = Drużyny -text.editor.elevation = Poziom terenu -text.editor.errorimageload = Błąd podczas ładowania pliku obrazu: [accent]{0} -text.editor.errorimagesave = Błąd podczas zapisywania pliku obrazu: [accent]{0} -text.editor.generate = Generuj -text.editor.resize = Zmień rozmiar -text.editor.loadmap = Załaduj mapę -text.editor.savemap = Zapisz mapę -text.editor.saved = Zapisano! -text.editor.save.noname = Twoja mapa nie ma nazwy! Ustaw ją w 'Informacjach o mapie'. -text.editor.save.overwrite = Ta mapa nadpisze wbudowaną mapę! Ustaw inną nazwę w 'Informacjach o mapie'. -text.editor.import.exists = [scarlet]Nie można zaimportować:[] istnieje już wbudowana mapa pod nazwą'{0}'! -text.editor.import = Importuj... -text.editor.importmap = Importuj Mapę -text.editor.importmap.description = Importuj istniejącą mapę -text.editor.importfile = Importuj Plik -text.editor.importfile.description = Importuj zewnętrzny plik mapy -text.editor.importimage = Importuj Obraz Terenu -text.editor.importimage.description = Importuj zewnętrzny obraz terenu -text.editor.export = Eksportuj... -text.editor.exportfile = Eksportuj mapę -text.editor.exportfile.description = Eksportuj plik mapy -text.editor.exportimage = Eksportuj Obraz Terenu -text.editor.exportimage.description = Eksportuj plik obrazu terenu -text.editor.loadimage = Załaduj obraz -text.editor.saveimage = Zapisz obraz -text.editor.unsaved = [scarlet]Masz niezapisane zmiany![]\nCzy na pewno chcesz wyjść? -text.editor.resizemap = Zmień rozmiar mapy -text.editor.mapname = Nazwa mapy: -text.editor.overwrite = [accent]Uwaga!\nSpowoduje to nadpisanie istniejącej mapy. -text.editor.overwrite.confirm = [scarlet]Uwaga![] Mapa pod tą nazwą już istnieje. Jesteś pewny, że chcesz ją nadpisać? -text.editor.selectmap = Wybierz mapę do załadowania: -text.width = Szerokość: -text.height = Wysokość: -text.menu = Menu -text.play = Graj -text.load = Wczytaj -text.save = Zapisz -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Ping: {0}ms -text.language.restart = Uruchom grę ponownie aby ustawiony język zaczął funkcjonować. -text.settings = Ustawienia -text.tutorial = Poradnik -text.editor = Edytor -text.mapeditor = Edytor map -text.donate = Wspomóż nas -text.connectfail = [crimson]Nie można połączyć się z serwerem: [accent] {0} -text.error.unreachable = Server unreachable. -text.error.invalidaddress = Invalid address. -text.error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! -text.error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! -text.error.alreadyconnected = Already connected. -text.error.mapnotfound = Map file not found! -text.error.any = Unkown network error. -text.settings.language = Język -text.settings.reset = Przywróć domyślne -text.settings.rebind = Zmień przyciski -text.settings.controls = Sterowanie -text.settings.game = Gra -text.settings.sound = Dźwięk -text.settings.graphics = Grafika -text.settings.cleardata = Clear Game Data... -text.settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! -text.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. -text.settings.clearsectors = Clear Sectors -text.settings.clearunlocks = Clear Unlocks -text.settings.clearall = Clear All -text.paused = Wstrzymano -text.yes = Jasne! -text.no = Nie ma mowy! -text.info.title = [accent]Informacje -text.error.title = [crimson]Wystąpił błąd -text.error.crashtitle = Wystąpił błąd -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = Informacje o bloku -text.blocks.powercapacity = Pojemność mocy -text.blocks.powershot = moc / strzał -text.blocks.targetsair = Może namierzać wrogów powietrznych -text.blocks.itemspeed = Szybkość Transporterów -text.blocks.shootrange = Zasięg -text.blocks.size = Rozmiar -text.blocks.liquidcapacity = Pojemność cieczy -text.blocks.maxitemssecond = Maksymalna liczba przedmiotów / Sekunda -text.blocks.powerrange = Zakres mocy -text.blocks.poweruse = Zużycie prądu -text.blocks.powerdamage = Power/Damage -text.blocks.inputitemcapacity = Pojemność materiałów -text.blocks.outputitemcapacity = Pojemność produktów -text.blocks.itemcapacity = Pojemność przedmiotów -text.blocks.basepowergeneration = Base Power Generation -text.blocks.powertransferspeed = Szybość przesyłu prądu -text.blocks.craftspeed = Szybkość produkcji -text.blocks.inputliquid = Potrzebna ciecz -text.blocks.inputliquidaux = Płyny do produkcji -text.blocks.inputitem = Potrzebne przedmioty -text.blocks.inputitems = Materiały do produkcji -text.blocks.outputitem = Produkty -text.blocks.drilltier = Co może wykopać -text.blocks.drillspeed = Postawowa szybkość kopania -text.blocks.liquidoutput = Wyprodukowany płyn -text.blocks.liquidoutputspeed = Liquid Output Speed -text.blocks.liquiduse = Zużycie płynów -text.blocks.coolant = Płyn chłodzący -text.blocks.coolantuse = Zużycie płynu chłodzącego -text.blocks.inputliquidfuel = Paliwo -text.blocks.liquidfueluse = Zużycie paliwa -text.blocks.boostitem = Boost Item -text.blocks.boostliquid = Boost Liquid -text.blocks.health = Zdrowie -text.blocks.inaccuracy = Niedokładność -text.blocks.shots = Strzały -text.blocks.reload = Przeładowanie -text.blocks.inputfuel = Paliwo -text.blocks.fuelburntime = Płonięcie paliwa -text.blocks.inputcapacity = Pojemność wejściowa -text.blocks.outputcapacity = Wydajność wyjściowa -text.unit.blocks = bloki -text.unit.powersecond = jednostek prądu na sekundę -text.unit.liquidsecond = jednostek płynów na sekundę -text.unit.itemssecond = przedmiotów na sekundę -text.unit.pixelssecond = pikseli na sekundę -text.unit.liquidunits = jednostek płynów -text.unit.powerunits = jednostek paliwa -text.unit.degrees = stopnie -text.unit.seconds = sekundy -text.unit.items = Przedmioty -text.category.general = Główne -text.category.power = Prąd -text.category.liquids = Płyny -text.category.items = Przedmioty -text.category.crafting = Przetwórstwo -text.category.shooting = Strzelanie -text.category.optional = Optional Enhancements -setting.autotarget.name = Auto-Target -setting.fpscap.name = Max FPS -setting.fpscap.none = None +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 = 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 = Zwyciężyła drużyna [accent]{0}[]! +highscore = [YELLOW] Nowy rekord! +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: +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[]. +construction.title = Poradnik tworzenia bloków +construction = Wybrałeś [accent]tryb tworzenia bloków[].\n\nAby zacząć stawiać bloki, po prostu kliknij na dostępne pole obok twojego statku.\nKiedy wybrałeś kilka bloków, kliknij ptaszek i twój statek zacznie budować bloki.\n\n- [accent]Anuluj bloki[] z twojej kolekcji przez klikanie ich(?).\n- [accent]Przesuwaj bloki w kolekcji[] przez przeciąganie ich w opowiednim kierunku.\n- [accent]Stawiaj bloki w lini[] przez kliknięcie w wybranym miejscu i przesuięcie palca.\n- [accent]Anuluj konstrukcję lub kolekcję [] przez kliknięcie X w lewym dolnym rogu. +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! > +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 +newgame = Nowa Gra +none = <żadne> +close = Zamknij +quit = Wyjdź +maps = Mapy +continue = Kontynuuj +maps.none = [LIGHT_GRAY]Nie znaleziono żadnych map! +about.button = O grze +name = Nazwa: +noname = Najpierw wybierz [accent]nazwę gracza[] +filename = Nazwa Pliku: +unlocked = Odblokowano nowy blok! +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.clientOutdated = Nieaktualna gra! Zaktualizują ją! +server.kicked.serverOutdated = Nieaktualny serwer! +server.kicked.banned = Zostałeś zbanowany na tym serwerze. +server.kicked.recentKick = Zostałeś niedawno wyrzucony.\nPoczekaj chwilę przed ponownym połączniem. +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 = Hostuj +hosting = [accent] Otwieranie serwera... +hosts.refresh = Odśwież +hosts.discovering = Wyszukiwanie gier w sieci LAN +server.refreshing = Odświeżanie serwera +hosts.none = [lightgray] Brak serwerów w sieci LAN! +host.invalid = [scarlet] Nie można połączyć się z hostem. +trace = Zlokalizuj gracza +trace.playername = Nazwa gracza: [accent]{0} +trace.ip = IP: [accent]{0} +trace.id = Wyjątkowe ID: [accent]{0} +trace.android = Klient Androida: [accent]{0} +trace.modclient = Zmodowany klient: [accent]{0} +trace.totalblocksbroken = Łączna liczba zniszczonych bloków: [accent]{0} +trace.structureblocksbroken = Zniszczone bloki struktur: [accent]{0} +trace.lastblockbroken = Ostatni zniszczony blok: [accent]{0} +trace.totalblocksplaced = Łączna liczba zbudowanych bloków: [accent]{0} +trace.lastblockplaced = Ostatni postawiony blok: [accent]{0} +invalidid = Złe ID klienta! Udostępnij raport błędu. +server.bans = Bany +server.bans.none = Nie znaleziono zbanowanych osób! +server.admins = Admini +server.admins.none = Nie znaleziono adminów! +server.add = Dodaj serwer +server.delete = Czy na pewno chcesz usunąć ten serwer? +server.hostname = Host: {0} +server.edit = Edytuj serwer +server.outdated = [crimson]Przestarzały serwer![] +server.outdated.client = [crimson]Przestarzały klient![] +server.version = [lightgray]Wersja: {0} +server.custombuild = [yellow]Zmodowany klient +confirmban = Jesteś pewny, że chcesz zbanować tego gracza? +confirmkick = Jesteś pewny, że chcesz wyrzucić tego gracza? +confirmunban = Jesteś pewny, że chcesz odbanować tego gracza? +confirmadmin = Jesteś pewny, że chcesz dać rangę admina temu graczowi? +confirmunadmin = Jesteś pewny, że chcesz zabrać rangę admina temu graczowi? +joingame.title = Dołącz do gry +joingame.ip = IP: +disconnect = Rozłączono. +disconnect.data = Nie udało się załadować mapy! +connecting = [accent]Łączenie... +connecting.data = [accent]Ładowanie danych świata... +server.port = Port: +server.addressinuse = Adres jest już w użyciu! +server.invalidport = Nieprawidłowy numer portu. +server.error = [crimson]Błąd hostowania serwera: [accent] {0} +save.old = Ten zapis jest ze starej wersji i gra nie może go teraz wczytać.\n\n[LIGHT_GRAY]Wsparcie starych zapisów będzie w pełnej wersji 4.0. +save.new = Nowy zapis +save.overwrite = Czy na pewno chcesz nadpisać zapis gry? +overwrite = Nadpisz +save.none = Nie znaleziono zapisów gry! +saveload = [accent]Zapisywanie... +savefail = Nie udało się zapisać gry! +save.delete.confirm = Czy na pewno chcesz usunąć ten zapis gry? +save.delete = Usuń +save.export = Eksportuj +save.import.invalid = [accent]Zapis gry jest niepoprawny! +save.import.fail = [crimson]Nie udało się zaimportować zapisu: [accent] {0} +save.export.fail = [crimson]Nie można wyeksportować zapisu: [accent] {0} +save.import = Importuj +save.newslot = Zapisz nazwę: +save.rename = Zmień nazwę +save.rename.text = Zmień nazwę +selectslot = Wybierz zapis. +slot = [accent]Slot {0} +save.corrupted = [accent]Zapis gry jest uszkodzony lub nieprawidłowy! +empty = +on = Włączone +off = Wyłączone +save.autosave = Zapisywanie automatyczne +save.map = Mapa: {0} +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 +open = Otwórz +cancel = Anuluj +openlink = Otwórz link +copylink = Kopiuj link +back = Wróć +quit.confirm = Czy na pewno chcesz wyjść? +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łąd podczas pobierania listy zmian!\nSprawdź połączenie z internetem. +changelog.current = [yellow][[Twoja wersja] +changelog.latest = [accent][[Najnowsza wersja] +loading = [accent]Ładowanie... +saving = [accent]Zapisywanie... +wave = [accent]Fala {0} +wave.waiting = Fala za {0} +waiting = Oczekiwanie... +waiting.players = Oczekiwanie na graczy... +wave.enemies = Pozostało [LIGHT_GRAY]{0} wrogów +wave.enemy = Pozostał [LIGHT_GRAY]{0} wróg +loadimage = Załaduj obraz +saveimage = Zapisz obraz +unknown = Nieznane +custom = Własne +builtin = Wbudowane +map.delete.confirm = Jesteś pewny, że chcesz usunąć tę mapę? Nie będzie można jej przywrócić. +map.random = [accent]Losowa mapa +map.nospawn = Ta mapa nie zawiera żadnego rdzenia! Musisz dodać [ROYAL]niebieski[] rdzeń do tej mapy. +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łóż: +editor.mapinfo = Informacje o mapie +editor.author = Autor: +editor.description = Opis: +editor.name = Nazwa: +editor.teams = Drużyny +editor.elevation = Poziom terenu +editor.errorimageload = Błąd podczas ładowania pliku obrazu: [accent]{0} +editor.errorimagesave = Błąd podczas zapisywania pliku obrazu: [accent]{0} +editor.generate = Generuj +editor.resize = Zmień rozmiar +editor.loadmap = Załaduj mapę +editor.savemap = Zapisz mapę +editor.saved = Zapisano! +editor.save.noname = Twoja mapa nie ma nazwy! Ustaw ją w 'Informacjach o mapie'. +editor.save.overwrite = Ta mapa nadpisze wbudowaną mapę! Ustaw inną nazwę w 'Informacjach o mapie'. +editor.import.exists = [scarlet]Nie można zaimportować:[] istnieje już wbudowana mapa pod nazwą'{0}'! +editor.import = Importuj... +editor.importmap = Importuj Mapę +editor.importmap.description = Importuj istniejącą mapę +editor.importfile = Importuj Plik +editor.importfile.description = Importuj zewnętrzny plik mapy +editor.importimage = Importuj Obraz Terenu +editor.importimage.description = Importuj zewnętrzny obraz terenu +editor.export = Eksportuj... +editor.exportfile = Eksportuj mapę +editor.exportfile.description = Eksportuj plik mapy +editor.exportimage = Eksportuj Obraz Terenu +editor.exportimage.description = Eksportuj plik obrazu terenu +editor.loadimage = Załaduj obraz +editor.saveimage = Zapisz obraz +editor.unsaved = [scarlet]Masz niezapisane zmiany![]\nCzy na pewno chcesz wyjść? +editor.resizemap = Zmień rozmiar mapy +editor.mapname = Nazwa mapy: +editor.overwrite = [accent]Uwaga!\nSpowoduje to nadpisanie istniejącej mapy. +editor.overwrite.confirm = [scarlet]Uwaga![] Mapa pod tą nazwą już istnieje. Jesteś pewny, że chcesz ją nadpisać? +editor.selectmap = Wybierz mapę do załadowania: +width = Szerokość: +height = Wysokość: +menu = Menu +play = Graj +load = Wczytaj +save = Zapisz +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0}ms +language.restart = Uruchom grę ponownie aby ustawiony język zaczął funkcjonować. +settings = Ustawienia +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. +zone.unlocked = [LIGHT_GRAY] Strefa {0} odblokowana! +connectfail = [crimson]Nie można połączyć się z serwerem: [accent] {0} +error.unreachable = Serwer niedostępny. +error.invalidaddress = Niepoprawny adres. +error.timedout = Przekroczono limit czasu!/nUpewnij się, że host ma ustawione przekierowanie portu oraz, czy adres jest poprawny! +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 +settings.controls = Sterowanie +settings.game = Gra +settings.sound = Dźwięk +settings.graphics = Grafika +settings.cleardata = Wyczyść dane gry... +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 = [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.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Informacje o bloku +blocks.powercapacity = Pojemność mocy +blocks.powershot = moc/strzał +blocks.targetsair = Może namierzać wrogów powietrznych +blocks.itemspeed = Szybkość Transporterów +blocks.shootrange = Zasięg +blocks.size = Rozmiar +blocks.liquidcapacity = Pojemność cieczy +blocks.maxitemssecond = Maksymalna liczba przedmiotów/sekundę +blocks.powerrange = Zakres mocy +blocks.poweruse = Zużycie prądu +blocks.powerdamage = Moc/Zniszczenia +blocks.inputitemcapacity = Pojemność materiałów +blocks.outputitemcapacity = Pojemność produktów +blocks.itemcapacity = Pojemność przedmiotów +blocks.basepowergeneration = Base Power Generation +blocks.powertransferspeed = Szybość przesyłu prądu +blocks.craftspeed = Szybkość produkcji +blocks.inputliquid = Potrzebna ciecz +blocks.inputliquidaux = Płyny do produkcji +blocks.inputitem = Potrzebne przedmioty +blocks.inputitems = Materiały do produkcji +blocks.outputitem = Produkty +blocks.drilltier = Co może wykopać +blocks.drillspeed = Postawowa szybkość kopania +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.power = Prąd +blocks.power.satisfaction = Zapotrzebowanie Prądu +blocks.inaccuracy = Niedokładność +blocks.shots = Strzały +blocks.reload = Przeładowanie +blocks.inputfuel = Paliwo +blocks.fuelburntime = Płonięcie paliwa +blocks.inputcapacity = Pojemność wejściowa +blocks.outputcapacity = Wydajność wyjściowa +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 prądu +unit.degrees = stopnie +unit.seconds = sekundy +unit.items = Przedmioty +category.general = Główne +category.power = Prąd +category.liquids = Płyny +category.items = Przedmioty +category.crafting = Przetwórstwo +category.shooting = Strzelanie +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 = training +setting.difficulty.training = trening setting.difficulty.easy = łatwy setting.difficulty.normal = normalny setting.difficulty.hard = trudny @@ -370,164 +378,176 @@ setting.musicvol.name = Głośność muzyki setting.mutemusic.name = Wycisz muzykę setting.sfxvol.name = Głośność dźwięków setting.mutesound.name = Wycisz dźwięki -setting.crashreport.name = Send Anonymous Crash Reports -text.keybind.title = Zmień ustawienia przycisków -category.general.name = General -category.view.name = View +setting.crashreport.name = Wysyłaj anonimowo dane o crashu gry +keybind.title = Zmień ustawienia przycisków +category.general.name = Ogólne +category.view.name = Wyświetl category.multiplayer.name = Multiplayer -command.attack = Attack -command.retreat = Retreat +command.attack = Atakuj +command.retreat = Wycofaj command.patrol = Patrol -keybind.press = Press a key... -keybind.press.axis = Press an axis or key... +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.select.name = Zaznacz +keybind.pick.name = Wybierz Blok keybind.break.name = Niszczenie -keybind.deselect.name = Deselect +keybind.deselect.name = Odznacz keybind.shoot.name = Strzelanie keybind.zoom_hold.name = Inicjator przybliżania keybind.zoom.name = Przybliżanie -keybind.menu.name = menu -keybind.pause.name = pauza -keybind.dash.name = przyśpieszenie +keybind.menu.name = Menu +keybind.pause.name = Pauza +keybind.dash.name = Przyspieszenie 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.drop_unit.name = drop unit -keybind.zoom_minimap.name = Zoom minimap -mode.text.help.title = Opis trybów -mode.waves.name = Fale -mode.waves.description = Normalny tryb. Normalne surowce i fale. -mode.sandbox.name = sandbox +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.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.name = Budowanie mode.freebuild.description = Normalne surowce i fale bez odliczania. mode.pvp.name = PvP -mode.pvp.description = fight against other players locally. +mode.pvp.description = Walcz przeciwko innym graczom. +mode.attack.name = Atak +mode.attack.descrption = Brak fal. Celem jest zniszczenie bazy wrogów. content.item.name = Przedmioty content.liquid.name = Płyny -content.unit.name = Units -content.recipe.name = Bloki +content.unit.name = Jednostki +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.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.titanium.name = tytan +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 +item.thorium.name = Uran item.thorium.description = Zwarty i radioaktywny materiał używany w struktucrach i paliwie nuklearnym. Nie trzymaj go w rękach! 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.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.biomatter.name = Biomateria item.biomatter.description = Zbita organiczna papka używana jako materiał do ropy lub jako podstawowy materiał energetyczny. Wegańska! -item.sand.name = piasek +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.lava.name = Lawa +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 -text.item.explosiveness = [LIGHT_GRAY]Wybuchowość: {0} -text.item.flammability = [LIGHT_GRAY]Palność: {0} -text.item.radioactivity = [LIGHT_GRAY]Promieniotwórczość: {0} -text.item.fluxiness = [LIGHT_GRAY]Moc topnika: {0} -text.unit.health = [LIGHT_GRAY]Health: {0} -text.unit.speed = [LIGHT_GRAY]Speed: {0} -text.mech.weapon = [LIGHT_GRAY]Weapon: {0} -text.mech.armor = [LIGHT_GRAY]Armor: {0} -text.mech.itemcapacity = [LIGHT_GRAY]Item Capacity: {0} -text.mech.minespeed = [LIGHT_GRAY]Mining Speed: {0} -text.mech.minepower = [LIGHT_GRAY]Mining Power: {0} -text.mech.ability = [LIGHT_GRAY]Ability: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]Wytrzymałość na przegrzewanie: {0} -text.liquid.viscosity = [LIGHT_GRAY]Lepkość: {0} -text.liquid.temperature = [LIGHT_GRAY]Temperatura: {0} -block.constructing = {0}\n[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.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.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.phase-wall.name = Phase Wall -block.phase-wall-large.name = Large Phase Wall +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} +unit.health = [LIGHT_GRAY]Zdrowie: {0} +unit.speed = [LIGHT_GRAY]Prędkość: {0} +mech.weapon = [LIGHT_GRAY]Broń: {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} +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.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-shard.name = Rdzeń: Ułamek +block.core-foundation.name = Rdzeń: Podstawa +block.core-nucleus = Rdzeń: Jądro +block.metalfloor.name = Podłoga Metalowa +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.copper-wall-large.name = Duża miedziana ściana +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.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 -block.titanium-conveyor.name = Tytanowy Transporter +block.titanium-conveyor.name = Tytanowy przenośnik block.junction.name = Węzeł block.router.name = Rozdzielacz block.distributor.name = Dystrybutor @@ -544,34 +564,36 @@ block.cryofluidmixer.name = Mieszacz Cryofluidu block.melter.name = Przetapiacz block.incinerator.name = Spalacz block.biomattercompressor.name = Kompresor Biomaterii -block.separator.name = Separator +block.separator.name = Rozdzielacz block.centrifuge.name = Wirnik 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.mechanical-drill.name = Mechanical Drill -block.pneumatic-drill.name = Pneumatic Drill -block.laser-drill.name = Laserowe Wiertło -block.water-extractor.name = Ekstraktor wody +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.itemsource.name = DEBUG Źródło przedmiotów -block.itemvoid.name = Item Void -block.liquidsource.name = DEBUG Źródło płynów -block.powervoid.name = Power Void -block.powerinfinite.name = DEBUG Nieskończony Prąd +block.item-source.name = Źródło przedmiotów +block.item-void.name = Próżnia przedmiotów +block.liquid-source.name = Źródło płynów +block.power-void.name = Próżnia prądu +block.power-source.name = Nieskończony Prąd block.unloader.name = Wyciągacz block.vault.name = Magazyn block.wave.name = Działo Płynowe @@ -587,14 +609,14 @@ 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 @@ -603,50 +625,55 @@ block.liquid-tank.name = Zbiornik Płynów 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 = 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 -block.thermal-generator.name = Thermal Generator -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.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.thorium-reactor.name = Reaktor Torowy +block.command-center.name = Centrum dowodzenia +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 = 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 = 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 = The most important building in the game. -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.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. +block.container.name = Kontener +block.launch-pad.name = Skocznia +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 = Dron Alpha +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. @@ -756,25 +783,25 @@ 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. +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. 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.liquid-junction.description = Działa jak most dla dwóch krzyżujących się rur. Przydatne w sytuacjach, kiedy dwie rury mają różne ciecze do różnych lokacji. +block.bridge-conduit.description = Zaawansowany blok przenoszący ciecze. Pozwala na przenoszenie cieczy nawet do 3 bloków na każdym terenie, przez każdy budynek. +block.mechanical-pump.description = Tania pompa o niskiej przepustowości. Nie wymaga prądu. +block.rotary-pump.description = Zaawansowana pompa, dwukrotnie większa przepustowość od mechanicznej pompy. Wymaga prądu. 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.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.itemsource.description = Infinitely outputs items. Sandbox only. -block.liquidsource.description = Infinitely outputs liquids. Sandbox only. -block.itemvoid.description = Destroys any items which go into it without using power. Sandbox only. -block.powerinfinite.description = Infinitely outputs power. Sandbox only. -block.powervoid.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. +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 cb44f65e08..a9088f98cf 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -1,351 +1,359 @@ -text.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!) -text.credits = Creditos -text.discord = Junte-se ao Discord do Mindustry! (Lá nós falamos em inglês) -text.link.discord.description = O discord oficial do Mindustry -text.link.github.description = Codigo fonte do jogo. -text.link.dev-builds.description = Desenvolvimentos Instaveis -text.link.trello.description = Trello Oficial para Updates Planejados -text.link.itch.io.description = Pagina da Itch.io com os Downloads -text.link.google-play.description = Listamento do google play store -text.link.wiki.description = Wiki oficial do Mindustry -text.linkfail = Falha ao abrir o link\nO Url foi copiado -text.gameover = O núcleo foi destruído. -text.gameover.pvp = O time[accent] {0}[] É vitorioso! -text.sector.gameover = Esse setor foi perdido! Soltar Novamente? -text.sector.retry = Tentar novamente? -text.highscore = [YELLOW]Novo recorde! -text.wave.lasted = Você sobreviveu até a onda [accent]{0}[]. -text.level.highscore = Melhor\npontuação: [accent] {0} -text.level.delete.title = Confirmar exclusão -text.map.delete = Certeza que quer deletar o mapa "[accent]{0}[]"? -text.level.select = Seleção de Fase -text.level.mode = Modo de Jogo: -text.construction.desktop = Os controles do Desktop foram Mudados.\nPara descelecionar um bloco ou parar de construir, [accent]Use espaço.[]. -text.construction.title = Guia de contrução de blocos -text.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. -text.deconstruction.title = Block Deconstruction Guide -text.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. -text.showagain = Não mostrar na proxima sessão -text.coreattack = < A base está sobre ataque! > -text.unlocks = Desbloqueados -text.savegame = Salvar Jogo -text.loadgame = Carregar Jogo -text.joingame = Entrar no Jogo -text.addplayers = Adicionar/Remover Jogador -text.customgame = Jogo Customizado -text.sectors = Setores -text.sector = Setor Selecionado: [LIGHT_GRAY]{0} -text.sector.time = Tempo: [LIGHT_GRAY]{0} -text.sector.deploy = Soltar -text.sector.abandon = Abandonar -text.sector.abandon.confirm = Certeza que quer abandonar seu progresso nesse setor?\nThis cannot be undone! -text.sector.resume = Voltar -text.sector.locked = [scarlet][[Não liberado] -text.sector.unexplored = [accent][[Inexplorado] -text.missions = Missões:[LIGHT_GRAY] {0} -text.mission = Missão:[LIGHT_GRAY] {0} -text.mission.main = Missão principal:[LIGHT_GRAY] {0} -text.mission.info = Info da missão -text.mission.complete = Missão completa! -text.mission.complete.body = Setor {0},{1} Foi conquistado. -text.mission.wave = Sobrevive [accent]{0}/{1}[] Onda\nOnda em {2} -text.mission.wave.enemies = Sobreviva[accent] {0}/{1} []ondas\n{2} inimigos -text.mission.wave.enemy = Sobreviva[accent] {0}/{1} []Ondas\n{2} Inimigos -text.mission.wave.menu = Sobreviva[accent] {0} []Ondas -text.mission.battle = Destrua a base inimiga. -text.mission.resource.menu = Obtenha {0} x{1} -text.mission.resource = Obtenha {0}:\n[accent]{1}/{2}[] -text.mission.block = Criar {0} -text.mission.unit = Criar {0} Unidade -text.mission.command = Enviar comando {0} As unidades -text.mission.linknode = Ligar nodo de energia -text.mission.display = [accent]Missão:\n[LIGHT_GRAY]{0} -text.mission.mech = Trocar para Meca[accent] {0}[] -text.mission.create = Criar[accent] {0}[] -text.none = -text.close = Fechar -text.quit = Sair -text.maps = Mapas -text.continue = Continue -text.nextmission = Próxima Missão -text.maps.none = [LIGHT_GRAY]Nenhum Mapa Encontrado! -text.about.button = Sobre -text.name = Nome: -text.filename = Nome do arquivo: -text.unlocked = Novo bloco Desbloqueado! -text.unlocked.plural = Novos Blocos desbloqueados! -text.players = {0} Jogadores Ativos -text.players.single = {0} Jogador Ativo -text.server.closing = [accent]Fechando servidor... -text.server.kicked.kick = Voce foi expulso do servidor! -text.server.kicked.serverClose = Servidor Fechado. -text.server.kicked.sectorComplete = Setor completo. -text.server.kicked.sectorComplete.text = Sua missão esta completa.\nO servidor vai continuar no proximo setor. -text.server.kicked.clientOutdated = Cliente desatualizado! Atualize seu jogo! -text.server.kicked.serverOutdated = Servidor desatualiado! Peca ao dono para atualizar! -text.server.kicked.banned = Voce foi banido do servidor. -text.server.kicked.recentKick = Voce foi banido recentemente.\nEspere para conectar de novo. -text.server.kicked.nameInUse = Este nome ja esta sendo usado\nneste servidor. -text.server.kicked.nameEmpty = Voce deve ter pelo menos uma letra ou numero. -text.server.kicked.idInUse = Voce ja esta neste servidor! Conectar com duas contas não é permitido. -text.server.kicked.customClient = Este servidor não suporta construções customizadas. Baixe a versão original. -text.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 -text.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. -text.hostserver = Hospedar servidor -text.hostserver.mobile = Hospedar\nJogo -text.host = Hospedar -text.hosting = [accent]Abrindo server... -text.hosts.refresh = atualizar -text.hosts.discovering = Descobrindo jogos em lan -text.server.refreshing = Atualizando servidor -text.hosts.none = [lightgray]Nenhum jogo lan encontrado! -text.host.invalid = [scarlet]Não foi possivel Hospedar. -text.trace = Traçar jogador -text.trace.playername = Nome do jogador: [accent]{0} -text.trace.ip = IP: [accent]{0} -text.trace.id = ID unico: [accent]{0} -text.trace.android = Cliente Androide: [accent]{0} -text.trace.modclient = Cliente Customizado: [accent]{0} -text.trace.totalblocksbroken = Blocos totais quebrados: [accent]{0} -text.trace.structureblocksbroken = Blocos de estrutura quebrados: [accent]{0} -text.trace.lastblockbroken = Ultimo bloco quebrado: [accent]{0} -text.trace.totalblocksplaced = Blocos totais Colocados: [accent]{0} -text.trace.lastblockplaced = Ultimo bloco colocado: [accent]{0} -text.invalidid = ID do cliente invalido! Reporte o bug. -text.server.bans = Banidos -text.server.bans.none = Nenhum jogador banido encontrado! -text.server.admins = Administradores -text.server.admins.none = Nenhum administrador encontrado! -text.server.add = Adicionar servidor -text.server.delete = Certeza que quer deletar o servidor? -text.server.hostname = Hospedar: {0} -text.server.edit = Editar servidor -text.server.outdated = [crimson]Servidor desatualizado![] -text.server.outdated.client = [crimson]Cliente desatualizado![] -text.server.version = [lightgray]Versão: {0} -text.server.custombuild = [yellow]Construção customizada -text.confirmban = Certeza que quer banir este jogador? -text.confirmkick = Certeza que quer kickar o jogador? -text.confirmunban = Certeza que quer desbanir este jogador? -text.confirmadmin = Certeza que quer fazer este jogador um administrador? -text.confirmunadmin = Certeza que quer remover o estatus de adminstrador deste jogador? -text.joingame.title = Entrar no jogo -text.joingame.ip = IP: -text.disconnect = Desconectado. -text.disconnect.data = Falha ao abrir a data do mundo! -text.connecting = [accent]Conectando... -text.connecting.data = [accent]Carregando data do mundo... -text.server.port = Porte: -text.server.addressinuse = Senha em uso! -text.server.invalidport = Numero de port invalido! -text.server.error = [crimson]Erro ao hospedar o servidor: [accent]{0} -text.save.old = Este save é para uma versão antiga do jogo, E não pode ser usado.\n\n[LIGHT_GRAY]Salvar Versões antigas vai ser Implementado Na versão 4.0 completa -text.save.new = Novo Save -text.save.overwrite = Você tem certeza que quer salvar sobre este slot? -text.overwrite = Salvar sobre -text.save.none = Nenhum save encontrado! -text.saveload = [accent]Salvando... -text.savefail = Falha ao salvar jogo! -text.save.delete.confirm = Certeza que quer deletar este save? -text.save.delete = Deletar -text.save.export = Exportar save -text.save.import.invalid = [accent]Este save é invalido! -text.save.import.fail = [crimson]Falha ao importar save: [accent]{0} -text.save.export.fail = [crimson]Falha ao Exportar save: [accent]{0} -text.save.import = Importar save -text.save.newslot = Nome do save: -text.save.rename = Renomear -text.save.rename.text = Novo jogo: -text.selectslot = Selecione um slot para salvar. -text.slot = [accent]Slot {0} -text.save.corrupted = [accent]Arquivo corrompido ou inválido! -text.sector.corrupted = [accent]Um arquivo de save Foi encontrado neste setor, Mas o login falhou.\nUm novo foi criado. -text.empty = -text.on = Ligado -text.off = Desligado -text.save.autosave = Autosalvar: {0} -text.save.map = Mapa: {0} -text.save.wave = Horda {0} -text.save.difficulty = Dificuldade: {0} -text.save.date = Último salvamento: {0} -text.save.playtime = Playtime: {0} -text.confirm = Confirmar -text.delete = Excluir -text.ok = OK -text.open = Abrir -text.cancel = Cancelar -text.openlink = Abrir Link -text.copylink = Copiar link -text.back = Voltar -text.quit.confirm = Você tem certeza que quer sair? -text.changelog.title = Changelog -text.changelog.loading = Coletando changelog... -text.changelog.error.android = [accent]Note que a Changelog as vezes Funciona no android 4.4 e abaixo!\nIsso é por causa de um erro interno no sistema android. -text.changelog.error.ios = [accent]A changelog não é suportada no IOS. -text.changelog.error = [scarlet]Erro ao coletar Changelog!\nCheque a Conexão com a internet. -text.changelog.current = [yellow][[Primeira versão] -text.changelog.latest = [accent][[Ultima versão] -text.loading = [accent]Carregando... -text.saving = [accent]Salvando... -text.wave = [accent]Horda {0} -text.wave.waiting = Horda em {0} -text.waiting = Aguardando... -text.waiting.players = Waiting for players... -text.wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining -text.wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining -text.loadimage = Carregar\nImagem -text.saveimage = Salvar\nImagem -text.unknown = Desconhecido -text.custom = Customizado -text.builtin = Built-In -text.map.delete.confirm = Certeza que quer deletar este mapa? Isto não pode ser desfeito! -text.map.random = [accent]Mapa aleatório -text.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. -text.map.nospawn.pvp = Esse mapa não tem cores inimigos para os jogadores nascerem! Adicione[SCARLET] Cores vermelhos[] no mapa no editor. -text.map.invalid = Erro ao carregar o mapa: Arquivo de mapa invalido ou corrupto. -text.editor.brush = Pincel -text.editor.slope = \\ -text.editor.openin = Abrir no Editor -text.editor.oregen = Geração de minério -text.editor.oregen.info = Geração de minério: -text.editor.mapinfo = Informação do mapa -text.editor.author = Autor: -text.editor.description = Descrição: -text.editor.name = Nome: -text.editor.teams = Time -text.editor.elevation = Elevação -text.editor.errorimageload = Erro ao carregar arquivo de imagem:\n[accent]{0} -text.editor.errorimagesave = Erro ao salvar arquivo de imagem:\n[accent]{0} -text.editor.generate = Gerar -text.editor.resize = Redimen\n sionar -text.editor.loadmap = Carregar\n Mapa -text.editor.savemap = Salvar\n Mapa -text.editor.saved = Salvo! -text.editor.save.noname = Seu mapa não tem um nome! Coloque um no menu de "Informação do mapa" -text.editor.save.overwrite = O seu mapa Substitui um mapa já construído! Coloque um nome diferente no menu "Informação do mapa" -text.editor.import.exists = [scarlet]Não foi possivel importar:[] Um mapa Construído chamado '{0}' Já existe! -text.editor.import = Importando... -text.editor.importmap = Importar Mapa -text.editor.importmap.description = Importar um mapa existente -text.editor.importfile = Importar arquivo -text.editor.importfile.description = Importar um arquivo externo -text.editor.importimage = Importar imagem do terreno -text.editor.importimage.description = Importar uma imagem de terreno externa -text.editor.export = Exportando... -text.editor.exportfile = Exportar arquivo -text.editor.exportfile.description = Exportar um arquivo de mapa -text.editor.exportimage = Exportar imagem de terreno -text.editor.exportimage.description = Exportar um arquivo de imagem de mapa -text.editor.loadimage = Carregar\n Imagem -text.editor.saveimage = Salvar\nImagem -text.editor.unsaved = [scarlet]Você tem alterações não salvas![]\nTem certeza que quer sair? -text.editor.resizemap = Redimensionar Mapa -text.editor.mapname = Nome do Mapa: -text.editor.overwrite = [accent]Aviso!\nIsso Subistitui um mapa existente. -text.editor.overwrite.confirm = [scarlet]Aviso![] Um mapa com esse nome já existe. Tem certeza que deseja substituir? -text.editor.selectmap = Selecione uma mapa para carregar: -text.width = Largura: -text.height = Altura: -text.menu = Menu -text.play = Jogar -text.load = Carregar -text.save = Salvar -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Ping: {0}ms -text.language.restart = Por favor Reinicie seu jogo para a tradução tomar efeito. -text.settings = Configurações -text.tutorial = Tutorial -text.editor = Editor -text.mapeditor = Editor de mapa -text.donate = Doar -text.connectfail = [crimson]Falha ao entrar no servidor: [accent]{0} -text.error.unreachable = Servidor inalcançavel. -text.error.invalidaddress = Endereço invalido. -text.error.timedout = Desconectado!\nTenha certeza que o Rosteador tenha feito Port forwading, E que o indereço esteja correto! -text.error.mismatch = Erro de pacote:\nPossivel versão do cliente/Servidor incompatibilidade.\nTenha certeza que você e o host tenham a ultima versão! -text.error.alreadyconnected = Já conectado. -text.error.mapnotfound = Arquivo de mapa não encontrado! -text.error.any = Erro de rede desconhecido. -text.settings.language = Linguagem -text.settings.reset = Restaurar Padrões -text.settings.rebind = Religar -text.settings.controls = Controles -text.settings.game = Jogo -text.settings.sound = Som -text.settings.graphics = Gráficos -text.settings.cleardata = Data do jogo limpa... -text.settings.clear.confirm = Certeza que quer limpar a data?\nOque é feito não pode ser desfeito! -text.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. -text.settings.clearsectors = Limpar setores -text.settings.clearunlocks = Limpar liberados -text.settings.clearall = Limpar tudo -text.paused = Pausado -text.yes = Sim -text.no = Não -text.info.title = [accent]Informação -text.error.title = [crimson]Ocorreu um Erro. -text.error.crashtitle = Ocorreu um Erro -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = Informação do Bloco -text.blocks.powercapacity = Capacidade de Energia -text.blocks.powershot = Energia/tiro -text.blocks.targetsair = Mirar no ar -text.blocks.itemspeed = Unidades mobilizadas -text.blocks.shootrange = Alcance -text.blocks.size = Tamanho -text.blocks.liquidcapacity = Capacidade de Líquido -text.blocks.maxitemssecond = Máximo de itens/segundo -text.blocks.powerrange = Alcance da Energia -text.blocks.poweruse = Uso de energia -text.blocks.powerdamage = Dano/Poder -text.blocks.inputitemcapacity = Configurar capacidade de itens -text.blocks.outputitemcapacity = Configurar capacidade de itens -text.blocks.itemcapacity = Capacidade de Itens -text.blocks.basepowergeneration = Geração de poder base -text.blocks.powertransferspeed = Transferência de energia -text.blocks.craftspeed = Velocidade de produção -text.blocks.inputliquid = Líquido de entrada -text.blocks.inputliquidaux = Líquido auxiliar -text.blocks.inputitem = Item de entrada -text.blocks.inputitems = Itens de entrada -text.blocks.outputitem = Itens de saida -text.blocks.drilltier = Furaveis -text.blocks.drillspeed = Velocidade da furadeira base -text.blocks.liquidoutput = Saida de liquido -text.blocks.liquidoutputspeed = Velocidade da saida de líquido -text.blocks.liquiduse = Uso de liquido -text.blocks.coolant = Esfriador -text.blocks.coolantuse = Uso do esfriador -text.blocks.inputliquidfuel = Liquido de combustivel -text.blocks.liquidfueluse = Uso do liquido de combustivel -text.blocks.boostitem = Acelerar item -text.blocks.boostliquid = Acelerar líquido -text.blocks.health = Saúde -text.blocks.inaccuracy = Imprecisão -text.blocks.shots = Tiros -text.blocks.reload = Recarregar -text.blocks.inputfuel = Combustivel -text.blocks.fuelburntime = Tempo de queima de combustivel -text.blocks.inputcapacity = Capacidade de entrada -text.blocks.outputcapacity = Capacidade de saída -text.unit.blocks = blocos -text.unit.powersecond = Unidades de energia/segundo -text.unit.liquidsecond = Unidades de líquido/segundo -text.unit.itemssecond = itens/segundo -text.unit.pixelssecond = pixeis/segundo -text.unit.liquidunits = Unidades de liquido -text.unit.powerunits = Unidades de energia -text.unit.degrees = Graus -text.unit.seconds = segundos -text.unit.items = itens -text.category.general = Geral -text.category.power = Poder -text.category.liquids = Liquidos -text.category.items = Itens -text.category.crafting = Construindo -text.category.shooting = Atirando -text.category.optional = Melhoras opcionais +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. +link.dev-builds.description = Desenvolvimentos Instaveis +link.trello.description = Trello Oficial para Updates Planejados +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! +highscore = [YELLOW]Novo recorde! +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: +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. +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 = < 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 +newgame = Novo Jogo +none = +close = Fechar +quit = Sair +maps = Mapas +continue = Continue +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! +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.clientOutdated = Cliente desatualizado! Atualize seu jogo! +server.kicked.serverOutdated = Servidor desatualiado! Peca ao dono para atualizar! +server.kicked.banned = Voce foi banido do servidor. +server.kicked.recentKick = Voce foi banido recentemente.\nEspere para conectar de novo. +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 +hostserver.mobile = Hospedar\nJogo +host = Hospedar +hosting = [accent]Abrindo server... +hosts.refresh = atualizar +hosts.discovering = Descobrindo jogos em lan +server.refreshing = Atualizando servidor +hosts.none = [lightgray]Nenhum jogo lan encontrado! +host.invalid = [scarlet]Não foi possivel Hospedar. +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 Android: [accent]{0} +trace.modclient = Cliente Customizado: [accent]{0} +trace.totalblocksbroken = Blocos totais quebrados: [accent]{0} +trace.structureblocksbroken = Blocos de estrutura quebrados: [accent]{0} +trace.lastblockbroken = Ultimo bloco quebrado: [accent]{0} +trace.totalblocksplaced = Blocos totais Colocados: [accent]{0} +trace.lastblockplaced = Ultimo bloco colocado: [accent]{0} +invalidid = ID do cliente invalido! Reporte o bug. +server.bans = Banidos +server.bans.none = Nenhum jogador banido encontrado! +server.admins = Administradores +server.admins.none = Nenhum administrador encontrado! +server.add = Adicionar servidor +server.delete = Certeza que quer deletar o servidor? +server.hostname = Hospedar: {0} +server.edit = Editar servidor +server.outdated = [crimson]Servidor desatualizado![] +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 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? +joingame.title = Entrar no jogo +joingame.ip = IP: +disconnect = Desconectado. +disconnect.data = Falha ao abrir a data do mundo! +connecting = [accent]Conectando... +connecting.data = [accent]Carregando data do mundo... +server.port = Porte: +server.addressinuse = Senha em uso! +server.invalidport = Numero de port invalido! +server.error = [crimson]Erro ao hospedar o servidor: [accent]{0} +save.old = Este save é para uma versão antiga do jogo, E não pode ser usado.\n\n[LIGHT_GRAY]Salvar Versões antigas vai ser Implementado Na versão 4.0 completa +save.new = Novo Save +save.overwrite = Você tem certeza que quer salvar sobre este slot? +overwrite = Salvar sobre +save.none = Nenhum save encontrado! +saveload = [accent]Salvando... +savefail = Falha ao salvar jogo! +save.delete.confirm = Certeza que quer deletar este save? +save.delete = Deletar +save.export = Exportar save +save.import.invalid = [accent]Este save é invalido! +save.import.fail = [crimson]Falha ao importar save: [accent]{0} +save.export.fail = [crimson]Falha ao Exportar save: [accent]{0} +save.import = Importar save +save.newslot = Nome do save: +save.rename = Renomear +save.rename.text = Novo jogo: +selectslot = Selecione um slot para salvar. +slot = [accent]Slot {0} +save.corrupted = [accent]Arquivo corrompido ou inválido! +empty = +on = Ligado +off = Desligado +save.autosave = Autosalvar: {0} +save.map = Mapa: {0} +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 +open = Abrir +cancel = Cancelar +openlink = Abrir Link +copylink = Copiar link +back = Voltar +quit.confirm = Você tem certeza que quer sair? +changelog.title = Changelog +changelog.loading = Coletando changelog... +changelog.error.android = [accent]Note que a Changelog as vezes Funciona no android 4.4 e abaixo!\nIsso é por causa de um erro interno no sistema android. +changelog.error.ios = [accent]A changelog não é suportada no IOS. +changelog.error = [scarlet]Erro ao coletar Changelog!\nCheque a Conexão com a internet. +changelog.current = [yellow][[Primeira versão] +changelog.latest = [accent][[Ultima versão] +loading = [accent]Carregando... +saving = [accent]Salvando... +wave = [accent]Horda {0} +wave.waiting = Horda em {0} +waiting = Aguardando... +waiting.players = Waiting for players... +wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining +wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining +loadimage = Carregar\nImagem +saveimage = Salvar\nImagem +unknown = Desconhecido +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]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: +editor.mapinfo = Informação do mapa +editor.author = Autor: +editor.description = Descrição: +editor.name = Nome: +editor.teams = Time +editor.elevation = Elevação +editor.errorimageload = Erro ao carregar arquivo de imagem:\n[accent]{0} +editor.errorimagesave = Erro ao salvar arquivo de imagem:\n[accent]{0} +editor.generate = Gerar +editor.resize = Redimen\n sionar +editor.loadmap = Carregar\n Mapa +editor.savemap = Salvar\n Mapa +editor.saved = Salvo! +editor.save.noname = Seu mapa não tem um nome! Coloque um no menu de "Informação do mapa" +editor.save.overwrite = O seu mapa Substitui um mapa já construído! Coloque um nome diferente no menu "Informação do mapa" +editor.import.exists = [scarlet]Não foi possivel importar:[] Um mapa Construído chamado '{0}' Já existe! +editor.import = Importando... +editor.importmap = Importar Mapa +editor.importmap.description = Importar um mapa existente +editor.importfile = Importar arquivo +editor.importfile.description = Importar um arquivo externo +editor.importimage = Importar imagem do terreno +editor.importimage.description = Importar uma imagem de terreno externa +editor.export = Exportando... +editor.exportfile = Exportar arquivo +editor.exportfile.description = Exportar um arquivo de mapa +editor.exportimage = Exportar imagem de terreno +editor.exportimage.description = Exportar um arquivo de imagem de mapa +editor.loadimage = Carregar\n Imagem +editor.saveimage = Salvar\nImagem +editor.unsaved = [scarlet]Você tem alterações não salvas![]\nTem certeza que quer sair? +editor.resizemap = Redimensionar Mapa +editor.mapname = Nome do Mapa: +editor.overwrite = [accent]Aviso!\nIsso Subistitui um mapa existente. +editor.overwrite.confirm = [scarlet]Aviso![] Um mapa com esse nome já existe. Tem certeza que deseja substituir? +editor.selectmap = Selecione uma mapa para carregar: +width = Largura: +height = Altura: +menu = Menu +play = Jogar +load = Carregar +save = Salvar +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0}ms +language.restart = Por favor Reinicie seu jogo para a tradução tomar efeito. +settings = Configurações +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson]Falha ao entrar no servidor: [accent]{0} +error.unreachable = Servidor inalcançavel. +error.invalidaddress = Endereço invalido. +error.timedout = Desconectado!\nTenha certeza que o Rosteador tenha feito Port forwading, E que o indereço esteja correto! +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 +settings.controls = Controles +settings.game = Jogo +settings.sound = Som +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.clearunlocks = Limpar liberados +settings.clearall = Limpar tudo +paused = Pausado +yes = Sim +no = Não +info.title = [accent]Informação +error.title = [crimson]Ocorreu um Erro. +error.crashtitle = Ocorreu um Erro +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Informação do Bloco +blocks.powercapacity = Capacidade de Energia +blocks.powershot = Energia/tiro +blocks.targetsair = Mirar no ar +blocks.itemspeed = Unidades mobilizadas +blocks.shootrange = Alcance +blocks.size = Tamanho +blocks.liquidcapacity = Capacidade de Líquido +blocks.maxitemssecond = Máximo de itens/segundo +blocks.powerrange = Alcance da Energia +blocks.poweruse = Uso de energia +blocks.powerdamage = Dano/Poder +blocks.inputitemcapacity = Configurar capacidade de itens +blocks.outputitemcapacity = Configurar capacidade de itens +blocks.itemcapacity = Capacidade de Itens +blocks.basepowergeneration = Geração de poder base +blocks.powertransferspeed = Transferência de energia +blocks.craftspeed = Velocidade de produção +blocks.inputliquid = Líquido de entrada +blocks.inputliquidaux = Líquido auxiliar +blocks.inputitem = Item de entrada +blocks.inputitems = Itens de entrada +blocks.outputitem = Itens de saida +blocks.drilltier = Furaveis +blocks.drillspeed = Velocidade da furadeira base +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.power = Poder +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = Imprecisão +blocks.shots = Tiros +blocks.reload = Recarregar +blocks.inputfuel = Combustivel +blocks.fuelburntime = Tempo de queima de combustivel +blocks.inputcapacity = Capacidade de entrada +blocks.outputcapacity = Capacidade de saída +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 +unit.seconds = segundos +unit.items = itens +category.general = Geral +category.power = Poder +category.liquids = Liquidos +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 @@ -371,60 +379,63 @@ setting.mutemusic.name = Desligar Música setting.sfxvol.name = Volume de Efeitos setting.mutesound.name = Desligar Som setting.crashreport.name = Enviar denuncias de crash anonimas -text.keybind.title = Refazer teclas +keybind.title = Refazer teclas category.general.name = Geral category.view.name = Ver 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.pick.name = Pick Block keybind.break.name = quebrar 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 keybind.chat_scroll.name = Rolar chat keybind.drop_unit.name = Soltar unidade keybind.zoom_minimap.name = Zoom minimap -mode.text.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.help.title = Descrição dos modos +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.descrption = 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 @@ -445,6 +456,10 @@ 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.oil.name = Petróleo @@ -478,44 +493,49 @@ mech.trident-ship.weapon = Carga de bombas mech.glaive-ship.name = Glaive mech.glaive-ship.description = Uma nave armada, bem armadurada. Com um repetidor incendario equipado. Boa aceleração e maxima velocidade. mech.glaive-ship.weapon = Repetidor de fogo -text.item.explosiveness = [LIGHT_GRAY]Explosividade: {0} -text.item.flammability = [LIGHT_GRAY]Inflamabilidade: {0} -text.item.radioactivity = [LIGHT_GRAY]RadioAtividade: {0} -text.item.fluxiness = [LIGHT_GRAY]Poder do fluxo: {0} -text.unit.health = [LIGHT_GRAY]Vida: {0} -text.unit.speed = [LIGHT_GRAY]Velocidade: {0} -text.mech.weapon = [LIGHT_GRAY]Arma: {0} -text.mech.armor = [LIGHT_GRAY]Armadura: {0} -text.mech.itemcapacity = [LIGHT_GRAY]Capacidade de itens: {0} -text.mech.minespeed = [LIGHT_GRAY]Velocidade de mineração: {0} -text.mech.minepower = [LIGHT_GRAY]Poder de mineração: {0} -text.mech.ability = [LIGHT_GRAY]Habilidade: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]Capacidade de aquecimento: {0} -text.liquid.viscosity = [LIGHT_GRAY]Viscosidade: {0} -text.liquid.temperature = [LIGHT_GRAY]Temperatura: {0} +item.explosiveness = [LIGHT_GRAY]Explosividade: {0} +item.flammability = [LIGHT_GRAY]Inflamabilidade: {0} +item.radioactivity = [LIGHT_GRAY]RadioAtividade: {0} +unit.health = [LIGHT_GRAY]Vida: {0} +unit.speed = [LIGHT_GRAY]Velocidade: {0} +mech.weapon = [LIGHT_GRAY]Arma: {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} +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.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.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = Chão de metal block.deepwater.name = água funda -block.water.name = água -block.lava.name = lava +block.water.name = Água +block.lava.name = Lava 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.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.rock.name = Rocha +block.blackrock.name = Rocha negra +block.icerock.name = Rocha de gelo 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 @@ -548,33 +568,35 @@ 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.itemsource.name = Fonte do item -block.itemvoid.name = Item Void -block.liquidsource.name = Liquid Source -block.powervoid.name = Power Void -block.powerinfinite.name = Power Infinite -block.unloader.name = Unloader +block.item-source.name = Fonte do item +block.item-void.name = Item Void +block.liquid-source.name = Liquid Source +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 @@ -586,14 +608,14 @@ 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 @@ -612,7 +634,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,7 +645,7 @@ 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 team.blue.name = Azul team.red.name = Vermelho team.orange.name = Laranja @@ -637,6 +659,7 @@ 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 +669,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. @@ -769,11 +796,11 @@ block.router.description = Aceita itens de uma direção e os divide em 3 direç 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.itemsource.description = Infinivamente da itens. Apenas caixa de areia. -block.liquidsource.description = Infinitivamente da Liquidos. Apenas caixa de areia. -block.itemvoid.description = Destroi qualquer item que entre sem requerir energia. Apenas caixa de areia. -block.powerinfinite.description = Infinitivamente da energia. Apenas caixa de areia. -block.powervoid.description = Destroi qualquer energia que entre dentro. Apenas caixa de areia. +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. diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index 000b995f43..c330164986 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -1,352 +1,359 @@ -text.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 -text.credits = Авторы -text.contributors = Переводчики и контрибьюторы -text.discord = Присоединяйтесь к нашему Discord! -text.link.discord.description = Официальный discord-сервер Mindustry -text.link.github.description = Исходный код игры -text.link.dev-builds.description = Нестабильные версии -text.link.trello.description = Официальная доска trello для запланированных функций -text.link.itch.io.description = itch.io страница с загрузкой ПК версии и веб-версией игры -text.link.google-play.description = Скачать для Android c Google play -text.link.wiki.description = Официальная вики Mindustry(англ.) -text.linkfail = Не удалось открыть ссылку!\nURL-адрес был скопирован в буфер обмена. -text.gameover = Игра окончена -text.gameover.pvp = [accent] {0}[] команда победила! -text.sector.gameover = Этот сектор потерян. Высадиться повторно? -text.sector.retry = Повторить попытку -text.highscore = [YELLOW]Новый рекорд! -text.wave.lasted = Вы продержались до [accent]{0}[]-ой волны. -text.level.highscore = Рекорд: [accent]{0} -text.level.delete.title = Подтвердите удаление -text.map.delete = Вы действительно хотите удалить карту "[accent]{0}[]"? -text.level.select = Выбор карты -text.level.mode = Режим игры: -text.construction.desktop = Чтобы отменить выбор блока или остановить строительство, [accent] используйте пробел[]. -text.construction.title = Руководство по размещению блоков -text.construction = Вы только что перешли в режим размещения[accent]блоков[].\n\nЧтобы начать размещение, просто коснитесь подходящего места рядом с вашим мехом.\nПосле того, как вы поставили несколько блоков, нажмите на галочку, чтобы подтвердить, и ваш мех начнет их строительство.\n\n- [accent]Удалите блоки [] из вашего плана строительства, нажав на них.n- [accent]Нажав Shift [] и, удерживая, перетащите любой выбранный блок.\n- [accent]Поместите блоки в линию [], нажимая и удерживая на пустое место, а затем перетаскивая в любом направлении.\n- [accent]Отмените размещение блоков [], нажав X в нижнем правом углу. -text.deconstruction.title = Руководство по разрушению блоков -text.deconstruction = Вы только что перешли в режим сноса[accent] блоков.[].\n\nЧтобы начать удалять, просто нажмите на блок рядом с вашим мехом.\nПосле того как вы выбрали несколько блоков, нажмите на галочку, чтобы подтвердить, и ваш мех начнёт их сносить.\n\n- [accent]Уберите блоки [] из вашего выбора, нажав на них.\n- [accent]Удалите блоки в области [], нажав и удерживая на пустом месте, а затем перетаскивая в нужном направлении.\n- [accent]Отменить снос или выбор [] можно нажав X в нижнем правом углу. -text.showagain = Не показывать снова до следующей сессии -text.coreattack = < Ядро находится под атакой! > -text.unlocks = Разблокированные -text.savegame = Сохранить игру -text.loadgame = Загрузить игру -text.joingame = Присоеди\nниться -text.addplayers = Доб/удалить игроков -text.customgame = Пользовательская игра -text.sectors = Секторы -text.sector = Выбранный сектор: [LIGHT_GRAY]{0} -text.sector.time = Время: [LIGHT_GRAY]{0} -text.sector.deploy = Высадиться -text.sector.abandon = Отступить -text.sector.abandon.confirm = Вы уверены, что хотите отступить?\nПрогресс на секторе нельзя восстановить! -text.sector.resume = Продолжить -text.sector.locked = [scarlet][[Не завершён] -text.sector.unexplored = [accent][[Неисследованный] -text.missions = Миссий:[LIGHT_GRAY] {0} -text.mission = Миссия:[LIGHT_GRAY] {0} -text.mission.main = Главная миссия:[LIGHT_GRAY] {0} -text.mission.info = Информация о миссии -text.mission.complete = Миссия выполнена! -text.mission.complete.body = Сектор {0},{1} был завоёван. -text.mission.wave = Волна[accent] {0}[] из[accent] {1}[]\nВолна через {2} -text.mission.wave.enemies = Волна[accent] {0} из {1}[]\n{2} враг. -text.mission.wave.enemy = Волна[accent] {0} из {1}[]\n{2} враг -text.mission.wave.menu = Пережить[accent] {0} []волн -text.mission.battle = Уничтожьте ядро противника. -text.mission.resource.menu = Добыть {0} х{1} -text.mission.resource = Добыть {0}:\n[accent]{1}/{2}[] -text.mission.block = Создать {0} -text.mission.unit = Создать {0} боев. ед. -text.mission.command = Отправить команду {0} к боев. единицам -text.mission.linknode = Соединить силовые узлы -text.mission.display = [accent]Миссия:\n[LIGHT_GRAY]{0} -text.mission.mech = Переключиться на мех[accent] {0}[] -text.mission.create = Создать[accent] {0}[] -text.none = <нет> -text.close = Закрыть -text.quit = Выход -text.maps = Карты -text.continue = Продолжить -text.nextmission = Следующая миссия -text.maps.none = [LIGHT_GRAY]Карты не найдены! -text.about.button = Об игре -text.name = Ник: -text.filename = Имя файла: -text.unlocked = Новый блок разблокирован! -text.unlocked.plural = Новые блоки разблокированы! -text.players = Игроков на сервере: {0} -text.players.single = {0} игрок на сервере -text.server.closing = [accent]Закрытие сервера... -text.server.kicked.kick = Вас выгнали с сервера! -text.server.kicked.serverClose = Сервер закрыт. -text.server.kicked.sectorComplete = Сектор завоёван. -text.server.kicked.sectorComplete.text = Ваша миссия завершена.\nСервер продолжит работу и высадит вас в следующем секторе. -text.server.kicked.clientOutdated = Устаревший клиент! Обновите игру! -text.server.kicked.serverOutdated = Устаревший сервер! Попросите хоста обновить сервер/игру! -text.server.kicked.banned = Вы заблокированы на этом сервере. -text.server.kicked.recentKick = Вы недавно были кикнуты.\n Подождите немного перед следующим подключением -text.server.kicked.nameInUse = На этом сервере есть кто-то с этим именем. -text.server.kicked.nameEmpty = Ваше имя должно содержать хотя бы один символ или цифру. -text.server.kicked.idInUse = Вы уже на этом сервере! Соединение с двумя учетными записями не разрешено. -text.server.kicked.customClient = Этот сервер не поддерживает пользовательские сборки. Загрузите официальную версию. -text.host.info = Кнопка [accent] Сервер [] размещает сервер на порт [accent]6567[].[]\nЛюбой пользователь в той же [LIGHT_GRAY]сети [] получет возможность видеть ваш сервер в своём списке серверов.\n\nЕсли вы хотите, чтобы люди могли подключаться из любого места по IP, то требуется переадресация(проброс) портов.[].\n\n[LIGHT_GRAY] Примечание. Если у кого-то возникают проблемы с подключением к вашей локальной сети, убедитесь, что вы разрешили Mindustry доступ к вашей локальной сети в настройках брандмауэра. -text.join.info = Здесь вы можете ввести IP-адрес [accent]сервера[] для подключения или открыть [accent]локальную сеть [] для подключения к другим серверам.\nПоддерживается многопользовательский режим LAN и WAN.\n\n[LIGHT_GRAY] Примечание: это не является автоматическим глобальным списком серверов; если вы хотите подключиться к кому-то по IP, вам нужно будет спросить у хоста его IP-адрес. -text.hostserver = Запустить сервер -text.hostserver.mobile = Запустить\nсервер -text.host = Сервер -text.hosting = [accent]Открытие сервера... -text.hosts.refresh = Обновить -text.hosts.discovering = Поиск локальных игр -text.server.refreshing = Обновление сервера -text.hosts.none = [lightgray]Локальных игр не обнаружено! -text.host.invalid = [scarlet] Не удается подключиться к хосту. -text.trace = Слежка за игроком -text.trace.playername = Имя игрока: [accent]{0} -text.trace.ip = IP: [accent]{0} -text.trace.id = ID: [accent]{0} -text.trace.android = Клиент Android: [accent]{0} -text.trace.modclient = Пользовательский клиент: [accent]{0} -text.trace.totalblocksbroken = Всего разрушено блоков: [accent]{0} -text.trace.structureblocksbroken = Структурных блоков сломано: [accent]{0} -text.trace.lastblockbroken = Последний сломанный блок:[accent]{0} -text.trace.totalblocksplaced = Всего размещено блоков: [accent]{0} -text.trace.lastblockplaced = Последний размещенный блок: [accent]{0} -text.invalidid = Недопустимый ID клиента! Отправьте отчёт об ошибке. -text.server.bans = Блокировки -text.server.bans.none = Заблокированных игроков нет! -text.server.admins = Администраторы -text.server.admins.none = Администраторов нет! -text.server.add = Добавить сервер -text.server.delete = Вы действительно хотите удалить этот сервер? -text.server.hostname = Хост: {0} -text.server.edit = Редактировать сервер -text.server.outdated = [crimson]Устаревший сервер![] -text.server.outdated.client = [crimson]Устаревший клиент![] -text.server.version = [lightgray]Версия: {0} {1} -text.server.custombuild = [yellow]Пользовательская сборка -text.confirmban = Вы действительно хотите заблокировать этого игрока? -text.confirmkick = Вы действительно хотите выгнать(кикнуть) этого игрока? -text.confirmunban = Вы действительно хотите разблокировать этого игрока? -text.confirmadmin = Вы уверены, что хотите сделать этого игрока администратором? -text.confirmunadmin = Вы действительно хотите убрать этого игрока из администраторов? -text.joingame.title = Присоединиться к игре -text.joingame.ip = IP: -text.disconnect = Отключён -text.disconnect.data = Не удалось загрузить данные мира! -text.connecting = [accent]Подключение... -text.connecting.data = [accent]Загрузка данных мира... -text.server.port = Порт: -text.server.addressinuse = Данный адрес уже используется! -text.server.invalidport = Неверный номер порта! -text.server.error = [crimson]Ошибка создания сервера: [accent] {0} -text.save.old = Это сохранение для более старой версии игры и больше не может использоваться.\n\n[LIGHT_GRAY]Совместимость сохранений будет реализована в полной версии 4.0. -text.save.new = Новое сохранение -text.save.overwrite = Вы уверены,что хотите перезаписать этот слот для сохранения? -text.overwrite = Перезаписать -text.save.none = Сохранения не найдены! -text.saveload = [accent]Сохранение... -text.savefail = Не удалось сохранить игру! -text.save.delete.confirm = Вы уверены,что хотите удалить это сохранение? -text.save.delete = Удалить -text.save.export = Экспортировать сохранение -text.save.import.invalid = [accent]Это сохранение недействительно! -text.save.import.fail = [crimson]Не удалось импортировать сохранение: [accent] {0} -text.save.export.fail = [crimson]Не удалось экспортировать сохранение: [accent] {0} -text.save.import = Импортировать сохранение -text.save.newslot = Имя сохранения: -text.save.rename = Переименовать -text.save.rename.text = Новое название: -text.selectslot = Выберите сохранение. -text.slot = [accent]Слот {0} -text.save.corrupted = [accent]Сохранённый файл повреждён или имеет недействительный формат!\nЕсли вы только что обновили свою игру, это, вероятно, из-за изменение формата сохранения[scarlet], а не []ошибка. -text.sector.corrupted = [accent] Файл сохранения для этого сектора был найден, но загрузка не удалась.\nСоздан новый файл. -text.empty = <Пусто> -text.on = Вкл -text.off = Выкл -text.save.autosave = Автосохранение: {0} -text.save.map = Карта: {0} -text.save.wave = Волна: {0} -text.save.difficulty = Сложность: {0} -text.save.date = Последнее сохранение: {0} -text.save.playtime = Время в игре: {0} -text.confirm = Подтверждение -text.delete = Удалить -text.ok = ОК -text.open = Открыть -text.cancel = Отмена -text.openlink = Открыть ссылку -text.copylink = Скопировать ссылку -text.back = Назад -text.quit.confirm = Вы уверены, что хотите выйти? -text.changelog.title = Список изменений -text.changelog.loading = Получение изменений ... -text.changelog.error.android = [accent]Обратите внимание, что журнал изменений иногда не работает на Android 4.4 и ниже!\nЭто связано с внутренней ошибкой Android. -text.changelog.error.ios = [accent]В настоящее время журнал изменений не поддерживается iOS. -text.changelog.error = [scarlet]Ошибка при получении изменений!\nПроверьте подключение к Интернету. -text.changelog.current = [yellow][[Текущая версия] -text.changelog.latest = [accent][[Последняя версия] -text.loading = [accent] Загрузка... -text.saving = [accent]Сохранение.. -text.wave = [accent]Волна {0} -text.wave.waiting = [LIGHT_GRAY]Волна через {0} -text.waiting = Ожидание... -text.waiting.players = Ожидание игроков ... -text.wave.enemies = [LIGHT_GRAY]{0} противник. остался -text.wave.enemy = [LIGHT_GRAY]{0} противник остался -text.loadimage = Загрузить изображение -text.saveimage = Сохранить изображение -text.unknown = Неизвестно -text.custom = Пользовательская -text.builtin = Встроенная -text.map.delete.confirm = Вы действительно хотите удалить эту карту? Это действие не может быть отменено! -text.map.random = [accent]Случайная карта -text.map.nospawn = Эта карта не имеет ядер, в которых игрок может появиться! Добавьте[ROYAL] синее[] ядро на эту карту в редакторе карт. -text.map.nospawn.pvp = У этой карты нет вражеских ядер, в которых игрок может появиться! Добавьте[SCARLET] красные[] ядра к этой карте в редакторе. -text.map.invalid = Ошибка загрузки карты: повреждённый или недопустимый файл карты. -text.editor.brush = Кисть -text.editor.slope = \\ -text.editor.openin = Открыть в редакторе -text.editor.oregen = Генерация Руд -text.editor.oregen.info = Генерация Руд: -text.editor.mapinfo = Информация о карте -text.editor.author = Автор: -text.editor.description = Описание: -text.editor.name = Название: -text.editor.teams = Команды -text.editor.elevation = Возвышенность -text.editor.errorimageload = Ошибка загрузки изображения: [accent] {0} -text.editor.errorimagesave = Ошибка сохранения изображения: [accent] {0} -text.editor.generate = Создать -text.editor.resize = Изменить \nразмер -text.editor.loadmap = Загрузить\nкарту -text.editor.savemap = Сохранить\nкарту -text.editor.saved = Сохранено! -text.editor.save.noname = У Вашей карты нет названия! Назовите её в меню «Информация о карте». -text.editor.save.overwrite = Ваша карта не может быть записана поверх встроенной карты! Введите другое название в меню «Информация о карте» -text.editor.import.exists = [scarlet]Не удалось импортировать: []карта с данным именем уже существует '{0}'! -text.editor.import = Импорт... -text.editor.importmap = Импортировать карту -text.editor.importmap.description = Импортировать уже существующую карту -text.editor.importfile = Импортировать файл -text.editor.importfile.description = Импортировать файл карты из вне -text.editor.importimage = Импортировать устаревшее изображение -text.editor.importimage.description = Импортировать файл с изображения ландшафта -text.editor.export = Экспорт... -text.editor.exportfile = Экспортировать файл -text.editor.exportfile.description = Экспорт файла карты -text.editor.exportimage = Экспортировать изображение ландшафта -text.editor.exportimage.description = Экспортировать файл с изображением карты -text.editor.loadimage = Загрузить \nизображение -text.editor.saveimage = Сохранить \nизображение -text.editor.unsaved = [scarlet]У вас есть несохранённые изменения![]\nВы уверены, что хотите выйти? -text.editor.resizemap = Изменить размер карты -text.editor.mapname = Название карты: -text.editor.overwrite = [accent]Внимание! \nЭто перезапишет уже существующую карту. -text.editor.overwrite.confirm = [scarlet]Осторожно![] Карта с таким названием уже существует. Вы действительно хотите её перезаписать? -text.editor.selectmap = Выберите карту для загрузки: -text.width = Ширина: -text.height = Высота: -text.menu = Меню -text.play = Играть -text.load = Загрузить -text.save = Сохранить -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Пинг: {0} мс -text.language.restart = Перезагрузите игру, чтобы языковые настройки вступили в силу.\nPlease restart your game for the language settings to take effect. -text.settings = Настройки -text.tutorial = Обучение -text.editor = Редактор -text.mapeditor = Редактор карт -text.donate = Пожертво\nвать -text.connectfail = [crimson]Не удалось подключиться к серверу: [accent] {0} -text.error.unreachable = Сервер недоступен. -text.error.invalidaddress = Некорректный адрес. -text.error.timedout = Время ожидания истекло!\nУбедитесь, что хост настроен для перенаправления портов и адрес корректный! -text.error.mismatch = Ошибка пакета:\nвозможное несоответствие версии клиента/сервера. \nУбедитесь, что у Вас и у владельца сервера установлена последняя версия Mindustry! -text.error.alreadyconnected = Вы уже подключены. -text.error.mapnotfound = Не найден файл карты! -text.error.any = Неизвестная сетевая ошибка. -text.settings.language = Язык -text.settings.reset = Сбросить по умолчанию -text.settings.rebind = Смена -text.settings.controls = Управление -text.settings.game = Игра -text.settings.sound = Звук -text.settings.graphics = Графика -text.settings.cleardata = Очистить данные ... -text.settings.clear.confirm = Вы действительно хотите очистить свои данные?\nТо, что сделано, нельзя отменить! -text.settings.clearall.confirm = [scarlet]ОСТОРОЖНО![]\nЭто уничтожит все данные, включая сохранения, карты, разблокированное и настройки управления.\nПосле того как вы нажмете ОК, игра уничтожит все данные и автоматически закроется. -text.settings.clearsectors = Очистить секторы -text.settings.clearunlocks = Очистить разблокированное -text.settings.clearall = Очистить всё -text.paused = Пауза -text.yes = Да -text.no = Нет -text.info.title = Информация -text.error.title = [crimson]Произошла ошибка -text.error.crashtitle = Произошла ошибка -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = Информация о блоке -text.blocks.powercapacity = Вместимость энергии -text.blocks.powershot = Энергия/выстрел -text.blocks.targetsair = Атакует воздуш. юнитов? -text.blocks.itemspeed = Скорость перемещения ресурсов -text.blocks.shootrange = Радиус действия -text.blocks.size = Размер -text.blocks.liquidcapacity = Вместимость жидкости -text.blocks.maxitemssecond = Макс. количество предметов/секунду -text.blocks.powerrange = Диапазон передачи энергии -text.blocks.poweruse = Потребляет энергии -text.blocks.powerdamage = Энергия/урон -text.blocks.inputitemcapacity = Вместимость входящих предметов -text.blocks.outputitemcapacity = Вместимость выходящих предметов -text.blocks.itemcapacity = Вместимость предметов -text.blocks.basepowergeneration = Базовая генерация энергии -text.blocks.powertransferspeed = Скорость передачи энергии -text.blocks.craftspeed = Скорость производства -text.blocks.inputliquid = Прием жидкости -text.blocks.inputliquidaux = Вспом. жидкость -text.blocks.inputitem = Входящий предмет -text.blocks.inputitems = Входящие предметы -text.blocks.outputitem = Выходящий предмет -text.blocks.drilltier = Добывает -text.blocks.drillspeed = Базовая скорость сверления -text.blocks.liquidoutput = Выходящая жидкость -text.blocks.liquidoutputspeed = Выходная скорость жидкости -text.blocks.liquiduse = Используется жидкости -text.blocks.coolant = Охлаждающая жидкость -text.blocks.coolantuse = Охлажд. жидкости используется -text.blocks.inputliquidfuel = Жидкое топливо -text.blocks.liquidfueluse = Жидкого топлива используется -text.blocks.boostitem = Ускоряющий предмет -text.blocks.boostliquid = Ускоряющая жидкость -text.blocks.health = Здоровье -text.blocks.inaccuracy = Разброс -text.blocks.shots = Выстрелы -text.blocks.reload = Выстрелы/секунду -text.blocks.inputfuel = Входящее топливо -text.blocks.fuelburntime = Время горения топлива -text.blocks.inputcapacity = Макс. вместимость входящих предметов -text.blocks.outputcapacity = Макс. вместимость выходящих предметов -text.unit.blocks = блоки -text.unit.powersecond = единиц энергии/секунду -text.unit.liquidsecond = жидкостных единиц/секунду -text.unit.itemssecond = предметов/секунду -text.unit.pixelssecond = пикселей/секунду -text.unit.liquidunits = жидкостных единиц -text.unit.powerunits = энерг. единиц -text.unit.degrees = град. -text.unit.seconds = сек. -text.unit.items = единиц -text.category.general = Основные -text.category.power = Энергия -text.category.liquids = Жидкости -text.category.items = Предметы -text.category.crafting = Создание -text.category.shooting = Стрельба -text.category.optional = Дополнительные улучшения +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 = Авторы +contributors = Переводчики и контрибьюторы +discord = Присоединяйтесь к нашему Discord! +link.discord.description = Официальный discord-сервер Mindustry +link.github.description = Исходный код игры +link.dev-builds.description = Нестабильные версии +link.trello.description = Официальная доска trello для запланированных функций +link.itch.io.description = itch.io страница с загрузкой ПК версии и веб-версией игры +link.google-play.description = Скачать для Android c Google play +link.wiki.description = Официальная вики Mindustry(англ.) +linkfail = Не удалось открыть ссылку!\nURL-адрес был скопирован в буфер обмена. +screenshot = Screenshot saved to {0} +gameover = Игра окончена +gameover.pvp = [accent] {0}[] команда победила! +highscore = [YELLOW]Новый рекорд! +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: +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 в нижнем правом углу. +deconstruction.title = Руководство по разрушению блоков +deconstruction = Вы только что перешли в режим сноса[accent] блоков.[].\n\nЧтобы начать удалять, просто нажмите на блок рядом с вашим мехом.\nПосле того как вы выбрали несколько блоков, нажмите на галочку, чтобы подтвердить, и ваш мех начнёт их сносить.\n\n- [accent]Уберите блоки [] из вашего выбора, нажав на них.\n- [accent]Удалите блоки в области [], нажав и удерживая на пустом месте, а затем перетаскивая в нужном направлении.\n- [accent]Отменить снос или выбор [] можно нажав X в нижнем правом углу. +showagain = Не показывать снова до следующей сессии +coreattack = < Ядро находится под атакой! > +nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent +outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} +database = Core Database +savegame = Сохранить игру +loadgame = Загрузить игру +joingame = Присоеди\nниться +addplayers = Доб/удалить игроков +customgame = Пользовательская игра +newgame = New Game +none = <нет> +close = Закрыть +quit = Выход +maps = Карты +continue = Продолжить +maps.none = [LIGHT_GRAY]Карты не найдены! +about.button = Об игре +name = Ник: +noname = Pick a[accent] player name[] first. +filename = Имя файла: +unlocked = Новый блок разблокирован! +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.clientOutdated = Устаревший клиент! Обновите игру! +server.kicked.serverOutdated = Устаревший сервер! Попросите хоста обновить сервер/игру! +server.kicked.banned = Вы заблокированы на этом сервере. +server.kicked.recentKick = Вы недавно были кикнуты.\n Подождите немного перед следующим подключением +server.kicked.nameInUse = На этом сервере есть кто-то с этим именем. +server.kicked.nameEmpty = Ваше имя должно содержать хотя бы один символ или цифру. +server.kicked.idInUse = Вы уже на этом сервере! Соединение с двумя учетными записями не разрешено. +server.kicked.customClient = Этот сервер не поддерживает пользовательские сборки. Загрузите официальную версию. +server.kicked.gameover = Game over! +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 = Запустить сервер +hostserver.mobile = Запустить\nсервер +host = Сервер +hosting = [accent]Открытие сервера... +hosts.refresh = Обновить +hosts.discovering = Поиск локальных игр +server.refreshing = Обновление сервера +hosts.none = [lightgray]Локальных игр не обнаружено! +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 клиента! Отправьте отчёт об ошибке. +server.bans = Блокировки +server.bans.none = Заблокированных игроков нет! +server.admins = Администраторы +server.admins.none = Администраторов нет! +server.add = Добавить сервер +server.delete = Вы действительно хотите удалить этот сервер? +server.hostname = Хост: {0} +server.edit = Редактировать сервер +server.outdated = [crimson]Устаревший сервер![] +server.outdated.client = [crimson]Устаревший клиент![] +server.version = [lightgray]Версия: {0} {1} +server.custombuild = [yellow]Пользовательская сборка +confirmban = Вы действительно хотите заблокировать этого игрока? +confirmkick = Вы действительно хотите выгнать(кикнуть) этого игрока? +confirmunban = Вы действительно хотите разблокировать этого игрока? +confirmadmin = Вы уверены, что хотите сделать этого игрока администратором? +confirmunadmin = Вы действительно хотите убрать этого игрока из администраторов? +joingame.title = Присоединиться к игре +joingame.ip = IP: +disconnect = Отключён +disconnect.data = Не удалось загрузить данные мира! +connecting = [accent]Подключение... +connecting.data = [accent]Загрузка данных мира... +server.port = Порт: +server.addressinuse = Данный адрес уже используется! +server.invalidport = Неверный номер порта! +server.error = [crimson]Ошибка создания сервера: [accent] {0} +save.old = Это сохранение для более старой версии игры и больше не может использоваться.\n\n[LIGHT_GRAY]Совместимость сохранений будет реализована в полной версии 4.0. +save.new = Новое сохранение +save.overwrite = Вы уверены,что хотите перезаписать этот слот для сохранения? +overwrite = Перезаписать +save.none = Сохранения не найдены! +saveload = [accent]Сохранение... +savefail = Не удалось сохранить игру! +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 = Импортировать сохранение +save.newslot = Имя сохранения: +save.rename = Переименовать +save.rename.text = Новое название: +selectslot = Выберите сохранение. +slot = [accent]Слот {0} +save.corrupted = [accent]Сохранённый файл повреждён или имеет недействительный формат!\nЕсли вы только что обновили свою игру, это, вероятно, из-за изменение формата сохранения[scarlet], а не []ошибка. +empty = <Пусто> +on = Вкл +off = Выкл +save.autosave = Автосохранение: {0} +save.map = Карта: {0} +save.wave = Волна: {0} +save.difficulty = Сложность: {0} +save.date = Последнее сохранение: {0} +save.playtime = Время в игре: {0} +warning = Warning. +confirm = Подтверждение +delete = Удалить +ok = ОК +open = Открыть +cancel = Отмена +openlink = Открыть ссылку +copylink = Скопировать ссылку +back = Назад +quit.confirm = Вы уверены, что хотите выйти? +changelog.title = Список изменений +changelog.loading = Получение изменений ... +changelog.error.android = [accent]Обратите внимание, что журнал изменений иногда не работает на Android 4.4 и ниже!\nЭто связано с внутренней ошибкой Android. +changelog.error.ios = [accent]В настоящее время журнал изменений не поддерживается iOS. +changelog.error = [scarlet]Ошибка при получении изменений!\nПроверьте подключение к Интернету. +changelog.current = [yellow][[Текущая версия] +changelog.latest = [accent][[Последняя версия] +loading = [accent] Загрузка... +saving = [accent]Сохранение.. +wave = [accent]Волна {0} +wave.waiting = [LIGHT_GRAY]Волна через {0} +waiting = Ожидание... +waiting.players = Ожидание игроков ... +wave.enemies = [LIGHT_GRAY]{0} противник. остался +wave.enemy = [LIGHT_GRAY]{0} противник остался +loadimage = Загрузить изображение +saveimage = Сохранить изображение +unknown = Неизвестно +custom = Пользовательская +builtin = Встроенная +map.delete.confirm = Вы действительно хотите удалить эту карту? Это действие не может быть отменено! +map.random = [accent]Случайная карта +map.nospawn = Эта карта не имеет ядер, в которых игрок может появиться! Добавьте[ROYAL] синее[] ядро на эту карту в редакторе карт. +map.nospawn.pvp = У этой карты нет вражеских ядер, в которых игрок может появиться! Добавьте[SCARLET] красные[] ядра к этой карте в редакторе. +map.invalid = Ошибка загрузки карты: повреждённый или недопустимый файл карты. +editor.brush = Кисть +editor.slope = \\ +editor.openin = Открыть в редакторе +editor.oregen = Генерация Руд +editor.oregen.info = Генерация Руд: +editor.mapinfo = Информация о карте +editor.author = Автор: +editor.description = Описание: +editor.name = Название: +editor.teams = Команды +editor.elevation = Возвышенность +editor.errorimageload = Ошибка загрузки изображения: [accent] {0} +editor.errorimagesave = Ошибка сохранения изображения: [accent] {0} +editor.generate = Создать +editor.resize = Изменить \nразмер +editor.loadmap = Загрузить\nкарту +editor.savemap = Сохранить\nкарту +editor.saved = Сохранено! +editor.save.noname = У Вашей карты нет названия! Назовите её в меню «Информация о карте». +editor.save.overwrite = Ваша карта не может быть записана поверх встроенной карты! Введите другое название в меню «Информация о карте» +editor.import.exists = [scarlet]Не удалось импортировать: []карта с данным именем уже существует '{0}'! +editor.import = Импорт... +editor.importmap = Импортировать карту +editor.importmap.description = Импортировать уже существующую карту +editor.importfile = Импортировать файл +editor.importfile.description = Импортировать файл карты из вне +editor.importimage = Импортировать устаревшее изображение +editor.importimage.description = Импортировать файл с изображения ландшафта +editor.export = Экспорт... +editor.exportfile = Экспортировать файл +editor.exportfile.description = Экспорт файла карты +editor.exportimage = Экспортировать изображение ландшафта +editor.exportimage.description = Экспортировать файл с изображением карты +editor.loadimage = Загрузить \nизображение +editor.saveimage = Сохранить \nизображение +editor.unsaved = [scarlet]У вас есть несохранённые изменения![]\nВы уверены, что хотите выйти? +editor.resizemap = Изменить размер карты +editor.mapname = Название карты: +editor.overwrite = [accent]Внимание! \nЭто перезапишет уже существующую карту. +editor.overwrite.confirm = [scarlet]Осторожно![] Карта с таким названием уже существует. Вы действительно хотите её перезаписать? +editor.selectmap = Выберите карту для загрузки: +width = Ширина: +height = Высота: +menu = Меню +play = Играть +load = Загрузить +save = Сохранить +fps = FPS: {0} +tps = TPS: {0} +ping = Пинг: {0} мс +language.restart = Перезагрузите игру, чтобы языковые настройки вступили в силу.\nPlease restart your game for the language settings to take effect. +settings = Настройки +tutorial = Обучение +editor = Редактор +mapeditor = Редактор карт +donate = Пожертво\nвать +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson]Не удалось подключиться к серверу: [accent] {0} +error.unreachable = Сервер недоступен. +error.invalidaddress = Некорректный адрес. +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 = Смена +settings.controls = Управление +settings.game = Игра +settings.sound = Звук +settings.graphics = Графика +settings.cleardata = Очистить данные ... +settings.clear.confirm = Вы действительно хотите очистить свои данные?\nТо, что сделано, нельзя отменить! +settings.clearall.confirm = [scarlet]ОСТОРОЖНО![]\nЭто уничтожит все данные, включая сохранения, карты, разблокированное и настройки управления.\nПосле того как вы нажмете ОК, игра уничтожит все данные и автоматически закроется. +settings.clearunlocks = Очистить разблокированное +settings.clearall = Очистить всё +paused = Пауза +yes = Да +no = Нет +info.title = Информация +error.title = [crimson]Произошла ошибка +error.crashtitle = Произошла ошибка +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Информация о блоке +blocks.powercapacity = Вместимость энергии +blocks.powershot = Энергия/выстрел +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.liquid = Liquid +blocks.coolantuse = Охлажд. жидкости используется +blocks.inputliquidfuel = Жидкое топливо +blocks.liquidfueluse = Жидкого топлива используется +blocks.boostitem = Ускоряющий предмет +blocks.boostliquid = Ускоряющая жидкость +blocks.health = Здоровье +blocks.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = Разброс +blocks.shots = Выстрелы +blocks.reload = Выстрелы/секунду +blocks.inputfuel = Входящее топливо +blocks.fuelburntime = Время горения топлива +blocks.inputcapacity = Макс. вместимость входящих предметов +blocks.outputcapacity = Макс. вместимость выходящих предметов +unit.blocks = блоки +unit.powersecond = единиц энергии/секунду +unit.liquidsecond = жидкостных единиц/секунду +unit.itemssecond = предметов/секунду +unit.pixelssecond = пикселей/секунду +unit.liquidunits = жидкостных единиц +unit.powerunits = энерг. единиц +unit.degrees = град. +unit.seconds = сек. +unit.items = единиц +category.general = Основные +category.power = Энергия +category.liquids = Жидкости +category.items = Предметы +category.crafting = Создание +category.shooting = Стрельба +category.optional = Дополнительные улучшения +setting.indicators.name = Ally Indicators setting.autotarget.name = Авто-цель setting.fpscap.name = Макс. FPS setting.fpscap.none = Неограниченный @@ -372,18 +379,22 @@ setting.mutemusic.name = Заглушить музыку setting.sfxvol.name = Громкость звуковых эффектов setting.mutesound.name = Заглушить звук setting.crashreport.name = Отправлять анонимные отчёты о вылетах -text.keybind.title = Настройка управления +keybind.title = Настройка управления category.general.name = Основное category.view.name = Просмотр category.multiplayer.name = Мультиплеер command.attack = Атаковать command.retreat = Отступить command.patrol = Патрулирование +keybind.gridMode.name = Block Select +keybind.gridModeShift.name = Category Select keybind.press = Нажмите клавишу... keybind.press.axis = Нажмите клавишу... +keybind.screenshot.name = Map Screenshot keybind.move_x.name = Движение по оси x keybind.move_y.name = Движение по оси y keybind.select.name = Выбор/Выстрел +keybind.pick.name = Pick Block keybind.break.name = Разрушение keybind.deselect.name = Отмена keybind.shoot.name = Выстрел @@ -402,30 +413,29 @@ keybind.chat_history_next.name = След. история чата keybind.chat_scroll.name = Прокрутка чата keybind.drop_unit.name = Сбросить юнита keybind.zoom_minimap.name = Увеличить миникарту. -mode.text.help.title = Описание режимов -mode.waves.name = Волны -mode.waves.description = Обычный режим. В режиме "Волны" надо самим добывать ресурсы и сами волны идут безостановочно. +mode.help.title = Описание режимов +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 = Свободная\nстройка mode.freebuild.description = Ограниченные ресурсы и нет таймера для волн. mode.pvp.name = Противо-\nстояние mode.pvp.description = боритесь против других игроков. +mode.attack.name = Attack +mode.attack.descrption = 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,6 +456,10 @@ 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.oil.name = Нефть @@ -479,25 +493,29 @@ mech.trident-ship.weapon = Грузовой отсек с бомбами mech.glaive-ship.name = Копьё mech.glaive-ship.description = Большой, хорошо бронированный боевой корабль. Оснащён зажигательным ретранслятором. Хорошее ускорение и максимальная скорость. mech.glaive-ship.weapon = Огненный пулемёт -text.item.explosiveness = [LIGHT_GRAY]Взрывоопасность: {0}% -text.item.flammability = [LIGHT_GRAY]Воспламеняемость: {0}% -text.item.radioactivity = [LIGHT_GRAY]Радиоактивность: {0}% -text.item.fluxiness = [LIGHT_GRAY]Осадочность: {0}% -text.unit.health = [LIGHT_GRAY]Здоровье: {0} -text.unit.speed = [LIGHT_GRAY]Скорость: {0} -text.mech.weapon = [LIGHT_GRAY]Оружие: {0} -text.mech.armor = [LIGHT_GRAY]Броня: {0} -text.mech.itemcapacity = [LIGHT_GRAY]Вместимость предметов: {0} -text.mech.minespeed = [LIGHT_GRAY]Скорость добычи: {0} -text.mech.minepower = [LIGHT_GRAY]Мощность добычи: {0} -text.mech.ability = [LIGHT_GRAY]Способность: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]Теплоёмкость: {0} -text.liquid.viscosity = [LIGHT_GRAY]Вязкость: {0} -text.liquid.temperature = [LIGHT_GRAY]Температура: {0} +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]Health: {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.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](В процессе) block.spawn.name = Точка появления врагов -block.core.name = Ядро -block.space.name = Пустота +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = Металлическая плита block.deepwater.name = Глубоководье block.water.name = Вода @@ -516,8 +534,8 @@ block.blackrock.name = Чёрный булыжник block.icerock.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 = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = Фазовая стена block.phase-wall-large.name = Большая фазовая стена block.thorium-wall.name = Ториевая стена @@ -550,17 +568,19 @@ 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 = Реконструктор кораблей "Трезубeц" @@ -569,11 +589,11 @@ block.omega-mech-pad.name = Реконструктор мехов "Омега" block.tau-mech-pad.name = Реконструктор мехов "Тау" block.conduit.name = Трубопровод block.mechanical-pump.name = Механическая помпа -block.itemsource.name = Источник предметов -block.itemvoid.name = Предметный вакуум -block.liquidsource.name = Источник жидкостей -block.powervoid.name = Энергетический вакуум -block.powerinfinite.name = Источник энергии +block.item-source.name = Источник предметов +block.item-void.name = Предметный вакуум +block.liquid-source.name = Источник жидкостей +block.power-void.name = Энергетический вакуум +block.power-source.name = Источник энергии block.unloader.name = Разгрузчик block.vault.name = Хранилище block.wave.name = Волна @@ -625,7 +645,7 @@ block.rtg-generator.name = Радиоизотопный термоэлектри block.spectre.name = Призрак block.meltdown.name = Катастрофа block.container.name = Склад -block.core.description = Самое главное здание в игре. +block.launch-pad.name = Launch Pad team.blue.name = Синяя team.red.name = Красная team.orange.name = Оранжевая @@ -639,6 +659,7 @@ 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 = Бомбардировщик "Гуль" @@ -648,7 +669,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Создайте конвейеры от бура к ядру. @@ -771,11 +796,11 @@ block.router.description = Принимает предметы из одного block.distributor.description = Передовой маршрутизатор, который равномерно разбивает элементы до 7 других направлений. block.bridge-conveyor.description = Улучшенный транспортный блок элементов. Позволяет транспортировать предметы до 3-х блоков над любым ландшафтом или зданием. block.alpha-mech-pad.description = Превращает вас в мех [accent] Альфа[]. Требует энергию. -block.itemsource.description = Бесконечно выводит предметы. Работает только в песочнице. -block.liquidsource.description = Бесконечно выводит жидкости. Работает только в песочнице. -block.itemvoid.description = Уничтожает любые предметы, которые входят в него, без использования энергии. Работает только в режиме песочницы. -block.powerinfinite.description = Бесконечность — не предел. Бесконечно выводит энергию. Доступен только в режиме песочницы. -block.powervoid.description = Энергия просто уходит в пустоту. Присутствует только в песочнице. +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Смесь жидких углеводородов, выделяющаяся из природного газа в результате снижения температуры и пластового давления. diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties index e0476393f0..10cefc3ba5 100644 --- a/core/assets/bundles/bundle_tk.properties +++ b/core/assets/bundles/bundle_tk.properties @@ -1,351 +1,359 @@ -text.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!) -text.credits = Emegi gecenler -text.discord = Mindustry'in Discord'una katilin! -text.link.discord.description = Orjinal Mindustry'in Discord Konusma Odasi -text.link.github.description = Oyunun Kodu -text.link.dev-builds.description = Bitirilmemis Yapim Surumu -text.link.trello.description = Planlanmis Hersey icin Tablo -text.link.itch.io.description = Bilgisayar ve Site versiyonunun bulundugu Site -text.link.google-play.description = Google Play magaza sayfasi -text.link.wiki.description = Orjinal Mindustry Bilgilendirme Sayfasi -text.linkfail = Link Acilamadi!\nLink sizin icin kopyalandi. -text.gameover = Cekirdegin yok edildi. -text.gameover.pvp = The[accent] {0}[] team is victorious! -text.sector.gameover = Sektor kaybedildi. Geri gitmek ister misin? -text.sector.retry = Gene dene -text.highscore = [accent]Yeni Yuksek skor! -text.wave.lasted = Su dalgaya kadar dayandin: [accent]{0}[]. -text.level.highscore = Yuksek Skor: [accent]{0} -text.level.delete.title = Silmeyi onayla -text.map.delete = Su haritayi silmek istediginden emin misin? "[accent]{0}[]"? -text.level.select = Seviye secimi -text.level.mode = Oyun Modu: -text.construction.desktop = Bilgisayar kontrolleri degisti.\nEsyayi secmeyi birakmak istiyorsan [accent]bosluga bas[]. -text.construction.title = Esya Insaat Egitimi -text.construction = Sen su anda [accent]insaat moduna[]girdin.\n\nYerlestirbeye baslamadan once, kendine bos ve gecerli bir arazi sec ve tikla\nBiraz Yapi yerlestirdikten sonra, onaylamak icin tikla,, ve geminle beraber yapmaya baslayacaksin.\n\n- [accent]Yapi secimini kaldirmak[] icin yandan uzerlerine tikla.\n- [accent]Yapi yonunu degistimek[] icin farenin tekerlegini kullan \n- [accent]Cizgi biciminde Yapi yerlestirmek[] icin bos bir yete tikla ve surukle\n- [accent]Yapi yapmayi iptal etmek icin[] kosedeki X tusuna bas -text.deconstruction.title = Yapi yikma egitimi -text.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 -text.showagain = Don't show again next session -text.coreattack = < Cekirdek Saldiri altinda! > -text.unlocks = Oduller -text.savegame = Oyunu kaydet -text.loadgame = Devam et -text.joingame = Oyuna katil -text.addplayers = Oyuncu ekle/cikar -text.customgame = Ozel oyun -text.sectors = Sektorler -text.sector = Sector: [LIGHT_GRAY]{0} -text.sector.time = Time: [LIGHT_GRAY]{0} -text.sector.deploy = Yukle -text.sector.abandon = Abandon -text.sector.abandon.confirm = Are you sure you want to abandon all progress at this sector?\nThis cannot be undone! -text.sector.resume = Devam et -text.sector.locked = [scarlet][[Incomplete] -text.sector.unexplored = [accent][[Unexplored] -text.missions = Missions:[LIGHT_GRAY] {0} -text.mission = Mission:[LIGHT_GRAY] {0} -text.mission.main = Main Mission:[LIGHT_GRAY] {0} -text.mission.info = Mission Info -text.mission.complete = Gorev tamamlandi! -text.mission.complete.body = Sektor {0},{1} ele gecirildi -text.mission.wave = [accent]{0}/{1}[] Dalga hayatta kal\n{2} Dalga -text.mission.wave.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies -text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy -text.mission.wave.menu = Survive[accent] {0} []waves -text.mission.battle = Dusmanin cekirdegini yok et -text.mission.resource.menu = Obtain {0} x{1} -text.mission.resource = {0} x{1} Kazan -text.mission.block = Create {0} -text.mission.unit = Create {0} Unit -text.mission.command = Send Command {0} To Units -text.mission.linknode = Link Power Node -text.mission.display = [accent]Mission:\n[LIGHT_GRAY]{0} -text.mission.mech = Switch to mech[accent] {0}[] -text.mission.create = Create[accent] {0}[] -text.none = -text.close = Kapat -text.quit = Cik -text.maps = Haritalar -text.continue = Devam et -text.nextmission = Yeni gorev -text.maps.none = [LIGHT_GRAY]Harita bulunamadi! -text.about.button = Hakkinda -text.name = isim: -text.filename = File Name: -text.unlocked = Yeni yapi acildi!! -text.unlocked.plural = Yeni yapilar acildi! -text.players = {0} oyuncu cevrimici -text.players.single = {0} oyuncu cevrimici -text.server.closing = [accent]Oyun kapaniyor. -text.server.kicked.kick = Oyundan cikarildin -text.server.kicked.serverClose = Oyun kapandi -text.server.kicked.sectorComplete = Sektor tamamlandi -text.server.kicked.sectorComplete.text = Gorev Tamamlandi.\nOyun siradaki sektorden devam edecek -text.server.kicked.clientOutdated = Yeni bir versiyon mevcut! Hemen indir! -text.server.kicked.serverOutdated = Eski oyun! Yapimciya guncellemesini soyle! -text.server.kicked.banned = Oyundan kalici olarak cikarildin. -text.server.kicked.recentKick = Oyundan cikarilmistin.\nBaglanmadn once biraz bekle. -text.server.kicked.nameInUse = Oyunda bu isimde bir\nkisi zaten var. -text.server.kicked.nameEmpty = ismin gecerli degil. -text.server.kicked.idInUse = Zaten oyundasin! iki ayri hesapla oyuna katilamazsin! -text.server.kicked.customClient = Bu oyun ayarlanmis vesiyonlara izin vermiyor. Orijinal bir versiyon dene! -text.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. -text.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. -text.hostserver = Oyun ac -text.hostserver.mobile = Host\nGame -text.host = Oyun ac -text.hosting = [accent]Oyun aciliyor -text.hosts.refresh = Yenile -text.hosts.discovering = internet oyunu araniyor -text.server.refreshing = liste yenileniyor -text.hosts.none = [lightgray]internet oyunu bulunamadi! -text.host.invalid = [scarlet]Oyuna baglanilamadi. -text.trace = Oyuncu isaretle -text.trace.playername = Player name: [accent]{0} -text.trace.ip = IP: [accent]{0} -text.trace.id = Unik ID: [accent]{0} -text.trace.android = Android Kullanicisi: [accent]{0} -text.trace.modclient = Ozel islemci Kullanicisi: [accent]{0} -text.trace.totalblocksbroken = kirilan yapilar: [accent]{0} -text.trace.structureblocksbroken = kirilan esyalar: [accent]{0} -text.trace.lastblockbroken = Son kirilan yapilar: [accent]{0} -text.trace.totalblocksplaced = yerlestirilen yapilar: [accent]{0} -text.trace.lastblockplaced = son yerlestirilen yapilar: [accent]{0} -text.invalidid = Yanlis islemci Linki! Sorunu bildir -text.server.bans = Yasaklamalar -text.server.bans.none = Yasaklananlar bulunamadi! -text.server.admins = Yetkililer -text.server.admins.none = Yetkili bulunamadi! -text.server.add = Oyun ekle -text.server.delete = Oyunu silmek istedigine emin misin? -text.server.hostname = Oyun yarat: {0} -text.server.edit = Oyunu ayarla -text.server.outdated = [crimson]Eski Oyun![] -text.server.outdated.client = [crimson]eski islemci![] -text.server.version = [lightgray]Versiyon: {0} -text.server.custombuild = [yellow]ozel yapi -text.confirmban = Bu oyuncuyu kalici olarak atmak istedigine emin misin? -text.confirmkick = Are you sure you want to kick this player? -text.confirmunban = Bu oyuncunun yasagini geri almak ister misin? -text.confirmadmin = Bu oyuncuyu yetkili yapmak istedigine emin misin? -text.confirmunadmin = Bu oyuncunun yetkisini almak istedigine emin misin? -text.joingame.title = Oyuna katil -text.joingame.ip = Link: -text.disconnect = Cikildi -text.disconnect.data = Oyunun geri yuklenemedi! -text.connecting = [accent]Baglaniliyor -text.connecting.data = [accent]Loading world data... -text.server.port = Link: -text.server.addressinuse = Addres zaten kullaniliyor! -text.server.invalidport = Geçersiz Oyun numarasi! -text.server.error = [crimson]Oyun acarkes sorun olustu: [accent]{0} -text.save.old = Bu oyun su anda kullanilamaz.\n\n[LIGHT_GRAY]geri alma oyunun 4.0 surumunde eklenecektir. -text.save.new = Yeni Kayit Dosyasi -text.save.overwrite = Bu oyunun uzerinden\ngecmek istedigine emin\nmisin? -text.overwrite = uzerinden gec -text.save.none = Kayitli oyun bulunamadi -text.saveload = [accent]Kaydediliyor... -text.savefail = Kaydedilemedi! -text.save.delete.confirm = Bu Kayiti silmek istedigine emin misin? -text.save.delete = Sil -text.save.export = Kayiti tasi -text.save.import.invalid = [accent]Kayit gecersiz! -text.save.import.fail = [crimson]Failed to import save: [accent]{0} -text.save.export.fail = [crimson]Failed to export save: [accent]{0} -text.save.import = Kayit al -text.save.newslot = Kayit ismi: -text.save.rename = Yeniden adlandir -text.save.rename.text = Yeni isim: -text.selectslot = Kayitli bir dosya sec. -text.slot = [accent]Slot {0} -text.save.corrupted = [accent]Kayit gecersiz!\nOyunu guncellediysen, bu buyuk ihtimalle degistirilecek vebu bir [scarlet]sorun degildir.[] -text.sector.corrupted = [accent]Yeni dosyalar bulundu, ama yuklenemedi.\nYeni bir tane yapildi. -text.empty = -text.on = Acik -text.off = Kapali -text.save.autosave = Otomatik kayit: {0} -text.save.map = Harita: {0} -text.save.wave = Dalga {0} -text.save.difficulty = Zorluk: {0} -text.save.date = En sonki kayit: {0} -text.save.playtime = Oyun Zamani!: {0} -text.confirm = Onayla -text.delete = Sil -text.ok = Tamam -text.open = Ac -text.cancel = iptal -text.openlink = Linki ac -text.copylink = Linki kopyala -text.back = Geri don -text.quit.confirm = Cikmak istedigine emin misin? -text.changelog.title = Degisimler -text.changelog.loading = Degisimler yukleniyor... -text.changelog.error.android = [accent]Not: Degisimler bazen androidde calismaz.\nBu bir degistirilemez sorundan kaynakli. -text.changelog.error.ios = [accent]Degisimler IOS'da su anda desteklenmiyor. -text.changelog.error = [scarlet]Degisimler alinamadi.\nInternet baglantini kontrol et -text.changelog.current = [yellow][[Current version] -text.changelog.latest = [accent][[Latest version] -text.loading = [accent]Yukleniyor... -text.saving = [accent]Kaydediliyor... -text.wave = [accent]Dalga {0} -text.wave.waiting = Dalganin baslamasina: {0} -text.waiting = Bekleniyor... -text.waiting.players = Waiting for players... -text.wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining -text.wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining -text.loadimage = Resimden Yukle -text.saveimage = Resimi kaydet -text.unknown = Bilinmeyen -text.custom = Ozel -text.builtin = Yapilandirilmis -text.map.delete.confirm = Haritayi silmek istedigine emin misin? Bu geri alinamaz! -text.map.random = [accent]Rasgele harita -text.map.nospawn = Haritada Oyncularin cikmasi icin cekirdek yok! Haritaya[ROYAL]Mavi[] cekirdek ekle. -text.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. -text.map.invalid = Harita yuklenemedi. Gecersiz yada bozuk dosya. -text.editor.brush = Firca -text.editor.slope = \\ -text.editor.openin = Editorde ac -text.editor.oregen = Maden Yaratilma hizi -text.editor.oregen.info = Maden Yaratilmasi: -text.editor.mapinfo = Harita bilgisi: -text.editor.author = Yapimci: -text.editor.description = Yorum: -text.editor.name = isim: -text.editor.teams = Takimlar -text.editor.elevation = Yukseklik -text.editor.errorimageload = Dosya yuklenemedi:\n[accent]{0} -text.editor.errorimagesave = Dosya kaydedilemedi.:\n[accent]{0} -text.editor.generate = Yarat -text.editor.resize = Boyutunu degistir -text.editor.loadmap = Harita yukle -text.editor.savemap = Haritayi kaydet -text.editor.saved = Kaydedildi! -text.editor.save.noname = Haritanin ismi yok! 'Harita bilgisinden' bi tane ekle -text.editor.save.overwrite = Haritanin ismi varolan bir haritanin ismi ile ayni! 'Harita bilgisinden' degisik bir isim sec -text.editor.import.exists = [scarlet]Tasinamadi.:[] ayni isimi tasiyan bir harita '{0}' zaten var!! -text.editor.import = Bilgisayara kaydet -text.editor.importmap = Bilgisayardan harita al -text.editor.importmap.description = Varolan bir harita al -text.editor.importfile = Dosyayi bilgisayara kaydet -text.editor.importfile.description = Bilgisayara ozel harita yukle -text.editor.importimage = Yuzey resmi al -text.editor.importimage.description = Degisik Yuzey resmi al -text.editor.export = Disari al -text.editor.exportfile = Disari cikart -text.editor.exportfile.description = Haritayi disari cikart -text.editor.exportimage = Haritanin resmini disari cikart -text.editor.exportimage.description = Haritanin resmini disari aktar -text.editor.loadimage = Araziyi yukle -text.editor.saveimage = Araziyi disari aktar -text.editor.unsaved = [scarlet]Kaydedilmemis verileriniz var![]\ncikmak istedigine emin misin? -text.editor.resizemap = Haritanin boyutunu degistir -text.editor.mapname = Harita ismi: -text.editor.overwrite = [accent]Dikkat et!\nBu bir haritanin uzerinden cececek. -text.editor.overwrite.confirm = [scarlet]uyari![] bu isimde bir harita zaten var. Uzerinden gececek misin? -text.editor.selectmap = Yukleyecek bir harita sec: -text.width = Genislik: -text.height = Yukseklik: -text.menu = Menu -text.play = Oyna -text.load = Yukle -text.save = Kaydet -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Ping: {0}ms -text.language.restart = Lutfen dil degisiminin etkin olmasi icin oyunu yeniden baslatin -text.settings = ayarlar -text.tutorial = Tutorial -text.editor = Editor -text.mapeditor = Harita yaraticisi -text.donate = Bagis yap -text.connectfail = [crimson]Su Oyuna baglanilamadi: [accent]{0} -text.error.unreachable = Server unreachable. -text.error.invalidaddress = Invalid address. -text.error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! -text.error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! -text.error.alreadyconnected = Already connected. -text.error.mapnotfound = Map file not found! -text.error.any = Unkown network error. -text.settings.language = Dil -text.settings.reset = ilk ayarlara geri al -text.settings.rebind = Geri al -text.settings.controls = Kontroller -text.settings.game = Oyun -text.settings.sound = Ses -text.settings.graphics = Grafikler -text.settings.cleardata = Clear Game Data... -text.settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! -text.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. -text.settings.clearsectors = Clear Sectors -text.settings.clearunlocks = Clear Unlocks -text.settings.clearall = Clear All -text.paused = Duraklatildi -text.yes = Evet -text.no = Hayir -text.info.title = [accent]Bilgi -text.error.title = [crimson]Bir hata olustu -text.error.crashtitle = Bir hata olustu -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = Yapi bilgisi -text.blocks.powercapacity = Guc kapasitesi -text.blocks.powershot = Guc/Saldiri hizi -text.blocks.targetsair = Havayi hedef alir mi? -text.blocks.itemspeed = Ilerleme hizi -text.blocks.shootrange = Menzil -text.blocks.size = Buyukluk -text.blocks.liquidcapacity = Sivi kapasitesi -text.blocks.maxitemssecond = Esya limiti -text.blocks.powerrange = Menzil -text.blocks.poweruse = Guc kullanimi -text.blocks.powerdamage = Power/Damage -text.blocks.inputitemcapacity = Giris esya kapasitesi -text.blocks.outputitemcapacity = Cikis esya kapasitesi -text.blocks.itemcapacity = Esya kapasitesi -text.blocks.basepowergeneration = Base Power Generation -text.blocks.powertransferspeed = Guc transfer hizi -text.blocks.craftspeed = Yapilma hizi -text.blocks.inputliquid = Giris sivi -text.blocks.inputliquidaux = Yardimci sivi -text.blocks.inputitem = Giris esyasi -text.blocks.inputitems = Giris esyalari -text.blocks.outputitem = Sonuc -text.blocks.drilltier = Kazilabilirler -text.blocks.drillspeed = Ana kazma hizi -text.blocks.liquidoutput = Sivi cikisi -text.blocks.liquidoutputspeed = Liquid Output Speed -text.blocks.liquiduse = Sivi kullanimi -text.blocks.coolant = Sogutma sivisi -text.blocks.coolantuse = Sogutma sivi kullanimi -text.blocks.inputliquidfuel = Yakit sivisi -text.blocks.liquidfueluse = Sivi yakit kullanimi -text.blocks.boostitem = Boost Item -text.blocks.boostliquid = Boost Liquid -text.blocks.health = Can -text.blocks.inaccuracy = sekme -text.blocks.shots = vuruslar -text.blocks.reload = Yeniden doldurma -text.blocks.inputfuel = Yakit -text.blocks.fuelburntime = Yakit yakilma suresi -text.blocks.inputcapacity = Giris kapasitesi -text.blocks.outputcapacity = Cikis kapasitesi -text.unit.blocks = Yapilar -text.unit.powersecond = saniyede bir -text.unit.liquidsecond = Saniyede bir -text.unit.itemssecond = Saniyede bir -text.unit.pixelssecond = Saniyede bir -text.unit.liquidunits = Litre -text.unit.powerunits = Volt -text.unit.degrees = derece -text.unit.seconds = saniye -text.unit.items = esya -text.category.general = General -text.category.power = Guc -text.category.liquids = sivilar -text.category.items = esyalar -text.category.crafting = uretim -text.category.shooting = sikma -text.category.optional = Optional Enhancements +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 +link.dev-builds.description = Bitirilmemis Yapim Surumu +link.trello.description = Planlanmis Hersey icin Tablo +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! +highscore = [accent]Yeni Yuksek skor! +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: +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[]. +construction.title = Esya Insaat Egitimi +construction = Sen su anda [accent]insaat moduna[]girdin.\n\nYerlestirbeye baslamadan once, kendine bos ve gecerli bir arazi sec ve tikla\nBiraz Yapi yerlestirdikten sonra, onaylamak icin tikla,, ve geminle beraber yapmaya baslayacaksin.\n\n- [accent]Yapi secimini kaldirmak[] icin yandan uzerlerine tikla.\n- [accent]Yapi yonunu degistimek[] icin farenin tekerlegini kullan \n- [accent]Cizgi biciminde Yapi yerlestirmek[] icin bos bir yete tikla ve surukle\n- [accent]Yapi yapmayi iptal etmek icin[] kosedeki X tusuna bas +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! > +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 +newgame = New Game +none = +close = Kapat +quit = Cik +maps = Haritalar +continue = Devam et +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!! +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.clientOutdated = Yeni bir versiyon mevcut! Hemen indir! +server.kicked.serverOutdated = Eski oyun! Yapimciya guncellemesini soyle! +server.kicked.banned = Oyundan kalici olarak cikarildin. +server.kicked.recentKick = Oyundan cikarilmistin.\nBaglanmadn once biraz bekle. +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 +hostserver.mobile = Host\nGame +host = Oyun ac +hosting = [accent]Oyun aciliyor +hosts.refresh = Yenile +hosts.discovering = internet oyunu araniyor +server.refreshing = liste yenileniyor +hosts.none = [lightgray]internet oyunu bulunamadi! +host.invalid = [scarlet]Oyuna baglanilamadi. +trace = Oyuncu isaretle +trace.playername = Player name: [accent]{0} +trace.ip = IP: [accent]{0} +trace.id = Unik ID: [accent]{0} +trace.android = Android Kullanicisi: [accent]{0} +trace.modclient = Ozel islemci Kullanicisi: [accent]{0} +trace.totalblocksbroken = kirilan yapilar: [accent]{0} +trace.structureblocksbroken = kirilan esyalar: [accent]{0} +trace.lastblockbroken = Son kirilan yapilar: [accent]{0} +trace.totalblocksplaced = yerlestirilen yapilar: [accent]{0} +trace.lastblockplaced = son yerlestirilen yapilar: [accent]{0} +invalidid = Yanlis islemci Linki! Sorunu bildir +server.bans = Yasaklamalar +server.bans.none = Yasaklananlar bulunamadi! +server.admins = Yetkililer +server.admins.none = Yetkili bulunamadi! +server.add = Oyun ekle +server.delete = Oyunu silmek istedigine emin misin? +server.hostname = Oyun yarat: {0} +server.edit = Oyunu ayarla +server.outdated = [crimson]Eski Oyun![] +server.outdated.client = [crimson]eski islemci![] +server.version = [lightgray]Versiyon: {0} +server.custombuild = [yellow]ozel yapi +confirmban = Bu oyuncuyu kalici olarak atmak istedigine emin misin? +confirmkick = Are you sure you want to kick this player? +confirmunban = Bu oyuncunun yasagini geri almak ister misin? +confirmadmin = Bu oyuncuyu yetkili yapmak istedigine emin misin? +confirmunadmin = Bu oyuncunun yetkisini almak istedigine emin misin? +joingame.title = Oyuna katil +joingame.ip = Link: +disconnect = Cikildi +disconnect.data = Oyunun geri yuklenemedi! +connecting = [accent]Baglaniliyor +connecting.data = [accent]Loading world data... +server.port = Link: +server.addressinuse = Addres zaten kullaniliyor! +server.invalidport = Geçersiz Oyun numarasi! +server.error = [crimson]Oyun acarkes sorun olustu: [accent]{0} +save.old = Bu oyun su anda kullanilamaz.\n\n[LIGHT_GRAY]geri alma oyunun 4.0 surumunde eklenecektir. +save.new = Yeni Kayit Dosyasi +save.overwrite = Bu oyunun uzerinden\ngecmek istedigine emin\nmisin? +overwrite = uzerinden gec +save.none = Kayitli oyun bulunamadi +saveload = [accent]Kaydediliyor... +savefail = Kaydedilemedi! +save.delete.confirm = Bu Kayiti silmek istedigine emin misin? +save.delete = Sil +save.export = Kayiti tasi +save.import.invalid = [accent]Kayit gecersiz! +save.import.fail = [crimson]Failed to import save: [accent]{0} +save.export.fail = [crimson]Failed to export save: [accent]{0} +save.import = Kayit al +save.newslot = Kayit ismi: +save.rename = Yeniden adlandir +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.[] +empty = +on = Acik +off = Kapali +save.autosave = Otomatik kayit: {0} +save.map = Harita: {0} +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 +open = Ac +cancel = iptal +openlink = Linki ac +copylink = Linki kopyala +back = Geri don +quit.confirm = Cikmak istedigine emin misin? +changelog.title = Degisimler +changelog.loading = Degisimler yukleniyor... +changelog.error.android = [accent]Not: Degisimler bazen androidde calismaz.\nBu bir degistirilemez sorundan kaynakli. +changelog.error.ios = [accent]Degisimler IOS'da su anda desteklenmiyor. +changelog.error = [scarlet]Degisimler alinamadi.\nInternet baglantini kontrol et +changelog.current = [yellow][[Current version] +changelog.latest = [accent][[Latest version] +loading = [accent]Yukleniyor... +saving = [accent]Kaydediliyor... +wave = [accent]Dalga {0} +wave.waiting = Dalganin baslamasina: {0} +waiting = Bekleniyor... +waiting.players = Waiting for players... +wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining +wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining +loadimage = Resimden Yukle +saveimage = Resimi kaydet +unknown = Bilinmeyen +custom = Ozel +builtin = Yapilandirilmis +map.delete.confirm = Haritayi silmek istedigine emin misin? Bu geri alinamaz! +map.random = [accent]Rasgele harita +map.nospawn = Haritada Oyncularin cikmasi icin cekirdek yok! Haritaya[ROYAL]Mavi[] cekirdek ekle. +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: +editor.mapinfo = Harita bilgisi: +editor.author = Yapimci: +editor.description = Yorum: +editor.name = isim: +editor.teams = Takimlar +editor.elevation = Yukseklik +editor.errorimageload = Dosya yuklenemedi:\n[accent]{0} +editor.errorimagesave = Dosya kaydedilemedi.:\n[accent]{0} +editor.generate = Yarat +editor.resize = Boyutunu degistir +editor.loadmap = Harita yukle +editor.savemap = Haritayi kaydet +editor.saved = Kaydedildi! +editor.save.noname = Haritanin ismi yok! 'Harita bilgisinden' bi tane ekle +editor.save.overwrite = Haritanin ismi varolan bir haritanin ismi ile ayni! 'Harita bilgisinden' degisik bir isim sec +editor.import.exists = [scarlet]Tasinamadi.:[] ayni isimi tasiyan bir harita '{0}' zaten var!! +editor.import = Bilgisayara kaydet +editor.importmap = Bilgisayardan harita al +editor.importmap.description = Varolan bir harita al +editor.importfile = Dosyayi bilgisayara kaydet +editor.importfile.description = Bilgisayara ozel harita yukle +editor.importimage = Yuzey resmi al +editor.importimage.description = Degisik Yuzey resmi al +editor.export = Disari al +editor.exportfile = Disari cikart +editor.exportfile.description = Haritayi disari cikart +editor.exportimage = Haritanin resmini disari cikart +editor.exportimage.description = Haritanin resmini disari aktar +editor.loadimage = Araziyi yukle +editor.saveimage = Araziyi disari aktar +editor.unsaved = [scarlet]Kaydedilmemis verileriniz var![]\ncikmak istedigine emin misin? +editor.resizemap = Haritanin boyutunu degistir +editor.mapname = Harita ismi: +editor.overwrite = [accent]Dikkat et!\nBu bir haritanin uzerinden cececek. +editor.overwrite.confirm = [scarlet]uyari![] bu isimde bir harita zaten var. Uzerinden gececek misin? +editor.selectmap = Yukleyecek bir harita sec: +width = Genislik: +height = Yukseklik: +menu = Menu +play = Oyna +load = Yukle +save = Kaydet +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0}ms +language.restart = Lutfen dil degisiminin etkin olmasi icin oyunu yeniden baslatin +settings = ayarlar +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson]Su Oyuna baglanilamadi: [accent]{0} +error.unreachable = Server unreachable. +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 = 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 +settings.controls = Kontroller +settings.game = Oyun +settings.sound = Ses +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.clearunlocks = Clear Unlocks +settings.clearall = Clear All +paused = Duraklatildi +yes = Evet +no = Hayir +info.title = [accent]Bilgi +error.title = [crimson]Bir hata olustu +error.crashtitle = Bir hata olustu +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Yapi bilgisi +blocks.powercapacity = Guc kapasitesi +blocks.powershot = Guc/Saldiri hizi +blocks.targetsair = Havayi hedef alir mi? +blocks.itemspeed = Ilerleme hizi +blocks.shootrange = Menzil +blocks.size = Buyukluk +blocks.liquidcapacity = Sivi kapasitesi +blocks.maxitemssecond = Esya limiti +blocks.powerrange = Menzil +blocks.poweruse = Guc kullanimi +blocks.powerdamage = Power/Damage +blocks.inputitemcapacity = Giris esya kapasitesi +blocks.outputitemcapacity = Cikis esya kapasitesi +blocks.itemcapacity = Esya kapasitesi +blocks.basepowergeneration = Base Power Generation +blocks.powertransferspeed = Guc transfer hizi +blocks.craftspeed = Yapilma hizi +blocks.inputliquid = Giris sivi +blocks.inputliquidaux = Yardimci sivi +blocks.inputitem = Giris esyasi +blocks.inputitems = Giris esyalari +blocks.outputitem = Sonuc +blocks.drilltier = Kazilabilirler +blocks.drillspeed = Ana kazma hizi +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.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = sekme +blocks.shots = vuruslar +blocks.reload = Yeniden doldurma +blocks.inputfuel = Yakit +blocks.fuelburntime = Yakit yakilma suresi +blocks.inputcapacity = Giris kapasitesi +blocks.outputcapacity = Cikis kapasitesi +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 +unit.seconds = saniye +unit.items = esya +category.general = General +category.power = Guc +category.liquids = sivilar +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 @@ -371,18 +379,22 @@ setting.mutemusic.name = Sesi kapat setting.sfxvol.name = Ses seviyesi setting.mutesound.name = Sesi kapat setting.crashreport.name = Send Anonymous Crash Reports -text.keybind.title = Tuslari ayarla +keybind.title = Tuslari ayarla category.general.name = General category.view.name = Goster 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.pick.name = Pick Block keybind.break.name = Kirma keybind.deselect.name = Eldeki yapiyi birak keybind.shoot.name = Sik @@ -401,30 +413,29 @@ keybind.chat_history_next.name = Konusma gecmisi ileri keybind.chat_scroll.name = Konusma kaydir keybind.drop_unit.name = Unit birak keybind.zoom_minimap.name = Haritayi yaklastir -mode.text.help.title = Modlarin aciklamalari -mode.waves.name = Dalgali -mode.waves.description = Klasik mod. Dalgalara karsi cekirdegi koru. +mode.help.title = Modlarin aciklamalari +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.descrption = 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 @@ -445,6 +456,10 @@ 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.oil.name = Benzin @@ -478,24 +493,29 @@ mech.trident-ship.weapon = mini atomlar mech.glaive-ship.name = Glaive mech.glaive-ship.description = Guzel, buyuk bir unit. Hiz limiti ve kapesitesi iyidir mech.glaive-ship.weapon = Orman yakici -text.item.explosiveness = [LIGHT_GRAY]Patlayicilik: {0} -text.item.flammability = [LIGHT_GRAY]Yanbilirlik: {0} -text.item.radioactivity = [LIGHT_GRAY]Radyoaktivite: {0} -text.item.fluxiness = [LIGHT_GRAY]akis gucu: {0} -text.unit.health = [LIGHT_GRAY]Can: {0} -text.unit.speed = [LIGHT_GRAY]hiz: {0} -text.mech.weapon = [LIGHT_GRAY]silah: {0} -text.mech.armor = [LIGHT_GRAY]zirh: {0} -text.mech.itemcapacity = [LIGHT_GRAY]esya kapasitesi: {0} -text.mech.minespeed = [LIGHT_GRAY]kazma hizi: {0} -text.mech.minepower = [LIGHT_GRAY]kazma gucu: {0} -text.mech.ability = [LIGHT_GRAY]yetenek gucu: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]isinma kapasitesi: {0} -text.liquid.viscosity = [LIGHT_GRAY]Yari sivilik: {0} -text.liquid.temperature = [LIGHT_GRAY]isi: {0} +item.explosiveness = [LIGHT_GRAY]Patlayicilik: {0} +item.flammability = [LIGHT_GRAY]Yanbilirlik: {0} +item.radioactivity = [LIGHT_GRAY]Radyoaktivite: {0} +unit.health = [LIGHT_GRAY]Can: {0} +unit.speed = [LIGHT_GRAY]hiz: {0} +mech.weapon = [LIGHT_GRAY]silah: {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} +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.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.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = metal zemin block.deepwater.name = su alti block.water.name = su @@ -514,8 +534,8 @@ block.blackrock.name = bkara tas block.icerock.name = buz tasi 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 @@ -548,17 +568,19 @@ 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 @@ -567,11 +589,11 @@ block.omega-mech-pad.name = Omega Mech Pad block.tau-mech-pad.name = Tau Mech Pad block.conduit.name = boru block.mechanical-pump.name = Mekanikal pompa -block.itemsource.name = esya kaynagi -block.itemvoid.name = esya deligi -block.liquidsource.name = sivi kaynagi -block.powervoid.name = guc deligi -block.powerinfinite.name = sonsuz guc +block.item-source.name = esya kaynagi +block.item-void.name = esya deligi +block.liquid-source.name = sivi kaynagi +block.power-void.name = guc deligi +block.power-source.name = sonsuz guc block.unloader.name = bekletici block.vault.name = kasa block.wave.name = Dalga @@ -623,7 +645,7 @@ 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 team.blue.name = blue team.red.name = red team.orange.name = orange @@ -637,6 +659,7 @@ 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 +669,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. @@ -769,11 +796,11 @@ block.router.description = Accepts items from one direction and outputs them to 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.itemsource.description = Infinitely outputs items. Sandbox only. -block.liquidsource.description = Infinitely outputs liquids. Sandbox only. -block.itemvoid.description = Destroys any items which go into it without using power. Sandbox only. -block.powerinfinite.description = Infinitely outputs power. Sandbox only. -block.powervoid.description = Voids all power inputted into it. Sandbox only. +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. diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 616b2c03b4..13c62b3f50 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -1,353 +1,359 @@ -text.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!) -text.credits = Yapımcılar -text.discord = Mindustry Discord'una katılın! -text.link.discord.description = Resmi Mindustry Discord iletişim kanalı -text.link.github.description = Oyunun kaynak kodu -text.link.dev-builds.description = Geliştirme altında olan sürüm -text.link.trello.description = Planlanan özellikler için resmi Trello Bülteni -text.link.itch.io.description = PC yüklemeleri ve web sürümü ile itch.io sayfası -text.link.google-play.description = Google Play mağaza sayfası -text.link.wiki.description = Resmi Mindustry Wikipedi'si -text.linkfail = Bağlantı açılamadı\! URL, yazı tahtanıza kopyalandı. -text.editor.web = Web sürümü editörü desteklemiyor\! Editörü kullanmak için oyunu indirin. -text.web.unsupported = Site versiyonu bunu desteklemiyor\! Oyunu indirip dene. -text.gameover = Çekirdek yok edildi. -text.gameover.pvp = [accent] {0}[] takimi kazandi \! -text.sector.gameover = Sektor kaybedildi. -text.sector.retry = Tekrar dene -text.highscore = [SARI] Yeni yüksek puan\! -text.wave.lasted = Su dalgaya kadar yasadin: [accent]{0}[]. -text.level.highscore = Yüksek Puan\: [accent] {0} -text.level.delete.title = Silmeyi onaylayın -text.map.delete = Su haritayi silmek istedigine emin misin? "[orange]{0}[]"? -text.level.select = Seviye Seç -text.level.mode = Oyun Modu -text.construction.desktop = Masaustu kontrolleri degisti.\nSecmeyi birakip yapmayi kesmek icin, [accent]bosluga bas[]. -text.construction.title = Blok Yapma Ogreticisi -text.construction = Sen su anda [accent]blok yapma moduna gectin[].\n\nYapmaya baslamak icin, geminin cevresinde uygun bir yere tikla.\nBiraz blok sectikten sonra, onaylamak icin "tik" tusuna bas, ve gemin onlari yapmaya baslayacaktir.\n\n- [accent]Blok kaldirmak[] icin onlari secme yerine gene tikla\n- [accent]Blok secmek icin[] onlara secme yerinde tikla.\n- [accent]Cizgi biciminde koymak icin[] bos bir yere bas, ve bir yere dogru surukle.\n- [accent]Yapma modundan cikmak icin[] alt kosedeki X tusuna bas -text.deconstruction.title = Blok Yikim Ogreticisi -text.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 -text.showagain = Bunu gene gosterme -text.coreattack = < Cekirdek saldiri altinda\! > -text.unlocks = Koleksiyon -text.savegame = Oyunu Kaydet -text.loadgame = Oyunu yükle -text.joingame = Oyuna katıl -text.addplayers = Oyuncu ekle/cikar -text.customgame = Ozel oyun -text.sectors = Sektorler -text.sector = Su sektoru sectin\: [LIGHT_GRAY]{0} -text.sector.time = Zaman\: [LIGHT_GRAY]{0} -text.sector.deploy = Basla -text.sector.abandon = Terk et -text.sector.abandon.confirm = Buradaki ilerlemeni silmek istedigine emin misin\nBu geri alinamaz\! -text.sector.resume = Devam et -text.sector.locked = [scarlet][[Bitirilmedi] -text.sector.unexplored = [accent][[Kesvedilmedş] -text.missions = Gorevler\:[LIGHT_GRAY] {0} -text.mission = Gorev\:[LIGHT_GRAY] {0} -text.mission.main = Ana gorev\:[LIGHT_GRAY] {0} -text.mission.info = Gorev bilgisi -text.mission.complete = Gorev tamamlandi\! -text.mission.complete.body = Sektor {0},{1} ele gecirildi -text.mission.wave = [accent]{0}[] dalga hayatta kal -text.mission.wave.enemies = [accent] {0}/{1} []dalga hayatta kal\n{2} Dusman oldur -text.mission.wave.enemy = [accent] {0}/{1} []dalga hayatta kal\n{2} Dusman oldur -text.mission.wave.menu = [accent] {0} []dalga hayatta kal -text.mission.battle = Dusman temelini yok et -text.mission.resource.menu = Sunlari ele gecir {0} x{1} -text.mission.resource = Sunlari ele gecir {0}\:\n[accent]{1}/{2}[] -text.mission.block = Su kadar yarat {0} -text.mission.unit = {0} Kadar unit yarat -text.mission.command = {0} Unite komut yolla -text.mission.linknode = Guc nodu bagla -text.mission.display = [accent]Gorev\:\n[LIGHT_GRAY]{0} -text.mission.mech = Su gemiye degis[accent] {0}[] -text.mission.create = Su kadar yarat[accent] {0}[] -text.none = -text.close = Kapat -text.quit = Çık -text.maps = Haritalar -text.continue = Devam et -text.nextmission = Siradaki gorev -text.maps.none = [LIGHT_GRAY]Harita bulunamadi\! -text.about.button = Hakkında -text.name = Adı: -text.filename = File Name: -text.unlocked = New Block Unlocked! -text.unlocked.plural = New Blocks Unlocked! -text.players = 1090 oyuncu çevrimiçi -text.players.single = {0} Oyuncu Çevrimiçi -text.server.closing = [accent] Sunucu kapatılıyor ... -text.server.kicked.kick = Sunucudan kovuldun! -text.server.kicked.serverClose = Server closed. -text.server.kicked.sectorComplete = Sector completed. -text.server.kicked.sectorComplete.text = Your mission is complete.\nThe server will now continue at the next sector. -text.server.kicked.clientOutdated = Oyun sürümünüz geçerli değil. Oyununu güncelleyin! -text.server.kicked.serverOutdated = Eski sunucu! Ev sahibinden güncellemesini isteyin! -text.server.kicked.banned = Bu sunucudan yasaklandınız. -text.server.kicked.recentKick = Son zamanlarda tekmelendin. Tekrar bağlanmadan önce bekleyin. -text.server.kicked.nameInUse = There is someone with that name\nalready on this server. -text.server.kicked.nameEmpty = Your name must contain at least one character or number. -text.server.kicked.idInUse = You are already on this server! Connecting with two accounts is not permitted. -text.server.kicked.customClient = This server does not support custom builds. Download an official version. -text.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. -text.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. -text.hostserver = Oyunu Sun -text.hostserver.mobile = Host\nGame -text.host = evsahibi -text.hosting = [accent] Sunucu açılıyor ... -text.hosts.refresh = Yenile -text.hosts.discovering = LAN oyunlarını keşfetme -text.server.refreshing = Canlandırıcı sunucu -text.hosts.none = [lightgray] Hayır LAN oyunları bulundu! -text.host.invalid = [scarlet] Ana bilgisayara bağlanılamıyor. -text.trace = Oyuncuyu Takip Et -text.trace.playername = Oyuncu adı: [accent] {0} -text.trace.ip = IP: [vurgu] {0} -text.trace.id = Benzersiz kimlik: [accent] {0} -text.trace.android = Android : [accent] {0} -text.trace.modclient = Özel Alıcı: [accent] {0} -text.trace.totalblocksbroken = Toplam kırık blok: [accent] {0} -text.trace.structureblocksbroken = Kırılan yapı blokları: [accent] {0} -text.trace.lastblockbroken = Kırılan son blok: [accent] {0} -text.trace.totalblocksplaced = Toplam blok yerleştirildi: [accent] {0} -text.trace.lastblockplaced = Konulan son blok: [accent] {0} -text.invalidid = Geçersiz alıcı kimliği! Bir hata raporu gönderin. -text.server.bans = yasaklar -text.server.bans.none = Yasaklanmış oyuncu bulunamadı! -text.server.admins = Yöneticiler -text.server.admins.none = Yönetici bulunamadı! -text.server.add = Sunucu ekle -text.server.delete = Bu sunucuyu silmek istediğinizden emin misiniz? -text.server.hostname = Sun -text.server.edit = Sunucuyu Düzenle -text.server.outdated = [crimson] Eski Sunucu! -text.server.outdated.client = [crimson] Eski Alıcı! -text.server.version = [lightgray] Sürüm: {0} -text.server.custombuild = [sarı] Özel Yapım -text.confirmban = Bu oyuncuyu yasaklamak istediğinizden emin misiniz? -text.confirmkick = Are you sure you want to kick this player? -text.confirmunban = Bu oyuncunun yasağını kaldırmak istediğinden emin misin? -text.confirmadmin = Bu oyuncunun yönetici yapmak istediğinden emin misin? -text.confirmunadmin = Bu oyuncudan yönetici durumunu kaldırmak istediğinizden emin misiniz? -text.joingame.title = Oyuna katılmak -text.joingame.ip = IP: -text.disconnect = Bağlantı Kesildi -text.disconnect.data = Dünya verileri yüklenemedi! -text.connecting = [Vurgu] bağlanıyor ... -text.connecting.data = [accent] Dünya verileri yükleniyor ... -text.server.port = Liman -text.server.addressinuse = Adres çoktan kullanımda! -text.server.invalidport = Bağlantı noktası numarası geçersiz. -text.server.error = [crimson] Sunucu barındırma hatası: [accent] {0} -text.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. -text.save.new = 6349,Yeni Kayıt -text.save.overwrite = Bu kayıt yuvasının üzerine yazmak istediğinizden emin misiniz? -text.overwrite = Üzerine Yaz -text.save.none = Hiçbir kayıt bulunamadı! -text.saveload = [Vurgu] Kaydediliyor ... -text.savefail = Oyun kaydedilemedi! -text.save.delete.confirm = Bu kaydı silmek istediğinizden emin misiniz? -text.save.delete = Sil -text.save.export = Dışa Aktar -text.save.import.invalid = [turuncu] Bu kayıt geçersiz! -text.save.import.fail = [crimson] Kayıt oyuna aktarılamadı : [accent] {0} -text.save.export.fail = [crimson] Kayıt dışa aktarılamadı: [accent] {0} -text.save.import = İçe Aktar -text.save.newslot = İsmi kaydet: -text.save.rename = Yeniden Adlandır -text.save.rename.text = Yeni İsim: -text.selectslot = Bir kayıt seçin. -text.slot = [accent] Yuva {0} -text.save.corrupted = [accent] Kayıt dosyası bozuk veya geçersiz! -text.sector.corrupted = [accent]A save file for this sector was found, but loading failed.\nA new one has been created. -text.empty = -text.on = Açık -text.off = Kapalı -text.save.autosave = Otomatik kaydetme: {0} -text.save.map = harita -text.save.wave = Dalga -text.save.difficulty = zorluk -text.save.date = Son Kaydedilen: {0} -text.save.playtime = Playtime: {0} -text.confirm = Onayla -text.delete = Sil -text.ok = Tamam -text.open = Açık -text.cancel = İptal -text.openlink = Linki aç -text.copylink = Bağlantıyı kopyala -text.back = Geri -text.quit.confirm = Çıkmak istediğinden emin misin? -text.changelog.title = Değişiklik listesi -text.changelog.loading = Değişiklik listesi yükleniyor -text.changelog.error.android = [turuncu] Android'da olan hata nedeniyle değişiklik listesi görüntülenemiyor. -text.changelog.error.ios = [accent]The changelog is currently not supported in iOS. -text.changelog.error = [scarlet] Değişiklik listesi alma hatası! İnternet bağlantınızı kontrol edin. -text.changelog.current = [sarı] [[Güncel versiyon] -text.changelog.latest = [turuncu] [[Son sürüm] -text.loading = [Vurgu] Yükleniyor ... -text.saving = [accent]Saving... -text.wave = [turuncu] Dalga {0} -text.wave.waiting = {0} içinde dalga -text.waiting = Bekleniyor -text.waiting.players = Waiting for players... -text.wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining -text.wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining -text.loadimage = Resmi yükle -text.saveimage = Resmi Kaydet -text.unknown = Unknown -text.custom = Custom -text.builtin = Built-In -text.map.delete.confirm = Are you sure you want to delete this map? This action cannot be undone! -text.map.random = [accent]Random Map -text.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. -text.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. -text.map.invalid = Error loading map: corrupted or invalid map file. -text.editor.brush = Brush -text.editor.slope = \\ -text.editor.openin = Open In Editor -text.editor.oregen = Ore Generation -text.editor.oregen.info = Ore Generation: -text.editor.mapinfo = Map Info -text.editor.author = Author: -text.editor.description = Description: -text.editor.name = Name: -text.editor.teams = Teams -text.editor.elevation = Elevation -text.editor.errorimageload = Resim dosyası yüklenirken hata oluştu: [accent] {0} -text.editor.errorimagesave = Resim dosyası kaydedilirken hata oluştu: [accent] {0} -text.editor.generate = Üretmek -text.editor.resize = Yeniden Boyutlandırma -text.editor.loadmap = Harita Yükle -text.editor.savemap = Harita Kaydet -text.editor.saved = Saved! -text.editor.save.noname = Your map does not have a name! Set one in the 'map info' menu. -text.editor.save.overwrite = Your map overwrites a built-in map! Pick a different name in the 'map info' menu. -text.editor.import.exists = [scarlet]Unable to import:[] a built-in map named '{0}' already exists! -text.editor.import = Import... -text.editor.importmap = Import Map -text.editor.importmap.description = Import an already existing map -text.editor.importfile = Import File -text.editor.importfile.description = Import an external map file -text.editor.importimage = Import Terrain Image -text.editor.importimage.description = Import an external map image file -text.editor.export = Export... -text.editor.exportfile = Export File -text.editor.exportfile.description = Export a map file -text.editor.exportimage = Export Terrain Image -text.editor.exportimage.description = Export a map image file -text.editor.loadimage = Resmi yükle -text.editor.saveimage = Resmi Kaydet -text.editor.unsaved = [scarlet] Kaydedilmemiş değişiklikleriniz var! [] Çıkmak istediğinizden emin misiniz? -text.editor.resizemap = Haritayı Yeniden Boyutlandır -text.editor.mapname = Harita Adı -text.editor.overwrite = [Vurgu] Uyarı! Bu mevcut bir haritanın üzerine yazar. -text.editor.overwrite.confirm = [scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? -text.editor.selectmap = Yüklenecek bir harita seçin: -text.width = Genişliği: -text.height = Boy: -text.menu = Menü -text.play = Oyna -text.load = Yükle -text.save = Kaydet -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Ping: {0}ms -text.language.restart = Lütfen dil ayarlarının etkili olması için oyununuzu yeniden başlatın. -text.settings = Ayarlar -text.tutorial = Eğitim -text.editor = Editör -text.mapeditor = Harita Editörü -text.donate = Bağışlamak -text.connectfail = [crimson] Sunucuya bağlanılamadı: [accent] {0} -text.error.unreachable = Server unreachable. -text.error.invalidaddress = Invalid address. -text.error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! -text.error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! -text.error.alreadyconnected = Already connected. -text.error.mapnotfound = Map file not found! -text.error.any = Unkown network error. -text.settings.language = Dil -text.settings.reset = Varsayılanlara Dön -text.settings.rebind = Rebind -text.settings.controls = kontroller -text.settings.game = Oyun -text.settings.sound = Ses -text.settings.graphics = Grafik -text.settings.cleardata = Clear Game Data... -text.settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! -text.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. -text.settings.clearsectors = Clear Sectors -text.settings.clearunlocks = Clear Unlocks -text.settings.clearall = Clear All -text.paused = Duraklatıldı -text.yes = Yes -text.no = No -text.info.title = [Vurgu] Bilgi -text.error.title = [crimson] Bir hata oluştu -text.error.crashtitle = Bir hata oluştu -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = Blok Bilgisi -text.blocks.powercapacity = Güç kapasitesi -text.blocks.powershot = Güç / atış -text.blocks.targetsair = Targets Air -text.blocks.itemspeed = Units Moved -text.blocks.shootrange = Range -text.blocks.size = Boyut -text.blocks.liquidcapacity = Sıvı kapasitesi -text.blocks.maxitemssecond = Maksimum öğe / saniye -text.blocks.powerrange = Güç aralığı -text.blocks.poweruse = Power Use -text.blocks.powerdamage = Power/Damage -text.blocks.inputitemcapacity = Input Item Capacity -text.blocks.outputitemcapacity = Input Item Capacity -text.blocks.itemcapacity = Ürün kapasitesi -text.blocks.basepowergeneration = Base Power Generation -text.blocks.powertransferspeed = Power Transfer -text.blocks.craftspeed = Production Speed -text.blocks.inputliquid = Giriş sıvı -text.blocks.inputliquidaux = Aux Liquid -text.blocks.inputitem = Giriş öğesi -text.blocks.inputitems = Input Items -text.blocks.outputitem = Output Item -text.blocks.drilltier = Drillables -text.blocks.drillspeed = Base Drill Speed -text.blocks.liquidoutput = Liquid Output -text.blocks.liquidoutputspeed = Liquid Output Speed -text.blocks.liquiduse = Liquid Use -text.blocks.coolant = Coolant -text.blocks.coolantuse = Coolant Use -text.blocks.inputliquidfuel = Fuel Liquid -text.blocks.liquidfueluse = Liquid Fuel Use -text.blocks.boostitem = Boost Item -text.blocks.boostliquid = Boost Liquid -text.blocks.health = Can -text.blocks.inaccuracy = yanlışlık -text.blocks.shots = atışlar -text.blocks.reload = Reload -text.blocks.inputfuel = Fuel -text.blocks.fuelburntime = Fuel Burn Time -text.blocks.inputcapacity = Giriş kapasitesi -text.blocks.outputcapacity = Çıkış kapasitesi -text.unit.blocks = blocks -text.unit.powersecond = power units/second -text.unit.liquidsecond = liquid units/second -text.unit.itemssecond = items/second -text.unit.pixelssecond = pixels/second -text.unit.liquidunits = liquid units -text.unit.powerunits = power units -text.unit.degrees = degrees -text.unit.seconds = seconds -text.unit.items = items -text.category.general = General -text.category.power = Power -text.category.liquids = Liquids -text.category.items = Items -text.category.crafting = Crafting -text.category.shooting = Shooting -text.category.optional = Optional Enhancements +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 +link.dev-builds.description = Geliştirme altında olan sürüm +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ı. +screenshot = Screenshot saved to {0} +gameover = Çekirdek yok edildi. +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: +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[]. +construction.title = Blok Yapma Ogreticisi +construction = Sen su anda [accent]blok yapma moduna gectin[].\n\nYapmaya baslamak icin, geminin cevresinde uygun bir yere tikla.\nBiraz blok sectikten sonra, onaylamak icin "tik" tusuna bas, ve gemin onlari yapmaya baslayacaktir.\n\n- [accent]Blok kaldirmak[] icin onlari secme yerine gene tikla\n- [accent]Blok secmek icin[] onlara secme yerinde tikla.\n- [accent]Cizgi biciminde koymak icin[] bos bir yere bas, ve bir yere dogru surukle.\n- [accent]Yapma modundan cikmak icin[] alt kosedeki X tusuna bas +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! > +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 +newgame = New Game +none = +close = Kapat +quit = Çık +maps = Haritalar +continue = Devam et +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! +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.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. +server.kicked.recentKick = Son zamanlarda tekmelendin. Tekrar bağlanmadan önce bekleyin. +server.kicked.nameInUse = There is someone with that name\nalready on this server. +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 +hostserver.mobile = Host\nGame +host = evsahibi +hosting = [accent] Sunucu açılıyor ... +hosts.refresh = Yenile +hosts.discovering = LAN oyunlarını keşfetme +server.refreshing = Canlandırıcı sunucu +hosts.none = [lightgray] Hayır LAN oyunları bulundu! +host.invalid = [scarlet] Ana bilgisayara bağlanılamıyor. +trace = Oyuncuyu Takip Et +trace.playername = Oyuncu adı: [accent] {0} +trace.ip = IP: [vurgu] {0} +trace.id = Benzersiz kimlik: [accent] {0} +trace.android = Android : [accent] {0} +trace.modclient = Özel Alıcı: [accent] {0} +trace.totalblocksbroken = Toplam kırık blok: [accent] {0} +trace.structureblocksbroken = Kırılan yapı blokları: [accent] {0} +trace.lastblockbroken = Kırılan son blok: [accent] {0} +trace.totalblocksplaced = Toplam blok yerleştirildi: [accent] {0} +trace.lastblockplaced = Konulan son blok: [accent] {0} +invalidid = Geçersiz alıcı kimliği! Bir hata raporu gönderin. +server.bans = yasaklar +server.bans.none = Yasaklanmış oyuncu bulunamadı! +server.admins = Yöneticiler +server.admins.none = Yönetici bulunamadı! +server.add = Sunucu ekle +server.delete = Bu sunucuyu silmek istediğinizden emin misiniz? +server.hostname = Sun +server.edit = Sunucuyu Düzenle +server.outdated = [crimson] Eski Sunucu! +server.outdated.client = [crimson] Eski Alıcı! +server.version = [lightgray] Sürüm: {0} +server.custombuild = [sarı] Özel Yapım +confirmban = Bu oyuncuyu yasaklamak istediğinizden emin misiniz? +confirmkick = Are you sure you want to kick this player? +confirmunban = Bu oyuncunun yasağını kaldırmak istediğinden emin misin? +confirmadmin = Bu oyuncunun yönetici yapmak istediğinden emin misin? +confirmunadmin = Bu oyuncudan yönetici durumunu kaldırmak istediğinizden emin misiniz? +joingame.title = Oyuna katılmak +joingame.ip = IP: +disconnect = Bağlantı Kesildi +disconnect.data = Dünya verileri yüklenemedi! +connecting = [Vurgu] bağlanıyor ... +connecting.data = [accent] Dünya verileri yükleniyor ... +server.port = Liman +server.addressinuse = Adres çoktan kullanımda! +server.invalidport = Bağlantı noktası numarası geçersiz. +server.error = [crimson] Sunucu barındırma hatası: [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 = 6349,Yeni Kayıt +save.overwrite = Bu kayıt yuvasının üzerine yazmak istediğinizden emin misiniz? +overwrite = Üzerine Yaz +save.none = Hiçbir kayıt bulunamadı! +saveload = [Vurgu] Kaydediliyor ... +savefail = Oyun kaydedilemedi! +save.delete.confirm = Bu kaydı silmek istediğinizden emin misiniz? +save.delete = Sil +save.export = Dışa Aktar +save.import.invalid = [turuncu] Bu kayıt geçersiz! +save.import.fail = [crimson] Kayıt oyuna aktarılamadı : [accent] {0} +save.export.fail = [crimson] Kayıt dışa aktarılamadı: [accent] {0} +save.import = İçe Aktar +save.newslot = İsmi kaydet: +save.rename = Yeniden Adlandır +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! +empty = +on = Açık +off = Kapalı +save.autosave = Otomatik kaydetme: {0} +save.map = harita +save.wave = Dalga +save.difficulty = zorluk +save.date = Son Kaydedilen: {0} +save.playtime = Playtime: {0} +warning = Warning. +confirm = Onayla +delete = Sil +ok = Tamam +open = Açık +cancel = İptal +openlink = Linki aç +copylink = Bağlantıyı kopyala +back = Geri +quit.confirm = Çıkmak istediğinden emin misin? +changelog.title = Değişiklik listesi +changelog.loading = Değişiklik listesi yükleniyor +changelog.error.android = [turuncu] Android'da olan hata nedeniyle değişiklik listesi görüntülenemiyor. +changelog.error.ios = [accent]The changelog is currently not supported in iOS. +changelog.error = [scarlet] Değişiklik listesi alma hatası! İnternet bağlantınızı kontrol edin. +changelog.current = [sarı] [[Güncel versiyon] +changelog.latest = [turuncu] [[Son sürüm] +loading = [Vurgu] Yükleniyor ... +saving = [accent]Saving... +wave = [turuncu] Dalga {0} +wave.waiting = {0} içinde dalga +waiting = Bekleniyor +waiting.players = Waiting for players... +wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining +wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining +loadimage = Resmi yükle +saveimage = Resmi Kaydet +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.slope = \\ +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 = Resim dosyası yüklenirken hata oluştu: [accent] {0} +editor.errorimagesave = Resim dosyası kaydedilirken hata oluştu: [accent] {0} +editor.generate = Üretmek +editor.resize = Yeniden Boyutlandırma +editor.loadmap = Harita Yükle +editor.savemap = Harita Kaydet +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 Terrain 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 = Resmi yükle +editor.saveimage = Resmi Kaydet +editor.unsaved = [scarlet] Kaydedilmemiş değişiklikleriniz var! [] Çıkmak istediğinizden emin misiniz? +editor.resizemap = Haritayı Yeniden Boyutlandır +editor.mapname = Harita Adı +editor.overwrite = [Vurgu] Uyarı! Bu mevcut bir haritanın üzerine yazar. +editor.overwrite.confirm = [scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? +editor.selectmap = Yüklenecek bir harita seçin: +width = Genişliği: +height = Boy: +menu = Menü +play = Oyna +load = Yükle +save = Kaydet +fps = FPS: {0} +tps = TPS: {0} +ping = Ping: {0}ms +language.restart = Lütfen dil ayarlarının etkili olması için oyununuzu yeniden başlatın. +settings = Ayarlar +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson] Sunucuya bağlanılamadı: [accent] {0} +error.unreachable = Server unreachable. +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 = 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 +settings.controls = kontroller +settings.game = Oyun +settings.sound = Ses +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.clearunlocks = Clear Unlocks +settings.clearall = Clear All +paused = Duraklatıldı +yes = Yes +no = No +info.title = [Vurgu] Bilgi +error.title = [crimson] Bir hata oluştu +error.crashtitle = Bir hata oluştu +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Blok Bilgisi +blocks.powercapacity = Güç kapasitesi +blocks.powershot = Güç / atış +blocks.targetsair = Targets Air +blocks.itemspeed = Units Moved +blocks.shootrange = Range +blocks.size = Boyut +blocks.liquidcapacity = Sıvı kapasitesi +blocks.maxitemssecond = Maksimum öğe / saniye +blocks.powerrange = Güç aralığı +blocks.poweruse = Power Use +blocks.powerdamage = Power/Damage +blocks.inputitemcapacity = Input Item Capacity +blocks.outputitemcapacity = Input Item Capacity +blocks.itemcapacity = Ürün kapasitesi +blocks.basepowergeneration = Base Power Generation +blocks.powertransferspeed = Power Transfer +blocks.craftspeed = Production Speed +blocks.inputliquid = Giriş sıvı +blocks.inputliquidaux = Aux Liquid +blocks.inputitem = Giriş öğesi +blocks.inputitems = Input Items +blocks.outputitem = Output Item +blocks.drilltier = Drillables +blocks.drillspeed = Base Drill Speed +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.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = yanlışlık +blocks.shots = atışlar +blocks.reload = Reload +blocks.inputfuel = Fuel +blocks.fuelburntime = Fuel Burn Time +blocks.inputcapacity = Giriş kapasitesi +blocks.outputcapacity = Çıkış kapasitesi +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 +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 @@ -373,18 +379,22 @@ setting.mutemusic.name = Müziği Kapat setting.sfxvol.name = SFX Hacmi setting.mutesound.name = Sesi kapat setting.crashreport.name = Send Anonymous Crash Reports -text.keybind.title = Tuşları yeniden ayarla +keybind.title = Tuşları yeniden ayarla 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 = sağ / sol keybind.move_y.name = yukarı / aşağı keybind.select.name = seçmek +keybind.pick.name = Pick Block keybind.break.name = kırmak keybind.deselect.name = Deselect keybind.shoot.name = ateş etme @@ -403,30 +413,29 @@ 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.text.help.title = Modların açıklaması -mode.waves.name = dalgalar -mode.waves.description = normal mod. sınırlı kaynaklar ve otomatik gelen dalgalar. +mode.help.title = Modların açıklaması +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.descrption = 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 @@ -447,6 +456,10 @@ 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.oil.name = petrol @@ -480,24 +493,29 @@ 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 -text.item.explosiveness = [LIGHT_GRAY]Explosiveness: {0} -text.item.flammability = [LIGHT_GRAY]Flammability: {0} -text.item.radioactivity = [LIGHT_GRAY]Radioactivity: {0} -text.item.fluxiness = [LIGHT_GRAY]Flux Power: {0} -text.unit.health = [LIGHT_GRAY]Health: {0} -text.unit.speed = [LIGHT_GRAY]Speed: {0} -text.mech.weapon = [LIGHT_GRAY]Weapon: {0} -text.mech.armor = [LIGHT_GRAY]Armor: {0} -text.mech.itemcapacity = [LIGHT_GRAY]Item Capacity: {0} -text.mech.minespeed = [LIGHT_GRAY]Mining Speed: {0} -text.mech.minepower = [LIGHT_GRAY]Mining Power: {0} -text.mech.ability = [LIGHT_GRAY]Ability: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]Heat Capacity: {0} -text.liquid.viscosity = [LIGHT_GRAY]Viscosity: {0} -text.liquid.temperature = [LIGHT_GRAY]Temperature: {0} +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.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.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = Metal Floor block.deepwater.name = deepwater block.water.name = water @@ -516,8 +534,8 @@ block.blackrock.name = blackrock block.icerock.name = icerock 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 @@ -550,17 +568,19 @@ 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 @@ -569,11 +589,11 @@ block.omega-mech-pad.name = Omega Mech Pad block.tau-mech-pad.name = Tau Mech Pad block.conduit.name = sıvı borusu block.mechanical-pump.name = Mechanical Pump -block.itemsource.name = Item Source -block.itemvoid.name = Item Void -block.liquidsource.name = Liquid Source -block.powervoid.name = Power Void -block.powerinfinite.name = Power Infinite +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 @@ -625,7 +645,7 @@ 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 team.blue.name = blue team.red.name = red team.orange.name = orange @@ -639,6 +659,7 @@ 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 +669,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. @@ -771,11 +796,11 @@ block.router.description = Accepts items from one direction and outputs them to 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.itemsource.description = Infinitely outputs items. Sandbox only. -block.liquidsource.description = Infinitely outputs liquids. Sandbox only. -block.itemvoid.description = Destroys any items which go into it without using power. Sandbox only. -block.powerinfinite.description = Infinitely outputs power. Sandbox only. -block.powervoid.description = Voids all power inputted into it. Sandbox only. +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. diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index 6bc5700d53..2e13882933 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -1,351 +1,359 @@ -text.credits.text = Створив [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\nЄ питання по грі або проблеми с перекладом? Іди в офіційний сервер discord Mindustry в канал #український. -text.credits = Автори -text.contributors = Перекладачі та Контриб'ютори -text.discord = Приєднуйтесь до нашого Discord! -text.link.discord.description = Офіційний discord-сервер Mindustry -text.link.github.description = Код гри -text.link.dev-builds.description = Нестабільні версії -text.link.trello.description = Офіційна дошка trello(на англ.) для запланованих функцій -text.link.itch.io.description = Itch.io сторінка з веб-версією та завантаженням для ПК -text.link.google-play.description = Скачати з Google Play для Android -text.link.wiki.description = Офіційна Mindustry вікі (англ.) -text.linkfail = Не вдалося відкрити посилання!\nURL-адреса скопійовано у ваш буфер обміну. -text.gameover = Гру закінчено -text.gameover.pvp = [accent] {0}[] команда перемогла! -text.sector.gameover = Цей сектор було втрачено. Повторно висадитися? -text.sector.retry = Повторити спробу -text.highscore = [YELLOW]Новий рекорд! -text.wave.lasted = Вы продержались до [accent]{0}[]-ой волны. -text.level.highscore = Рекорд: [accent]{0} -text.level.delete.title = Підтвердьте видалення -text.map.delete = Ви впевнені, що хочете видалити карту "[accent]{0}[]"? -text.level.select = Вибір мапи -text.level.mode = Режим гри: -text.construction.desktop = Щоб скасувати вибір блоку або припинити будівництво, [accent] скористайтеся пробілом[]. -text.construction.title = Інструкція з будівництва блоків -text.construction = Ви тільки що перейшли в режим будівництва[accent] блоків[].\n\nЩоб розпочати розміщення, просто торкніться підходящого місця поруч із вашим кораблем.\nПісля вибору деяких блоків натисніть прапорець, щоб підтвердити, і ваш корабель почне будувати їх.\n\n- [accent]Вилучіть блоки[] з вашого вибору, торкнувшись їх.\n- [accent]Перемістіть виділення[] утримуючи та перетягнувши будь-який блок у виділенні.\n- [accent]Розташуйте блоки у лінію[], торкнувшись і утримуючи порожнє місце, а потім перетягуючи в потрібному напрямку.\n- [accent]Скасуйте розміщення блоків[] натиснувши X внизу ліворуч. -text.deconstruction.title = Інструкція з деконструкції блоків -text.deconstruction = Ви тільки що перешли в [accent] режим деконструкції блоків[].\n\nЩоб почати руйнувати, просто торкніться блоку поруч із вашим кораблем.\nПісля вибору деяких блоків натисніть прапорець, щоб підтвердити, і ваш корабель почне їх деконструювати.\n\n- [accent]Вилучіть блоки[] з вашого вибору, торкнувшись їх.\n- [accent]Вилучіть блоки в зоні[] , торкнувшись і утримуючи порожнє місце, потім перетягніть у потрібному напрямку.\n- [accent]Скасуйте деконструкцію або виділення[] натиснувши X внизу ліворуч. -text.showagain = Не показувати знову до наступного сеансу -text.coreattack = < Ядро під атакою! > -text.unlocks = Розблоковане -text.savegame = Зберегти гру -text.loadgame = Завантажити гру -text.joingame = Приєднатися -text.addplayers = Дод/Видалити гравців -text.customgame = Користувальницька гра -text.sectors = Сектори -text.sector = Обраний сектор: [LIGHT_GRAY]{0} -text.sector.time = Час: [LIGHT_GRAY]{0} -text.sector.deploy = Висадитися -text.sector.abandon = Відступити -text.sector.abandon.confirm = Ви впевнені, що хочете відступити?\nЦе не може бути скасовано! -text.sector.resume = Продовжити -text.sector.locked = [scarlet][[Незавершений] -text.sector.unexplored = [accent][[Недосліджений] -text.missions = Місії:[LIGHT_GRAY] {0} -text.mission = Місія:[LIGHT_GRAY] {0} -text.mission.main = Головна місія:[LIGHT_GRAY] {0} -text.mission.info = Інформація про місію -text.mission.complete = Місія виконана! -text.mission.complete.body = Сектор {0},{1} був завойований. -text.mission.wave = Пережити [accent]{0}/{1}[]\nХвиля через {2} -text.mission.wave.enemies = Пережити [accent] {0}/{1} []хвиль\n{2} ворог. -text.mission.wave.enemy = Пережити[accent] {0}/{1} []хвил.\n{2} Ворог -text.mission.wave.menu = Пережити[accent] {0} [] хвиль -text.mission.battle = Знищте ядро супротивника. -text.mission.resource.menu = Добути {0} x{1} -text.mission.resource = Добути {0}:\n[accent]{1}/{2}[] -text.mission.block = Створити {0} -text.mission.unit = Створити {0} бой.од. -text.mission.command = Надіслати команду {0} боїв. одиницям -text.mission.linknode = З'єднати силові вузли -text.mission.display = [accent]Місія:\n[LIGHT_GRAY]{0} -text.mission.mech = Переключитися на мех[accent] {0}[] -text.mission.create = Створити[accent] {0}[] -text.none = <нічого> -text.close = Закрити -text.quit = Вийти -text.maps = Мапи -text.continue = Продовжити -text.nextmission = Наступна місія -text.maps.none = [LIGHT_GRAY]Карт не знайдено! -text.about.button = Про гру -text.name = Нік: -text.filename = Ім'я файлу: -text.unlocked = Новий блок розблоковано! -text.unlocked.plural = Нові блоки розблоковано! -text.players = Гравців на сервері: {0} -text.players.single = {0} гравець на сервері -text.server.closing = [accent]Закриття серверу... -text.server.kicked.kick = Ви були вигнані(кікнуті) з сервера! -text.server.kicked.serverClose = Сервер закрито. -text.server.kicked.sectorComplete = Сектор завойовано. -text.server.kicked.sectorComplete.text = Ваша місія завершена. \nСервер продовжить роботу і висадить Вас в наступному секторі. -text.server.kicked.clientOutdated = Застарілий клієнт! Оновіть свою гру! -text.server.kicked.serverOutdated = Застарілий сервер! Попросіть адміністратора серверу оновити сервер/гру! -text.server.kicked.banned = Ви були заблоковані на цьому сервері. -text.server.kicked.recentKick = Нещодавно Вас вигнали(кікнули). \nПочекайте трохи перед наступним підключенням. -text.server.kicked.nameInUse = На цьому сервері є хтось \nз таким ніком. -text.server.kicked.nameEmpty = Ваш нікнейм має містити принаймні один символ або цифру. -text.server.kicked.idInUse = Ви вже на цьому сервері! Підключення двох облікових записів не допускається. -text.server.kicked.customClient = Цей сервер не підтримує користувальницькі збірки. Завантажте офіційну версію. -text.host.info = Кнопка [accent]Сервер[] розміщує сервер на порті [scarlet]6567[]. \nКористувачі, які знаходяться у тій же [LIGHT_GRAY] WiFi або локальній мережі[] повинні бачити ваш сервер у своєму списку серверів.\n\nЯкщо ви хочете, щоб люди могли приєднуватися з будь-якої точки через IP, то [accent] переадресація порту [] обов'язкова.\n\n[LIGHT_GRAY] Примітка. Якщо у вас виникли проблеми з підключенням до вашої локальної гри, переконайтеся, що ви дозволили Mindustry доступ до вашої локальної мережі в налаштуваннях брандмауера. -text.join.info = Тут ви можете ввести [accent]IP серверу[] для підключення або знайти сервери у [accent]локальній мережі[] для підключення до них.\nПідтримується локальна мережа(LAN) і широкосмугова мережа(WAN).\n\n[LIGHT_GRAY] Примітка. Тут немає автоматичного глобального списку серверів; якщо ви хочете підключитися до когось через IP, вам доведеться попросити створювача серверу дати свій ip. -text.hostserver = Запустити сервер -text.hostserver.mobile = Запустити\nсерверу -text.host = Сервер -text.hosting = [accent]Відкриття серверу... -text.hosts.refresh = Оновити -text.hosts.discovering = Пошук локальних ігор -text.server.refreshing = Оновлення серверу -text.hosts.none = [lightgray]Локальних ігр не знайдено -text.host.invalid = [scarlet]Не вдалося підключитися до хосту. -text.trace = Стежити за гравцем -text.trace.playername = Ім'я гравця: [accent]{0} -text.trace.ip = IP: [accent]{0} -text.trace.id = Унікальний ідентифікатор: [accent]{0} -text.trace.android = Клієнт Android: [accent]{0} -text.trace.modclient = Користувацький клієнт: [accent]{0} -text.trace.totalblocksbroken = Всього зруйновано блоків: [accent]{0} -text.trace.structureblocksbroken = Структурних блоків зруйновано: [accent]{0} -text.trace.lastblockbroken = Останній зруйнований блок: [accent]{0} -text.trace.totalblocksplaced = Всього встановлено блоків: [accent]{0} -text.trace.lastblockplaced = Останній встановлений блок: [accent]{0} -text.invalidid = Невірний ідентифікатор клієнта! Надішліть звіт про помилку. -text.server.bans = Блокування -text.server.bans.none = Заблокованих гравців нема! -text.server.admins = Адміністратори -text.server.admins.none = Адміністраторів нема -text.server.add = Додати сервер -text.server.delete = Ви впевнені, що хочете видалити цей сервер? -text.server.hostname = Хост: {0} -text.server.edit = Редагувати сервер -text.server.outdated = [crimson]Застарілий сервер![] -text.server.outdated.client = [crimson]Застарілий клієнт![] -text.server.version = [lightgray]Версія: {0} -text.server.custombuild = [yellow]Користувацький збірка -text.confirmban = Ви впевнені, що хочете заблокувати цього гравця? -text.confirmkick = Ви впевнені, що хочете викинути(кікнути) цього гравця? -text.confirmunban = Ви впевнені, що хочете розблокувати цього гравця? -text.confirmadmin = Ви впевнені, що хочете зробити цього гравця адміністратором? -text.confirmunadmin = Ви впевнені, що хочете видалити статус адміністратора з цього гравця? -text.joingame.title = Приєднатися до гри -text.joingame.ip = IP: -text.disconnect = Відключено. -text.disconnect.data = Не вдалося завантажити світові дані! -text.connecting = [accent]Підключення... -text.connecting.data = [accent]Завантаження даних світу... -text.server.port = Порт: -text.server.addressinuse = Ця адреса вже використовується! -text.server.invalidport = Недійсний номер порту! -text.server.error = [crimson]Помилка запуску сервера: [accent]{0} -text.save.old = Це збереження для старої версії гри, і його більше не можна використовувати.\n\n [LIGHT_GRAY]Зворотна сумісність буде реалізовано у повній версії 4.0. -text.save.new = Нове збереження -text.save.overwrite = Ви впевнені, що хочете перезаписати цей слот для збереження? -text.overwrite = Перезаписати -text.save.none = Збережень не знайдено! -text.saveload = [accent]Збереження... -text.savefail = Не вдалося зберегти гру! -text.save.delete.confirm = Ви впевнені, що хочете видалити це збереження? -text.save.delete = Видалити -text.save.export = Экспортувати збереження -text.save.import.invalid = [accent]Це збереження недійсне! -text.save.import.fail = [crimson]Не вдалося імпортувати збереження: [accent]{0} -text.save.export.fail = [crimson]Не вдалося экспортувати збереження: [accent]{0} -text.save.import = Імпортувати збереження -text.save.newslot = Назва збереження: -text.save.rename = Перейменувати -text.save.rename.text = Нова назва: -text.selectslot = Виберіть збереження. -text.slot = [accent]Слот {0} -text.save.corrupted = [accent]Збережений файл пошкоджено або э недійсним! \nЯкщо ви щойно оновили свою гру, це, мабуть, є зміною формату збереження та [scarlet] не[] є помилкою. -text.sector.corrupted = [accent]Файл збереження для цього сектора знайдено, але завантаження не вдалося. \n Буде створено новий файл. -text.empty = <порожній> -text.on = Включено -text.off = Вимкнено -text.save.autosave = Автозбереження: {0} -text.save.map = Мапа: {0} -text.save.wave = Хвиля {0} -text.save.difficulty = Складність: {0} -text.save.date = Останнє збереження -text.save.playtime = Час гри: {0} -text.confirm = Підтвердження -text.delete = Видалити -text.ok = ОК -text.open = Відкрити -text.cancel = Скасувати -text.openlink = Відкрити посилання -text.copylink = Скопіювати посилання -text.back = Назад -text.quit.confirm = Ви впевнені що хочете вийти? -text.changelog.title = Журнал змін -text.changelog.loading = Отримання журналу змін... -text.changelog.error.android = [accent]Зверніть увагу, що іноді журнал змін не працює на ОС Android 4.4 або на нижчій версії!\nЦе пов'язано з внутрішньою помилкою Android. -text.changelog.error.ios = [accent]В настоящее время журнал изменений не поддерживается iOS. -text.changelog.error = [scarlet]Помилка отримання журналу змін!\nПеревірте підключення до Інтернету. -text.changelog.current = [yellow][[Поточна версія] -text.changelog.latest = [accent][[Остання версія] -text.loading = [accent]Завантаження... -text.saving = [accent]Збереження... -text.wave = [accent]Хвиля {0} -text.wave.waiting = Хвиля через {0} -text.waiting = Очікування... -text.waiting.players = Очікування гравців -text.wave.enemies = [LIGHT_GRAY]{0} ворог. залишилося -text.wave.enemy = [LIGHT_GRAY]{0} ворог залишився -text.loadimage = Завантажити зображення -text.saveimage = Зберегти зображення -text.unknown = Невідомо -text.custom = Користувальницька -text.builtin = Bбудована -text.map.delete.confirm = Ви впевнені, що хочете видалити цю карту? Цю дію не можна скасувати! -text.map.random = [accent]Випадкова мапа -text.map.nospawn = Ця мапа не має жодного ядра для спавну гравця! Додайте[ROYAL] сине[] ядро в цю мапу редакторі. -text.map.nospawn.pvp = У цій карти немає ворожих ядер, в яких гравець може з'явитися! Додайте[SCARLET] червоні[] ядра до цієї карті в редакторі. -text.map.invalid = Помилка завантаження карти: пошкоджений або невірний файл карти. -text.editor.brush = Пензлик -text.editor.slope = -text.editor.openin = Відкрити в редакторі -text.editor.oregen = Генерація руд -text.editor.oregen.info = Генерація руд: -text.editor.mapinfo = Інформація про мапу -text.editor.author = Автор: -text.editor.description = Опис: -text.editor.name = Назва: -text.editor.teams = Команди -text.editor.elevation = Висота -text.editor.errorimageload = Помилка завантаження зображення:[accent] {0} -text.editor.errorimagesave = Помилка збереження зображення:\n[accent]{0} -text.editor.generate = Створити -text.editor.resize = Змінити \nрозмір -text.editor.loadmap = Завантажити мапу -text.editor.savemap = Зберегти карту -text.editor.saved = Збережено! -text.editor.save.noname = Ваша карта не має назви! Встановіть його в меню «Інформація про карту». -text.editor.save.overwrite = Ваша карта перезаписує вбудовану карту! Виберіть інше ім'я в меню «Інформація про карту». -text.editor.import.exists = [scarlet]Неможливо імпортувати: [] вбудована карта з назвою "{0}" вже існує! -text.editor.import = Імпорт... -text.editor.importmap = Імпортувати карту -text.editor.importmap.description = Імпортувати вже існуючу карту -text.editor.importfile = Імпортувати файл -text.editor.importfile.description = Імпортувати зовнішній файл карти -text.editor.importimage = Імпорт зовнішнього файла зображення карти -text.editor.importimage.description = Імпорт зображення місцевості -text.editor.export = Експорт... -text.editor.exportfile = Експорт файлу -text.editor.exportfile.description = Експортувати файл карти -text.editor.exportimage = Експорт зображення місцевості -text.editor.exportimage.description = Експорт файла з зображенням карти -text.editor.loadimage = Завантажити\nзображення -text.editor.saveimage = Зберегти\nзображення -text.editor.unsaved = [scarlet]У вас є незбережені зміни![]\nВи впевнені, що хочете вийти? -text.editor.resizemap = Змінити розмір карти -text.editor.mapname = Название карты: -text.editor.overwrite = [accent]Попередження!\nЦе перезаписує існуючу карту. -text.editor.overwrite.confirm = [scarlet]Попередження![] Карта з такою назвою вже існує. Ви впевнені, що хочете переписати її? -text.editor.selectmap = Виберіть мапу для завантаження: -text.width = Ширина: -text.height = Висота: -text.menu = Меню -text.play = Грати -text.load = Завантажити -text.save = Зберегти -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Пінг: {0} мс -text.language.restart = Будь ласка, перезапустіть свою гру, щоб налаштування мови набули чинності.\nPlease restart your game for the language settings to take effect. -text.settings = Налаштування -text.tutorial = Навчання -text.editor = Редактор -text.mapeditor = Редактор мап -text.donate = Пожертву\nвання -text.connectfail = [crimson]Не вдалося підключитися до сервера: [accent]{0} -text.error.unreachable = Сервер не доступний. -text.error.invalidaddress = Некоректна адреса. -text.error.timedout = Час очікувування вийшов.\nПереконайтеся, що адреса коректна і що власник сервера налаштував переадресацію порту! -text.error.mismatch = Ошибка пакету:\nможливе невідповідність версії клієнта / сервера.\nПереконайтеся, що у Вас та у володара сервера встановлена остання версія Mindustry! -text.error.alreadyconnected = Ви вже підключилися. -text.error.any = Невідома мережева помилка -text.settings.language = Мова -text.settings.reset = Скинути за замовчуванням -text.settings.rebind = Зміна -text.settings.controls = Управління -text.settings.game = Гра -text.settings.sound = Звук -text.settings.graphics = Графіка -text.settings.cleardata = Очистити дані... -text.settings.clear.confirm = Ви впевнені, що хочете очистити ці дані?\nЦя дія не може бути скасовано! -text.settings.clearall.confirm = [scarlet]УВАГА![]\nЦе очистить всі дані, включаючи збереження, карти, розблокуване та призначенні клавіші.\nПісля того, як ви натиснете ОК, гра видалить усі дані та автоматично вийде. -text.settings.clearsectors = Очистити сектори -text.settings.clearunlocks = Очистити розблоковане -text.settings.clearall = Очистити все -text.paused = Пауза -text.yes = Так -text.no = Ні -text.info.title = Інформація -text.error.title = [crimson]Виникла помилка -text.error.crashtitle = Виникла помилка -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = Інформація про блок -text.blocks.powercapacity = Місткість енергії -text.blocks.powershot = Енергія/постріл -text.blocks.targetsair = Атакуе повітряних ворогів? -text.blocks.itemspeed = Швидкість переміщення ресурсів -text.blocks.shootrange = Діапазон дії -text.blocks.size = Розмір -text.blocks.liquidcapacity = Місткість рідини -text.blocks.maxitemssecond = Макс. кількість предметів/секунду -text.blocks.powerrange = Діапазон передачі енергії -text.blocks.poweruse = Енергії використовує -text.blocks.powerdamage = Енергія/урон -text.blocks.inputitemcapacity = Ємність вхідних елементів -text.blocks.outputitemcapacity = Ємність вихідних елементів -text.blocks.itemcapacity = Місткість предметів -text.blocks.basepowergeneration = Базова генерація енергії -text.blocks.powertransferspeed = Швидкість передачі енергії -text.blocks.craftspeed = Швидкість виробництва -text.blocks.inputliquid = Прийом рідини -text.blocks.inputliquidaux = Допоміжна рідина -text.blocks.inputitem = Вхідний предмет -text.blocks.inputitems = Вхідні предмети -text.blocks.outputitem = Вихідний предмет -text.blocks.drilltier = Видобуває -text.blocks.drillspeed = Базова швидкість свердління -text.blocks.liquidoutput = Вихідна рідина -text.blocks.liquidoutputspeed = Швидкість вихідної рідини -text.blocks.liquiduse = Використовуеться рідин -text.blocks.coolant = Охолоджуюча рідина -text.blocks.coolantuse = Охолодж. рідини використовуеться -text.blocks.inputliquidfuel = Рідке паливо -text.blocks.liquidfueluse = Рідкого палива використовуеться -text.blocks.boostitem = Прискорюючий предмет -text.blocks.boostliquid = Прискорююча рідина -text.blocks.health = Здоров'я -text.blocks.inaccuracy = Розкид -text.blocks.shots = Постріли -text.blocks.reload = Постріли/секунду -text.blocks.inputfuel = Паливо -text.blocks.fuelburntime = Час горіння топлива -text.blocks.inputcapacity = Макс. місткість вхідних предметів -text.blocks.outputcapacity = Макс. місткість вихідних предметів -text.unit.blocks = блоки -text.unit.powersecond = одиниць енергії/секунду -text.unit.liquidsecond = рідких одиниць/секунду -text.unit.itemssecond = предметів/секунду -text.unit.pixelssecond = пікселів/секунду -text.unit.liquidunits = рідинних одиниць -text.unit.powerunits = енергетичних одиниць -text.unit.degrees = град. -text.unit.seconds = сек. -text.unit.items = предм. -text.category.general = Загальні -text.category.power = Енергетичні -text.category.liquids = Рідини -text.category.items = Предмети -text.category.crafting = Створення -text.category.shooting = Стрільба -text.category.optional = Додаткові поліпшення +credits.text = Створив [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\nЄ питання по грі або проблеми с перекладом? Іди в офіційний сервер discord Mindustry в канал #український. +credits = Автори +contributors = Перекладачі та Помічники +discord = Приєднуйтесь до нашого Discord! +link.discord.description = Офіційний discord-сервер Mindustry +link.github.description = Код гри +link.dev-builds.description = Нестабільні версії +link.trello.description = Офіційна дошка trello(на англ.) для запланованих функцій +link.itch.io.description = Itch.io сторінка з веб-версією та завантаженням для ПК +link.google-play.description = Скачати з Google Play для Android +link.wiki.description = Офіційна Mindustry вікі (англ.) +linkfail = Не вдалося відкрити посилання!\nURL-адреса скопійовано у ваш буфер обміну. +screenshot = Скріншот збережено в {0} +gameover = Гру закінчено +gameover.pvp = [accent] {0}[] команда перемогла! +highscore = [YELLOW]Новий рекорд! +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: +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]Перемістіть виділення[] утримуючи та перетягнувши будь-який блок у виділенні.\n- [accent]Розташуйте блоки у лінію[], торкнувшись і утримуючи порожнє місце, а потім перетягуючи в потрібному напрямку.\n- [accent]Скасуйте розміщення блоків[] натиснувши X внизу праворуч. +deconstruction.title = Інструкція з деконструкції блоків +deconstruction = Ви тільки що перешли в [accent] режим деконструкції блоків[].\n\nЩоб почати руйнувати, просто торкніться блоку поруч із вашим кораблем.\nПісля вибору деяких блоків натисніть прапорець, щоб підтвердити, і ваш корабель почне їх деконструювати.\n\n- [accent]Вилучіть блоки[] з вашого вибору, торкнувшись їх.\n- [accent]Вилучіть блоки в зоні[] , торкнувшись і утримуючи порожнє місце, потім перетягніть у потрібному напрямку.\n- [accent]Скасуйте деконструкцію або виділення[] натиснувши X внизу праворуч. +showagain = Не показувати знову до наступного сеансу +coreattack = < Ядро під атакою! > +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 = Користувальницька гра +newgame = New Game +none = <нічого> +close = Закрити +quit = Вийти +maps = Мапи +continue = Продовжити +maps.none = [LIGHT_GRAY]Карт не знайдено! +about.button = Про гру +name = Нік: +noname = Спочатку придумайте[accent] собі нікнейм[]. +filename = Ім'я файлу: +unlocked = Новий блок розблоковано! +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.clientOutdated = Застарілий клієнт! Оновіть свою гру! +server.kicked.serverOutdated = Застарілий сервер! Попросіть адміністратора серверу оновити сервер/гру! +server.kicked.banned = Ви були заблоковані на цьому сервері. +server.kicked.recentKick = Нещодавно Вас вигнали(кікнули). \nПочекайте трохи перед наступним підключенням. +server.kicked.nameInUse = На цьому сервері є хтось \nз таким ніком. +server.kicked.nameEmpty = Ваш нікнейм має містити принаймні один символ або цифру. +server.kicked.idInUse = Ви вже на цьому сервері! Підключення двох облікових записів не допускається. +server.kicked.customClient = Цей сервер не підтримує користувальницькі збірки. Завантажте офіційну версію. +server.kicked.gameover = Гра завершена! +host.info = Кнопка [accent]Сервер[] розміщує сервер на порті [scarlet]6567[]. \nКористувачі, які знаходяться у тій же [LIGHT_GRAY] WiFi або локальній мережі[] повинні бачити ваш сервер у своєму списку серверів.\n\nЯкщо ви хочете, щоб люди могли приєднуватися з будь-якої точки через IP, то [accent] переадресація порту [] обов'язкова.\n\n[LIGHT_GRAY] Примітка. Якщо у вас виникли проблеми з підключенням до вашої локальної гри, переконайтеся, що ви дозволили Mindustry доступ до вашої локальної мережі в налаштуваннях брандмауера. +join.info = Тут ви можете ввести [accent]IP серверу[] для підключення або знайти сервери у [accent]локальній мережі[] для підключення до них.\nПідтримується локальна мережа(LAN) і широкосмугова мережа(WAN).\n\n[LIGHT_GRAY] Примітка. Тут немає автоматичного глобального списку серверів; якщо ви хочете підключитися до когось через IP, вам доведеться попросити створювача серверу дати свій ip. +hostserver = Запустити сервер +hostserver.mobile = Запустити\nсерверу +host = Сервер +hosting = [accent]Відкриття серверу... +hosts.refresh = Оновити +hosts.discovering = Пошук локальних ігор +server.refreshing = Оновлення серверу +hosts.none = [lightgray]Локальних ігр не знайдено +host.invalid = [scarlet]Не вдалося підключитися до хосту. +trace = Стежити за гравцем +trace.playername = Ім'я гравця: [accent]{0} +trace.ip = IP: [accent]{0} +trace.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 = Невірний ідентифікатор клієнта! Надішліть звіт про помилку. +server.bans = Блокування +server.bans.none = Заблокованих гравців нема! +server.admins = Адміністратори +server.admins.none = Адміністраторів нема +server.add = Додати сервер +server.delete = Ви впевнені, що хочете видалити цей сервер? +server.hostname = Хост: {0} +server.edit = Редагувати сервер +server.outdated = [crimson]Застарілий сервер![] +server.outdated.client = [crimson]Застарілий клієнт![] +server.version = [lightgray]Версія: {0} +server.custombuild = [yellow]Користувацький збірка +confirmban = Ви впевнені, що хочете заблокувати цього гравця? +confirmkick = Ви впевнені, що хочете викинути(кікнути) цього гравця? +confirmunban = Ви впевнені, що хочете розблокувати цього гравця? +confirmadmin = Ви впевнені, що хочете зробити цього гравця адміністратором? +confirmunadmin = Ви впевнені, що хочете видалити статус адміністратора з цього гравця? +joingame.title = Приєднатися до гри +joingame.ip = IP: +disconnect = Відключено. +disconnect.data = Не вдалося завантажити світові дані! +connecting = [accent]Підключення... +connecting.data = [accent]Завантаження даних світу... +server.port = Порт: +server.addressinuse = Ця адреса вже використовується! +server.invalidport = Недійсний номер порту! +server.error = [crimson]Помилка запуску сервера: [accent]{0} +save.old = Це збереження для старої версії гри, і його більше не можна використовувати.\n\n [LIGHT_GRAY]Зворотна сумісність буде реалізовано у повній версії 4.0. +save.new = Нове збереження +save.overwrite = Ви впевнені, що хочете перезаписати цей слот для збереження? +overwrite = Перезаписати +save.none = Збережень не знайдено! +saveload = [accent]Збереження... +savefail = Не вдалося зберегти гру! +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 = Імпортувати збереження +save.newslot = Назва збереження: +save.rename = Перейменувати +save.rename.text = Нова назва: +selectslot = Виберіть збереження. +slot = [accent]Слот {0} +save.corrupted = [accent]Збережений файл пошкоджено або э недійсним! \nЯкщо ви щойно оновили свою гру, це, мабуть, є зміною формату збереження та [scarlet] не[] є помилкою. +empty = <порожній> +on = Включено +off = Вимкнено +save.autosave = Автозбереження: {0} +save.map = Мапа: {0} +save.wave = Хвиля {0} +save.difficulty = Складність: {0} +save.date = Останнє збереження +save.playtime = Час гри: {0} +warning = Warning. +confirm = Підтвердження +delete = Видалити +ok = ОК +open = Відкрити +cancel = Скасувати +openlink = Відкрити посилання +copylink = Скопіювати посилання +back = Назад +quit.confirm = Ви впевнені що хочете вийти? +changelog.title = Журнал змін +changelog.loading = Отримання журналу змін... +changelog.error.android = [accent]Зверніть увагу, що іноді журнал змін не працює на ОС Android 4.4 або на нижчій версії!\nЦе пов'язано з внутрішньою помилкою Android. +changelog.error.ios = [accent]Журнал змін наразі не підтримується iOS. +changelog.error = [scarlet]Помилка отримання журналу змін!\nПеревірте підключення до Інтернету. +changelog.current = [yellow][[Поточна версія] +changelog.latest = [accent][[Остання версія] +loading = [accent]Завантаження... +saving = [accent]Збереження... +wave = [accent]Хвиля {0} +wave.waiting = Хвиля через {0} +waiting = Очікування... +waiting.players = Очікування гравців +wave.enemies = [LIGHT_GRAY]{0} ворог. залишилося +wave.enemy = [LIGHT_GRAY]{0} ворог залишився +loadimage = Завантажити зображення +saveimage = Зберегти зображення +unknown = Невідомо +custom = Користувальницька +builtin = Bбудована +map.delete.confirm = Ви впевнені, що хочете видалити цю карту? Цю дію не можна скасувати! +map.random = [accent]Випадкова мапа +map.nospawn = Ця мапа не має жодного ядра для спавну гравця! Додайте[ROYAL] сине[] ядро в цю мапу редакторі. +map.nospawn.pvp = У цій карти немає ворожих ядер, в яких гравець може з'явитися! Додайте[SCARLET] червоні[] ядра до цієї карті в редакторі. +map.invalid = Помилка завантаження карти: пошкоджений або невірний файл карти. +editor.brush = Пензлик +editor.slope = \\ +editor.openin = Відкрити в редакторі +editor.oregen = Генерація руд +editor.oregen.info = Генерація руд: +editor.mapinfo = Інформація про мапу +editor.author = Автор: +editor.description = Опис: +editor.name = Назва: +editor.teams = Команди +editor.elevation = Висота +editor.errorimageload = Помилка завантаження зображення:[accent] {0} +editor.errorimagesave = Помилка збереження зображення:\n[accent]{0} +editor.generate = Створити +editor.resize = Змінити \nрозмір +editor.loadmap = Завантажити мапу +editor.savemap = Зберегти карту +editor.saved = Збережено! +editor.save.noname = Ваша карта не має назви! Встановіть його в меню «Інформація про карту». +editor.save.overwrite = Ваша карта перезаписує вбудовану карту! Виберіть інше ім'я в меню «Інформація про карту». +editor.import.exists = [scarlet]Неможливо імпортувати: [] вбудована карта з назвою "{0}" вже існує! +editor.import = Імпорт... +editor.importmap = Імпортувати карту +editor.importmap.description = Імпортувати вже існуючу карту +editor.importfile = Імпортувати файл +editor.importfile.description = Імпортувати зовнішній файл карти +editor.importimage = Імпорт зовнішнього файла зображення карти +editor.importimage.description = Імпорт зображення місцевості +editor.export = Експорт... +editor.exportfile = Експорт файлу +editor.exportfile.description = Експортувати файл карти +editor.exportimage = Експорт зображення місцевості +editor.exportimage.description = Експорт файла з зображенням карти +editor.loadimage = Завантажити\nзображення +editor.saveimage = Зберегти\nзображення +editor.unsaved = [scarlet]У вас є незбережені зміни![]\nВи впевнені, що хочете вийти? +editor.resizemap = Змінити розмір карти +editor.mapname = Название карты: +editor.overwrite = [accent]Попередження!\nЦе перезаписує існуючу карту. +editor.overwrite.confirm = [scarlet]Попередження![] Карта з такою назвою вже існує. Ви впевнені, що хочете переписати її? +editor.selectmap = Виберіть мапу для завантаження: +width = Ширина: +height = Висота: +menu = Меню +play = Грати +load = Завантажити +save = Зберегти +fps = FPS: {0} +tps = TPS: {0} +ping = Пінг: {0} мс +language.restart = Будь ласка, перезапустіть свою гру, щоб налаштування мови набули чинності.\nPlease restart your game for the language settings to take effect. +settings = Налаштування +tutorial = Навчання +editor = Редактор +mapeditor = Редактор мап +donate = Пожертву\nвання +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson]Не вдалося підключитися до сервера: [accent]{0} +error.unreachable = Сервер не доступний. +error.invalidaddress = Некоректна адреса. +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 = Зміна +settings.controls = Управління +settings.game = Гра +settings.sound = Звук +settings.graphics = Графіка +settings.cleardata = Очистити дані... +settings.clear.confirm = Ви впевнені, що хочете очистити ці дані?\nЦя дія не може бути скасовано! +settings.clearall.confirm = [scarlet]УВАГА![]\nЦе очистить всі дані, включаючи збереження, карти, розблокуване та призначенні клавіші.\nПісля того, як ви натиснете ОК, гра видалить усі дані та автоматично вийде. +settings.clearunlocks = Очистити розблоковане +settings.clearall = Очистити все +paused = Пауза +yes = Так +no = Ні +info.title = Інформація +error.title = [crimson]Виникла помилка +error.crashtitle = Виникла помилка +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = Інформація про блок +blocks.powercapacity = Місткість енергії +blocks.powershot = Енергія/постріл +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.liquid = Liquid +blocks.coolantuse = Охолодж. рідини використовуеться +blocks.inputliquidfuel = Рідке паливо +blocks.liquidfueluse = Рідкого палива використовуеться +blocks.boostitem = Прискорюючий предмет +blocks.boostliquid = Прискорююча рідина +blocks.health = Здоров'я +blocks.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = Розкид +blocks.shots = Постріли +blocks.reload = Постріли/секунду +blocks.inputfuel = Паливо +blocks.fuelburntime = Час горіння топлива +blocks.inputcapacity = Макс. місткість вхідних предметів +blocks.outputcapacity = Макс. місткість вихідних предметів +unit.blocks = блоки +unit.powersecond = одиниць енергії/секунду +unit.liquidsecond = рідких одиниць/секунду +unit.itemssecond = предметів/секунду +unit.pixelssecond = пікселів/секунду +unit.liquidunits = рідинних одиниць +unit.powerunits = енергетичних одиниць +unit.degrees = град. +unit.seconds = сек. +unit.items = предм. +category.general = Загальні +category.power = Енергетичні +category.liquids = Рідини +category.items = Предмети +category.crafting = Створення +category.shooting = Стрільба +category.optional = Додаткові поліпшення +setting.indicators.name = Показувати у сторону союзників setting.autotarget.name = Авто-ціль setting.fpscap.name = Макс. FPS setting.fpscap.none = Необмежений @@ -371,18 +379,22 @@ setting.mutemusic.name = Заглушити музику setting.sfxvol.name = Гучність звукових ефектів setting.mutesound.name = Заглушити звук setting.crashreport.name = Надіслати анонімні звіти про аварійне завершення гри -text.keybind.title = Налаштування управління +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 = Рух по осі x keybind.select.name = ВибратиПостріл +keybind.pick.name = Pick Block keybind.break.name = Руйнування keybind.deselect.name = Скасувати keybind.shoot.name = Постріл @@ -401,41 +413,40 @@ keybind.chat_history_next.name = Наступна історія чату keybind.chat_scroll.name = Прокрутка чату keybind.drop_unit.name = Скинути бой. од. keybind.zoom_minimap.name = Збільшити мінікарту -mode.text.help.title = Опис режимів -mode.waves.name = Хвилі -mode.waves.description = Звичайний режим. В режимі "Хвилі" треба самим добувати ресурси та хвилі йдуть беззупинно. +mode.help.title = Опис режимів +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 = Вільне\nбудівництво mode.freebuild.description = В режимі "Пісочниця" треба самим добувати ресурси та хвилі йдуть за вашим бажанням. mode.pvp.name = PVP mode.pvp.description = боріться проти інших гравців. +mode.attack.name = Атака +mode.attack.descrption = Немає хвиль, мета - знищити базу противника. 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 = Торій item.thorium.description = Густий, радіоактивний метал, що використовується як структурна підтримка та ядерне паливо. -item.silicon.name = Кремень +item.silicon.name = Кремній item.silicon.description = Надзвичайно корисний напівпровідник з застосуванням в сонячних батареях та складній електроніці. item.plastanium.name = Пластиній item.plastanium.description = Легкий, пластичний матеріал, що використовується в сучасних літальних апаратах та у боєприпасах для фрагментації. item.phase-fabric.name = Фазова тканина -item.phase-fabric.description = Невагоме речовина, що використовується в сучасній електроніці і технології самовідновлення. -item.surge-alloy.name = Високоміцний сплав +item.phase-fabric.description = Невагоме речовина, що використовується в сучасній електроніці і технології самовідновлення. Не для вишивання. +item.surge-alloy.name = Кінетичний сплав item.surge-alloy.description = Передовий сплав з унікальними електричними властивостями. item.biomatter.name = Біоматерія item.biomatter.description = Скупчення органічної муси; використовується для перетворення в нафту або як паливо. @@ -445,12 +456,16 @@ 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.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 = Дельта @@ -460,10 +475,10 @@ mech.delta-mech.description = Швидкий, легкоброньований mech.tau-mech.name = Тау mech.tau-mech.weapon = Відновлювальний лазер mech.tau-mech.ability = Відновлювальний спалах -mech.tau-mech.description = Мех підтримки. Зцілює союзницькі блоки, стріляючи в них. Може зцілити союзників у радіусі зі своєю здатністю для ремонту. +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 = Ретранслятор @@ -474,30 +489,34 @@ 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 = Вогняний кулемет -text.item.explosiveness = [LIGHT_GRAY]Вибухонебезпечність: {0} -text.item.flammability = [LIGHT_GRAY]Вогненебезпечність: {0} -text.item.radioactivity = [LIGHT_GRAY]Радіоактивність: {0} -text.item.fluxiness = [LIGHT_GRAY]Осадковість: {0} -text.unit.health = [LIGHT_GRAY]Здоров'я: {0} -text.unit.speed = [LIGHT_GRAY]Швидкість: {0} -text.mech.weapon = [LIGHT_GRAY]Зброя: {0} -text.mech.armor = [LIGHT_GRAY]Броня: {0} -text.mech.itemcapacity = [LIGHT_GRAY] Ємність елементів: {0} -text.mech.minespeed = [LIGHT_GRAY]Швидкість видобутку: {0} -text.mech.minepower = [LIGHT_GRAY]Потужність видобутку: {0} -text.mech.ability = [LIGHT_GRAY]Здібність: {0} -text.liquid.heatcapacity = [LIGHT_GRAY]Теплоємність: {0} -text.liquid.viscosity = [LIGHT_GRAY]В'язкість: {0} -text.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]Health: {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.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.space.name = Пустота -block.metalfloor.name = Металічна підлога +block.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus +block.metalfloor.name = Металева плитка block.deepwater.name = Глибоководдя block.water.name = Вода block.lava.name = Лава @@ -515,8 +534,8 @@ block.blackrock.name = Чорний кругляк block.icerock.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 = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = Фазова стіна block.phase-wall-large.name = Велика фазова стіна block.thorium-wall.name = Торієва стіна @@ -549,17 +568,19 @@ 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 = Реконструктор "Тризуб" @@ -568,11 +589,11 @@ block.omega-mech-pad.name = Реконструктор "Омега" block.tau-mech-pad.name = Реконструктор "Тау" block.conduit.name = Трубопровід block.mechanical-pump.name = Механічний насос -block.itemsource.name = Джерело предметів -block.itemvoid.name = Предметний вакуум -block.liquidsource.name = Рідке джерело -block.powervoid.name = Енергетичний вакуум -block.powerinfinite.name = Нескінченна енергія +block.item-source.name = Джерело предметів +block.item-void.name = Предметний вакуум +block.liquid-source.name = Рідке джерело +block.power-void.name = Енергетичний вакуум +block.power-source.name = Нескінченна енергія block.unloader.name = Розвантажувач block.vault.name = Сховище block.wave.name = Хвиля @@ -591,10 +612,10 @@ block.oil-extractor.name = Екстрактор нафти block.spirit-factory.name = Завод дронов "Призрак" block.phantom-factory.name = Завод дронов "Фантом" block.wraith-factory.name = Завод винищувачів "Примара" -block.ghoul-factory.name = Завод бомбардувальників "Ґуль" -block.dagger-factory.name = Завод мехов "Разведчик" -block.titan-factory.name = Завод мехов "Титан" -block.fortress-factory.name = Завод мехов "Крепость" +block.ghoul-factory.name = Завод бомбардувальників-винищувачів "Ґуль" +block.dagger-factory.name = Завод мехів "Кинджал" +block.titan-factory.name = Завод мехів "Титан" +block.fortress-factory.name = Завод мехів "Крепость" block.revenant-factory.name = Завод бомбардировщиков "Потусторонний убийца" block.repair-point.name = Ремонтний пункт block.pulse-conduit.name = Імпульсний водовід @@ -624,6 +645,7 @@ block.rtg-generator.name = Радіоізотопний термоелектри block.spectre.name = Мара block.meltdown.name = Розтоплення block.container.name = Склад +block.launch-pad.name = Launch Pad team.blue.name = Синя team.red.name = Червона team.orange.name = Помаренчева @@ -635,8 +657,9 @@ 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 = Бомбардувальний "Ґуль" @@ -646,7 +669,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Зробіть лінію конвейерів від бурів до ядра. @@ -662,13 +689,12 @@ tutorial.silicondrill = Кремній потребує[accent] вугілляl[ tutorial.generator = Ця технологія потребує енергії.\nЗробіть[accent] генератор внутрішнього згорання[] для цього. tutorial.generatordrill = Генератор потребує вугілля.\nПобудуйте бур на вугільній жилі. tutorial.node = Енергії потребує транспортування\nСоздайте[accent] силовий вузол[] поруч з вашим генератором згорання, щоб передавати його енергію. -tutorial.nodelink = Енергія може бути передана через контактні енергетичні блоки та генератори, або з'єднані силові вузли.\n\nЗ'єднайте живлення, торкнувшись вузла та вибравши генератор і кремнієвий завод. +tutorial.nodelink = Енергія може бути передана через контактні енергетичні блоки та генератори, або з'єднані силові вузли.\n\nЗ'єднайте їх, торкнувшись вузла та вибравши генератор і кремнієвий завод. tutorial.silicon = Кремній почався створюватися. Отримайте трохи.\n\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.core.description = Найголовніше будівля в грі. block.copper-wall.description = Дешевий оборонний блок.\nКорисен для захисту ядра і турелей під час перших хвиль. block.copper-wall-large.description = Велика стіна найменшим запасом міцності.\nКорисна на початку гри. block.dense-alloy-wall.description = Стіна з показником міцності "нижче середнього". @@ -703,11 +729,11 @@ block.phase-conveyor.description = Поки гра знаходиться в 2D, block.junction.description = Назва говорить сама за себе. За допомогою нього можна зробити дві конвеєрні стрічки, які проходять через один одного і не змішуються. block.mass-driver.description = При наявності енергії передають ресурси на відстань 100 блоків, стріляючи в один-одного. block.smelter.description = Виробляє щільний сплав з міді і свинцю. Можна підвести пісок для прискорення виробництва. -block.arc-smelter.description = Покращена версія плавильного заводу. Вимагає енергію. Виробляє щільний сплав зміді і свинця.\nМожно підвести пісок для прискорення виробництва. +block.arc-smelter.description = Покращена версія плавильного заводу. Вимагає енергію. Виробляє щільний сплав з міді і свинця.\nМожно підвести пісок для прискорення виробництва. block.silicon-smelter.description = За допомогою піску, вугілля і енергії виробляє кремній. block.plastanium-compressor.description = Створює пластинійи з титану і нафти. Вимагає енергії. Для прискорення виробництва можна додати в компресор пісок. block.phase-weaver.description = Виробляє фазову тканину торію і піску. Вимагає багато енергії. -block.alloy-smelter.description = Створює високоміцний сплав з титану, кременя, міді і свинця. Вимагає енергію. +block.alloy-smelter.description = Створює кінетичний сплав з титану, кременя, міді і свинця. Вимагає енергію. block.pulverizer.description = Подрібнює камінь в пісок. Вимагає енергії. block.pyratite-mixer.description = Створює піротит з вугілля, свинцю і піску. Вимагає енергії. block.blast-mixer.description = Створює вибухонебезпечне з'єднання з нафти і піротіта. Для прискорення виробництва можна додати в мішалку пісок. @@ -718,7 +744,7 @@ block.incinerator.description = Якщо є непотрібні ресурси, block.biomattercompressor.description = Виробляє нафту з біоматеріі, біосміття і енергії. block.separator.description = Шукає в камені різні ресурси. Чим цінніше ресурс, тим з меншою ймовірністю він "знайдеться". block.centrifuge.description = Шукає в камені різні ресурси. Чим цінніше ресурс, тим з меншою ймовірністю він "знайдеться".\nТребует енергію. -block.power-node.description = Максимум допустимо 4 підключення.\nЩоб з'єднати з якимось блоком потрібно наступне\:\n1. Щоб він знаходився в радіусі дії \n2. Натиснити на потрібний силовий вузол, а потім на інший силовий вузол або блок. +block.power-node.description = Максимум допустимо 4 підключення.\nЩоб з'єднати з якимось блоком потрібно наступне:\n1. Щоб він знаходився в радіусі дії \n2. Натиснити на потрібний силовий вузол, а потім на інший силовий вузол або блок. block.power-node-large.description = Силовий вузол другого покоління. Збільшено радіус дії і кількість максимально допустимих підключень. block.battery.description = Хранит энергию всякий раз, когда есть изобилие, и обеспечивает мощность всякий раз, когда есть недостаток, если есть мощность, але БАТАРЕЙКИ DURACELL ЗБЕРІГАЮТЬ БІЛЬШЕ! (прихована реклама) block.battery-large.description = Зберігає значно більше енергії, ніж звичайна батарейка... @@ -770,12 +796,12 @@ block.router.description = Приймає елементи з одного на block.distributor.description = Розширений маршрутизатор, який рівномірно розбиває елементи на 7 різних напрямків. block.bridge-conveyor.description = Покращений блок транспортування предметів. Дозволяє транспортувати предмети понад 3 блоки над будь-якої місцевостю або будівлеє. block.alpha-mech-pad.description = Коли ви отримаєте достатньо енергії, перебудовує ваш корабель у [accent] Альфа[] мех. -block.itemsource.description = Безліченно виводить предмети. Лише пісочниця. -block.liquidsource.description = Безліченно виводить рідини. Лише пісочниця. -block.itemvoid.description = Знищує будь-які предмети, які входять, без використання енергії. Працює тільки в пісочниці. -block.powerinfinite.description = Нескінченність не межа. Безмежно виводить енергію. Лише пісочниця. -block.powervoid.description = Енергія просто йде в порожнечу. Лише пісочниця. -liquid.water.description = Зазвичай використовується для охолодження машин та переробки відходів. -liquid.lava.description = Можна перетворити в[LIGHT_GRAY] камінь[], який використовується для генерації енергії або використовуати як боєприпаси для певних турелей. -liquid.oil.description = Можна спалити, взірвати або використовувати як теплоносій. -liquid.cryofluid.description = Найефективніша рідина для охолодження. Рідина з температурою нижче ніж -273 градусів за Цельсієм. Може бути використана для прискорення стрільби турелей або для охолодження чогось. +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 cc6dbb00bb..9249d5ad23 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -1,351 +1,359 @@ -text.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!) -text.credits = 致谢 -text.discord = 加入 Mindustry 的 Discord! -text.link.discord.description = 官方 Mindustry discord 聊天室 -text.link.github.description = 游戏源码 -text.link.dev-builds.description = 不稳定开发版 -text.link.trello.description = Trello board 上的官方计划表 -text.link.itch.io.description = PC版下载和网页版(itch.io) -text.link.google-play.description = 从谷歌商店获取安卓版 -text.link.wiki.description = 官方 Mindustry 维基 -text.linkfail = 打开链接失败!\nURL 已经复制到剪贴板。 -text.gameover = 你的核心被摧毁了! -text.gameover.pvp = accent] {0}[] 队获胜! -text.sector.gameover = 这个区域失守了,要重新部署吗? -text.sector.retry = 重试 -text.highscore = [accent]新纪录! -text.wave.lasted = 你坚持到了第 [accent]{0}[] 波。 -text.level.highscore = 最高分: [accent]{0} -text.level.delete.title = 确认删除 -text.map.delete = 确定要删除 "[accent]{0}[]" 地图吗? -text.level.select = 选择关卡 -text.level.mode = 游戏模式: -text.construction.desktop = 桌面控制已更改.\n取消选择快活停止构建, [accent]使用空间[]. -text.construction.title = 方块建造指导 -text.construction = 你选择了 [accent]建造模式[].\n\n点击你附近的有效位置以放置\n选择了方块以后, 点击复选框就会开始建造。\n\n- [accent]移除方块-[] 点击想要删除的方块。\n- [accent]直线放置方块-[] 按住一个空点然后拖到目的地。\n- [accent]取消建造或选择-[] 按左下角的X。 -text.deconstruction.title = 方块删除指导 -text.deconstruction = 你选择了 [accent]删除模式[]。\n\n点击你附近的有效位置以删除\n选择了方块以后,点击复选框就会开始删除。\n\n- [accent]移除方块-[] 点击想要删除的方块。\n- [accent]移除选中部分-[] 按住并拖动以选中一个区域。\n- [accent]取消删除或选择-[] 按左下角的X. -text.showagain = 不再显示 -text.coreattack = < 核心正在受到攻击! > -text.unlocks = 已解锁 -text.savegame = 保存游戏 -text.loadgame = 载入游戏 -text.joingame = 加入游戏 -text.addplayers = 增加/删除玩家 -text.customgame = 自定义游戏 -text.sectors = 区域 -text.sector = 区域: [LIGHT_GRAY]{0} -text.sector.time = 时间: [LIGHT_GRAY]{0} -text.sector.deploy = 部署 -text.sector.abandon = 放弃 -text.sector.abandon.confirm = 你确定要放弃这个区域的所有进展吗?\n此操作不可撤销! -text.sector.resume = 继续 -text.sector.locked = [scarlet][[Incomplete] -text.sector.unexplored = [accent][[Unexplored] -text.missions = 任务:[LIGHT_GRAY] {0} -text.mission = 任务[LIGHT_GRAY] {0} -text.mission.main = 主要任务:[LIGHT_GRAY] {0} -text.mission.info = 任务信息 -text.mission.complete = 任务完成! -text.mission.complete.body = 区域 {0},攻占了 {1} 个 -text.mission.wave = 存活了 [accent]{0}/{1}[] 波。\n下一波 {2} -text.mission.wave.enemies = 存活[accent] {0}/{1} []波\n{2} 敌人 -text.mission.wave.enemy = 存活[accent] {0}/{1} []波\n{2} 敌人 -text.mission.wave.menu = 存活[accent] {0} []波 -text.mission.battle = 摧毁敌方基地。 -text.mission.resource.menu = 获取{0}x{1} -text.mission.resource = 获取{0}︰\n[accent]{1}/{2}[] -text.mission.block = 建造{0} -text.mission.unit = 生产{0}机组 -text.mission.command = 发送{0}指令至机组 -text.mission.linknode = 连接能源节点 -text.mission.display = [accent]任务︰\n[LIGHT_GRAY]{0} -text.mission.mech = 转换至[accent]{0}[]机甲 -text.mission.create = 制造[accent] {0}[] -text.none = <无> -text.close = 关闭 -text.quit = 退出 -text.maps = 地图 -text.continue = 继续 -text.nextmission = 下一个任务 -text.maps.none = [LIGHT_GRAY]未发现地图! -text.about.button = 关于 -text.name = 名字: -text.filename = 文件名: -text.unlocked = 新方块已解锁! -text.unlocked.plural = 新方块已解锁! -text.players = {0} 玩家在线 -text.players.single = {0} 玩家在线 -text.server.closing = [accent]正在关闭服务器…… -text.server.kicked.kick = 你被踢出服务器了! -text.server.kicked.serverClose = 服务器已关闭。 -text.server.kicked.sectorComplete = 区域已完成。 -text.server.kicked.sectorComplete.text = 任务已完成。\n服务器将在下一个区域继续。 -text.server.kicked.clientOutdated = 客户端版本过旧!请升级! -text.server.kicked.serverOutdated = 服务器版本过旧!请联系房主升级! -text.server.kicked.banned = 你被这个服务器拉黑了。 -text.server.kicked.recentKick = 你刚刚被踢出服务器。\n请稍后重新连接! -text.server.kicked.nameInUse = 服务器中已经\n有人有相同的名字了。 -text.server.kicked.nameEmpty = 你的名字必须至少包含一个字母或数字。 -text.server.kicked.idInUse = 你已经在服务器中!不允许用两个账号。 -text.server.kicked.customClient = 这个服务器不支持修改版客户端,请下载官方版本。 -text.host.info = [accent]创建局域网游戏[]按钮会在[scarlet]6567[]端口运行一个服务器。[]\n任何在同一个[LIGHT_GRAY]网络或本地网络[]下的人都将在服务器列表中看到你的服务器。\n\n如果你想让别人在任何地方都能通过IP地址连接,你需要设定[accent]端口转发[]。\n\n[LIGHT_GRAY]请注意:如果某人无法连接到你的局域网游戏,请确保你在防火墙设置里允许了Mindustry连接本地网络。 -text.join.info = 你可以在这里输入[accent]服务器的IP地址[]以连接,或寻找[accent]本地网络[]中的服务器以连接。\n目前支持局域网或广域网多人游戏。\n\n[LIGHT_GRAY]请注意:没有全球服务器列表;如果你想通过IP地址连接某个服务器,你需要向房主询问IP地址。 -text.hostserver = 创建服务器 -text.hostserver.mobile = 创建\n服务器 -text.host = 创建 -text.hosting = [accent]正在打开服务器…… -text.hosts.refresh = 刷新 -text.hosts.discovering = 正在搜索局域网服务器 -text.server.refreshing = 正在刷新服务器 -text.hosts.none = [lightgray]未发现局域网游戏! -text.host.invalid = [scarlet]无法连接服务器。 -text.trace = 跟踪玩家 -text.trace.playername = 玩家名字: [accent]{0} -text.trace.ip = IP地址: [accent]{0} -text.trace.id = ID︰[accent]{0} -text.trace.android = 安卓客户端: [accent]{0} -text.trace.modclient = 修改版客户端: [accent]{0} -text.trace.totalblocksbroken = 总共破坏了 [accent]{0} 个方块。 -text.trace.structureblocksbroken = 总共破坏了[accent]{0}个方块。 -text.trace.lastblockbroken = 最后破坏的方块: [accent]{0} -text.trace.totalblocksplaced = 总共放置了 [accent]{0} 个方块。 -text.trace.lastblockplaced = 最后放置的方块: [accent]{0} -text.invalidid = 无效的客户端ID!请提交错误报告。 -text.server.bans = 黑名单 -text.server.bans.none = 没有被拉黑的玩家! -text.server.admins = 管理员 -text.server.admins.none = 没有管理员! -text.server.add = 添加服务器 -text.server.delete = 确定要删除这个服务器吗? -text.server.hostname = 主机︰{0} -text.server.edit = 编辑服务器 -text.server.outdated = [crimson]服务器过旧![] -text.server.outdated.client = [crimson]客户端过旧![] -text.server.version = [lightgray]版本: {0} -text.server.custombuild = [yellow]修改版 -text.confirmban = 确认拉黑这个玩家吗? -text.confirmkick = 您确定要踢出这个玩家吗? -text.confirmunban = 确认要取消拉黑这个玩家吗? -text.confirmadmin = 确认要添加这个玩家为管理员吗? -text.confirmunadmin = 确认要取消这个玩家的管理员身份吗? -text.joingame.title = 加入游戏 -text.joingame.ip = IP: -text.disconnect = 已断开 -text.disconnect.data = 载入世界失败! -text.connecting = [accent]连接中…… -text.connecting.data = [accent]加载世界中…… -text.server.port = 端口︰ -text.server.addressinuse = 地址已经使用! -text.server.invalidport = 无效的端口! -text.server.error = [crimson]创建服务器错误:[accent]{0} -text.save.old = 这个存档属于旧版本游戏,无法继续使用了。\n\n[LIGHT_GRAY]存档向下兼容将在 4.0 版本中实现。 -text.save.new = 新存档 -text.save.overwrite = 确认要覆盖这个存档吗? -text.overwrite = 覆盖 -text.save.none = 没有存档! -text.saveload = [accent]保存中…… -text.savefail = 保存失败! -text.save.delete.confirm = 确认要删除这个存档吗? -text.save.delete = 删除 -text.save.export = 导出存档 -text.save.import.invalid = [accent]存档无效! -text.save.import.fail = [crimson]导入存档失败:[accent]{0} -text.save.export.fail = [crimson]导出存档失败:[accent]{0} -text.save.import = 导入存档 -text.save.newslot = 保存游戏: -text.save.rename = 重命名 -text.save.rename.text = 新名字: -text.selectslot = 选择一个存档。 -text.slot = [accent]存档 {0} -text.save.corrupted = [accent]存档损坏或无效!\n如果你刚刚升级了游戏,那么这可能是因为存档格式改变了而[scarlet]不是[] bug 。 -text.sector.corrupted = [accent]发现了一个此区域的保存文件,但是加载失败。\n已经创建了一个新的。 -text.empty = <空> -text.on = 开 -text.off = 关 -text.save.autosave = 自动保存:{0} -text.save.map = 地图:{0} -text.save.wave = 第 {0} 波 -text.save.difficulty = 难度: {0} -text.save.date = 最后保存日期:{0} -text.save.playtime = 游戏时间:{0} -text.confirm = 确认 -text.delete = 删除 -text.ok = 好的 -text.open = 打开 -text.cancel = 取消 -text.openlink = 打开链接 -text.copylink = 删除链接 -text.back = 返回 -text.quit.confirm = 确认要退出? -text.changelog.title = 更新日志 -text.changelog.loading = 正在获取更新日志... -text.changelog.error.android = [accent]请注意更新日志有时在安卓 4.4 以下不工作。\n这是因为安卓系统的一个 bug 。 -text.changelog.error.ios = [accent]iOS还不支持更新日志。 -text.changelog.error = [scarlet]获取更新日志失败!\n请检查你的网络。 -text.changelog.current = [yellow][[Current version] -text.changelog.latest = [accent][[Latest version] -text.loading = [accent]加载中…… -text.saving = [accent]保存中…… -text.wave = [accent]第 {0} 波 -text.wave.waiting = 下一波将在 {0} 秒后到来 -text.waiting = 等待中…… -text.waiting.players = 等待玩家中…… -text.wave.enemies = 剩下 [LIGHT_GRAY]{0} 敌人 -text.wave.enemy = 剩下 [LIGHT_GRAY]{0} 敌人 -text.loadimage = 加载图片 -text.saveimage = 保存图片 -text.unknown = 未知 -text.custom = 自定义 -text.builtin = 内建的 -text.map.delete.confirm = 确认要删除地图吗?这个操作无法撤销! -text.map.random = [accent]随机地图 -text.map.nospawn = 这个地图没有核心!请在编辑器中添加一个[ROYAL]蓝色[]的核心。 -text.map.nospawn.pvp = 这个地图没有敌人的核心!请在编辑器中添加一个[ROYAL]红色[]的核心。 -text.map.invalid = 地图载入错误:地图文件可能已经损坏。 -text.editor.brush = 笔刷 -text.editor.slope = \\ -text.editor.openin = 在编辑器中打开 -text.editor.oregen = 生成矿石 -text.editor.oregen.info = 生成矿石: -text.editor.mapinfo = 地图详情 -text.editor.author = 作者: -text.editor.description = 描述: -text.editor.name = 名字: -text.editor.teams = 团队 -text.editor.elevation = 高度 -text.editor.errorimageload = 载入文件出错:\n[accent]{0} -text.editor.errorimagesave = 保存文件出错:\n[accent]{0} -text.editor.generate = 生成 -text.editor.resize = 调整 -text.editor.loadmap = 载入地图 -text.editor.savemap = 保存地图 -text.editor.saved = 已保存! -text.editor.save.noname = 你的地图还没有名字!在“地图信息”菜单里设置一个名字。 -text.editor.save.overwrite = 你的地图覆盖了一个内建的地图!在“地图信息”菜单里重新设置一个。 -text.editor.import.exists = [scarlet]无法导入:[] 一个叫 '{0}' 的内建地图已经存在。 -text.editor.import = 导入…… -text.editor.importmap = 导入地图 -text.editor.importmap.description = 导入一个已经存在的地图 -text.editor.importfile = 导入文件 -text.editor.importfile.description = 导入一个外置的地图文件 -text.editor.importimage = 导入地形图像 -text.editor.importimage.description = 导入外置地图图像文件 -text.editor.export = 导出…… -text.editor.exportfile = 导出文件 -text.editor.exportfile.description = 导出一个地图文件 -text.editor.exportimage = 导出一个地形文件 -text.editor.exportimage.description = 导出一个地图图像文件 -text.editor.loadimage = 导入地形 -text.editor.saveimage = 导出地形 -text.editor.unsaved = [scarlet]你有未保存的更改![]\n确定要退出? -text.editor.resizemap = 调整地图 -text.editor.mapname = 地图名字: -text.editor.overwrite = [accent]警告!\n这将会覆盖一个已经存在的地图。 -text.editor.overwrite.confirm = [scarlet]警告![] 存在同名地图,确定要覆盖? -text.editor.selectmap = 选择一个地图加载: -text.width = 宽度: -text.height = 高度: -text.menu = 菜单 -text.play = 开始游戏 -text.load = 载入游戏 -text.save = 保存 -text.fps = FPS: {0} -text.tps = TPS: {0} -text.ping = Ping: {0}ms -text.language.restart = 为了使语言设置生效请重启游戏。 -text.settings = 设置 -text.tutorial = 教程 -text.editor = 编辑器 -text.mapeditor = 地图编辑器 -text.donate = 捐赠 -text.connectfail = [crimson]服务器连接失败: [accent]{0} -text.error.unreachable = 服务器无法访问。 -text.error.invalidaddress = 地址无效。 -text.error.timedout = 连接超时!\n确保服务器设置了端口转发,并且地址正确! -text.error.mismatch = 包错误:\n可能是客户端/服务器版本不匹配.\n请确保客户端和服务器都是最新的版本! -text.error.alreadyconnected = 已连接。 -text.error.mapnotfound = 找不到地图文件! -text.error.any = 未知网络错误. -text.settings.language = 语言 -text.settings.reset = 恢复默认 -text.settings.rebind = 重新绑定 -text.settings.controls = 控制 -text.settings.game = 游戏 -text.settings.sound = 声音 -text.settings.graphics = 图像 -text.settings.cleardata = 清除游戏数据…… -text.settings.clear.confirm = 您确定要清除数据吗?\n这个操作无法撤销! -text.settings.clearall.confirm = [scarlet]警告![]\n这将清除所有数据,包括存档、地图、解锁和键绑定。\n按「是」后,游戏将删除所有数据并自动退出。 -text.settings.clearsectors = 清除区域 -text.settings.clearunlocks = 清除解锁 -text.settings.clearall = 清除所有 -text.paused = 暂停 -text.yes = 是 -text.no = 不 -text.info.title = [accent]详情 -text.error.title = [crimson]发生了一个错误 -text.error.crashtitle = 发生了一个错误 -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = 方块详情 -text.blocks.powercapacity = 能量容量 -text.blocks.powershot = 能量/发射 -text.blocks.targetsair = 攻击空中单位 -text.blocks.itemspeed = 移动速度 -text.blocks.shootrange = 范围 -text.blocks.size = 尺寸 -text.blocks.liquidcapacity = 液体容量 -text.blocks.maxitemssecond = 最大物品数量 -text.blocks.powerrange = 能量范围 -text.blocks.poweruse = 能量使用 -text.blocks.powerdamage = 功率/损伤 -text.blocks.inputitemcapacity = 最大输入 -text.blocks.outputitemcapacity = 最大输出 -text.blocks.itemcapacity = 物品容量 -text.blocks.basepowergeneration = 基础能源输出 -text.blocks.powertransferspeed = 能量传输 -text.blocks.craftspeed = 生产速度 -text.blocks.inputliquid = 液体输入 -text.blocks.inputliquidaux = 辅助液体 -text.blocks.inputitem = 物品输入 -text.blocks.inputitems = 物品输入 -text.blocks.outputitem = 物品输出 -text.blocks.drilltier = 可钻探矿物 -text.blocks.drillspeed = 基础钻探速度 -text.blocks.liquidoutput = 液体输出 -text.blocks.liquidoutputspeed = 液体输出速度 -text.blocks.liquiduse = 液体使用速度 -text.blocks.coolant = 冷却剂 -text.blocks.coolantuse = 冷却剂使用速度 -text.blocks.inputliquidfuel = 液体燃料输入 -text.blocks.liquidfueluse = 液体燃料使用速度 -text.blocks.boostitem = Boost Item -text.blocks.boostliquid = Boost Liquid -text.blocks.health = 生命值 -text.blocks.inaccuracy = 误差 -text.blocks.shots = 发射数 -text.blocks.reload = 重新装弹 -text.blocks.inputfuel = 燃料 -text.blocks.fuelburntime = 燃料燃烧时间 -text.blocks.inputcapacity = 输入容量 -text.blocks.outputcapacity = 输出容量 -text.unit.blocks = 方块 -text.unit.powersecond = 能量单位/秒 -text.unit.liquidsecond = 液体单位/秒 -text.unit.itemssecond = 物品/秒 -text.unit.pixelssecond = 像素/秒 -text.unit.liquidunits = 液体单位 -text.unit.powerunits = 能量单位 -text.unit.degrees = 度 -text.unit.seconds = 秒 -text.unit.items = 物品 -text.category.general = 普通 -text.category.power = 能量 -text.category.liquids = 液体 -text.category.items = 物品 -text.category.crafting = 制造 -text.category.shooting = 发射 -text.category.optional = Optional Enhancements +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 = 游戏源码 +link.dev-builds.description = 不稳定开发版 +link.trello.description = Trello board 上的官方计划表 +link.itch.io.description = PC版下载和网页版(itch.io) +link.google-play.description = 从谷歌商店获取安卓版 +link.wiki.description = 官方 Mindustry 维基 +linkfail = 打开链接失败!\nURL 已经复制到剪贴板。 +screenshot = Screenshot saved to {0} +gameover = 你的核心被摧毁了! +gameover.pvp = accent] {0}[] 队获胜! +highscore = [accent]新纪录! +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: +map.delete = 确定要删除 "[accent]{0}[]" 地图吗? +level.highscore = 最高分: [accent]{0} +level.select = 选择关卡 +level.mode = 游戏模式: +construction.desktop = 桌面控制已更改.\n取消选择快活停止构建, [accent]使用空间[]. +construction.title = 方块建造指导 +construction = 你选择了 [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 = < 核心正在受到攻击! > +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 = 自定义游戏 +newgame = 新游戏 +none = <无> +close = 关闭 +quit = 退出 +maps = 地图 +continue = 继续 +maps.none = [LIGHT_GRAY]未发现地图! +about.button = 关于 +name = 名字: +noname = Pick a[accent] player name[] first. +filename = 文件名: +unlocked = 新方块已解锁! +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.clientOutdated = 客户端版本过旧!请升级! +server.kicked.serverOutdated = 服务器版本过旧!请联系房主升级! +server.kicked.banned = 你被这个服务器拉黑了。 +server.kicked.recentKick = 你刚刚被踢出服务器。\n请稍后重新连接! +server.kicked.nameInUse = 服务器中已经\n有人有相同的名字了。 +server.kicked.nameEmpty = 你的名字必须至少包含一个字母或数字。 +server.kicked.idInUse = 你已经在服务器中!不允许用两个账号。 +server.kicked.customClient = 这个服务器不支持修改版客户端,请下载官方版本。 +server.kicked.gameover = Game over! +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 = 创建服务器 +hostserver.mobile = 创建\n服务器 +host = 创建 +hosting = [accent]正在打开服务器…… +hosts.refresh = 刷新 +hosts.discovering = 正在搜索局域网服务器 +server.refreshing = 正在刷新服务器 +hosts.none = [lightgray]未发现局域网游戏! +host.invalid = [scarlet]无法连接服务器。 +trace = 跟踪玩家 +trace.playername = 玩家名字: [accent]{0} +trace.ip = IP地址: [accent]{0} +trace.id = ID︰[accent]{0} +trace.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.edit = 编辑服务器 +server.outdated = [crimson]服务器过旧![] +server.outdated.client = [crimson]客户端过旧![] +server.version = [lightgray]版本: {0} +server.custombuild = [yellow]修改版 +confirmban = 确认拉黑这个玩家吗? +confirmkick = 您确定要踢出这个玩家吗? +confirmunban = 确认要取消拉黑这个玩家吗? +confirmadmin = 确认要添加这个玩家为管理员吗? +confirmunadmin = 确认要取消这个玩家的管理员身份吗? +joingame.title = 加入游戏 +joingame.ip = IP: +disconnect = 已断开 +disconnect.data = 载入世界失败! +connecting = [accent]连接中…… +connecting.data = [accent]加载世界中…… +server.port = 端口︰ +server.addressinuse = 地址已经使用! +server.invalidport = 无效的端口! +server.error = [crimson]创建服务器错误:[accent]{0} +save.old = 这个存档属于旧版本游戏,无法继续使用了。\n\n[LIGHT_GRAY]存档向下兼容将在 4.0 版本中实现。 +save.new = 新存档 +save.overwrite = 确认要覆盖这个存档吗? +overwrite = 覆盖 +save.none = 没有存档! +saveload = [accent]保存中…… +savefail = 保存失败! +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 = 导入存档 +save.newslot = 保存游戏: +save.rename = 重命名 +save.rename.text = 新名字: +selectslot = 选择一个存档。 +slot = [accent]存档 {0} +save.corrupted = [accent]存档损坏或无效!\n如果你刚刚升级了游戏,那么这可能是因为存档格式改变了而[scarlet]不是[] bug 。 +empty = <空> +on = 开 +off = 关 +save.autosave = 自动保存:{0} +save.map = 地图:{0} +save.wave = 第 {0} 波 +save.difficulty = 难度: {0} +save.date = 最后保存日期:{0} +save.playtime = 游戏时间:{0} +warning = Warning. +confirm = 确认 +delete = 删除 +ok = 好的 +open = 打开 +cancel = 取消 +openlink = 打开链接 +copylink = 删除链接 +back = 返回 +quit.confirm = 确认要退出? +changelog.title = 更新日志 +changelog.loading = 正在获取更新日志... +changelog.error.android = [accent]请注意更新日志有时在安卓 4.4 以下不工作。\n这是因为安卓系统的一个 bug 。 +changelog.error.ios = [accent]iOS还不支持更新日志。 +changelog.error = [scarlet]获取更新日志失败!\n请检查你的网络。 +changelog.current = [yellow][[Current version] +changelog.latest = [accent][[Latest version] +loading = [accent]加载中…… +saving = [accent]保存中…… +wave = [accent]第 {0} 波 +wave.waiting = 下一波将在 {0} 秒后到来 +waiting = 等待中…… +waiting.players = 等待玩家中…… +wave.enemies = 剩下 [LIGHT_GRAY]{0} 敌人 +wave.enemy = 剩下 [LIGHT_GRAY]{0} 敌人 +loadimage = 加载图片 +saveimage = 保存图片 +unknown = 未知 +custom = 自定义 +builtin = 内建的 +map.delete.confirm = 确认要删除地图吗?这个操作无法撤销! +map.random = [accent]随机地图 +map.nospawn = 这个地图没有核心!请在编辑器中添加一个[ROYAL]蓝色[]的核心。 +map.nospawn.pvp = 这个地图没有敌人的核心!请在编辑器中添加一个[ROYAL]红色[]的核心。 +map.invalid = 地图载入错误:地图文件可能已经损坏。 +editor.brush = 笔刷 +editor.slope = \\ +editor.openin = 在编辑器中打开 +editor.oregen = 生成矿石 +editor.oregen.info = 生成矿石: +editor.mapinfo = 地图详情 +editor.author = 作者: +editor.description = 描述: +editor.name = 名字: +editor.teams = 团队 +editor.elevation = 高度 +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.import = 导入…… +editor.importmap = 导入地图 +editor.importmap.description = 导入一个已经存在的地图 +editor.importfile = 导入文件 +editor.importfile.description = 导入一个外置的地图文件 +editor.importimage = 导入地形图像 +editor.importimage.description = 导入外置地图图像文件 +editor.export = 导出…… +editor.exportfile = 导出文件 +editor.exportfile.description = 导出一个地图文件 +editor.exportimage = 导出一个地形文件 +editor.exportimage.description = 导出一个地图图像文件 +editor.loadimage = 导入地形 +editor.saveimage = 导出地形 +editor.unsaved = [scarlet]你有未保存的更改![]\n确定要退出? +editor.resizemap = 调整地图 +editor.mapname = 地图名字: +editor.overwrite = [accent]警告!\n这将会覆盖一个已经存在的地图。 +editor.overwrite.confirm = [scarlet]警告![] 存在同名地图,确定要覆盖? +editor.selectmap = 选择一个地图加载: +width = 宽度: +height = 高度: +menu = 菜单 +play = 开始游戏 +load = 载入游戏 +save = 保存 +fps = FPS: {0} +tps = TPS: {0} +ping = 延迟: {0}ms +language.restart = 为了使语言设置生效请重启游戏。 +settings = 设置 +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. +zone.unlocked = [LIGHT_GRAY]{0} unlocked. +connectfail = [crimson]服务器连接失败: [accent]{0} +error.unreachable = 服务器无法访问。 +error.invalidaddress = 地址无效。 +error.timedout = 连接超时!\n确保服务器设置了端口转发,并且地址正确! +error.mismatch = 包错误:\n可能是客户端/服务器版本不匹配.\n请确保客户端和服务器都是最新的版本! +error.alreadyconnected = 已连接。 +error.mapnotfound = 找不到地图文件! +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 = 重新绑定 +settings.controls = 控制 +settings.game = 游戏 +settings.sound = 声音 +settings.graphics = 图像 +settings.cleardata = 清除游戏数据…… +settings.clear.confirm = 您确定要清除数据吗?\n这个操作无法撤销! +settings.clearall.confirm = [scarlet]警告![]\n这将清除所有数据,包括存档、地图、解锁和键绑定。\n按「是」后,游戏将删除所有数据并自动退出。 +settings.clearunlocks = 清除解锁 +settings.clearall = 清除所有 +paused = 暂停 +yes = 是 +no = 不 +info.title = [accent]详情 +error.title = [crimson]发生了一个错误 +error.crashtitle = 发生了一个错误 +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = 方块详情 +blocks.powercapacity = 能量容量 +blocks.powershot = 能量/发射 +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.liquid = Liquid +blocks.coolantuse = 冷却剂使用速度 +blocks.inputliquidfuel = 液体燃料输入 +blocks.liquidfueluse = 液体燃料使用速度 +blocks.boostitem = Boost Item +blocks.boostliquid = Boost Liquid +blocks.health = 生命值 +blocks.power = 电力 +blocks.power.satisfaction = 电力见面 +blocks.inaccuracy = 误差 +blocks.shots = 发射数 +blocks.reload = 重新装弹 +blocks.inputfuel = 燃料 +blocks.fuelburntime = 燃料燃烧时间 +blocks.inputcapacity = 输入容量 +blocks.outputcapacity = 输出容量 +unit.blocks = 方块 +unit.powersecond = 能量单位/秒 +unit.liquidsecond = 液体单位/秒 +unit.itemssecond = 物品/秒 +unit.pixelssecond = 像素/秒 +unit.liquidunits = 液体单位 +unit.powerunits = 能量单位 +unit.degrees = 度 +unit.seconds = 秒 +unit.items = 物品 +category.general = 普通 +category.power = 能量 +category.liquids = 液体 +category.items = 物品 +category.crafting = 制造 +category.shooting = 发射 +category.optional = Optional Enhancements +setting.indicators.name = Ally Indicators setting.autotarget.name = 自动发射 setting.fpscap.name = 最高 FPS setting.fpscap.none = 无 @@ -371,18 +379,22 @@ setting.mutemusic.name = 静音 setting.sfxvol.name = 音效音量 setting.mutesound.name = 静音 setting.crashreport.name = 发送匿名崩溃报告 -text.keybind.title = 重新绑定按键 +keybind.title = 重新绑定按键 category.general.name = 普通 category.view.name = 查看 category.multiplayer.name = 多人 command.attack = 攻击 command.retreat = 撤退 command.patrol = 巡逻 +keybind.gridMode.name = 选择块 +keybind.gridModeShift.name = 选择类别 keybind.press = 按一下键…… keybind.press.axis = 按一下轴或键…… +keybind.screenshot.name = Map Screenshot keybind.move_x.name = 水平移动 keybind.move_y.name = 垂直移动 keybind.select.name = 选择 +keybind.pick.name = Pick Block keybind.break.name = 破坏 keybind.deselect.name = 取消 keybind.shoot.name = 射击 @@ -401,30 +413,29 @@ keybind.chat_history_next.name = 后面的聊天记录 keybind.chat_scroll.name = 聊天记录滚动 keybind.drop_unit.name = 掉落单位 keybind.zoom_minimap.name = 小地图缩放 -mode.text.help.title = 模式说明 -mode.waves.name = 普通 -mode.waves.description = 普通模式,有限的资源和自动生成敌人。 +mode.help.title = 模式说明 +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.descrption = 没有波浪,目标是摧毁敌人的基地。 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 = 钍 @@ -445,6 +456,10 @@ 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.oil.name = 石油 @@ -478,24 +493,29 @@ mech.trident-ship.weapon = 炸弹 mech.glaive-ship.name = Glaive mech.glaive-ship.description = 一种大型,装甲厚重的武装直升机。配备燃烧机枪。有优秀的加速能力和最快的速度。 mech.glaive-ship.weapon = 火焰机枪 -text.item.explosiveness = [LIGHT_GRAY]爆炸性:{0} -text.item.flammability = [LIGHT_GRAY]易燃性:{0} -text.item.radioactivity = [LIGHT_GRAY]放射性:{0} -text.item.fluxiness = [LIGHT_GRAY]助熔性:{0} -text.unit.health = [LIGHT_GRAY]生命值:{0} -text.unit.speed = [LIGHT_GRAY]速度:{0} -text.mech.weapon = [LIGHT_GRAY]武器:{0} -text.mech.armor = [LIGHT_GRAY]装甲:{0} -text.mech.itemcapacity = [LIGHT_GRAY]物品容量:{0} -text.mech.minespeed = [LIGHT_GRAY]采矿速度:{0} -text.mech.minepower = [LIGHT_GRAY]采矿力量:{0} -text.mech.ability = [LIGHT_GRAY]能力:{0} -text.liquid.heatcapacity = [LIGHT_GRAY]热容量:{0} -text.liquid.viscosity = [LIGHT_GRAY]粘度:{0} -text.liquid.temperature = [LIGHT_GRAY]温度:{0} +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]Health: {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.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.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = 金属地板 block.deepwater.name = 深水 block.water.name = 水 @@ -514,8 +534,8 @@ block.blackrock.name = 黑岩 block.icerock.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 = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = 相织布墙 block.phase-wall-large.name = 大型相织布墙 block.thorium-wall.name = 钍墙 @@ -548,17 +568,19 @@ 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 = 三叉戟 机甲平台 @@ -567,11 +589,11 @@ block.omega-mech-pad.name = Omega 机甲平台 block.tau-mech-pad.name = Tau 机甲平台 block.conduit.name = 导管 block.mechanical-pump.name = 机械泵 -block.itemsource.name = 物品源 -block.itemvoid.name = 物品黑洞 -block.liquidsource.name = 液体源 -block.powervoid.name = 能源黑洞 -block.powerinfinite.name = 无限能源 +block.item-source.name = 物品源 +block.item-void.name = 物品黑洞 +block.liquid-source.name = 液体源 +block.power-void.name = 能源黑洞 +block.power-source.name = 无限能源 block.unloader.name = 装卸器 block.vault.name = 仓库 block.wave.name = 波浪 @@ -623,7 +645,7 @@ block.rtg-generator.name = RTG 发电机 block.spectre.name = 幽灵 block.meltdown.name = 熔毁 block.container.name = 容器 -block.core.description = 游戏中最重要的建筑。 +block.launch-pad.name = Launch Pad team.blue.name = 蓝 team.red.name = 红 team.orange.name = 橙 @@ -637,6 +659,7 @@ 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 +669,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请造一个传送线,从钻头到核心. @@ -769,11 +796,11 @@ block.router.description = 从一个方向接受物品,并将它们平均输 block.distributor.description = 一个高级路由器,可以将物品分成最多7个方向。 block.bridge-conveyor.description = 高级项目传输块。允许在跨越任何地形或建筑物上运输物品,最多跨越3个块。 block.alpha-mech-pad.description = 当给予足够的电力时,将你的装置重建为[accent] Alpha []机甲。 -block.itemsource.description = 无限输出物品。仅限沙箱。 -block.liquidsource.description = 无限输出液体。仅限沙箱。 -block.itemvoid.description = 在不使用电源的情况下销毁任何进入它的物品。仅限沙箱。 -block.powerinfinite.description = 无限输出功率。仅限沙箱。 -block.powervoid.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 = 可以转换成[LIGHT_GRAY] 石头 [],用于发电或用作某些炮塔的弹药。 liquid.oil.description = 可以燃烧,爆炸或用作冷却液。 diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index 7800279a14..d270e4536d 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -1,356 +1,358 @@ -text.credits.text = 由[ROYAL]Anuken[]製作 - [SKY]anukendev@gmail.com[] -text.credits = 致謝名單 -text.contributors = 翻譯員和貢獻者 -text.discord = 加入 Mindustry 的 Discord 聊天室! -text.link.discord.description = 官方 Mindustry Discord 聊天室 -text.link.github.description = 遊戲原始碼 -text.link.dev-builds.description = 開發中版本 -text.link.trello.description = 官方 Trello 功能規劃看板 -text.link.itch.io.description = itch.io 電腦版下載與網頁版 -text.link.google-play.description = Google Play 商店頁面 -text.link.wiki.description = 官方 Mindustry 維基 -text.linkfail = 無法打開連結!\n我們已將該網址複製到您的剪貼簿。 -text.screenshot = 截圖保存到{0} -text.gameover = 核心已被摧毀。 -text.gameover.pvp = [accent]{0}[]隊獲勝! -text.sector.gameover = 這個區域失守了,重新部署? -text.sector.retry = 重試 -text.highscore = [accent]新的高分紀錄! -text.wave.lasted = 你維持到第[accent]{0}[]波。 -text.level.highscore = 最高分:[accent]{0} -text.level.delete.title = 確認刪除 -text.map.delete = 確認要刪除「[accent]{0}[]」地圖嗎? -text.level.select = 選擇關卡 -text.level.mode = 遊戲模式: -text.construction.desktop = 電腦控制已更改。\n要取消選擇或停止建設,[accent]按空格鍵[]。 -text.construction.title = 方塊建設指南 -text.construction = 你選擇了[accent]方塊建設模式[]。\n\n要放置方塊,點擊你的船附近的有效位置。\n選擇了方塊後,點擊複選框就會開始建設。\n\n- 點擊方塊以從選擇區[accent]移除方塊[]。\n- 按住並拖動以[accent]直線放置方塊[]。\n- 點擊左下角的「X」以[accent]取消建設或取消選擇[]。 -text.deconstruction.title = 方塊移除指南 -text.deconstruction = 你選擇了[accent]方塊移除模式[]。\n\n要移除方塊,點擊你的船附近的方塊。\n選擇了方塊後,點擊複選框就會開始移除。\n\n- 點擊方塊以從選擇區[accent]移除方塊[]。\n- 按住一個空點向任何方向拖動以[accent]移除選中區域的方塊[]。\n- 點擊左下角的「X」以[accent]取消移除或取消選擇[]。 -text.showagain = 下次不再顯示 -text.coreattack = 〈核心正在受到攻擊!〉 -text.unlocks = 已解鎖 -text.savegame = 儲存遊戲 -text.loadgame = 載入遊戲 -text.joingame = 多人連線 -text.addplayers = 增加/移除玩家 -text.customgame = 自訂遊戲 -text.sectors = 區域 -text.sector = 區域︰[LIGHT_GRAY]{0} -text.sector.time = 時間︰[LIGHT_GRAY]{0} -text.sector.deploy = 部署 -text.sector.abandon = 放棄 -text.sector.abandon.confirm = 確認要放棄這區域所有進度嗎?\n此操作不可撤回! -text.sector.resume = 繼續 -text.sector.locked = [scarlet][[Incomplete] -text.sector.unexplored = [accent][[Unexplored] -text.missions = 任務︰[LIGHT_GRAY]{0} -text.mission = 任務︰[LIGHT_GRAY]{0} -text.mission.main = 主要任務︰[LIGHT_GRAY]{0} -text.mission.info = 任務資訊 -text.mission.complete = 任務完成! -text.mission.complete.body = 區域{0},{1}已被佔領。 -text.mission.wave = 存活[accent]{0}/{1}[]波\n下一波於{2}開始 -text.mission.wave.enemies = 存活[accent]{0}/{1}[]波\n{2}個敵人 -text.mission.wave.enemy = 存活[accent]{0}/{1}[]波\n{2}個敵人 -text.mission.wave.menu = 存活[accent]{0}[]波 -text.mission.battle = 摧毀敵方基地。 -text.mission.resource.menu = 獲取{0}x{1} -text.mission.resource = 獲取{0}︰\n[accent]{1}/{2}[] -text.mission.block = 建造{0} -text.mission.unit = 生產{0}機組 -text.mission.command = 發送{0}指令至機組 -text.mission.linknode = 鏈接能量節點 -text.mission.display = [accent]任務︰\n[LIGHT_GRAY]{0} -text.mission.mech = 轉換至[accent]{0}[]機甲 -text.mission.create = 製造[accent]{0}[] -text.none = <沒有> -text.close = 關閉 -text.quit = 退出 -text.maps = 地圖 -text.continue = 繼續 -text.nextmission = 下一個任務 -text.maps.none = [LIGHT_GRAY]找不到地圖! -text.about.button = 關於 -text.name = 名稱: -text.noname = 先選擇一個[accent]玩家名稱[]。 -text.filename = 檔案名稱︰ -text.unlocked = 新方塊已解鎖! -text.unlocked.plural = 新方塊已解鎖! -text.players = {0}個線上玩家 -text.players.single = {0}個線上玩家 -text.server.closing = [accent]正在關閉伺服器…… -text.server.kicked.kick = 您已被踢出伺服器! -text.server.kicked.serverClose = 伺服器已關閉。 -text.server.kicked.sectorComplete = 區域已完成。 -text.server.kicked.sectorComplete.text = 任務已完成。\n服務器將於下一個區域繼續。 -text.server.kicked.clientOutdated = 客戶端版本過舊!請更新遊戲! -text.server.kicked.serverOutdated = 伺服器版本過舊!請聯絡伺服主更新伺服器! -text.server.kicked.banned = 您已經從這個伺服器被封禁。 -text.server.kicked.recentKick = 您已經從伺服器被踢除。\n請稍後再進行連線。 -text.server.kicked.nameInUse = 伺服器中已經\n有人有相同的名稱了。 -text.server.kicked.nameEmpty = 你的名稱必須至少包含一個字母或數字。 -text.server.kicked.idInUse = 你已經在伺服器中!不允許用兩個賬號。 -text.server.kicked.customClient = 這個伺服器不支持自訂客戶端,請下載官方版本。 -text.host.info = 目前伺服器監聽於連接埠[scarlet]6567[]。\n所有跟您在同一個[LIGHT_GRAY]網路或區域網路[]環境的玩家應該能在他們的伺服器清單中找到您的伺服器。\n\n如果您希望網際網路上的玩家透過IP 位址連線到您的伺服器,您必須設定[accent]連接埠轉發[]。\n\n[LIGHT_GRAY]注意:如果區域網路內有玩家無法連線至您的伺服器,請務必確認您已於防火牆設定中開放Mindustry存取您的區域網路。 -text.join.info = 您可以在此輸入欲連線的[accent]伺服器的IP位址[],或尋找[accent]區域網路[]內的伺服器。目前支援區域網路與網際網路連線。\n\n[LIGHT_GRAY]注意:這裡沒有網際網路伺服器清單,如果您想透過IP位址連線到某人的伺服器,您必須向他們詢問IP位址。 -text.hostserver = 建立伺服器 -text.hostserver.mobile = 建立\n伺服器 -text.host = 建立 -text.hosting = [accent]伺服器啟動中…… -text.hosts.refresh = 刷新 -text.hosts.discovering = 搜尋區域網路遊戲 -text.server.refreshing = 刷新伺服器 -text.hosts.none = [lightgray]找不到區域網路伺服器! -text.host.invalid = [scarlet]無法連線至伺服器。 -text.trace = 跟隨玩家 -text.trace.playername = 玩家名稱:[accent]{0} -text.trace.ip = IP:[accent]{0} -text.trace.id = ID:[accent]{0} -text.trace.android = Android 客戶端:[accent]{0} -text.trace.modclient = 自訂客戶端:[accent]{0} -text.trace.totalblocksbroken = 方塊拆除總數:[accent]{0} -text.trace.structureblocksbroken = 結構方塊拆除數:[accent]{0} -text.trace.lastblockbroken = 最後拆除的方塊:[accent]{0} -text.trace.totalblocksplaced = 方塊建造數:[accent]{0} -text.trace.lastblockplaced = 最後建造的方塊:[accent]{0} -text.invalidid = 無效的客戶端 ID!請提交錯誤報告。 -text.server.bans = 封禁 -text.server.bans.none = 沒有玩家被封禁! -text.server.admins = 管理員 -text.server.admins.none = 找不到管理員! -text.server.add = 新增伺服器 -text.server.delete = 您確定要刪除這個伺服器嗎? -text.server.hostname = 主機:{0} -text.server.edit = 編輯伺服器 -text.server.outdated = [crimson]伺服器版本過舊![] -text.server.outdated.client = [crimson]客戶端版本過舊![] -text.server.version = [lightgray]版本:{0} -text.server.custombuild = [yellow]自訂組建 -text.confirmban = 您確定要封禁該玩家嗎? -text.confirmkick = 您確定要踢出該玩家嗎? -text.confirmunban = 您確定要解除封禁該玩家嗎? -text.confirmadmin = 您確定要提升這個玩家為管理員嗎? -text.confirmunadmin = 您確定要解除這個玩家的管理員嗎? -text.joingame.title = 加入遊戲 -text.joingame.ip = IP位址: -text.disconnect = 已中斷連線。 -text.disconnect.data = 無法載入地圖資料! -text.connecting = [accent]連線中…… -text.connecting.data = [accent]正在載入地圖資料…… -text.server.port = 連接埠: -text.server.addressinuse = 該位址已使用中! -text.server.invalidport = 無效的連接埠! -text.server.error = [crimson]建立伺服器時發生錯誤:[accent]{0} -text.save.old = 這個存檔屬於舊版本,無法使用了。\n\n[LIGHT_GRAY]舊存檔兼容將在正式4.0版本中實現。 -text.save.new = 新存檔 -text.save.overwrite = 您確定要覆蓋存檔嗎? -text.overwrite = 覆蓋 -text.save.none = 找不到存檔! -text.saveload = [accent]存檔中…… -text.savefail = 無法存檔! -text.save.delete.confirm = 您確定要刪除這個存檔嗎? -text.save.delete = 刪除 -text.save.export = 匯出存檔 -text.save.import.invalid = [accent]這是個無效的存檔! -text.save.import.fail = [crimson]無法匯入存檔:[accent]{0} -text.save.export.fail = [crimson]無法匯出存檔:[accent]{0} -text.save.import = 匯入存檔 -text.save.newslot = 存檔名稱: -text.save.rename = 重新命名 -text.save.rename.text = 新名稱: -text.selectslot = 選取一個存檔。 -text.slot = [accent]存檔{0} -text.save.corrupted = [accent]此存檔無效或已損毀!\n如果你剛剛升級了遊戲,那麼這可能是因為存檔格式改變了而[scarlet]不是[]錯誤。 -text.sector.corrupted = [accent]找到此區域的存檔,但是加載失敗。\n已經創建了一個新的存檔。 -text.empty = <空白> -text.on = 開啟 -text.off = 關閉 -text.save.autosave = 自動存檔:{0} -text.save.map = 地圖:{0} -text.save.wave = 波次:{0} -text.save.difficulty = 難度:{0} -text.save.date = 最後存檔時間:{0} -text.save.playtime = 遊玩時間: {0} -text.confirm = 確認 -text.delete = 刪除 -text.ok = 確定 -text.open = 開啟 -text.cancel = 取消 -text.openlink = 開啟連結 -text.copylink = 複製連結 -text.back = 返回 -text.quit.confirm = 您確定要退出嗎? -text.changelog.title = 更新日誌 -text.changelog.loading = 正在取得更新日誌…… -text.changelog.error.android = [accent]請注意,更新日誌有時無法在Android 4.4或更低版本使用!這是因為 Android 的內部錯誤導致。 -text.changelog.error.ios = [accent]目前無法在iOS系統中使用更新日誌。 -text.changelog.error = [scarlet]無法取得更新日誌!請檢查您的網路連線! -text.changelog.current = [yellow][[Current version] -text.changelog.latest = [accent][[Latest version] -text.loading = [accent]載入中…… -text.saving = [accent]儲存中…… -text.wave = [accent]第{0}波 -text.wave.waiting = 將於{0}秒後抵達 -text.waiting = 等待中…… -text.waiting.players = 等待玩家中…… -text.wave.enemies = [LIGHT_GRAY]剩下{0}敵人 -text.wave.enemy = [LIGHT_GRAY]剩下{0}敵人 -text.loadimage = 載入圖像 -text.saveimage = 儲存圖像 -text.unknown = 未知 -text.custom = 自訂 -text.builtin = 内建 -text.map.delete.confirm = 確認要刪除地圖嗎?此操作無法撤回! -text.map.random = [accent]隨機地圖 -text.map.nospawn = 這個地圖沒有核心!請在編輯器中添加一個[ROYAL]藍色[]的核心。 -text.map.nospawn.pvp = 這個地圖沒有核心讓敵人重生!請在編輯器中添加一個[SCARLET]紅色[]的核心。 -text.map.invalid = 地圖載入錯誤:地圖可能已經損壞。 -text.editor.brush = 粉刷 -text.editor.slope = \\ -text.editor.openin = 在編輯器中開啟 -text.editor.oregen = 礦石產生 -text.editor.oregen.info = 礦石產生: -text.editor.mapinfo = 地圖資訊 -text.editor.author = 作者: -text.editor.description = 描述: -text.editor.name = 名稱: -text.editor.teams = 隊伍 -text.editor.elevation = 高度 -text.editor.errorimageload = 載入圖像檔時發生錯誤:[accent]{0} -text.editor.errorimagesave = 儲存圖像檔時發生錯誤:[橙色]{0} -text.editor.generate = 產生 -text.editor.resize = 調整大小 -text.editor.loadmap = 載入地圖 -text.editor.savemap = 儲存地圖 -text.editor.saved = 已儲存! -text.editor.save.noname = 您的地圖沒有名稱!在「地圖資訊」畫面設置一個名稱。 -text.editor.save.overwrite = 您的地圖覆寫一個內建的地圖!在「地圖信息」畫面設置一個不同的名稱。 -text.editor.import.exists = [scarlet]匯入失敗:[]一個叫「{0}」的內建地圖已存在! -text.editor.import = 匯入…… -text.editor.importmap = 匯入地圖 -text.editor.importmap.description = 匯入一個已存在的地圖 -text.editor.importfile = 匯入檔案 -text.editor.importfile.description = 匯入一個外部的地圖檔案 -text.editor.importimage = 匯入地形圖像檔 -text.editor.importimage.description = 匯入一個外部的地形圖像檔 -text.editor.export = 匯出…… -text.editor.exportfile = 匯出檔案 -text.editor.exportfile.description = 匯出一個地圖檔案 -text.editor.exportimage = 匯出地形圖像檔 -text.editor.exportimage.description = 匯出一個地形圖像檔 -text.editor.loadimage = 載入圖像 -text.editor.saveimage = 儲存圖像 -text.editor.unsaved = [scarlet]尚未儲存變更![]\n您確定要退出嗎? -text.editor.resizemap = 調整地圖大小 -text.editor.mapname = 地圖名稱: -text.editor.overwrite = [accent]警告!這將會覆蓋現有的地圖。 -text.editor.overwrite.confirm = [scarlet]警告![]同名地圖存在,確定要覆蓋現有地圖? -text.editor.selectmap = 選取要載入的地圖: -text.width = 寬度: -text.height = 長度: -text.menu = 主選單 -text.play = 開始 -text.load = 載入 -text.save = 儲存 -text.fps = FPS:{0} -text.tps = TPS:{0} -text.ping = 延遲:{0}ms -text.language.restart = 請重新啟動遊戲以使選取的語言生效。 -text.settings = 設定 -text.tutorial = 教學 -text.editor = 地圖編輯器 -text.mapeditor = 地圖編輯器 -text.donate = 贊助 - -text.connectfail = [crimson]無法連線到伺服器:[accent]{0} -text.error.unreachable = 無法到達伺服器。 -text.error.invalidaddress = 無效地址。 -text.error.timedout = 超時連接!\n確保伺服器設置了連接埠轉發,並且地址正確! -text.error.mismatch = 包裹錯誤:\n客戶端/伺服器版本可能不匹配。 n確保客戶端和伺服器有最新版本的Mindustry! -text.error.alreadyconnected = 已連接。 -text.error.mapnotfound = 找不到地圖! -text.error.any = 未知網絡錯誤。 - -text.settings.language = 語言 -text.settings.reset = 重設為預設設定 -text.settings.rebind = 重新綁定 -text.settings.controls = 操作 -text.settings.game = 遊戲 -text.settings.sound = 音效 -text.settings.graphics = 圖形 -text.settings.cleardata = 清除遊戲數據…… -text.settings.clear.confirm = 您確定要清除數據嗎?\n此操作無法撤回! -text.settings.clearall.confirm = [scarlet]警告![]\n這將清除所有數據,包括存檔、地圖、解鎖和熱鍵綁定。\n按「是」後,遊戲將刪除所有數據並自動退出。 -text.settings.clearsectors = 清除區域 -text.settings.clearunlocks = 清除已解鎖 -text.settings.clearall = 清除所有 -text.paused = 已暫停 -text.yes = 是 -text.no = 否 -text.info.title = [accent]資訊 -text.error.title = [crimson]發生錯誤 -text.error.crashtitle = 發生錯誤 -text.blocks.unknown = [LIGHT_GRAY]??? -text.blocks.blockinfo = 方塊資訊 -text.blocks.powercapacity = 蓄電量 -text.blocks.powershot = 能量/射擊 -text.blocks.targetsair = 攻擊空中目標 -text.blocks.itemspeed = 移動速度 -text.blocks.shootrange = 範圍 -text.blocks.size = 尺寸 -text.blocks.liquidcapacity = 液體容量 -text.blocks.maxitemssecond = 最高產量 -text.blocks.powerrange = 輸出範圍 -text.blocks.poweruse = 能量使用 -text.blocks.powerdamage = 能量/傷害 -text.blocks.inputitemcapacity = 最大輸入 -text.blocks.outputitemcapacity = 最大輸出 -text.blocks.itemcapacity = 物品容量 -text.blocks.basepowergeneration = 基本能量生产 -text.blocks.powertransferspeed = 能量傳輸 -text.blocks.craftspeed = 產生速度 -text.blocks.inputliquid = 輸入液體 -text.blocks.inputliquidaux = 輔助液體 -text.blocks.inputitem = 輸入物品 -text.blocks.inputitems = 輸入物品 -text.blocks.outputitem = 輸出物品 -text.blocks.drilltier = 可鑽取礦物 -text.blocks.drillspeed = 基本鑽取速度 -text.blocks.liquidoutput = 輸出液體 -text.blocks.liquidoutputspeed = 輸出液體速度 -text.blocks.liquiduse = 使用液體速度 -text.blocks.coolant = 冷卻劑 -text.blocks.coolantuse = 使用冷卻劑 -text.blocks.inputliquidfuel = 輸入液體燃料 -text.blocks.liquidfueluse = 使用液體燃料速度 -text.blocks.boostitem = 強化物品 -text.blocks.boostliquid = 強化液體 -text.blocks.health = 耐久度 -text.blocks.inaccuracy = 誤差 -text.blocks.shots = 射擊數 -text.blocks.reload = 重裝彈藥 -text.blocks.inputfuel = 燃料 -text.blocks.fuelburntime = 燃燒燃料時間 -text.blocks.inputcapacity = 輸入容量 -text.blocks.outputcapacity = 輸出容量 -text.unit.blocks = 方塊 -text.unit.powersecond = 能量單位/秒 -text.unit.liquidsecond = 液體單位/秒 -text.unit.itemssecond = 物品/秒 -text.unit.pixelssecond = 像素/秒 -text.unit.liquidunits = 液體單位 -text.unit.powerunits = 能量單位 -text.unit.degrees = 度 -text.unit.seconds = 秒 -text.unit.items = 物品 -text.category.general = 一般 -text.category.power = 能量 -text.category.liquids = 液體 -text.category.items = 物品 -text.category.crafting = 合成 -text.category.shooting = 射擊 -text.category.optional = 可選的強化 +credits.text = 由[ROYAL]Anuken[]製作 - [SKY]anukendev@gmail.com[] +credits = 致謝名單 +contributors = 翻譯員和貢獻者 +discord = 加入 Mindustry 的 Discord 聊天室! +link.discord.description = 官方 Mindustry Discord 聊天室 +link.github.description = 遊戲原始碼 +link.dev-builds.description = 開發中版本 +link.trello.description = 官方 Trello 功能規劃看板 +link.itch.io.description = itch.io 電腦版下載與網頁版 +link.google-play.description = Google Play 商店頁面 +link.wiki.description = 官方 Mindustry 維基 +linkfail = 無法打開連結!\n我們已將該網址複製到您的剪貼簿。 +screenshot = 截圖保存到{0} +gameover = 遊戲結束 +gameover.pvp = [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 = 發射的資源: +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]直線放置方塊[]。\n- 點擊左下角的「X」以[accent]取消建設或取消選擇[]。 +deconstruction.title = 方塊移除指南 +deconstruction = 你選擇了[accent]方塊移除模式[]。\n\n要移除方塊,點擊你的船附近的方塊。\n選擇了方塊後,點擊複選框就會開始移除。\n\n- 點擊方塊以從選擇區[accent]移除方塊[]。\n- 按住一個空點向任何方向拖動以[accent]移除選中區域的方塊[]。\n- 點擊左下角的「X」以[accent]取消移除或取消選擇[]。 +showagain = 下次不再顯示 +coreattack = 〈核心正在受到攻擊!〉 +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 = 自訂遊戲 +newgame = New Game +none = <沒有> +close = 關閉 +quit = 退出 +maps = 地圖 +continue = 繼續 +maps.none = [LIGHT_GRAY]找不到地圖! +about.button = 關於 +name = 名稱: +noname = 先選擇一個[accent]玩家名稱[]。 +filename = 檔案名稱︰ +unlocked = 新方塊已解鎖! +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.clientOutdated = 客戶端版本過舊!請更新遊戲! +server.kicked.serverOutdated = 伺服器版本過舊!請聯絡伺服主更新伺服器! +server.kicked.banned = 您已經從這個伺服器被封禁。 +server.kicked.recentKick = 您已經從伺服器被踢除。\n請稍後再進行連線。 +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 = 建立伺服器 +hostserver.mobile = 建立\n伺服器 +host = 建立 +hosting = [accent]伺服器啟動中…… +hosts.refresh = 刷新 +hosts.discovering = 搜尋區域網路遊戲 +server.refreshing = 刷新伺服器 +hosts.none = [lightgray]找不到區域網路伺服器! +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!請提交錯誤報告。 +server.bans = 封禁 +server.bans.none = 沒有玩家被封禁! +server.admins = 管理員 +server.admins.none = 找不到管理員! +server.add = 新增伺服器 +server.delete = 您確定要刪除這個伺服器嗎? +server.hostname = 主機:{0} +server.edit = 編輯伺服器 +server.outdated = [crimson]伺服器版本過舊![] +server.outdated.client = [crimson]客戶端版本過舊![] +server.version = [lightgray]版本:{0} +server.custombuild = [yellow]自訂組建 +confirmban = 您確定要封禁該玩家嗎? +confirmkick = 您確定要踢出該玩家嗎? +confirmunban = 您確定要解除封禁該玩家嗎? +confirmadmin = 您確定要提升這個玩家為管理員嗎? +confirmunadmin = 您確定要解除這個玩家的管理員嗎? +joingame.title = 加入遊戲 +joingame.ip = IP位址: +disconnect = 已中斷連線。 +disconnect.data = 無法載入地圖資料! +connecting = [accent]連線中…… +connecting.data = [accent]正在載入地圖資料…… +server.port = 連接埠: +server.addressinuse = 該位址已使用中! +server.invalidport = 無效的連接埠! +server.error = [crimson]建立伺服器時發生錯誤:[accent]{0} +save.old = 這個存檔屬於舊版本,無法使用了。\n\n[LIGHT_GRAY]舊存檔兼容將在正式4.0版本中實現。 +save.new = 新存檔 +save.overwrite = 您確定要覆蓋存檔嗎? +overwrite = 覆蓋 +save.none = 找不到存檔! +saveload = [accent]存檔中…… +savefail = 無法存檔! +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 = 匯入存檔 +save.newslot = 存檔名稱: +save.rename = 重新命名 +save.rename.text = 新名稱: +selectslot = 選取一個存檔。 +slot = [accent]存檔{0} +save.corrupted = [accent]此存檔無效或已損毀!\n如果你剛剛升級了遊戲,那麼這可能是因為存檔格式改變了而[scarlet]不是[]錯誤。 +empty = <空白> +on = 開啟 +off = 關閉 +save.autosave = 自動存檔:{0} +save.map = 地圖:{0} +save.wave = 波次:{0} +save.difficulty = 難度:{0} +save.date = 最後存檔時間:{0} +save.playtime = 遊玩時間: {0} +warning = Warning. +confirm = 確認 +delete = 刪除 +ok = 確定 +open = 開啟 +cancel = 取消 +openlink = 開啟連結 +copylink = 複製連結 +back = 返回 +quit.confirm = 您確定要退出嗎? +changelog.title = 更新日誌 +changelog.loading = 正在取得更新日誌…… +changelog.error.android = [accent]請注意,更新日誌有時無法在Android 4.4或更低版本使用!這是因為 Android 的內部錯誤導致。 +changelog.error.ios = [accent]目前無法在iOS系統中使用更新日誌。 +changelog.error = [scarlet]無法取得更新日誌!請檢查您的網路連線! +changelog.current = [yellow][[Current version] +changelog.latest = [accent][[Latest version] +loading = [accent]載入中…… +saving = [accent]儲存中…… +wave = [accent]第{0}波 +wave.waiting = 將於{0}秒後抵達 +waiting = 等待中…… +waiting.players = 等待玩家中…… +wave.enemies = [LIGHT_GRAY]剩下{0}敵人 +wave.enemy = [LIGHT_GRAY]剩下{0}敵人 +loadimage = 載入圖像 +saveimage = 儲存圖像 +unknown = 未知 +custom = 自訂 +builtin = 内建 +map.delete.confirm = 確認要刪除地圖嗎?此操作無法撤回! +map.random = [accent]隨機地圖 +map.nospawn = 這個地圖沒有核心!請在編輯器中添加一個[ROYAL]藍色[]的核心。 +map.nospawn.pvp = 這個地圖沒有核心讓敵人重生!請在編輯器中添加一個[SCARLET]紅色[]的核心。 +map.invalid = 地圖載入錯誤:地圖可能已經損壞。 +editor.brush = 粉刷 +editor.slope = \\ +editor.openin = 在編輯器中開啟 +editor.oregen = 礦石產生 +editor.oregen.info = 礦石產生: +editor.mapinfo = 地圖資訊 +editor.author = 作者: +editor.description = 描述: +editor.name = 名稱: +editor.teams = 隊伍 +editor.elevation = 高度 +editor.errorimageload = 載入圖像檔時發生錯誤:[accent]{0} +editor.errorimagesave = 儲存圖像檔時發生錯誤:[橙色]{0} +editor.generate = 產生 +editor.resize = 調整大小 +editor.loadmap = 載入地圖 +editor.savemap = 儲存地圖 +editor.saved = 已儲存! +editor.save.noname = 您的地圖沒有名稱!在「地圖資訊」畫面設置一個名稱。 +editor.save.overwrite = 您的地圖覆寫一個內建的地圖!在「地圖信息」畫面設置一個不同的名稱。 +editor.import.exists = [scarlet]匯入失敗:[]一個叫「{0}」的內建地圖已存在! +editor.import = 匯入…… +editor.importmap = 匯入地圖 +editor.importmap.description = 匯入一個已存在的地圖 +editor.importfile = 匯入檔案 +editor.importfile.description = 匯入一個外部的地圖檔案 +editor.importimage = 匯入地形圖像檔 +editor.importimage.description = 匯入一個外部的地形圖像檔 +editor.export = 匯出…… +editor.exportfile = 匯出檔案 +editor.exportfile.description = 匯出一個地圖檔案 +editor.exportimage = 匯出地形圖像檔 +editor.exportimage.description = 匯出一個地形圖像檔 +editor.loadimage = 載入圖像 +editor.saveimage = 儲存圖像 +editor.unsaved = [scarlet]尚未儲存變更![]\n您確定要退出嗎? +editor.resizemap = 調整地圖大小 +editor.mapname = 地圖名稱: +editor.overwrite = [accent]警告!這將會覆蓋現有的地圖。 +editor.overwrite.confirm = [scarlet]警告![]同名地圖存在,確定要覆蓋現有地圖? +editor.selectmap = 選取要載入的地圖: +width = 寬度: +height = 長度: +menu = 主選單 +play = 開始 +load = 載入 +save = 儲存 +fps = FPS:{0} +tps = TPS:{0} +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 = 發射成功 +zone.unlocked = [LIGHT_GRAY]{0}已解鎖。 +launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. +connectfail = [crimson]無法連線到伺服器:[accent]{0} +error.unreachable = 無法到達伺服器。 +error.invalidaddress = 無效地址。 +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 = 重新綁定 +settings.controls = 操作 +settings.game = 遊戲 +settings.sound = 音效 +settings.graphics = 圖形 +settings.cleardata = 清除遊戲數據…… +settings.clear.confirm = 您確定要清除數據嗎?\n此操作無法撤回! +settings.clearall.confirm = [scarlet]警告![]\n這將清除所有數據,包括存檔、地圖、解鎖和熱鍵綁定。\n按「是」後,遊戲將刪除所有數據並自動退出。 +settings.clearunlocks = 清除已解鎖 +settings.clearall = 清除所有 +paused = [accent]〈已暫停〉 +yes = 是 +no = 否 +info.title = [accent]資訊 +error.title = [crimson]發生錯誤 +error.crashtitle = 發生錯誤 +blocks.unknown = [LIGHT_GRAY]??? +blocks.blockinfo = 方塊資訊 +blocks.powercapacity = 蓄電量 +blocks.powershot = 能量/射擊 +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.liquid = Liquid +blocks.coolantuse = 使用冷卻劑 +blocks.inputliquidfuel = 輸入液體燃料 +blocks.liquidfueluse = 使用液體燃料速度 +blocks.boostitem = 強化物品 +blocks.boostliquid = 強化液體 +blocks.health = 耐久度 +blocks.power = Power +blocks.power.satisfaction = Power Satisfaction +blocks.inaccuracy = 誤差 +blocks.shots = 射擊數 +blocks.reload = 重裝彈藥 +blocks.inputfuel = 燃料 +blocks.fuelburntime = 燃燒燃料時間 +blocks.inputcapacity = 輸入容量 +blocks.outputcapacity = 輸出容量 +unit.blocks = 方塊 +unit.powersecond = 能量單位/秒 +unit.liquidsecond = 液體單位/秒 +unit.itemssecond = 物品/秒 +unit.pixelssecond = 像素/秒 +unit.liquidunits = 液體單位 +unit.powerunits = 能量單位 +unit.degrees = 度 +unit.seconds = 秒 +unit.items = 物品 +category.general = 一般 +category.power = 能量 +category.liquids = 液體 +category.items = 物品 +category.crafting = 合成 +category.shooting = 射擊 +category.optional = 可選的強化 setting.indicators.name = 盟友指標 setting.autotarget.name = 自動射擊 setting.fpscap.name = 最大FPS @@ -377,19 +379,22 @@ setting.mutemusic.name = 靜音 setting.sfxvol.name = 音效音量 setting.mutesound.name = 靜音 setting.crashreport.name = 發送匿名崩潰報告 -text.keybind.title = 重新綁定按鍵 +keybind.title = 重新綁定按鍵 category.general.name = 一般 category.view.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 = 水平移動 keybind.move_y.name = 垂直移動 keybind.select.name = 選取 +keybind.pick.name = Pick Block keybind.break.name = 拆除 keybind.deselect.name = 取消選取 keybind.shoot.name = 射擊 @@ -408,9 +413,9 @@ keybind.chat_history_next.name = 之後的聊天記錄 keybind.chat_scroll.name = 聊天記錄滾動 keybind.drop_unit.name = 放下單位 keybind.zoom_minimap.name = 縮放小地圖 -mode.text.help.title = 模式說明 -mode.waves.name = 一般 -mode.waves.description = 一般模式,有限的資源與自動來襲的波次。 +mode.help.title = 模式說明 +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 +423,19 @@ mode.freebuild.description = 有限的資源,與不倒數計時的波次。 mode.pvp.name = 對戰 mode.pvp.description = 和其他玩家鬥爭。 mode.attack.name = 攻擊 -mode.attack.description = 沒有波次,目標是摧毀敵人的基地。 +mode.attack.descrption = 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 = 釷 @@ -454,6 +456,10 @@ 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.oil.name = 原油 @@ -487,24 +493,29 @@ mech.trident-ship.weapon = 炸彈 mech.glaive-ship.name = 長柄 mech.glaive-ship.description = 一種大型、裝甲厚的武裝直升機。配備燃燒機關槍。有優秀的加速能力與最快的速度。 mech.glaive-ship.weapon = 火焰機關槍 -text.item.explosiveness = [LIGHT_GRAY]爆炸性:{0} -text.item.flammability = [LIGHT_GRAY]易燃性:{0} -text.item.radioactivity = [LIGHT_GRAY]放射性:{0} -text.item.fluxiness = [LIGHT_GRAY]助熔性:{0} -text.unit.health = [LIGHT_GRAY]耐久度:{0} -text.unit.speed = [LIGHT_GRAY]速度:{0} -text.mech.weapon = [LIGHT_GRAY]武器:{0} -text.mech.armor = [LIGHT_GRAY]裝甲:{0} -text.mech.itemcapacity = [LIGHT_GRAY]物品容量:{0} -text.mech.minespeed = [LIGHT_GRAY]採礦速度:{0} -text.mech.minepower = [LIGHT_GRAY]採礦力度:{0} -text.mech.ability = [LIGHT_GRAY]能力:{0} -text.liquid.heatcapacity = [LIGHT_GRAY]熱容量:{0} -text.liquid.viscosity = [LIGHT_GRAY]粘性:{0} -text.liquid.temperature = [LIGHT_GRAY]温度:{0} +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]Health: {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.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.core-shard.name = Core: Shard +block.core-foundation.name = Core: Foundation +block.core-nucleus.name = Core: Nucleus block.metalfloor.name = 金屬地板 block.deepwater.name = 深水 block.water.name = 水 @@ -523,8 +534,8 @@ block.blackrock.name = 黑岩石 block.icerock.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 = Titanium Wall +block.titanium-wall-large.name = Large Titanium Wall block.phase-wall.name = 相織布牆 block.phase-wall-large.name = 大型相織布牆 block.thorium-wall.name = 釷牆 @@ -557,17 +568,19 @@ 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 = 三叉船墊 @@ -576,11 +589,11 @@ block.omega-mech-pad.name = 奧米伽機甲墊 block.tau-mech-pad.name = Tau機甲墊 block.conduit.name = 管線 block.mechanical-pump.name = 機械泵 -block.itemsource.name = 物品源 -block.itemvoid.name = 物品虚 -block.liquidsource.name = 液體源 -block.powervoid.name = 能量空虛 -block.powerinfinite.name = 無限能量 +block.item-source.name = 物品源 +block.item-void.name = 物品虚 +block.liquid-source.name = 液體源 +block.power-void.name = 能量空虛 +block.power-source.name = 無限能量 block.unloader.name = 裝卸器 block.vault.name = 存儲庫 block.wave.name = 波浪炮 @@ -633,6 +646,7 @@ block.spectre.name = 幽靈炮 block.meltdown.name = 熔毀炮 block.container.name = 容器 block.core.description = 遊戲中最重要的建築。 +block.launch-pad.name = 發射台 team.blue.name = 藍 team.red.name = 紅 team.orange.name = 橙 @@ -646,6 +660,7 @@ 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 +670,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製作一條從鑽頭開始到核心的輸送帶。 @@ -778,11 +797,11 @@ block.router.description = 接受來自一個方向的物品並將它們平均 block.distributor.description = 高級的分配器,可將物品均分到最多7個其他方向。 block.bridge-conveyor.description = 高級的物品運輸方塊。允許跨過最多3個任何地形或建築物的方塊運輸物品。 block.alpha-mech-pad.description = 當給予足夠能量時,將你的船重建為[accent]阿爾法[]機甲。 -block.itemsource.description = 不限地輸出物品。僅限沙盒。 -block.liquidsource.description = 不限地輸出液體。僅限沙盒。 -block.itemvoid.description = 不使用能量銷毀任何進入它的物品。僅限沙盒。 -block.powerinfinite.description = 不限地輸出能量。僅限沙盒。 -block.powervoid.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 = 可以轉換為[LIGHT_GRAY]石頭[]、用於發電或用作某些砲塔的彈藥。 liquid.oil.description = 可以燃燒、爆炸或用作冷卻劑。 diff --git a/core/assets/cursors/ibar.png b/core/assets/cursors/ibeam.png similarity index 100% rename from core/assets/cursors/ibar.png rename to core/assets/cursors/ibeam.png diff --git a/core/assets/maps/craters.mmap b/core/assets/maps/craters.mmap new file mode 100644 index 0000000000..b3a6e5432d Binary files /dev/null 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..130da8e7a2 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 new file mode 100644 index 0000000000..b73cd867af Binary files /dev/null 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..0451d04b2a 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..ad90b921fd 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..3f3ab56c34 Binary files /dev/null and b/core/assets/maps/ruinousShores.mmap differ diff --git a/core/assets/maps/sandbox.mmap b/core/assets/maps/sandbox.mmap deleted file mode 100644 index 14e89ed3b7..0000000000 Binary files a/core/assets/maps/sandbox.mmap and /dev/null 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 f79b58b3c0..858018291f 100644 --- a/core/assets/shaders/blockbuild.fragment +++ b/core/assets/shaders/blockbuild.fragment @@ -22,17 +22,13 @@ 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) || id(T + vec2(step, 0) * v, base) || id(T + vec2(-step, 0) * v, base)); } -float rand(vec2 co){ - return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); -} - void main() { vec2 t = v_texCoord.xy; @@ -45,17 +41,12 @@ 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)) && rand(coords) < chance){ + 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; - }else if((dst + 1.0 > (1.0-u_progress) * (center.x)) && color.a > 0.1 && rand(coords) < chance){ + }else if((dst + 1.0 > (1.0-u_progress) * (center.x)) && color.a > 0.1){ gl_FragColor = u_color; }else{ gl_FragColor = vec4(0.0); diff --git a/core/assets/shaders/build.fragment b/core/assets/shaders/build.fragment index 1762a407be..a5bd5c05f1 100644 --- a/core/assets/shaders/build.fragment +++ b/core/assets/shaders/build.fragment @@ -29,18 +29,11 @@ void main() { vec4 c = texture2D(u_texture, v_texCoord.xy); - vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y); - float step = 1.0; - - bool outline = texture2D(u_texture, t).a < 0.1 && - (id(texture2D(u_texture, t + vec2(0, step) * v)) || id(texture2D(u_texture, t + vec2(0, -step) * v)) || - id(texture2D(u_texture, t + vec2(step, 0) * v)) || id(texture2D(u_texture, t + vec2(-step, 0) * v))); - if(1.0-abs(coords.x - 0.5)*2.0 < 1.0-u_progress){ c = vec4(0.0); } - if(c.a > 0.01 || outline){ + if(c.a > 0.01){ float f = abs(sin(coords.x*2.0 + u_time)); if(f > 0.9 ) f = 1.0; diff --git a/core/assets/shaders/cache.vertex b/core/assets/shaders/cache.vertex new file mode 100644 index 0000000000..058b8888ef --- /dev/null +++ b/core/assets/shaders/cache.vertex @@ -0,0 +1,14 @@ +attribute vec4 a_position; +attribute vec4 a_color; +attribute vec2 a_texCoord0; +uniform mat4 u_projectionViewMatrix; +varying vec4 v_color; +varying vec2 v_texCoords; + +void main() +{ + v_color = a_color; + v_color.a = v_color.a * (255.0/254.0); + v_texCoords = a_texCoord0; + gl_Position = u_projectionViewMatrix * a_position; +} \ No newline at end of file diff --git a/core/assets/shaders/fog.fragment b/core/assets/shaders/fog.fragment index 8955cc9665..ea94aa2f5a 100644 --- a/core/assets/shaders/fog.fragment +++ b/core/assets/shaders/fog.fragment @@ -5,18 +5,13 @@ precision mediump int; uniform sampler2D u_texture; -const float round = 0.23; +const float round = 0.01; 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/menu.fragment b/core/assets/shaders/menu.fragment index 397cf6dbc9..1d793559ca 100644 --- a/core/assets/shaders/menu.fragment +++ b/core/assets/shaders/menu.fragment @@ -7,6 +7,7 @@ precision mediump int; #define p2 vec3(234.0,182.0,120.0)/255.0 #define p3 vec3(212.0,129.0,107.0)/255.0 #define p4 vec3(142.0,77.0,72.0)/255.0 +#define roundm 0.2 uniform sampler2D u_texture; uniform vec2 u_resolution; @@ -21,12 +22,11 @@ varying vec2 v_texCoord; void main() { ivec2 coords = ivec2((gl_FragCoord.xy - u_resolution/2.0)/u_scl); - int roundx = 8; - int roundy = roundx; - float roundm = 0.2; + //int roundx = 8; + //int roundy = roundx; - coords.x = (coords.x / roundx) * roundx; - coords.y = (coords.y / roundy) * roundy; + //coords.x = (coords.x / roundx) * roundx; + //coords.y = (coords.y / roundy) * roundy; float d = (abs(float(coords.x)) - abs(float(coords.y))); diff --git a/core/assets/shaders/outline.fragment b/core/assets/shaders/outline.fragment index 46f6f6872d..09a9a4e041 100644 --- a/core/assets/shaders/outline.fragment +++ b/core/assets/shaders/outline.fragment @@ -3,12 +3,13 @@ precision mediump float; precision mediump int; #endif -#define SPACE 1.0 +#define SPACE 2.0 uniform sampler2D u_texture; uniform vec4 u_color; uniform vec2 u_texsize; +uniform float u_scl; varying vec4 v_color; varying vec2 v_texCoord; @@ -17,11 +18,27 @@ void main() { vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y); vec4 c = texture2D(u_texture, v_texCoord.xy); + float spacing = SPACE * u_scl; gl_FragColor = mix(c * v_color, u_color, - (1.0-step(0.1, texture2D(u_texture, v_texCoord.xy).a)) * - step(0.1, texture2D(u_texture, v_texCoord.xy + vec2(0, SPACE) * v).a + - texture2D(u_texture, v_texCoord.xy + vec2(0, -SPACE) * v).a + - texture2D(u_texture, v_texCoord.xy + vec2(SPACE, 0) * v).a + - texture2D(u_texture, v_texCoord.xy + vec2(-SPACE, 0) * v).a)); + (1.0-step(0.001, texture2D(u_texture, v_texCoord.xy).a)) * + step(0.001, + //cardinals + texture2D(u_texture, v_texCoord.xy + vec2(0, spacing) * v).a + + texture2D(u_texture, v_texCoord.xy + vec2(0, -spacing) * v).a + + texture2D(u_texture, v_texCoord.xy + vec2(spacing, 0) * v).a + + texture2D(u_texture, v_texCoord.xy + vec2(-spacing, 0) * v).a + + + //cardinal edges + texture2D(u_texture, v_texCoord.xy + vec2(spacing, spacing) * v).a + + texture2D(u_texture, v_texCoord.xy + vec2(spacing, -spacing) * v).a + + texture2D(u_texture, v_texCoord.xy + vec2(-spacing, spacing) * v).a + + texture2D(u_texture, v_texCoord.xy + vec2(-spacing, -spacing) * v).a + + + //cardinals * 2 + texture2D(u_texture, v_texCoord.xy + vec2(0, spacing) * v*2.0).a + + texture2D(u_texture, v_texCoord.xy + vec2(0, -spacing) * v*2.0).a + + 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 + )); } diff --git a/core/assets/shaders/shadow.fragment b/core/assets/shaders/shadow.fragment new file mode 100644 index 0000000000..b1d73a8b1f --- /dev/null +++ b/core/assets/shaders/shadow.fragment @@ -0,0 +1,44 @@ +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + +#define SPACE 2.0 + +uniform sampler2D u_texture; + +uniform vec4 u_color; +uniform vec2 u_texsize; +uniform float u_scl; + +varying vec4 v_color; +varying vec2 v_texCoord; + +void main() { + vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y); + + vec4 c = texture2D(u_texture, v_texCoord.xy); + float spacing = SPACE * u_scl; + + 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 + texture2D(u_texture, v_texCoord.xy + vec2(0, spacing) * v).a + + texture2D(u_texture, v_texCoord.xy + vec2(0, -spacing) * v).a + + texture2D(u_texture, v_texCoord.xy + vec2(spacing, 0) * v).a + + texture2D(u_texture, v_texCoord.xy + vec2(-spacing, 0) * v).a + + + //cardinal edges + texture2D(u_texture, v_texCoord.xy + vec2(spacing, spacing) * v).a + + texture2D(u_texture, v_texCoord.xy + vec2(spacing, -spacing) * v).a + + texture2D(u_texture, v_texCoord.xy + vec2(-spacing, spacing) * v).a + + texture2D(u_texture, v_texCoord.xy + vec2(-spacing, -spacing) * v).a + + + //cardinals * 2 + texture2D(u_texture, v_texCoord.xy + vec2(0, spacing) * v*2.0).a + + texture2D(u_texture, v_texCoord.xy + vec2(0, -spacing) * v*2.0).a + + 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 + )); +} diff --git a/core/assets/shaders/water.fragment b/core/assets/shaders/water.fragment index d8f26bebb1..172725177b 100644 --- a/core/assets/shaders/water.fragment +++ b/core/assets/shaders/water.fragment @@ -1,90 +1,18 @@ #ifdef GL_ES -precision highp float; -precision mediump int; +precision mediump float; #endif +varying vec4 v_color; +varying vec2 v_texCoords; uniform sampler2D u_texture; +uniform float u_time; -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; +float round(float f, float v){ + return float(int(f / v)) * v; } -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) * 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)); - - 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; - } - } - - gl_FragColor = color; -} +void main(){ + vec2 r = v_texCoords.xy; + vec4 c = v_color * texture2D(u_texture, v_texCoords.xy); + gl_FragColor = c * vec4(vec3(round(1.0 + sin((r.x + r.y) * 404.0 + u_time / 20.0) / 10.0, 0.05)), 1.0); +} \ No newline at end of file diff --git a/core/assets/sprites/block_colors.png b/core/assets/sprites/block_colors.png new file mode 100644 index 0000000000..94b5e2d2a9 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 9a52df3e11..b704a47f15 100644 --- a/core/assets/sprites/sprites.atlas +++ b/core/assets/sprites/sprites.atlas @@ -1,5283 +1,8513 @@ sprites.png -size: 1024,512 +size: 2048,2048 format: RGBA8888 filter: Nearest,Nearest repeat: none +force-projector + rotate: false + xy: 1847, 1593 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 force-projector-top rotate: false - xy: 392, 312 - size: 24, 24 - orig: 24, 24 + xy: 453, 1214 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +mend-projector + rotate: false + xy: 771, 807 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 mend-projector-top rotate: false - xy: 530, 378 - size: 16, 16 - orig: 16, 16 + xy: 705, 741 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +overdrive-projector + rotate: false + xy: 771, 741 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 overdrive-projector-top rotate: false - xy: 512, 342 - size: 16, 16 - orig: 16, 16 + xy: 705, 675 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +shock-mine + rotate: false + xy: 1391, 205 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conveyor + rotate: false + xy: 1213, 480 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-bridge rotate: false - xy: 84, 108 - size: 8, 8 - orig: 8, 8 + xy: 1247, 477 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-end rotate: false - xy: 124, 138 - size: 8, 8 - orig: 8, 8 + xy: 1281, 477 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-0-0 + rotate: false + xy: 1017, 206 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-1 rotate: false - xy: 124, 98 - size: 8, 8 - orig: 8, 8 + xy: 1017, 172 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-2 rotate: false - xy: 174, 138 - size: 8, 8 - orig: 8, 8 + xy: 1055, 274 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-3 rotate: false - xy: 164, 128 - size: 8, 8 - orig: 8, 8 + xy: 1051, 240 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-0 rotate: false - xy: 154, 118 - size: 8, 8 - orig: 8, 8 + xy: 1051, 206 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-1 rotate: false - xy: 144, 108 - size: 8, 8 - orig: 8, 8 + xy: 1051, 172 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-2 rotate: false - xy: 134, 98 - size: 8, 8 - orig: 8, 8 + xy: 1063, 308 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-3 rotate: false - xy: 184, 138 - size: 8, 8 - orig: 8, 8 + xy: 1089, 274 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-0 rotate: false - xy: 174, 128 - size: 8, 8 - orig: 8, 8 + xy: 1085, 240 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-1 rotate: false - xy: 164, 118 - size: 8, 8 - orig: 8, 8 + xy: 1085, 206 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-2 rotate: false - xy: 154, 108 - size: 8, 8 - orig: 8, 8 + xy: 1085, 172 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-3 rotate: false - xy: 144, 98 - size: 8, 8 - orig: 8, 8 + xy: 745, 143 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-0 rotate: false - xy: 184, 128 - size: 8, 8 - orig: 8, 8 + xy: 779, 143 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-1 rotate: false - xy: 174, 118 - size: 8, 8 - orig: 8, 8 + xy: 813, 143 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-2 rotate: false - xy: 164, 108 - size: 8, 8 - orig: 8, 8 + xy: 847, 143 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-3 rotate: false - xy: 154, 98 - size: 8, 8 - orig: 8, 8 + xy: 881, 143 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-0 rotate: false - xy: 184, 118 - size: 8, 8 - orig: 8, 8 + xy: 1245, 362 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-1 rotate: false - xy: 174, 108 - size: 8, 8 - orig: 8, 8 + xy: 1067, 346 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-2 rotate: false - xy: 164, 98 - size: 8, 8 - orig: 8, 8 + xy: 1101, 333 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-3 rotate: false - xy: 184, 108 - size: 8, 8 - orig: 8, 8 + xy: 1135, 333 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-0-0 + rotate: false + xy: 1531, 275 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-1 rotate: false - xy: 93, 39 - size: 8, 8 - orig: 8, 8 + xy: 1565, 275 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-2 rotate: false - xy: 103, 38 - size: 8, 8 - orig: 8, 8 + xy: 1599, 275 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-3 rotate: false - xy: 113, 38 - size: 8, 8 - orig: 8, 8 + xy: 1633, 275 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-0 rotate: false - xy: 123, 38 - size: 8, 8 - orig: 8, 8 + xy: 1667, 275 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-1 rotate: false - xy: 133, 38 - size: 8, 8 - orig: 8, 8 + xy: 1493, 241 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-2 rotate: false - xy: 143, 38 - size: 8, 8 - orig: 8, 8 + xy: 1493, 207 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-3 rotate: false - xy: 153, 38 - size: 8, 8 - orig: 8, 8 + xy: 1527, 241 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-0 rotate: false - xy: 163, 38 - size: 8, 8 - orig: 8, 8 + xy: 1493, 173 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-1 rotate: false - xy: 173, 38 - size: 8, 8 - orig: 8, 8 + xy: 1527, 207 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-2 rotate: false - xy: 183, 38 - size: 8, 8 - orig: 8, 8 + xy: 1561, 241 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-3 rotate: false - xy: 91, 29 - size: 8, 8 - orig: 8, 8 + xy: 1493, 139 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-0 rotate: false - xy: 91, 19 - size: 8, 8 - orig: 8, 8 + xy: 1527, 173 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-1 rotate: false - xy: 91, 9 - size: 8, 8 - orig: 8, 8 + xy: 1561, 207 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-2 rotate: false - xy: 101, 28 - size: 8, 8 - orig: 8, 8 + xy: 1595, 241 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-3 rotate: false - xy: 101, 18 - size: 8, 8 - orig: 8, 8 + xy: 1493, 105 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-0 rotate: false - xy: 111, 28 - size: 8, 8 - orig: 8, 8 + xy: 1527, 139 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-1 rotate: false - xy: 111, 18 - size: 8, 8 - orig: 8, 8 + xy: 1561, 173 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-2 rotate: false - xy: 121, 28 - size: 8, 8 - orig: 8, 8 + xy: 1595, 207 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-3 rotate: false - xy: 121, 18 - size: 8, 8 - orig: 8, 8 + xy: 1629, 241 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -mass-driver-turret +distributor rotate: false - xy: 778, 427 - size: 24, 24 - orig: 24, 24 + xy: 389, 45 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +junction + rotate: false + xy: 1869, 1021 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mass-driver-base + rotate: false + xy: 965, 1495 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +overflow-gate + rotate: false + xy: 657, 105 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conveyor + rotate: false + xy: 691, 105 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-arrow rotate: false - xy: 457, 220 - size: 8, 8 - orig: 8, 8 + xy: 691, 71 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-bridge rotate: false - xy: 467, 240 - size: 8, 8 - orig: 8, 8 + xy: 691, 37 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-end rotate: false - xy: 467, 230 - size: 8, 8 - orig: 8, 8 + xy: 589, 3 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -warp-gate +router rotate: false - xy: 934, 427 - size: 24, 24 - orig: 24, 24 + xy: 1283, 409 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -warp-gate-top +sorter rotate: false - xy: 960, 453 - size: 24, 24 - orig: 24, 24 + xy: 1415, 391 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 blast-drill rotate: false - xy: 39, 17 - size: 24, 24 - orig: 24, 24 + xy: 323, 1376 + size: 128, 128 + orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rim rotate: false - xy: 622, 458 - size: 24, 24 - orig: 24, 24 + xy: 323, 1246 + size: 128, 128 + orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rotator rotate: false - xy: 648, 461 - size: 24, 24 - orig: 24, 24 + xy: 323, 1116 + size: 128, 128 + orig: 128, 128 offset: 0, 0 index: -1 blast-drill-top rotate: false - xy: 288, 372 - size: 24, 24 - orig: 24, 24 + xy: 526, 1821 + size: 128, 128 + orig: 128, 128 offset: 0, 0 index: -1 laser-drill rotate: false - xy: 531, 252 - size: 16, 16 - orig: 16, 16 + xy: 649, 1365 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +laser-drill-rim + rotate: false + xy: 747, 1365 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 laser-drill-rotator rotate: false - xy: 512, 396 - size: 16, 16 - orig: 16, 16 + xy: 649, 1267 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 laser-drill-top rotate: false - xy: 512, 378 - size: 16, 16 - orig: 16, 16 + xy: 747, 1267 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 mechanical-drill rotate: false - xy: 530, 396 - size: 16, 16 - orig: 16, 16 + xy: 639, 741 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-rotator rotate: false - xy: 512, 360 - size: 16, 16 - orig: 16, 16 + xy: 705, 807 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-top rotate: false - xy: 548, 396 - size: 16, 16 - orig: 16, 16 + xy: 639, 675 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 oil-extractor rotate: false - xy: 804, 453 - size: 24, 24 - orig: 24, 24 + xy: 1259, 1495 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-liquid rotate: false - xy: 804, 427 - size: 24, 24 - orig: 24, 24 + xy: 1455, 1495 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-rotator rotate: false - xy: 830, 453 - size: 24, 24 - orig: 24, 24 + xy: 1553, 1495 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-top rotate: false - xy: 830, 427 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -plasma-drill - rotate: false - xy: 269, 398 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -plasma-drill-rim - rotate: false - xy: 303, 435 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -plasma-drill-rotator - rotate: false - xy: 303, 401 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -plasma-drill-top - rotate: false - xy: 254, 364 - size: 32, 32 - orig: 32, 32 + xy: 1651, 1495 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 pneumatic-drill rotate: false - xy: 566, 378 - size: 16, 16 - orig: 16, 16 + xy: 1509, 1297 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-rotator rotate: false - xy: 548, 360 - size: 16, 16 - orig: 16, 16 + xy: 1641, 1297 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-top rotate: false - xy: 602, 396 - size: 16, 16 - orig: 16, 16 + xy: 1707, 1297 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 water-extractor rotate: false - xy: 554, 270 - size: 16, 16 - orig: 16, 16 + xy: 1459, 1091 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 water-extractor-liquid rotate: false - xy: 549, 252 - size: 16, 16 - orig: 16, 16 + xy: 1459, 959 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 water-extractor-rotator rotate: false - xy: 584, 324 - size: 16, 16 - orig: 16, 16 + xy: 1393, 893 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 water-extractor-top rotate: false - xy: 582, 306 - size: 16, 16 - orig: 16, 16 + xy: 1459, 893 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 -blackrock1 +char1 rotate: false - xy: 672, 353 - size: 8, 8 - orig: 8, 8 + xy: 1315, 477 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -block-icon-blackrock +char2 rotate: false - xy: 672, 353 - size: 8, 8 - orig: 8, 8 + xy: 1349, 477 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -blackrockshadow1 +char3 rotate: false - xy: 684, 365 - size: 8, 8 - orig: 8, 8 + xy: 1383, 493 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -blackstone1 +cliffs1 rotate: false - xy: 708, 389 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-blackstone - rotate: false - xy: 708, 389 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -blackstone2 - rotate: false - xy: 672, 343 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -blackstone3 - rotate: false - xy: 1012, 437 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -blackstoneedge - rotate: false - xy: 288, 332 - size: 12, 12 - orig: 12, 12 + xy: 1417, 493 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 coal1 rotate: false - xy: 114, 128 - size: 8, 8 - orig: 8, 8 + xy: 1383, 459 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 coal2 rotate: false - xy: 104, 118 - size: 8, 8 - orig: 8, 8 + xy: 1417, 459 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 coal3 rotate: false - xy: 94, 108 - size: 8, 8 - orig: 8, 8 + xy: 1215, 396 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 copper1 rotate: false - xy: 174, 98 - size: 8, 8 - orig: 8, 8 + xy: 1169, 328 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 copper2 rotate: false - xy: 184, 98 - size: 8, 8 - orig: 8, 8 + xy: 1203, 328 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 copper3 rotate: false - xy: 84, 88 - size: 8, 8 - orig: 8, 8 + xy: 1237, 328 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -dirt2 +craters1 rotate: false - xy: 154, 88 - size: 8, 8 - orig: 8, 8 + xy: 1157, 294 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -dirt3 +craters2 rotate: false - xy: 164, 88 - size: 8, 8 - orig: 8, 8 + xy: 1191, 294 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -dirtedge +craters3 rotate: false - xy: 634, 278 - size: 12, 12 - orig: 12, 12 + xy: 1225, 294 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -generic-cliff-edge +craters4 rotate: false - xy: 103, 78 - size: 8, 8 - orig: 8, 8 + xy: 1157, 260 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -ice-cliff-edge +craters5 rotate: false - xy: 103, 78 - size: 8, 8 - orig: 8, 8 + xy: 1191, 260 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -generic-cliff-edge-1 +stone1 rotate: false - xy: 83, 48 - size: 8, 8 - orig: 8, 8 + xy: 1191, 260 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -ice-cliff-edge-1 +craters6 rotate: false - xy: 83, 48 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -generic-cliff-edge-2 - rotate: false - xy: 93, 59 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ice-cliff-edge-2 - rotate: false - xy: 93, 59 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -generic-cliff-side - rotate: false - xy: 103, 68 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ice-cliff-side - rotate: false - xy: 103, 68 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -grass-cliff-edge - rotate: false - xy: 103, 58 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -grass-cliff-edge-1 - rotate: false - xy: 113, 68 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -grass-cliff-edge-2 - rotate: false - xy: 123, 78 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -grass-cliff-side - rotate: false - xy: 113, 58 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -grass2 - rotate: false - xy: 113, 78 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -grass3 - rotate: false - xy: 93, 49 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -grassedge - rotate: false - xy: 585, 256 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -ice2 - rotate: false - xy: 133, 78 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ice3 - rotate: false - xy: 123, 58 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -iceedge - rotate: false - xy: 620, 264 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -icerock2 - rotate: false - xy: 133, 68 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -icerockshadow1 - rotate: false - xy: 143, 78 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -rockshadow1 - rotate: false - xy: 143, 78 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -icerockshadow2 - rotate: false - xy: 133, 58 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -rockshadow2 - rotate: false - xy: 133, 58 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -lavaedge - rotate: false - xy: 585, 242 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -lead1 - rotate: false - xy: 183, 48 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -lead2 - rotate: false - xy: 1004, 395 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -lead3 - rotate: false - xy: 1004, 385 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -metalfloor2 - rotate: false - xy: 694, 365 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -metalfloor3 - rotate: false - xy: 708, 379 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -metalfloor4 - rotate: false - xy: 740, 379 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -metalfloor5 - rotate: false - xy: 682, 353 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -metalfloor6 - rotate: false - xy: 682, 343 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -metalflooredge - rotate: false - xy: 641, 250 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -rock2 - rotate: false - xy: 497, 222 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -sand2 - rotate: false - xy: 517, 232 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -sand3 - rotate: false - xy: 507, 222 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -sandedge - rotate: false - xy: 599, 236 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -shrubshadow - rotate: false - xy: 557, 232 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -snow2 - rotate: false - xy: 547, 222 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -snow3 - rotate: false - xy: 567, 242 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -snowedge - rotate: false - xy: 627, 236 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -spaceedge - rotate: false - xy: 641, 236 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -stone-cliff-edge - rotate: false - xy: 204, 122 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -stone-cliff-edge-1 - rotate: false - xy: 204, 112 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -stone-cliff-edge-2 - rotate: false - xy: 204, 102 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -stone-cliff-side - rotate: false - xy: 204, 92 - size: 8, 8 - orig: 8, 8 + xy: 1225, 260 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 stone2 rotate: false - xy: 205, 142 - size: 8, 8 - orig: 8, 8 + xy: 1225, 260 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +deepwater + rotate: false + xy: 1221, 226 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +differential-generator + rotate: false + xy: 1651, 1593 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +differential-generator-top + rotate: false + xy: 1749, 1593 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +dunerocks-large + rotate: false + xy: 931, 971 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dunerocks1 + rotate: false + xy: 1255, 226 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dunerocks2 + rotate: false + xy: 1255, 192 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +edge-stencil-blocky + rotate: false + xy: 1, 799 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +edge-stencil-smooth + rotate: false + xy: 1, 701 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +grass1 + rotate: false + xy: 1323, 158 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass2 + rotate: false + xy: 983, 139 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass3 + rotate: false + xy: 1017, 138 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone1 + rotate: false + xy: 1119, 129 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone2 + rotate: false + xy: 1153, 124 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone3 + rotate: false + xy: 1187, 124 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock1 + rotate: false + xy: 1221, 124 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock2 + rotate: false + xy: 1255, 124 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock3 + rotate: false + xy: 1289, 124 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-edge + rotate: false + xy: 1, 505 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +ice-snow1 + rotate: false + xy: 1699, 1063 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow2 + rotate: false + xy: 1699, 1029 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow3 + rotate: false + xy: 1699, 995 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice1 + rotate: false + xy: 1323, 124 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice2 + rotate: false + xy: 1699, 1131 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice3 + rotate: false + xy: 1699, 1097 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icerocks-large + rotate: false + xy: 1641, 1363 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +icerocks1 + rotate: false + xy: 1451, 427 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icerocks2 + rotate: false + xy: 1485, 427 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock1 + rotate: false + xy: 1553, 411 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock2 + rotate: false + xy: 1587, 411 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock3 + rotate: false + xy: 1621, 411 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lead1 + rotate: false + xy: 1971, 1033 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lead2 + rotate: false + xy: 1903, 999 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lead3 + rotate: false + xy: 1937, 999 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock1 + rotate: false + xy: 1809, 953 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock2 + rotate: false + xy: 1775, 919 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock3 + rotate: false + xy: 1843, 953 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor + rotate: false + xy: 1911, 931 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged5 + rotate: false + xy: 1911, 931 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-2 + rotate: false + xy: 1979, 965 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-3 + rotate: false + xy: 1945, 931 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-5 + rotate: false + xy: 1979, 931 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged1 + rotate: false + xy: 2013, 965 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged2 + rotate: false + xy: 2013, 931 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged3 + rotate: false + xy: 1877, 897 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged4 + rotate: false + xy: 1911, 897 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged6 + rotate: false + xy: 1945, 897 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pine + rotate: false + xy: 725, 109 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rock1 + rotate: false + xy: 1737, 641 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rock2 + rotate: false + xy: 1737, 591 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rocks-large + rotate: false + xy: 1311, 1265 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rocks1 + rotate: false + xy: 1283, 443 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rocks2 + rotate: false + xy: 1317, 443 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-water + rotate: false + xy: 1327, 307 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand1 + rotate: false + xy: 1305, 341 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand2 + rotate: false + xy: 1339, 341 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand3 + rotate: false + xy: 1347, 375 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap1 + rotate: false + xy: 1327, 273 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap2 + rotate: false + xy: 1361, 307 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap3 + rotate: false + xy: 1361, 273 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow1 + rotate: false + xy: 1425, 239 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow2 + rotate: false + xy: 1425, 205 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow3 + rotate: false + xy: 1425, 171 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrocks-large + rotate: false + xy: 997, 956 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +snowrocks1 + rotate: false + xy: 1425, 137 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrocks2 + rotate: false + xy: 1425, 103 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-cluster1 + rotate: false + xy: 987, 338 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-cluster2 + rotate: false + xy: 1029, 380 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-cluster3 + rotate: false + xy: 1071, 422 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +stained-boulder1 + rotate: false + xy: 1551, 377 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-boulder2 + rotate: false + xy: 1585, 377 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks-large + rotate: false + xy: 1129, 1022 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +stained-rocks-red-large + rotate: false + xy: 1129, 956 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +stained-rocks-red1 + rotate: false + xy: 1687, 377 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks-red2 + rotate: false + xy: 1721, 355 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks-yellow-large + rotate: false + xy: 1205, 1186 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +stained-rocks-yellow1 + rotate: false + xy: 1755, 355 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks-yellow2 + rotate: false + xy: 1789, 355 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks1 + rotate: false + xy: 1619, 377 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-rocks2 + rotate: false + xy: 1653, 377 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-red1 + rotate: false + xy: 1925, 319 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-red2 + rotate: false + xy: 1959, 319 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-red3 + rotate: false + xy: 1993, 319 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-yellow1 + rotate: false + xy: 1441, 357 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-yellow2 + rotate: false + xy: 1475, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone-yellow3 + rotate: false + xy: 1429, 323 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone1 + rotate: false + xy: 1823, 337 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone2 + rotate: false + xy: 1857, 337 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stained-stone3 + rotate: false + xy: 1891, 319 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stainedrocks-large + rotate: false + xy: 1173, 1120 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +stainedrocks1 + rotate: false + xy: 1429, 289 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stainedrocks2 + rotate: false + xy: 1463, 323 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 stone3 rotate: false - xy: 204, 132 - size: 8, 8 - orig: 8, 8 + xy: 1463, 289 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -stoneedge +tar rotate: false - xy: 655, 236 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -taredge - rotate: false - xy: 998, 433 - size: 12, 12 - orig: 12, 12 + xy: 1459, 119 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 thorium1 rotate: false - xy: 203, 72 - size: 8, 8 - orig: 8, 8 + xy: 1577, 343 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 thorium2 rotate: false - xy: 193, 52 - size: 8, 8 - orig: 8, 8 + xy: 1611, 343 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 thorium3 rotate: false - xy: 203, 62 - size: 8, 8 - orig: 8, 8 + xy: 1645, 343 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium1 rotate: false - xy: 203, 52 - size: 8, 8 - orig: 8, 8 + xy: 1633, 309 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium2 rotate: false - xy: 193, 42 - size: 8, 8 - orig: 8, 8 + xy: 1667, 309 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 titanium3 rotate: false - xy: 203, 42 - size: 8, 8 - orig: 8, 8 + xy: 1497, 275 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -water-cliff-edge +water rotate: false - xy: 131, 18 - size: 8, 8 - orig: 8, 8 + xy: 1629, 173 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -water-cliff-edge-1 +white-tree rotate: false - xy: 141, 28 - size: 8, 8 - orig: 8, 8 + xy: 1, 1317 + size: 320, 320 + orig: 320, 320 offset: 0, 0 index: -1 -water-cliff-edge-2 +white-tree-dead rotate: false - xy: 141, 18 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -water-cliff-side - rotate: false - xy: 151, 28 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -wateredge - rotate: false - xy: 1000, 349 - size: 12, 12 - orig: 12, 12 + xy: 1, 995 + size: 320, 320 + orig: 320, 320 offset: 0, 0 index: -1 block-border rotate: false - xy: 672, 323 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-elevation - rotate: false - xy: 662, 317 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -combustion-generator-top - rotate: false - xy: 662, 317 - size: 8, 8 - orig: 8, 8 + xy: 1177, 362 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 block-middle rotate: false - xy: 104, 138 - size: 8, 8 - orig: 8, 8 + xy: 1729, 457 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 pump-liquid rotate: false - xy: 104, 138 - size: 8, 8 - orig: 8, 8 + xy: 1729, 457 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -block-slope +block-select rotate: false - xy: 94, 128 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -border - rotate: false - xy: 84, 118 - size: 8, 8 - orig: 8, 8 + xy: 1763, 457 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-liquid rotate: false - xy: 144, 128 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -cross-1 - rotate: false - xy: 94, 88 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -cross-2 - rotate: false - xy: 950, 361 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -cross-3 - rotate: false - xy: 340, 312 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -cross-4 - rotate: false - xy: 949, 479 + xy: 1689, 445 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -nuclearreactor-shadow - rotate: false - xy: 499, 416 - size: 26, 26 - orig: 26, 26 - offset: 0, 0 - index: -1 place-arrow rotate: false - xy: 467, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ripples - rotate: false - xy: 684, 387 - size: 10, 10 - orig: 10, 10 + xy: 1847, 1495 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 rubble-1-0 rotate: false - xy: 528, 306 - size: 16, 16 - orig: 16, 16 + xy: 1905, 1267 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 rubble-1-1 rotate: false - xy: 584, 378 - size: 16, 16 - orig: 16, 16 + xy: 1971, 1267 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 rubble-2-0 rotate: false - xy: 548, 342 - size: 16, 16 - orig: 16, 16 + xy: 813, 609 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 rubble-2-1 rotate: false - xy: 566, 360 - size: 16, 16 - orig: 16, 16 + xy: 813, 543 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 rubble-3-0 rotate: false - xy: 882, 453 - size: 24, 24 - orig: 24, 24 + xy: 845, 1201 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 rubble-3-1 rotate: false - xy: 882, 453 - size: 24, 24 - orig: 24, 24 + xy: 845, 1201 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 -shadow-1 +rubble-4-0 rotate: false - xy: 684, 375 - size: 10, 10 - orig: 10, 10 + xy: 1566, 1691 + size: 128, 128 + orig: 128, 128 offset: 0, 0 index: -1 -shadow-2 +rubble-4-1 rotate: false - xy: 418, 316 - size: 18, 18 - orig: 18, 18 + xy: 1566, 1691 + size: 128, 128 + orig: 128, 128 offset: 0, 0 index: -1 -shadow-3 +spawn rotate: false - xy: 39, 71 - size: 26, 26 - orig: 26, 26 + xy: 1449, 393 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -shadow-4 +bridge-conduit rotate: false - xy: 53, 204 - size: 34, 34 - orig: 34, 34 - offset: 0, 0 - index: -1 -shadow-5 - rotate: false - xy: 290, 469 - size: 42, 42 - orig: 42, 42 - offset: 0, 0 - index: -1 -shadow-6 - rotate: false - xy: 1, 188 - size: 50, 50 - orig: 50, 50 - offset: 0, 0 - index: -1 -shadow-corner - rotate: false - xy: 672, 363 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -shadow-round-1 - rotate: false - xy: 696, 387 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -shadow-round-2 - rotate: false - xy: 438, 390 - size: 18, 18 - orig: 18, 18 - offset: 0, 0 - index: -1 -shadow-round-3 - rotate: false - xy: 39, 43 - size: 26, 26 - orig: 26, 26 - offset: 0, 0 - index: -1 -shadow-round-4 - rotate: false - xy: 675, 477 - size: 34, 34 - orig: 34, 34 - offset: 0, 0 - index: -1 -shadow-rounded-2 - rotate: false - xy: 438, 370 - size: 18, 18 - orig: 18, 18 - offset: 0, 0 - index: -1 -shadow-shock-mine - rotate: false - xy: 537, 222 - size: 8, 8 - orig: 8, 8 + xy: 1797, 457 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-arrow rotate: false - xy: 114, 138 - size: 8, 8 - orig: 8, 8 + xy: 555, 94 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-arrow rotate: false - xy: 114, 138 - size: 8, 8 - orig: 8, 8 + xy: 555, 94 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-bridge rotate: false - xy: 104, 128 - size: 8, 8 - orig: 8, 8 + xy: 555, 60 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-end rotate: false - xy: 94, 118 - size: 8, 8 - orig: 8, 8 + xy: 555, 26 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom rotate: false - xy: 104, 108 - size: 8, 8 - orig: 8, 8 + xy: 1831, 473 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-0 rotate: false - xy: 94, 98 - size: 8, 8 - orig: 8, 8 + xy: 1831, 439 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-1 rotate: false - xy: 144, 138 - size: 8, 8 - orig: 8, 8 + xy: 1451, 461 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-2 rotate: false - xy: 134, 128 - size: 8, 8 - orig: 8, 8 + xy: 1485, 461 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-3 rotate: false - xy: 124, 118 - size: 8, 8 - orig: 8, 8 + xy: 1519, 445 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-4 rotate: false - xy: 114, 108 - size: 8, 8 - orig: 8, 8 + xy: 1553, 445 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-5 rotate: false - xy: 104, 98 - size: 8, 8 - orig: 8, 8 + xy: 1587, 445 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-6 rotate: false - xy: 154, 138 - size: 8, 8 - orig: 8, 8 + xy: 1621, 445 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-top-0 rotate: false - xy: 134, 118 - size: 8, 8 - orig: 8, 8 + xy: 1723, 423 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-top-1 rotate: false - xy: 124, 108 - size: 8, 8 - orig: 8, 8 + xy: 1757, 423 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-top-2 rotate: false - xy: 114, 98 - size: 8, 8 - orig: 8, 8 + xy: 1791, 423 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-top-3 rotate: false - xy: 164, 138 - size: 8, 8 - orig: 8, 8 + xy: 1825, 405 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-top-4 rotate: false - xy: 154, 128 - size: 8, 8 - orig: 8, 8 + xy: 1859, 405 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-top-5 rotate: false - xy: 144, 118 - size: 8, 8 - orig: 8, 8 + xy: 1029, 308 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 conduit-top-6 rotate: false - xy: 134, 108 - size: 8, 8 - orig: 8, 8 + xy: 1021, 274 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-junction + rotate: false + xy: 2005, 1067 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 liquid-router-bottom rotate: false - xy: 1014, 367 - size: 8, 8 - orig: 8, 8 + xy: 2005, 999 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 liquid-router-liquid rotate: false - xy: 1014, 357 - size: 8, 8 - orig: 8, 8 + xy: 1741, 953 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 liquid-router-top rotate: false - xy: 1014, 347 - size: 8, 8 - orig: 8, 8 + xy: 1775, 987 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 liquid-tank-bottom rotate: false - xy: 726, 401 - size: 24, 24 - orig: 24, 24 + xy: 747, 1169 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-liquid rotate: false - xy: 752, 411 - size: 24, 24 - orig: 24, 24 + xy: 649, 1071 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-top rotate: false - xy: 778, 453 - size: 24, 24 - orig: 24, 24 + xy: 747, 1071 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +mechanical-pump + rotate: false + xy: 1877, 965 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conduit + rotate: false + xy: 623, 71 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-arrow rotate: false - xy: 457, 240 - size: 8, 8 - orig: 8, 8 + xy: 623, 37 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-bridge rotate: false - xy: 447, 220 - size: 8, 8 - orig: 8, 8 + xy: 657, 71 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-end rotate: false - xy: 457, 230 - size: 8, 8 - orig: 8, 8 + xy: 657, 37 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-0 rotate: false - xy: 477, 242 - size: 8, 8 - orig: 8, 8 + xy: 861, 109 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-1 rotate: false - xy: 477, 232 - size: 8, 8 - orig: 8, 8 + xy: 759, 7 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-2 rotate: false - xy: 487, 242 - size: 8, 8 - orig: 8, 8 + xy: 793, 41 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-3 rotate: false - xy: 487, 232 - size: 8, 8 - orig: 8, 8 + xy: 827, 75 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-4 rotate: false - xy: 477, 222 - size: 8, 8 - orig: 8, 8 + xy: 793, 7 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-5 rotate: false - xy: 497, 242 - size: 8, 8 - orig: 8, 8 + xy: 827, 41 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-6 rotate: false - xy: 497, 232 - size: 8, 8 - orig: 8, 8 + xy: 861, 75 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -alpha-mech-pad +rotary-pump rotate: false - xy: 796, 409 - size: 16, 16 - orig: 16, 16 + xy: 1905, 1333 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 -block-icon-alpha-mech-pad +thermal-pump rotate: false - xy: 796, 409 - size: 16, 16 - orig: 16, 16 + xy: 1261, 922 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +alpha-dart-mech-pad + rotate: false + xy: 1483, 1429 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +delta-mech-pad + rotate: false + xy: 931, 1037 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +glaive-ship-pad + rotate: false + xy: 747, 1463 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +javelin-ship-pad + rotate: false + xy: 1707, 1363 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +omega-mech-pad + rotate: false + xy: 1749, 1495 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +tau-mech-pad + rotate: false + xy: 1261, 988 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +trident-ship-pad + rotate: false + xy: 1327, 927 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 battery rotate: false - xy: 302, 312 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-battery - rotate: false - xy: 302, 312 - size: 8, 8 - orig: 8, 8 + xy: 1113, 401 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 battery-large rotate: false - xy: 43, 162 - size: 24, 24 - orig: 24, 24 + xy: 1063, 1593 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 -block-icon-battery-large +combustion-generator rotate: false - xy: 43, 162 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -fusion-reactor - rotate: false - xy: 92, 276 + xy: 1211, 362 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -fusion-reactor-bottom +combustion-generator-top rotate: false - xy: 126, 276 + xy: 1829, 507 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -fusion-reactor-light +impact-reactor rotate: false - xy: 160, 276 + xy: 1306, 1821 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-bottom + rotate: false + xy: 1436, 1821 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-light + rotate: false + xy: 1696, 1821 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-plasma-0 + rotate: false + xy: 1826, 1821 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-plasma-1 + rotate: false + xy: 509, 767 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-plasma-2 + rotate: false + xy: 509, 637 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-plasma-3 + rotate: false + xy: 453, 507 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-top + rotate: false + xy: 526, 1691 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +power-node + rotate: false + xy: 793, 109 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -fusion-reactor-plasma-0 +power-node-large rotate: false - xy: 87, 242 + xy: 1773, 1297 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +power-source + rotate: false + xy: 759, 75 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -fusion-reactor-plasma-1 +power-void rotate: false - xy: 121, 242 + xy: 827, 109 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -fusion-reactor-plasma-2 +powerinfinite rotate: false - xy: 155, 242 + xy: 725, 7 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -fusion-reactor-plasma-3 +powervoid rotate: false - xy: 89, 208 + xy: 759, 41 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -fusion-reactor-top +rtg-generator rotate: false - xy: 123, 208 - size: 32, 32 - orig: 32, 32 + xy: 1971, 1333 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 rtg-generator-top rotate: false - xy: 517, 242 - size: 8, 8 - orig: 8, 8 + xy: 1279, 375 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel + rotate: false + xy: 1351, 425 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-large + rotate: false + xy: 943, 1201 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +surge-tower + rotate: false + xy: 1239, 1120 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thermal-generator + rotate: false + xy: 1195, 922 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thorium-reactor + rotate: false + xy: 1041, 1299 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-center rotate: false - xy: 908, 453 - size: 24, 24 - orig: 24, 24 + xy: 1139, 1397 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-lights rotate: false - xy: 908, 427 - size: 24, 24 - orig: 24, 24 + xy: 943, 1103 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +turbine-generator + rotate: false + xy: 1371, 1157 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-top rotate: false - xy: 554, 288 - size: 16, 16 - orig: 16, 16 + xy: 1437, 1157 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 alloy-smelter rotate: false - xy: 438, 332 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-alloy-smelter - rotate: false - xy: 438, 332 - size: 16, 16 - orig: 16, 16 + xy: 867, 1593 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 alloy-smelter-top rotate: false - xy: 778, 409 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -arc-smelter - rotate: false - xy: 814, 409 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-arc-smelter - rotate: false - xy: 814, 409 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -arc-smelter-top - rotate: false - xy: 832, 409 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -silicon-smelter-top - rotate: false - xy: 832, 409 - size: 16, 16 - orig: 16, 16 + xy: 965, 1593 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 biomattercompressor rotate: false - xy: 850, 409 - size: 16, 16 - orig: 16, 16 + xy: 1549, 1429 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 biomattercompressor-frame0 rotate: false - xy: 438, 314 - size: 16, 16 - orig: 16, 16 + xy: 1615, 1429 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 biomattercompressor-frame1 rotate: false - xy: 908, 409 - size: 16, 16 - orig: 16, 16 + xy: 1681, 1429 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 biomattercompressor-frame2 rotate: false - xy: 926, 409 - size: 16, 16 - orig: 16, 16 + xy: 1747, 1429 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 biomattercompressor-liquid rotate: false - xy: 944, 409 - size: 16, 16 - orig: 16, 16 + xy: 1879, 1429 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 biomattercompressor-top rotate: false - xy: 962, 415 - size: 16, 16 - orig: 16, 16 + xy: 1041, 1088 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 blast-mixer rotate: false - xy: 1006, 461 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-blast-mixer - rotate: false - xy: 1006, 461 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -centrifuge-liquid - rotate: false - xy: 968, 379 - size: 16, 16 - orig: 16, 16 + xy: 1139, 1186 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-bottom rotate: false - xy: 968, 361 - size: 16, 16 - orig: 16, 16 + xy: 1945, 1465 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-liquid rotate: false - xy: 986, 363 - size: 16, 16 - orig: 16, 16 + xy: 601, 1005 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-top rotate: false - xy: 189, 258 - size: 16, 16 - orig: 16, 16 + xy: 667, 1005 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 cultivator rotate: false - xy: 207, 260 - size: 16, 16 - orig: 16, 16 + xy: 733, 1005 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 cultivator-middle rotate: false - xy: 225, 260 - size: 16, 16 - orig: 16, 16 + xy: 647, 939 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 cultivator-top rotate: false - xy: 243, 260 - size: 16, 16 - orig: 16, 16 + xy: 713, 939 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +graphite-press + rotate: false + xy: 1575, 1363 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +incinerator + rotate: false + xy: 1689, 411 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-source + rotate: false + xy: 1767, 1021 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-void + rotate: false + xy: 1869, 1055 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +kiln + rotate: false + xy: 1773, 1363 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +kiln-top + rotate: false + xy: 1839, 1363 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +silicon-smelter-top + rotate: false + xy: 1839, 1363 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 lavasmelter rotate: false - xy: 173, 48 - size: 8, 8 - orig: 8, 8 + xy: 1971, 1067 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-source + rotate: false + xy: 1809, 987 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +melter + rotate: false + xy: 1877, 931 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +multi-press + rotate: false + xy: 1161, 1495 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 oilrefinery rotate: false - xy: 682, 293 - size: 8, 8 - orig: 8, 8 + xy: 1783, 885 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 phase-weaver rotate: false - xy: 530, 360 - size: 16, 16 - orig: 16, 16 + xy: 747, 543 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-bottom rotate: false - xy: 548, 378 - size: 16, 16 - orig: 16, 16 + xy: 715, 477 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-weave rotate: false - xy: 584, 396 - size: 16, 16 - orig: 16, 16 + xy: 421, 175 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +plastanium-compressor + rotate: false + xy: 1377, 1289 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor-top rotate: false - xy: 530, 342 - size: 16, 16 - orig: 16, 16 + xy: 1443, 1289 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 pulverizer rotate: false - xy: 487, 222 - size: 8, 8 - orig: 8, 8 + xy: 827, 7 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 pulverizer-rotator rotate: false - xy: 507, 242 - size: 8, 8 - orig: 8, 8 + xy: 861, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pyratite-mixer + rotate: false + xy: 1839, 1297 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +separator + rotate: false + xy: 1905, 1201 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 separator-liquid rotate: false - xy: 547, 232 - size: 8, 8 - orig: 8, 8 + xy: 1971, 1201 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 -core-open +silicon-smelter rotate: false - xy: 392, 338 - size: 24, 24 - orig: 24, 24 + xy: 997, 1022 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 -core-top +smelter rotate: false - xy: 314, 323 - size: 24, 24 - orig: 24, 24 + xy: 1391, 103 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +container + rotate: false + xy: 1945, 1597 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +core-foundation + rotate: false + xy: 1176, 1821 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +core-nucleus + rotate: false + xy: 291, 493 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +core-shard + rotate: false + xy: 1259, 1593 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +core-shard-top + rotate: false + xy: 1357, 1593 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +launch-pad + rotate: false + xy: 649, 1169 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 sortedunloader rotate: false - xy: 194, 132 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-1 - rotate: false - xy: 752, 383 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-1-top - rotate: false - xy: 662, 327 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-2 - rotate: false - xy: 458, 392 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-2-top - rotate: false - xy: 458, 374 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-3 - rotate: false - xy: 314, 375 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-3-top - rotate: false - xy: 674, 451 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-4 - rotate: false - xy: 711, 479 + xy: 1381, 391 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-4-top +unloader rotate: false - xy: 745, 479 + xy: 1561, 105 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -arc +vault rotate: false - xy: 194, 300 - size: 8, 8 - orig: 8, 8 + xy: 1237, 1397 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 arc-heat rotate: false - xy: 256, 312 - size: 8, 8 - orig: 8, 8 + xy: 983, 207 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +block-1 + rotate: false + xy: 1143, 367 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +block-2 + rotate: false + xy: 1956, 1663 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +block-3 + rotate: false + xy: 1161, 1593 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +block-4 + rotate: false + xy: 656, 1821 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +hail-heat + rotate: false + xy: 581, 897 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +lancer-heat + rotate: false + xy: 639, 807 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +meltdown-heat + rotate: false + xy: 786, 1691 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +ripple-heat + rotate: false + xy: 845, 1299 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +salvo-heat + rotate: false + xy: 1377, 1223 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +salvo-panel-left + rotate: false + xy: 1509, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +salvo-panel-right + rotate: false + xy: 1575, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wave-liquid + rotate: false + xy: 1459, 827 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dagger-factory + rotate: false + xy: 799, 1005 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phantom-factory + rotate: false + xy: 799, 1005 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spirit-factory + rotate: false + xy: 799, 1005 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wraith-factory + rotate: false + xy: 799, 1005 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dagger-factory-top + rotate: false + xy: 1945, 1399 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dagger-factory-top-open + rotate: false + xy: 865, 1037 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +fortress-factory + rotate: false + xy: 453, 1116 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fortress-factory-top + rotate: false + xy: 291, 13 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ghoul-factory-top + rotate: false + xy: 291, 13 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +titan-factory-top + rotate: false + xy: 291, 13 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fortress-factory-top-open + rotate: false + xy: 583, 539 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ghoul-factory-top-open + rotate: false + xy: 583, 539 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +titan-factory-top-open + rotate: false + xy: 583, 539 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ghoul-factory + rotate: false + xy: 649, 1463 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +phantom-factory-top + rotate: false + xy: 681, 609 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phantom-factory-top-open + rotate: false + xy: 681, 543 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +repair-point-base + rotate: false + xy: 895, 75 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +repair-point-turret + rotate: false + xy: 895, 41 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +revenant-factory + rotate: false + xy: 1046, 1691 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +revenant-factory-top + rotate: false + xy: 1306, 1691 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +revenant-factory-top-open + rotate: false + xy: 1436, 1691 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +spirit-factory-top + rotate: false + xy: 1063, 956 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spirit-factory-top-open + rotate: false + xy: 1107, 1088 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +titan-factory + rotate: false + xy: 1041, 1201 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +wraith-factory-top + rotate: false + xy: 1569, 1165 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wraith-factory-top-open + rotate: false + xy: 1635, 1165 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +copper-wall + rotate: false + xy: 1123, 299 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper-wall-large + rotate: false + xy: 1945, 1531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +door + rotate: false + xy: 1221, 158 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +door-large + rotate: false + xy: 583, 473 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +door-large-open + rotate: false + xy: 865, 971 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +door-open + rotate: false + xy: 1259, 260 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall + rotate: false + xy: 623, 3 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-large + rotate: false + xy: 747, 609 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-gigantic + rotate: false + xy: 1696, 1691 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +scrap-wall-huge1 + rotate: false + xy: 943, 1299 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-huge2 + rotate: false + xy: 1041, 1397 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-huge3 + rotate: false + xy: 845, 1103 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-large1 + rotate: false + xy: 1641, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-large2 + rotate: false + xy: 1707, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-large3 + rotate: false + xy: 1773, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-large4 + rotate: false + xy: 1839, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall1 + rotate: false + xy: 1373, 341 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall2 + rotate: false + xy: 1357, 239 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall3 + rotate: false + xy: 1357, 205 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall4 + rotate: false + xy: 1357, 171 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall5 + rotate: false + xy: 1357, 171 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-wall + rotate: false + xy: 1459, 221 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-wall-large + rotate: false + xy: 1195, 1054 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thorium-wall + rotate: false + xy: 1497, 309 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-wall-large + rotate: false + xy: 1271, 1191 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thruster + rotate: false + xy: 607, 1561 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +titanium-wall + rotate: false + xy: 1527, 105 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-wall-large + rotate: false + xy: 1327, 993 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +beam + rotate: false + xy: 1303, 1273 + size: 4, 48 + orig: 4, 48 + offset: 0, 0 + index: -1 +beam-end + rotate: false + xy: 1956, 1877 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +bullet + rotate: false + xy: 477, 1507 + size: 52, 52 + orig: 52, 52 + offset: 0, 0 + index: -1 +bullet-back + rotate: false + xy: 1583, 879 + size: 52, 52 + orig: 52, 52 + offset: 0, 0 + index: -1 +casing + rotate: false + xy: 1449, 85 + size: 8, 16 + orig: 8, 16 + offset: 0, 0 + index: -1 +error + rotate: false + xy: 1245, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +laser + rotate: false + xy: 2029, 405 + size: 4, 48 + orig: 4, 48 + offset: 0, 0 + index: -1 +laser-end + rotate: false + xy: 1335, 1421 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +laserfull + rotate: false + xy: 1956, 1803 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +minelaser + rotate: false + xy: 2037, 1292 + size: 4, 48 + orig: 4, 48 + offset: 0, 0 + index: -1 +minelaser-end + rotate: false + xy: 1409, 1421 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +missile + rotate: false + xy: 1029, 342 + size: 36, 36 + orig: 36, 36 + offset: 0, 0 + index: -1 +missile-back + rotate: false + xy: 1071, 384 + size: 36, 36 + orig: 36, 36 + offset: 0, 0 + index: -1 +scale_marker + rotate: false + xy: 1387, 855 + size: 4, 4 + orig: 4, 4 + offset: 0, 0 + index: -1 +scorch1 + rotate: false + xy: 929, 1 + size: 28, 100 + orig: 28, 100 + offset: 0, 0 + index: -1 +scorch2 + rotate: false + xy: 959, 1 + size: 28, 100 + orig: 28, 100 + offset: 0, 0 + index: -1 +scorch3 + rotate: false + xy: 989, 1 + size: 28, 100 + orig: 28, 100 + offset: 0, 0 + index: -1 +scorch4 + rotate: false + xy: 1019, 1 + size: 28, 100 + orig: 28, 100 + offset: 0, 0 + index: -1 +scorch5 + rotate: false + xy: 1049, 1 + size: 28, 100 + orig: 28, 100 + offset: 0, 0 + index: -1 +shell + rotate: false + xy: 945, 200 + size: 36, 36 + orig: 36, 36 + offset: 0, 0 + index: -1 +shell-back + rotate: false + xy: 1337, 1227 + size: 36, 36 + orig: 36, 36 + offset: 0, 0 + index: -1 +shot + rotate: false + xy: 1391, 171 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +transfer + rotate: false + xy: 2043, 1292 + size: 4, 48 + orig: 4, 48 + offset: 0, 0 + index: -1 +transfer-arrow + rotate: false + xy: 1595, 173 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +transfer-end + rotate: false + xy: 1956, 1729 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +alloy-smelter-icon-large + rotate: false + xy: 1641, 941 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +alloy-smelter-icon-medium + rotate: false + xy: 1337, 1193 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +alloy-smelter-icon-small + rotate: false + xy: 879, 545 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +alpha-dart-mech-pad-icon-large + rotate: false + xy: 1583, 829 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +alpha-dart-mech-pad-icon-medium + rotate: false + xy: 987, 275 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +alpha-dart-mech-pad-icon-small + rotate: false + xy: 1451, 501 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +arc + rotate: false + xy: 983, 241 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +arc-icon-full + rotate: false + xy: 983, 173 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +arc-icon-large + rotate: false + xy: 453, 457 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +arc-icon-small + rotate: false + xy: 1741, 893 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +battery-icon-large + rotate: false + xy: 503, 457 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +battery-icon-small + rotate: false + xy: 2021, 871 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +battery-large-icon-large + rotate: false + xy: 445, 349 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +battery-large-icon-medium + rotate: false + xy: 1147, 401 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +battery-large-icon-small + rotate: false + xy: 715, 147 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +biomattercompressor-icon-full + rotate: false + xy: 1813, 1429 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +biomattercompressor-icon-large + rotate: false + xy: 495, 407 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +biomattercompressor-icon-medium + rotate: false + xy: 1189, 430 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +biomattercompressor-icon-small + rotate: false + xy: 1663, 107 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +blast-drill-icon-full + rotate: false + xy: 291, 111 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +blast-drill-icon-large + rotate: false + xy: 445, 299 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +blast-drill-icon-medium + rotate: false + xy: 1181, 396 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +blast-drill-icon-small + rotate: false + xy: 929, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +blast-mixer-icon-large + rotate: false + xy: 495, 357 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +blast-mixer-icon-medium + rotate: false + xy: 1109, 367 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +blast-mixer-icon-small + rotate: false + xy: 955, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +bridge-conduit-icon-large + rotate: false + xy: 495, 257 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +bridge-conduit-icon-small + rotate: false + xy: 945, 145 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +bridge-conveyor-icon-large + rotate: false + xy: 845, 921 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +bridge-conveyor-icon-small + rotate: false + xy: 981, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +char-icon-large + rotate: false + xy: 945, 921 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +char-icon-small + rotate: false + xy: 1033, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +cliffs-icon-large + rotate: false + xy: 837, 871 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cliffs-icon-small + rotate: false + xy: 1493, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +combustion-generator-icon-large + rotate: false + xy: 837, 821 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +combustion-generator-icon-small + rotate: false + xy: 1519, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +conduit-icon-full + rotate: false + xy: 1655, 445 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-icon-large + rotate: false + xy: 887, 871 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +conduit-icon-small + rotate: false + xy: 1545, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +container-icon-large + rotate: false + xy: 837, 771 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +container-icon-medium + rotate: false + xy: 1017, 240 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +container-icon-small + rotate: false + xy: 1571, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +conveyor-icon-large + rotate: false + xy: 937, 871 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +conveyor-icon-small + rotate: false + xy: 1597, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +copper-wall-icon-large + rotate: false + xy: 887, 821 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +copper-wall-icon-small + rotate: false + xy: 1623, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +copper-wall-large-icon-large + rotate: false + xy: 837, 721 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +copper-wall-large-icon-medium + rotate: false + xy: 1123, 265 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper-wall-large-icon-small + rotate: false + xy: 1059, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +core-foundation-icon-large + rotate: false + xy: 887, 771 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +core-foundation-icon-medium + rotate: false + xy: 1119, 231 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +core-foundation-icon-small + rotate: false + xy: 1085, 112 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +core-nucleus-icon-large + rotate: false + xy: 937, 821 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +core-nucleus-icon-medium + rotate: false + xy: 1119, 197 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +core-nucleus-icon-small + rotate: false + xy: 1223, 451 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +core-shard-icon-large + rotate: false + xy: 887, 721 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +core-shard-icon-medium + rotate: false + xy: 1119, 163 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +core-shard-icon-small + rotate: false + xy: 1127, 1160 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +craters-icon-large + rotate: false + xy: 937, 771 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +craters-icon-small + rotate: false + xy: 1730, 329 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-full + rotate: false + xy: 535, 1005 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-large + rotate: false + xy: 1095, 906 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-medium + rotate: false + xy: 1153, 226 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-small + rotate: false + xy: 1756, 329 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +cultivator-icon-full + rotate: false + xy: 581, 939 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cultivator-icon-large + rotate: false + xy: 1145, 906 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cultivator-icon-medium + rotate: false + xy: 1153, 192 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cultivator-icon-small + rotate: false + xy: 1730, 303 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 cyclone rotate: false - xy: 366, 312 + xy: 1455, 1593 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +cyclone-icon-full + rotate: false + xy: 1553, 1593 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +cyclone-icon-large + rotate: false + xy: 987, 856 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cyclone-icon-medium + rotate: false + xy: 1187, 226 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cyclone-icon-small + rotate: false + xy: 1782, 329 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dagger-factory-icon-full + rotate: false + xy: 779, 939 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dagger-factory-icon-large + rotate: false + xy: 987, 756 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dagger-factory-icon-medium + rotate: false + xy: 1187, 192 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dagger-factory-icon-small + rotate: false + xy: 1756, 303 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +deepwater-edge + rotate: false + xy: 1, 897 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +deepwater-icon-large + rotate: false + xy: 1037, 756 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +deepwater-icon-small + rotate: false + xy: 1782, 303 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-large + rotate: false + xy: 1137, 806 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-medium + rotate: false + xy: 1221, 192 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-small + rotate: false + xy: 1730, 277 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +differential-generator-icon-large + rotate: false + xy: 1137, 756 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +differential-generator-icon-medium + rotate: false + xy: 1153, 158 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +differential-generator-icon-small + rotate: false + xy: 1756, 277 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +distributor-icon-large + rotate: false + xy: 987, 706 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +distributor-icon-medium + rotate: false + xy: 1187, 158 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +distributor-icon-small + rotate: false + xy: 1782, 277 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +door-icon-large + rotate: false + xy: 1037, 706 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +door-icon-small + rotate: false + xy: 1649, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +door-large-icon-large + rotate: false + xy: 1087, 706 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +door-large-icon-medium + rotate: false + xy: 1259, 294 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +door-large-icon-small + rotate: false + xy: 1675, 81 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dunerocks-icon-large + rotate: false + xy: 1137, 706 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dunerocks-icon-small + rotate: false + xy: 1689, 107 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 duo rotate: false - xy: 83, 58 - size: 8, 8 - orig: 8, 8 + xy: 1255, 158 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +duo-icon-full + rotate: false + xy: 1271, 328 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +duo-icon-large + rotate: false + xy: 1195, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +duo-icon-small + rotate: false + xy: 1701, 81 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +force-projector-icon-large + rotate: false + xy: 1187, 714 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +force-projector-icon-medium + rotate: false + xy: 1293, 260 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +force-projector-icon-small + rotate: false + xy: 1808, 311 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +fortress-factory-icon-full + rotate: false + xy: 437, 1018 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fortress-factory-icon-large + rotate: false + xy: 1237, 764 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +fortress-factory-icon-medium + rotate: false + xy: 1289, 226 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +fortress-factory-icon-small + rotate: false + xy: 1834, 311 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 fuse rotate: false - xy: 726, 453 + xy: 551, 1463 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fuse-icon-full + rotate: false + xy: 551, 1365 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fuse-icon-large + rotate: false + xy: 1237, 714 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +fuse-icon-medium + rotate: false + xy: 1289, 192 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +fuse-icon-small + rotate: false + xy: 1808, 285 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ghoul-factory-icon-full + rotate: false + xy: 551, 1267 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ghoul-factory-icon-large + rotate: false + xy: 1287, 811 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ghoul-factory-icon-medium + rotate: false + xy: 1289, 158 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ghoul-factory-icon-small + rotate: false + xy: 1860, 311 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-large + rotate: false + xy: 1337, 811 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-medium + rotate: false + xy: 1323, 226 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-small + rotate: false + xy: 1834, 285 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +graphite-press-icon-large + rotate: false + xy: 1287, 761 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +graphite-press-icon-medium + rotate: false + xy: 1323, 192 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +graphite-press-icon-small + rotate: false + xy: 1860, 285 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 hail rotate: false - xy: 123, 68 - size: 8, 8 - orig: 8, 8 + xy: 1051, 138 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -hail-heat +hail-icon-full rotate: false - xy: 242, 339 - size: 10, 10 - orig: 10, 10 + xy: 1085, 138 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hail-icon-large + rotate: false + xy: 1337, 761 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +hail-icon-small + rotate: false + xy: 1886, 293 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +holostone-edge + rotate: false + xy: 1, 603 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +holostone-icon-large + rotate: false + xy: 1337, 711 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +holostone-icon-small + rotate: false + xy: 1912, 293 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +hotrock-icon-large + rotate: false + xy: 1387, 777 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +hotrock-icon-small + rotate: false + xy: 1938, 293 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ice-icon-large + rotate: false + xy: 1437, 777 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ice-icon-small + rotate: false + xy: 1964, 293 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ice-snow-edge + rotate: false + xy: 1, 407 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +ice-snow-icon-large + rotate: false + xy: 1387, 727 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ice-snow-icon-small + rotate: false + xy: 1990, 293 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +icerocks-icon-large + rotate: false + xy: 1437, 727 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icerocks-icon-small + rotate: false + xy: 2016, 293 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ignarock-icon-large + rotate: false + xy: 1437, 677 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ignarock-icon-small + rotate: false + xy: 1079, 34 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +impact-reactor-icon-full + rotate: false + xy: 1566, 1821 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +impact-reactor-icon-large + rotate: false + xy: 1487, 745 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +impact-reactor-icon-medium + rotate: false + xy: 1655, 411 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +impact-reactor-icon-small + rotate: false + xy: 1079, 8 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +incinerator-icon-large + rotate: false + xy: 1487, 695 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +incinerator-icon-small + rotate: false + xy: 1111, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-biomatter-medium + rotate: false + xy: 1105, 9 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-biomatter-small + rotate: false + xy: 1131, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-biomatter-xlarge + rotate: false + xy: 837, 679 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-blast-compound-medium + rotate: false + xy: 1137, 98 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-blast-compound-small + rotate: false + xy: 1149, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-blast-compound-xlarge + rotate: false + xy: 477, 1716 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-coal-medium + rotate: false + xy: 1163, 98 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-coal-small + rotate: false + xy: 1167, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-coal-xlarge + rotate: false + xy: 913, 479 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-copper-medium + rotate: false + xy: 1189, 98 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-copper-small + rotate: false + xy: 1185, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-copper-xlarge + rotate: false + xy: 955, 464 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-graphite-medium + rotate: false + xy: 1215, 98 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-graphite-small + rotate: false + xy: 1203, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-graphite-xlarge + rotate: false + xy: 997, 464 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-lead-medium + rotate: false + xy: 1241, 98 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-lead-small + rotate: false + xy: 1221, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-lead-xlarge + rotate: false + xy: 1039, 464 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-metaglass-medium + rotate: false + xy: 1267, 98 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-metaglass-small + rotate: false + xy: 1239, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-metaglass-xlarge + rotate: false + xy: 1081, 464 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-phase-fabric-medium + rotate: false + xy: 1293, 98 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-phase-fabric-small + rotate: false + xy: 1257, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-phase-fabric-xlarge + rotate: false + xy: 1123, 464 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-plastanium-medium + rotate: false + xy: 1319, 98 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-plastanium-small + rotate: false + xy: 1275, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-plastanium-xlarge + rotate: false + xy: 1165, 464 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-pyratite-medium + rotate: false + xy: 1137, 72 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-pyratite-small + rotate: false + xy: 1293, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-pyratite-xlarge + rotate: false + xy: 945, 422 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-sand-medium + rotate: false + xy: 1163, 72 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-sand-small + rotate: false + xy: 1311, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-sand-xlarge + rotate: false + xy: 945, 380 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-scrap-medium + rotate: false + xy: 1189, 72 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-scrap-small + rotate: false + xy: 1329, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-scrap-xlarge + rotate: false + xy: 987, 422 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-silicon-medium + rotate: false + xy: 1215, 72 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-silicon-small + rotate: false + xy: 1347, 2 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-silicon-xlarge + rotate: false + xy: 945, 338 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-source-icon-large + rotate: false + xy: 1487, 645 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-source-icon-small + rotate: false + xy: 1241, 72 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-surge-alloy-medium + rotate: false + xy: 1267, 72 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-surge-alloy-small + rotate: false + xy: 1365, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-surge-alloy-xlarge + rotate: false + xy: 987, 380 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-thorium-medium + rotate: false + xy: 1293, 72 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-thorium-small + rotate: false + xy: 1383, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-thorium-xlarge + rotate: false + xy: 1029, 422 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-titanium-medium + rotate: false + xy: 1319, 72 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-titanium-small + rotate: false + xy: 1401, 7 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-titanium-xlarge + rotate: false + xy: 945, 296 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-void-icon-large + rotate: false + xy: 1537, 729 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-void-icon-small + rotate: false + xy: 1131, 46 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-large + rotate: false + xy: 1587, 729 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-medium + rotate: false + xy: 1835, 1021 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-small + rotate: false + xy: 1131, 20 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +junction-icon-large + rotate: false + xy: 1537, 629 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +junction-icon-small + rotate: false + xy: 1157, 46 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +kiln-icon-large + rotate: false + xy: 1587, 629 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +kiln-icon-medium + rotate: false + xy: 1903, 1067 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +kiln-icon-small + rotate: false + xy: 1157, 20 + size: 24, 24 + orig: 24, 24 offset: 0, 0 index: -1 lancer rotate: false - xy: 495, 252 - size: 16, 16 - orig: 16, 16 + xy: 639, 873 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 -lancer-heat +lancer-icon-full rotate: false - xy: 513, 252 - size: 16, 16 - orig: 16, 16 + xy: 705, 873 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 -meltdown +lancer-icon-large rotate: false - xy: 157, 208 + xy: 1625, 779 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +lancer-icon-medium + rotate: false + xy: 1903, 1033 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -meltdown-heat +lancer-icon-small rotate: false - xy: 269, 432 + xy: 1183, 46 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +laser-drill-icon-full + rotate: false + xy: 551, 1169 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +laser-drill-icon-large + rotate: false + xy: 1633, 829 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +laser-drill-icon-medium + rotate: false + xy: 1937, 1067 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ripple +laser-drill-icon-small rotate: false - xy: 856, 453 + xy: 1183, 20 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ripple-heat +launch-pad-icon-large rotate: false - xy: 856, 427 - size: 24, 24 - orig: 24, 24 + xy: 1637, 729 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 -salvo +launch-pad-icon-medium rotate: false - xy: 602, 378 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -salvo-heat - rotate: false - xy: 548, 324 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -salvo-panel-left - rotate: false - xy: 546, 306 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -salvo-panel-right - rotate: false - xy: 536, 288 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -scatter - rotate: false - xy: 537, 232 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -scorch - rotate: false - xy: 527, 222 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -scorch-shoot - rotate: false - xy: 547, 242 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -spectre - rotate: false - xy: 405, 416 + xy: 1937, 1033 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -swarmer +launch-pad-icon-small rotate: false - xy: 584, 360 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -wave - rotate: false - xy: 572, 288 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -wave-liquid - rotate: false - xy: 602, 342 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -dagger-factory-top - rotate: false - xy: 494, 396 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -dagger-factory-top-open - rotate: false - xy: 494, 378 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -fortress-factory - rotate: false - xy: 700, 451 + xy: 1209, 46 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -fortress-factory-top +liquid-junction-icon-large rotate: false - xy: 700, 425 + xy: 1637, 629 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-junction-icon-small + rotate: false + xy: 1209, 20 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ghoul-factory-top +liquid-router-icon-full rotate: false - xy: 700, 425 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -titan-factory-top - rotate: false - xy: 700, 425 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -fortress-factory-top-open - rotate: false - xy: 700, 399 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ghoul-factory-top-open - rotate: false - xy: 700, 399 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -titan-factory-top-open - rotate: false - xy: 700, 399 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ghoul-factory - rotate: false - xy: 726, 427 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -phantom-factory-top - rotate: false - xy: 512, 324 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -phantom-factory-top-open - rotate: false - xy: 566, 396 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -reconstructor-open - rotate: false - xy: 530, 324 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -repair-point-turret - rotate: false - xy: 507, 232 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -revenant-factory - rotate: false - xy: 337, 450 + xy: 1741, 987 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -revenant-factory-top +liquid-router-icon-large rotate: false - xy: 337, 416 + xy: 1675, 779 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-router-icon-small + rotate: false + xy: 1235, 46 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-source-icon-large + rotate: false + xy: 1687, 729 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-source-icon-small + rotate: false + xy: 1235, 20 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-tank-icon-full + rotate: false + xy: 551, 1071 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +liquid-tank-icon-large + rotate: false + xy: 1687, 679 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-tank-icon-medium + rotate: false + xy: 1775, 953 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -revenant-factory-top-open +liquid-tank-icon-small rotate: false - xy: 371, 450 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spirit-factory-top - rotate: false - xy: 536, 270 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -spirit-factory-top-open - rotate: false - xy: 566, 342 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -titan-factory - rotate: false - xy: 934, 453 + xy: 1261, 46 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -wraith-factory-top +magmarock-icon-large rotate: false - xy: 572, 270 - size: 16, 16 - orig: 16, 16 + xy: 1687, 629 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 -wraith-factory-top-open +magmarock-icon-small rotate: false - xy: 567, 252 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -deflector-wall - rotate: false - xy: 144, 88 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -deflector-wall-large - rotate: false - xy: 494, 360 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -door-large-open - rotate: false - xy: 494, 342 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -door-open - rotate: false - xy: 93, 78 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -beam - rotate: false - xy: 334, 470 - size: 1, 12 - orig: 1, 12 - offset: 0, 0 - index: -1 -beam-end - rotate: false - xy: 418, 396 - size: 18, 18 - orig: 18, 18 - offset: 0, 0 - index: -1 -blank - rotate: false - xy: 290, 466 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -bullet - rotate: false - xy: 197, 195 - size: 13, 13 - orig: 13, 13 - offset: 0, 0 - index: -1 -bullet-back - rotate: false - xy: 197, 180 - size: 13, 13 - orig: 13, 13 - offset: 0, 0 - index: -1 -casing - rotate: false - xy: 85, 198 - size: 2, 4 - orig: 2, 4 - offset: 0, 0 - index: -1 -clear - rotate: false - xy: 254, 398 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -command-attack - rotate: false - xy: 84, 98 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -command-idle - rotate: false - xy: 134, 138 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -command-patrol - rotate: false - xy: 124, 128 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -command-retreat - rotate: false - xy: 114, 118 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -enemyarrow - rotate: false - xy: 93, 69 - size: 8, 7 - orig: 8, 7 - offset: 0, 0 - index: -1 -error - rotate: false - xy: 642, 306 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -laser - rotate: false - xy: 337, 402 - size: 1, 12 - orig: 1, 12 - offset: 0, 0 - index: -1 -laser-end - rotate: false - xy: 418, 376 - size: 18, 18 - orig: 18, 18 - offset: 0, 0 - index: -1 -laserfull - rotate: false - xy: 418, 356 - size: 18, 18 - orig: 18, 18 - offset: 0, 0 - index: -1 -minelaser - rotate: false - xy: 414, 298 - size: 1, 12 - orig: 1, 12 - offset: 0, 0 - index: -1 -minelaser-end - rotate: false - xy: 418, 336 - size: 18, 18 - orig: 18, 18 - offset: 0, 0 - index: -1 -missile - rotate: false - xy: 868, 416 - size: 9, 9 - orig: 9, 9 - offset: 0, 0 - index: -1 -missile-back - rotate: false - xy: 314, 312 - size: 9, 9 - orig: 9, 9 - offset: 0, 0 - index: -1 -scorch1 - rotate: false - xy: 702, 338 - size: 7, 25 - orig: 7, 25 - offset: 0, 0 - index: -1 -scorch2 - rotate: false - xy: 702, 311 - size: 7, 25 - orig: 7, 25 - offset: 0, 0 - index: -1 -scorch3 - rotate: false - xy: 702, 284 - size: 7, 25 - orig: 7, 25 - offset: 0, 0 - index: -1 -scorch4 - rotate: false - xy: 699, 238 - size: 7, 25 - orig: 7, 25 - offset: 0, 0 - index: -1 -scorch5 - rotate: false - xy: 211, 153 - size: 7, 25 - orig: 7, 25 - offset: 0, 0 - index: -1 -shell - rotate: false - xy: 325, 312 - size: 9, 9 - orig: 9, 9 - offset: 0, 0 - index: -1 -shell-back - rotate: false - xy: 696, 376 - size: 9, 9 - orig: 9, 9 - offset: 0, 0 - index: -1 -shot - rotate: false - xy: 557, 242 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -transfer - rotate: false - xy: 1020, 447 - size: 1, 12 - orig: 1, 12 - offset: 0, 0 - index: -1 -transfer-arrow - rotate: false - xy: 131, 28 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -transfer-end - rotate: false - xy: 438, 350 - size: 18, 18 - orig: 18, 18 - offset: 0, 0 - index: -1 -blackstone-cliff-edge - rotate: false - xy: 1012, 427 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -blackstone-cliff-edge-1 - rotate: false - xy: 1012, 417 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -blackstone-cliff-edge-2 - rotate: false - xy: 1012, 407 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -blackstone-cliff-side - rotate: false - xy: 672, 333 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-arc - rotate: false - xy: 672, 313 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-biomattercompressor - rotate: false - xy: 458, 356 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-blast-drill - rotate: false - xy: 254, 338 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-bridge-conduit - rotate: false - xy: 656, 307 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -bridge-conduit - rotate: false - xy: 656, 307 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-bridge-conveyor - rotate: false - xy: 662, 297 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -bridge-conveyor - rotate: false - xy: 662, 297 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-centrifuge - rotate: false - xy: 476, 396 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -centrifuge - rotate: false - xy: 476, 396 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-combustion-generator - rotate: false - xy: 662, 287 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -combustion-generator - rotate: false - xy: 662, 287 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-command-center - rotate: false - xy: 476, 378 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -command-center - rotate: false - xy: 476, 378 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-conduit - rotate: false - xy: 662, 277 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-container - rotate: false - xy: 476, 360 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -container - rotate: false - xy: 476, 360 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-conveyor - rotate: false - xy: 662, 267 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -conveyor-0-0 - rotate: false - xy: 662, 267 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-copper-wall - rotate: false - xy: 672, 303 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -copper-wall - rotate: false - xy: 672, 303 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-copper-wall-large - rotate: false - xy: 752, 393 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -copper-wall-large - rotate: false - xy: 752, 393 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-core - rotate: false - xy: 648, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -core - rotate: false - xy: 648, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-cryofluidmixer - rotate: false - xy: 194, 278 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-cultivator - rotate: false - xy: 212, 278 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-cyclone - rotate: false - xy: 622, 432 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-dagger-factory - rotate: false - xy: 230, 278 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-dart-ship-pad - rotate: false - xy: 770, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -dart-ship-pad - rotate: false - xy: 770, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-deepwater - rotate: false - xy: 672, 293 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -deepwater - rotate: false - xy: 672, 293 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-delta-mech-pad - rotate: false - xy: 788, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -delta-mech-pad - rotate: false - xy: 788, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-dense-alloy-wall - rotate: false - xy: 672, 283 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -dense-alloy-wall - rotate: false - xy: 672, 283 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-dense-alloy-wall-large - rotate: false - xy: 806, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -dense-alloy-wall-large - rotate: false - xy: 806, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-dirt - rotate: false - xy: 672, 273 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -dirt1 - rotate: false - xy: 672, 273 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-distributor - rotate: false - xy: 824, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -distributor - rotate: false - xy: 824, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-door - rotate: false - xy: 672, 263 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -door - rotate: false - xy: 672, 263 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-door-large - rotate: false - xy: 842, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -door-large - rotate: false - xy: 842, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-duo - rotate: false - xy: 669, 253 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-force-projector - rotate: false - xy: 674, 425 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -force-projector - rotate: false - xy: 674, 425 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-fortress-factory - rotate: false - xy: 648, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-fuse - rotate: false - xy: 674, 399 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-fusion-reactor - rotate: false - xy: 779, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -block-icon-ghoul-factory - rotate: false - xy: 204, 296 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-glaive-ship-pad - rotate: false - xy: 230, 296 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -glaive-ship-pad - rotate: false - xy: 230, 296 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-grass - rotate: false - xy: 669, 243 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -grass1 - rotate: false - xy: 669, 243 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-hail - rotate: false - xy: 669, 233 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-ice - rotate: false - xy: 679, 253 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ice1 - rotate: false - xy: 679, 253 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-icerock - rotate: false - xy: 679, 243 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -icerock1 - rotate: false - xy: 679, 243 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-incinerator - rotate: false - xy: 679, 233 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -incinerator - rotate: false - xy: 679, 233 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-itemsource - rotate: false - xy: 205, 248 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -itemsource - rotate: false - xy: 205, 248 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-itemvoid - rotate: false - xy: 215, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -itemvoid - rotate: false - xy: 215, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-javelin-ship-pad - rotate: false - xy: 248, 278 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -javelin-ship-pad - rotate: false - xy: 248, 278 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-junction - rotate: false - xy: 225, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -junction - rotate: false - xy: 225, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-lancer - rotate: false - xy: 860, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-laser-drill - rotate: false - xy: 878, 398 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-lava - rotate: false - xy: 235, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -lava - rotate: false - xy: 235, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-liquid-junction - rotate: false - xy: 245, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -liquid-junction - rotate: false - xy: 245, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-liquid-router - rotate: false - xy: 255, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-liquid-tank - rotate: false - xy: 340, 390 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-liquidsource - rotate: false - xy: 265, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -liquidsource - rotate: false - xy: 265, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-mass-driver - rotate: false - xy: 366, 390 + xy: 1261, 20 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 mass-driver rotate: false - xy: 366, 390 - size: 24, 24 - orig: 24, 24 + xy: 867, 1495 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 -block-icon-mechanical-drill +mass-driver-icon-full rotate: false - xy: 878, 380 - size: 16, 16 - orig: 16, 16 + xy: 1063, 1495 + size: 96, 96 + orig: 96, 96 offset: 0, 0 index: -1 -block-icon-mechanical-pump +mass-driver-icon-large rotate: false - xy: 275, 250 - size: 8, 8 - orig: 8, 8 + xy: 479, 125 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 -mechanical-pump +mass-driver-icon-medium rotate: false - xy: 275, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-meltdown - rotate: false - xy: 813, 479 + xy: 1809, 919 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-icon-melter +mass-driver-icon-small rotate: false - xy: 285, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -melter - rotate: false - xy: 285, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-mend-projector - rotate: false - xy: 532, 432 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -mend-projector - rotate: false - xy: 532, 432 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-metalfloor - rotate: false - xy: 295, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -metalfloor1 - rotate: false - xy: 295, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-oil-extractor - rotate: false - xy: 392, 390 + xy: 1287, 46 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-icon-omega-mech-pad - rotate: false - xy: 340, 364 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -omega-mech-pad - rotate: false - xy: 340, 364 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-overdrive-projector - rotate: false - xy: 550, 432 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -overdrive-projector - rotate: false - xy: 550, 432 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-overflow-gate - rotate: false - xy: 305, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -overflow-gate - rotate: false - xy: 305, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-phantom-factory - rotate: false - xy: 568, 432 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-phase-conduit - rotate: false - xy: 315, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -phase-conduit - rotate: false - xy: 315, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-phase-conveyor - rotate: false - xy: 325, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -phase-conveyor - rotate: false - xy: 325, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-phase-wall - rotate: false - xy: 335, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -phase-wall - rotate: false - xy: 335, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-phase-wall-large - rotate: false - xy: 586, 432 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -phase-wall-large - rotate: false - xy: 586, 432 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-phase-weaver - rotate: false - xy: 604, 432 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-plasma-drill - rotate: false - xy: 847, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -block-icon-plastanium-compressor - rotate: false - xy: 527, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -plastanium-compressor - rotate: false - xy: 527, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-pneumatic-drill - rotate: false - xy: 545, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-power-node - rotate: false - xy: 345, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -power-node - rotate: false - xy: 345, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-power-node-large - rotate: false - xy: 563, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -power-node-large - rotate: false - xy: 563, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-powerinfinite - rotate: false - xy: 355, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -powerinfinite - rotate: false - xy: 355, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-powervoid - rotate: false - xy: 365, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -powervoid - rotate: false - xy: 365, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-pulse-conduit - rotate: false - xy: 375, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-pulverizer - rotate: false - xy: 385, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-pyratite-mixer - rotate: false - xy: 581, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -pyratite-mixer - rotate: false - xy: 581, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-reconstructor - rotate: false - xy: 599, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -dagger-factory - rotate: false - xy: 599, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -phantom-factory - rotate: false - xy: 599, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -reconstructor - rotate: false - xy: 599, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -spirit-factory - rotate: false - xy: 599, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -wraith-factory - rotate: false - xy: 599, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-repair-point - rotate: false - xy: 395, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -repair-point - rotate: false - xy: 395, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-revenant-factory - rotate: false - xy: 881, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -block-icon-ripple - rotate: false - xy: 366, 364 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-rock - rotate: false - xy: 405, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -rock1 - rotate: false - xy: 405, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-rotary-pump - rotate: false - xy: 617, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -rotary-pump - rotate: false - xy: 617, 414 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-router - rotate: false - xy: 415, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -router - rotate: false - xy: 415, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-rtg-generator - rotate: false - xy: 980, 435 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -rtg-generator - rotate: false - xy: 980, 435 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-salvo - rotate: false - xy: 980, 417 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-sand - rotate: false - xy: 425, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -sand1 - rotate: false - xy: 425, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-scorch - rotate: false - xy: 435, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-separator - rotate: false - xy: 445, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -separator - rotate: false - xy: 445, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-shock-mine - rotate: false - xy: 455, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -shock-mine - rotate: false - xy: 455, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-shrub - rotate: false - xy: 465, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -shrub - rotate: false - xy: 465, 250 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-silicon-smelter - rotate: false - xy: 962, 397 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -silicon-smelter - rotate: false - xy: 962, 397 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-smelter - rotate: false - xy: 85, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -smelter - rotate: false - xy: 85, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-snow - rotate: false - xy: 95, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -snow1 - rotate: false - xy: 95, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-solar-panel - rotate: false - xy: 105, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -solar-panel - rotate: false - xy: 105, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-solar-panel-large - rotate: false - xy: 392, 364 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -solar-panel-large - rotate: false - xy: 392, 364 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-solidifer - rotate: false - xy: 115, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -solidifer - rotate: false - xy: 115, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-sorter - rotate: false - xy: 125, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -sorter - rotate: false - xy: 125, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-space - rotate: false - xy: 135, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -space - rotate: false - xy: 135, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-spawn - rotate: false - xy: 145, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -spawn - rotate: false - xy: 145, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-spectre - rotate: false - xy: 915, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -block-icon-spirit-factory - rotate: false - xy: 980, 399 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-stone - rotate: false - xy: 155, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -stone1 - rotate: false - xy: 155, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-surge-wall - rotate: false - xy: 165, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -surge-wall - rotate: false - xy: 165, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-surge-wall-large - rotate: false - xy: 458, 338 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -surge-wall-large - rotate: false - xy: 458, 338 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-swarmer - rotate: false - xy: 476, 342 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-tar - rotate: false - xy: 175, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -tar - rotate: false - xy: 175, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-tau-mech-pad - rotate: false - xy: 456, 320 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -tau-mech-pad - rotate: false - xy: 456, 320 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-thermal-generator - rotate: false - xy: 896, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -thermal-generator - rotate: false - xy: 896, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-thermal-pump - rotate: false - xy: 914, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -thermal-pump - rotate: false - xy: 914, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-thorium-reactor - rotate: false - xy: 314, 349 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thorium-reactor - rotate: false - xy: 314, 349 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-thorium-wall - rotate: false - xy: 185, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -thorium-wall - rotate: false - xy: 185, 148 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-thorium-wall-large - rotate: false - xy: 932, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -thorium-wall-large - rotate: false - xy: 932, 391 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-titan-factory - rotate: false - xy: 288, 346 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-titanium-conveyor - rotate: false - xy: 84, 138 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -titanium-conveyor-0-0 - rotate: false - xy: 84, 138 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-trident-ship-pad - rotate: false - xy: 896, 373 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -trident-ship-pad - rotate: false - xy: 896, 373 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-turbine-generator - rotate: false - xy: 914, 373 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -turbine-generator - rotate: false - xy: 914, 373 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-unloader - rotate: false - xy: 94, 138 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -unloader - rotate: false - xy: 94, 138 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-vault - rotate: false - xy: 340, 338 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -vault - rotate: false - xy: 340, 338 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -block-icon-water - rotate: false - xy: 84, 128 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -water - rotate: false - xy: 84, 128 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -block-icon-water-extractor - rotate: false - xy: 932, 373 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-wave - rotate: false - xy: 456, 302 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-icon-wraith-factory - rotate: false - xy: 950, 379 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -deepwater-cliff-edge - rotate: false - xy: 104, 88 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -deepwater-cliff-edge-1 - rotate: false - xy: 114, 88 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -deepwater-cliff-edge-2 - rotate: false - xy: 124, 88 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -deepwater-cliff-side - rotate: false - xy: 134, 88 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -dirt-cliff-edge - rotate: false - xy: 174, 88 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -dirt-cliff-edge-1 - rotate: false - xy: 184, 88 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -dirt-cliff-edge-2 - rotate: false - xy: 83, 78 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -dirt-cliff-side - rotate: false - xy: 83, 68 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -lava-cliff-edge - rotate: false - xy: 133, 48 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -lava-cliff-edge-1 - rotate: false - xy: 143, 48 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -lava-cliff-edge-2 - rotate: false - xy: 153, 48 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -lava-cliff-side - rotate: false - xy: 163, 48 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -liquid-icon-cryofluid - rotate: false - xy: 1004, 365 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -liquid-icon-lava - rotate: false - xy: 1014, 397 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -liquid-icon-oil - rotate: false - xy: 1014, 387 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -liquid-icon-water - rotate: false - xy: 1014, 377 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 mech-icon-alpha-mech rotate: false - xy: 599, 250 - size: 12, 12 - orig: 12, 12 + xy: 505, 75 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 mech-icon-dart-ship rotate: false - xy: 613, 250 - size: 12, 12 - orig: 12, 12 + xy: 505, 25 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 mech-icon-delta-mech rotate: false - xy: 627, 250 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -mech-icon-omega-mech - rotate: false - xy: 165, 158 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -mech-icon-tau-mech - rotate: false - xy: 181, 158 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -mech-icon-trident-ship - rotate: false - xy: 68, 140 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -trident-ship - rotate: false - xy: 68, 140 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -metalfloor-cliff-edge - rotate: false - xy: 682, 333 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -metalfloor-cliff-edge-1 - rotate: false - xy: 682, 323 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -metalfloor-cliff-edge-2 - rotate: false - xy: 682, 313 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -metalfloor-cliff-side - rotate: false - xy: 682, 303 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-blackstone1 - rotate: false - xy: 682, 283 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-blackstone2 - rotate: false - xy: 682, 273 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-blackstone3 - rotate: false - xy: 682, 263 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-grass1 - rotate: false - xy: 692, 355 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-grass2 - rotate: false - xy: 692, 345 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-grass3 - rotate: false - xy: 692, 335 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-ice1 - rotate: false - xy: 692, 325 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-ice2 - rotate: false - xy: 692, 315 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-ice3 - rotate: false - xy: 692, 305 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-sand1 - rotate: false - xy: 692, 295 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-sand2 - rotate: false - xy: 692, 285 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-sand3 - rotate: false - xy: 692, 275 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-snow1 - rotate: false - xy: 692, 265 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-snow2 - rotate: false - xy: 689, 253 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-snow3 - rotate: false - xy: 689, 243 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-stone1 - rotate: false - xy: 689, 233 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-stone2 - rotate: false - xy: 207, 238 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-coal-stone3 - rotate: false - xy: 207, 228 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-blackstone1 - rotate: false - xy: 207, 218 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-blackstone2 - rotate: false - xy: 217, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-blackstone3 - rotate: false - xy: 217, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-grass1 - rotate: false - xy: 227, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-grass2 - rotate: false - xy: 217, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-grass3 - rotate: false - xy: 227, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-ice1 - rotate: false - xy: 237, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-ice2 - rotate: false - xy: 227, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-ice3 - rotate: false - xy: 237, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-sand1 - rotate: false - xy: 247, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-sand2 - rotate: false - xy: 237, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-sand3 - rotate: false - xy: 247, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-snow1 - rotate: false - xy: 257, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-snow2 - rotate: false - xy: 247, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-snow3 - rotate: false - xy: 257, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-stone1 - rotate: false - xy: 267, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-stone2 - rotate: false - xy: 257, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-copper-stone3 - rotate: false - xy: 267, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-blackstone1 - rotate: false - xy: 277, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-blackstone2 - rotate: false - xy: 267, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-blackstone3 - rotate: false - xy: 277, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-grass1 - rotate: false - xy: 287, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-grass2 - rotate: false - xy: 277, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-grass3 - rotate: false - xy: 287, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-ice1 - rotate: false - xy: 297, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-ice2 - rotate: false - xy: 287, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-ice3 - rotate: false - xy: 297, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-sand1 - rotate: false - xy: 307, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-sand2 - rotate: false - xy: 297, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-sand3 - rotate: false - xy: 307, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-snow1 - rotate: false - xy: 317, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-snow2 - rotate: false - xy: 307, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-snow3 - rotate: false - xy: 317, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-stone1 - rotate: false - xy: 327, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-stone2 - rotate: false - xy: 317, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-lead-stone3 - rotate: false - xy: 327, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-blackstone1 - rotate: false - xy: 337, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-blackstone2 - rotate: false - xy: 327, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-blackstone3 - rotate: false - xy: 337, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-grass1 - rotate: false - xy: 347, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-grass2 - rotate: false - xy: 337, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-grass3 - rotate: false - xy: 347, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-ice1 - rotate: false - xy: 357, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-ice2 - rotate: false - xy: 347, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-ice3 - rotate: false - xy: 357, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-sand1 - rotate: false - xy: 367, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-sand2 - rotate: false - xy: 357, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-sand3 - rotate: false - xy: 367, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-snow1 - rotate: false - xy: 377, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-snow2 - rotate: false - xy: 367, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-snow3 - rotate: false - xy: 377, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-stone1 - rotate: false - xy: 387, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-stone2 - rotate: false - xy: 377, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-thorium-stone3 - rotate: false - xy: 387, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-blackstone1 - rotate: false - xy: 397, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-blackstone2 - rotate: false - xy: 387, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-blackstone3 - rotate: false - xy: 397, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-grass1 - rotate: false - xy: 407, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-grass2 - rotate: false - xy: 397, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-grass3 - rotate: false - xy: 407, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-ice1 - rotate: false - xy: 417, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-ice2 - rotate: false - xy: 407, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-ice3 - rotate: false - xy: 417, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-sand1 - rotate: false - xy: 427, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-sand2 - rotate: false - xy: 417, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-sand3 - rotate: false - xy: 427, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-snow1 - rotate: false - xy: 437, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-snow2 - rotate: false - xy: 427, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-snow3 - rotate: false - xy: 437, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-stone1 - rotate: false - xy: 447, 240 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-stone2 - rotate: false - xy: 437, 220 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -ore-titanium-stone3 - rotate: false - xy: 447, 230 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -sand-cliff-edge - rotate: false - xy: 527, 242 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -sand-cliff-edge-1 - rotate: false - xy: 527, 232 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -sand-cliff-edge-2 - rotate: false - xy: 517, 222 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -sand-cliff-side - rotate: false - xy: 537, 242 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -snow-cliff-edge - rotate: false - xy: 567, 232 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -snow-cliff-edge-1 - rotate: false - xy: 557, 222 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -snow-cliff-edge-2 - rotate: false - xy: 567, 222 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -snow-cliff-side - rotate: false - xy: 195, 142 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -space-cliff-edge - rotate: false - xy: 194, 122 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -space-cliff-edge-1 - rotate: false - xy: 194, 112 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -space-cliff-edge-2 - rotate: false - xy: 194, 102 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -space-cliff-side - rotate: false - xy: 194, 92 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -tar-cliff-edge - rotate: false - xy: 194, 82 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -tar-cliff-edge-1 - rotate: false - xy: 204, 82 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -tar-cliff-edge-2 - rotate: false - xy: 193, 72 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -tar-cliff-side - rotate: false - xy: 193, 62 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -unit-icon-dagger - rotate: false - xy: 726, 387 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -unit-icon-fortress - rotate: false - xy: 584, 342 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -unit-icon-titan - rotate: false - xy: 602, 360 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -unit-icon-wraith - rotate: false - xy: 986, 349 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -wraith - rotate: false - xy: 986, 349 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -item-biomatter - rotate: false - xy: 143, 58 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-blast-compound - rotate: false - xy: 153, 68 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-coal - rotate: false - xy: 163, 78 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-copper - rotate: false - xy: 153, 58 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-dense-alloy - rotate: false - xy: 163, 68 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-lead - rotate: false - xy: 173, 78 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-phase-fabric - rotate: false - xy: 163, 58 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-plastanium - rotate: false - xy: 173, 68 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-pyratite - rotate: false - xy: 183, 78 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-sand - rotate: false - xy: 173, 58 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-silicon - rotate: false - xy: 183, 68 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-stone - rotate: false - xy: 183, 58 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-surge-alloy - rotate: false - xy: 103, 48 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-thorium - rotate: false - xy: 113, 48 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -item-titanium - rotate: false - xy: 123, 48 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -liquid-icon - rotate: false - xy: 1004, 375 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -alpha-mech - rotate: false - xy: 197, 166 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -alpha-mech-base - rotate: false - xy: 197, 152 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -alpha-mech-leg - rotate: false - xy: 274, 324 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -delta-mech - rotate: false - xy: 628, 306 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -delta-mech-base - rotate: false - xy: 632, 320 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -delta-mech-leg - rotate: false - xy: 634, 292 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -omega-mech - rotate: false - xy: 68, 124 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -omega-mech-armor - rotate: false - xy: 68, 108 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -omega-mech-base - rotate: false - xy: 68, 92 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -omega-mech-leg - rotate: false - xy: 67, 76 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -tau-mech - rotate: false - xy: 620, 334 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -tau-mech-base - rotate: false - xy: 998, 419 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -tau-mech-leg - rotate: false - xy: 998, 405 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -dart-ship - rotate: false - xy: 620, 278 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -glaive-ship - rotate: false - xy: 1, 1 - size: 14, 14 - orig: 14, 14 + xy: 1187, 664 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 mech-icon-glaive-ship rotate: false - xy: 1, 1 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -javelin-ship - rotate: false - xy: 634, 264 - size: 12, 12 - orig: 12, 12 + xy: 1766, 1173 + size: 56, 56 + orig: 56, 56 offset: 0, 0 index: -1 mech-icon-javelin-ship rotate: false - xy: 634, 264 - size: 12, 12 - orig: 12, 12 + xy: 1237, 664 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mech-icon-omega-mech + rotate: false + xy: 1525, 961 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +mech-icon-tau-mech + rotate: false + xy: 1824, 1173 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +mech-icon-trident-ship + rotate: false + xy: 1525, 903 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +mechanical-drill-icon-full + rotate: false + xy: 771, 873 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mechanical-drill-icon-large + rotate: false + xy: 1287, 661 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mechanical-drill-icon-medium + rotate: false + xy: 1843, 919 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mechanical-drill-icon-small + rotate: false + xy: 1287, 20 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mechanical-pump-icon-large + rotate: false + xy: 1337, 661 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mechanical-pump-icon-small + rotate: false + xy: 1313, 46 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +meltdown + rotate: false + xy: 656, 1691 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +meltdown-icon-full + rotate: false + xy: 916, 1691 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +meltdown-icon-large + rotate: false + xy: 1387, 627 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +meltdown-icon-medium + rotate: false + xy: 1911, 965 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +meltdown-icon-small + rotate: false + xy: 1313, 20 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +melter-icon-large + rotate: false + xy: 1437, 627 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +melter-icon-small + rotate: false + xy: 1345, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mend-projector-icon-large + rotate: false + xy: 1487, 595 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mend-projector-icon-medium + rotate: false + xy: 1945, 965 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mend-projector-icon-small + rotate: false + xy: 1371, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-2-icon-large + rotate: false + xy: 1537, 579 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-2-icon-small + rotate: false + xy: 1397, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-3-icon-large + rotate: false + xy: 1587, 579 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-3-icon-small + rotate: false + xy: 1423, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-5-icon-large + rotate: false + xy: 1637, 579 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-5-icon-small + rotate: false + xy: 2022, 1703 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-damaged-icon-large + rotate: false + xy: 1687, 579 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-damaged-icon-small + rotate: false + xy: 2022, 1677 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-edge + rotate: false + xy: 1, 309 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +metal-floor-icon-large + rotate: false + xy: 1641, 891 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-icon-small + rotate: false + xy: 1808, 259 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +multi-press-icon-large + rotate: false + xy: 1691, 941 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +multi-press-icon-medium + rotate: false + xy: 1979, 897 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +multi-press-icon-small + rotate: false + xy: 1834, 259 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +oil-extractor-icon-full + rotate: false + xy: 1357, 1495 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +oil-extractor-icon-large + rotate: false + xy: 1691, 891 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +oil-extractor-icon-medium + rotate: false + xy: 2013, 897 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +oil-extractor-icon-small + rotate: false + xy: 1860, 259 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-large + rotate: false + xy: 1683, 841 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-medium + rotate: false + xy: 1783, 851 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-small + rotate: false + xy: 1886, 267 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-coal-holostone-icon-large + rotate: false + xy: 495, 207 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-coal-holostone-icon-small + rotate: false + xy: 1912, 267 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-coal-holostone1 + rotate: false + xy: 1817, 885 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-holostone2 + rotate: false + xy: 1817, 851 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-holostone3 + rotate: false + xy: 1825, 817 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-holostone-icon-full + rotate: false + xy: 1825, 817 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-holostone-icon-medium + rotate: false + xy: 1825, 817 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-sand-icon-large + rotate: false + xy: 545, 407 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-coal-sand-icon-small + rotate: false + xy: 1938, 267 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-coal-sand1 + rotate: false + xy: 1851, 863 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-sand2 + rotate: false + xy: 1885, 863 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-sand3 + rotate: false + xy: 1919, 863 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-sand-icon-full + rotate: false + xy: 1919, 863 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-sand-icon-medium + rotate: false + xy: 1919, 863 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-icon-large + rotate: false + xy: 545, 357 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-icon-small + rotate: false + xy: 1964, 267 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-red-icon-large + rotate: false + xy: 545, 307 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-red-icon-small + rotate: false + xy: 1990, 267 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-red1 + rotate: false + xy: 1893, 829 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-red2 + rotate: false + xy: 1927, 829 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-red3 + rotate: false + xy: 1961, 829 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-red-icon-full + rotate: false + xy: 1961, 829 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-red-icon-medium + rotate: false + xy: 1961, 829 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone1 + rotate: false + xy: 1953, 863 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone2 + rotate: false + xy: 1987, 863 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone3 + rotate: false + xy: 1859, 829 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-icon-full + rotate: false + xy: 1859, 829 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stained-stone-icon-medium + rotate: false + xy: 1859, 829 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stone-icon-large + rotate: false + xy: 545, 257 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-coal-stone-icon-small + rotate: false + xy: 2016, 267 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-coal-stone1 + rotate: false + xy: 1995, 829 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stone2 + rotate: false + xy: 1859, 795 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stone3 + rotate: false + xy: 1893, 795 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stone-icon-full + rotate: false + xy: 1893, 795 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-stone-icon-medium + rotate: false + xy: 1893, 795 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-holostone-icon-large + rotate: false + xy: 545, 207 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-copper-holostone-icon-small + rotate: false + xy: 1886, 241 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-copper-holostone1 + rotate: false + xy: 1927, 795 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-holostone2 + rotate: false + xy: 1961, 795 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-holostone3 + rotate: false + xy: 1995, 795 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-holostone-icon-full + rotate: false + xy: 1995, 795 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-holostone-icon-medium + rotate: false + xy: 1995, 795 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-sand-icon-large + rotate: false + xy: 595, 423 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-copper-sand-icon-small + rotate: false + xy: 1912, 241 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-copper-sand1 + rotate: false + xy: 1837, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-sand2 + rotate: false + xy: 1837, 727 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-sand3 + rotate: false + xy: 1871, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-sand-icon-full + rotate: false + xy: 1871, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-sand-icon-medium + rotate: false + xy: 1871, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-icon-large + rotate: false + xy: 595, 373 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-icon-small + rotate: false + xy: 1938, 241 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-red-icon-large + rotate: false + xy: 645, 423 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-red-icon-small + rotate: false + xy: 1964, 241 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-red1 + rotate: false + xy: 1837, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-red2 + rotate: false + xy: 1939, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-red3 + rotate: false + xy: 1905, 727 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-red-icon-full + rotate: false + xy: 1905, 727 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-red-icon-medium + rotate: false + xy: 1905, 727 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone1 + rotate: false + xy: 1837, 693 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone2 + rotate: false + xy: 1905, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone3 + rotate: false + xy: 1871, 727 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-icon-full + rotate: false + xy: 1871, 727 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stained-stone-icon-medium + rotate: false + xy: 1871, 727 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stone-icon-large + rotate: false + xy: 595, 323 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-copper-stone-icon-small + rotate: false + xy: 1990, 241 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-copper-stone1 + rotate: false + xy: 1871, 693 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stone2 + rotate: false + xy: 1837, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stone3 + rotate: false + xy: 1973, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stone-icon-full + rotate: false + xy: 1973, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper-stone-icon-medium + rotate: false + xy: 1973, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-holostone-icon-large + rotate: false + xy: 645, 373 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-lead-holostone-icon-small + rotate: false + xy: 2016, 241 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-lead-holostone1 + rotate: false + xy: 1939, 727 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-holostone2 + rotate: false + xy: 1905, 693 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-holostone3 + rotate: false + xy: 1871, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-holostone-icon-full + rotate: false + xy: 1871, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-holostone-icon-medium + rotate: false + xy: 1871, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-sand-icon-large + rotate: false + xy: 595, 273 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-lead-sand-icon-small + rotate: false + xy: 1339, 46 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-lead-sand1 + rotate: false + xy: 1837, 591 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-sand2 + rotate: false + xy: 1973, 727 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-sand3 + rotate: false + xy: 1939, 693 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-sand-icon-full + rotate: false + xy: 1939, 693 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-sand-icon-medium + rotate: false + xy: 1939, 693 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-icon-large + rotate: false + xy: 645, 323 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-icon-small + rotate: false + xy: 1339, 20 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-red-icon-large + rotate: false + xy: 595, 223 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-red-icon-small + rotate: false + xy: 1365, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-red1 + rotate: false + xy: 1973, 693 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-red2 + rotate: false + xy: 1939, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-red3 + rotate: false + xy: 1905, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-red-icon-full + rotate: false + xy: 1905, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-red-icon-medium + rotate: false + xy: 1905, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone1 + rotate: false + xy: 1905, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone2 + rotate: false + xy: 1871, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone3 + rotate: false + xy: 1837, 557 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-icon-full + rotate: false + xy: 1837, 557 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stained-stone-icon-medium + rotate: false + xy: 1837, 557 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stone-icon-large + rotate: false + xy: 645, 273 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-lead-stone-icon-small + rotate: false + xy: 1365, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-lead-stone1 + rotate: false + xy: 1871, 591 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stone2 + rotate: false + xy: 1973, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stone3 + rotate: false + xy: 1939, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stone-icon-full + rotate: false + xy: 1939, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead-stone-icon-medium + rotate: false + xy: 1939, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-holostone-icon-large + rotate: false + xy: 645, 223 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-scrap-holostone-icon-small + rotate: false + xy: 1391, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-scrap-holostone1 + rotate: false + xy: 1905, 591 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-holostone2 + rotate: false + xy: 1871, 557 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-holostone3 + rotate: false + xy: 1973, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-holostone-icon-full + rotate: false + xy: 1973, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-holostone-icon-medium + rotate: false + xy: 1973, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-sand-icon-large + rotate: false + xy: 695, 423 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-scrap-sand-icon-small + rotate: false + xy: 1391, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-scrap-sand1 + rotate: false + xy: 1939, 591 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-sand2 + rotate: false + xy: 1905, 557 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-sand3 + rotate: false + xy: 1973, 591 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-sand-icon-full + rotate: false + xy: 1973, 591 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-sand-icon-medium + rotate: false + xy: 1973, 591 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-snow-icon-large + rotate: false + xy: 695, 373 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-scrap-snow-icon-small + rotate: false + xy: 1417, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-scrap-snow1 + rotate: false + xy: 1939, 557 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-snow2 + rotate: false + xy: 1973, 557 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-snow3 + rotate: false + xy: 2007, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-snow-icon-full + rotate: false + xy: 2007, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-snow-icon-medium + rotate: false + xy: 2007, 761 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-icon-large + rotate: false + xy: 695, 323 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-icon-small + rotate: false + xy: 1417, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red-icon-large + rotate: false + xy: 695, 273 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red-icon-small + rotate: false + xy: 1443, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red1 + rotate: false + xy: 2007, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red2 + rotate: false + xy: 2007, 591 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red3 + rotate: false + xy: 2007, 557 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red-icon-full + rotate: false + xy: 2007, 557 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-red-icon-medium + rotate: false + xy: 2007, 557 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone1 + rotate: false + xy: 2007, 727 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone2 + rotate: false + xy: 2007, 693 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone3 + rotate: false + xy: 2007, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-icon-full + rotate: false + xy: 2007, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stained-stone-icon-medium + rotate: false + xy: 2007, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stone-icon-large + rotate: false + xy: 695, 223 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-scrap-stone-icon-small + rotate: false + xy: 1443, 25 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-scrap-stone1 + rotate: false + xy: 1863, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stone2 + rotate: false + xy: 1897, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stone3 + rotate: false + xy: 1931, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stone-icon-full + rotate: false + xy: 1931, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-stone-icon-medium + rotate: false + xy: 1931, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-holostone-icon-large + rotate: false + xy: 745, 427 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-thorium-holostone-icon-small + rotate: false + xy: 1701, 254 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-thorium-holostone1 + rotate: false + xy: 1965, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-holostone2 + rotate: false + xy: 1999, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-holostone3 + rotate: false + xy: 1865, 489 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-holostone-icon-full + rotate: false + xy: 1865, 489 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-holostone-icon-medium + rotate: false + xy: 1865, 489 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-sand-icon-large + rotate: false + xy: 745, 377 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-thorium-sand-icon-small + rotate: false + xy: 1697, 228 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-thorium-sand1 + rotate: false + xy: 1865, 455 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-sand2 + rotate: false + xy: 1899, 489 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-sand3 + rotate: false + xy: 1899, 455 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-sand-icon-full + rotate: false + xy: 1899, 455 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-sand-icon-medium + rotate: false + xy: 1899, 455 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-icon-large + rotate: false + xy: 795, 427 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-icon-small + rotate: false + xy: 1697, 202 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-red-icon-large + rotate: false + xy: 745, 327 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-red-icon-small + rotate: false + xy: 1697, 176 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-red1 + rotate: false + xy: 1967, 455 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-red2 + rotate: false + xy: 2001, 489 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-red3 + rotate: false + xy: 2001, 455 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-red-icon-full + rotate: false + xy: 2001, 455 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-red-icon-medium + rotate: false + xy: 2001, 455 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone1 + rotate: false + xy: 1933, 489 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone2 + rotate: false + xy: 1933, 455 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone3 + rotate: false + xy: 1967, 489 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-icon-full + rotate: false + xy: 1967, 489 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stained-stone-icon-medium + rotate: false + xy: 1967, 489 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stone-icon-large + rotate: false + xy: 795, 377 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-thorium-stone-icon-small + rotate: false + xy: 1727, 251 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-thorium-stone1 + rotate: false + xy: 1893, 421 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stone2 + rotate: false + xy: 1893, 387 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stone3 + rotate: false + xy: 1927, 421 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stone-icon-full + rotate: false + xy: 1927, 421 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium-stone-icon-medium + rotate: false + xy: 1927, 421 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-holostone-icon-large + rotate: false + xy: 845, 427 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-titanium-holostone-icon-small + rotate: false + xy: 1753, 251 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-titanium-holostone1 + rotate: false + xy: 1927, 387 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-holostone2 + rotate: false + xy: 1961, 421 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-holostone3 + rotate: false + xy: 1961, 387 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-holostone-icon-full + rotate: false + xy: 1961, 387 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-holostone-icon-medium + rotate: false + xy: 1961, 387 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-sand-icon-large + rotate: false + xy: 745, 277 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-titanium-sand-icon-small + rotate: false + xy: 1779, 251 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-titanium-sand1 + rotate: false + xy: 1995, 421 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-sand2 + rotate: false + xy: 1995, 387 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-sand3 + rotate: false + xy: 1893, 353 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-sand-icon-full + rotate: false + xy: 1893, 353 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-sand-icon-medium + rotate: false + xy: 1893, 353 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-icon-large + rotate: false + xy: 795, 327 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-icon-small + rotate: false + xy: 1723, 225 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-red-icon-large + rotate: false + xy: 845, 377 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-red-icon-small + rotate: false + xy: 1723, 199 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-red1 + rotate: false + xy: 579, 139 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-red2 + rotate: false + xy: 613, 139 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-red3 + rotate: false + xy: 647, 139 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-red-icon-full + rotate: false + xy: 647, 139 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-red-icon-medium + rotate: false + xy: 647, 139 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone1 + rotate: false + xy: 1927, 353 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone2 + rotate: false + xy: 1961, 353 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone3 + rotate: false + xy: 1995, 353 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-icon-full + rotate: false + xy: 1995, 353 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stained-stone-icon-medium + rotate: false + xy: 1995, 353 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stone-icon-large + rotate: false + xy: 745, 227 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ore-titanium-stone-icon-small + rotate: false + xy: 1749, 225 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ore-titanium-stone1 + rotate: false + xy: 681, 139 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stone2 + rotate: false + xy: 589, 105 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stone3 + rotate: false + xy: 623, 105 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stone-icon-full + rotate: false + xy: 623, 105 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium-stone-icon-medium + rotate: false + xy: 623, 105 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +overdrive-projector-icon-large + rotate: false + xy: 795, 277 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +overdrive-projector-icon-medium + rotate: false + xy: 589, 71 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +overdrive-projector-icon-small + rotate: false + xy: 1749, 199 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +overflow-gate-icon-large + rotate: false + xy: 845, 327 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +overflow-gate-icon-small + rotate: false + xy: 1775, 225 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phantom-factory-icon-full + rotate: false + xy: 771, 675 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phantom-factory-icon-large + rotate: false + xy: 795, 227 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phantom-factory-icon-medium + rotate: false + xy: 589, 37 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phantom-factory-icon-small + rotate: false + xy: 1775, 199 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-conduit-icon-large + rotate: false + xy: 845, 277 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-conduit-icon-small + rotate: false + xy: 1723, 173 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-conveyor-icon-large + rotate: false + xy: 845, 227 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-conveyor-icon-small + rotate: false + xy: 1749, 173 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-wall-icon-large + rotate: false + xy: 529, 157 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-wall-icon-small + rotate: false + xy: 1775, 173 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-wall-large-icon-large + rotate: false + xy: 895, 427 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-wall-large-icon-medium + rotate: false + xy: 657, 3 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-large-icon-small + rotate: false + xy: 1697, 150 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-weaver-icon-full + rotate: false + xy: 781, 477 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-weaver-icon-large + rotate: false + xy: 895, 377 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-weaver-icon-medium + rotate: false + xy: 691, 3 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-weaver-icon-small + rotate: false + xy: 1723, 147 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pine-icon-large + rotate: false + xy: 895, 327 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pine-icon-small + rotate: false + xy: 1749, 147 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-large + rotate: false + xy: 895, 277 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-medium + rotate: false + xy: 759, 109 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-small + rotate: false + xy: 1775, 147 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-full + rotate: false + xy: 1575, 1297 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-large + rotate: false + xy: 895, 227 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-medium + rotate: false + xy: 725, 75 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-small + rotate: false + xy: 1805, 233 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +power-node-icon-large + rotate: false + xy: 595, 173 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-node-icon-small + rotate: false + xy: 1831, 233 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +power-node-large-icon-large + rotate: false + xy: 645, 173 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-node-large-icon-medium + rotate: false + xy: 725, 41 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-node-large-icon-small + rotate: false + xy: 1857, 233 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +power-source-icon-large + rotate: false + xy: 695, 173 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-source-icon-small + rotate: false + xy: 1801, 207 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +power-void-icon-large + rotate: false + xy: 745, 177 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-void-icon-small + rotate: false + xy: 1801, 181 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pulse-conduit-icon-full + rotate: false + xy: 793, 75 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-icon-large + rotate: false + xy: 795, 177 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pulse-conduit-icon-small + rotate: false + xy: 1827, 207 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pulverizer-icon-full + rotate: false + xy: 861, 41 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulverizer-icon-large + rotate: false + xy: 845, 177 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pulverizer-icon-small + rotate: false + xy: 1801, 155 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-large + rotate: false + xy: 895, 177 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-medium + rotate: false + xy: 895, 109 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-small + rotate: false + xy: 1827, 181 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +revenant-factory-icon-full + rotate: false + xy: 1176, 1691 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +revenant-factory-icon-large + rotate: false + xy: 1725, 791 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +revenant-factory-icon-medium + rotate: false + xy: 895, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +revenant-factory-icon-small + rotate: false + xy: 1853, 207 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ripple + rotate: false + xy: 845, 1397 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ripple-icon-full + rotate: false + xy: 943, 1397 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ripple-icon-large + rotate: false + xy: 1737, 691 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ripple-icon-medium + rotate: false + xy: 1249, 443 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ripple-icon-small + rotate: false + xy: 1827, 155 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +rocks-icon-large + rotate: false + xy: 1775, 791 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rocks-icon-small + rotate: false + xy: 1853, 181 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +rotary-pump-icon-large + rotate: false + xy: 1787, 741 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rotary-pump-icon-medium + rotate: false + xy: 1249, 409 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rotary-pump-icon-small + rotate: false + xy: 1853, 155 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +router-icon-large + rotate: false + xy: 1787, 691 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +router-icon-small + rotate: false + xy: 1801, 129 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +rtg-generator-icon-large + rotate: false + xy: 1787, 641 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rtg-generator-icon-medium + rotate: false + xy: 1317, 409 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rtg-generator-icon-small + rotate: false + xy: 1827, 129 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +salvo + rotate: false + xy: 847, 477 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +salvo-icon-full + rotate: false + xy: 1443, 1223 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +salvo-icon-large + rotate: false + xy: 1787, 591 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +salvo-icon-medium + rotate: false + xy: 1313, 375 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +salvo-icon-small + rotate: false + xy: 1853, 129 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sand-edge + rotate: false + xy: 1, 211 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +sand-icon-large + rotate: false + xy: 1737, 541 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sand-icon-small + rotate: false + xy: 1883, 215 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sand-water-edge + rotate: false + xy: 1, 113 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +sand-water-icon-large + rotate: false + xy: 1787, 541 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sand-water-icon-small + rotate: false + xy: 1909, 215 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-large + rotate: false + xy: 1766, 1123 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-medium + rotate: false + xy: 1357, 137 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-small + rotate: false + xy: 1935, 215 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-large + rotate: false + xy: 1816, 1123 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-medium + rotate: false + xy: 1357, 103 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-small + rotate: false + xy: 1961, 215 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-icon-large + rotate: false + xy: 1866, 1123 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-icon-small + rotate: false + xy: 1987, 215 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-large + rotate: false + xy: 1916, 1151 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-medium + rotate: false + xy: 1395, 307 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-small + rotate: false + xy: 2013, 215 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +separator-icon-large + rotate: false + xy: 1966, 1151 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +separator-icon-medium + rotate: false + xy: 1391, 239 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +separator-icon-small + rotate: false + xy: 1905, 189 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shock-mine-icon-large + rotate: false + xy: 1916, 1101 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shock-mine-icon-small + rotate: false + xy: 1905, 163 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +silicon-smelter-icon-large + rotate: false + xy: 879, 671 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +silicon-smelter-icon-medium + rotate: false + xy: 1391, 137 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +silicon-smelter-icon-small + rotate: false + xy: 1931, 189 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +snow-edge + rotate: false + xy: 1, 15 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +snow-icon-large + rotate: false + xy: 879, 621 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snow-icon-small + rotate: false + xy: 1905, 137 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +snowrocks-icon-large + rotate: false + xy: 929, 671 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snowrocks-icon-small + rotate: false + xy: 1931, 163 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +solar-panel-icon-large + rotate: false + xy: 879, 571 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +solar-panel-icon-small + rotate: false + xy: 1957, 189 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +solar-panel-large-icon-large + rotate: false + xy: 929, 621 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +solar-panel-large-icon-medium + rotate: false + xy: 1385, 425 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-large-icon-small + rotate: false + xy: 1931, 137 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sorter-icon-large + rotate: false + xy: 929, 571 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sorter-icon-small + rotate: false + xy: 1957, 163 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spawn-icon-large + rotate: false + xy: 979, 656 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spawn-icon-small + rotate: false + xy: 1983, 189 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spectre + rotate: false + xy: 1826, 1691 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +spectre-icon-full + rotate: false + xy: 477, 1561 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +spectre-icon-large + rotate: false + xy: 1029, 656 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spectre-icon-medium + rotate: false + xy: 1483, 393 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spectre-icon-small + rotate: false + xy: 1957, 137 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spirit-factory-icon-full + rotate: false + xy: 1063, 1022 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spirit-factory-icon-large + rotate: false + xy: 1079, 656 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spirit-factory-icon-medium + rotate: false + xy: 1407, 357 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spirit-factory-icon-small + rotate: false + xy: 1983, 163 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spore-cluster-icon-large + rotate: false + xy: 1029, 606 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-cluster-icon-medium + rotate: false + xy: 1517, 377 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-cluster-icon-small + rotate: false + xy: 2009, 189 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-boulder-icon-large + rotate: false + xy: 1129, 656 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-boulder-icon-small + rotate: false + xy: 1983, 137 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-rocks-icon-large + rotate: false + xy: 1079, 606 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-rocks-icon-small + rotate: false + xy: 2009, 163 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-rocks-red-icon-large + rotate: false + xy: 1129, 606 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-rocks-red-icon-small + rotate: false + xy: 2009, 137 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-rocks-yellow-icon-large + rotate: false + xy: 1179, 614 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-rocks-yellow-icon-small + rotate: false + xy: 1879, 110 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-stone-edge + rotate: false + xy: 582, 1951 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +stained-stone-icon-large + rotate: false + xy: 1229, 614 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-stone-icon-small + rotate: false + xy: 1905, 111 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-stone-red-edge + rotate: false + xy: 872, 1951 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +stained-stone-red-icon-large + rotate: false + xy: 1279, 611 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-stone-red-icon-small + rotate: false + xy: 1931, 111 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stained-stone-yellow-edge + rotate: false + xy: 1162, 1951 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +stained-stone-yellow-icon-large + rotate: false + xy: 1329, 611 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stained-stone-yellow-icon-small + rotate: false + xy: 1957, 111 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stone-edge + rotate: false + xy: 1452, 1951 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +stone-icon-large + rotate: false + xy: 979, 556 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stone-icon-small + rotate: false + xy: 1983, 111 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +surge-tower-icon-large + rotate: false + xy: 1029, 556 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +surge-tower-icon-medium + rotate: false + xy: 1459, 255 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-tower-icon-small + rotate: false + xy: 2009, 111 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +surge-wall-icon-large + rotate: false + xy: 1079, 556 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +surge-wall-icon-small + rotate: false + xy: 1715, 121 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +surge-wall-large-icon-large + rotate: false + xy: 1129, 556 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +surge-wall-large-icon-medium + rotate: false + xy: 1459, 187 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-wall-large-icon-small + rotate: false + xy: 1741, 121 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +swarmer + rotate: false + xy: 1195, 988 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +swarmer-icon-full + rotate: false + xy: 1261, 1054 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +swarmer-icon-large + rotate: false + xy: 1229, 564 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +swarmer-icon-medium + rotate: false + xy: 1459, 153 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +swarmer-icon-small + rotate: false + xy: 1767, 121 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +tar-edge + rotate: false + xy: 1742, 1951 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +tar-icon-large + rotate: false + xy: 1279, 561 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +tar-icon-small + rotate: false + xy: 1727, 95 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-large + rotate: false + xy: 1429, 577 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-medium + rotate: false + xy: 1459, 85 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-small + rotate: false + xy: 1753, 95 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thermal-generator-icon-large + rotate: false + xy: 913, 521 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thermal-generator-icon-medium + rotate: false + xy: 1509, 343 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thermal-generator-icon-small + rotate: false + xy: 1727, 69 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thermal-pump-icon-large + rotate: false + xy: 963, 506 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thermal-pump-icon-medium + rotate: false + xy: 1543, 343 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thermal-pump-icon-small + rotate: false + xy: 1753, 69 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thorium-reactor-icon-large + rotate: false + xy: 1013, 506 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thorium-reactor-icon-medium + rotate: false + xy: 1679, 343 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-reactor-icon-small + rotate: false + xy: 1779, 95 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thorium-wall-icon-large + rotate: false + xy: 1063, 506 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thorium-wall-icon-small + rotate: false + xy: 1779, 69 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-large + rotate: false + xy: 1113, 506 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-medium + rotate: false + xy: 1531, 309 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-small + rotate: false + xy: 1805, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thruster-icon-large + rotate: false + xy: 1379, 527 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thruster-icon-medium + rotate: false + xy: 1565, 309 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thruster-icon-small + rotate: false + xy: 1831, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titan-factory-icon-full + rotate: false + xy: 1139, 1299 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +titan-factory-icon-large + rotate: false + xy: 1429, 527 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +titan-factory-icon-medium + rotate: false + xy: 1599, 309 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titan-factory-icon-small + rotate: false + xy: 1805, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titanium-conveyor-icon-large + rotate: false + xy: 1479, 545 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +titanium-conveyor-icon-small + rotate: false + xy: 1831, 77 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titanium-wall-icon-large + rotate: false + xy: 1529, 529 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +titanium-wall-icon-small + rotate: false + xy: 1805, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-large + rotate: false + xy: 1579, 529 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-medium + rotate: false + xy: 1561, 139 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-small + rotate: false + xy: 1831, 51 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-large + rotate: false + xy: 1629, 529 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-medium + rotate: false + xy: 1629, 207 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-small + rotate: false + xy: 1857, 84 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +turbine-generator-icon-large + rotate: false + xy: 1679, 529 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +turbine-generator-icon-medium + rotate: false + xy: 1663, 241 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +turbine-generator-icon-small + rotate: false + xy: 1857, 58 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +unit-icon-chaos-array + rotate: false + xy: 737, 1561 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +unit-icon-crawler + rotate: false + xy: 1479, 495 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unit-icon-dagger + rotate: false + xy: 1529, 479 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unit-icon-eradicator + rotate: false + xy: 291, 241 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +unit-icon-eruptor + rotate: false + xy: 1393, 1091 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +unit-icon-fortress + rotate: false + xy: 1393, 1025 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +unit-icon-titan + rotate: false + xy: 1393, 959 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +unloader-icon-large + rotate: false + xy: 1579, 479 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unloader-icon-small + rotate: false + xy: 1883, 84 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +vault-icon-large + rotate: false + xy: 1629, 479 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +vault-icon-medium + rotate: false + xy: 1595, 139 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +vault-icon-small + rotate: false + xy: 1883, 58 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +water-edge + rotate: false + xy: 291, 897 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +water-extractor-icon-full + rotate: false + xy: 1459, 1025 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +water-extractor-icon-large + rotate: false + xy: 1679, 479 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +water-extractor-icon-medium + rotate: false + xy: 1663, 207 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water-extractor-icon-small + rotate: false + xy: 1909, 85 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +water-icon-large + rotate: false + xy: 1729, 491 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +water-icon-small + rotate: false + xy: 1909, 59 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +wave + rotate: false + xy: 1327, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wave-icon-full + rotate: false + xy: 1393, 827 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wave-icon-large + rotate: false + xy: 1779, 491 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +wave-icon-medium + rotate: false + xy: 1595, 105 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +wave-icon-small + rotate: false + xy: 1935, 85 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +white-tree-dead-icon-large + rotate: false + xy: 1163, 506 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +white-tree-dead-icon-medium + rotate: false + xy: 1629, 139 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +white-tree-dead-icon-small + rotate: false + xy: 1935, 59 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +white-tree-icon-large + rotate: false + xy: 1213, 514 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +white-tree-icon-medium + rotate: false + xy: 1663, 173 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +white-tree-icon-small + rotate: false + xy: 1961, 85 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +wraith-factory-icon-full + rotate: false + xy: 1503, 1157 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wraith-factory-icon-large + rotate: false + xy: 1313, 511 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +wraith-factory-icon-medium + rotate: false + xy: 1629, 105 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +wraith-factory-icon-small + rotate: false + xy: 1961, 59 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-biomatter + rotate: false + xy: 1723, 389 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-blast-compound + rotate: false + xy: 1757, 389 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-coal + rotate: false + xy: 1791, 389 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-copper + rotate: false + xy: 1825, 371 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-graphite + rotate: false + xy: 1859, 371 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-lead + rotate: false + xy: 1733, 1089 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-metaglass + rotate: false + xy: 1767, 1089 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-phase-fabric + rotate: false + xy: 1733, 1055 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-plastanium + rotate: false + xy: 1801, 1089 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-pyratite + rotate: false + xy: 1767, 1055 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-sand + rotate: false + xy: 1733, 1021 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-scrap + rotate: false + xy: 1835, 1089 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-silicon + rotate: false + xy: 1801, 1055 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-surge-alloy + rotate: false + xy: 1869, 1089 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-thorium + rotate: false + xy: 1835, 1055 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-titanium + rotate: false + xy: 1801, 1021 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-cryofluid + rotate: false + xy: 1971, 999 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-oil + rotate: false + xy: 2005, 1033 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-slag + rotate: false + xy: 1741, 919 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-water + rotate: false + xy: 1843, 987 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +alpha-mech + rotate: false + xy: 455, 17 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +alpha-mech-base + rotate: false + xy: 1525, 795 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +alpha-mech-leg + rotate: false + xy: 1575, 779 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +chaos-array + rotate: false + xy: 786, 1821 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +chaos-array-base + rotate: false + xy: 916, 1821 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +chaos-array-leg + rotate: false + xy: 1046, 1821 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +delta-mech + rotate: false + xy: 1087, 806 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +delta-mech-base + rotate: false + xy: 1137, 856 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +delta-mech-leg + rotate: false + xy: 1087, 756 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +eradicator + rotate: false + xy: 323, 1632 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +eradicator-base + rotate: false + xy: 291, 367 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +eradicator-leg + rotate: false + xy: 323, 1506 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +omega-mech + rotate: false + xy: 1525, 845 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +omega-mech-armor + rotate: false + xy: 1583, 1107 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +omega-mech-base + rotate: false + xy: 1583, 1049 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +omega-mech-leg + rotate: false + xy: 1641, 1107 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +tau-mech + rotate: false + xy: 1583, 933 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +tau-mech-base + rotate: false + xy: 1329, 561 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +tau-mech-leg + rotate: false + xy: 1379, 577 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dart-ship + rotate: false + xy: 1087, 856 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +glaive-ship + rotate: false + xy: 421, 117 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +javelin-ship + rotate: false + xy: 1537, 679 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 javelin-ship-shield rotate: false - xy: 648, 264 - size: 12, 12 - orig: 12, 12 + xy: 1587, 679 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +trident-ship + rotate: false + xy: 1641, 991 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +blank + rotate: false + xy: 1727, 277 + size: 1, 1 + orig: 1, 1 offset: 0, 0 index: -1 circle rotate: false - xy: 1, 310 + xy: 323, 1758 size: 201, 201 orig: 201, 201 offset: 0, 0 index: -1 +clear + rotate: false + xy: 1279, 661 + size: 1, 1 + orig: 1, 1 + offset: 0, 0 + index: -1 shape-3 rotate: false - xy: 204, 401 + xy: 1701, 1166 size: 63, 63 orig: 63, 63 offset: 0, 0 index: -1 +bar + rotate: false + xy: 2016, 1125 + size: 27, 36 + split: 9, 9, 9, 9 + orig: 27, 36 + offset: 0, 0 + index: -1 +bar-top + rotate: false + xy: 2016, 1163 + size: 27, 36 + split: 9, 10, 9, 10 + orig: 27, 36 + offset: 0, 0 + index: -1 button rotate: false - xy: 486, 484 + xy: 1905, 1400 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-disabled + rotate: false + xy: 1487, 798 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -5285,7 +8515,7 @@ button index: -1 button-down rotate: false - xy: 204, 322 + xy: 2011, 1634 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -5293,7 +8523,7 @@ button-down index: -1 button-edge-1 rotate: false - xy: 334, 484 + xy: 2011, 1605 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -5301,7 +8531,7 @@ button-edge-1 index: -1 button-edge-2 rotate: false - xy: 1, 133 + xy: 2011, 1576 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -5309,7 +8539,7 @@ button-edge-2 index: -1 button-edge-3 rotate: false - xy: 372, 484 + xy: 2011, 1547 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -5317,7 +8547,7 @@ button-edge-3 index: -1 button-edge-4 rotate: false - xy: 1, 104 + xy: 2011, 1518 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -5325,7 +8555,7 @@ button-edge-4 index: -1 button-over rotate: false - xy: 410, 484 + xy: 2011, 1489 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -5333,7 +8563,7 @@ button-over index: -1 button-right rotate: false - xy: 1, 46 + xy: 2011, 1402 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -5341,7 +8571,7 @@ button-right index: -1 button-right-down rotate: false - xy: 1, 75 + xy: 2011, 1460 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -5349,7 +8579,7 @@ button-right-down index: -1 button-right-over rotate: false - xy: 448, 484 + xy: 2011, 1431 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -5357,7 +8587,7 @@ button-right-over index: -1 button-select rotate: false - xy: 366, 338 + xy: 1007, 103 size: 24, 24 split: 4, 4, 4, 4 orig: 24, 24 @@ -5365,868 +8595,941 @@ button-select index: -1 check-off rotate: false - xy: 532, 450 + xy: 553, 473 size: 28, 32 orig: 28, 32 offset: 0, 0 index: -1 check-on rotate: false - xy: 562, 450 + xy: 1419, 425 size: 28, 32 orig: 28, 32 offset: 0, 0 index: -1 check-on-over rotate: false - xy: 592, 450 + xy: 915, 143 size: 28, 32 orig: 28, 32 offset: 0, 0 index: -1 check-over rotate: false - xy: 439, 410 + xy: 1733, 1132 size: 28, 32 orig: 28, 32 offset: 0, 0 index: -1 clear rotate: false - xy: 950, 397 + xy: 1725, 779 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 +content-background + rotate: false + xy: 987, 309 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +content-background-locked + rotate: false + xy: 529, 128 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +content-background-over + rotate: false + xy: 945, 267 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 cursor rotate: false - xy: 998, 399 + xy: 421, 111 size: 4, 4 orig: 4, 4 offset: 0, 0 index: -1 discord-banner rotate: false - xy: 204, 466 + xy: 1041, 1154 size: 84, 45 orig: 84, 45 offset: 0, 0 index: -1 empty-sector rotate: false - xy: 983, 479 + xy: 1293, 294 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icon-crafting rotate: false - xy: 266, 278 + xy: 1371, 1139 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-defense rotate: false - xy: 279, 260 + xy: 531, 1543 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-distribution rotate: false - xy: 284, 278 + xy: 845, 987 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-effect rotate: false - xy: 297, 260 + xy: 1882, 1213 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-liquid rotate: false - xy: 374, 278 + xy: 1857, 111 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-power rotate: false - xy: 459, 260 + xy: 2005, 93 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-production rotate: false - xy: 476, 324 + xy: 845, 1507 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-turret rotate: false - xy: 510, 306 + xy: 1987, 57 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-units rotate: false - xy: 482, 270 + xy: 1097, 315 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-upgrade rotate: false - xy: 518, 270 + xy: 2023, 75 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 controller-cursor rotate: false - xy: 986, 381 + xy: 453, 637 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-about rotate: false - xy: 53, 188 + xy: 1207, 464 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-add rotate: false - xy: 17, 1 + xy: 535, 1100 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-admin rotate: false - xy: 33, 1 + xy: 1537, 779 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-admin-small rotate: false - xy: 1017, 505 + xy: 1483, 1421 size: 6, 6 orig: 6, 6 offset: 0, 0 index: -1 icon-areaDelete rotate: false - xy: 302, 334 + xy: 1225, 1287 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow rotate: false - xy: 125, 190 + xy: 1351, 459 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-arrow-16 rotate: false - xy: 125, 190 + xy: 1351, 459 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-arrow-down rotate: false - xy: 302, 322 + xy: 1683, 829 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-left rotate: false - xy: 740, 389 + xy: 639, 637 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-right rotate: false - xy: 274, 312 + xy: 567, 145 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-up rotate: false - xy: 635, 420 + xy: 1127, 1189 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-back rotate: false - xy: 143, 190 + xy: 471, 637 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-ban rotate: false - xy: 49, 1 + xy: 553, 457 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-break rotate: false - xy: 161, 190 + xy: 489, 637 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-cancel rotate: false - xy: 179, 190 + xy: 845, 1543 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 +icon-cancel-2 + rotate: false + xy: 1111, 103 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 icon-chat rotate: false - xy: 636, 408 + xy: 1345, 112 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-check rotate: false - xy: 418, 298 + xy: 1335, 1403 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 +icon-check-2 + rotate: false + xy: 1085, 86 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 icon-copy rotate: false - xy: 436, 296 + xy: 1173, 1102 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-cursor rotate: false - xy: 636, 396 + xy: 1715, 109 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-dev-builds rotate: false - xy: 242, 322 + xy: 623, 923 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-discord rotate: false - xy: 189, 242 + xy: 1363, 545 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-donate rotate: false - xy: 69, 188 + xy: 1837, 541 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-dots rotate: false - xy: 256, 296 + xy: 1865, 439 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-editor rotate: false - xy: 602, 326 + xy: 579, 191 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-egg rotate: false - xy: 69, 172 + xy: 1351, 409 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-elevation rotate: false - xy: 302, 278 + xy: 433, 27 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-eraser rotate: false - xy: 315, 260 + xy: 477, 1698 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-exit rotate: false - xy: 272, 296 + xy: 1381, 375 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-file rotate: false - xy: 320, 278 + xy: 1877, 1003 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-file-image rotate: false - xy: 333, 260 + xy: 1851, 901 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-file-text rotate: false - xy: 258, 322 + xy: 1407, 341 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-fill rotate: false - xy: 338, 278 + xy: 1825, 799 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-floppy rotate: false - xy: 288, 296 + xy: 1429, 273 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-floppy-16 rotate: false - xy: 351, 260 + xy: 2016, 1107 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-folder rotate: false - xy: 304, 296 + xy: 1767, 903 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-folder-parent rotate: false - xy: 320, 296 + xy: 845, 971 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-generated rotate: false - xy: 204, 351 + xy: 1387, 677 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 icon-github rotate: false - xy: 336, 296 + xy: 1843, 801 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-google-play rotate: false - xy: 352, 296 + xy: 535, 1084 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-grid rotate: false - xy: 356, 278 + xy: 1223, 433 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-hold rotate: false - xy: 648, 397 + xy: 845, 1071 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-holdDelete rotate: false - xy: 636, 384 + xy: 845, 1495 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-home rotate: false - xy: 368, 296 + xy: 1553, 779 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-host rotate: false - xy: 384, 296 + xy: 569, 457 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-info rotate: false - xy: 660, 397 - size: 10, 10 - orig: 10, 10 + xy: 623, 907 + size: 14, 14 + orig: 14, 14 offset: 0, 0 index: -1 icon-itch.io rotate: false - xy: 620, 398 + xy: 1363, 529 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-item rotate: false - xy: 648, 385 + xy: 1881, 443 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-items-none rotate: false - xy: 143, 68 + xy: 526, 1951 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-line rotate: false - xy: 369, 260 + xy: 1153, 1168 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-link rotate: false - xy: 620, 382 + xy: 579, 175 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-liquid-small rotate: false - xy: 636, 372 + xy: 971, 159 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-load rotate: false - xy: 620, 366 + xy: 1900, 1185 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-load-image rotate: false - xy: 387, 260 + xy: 1987, 93 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-load-map rotate: false - xy: 392, 278 + xy: 845, 1525 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-loading rotate: false - xy: 410, 280 + xy: 1353, 1403 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-locked rotate: false - xy: 428, 278 + xy: 531, 1525 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-logic rotate: false - xy: 660, 385 + xy: 1225, 1275 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-map rotate: false - xy: 620, 350 + xy: 2033, 541 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-menu rotate: false - xy: 648, 373 + xy: 1695, 829 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-menu-large rotate: false - xy: 446, 278 + xy: 1882, 1195 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-missing rotate: false - xy: 636, 360 + xy: 651, 637 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-mission-background rotate: false - xy: 986, 459 + xy: 845, 1083 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 icon-mission-battle rotate: false - xy: 648, 361 + xy: 971, 147 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-mission-defense rotate: false - xy: 660, 373 + xy: 1225, 1263 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-mission-done rotate: false - xy: 636, 348 + xy: 1707, 829 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-none rotate: false - xy: 648, 349 + xy: 663, 637 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 -icon-nullitem - rotate: false - xy: 153, 78 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 icon-paste rotate: false - xy: 405, 260 + xy: 433, 9 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-pause rotate: false - xy: 660, 361 + xy: 1497, 347 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-pencil rotate: false - xy: 423, 260 + xy: 495, 1698 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-pencil-small rotate: false - xy: 191, 226 + xy: 2033, 525 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-pick rotate: false - xy: 441, 260 + xy: 1987, 75 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-play rotate: false - xy: 636, 336 + xy: 1767, 891 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-play-2 rotate: false - xy: 191, 210 + xy: 451, 1 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 +icon-play-custom + rotate: false + xy: 467, 1 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-players rotate: false - xy: 648, 337 + xy: 2037, 1390 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-power-small rotate: false - xy: 660, 349 + xy: 2037, 1378 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-quit rotate: false - xy: 85, 174 + xy: 483, 1 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-redo rotate: false - xy: 494, 324 + xy: 531, 1507 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-refresh rotate: false - xy: 101, 174 + xy: 499, 1 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rename rotate: false - xy: 117, 174 + xy: 945, 129 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-resize rotate: false - xy: 474, 306 + xy: 1882, 1177 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-rotate rotate: false - xy: 133, 174 + xy: 961, 129 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-arrow rotate: false - xy: 149, 174 + xy: 1363, 513 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-left rotate: false - xy: 165, 174 + xy: 2032, 2033 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-right rotate: false - xy: 181, 174 + xy: 1419, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-save rotate: false - xy: 590, 290 + xy: 2032, 2017 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-save-image rotate: false - xy: 492, 306 + xy: 2005, 75 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-save-map rotate: false - xy: 464, 284 + xy: 437, 1000 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-settings rotate: false - xy: 660, 337 + xy: 2037, 1366 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 +icon-spray + rotate: false + xy: 455, 1000 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 icon-terrain rotate: false - xy: 482, 288 + xy: 473, 1000 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-tools rotate: false - xy: 590, 274 + xy: 1435, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-touch rotate: false - xy: 672, 387 + xy: 2037, 1354 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-touchDelete rotate: false - xy: 672, 375 + xy: 2037, 1342 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-trash rotate: false - xy: 69, 156 + xy: 2032, 2001 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-trash-16 rotate: false - xy: 500, 288 + xy: 491, 1000 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 +icon-tree + rotate: false + xy: 509, 1000 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +icon-tree-locked + rotate: false + xy: 1519, 411 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 icon-trello rotate: false - xy: 85, 158 + xy: 1451, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-tutorial rotate: false - xy: 101, 158 + xy: 2032, 1985 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-undo rotate: false - xy: 518, 288 + xy: 2005, 57 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-unlocked rotate: false - xy: 500, 270 + xy: 2023, 93 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-unlocks rotate: false - xy: 117, 158 + xy: 2032, 1969 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-wiki rotate: false - xy: 133, 158 + xy: 2032, 1953 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 +icon-zone + rotate: false + xy: 1079, 60 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +icon-zone-locked + rotate: false + xy: 389, 1 + size: 42, 42 + orig: 42, 42 + offset: 0, 0 + index: -1 icon-zoom rotate: false - xy: 477, 252 + xy: 2023, 57 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-zoom-small rotate: false - xy: 149, 158 + xy: 1694, 134 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 info-banner rotate: false - xy: 1, 240 + xy: 1139, 1252 size: 84, 45 orig: 84, 45 offset: 0, 0 index: -1 inventory rotate: false - xy: 752, 437 + xy: 1105, 35 size: 24, 40 split: 10, 10, 10, 14 orig: 24, 40 @@ -6234,14 +9537,14 @@ inventory index: -1 logotext rotate: false - xy: 1, 287 - size: 89, 21 - orig: 89, 21 + xy: 1, 1961 + size: 579, 86 + orig: 579, 86 offset: 0, 0 index: -1 pane rotate: false - xy: 524, 484 + xy: 945, 238 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6249,7 +9552,7 @@ pane index: -1 pane-2 rotate: false - xy: 1, 17 + xy: 1113, 435 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6257,7 +9560,7 @@ pane-2 index: -1 scroll rotate: false - xy: 882, 416 + xy: 1879, 136 size: 24, 35 split: 10, 10, 6, 5 orig: 24, 35 @@ -6265,7 +9568,7 @@ scroll index: -1 scroll-horizontal rotate: false - xy: 638, 487 + xy: 487, 181 size: 35, 24 split: 6, 5, 10, 10 orig: 35, 24 @@ -6273,7 +9576,7 @@ scroll-horizontal index: -1 scroll-knob-horizontal-black rotate: false - xy: 1, 162 + xy: 639, 649 size: 40, 24 split: 11, 10, 10, 10 orig: 40, 24 @@ -6281,71 +9584,64 @@ scroll-knob-horizontal-black index: -1 scroll-knob-vertical-black rotate: false - xy: 65, 1 + xy: 1879, 173 size: 24, 40 split: 10, 10, 6, 10 orig: 24, 40 offset: 0, 0 index: -1 -sector-edge - rotate: false - xy: 371, 416 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 sector-select rotate: false - xy: 405, 450 + xy: 1395, 273 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 selection rotate: false - xy: 303, 398 + xy: 1487, 795 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 slider rotate: false - xy: 879, 417 + xy: 1763, 1156 size: 1, 8 orig: 1, 8 offset: 0, 0 index: -1 slider-knob rotate: false - xy: 439, 444 + xy: 1295, 882 size: 29, 38 orig: 29, 38 offset: 0, 0 index: -1 slider-knob-down rotate: false - xy: 470, 444 + xy: 1663, 133 size: 29, 38 orig: 29, 38 offset: 0, 0 index: -1 slider-knob-over rotate: false - xy: 501, 444 + xy: 1663, 133 size: 29, 38 orig: 29, 38 offset: 0, 0 index: -1 slider-vertical rotate: false - xy: 638, 484 + xy: 1263, 561 size: 8, 1 orig: 8, 1 offset: 0, 0 index: -1 underline rotate: false - xy: 600, 484 + xy: 945, 171 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6353,7 +9649,7 @@ underline index: -1 underline-2 rotate: false - xy: 562, 484 + xy: 1151, 435 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -6361,14 +9657,14 @@ underline-2 index: -1 white rotate: false - xy: 87, 282 + xy: 1271, 1186 size: 3, 3 orig: 3, 3 offset: 0, 0 index: -1 window-empty rotate: false - xy: 39, 99 + xy: 1701, 280 size: 27, 61 split: 8, 8, 44, 11 orig: 27, 61 @@ -6376,211 +9672,281 @@ window-empty index: -1 alpha-drone rotate: false - xy: 400, 298 - size: 12, 12 - orig: 12, 12 + xy: 455, 67 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 -unit-icon-alpha-drone +crawler rotate: false - xy: 400, 298 - size: 12, 12 - orig: 12, 12 + xy: 937, 721 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-base + rotate: false + xy: 995, 906 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-leg + rotate: false + xy: 1045, 906 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 dagger rotate: false - xy: 606, 292 - size: 12, 12 - orig: 12, 12 + xy: 987, 806 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 dagger-base rotate: false - xy: 606, 278 - size: 12, 12 - orig: 12, 12 + xy: 1037, 856 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 dagger-leg rotate: false - xy: 620, 292 - size: 12, 12 - orig: 12, 12 + xy: 1037, 806 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +eruptor + rotate: false + xy: 649, 473 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +eruptor-base + rotate: false + xy: 1237, 1257 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +eruptor-leg + rotate: false + xy: 1311, 1331 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 fortress rotate: false - xy: 261, 260 - size: 16, 16 - orig: 16, 16 + xy: 1377, 1355 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 fortress-base rotate: false - xy: 89, 190 - size: 16, 16 - orig: 16, 16 + xy: 1443, 1355 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 titan-base rotate: false - xy: 89, 190 - size: 16, 16 - orig: 16, 16 + xy: 1443, 1355 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 fortress-leg rotate: false - xy: 107, 190 - size: 16, 16 - orig: 16, 16 + xy: 1509, 1363 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 ghoul rotate: false - xy: 960, 433 - size: 18, 18 - orig: 18, 18 + xy: 1237, 1323 + size: 72, 72 + orig: 72, 72 offset: 0, 0 index: -1 -unit-icon-ghoul +lich rotate: false - xy: 960, 433 - size: 18, 18 - orig: 18, 18 + xy: 291, 655 + size: 216, 240 + orig: 216, 240 offset: 0, 0 index: -1 phantom rotate: false - xy: 67, 60 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -unit-icon-phantom - rotate: false - xy: 67, 60 - size: 14, 14 - orig: 14, 14 + xy: 1583, 991 + size: 56, 56 + orig: 56, 56 offset: 0, 0 index: -1 power-cell rotate: false - xy: 67, 44 - size: 14, 14 - orig: 14, 14 + xy: 1641, 1049 + 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: 469, 414 - size: 28, 28 - orig: 28, 28 - offset: 0, 0 - index: -1 -unit-icon-revenant - rotate: false - xy: 469, 414 - size: 28, 28 - orig: 28, 28 + xy: 323, 1002 + size: 112, 112 + orig: 112, 112 offset: 0, 0 index: -1 spirit rotate: false - xy: 655, 250 - size: 12, 12 - orig: 12, 12 - offset: 0, 0 - index: -1 -unit-icon-spirit - rotate: false - xy: 655, 250 - size: 12, 12 - orig: 12, 12 + xy: 979, 606 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 titan rotate: false - xy: 566, 324 - size: 16, 16 - orig: 16, 16 + xy: 1305, 1125 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 titan-leg rotate: false - xy: 564, 306 - size: 16, 16 - orig: 16, 16 + xy: 1327, 1059 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wraith + rotate: false + xy: 1263, 511 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 artillery-equip rotate: false - xy: 618, 320 - size: 12, 12 - orig: 12, 12 + xy: 445, 399 + size: 48, 56 + orig: 48, 56 offset: 0, 0 index: -1 blaster-equip rotate: false - xy: 288, 318 - size: 12, 12 - orig: 12, 12 + xy: 445, 249 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 bomber-equip rotate: false - xy: 600, 306 - size: 12, 12 - orig: 12, 12 + xy: 495, 307 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 missiles-equip rotate: false - xy: 600, 306 - size: 12, 12 - orig: 12, 12 + xy: 495, 307 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 chain-blaster-equip rotate: false - xy: 614, 306 - size: 12, 12 - orig: 12, 12 + xy: 895, 921 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +chaos-equip + rotate: false + xy: 1525, 1019 + size: 56, 136 + orig: 56, 136 + offset: 0, 0 + index: -1 +eradication-equip + rotate: false + xy: 453, 1312 + size: 96, 192 + orig: 96, 192 + offset: 0, 0 + index: -1 +eruption-equip + rotate: false + xy: 1187, 814 + size: 48, 56 + orig: 48, 56 offset: 0, 0 index: -1 flakgun-equip rotate: false - xy: 648, 292 - size: 12, 12 - orig: 12, 12 + xy: 1187, 764 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 flamethrower-equip rotate: false - xy: 648, 278 - size: 12, 12 - orig: 12, 12 + xy: 1237, 814 + size: 48, 56 + orig: 48, 56 offset: 0, 0 index: -1 heal-blaster-equip rotate: false - xy: 606, 264 - size: 12, 12 - orig: 12, 12 + xy: 1287, 711 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +lich-missiles-equip + rotate: false + xy: 1637, 679 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +reaper-gun-equip + rotate: false + xy: 1733, 841 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +revenant-missiles-equip + rotate: false + xy: 1737, 741 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 shockgun-equip rotate: false - xy: 613, 236 - size: 12, 12 - orig: 12, 12 + xy: 1966, 1101 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 swarmer-equip rotate: false - xy: 1006, 447 - size: 12, 12 - orig: 12, 12 + xy: 1179, 564 + size: 48, 48 + orig: 48, 48 offset: 0, 0 index: -1 diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index 83413e6262..1e7dd1e515 100644 Binary files a/core/assets/sprites/sprites.png and b/core/assets/sprites/sprites.png differ diff --git a/core/assets/sprites/uiskin.json b/core/assets/sprites/uiskin.json new file mode 100644 index 0000000000..f57d3613ec --- /dev/null +++ b/core/assets/sprites/uiskin.json @@ -0,0 +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-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/assets/ui/title.fnt b/core/assets/ui/title.fnt deleted file mode 100644 index ef571ca7e7..0000000000 --- a/core/assets/ui/title.fnt +++ /dev/null @@ -1,57 +0,0 @@ -info face="Title" size=16 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=0,0 -common lineHeight=14 base=0 scaleW=512 scaleH=512 pages=1 packed=0 -page id=0 file="title.png" -chars count=53 -char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=0 xadvance=3 page=0 chnl=0 -char id=97 x=1 y=0 width=9 height=12 xoffset=0 yoffset=-12 xadvance=8 page=0 chnl=0 -char id=65 x=1 y=0 width=9 height=12 xoffset=0 yoffset=-12 xadvance=8 page=0 chnl=0 -char id=98 x=14 y=0 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=66 x=14 y=0 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=99 x=26 y=0 width=7 height=12 xoffset=0 yoffset=-12 xadvance=6 page=0 chnl=0 -char id=67 x=26 y=0 width=7 height=12 xoffset=0 yoffset=-12 xadvance=6 page=0 chnl=0 -char id=100 x=39 y=0 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=68 x=39 y=0 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=101 x=50 y=0 width=7 height=12 xoffset=0 yoffset=-12 xadvance=6 page=0 chnl=0 -char id=69 x=50 y=0 width=7 height=12 xoffset=0 yoffset=-12 xadvance=6 page=0 chnl=0 -char id=102 x=63 y=0 width=7 height=12 xoffset=0 yoffset=-12 xadvance=6 page=0 chnl=0 -char id=70 x=63 y=0 width=7 height=12 xoffset=0 yoffset=-12 xadvance=6 page=0 chnl=0 -char id=103 x=74 y=0 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=71 x=74 y=0 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=104 x=86 y=0 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=72 x=86 y=0 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=105 x=100 y=0 width=4 height=12 xoffset=0 yoffset=-12 xadvance=3 page=0 chnl=0 -char id=73 x=100 y=0 width=4 height=12 xoffset=0 yoffset=-12 xadvance=3 page=0 chnl=0 -char id=106 x=2 y=12 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=74 x=2 y=12 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=107 x=14 y=12 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=75 x=14 y=12 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=108 x=28 y=12 width=7 height=12 xoffset=0 yoffset=-12 xadvance=6 page=0 chnl=0 -char id=76 x=28 y=12 width=7 height=12 xoffset=0 yoffset=-12 xadvance=6 page=0 chnl=0 -char id=109 x=38 y=12 width=10 height=12 xoffset=0 yoffset=-12 xadvance=9 page=0 chnl=0 -char id=77 x=38 y=12 width=10 height=12 xoffset=0 yoffset=-12 xadvance=9 page=0 chnl=0 -char id=110 x=50 y=12 width=9 height=12 xoffset=0 yoffset=-12 xadvance=8 page=0 chnl=0 -char id=78 x=50 y=12 width=9 height=12 xoffset=0 yoffset=-12 xadvance=8 page=0 chnl=0 -char id=111 x=63 y=12 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=79 x=63 y=12 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=112 x=75 y=12 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=80 x=75 y=12 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=113 x=87 y=12 width=9 height=12 xoffset=0 yoffset=-12 xadvance=8 page=0 chnl=0 -char id=81 x=87 y=12 width=9 height=12 xoffset=0 yoffset=-12 xadvance=8 page=0 chnl=0 -char id=114 x=99 y=12 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=82 x=99 y=12 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=115 x=2 y=24 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=83 x=2 y=24 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=116 x=14 y=24 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=84 x=14 y=24 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=117 x=26 y=24 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=85 x=26 y=24 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=118 x=37 y=24 width=9 height=12 xoffset=0 yoffset=-12 xadvance=8 page=0 chnl=0 -char id=86 x=37 y=24 width=9 height=12 xoffset=0 yoffset=-12 xadvance=8 page=0 chnl=0 -char id=119 x=50 y=24 width=10 height=12 xoffset=0 yoffset=-12 xadvance=9 page=0 chnl=0 -char id=87 x=50 y=24 width=10 height=12 xoffset=0 yoffset=-12 xadvance=9 page=0 chnl=0 -char id=120 x=62 y=24 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=88 x=62 y=24 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=121 x=75 y=24 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=89 x=75 y=24 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=122 x=86 y=24 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 -char id=90 x=86 y=24 width=8 height=12 xoffset=0 yoffset=-12 xadvance=7 page=0 chnl=0 diff --git a/core/assets/ui/title.png b/core/assets/ui/title.png deleted file mode 100644 index 0141415b7c..0000000000 Binary files a/core/assets/ui/title.png and /dev/null differ diff --git a/core/assets/ui/uiskin.atlas b/core/assets/ui/uiskin.atlas deleted file mode 100644 index 9926e77897..0000000000 --- a/core/assets/ui/uiskin.atlas +++ /dev/null @@ -1,770 +0,0 @@ - -uiskin.png -size: 512,128 -format: RGBA8888 -filter: Nearest,Nearest -repeat: none -blank - rotate: false - xy: 202, 14 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -border - rotate: false - xy: 360, 35 - size: 12, 12 - split: 4, 4, 4, 4 - orig: 12, 12 - offset: 0, 0 - index: -1 -border-circle - rotate: false - xy: 418, 35 - size: 28, 28 - orig: 28, 28 - offset: 0, 0 - index: -1 -border-circle-error - rotate: false - xy: 82, 10 - size: 28, 28 - orig: 28, 28 - offset: 0, 0 - index: -1 -border-dark-blue - rotate: false - xy: 500, 42 - size: 3, 3 - split: 1, 1, 1, 1 - orig: 3, 3 - offset: 0, 0 - index: -1 -border-error - rotate: false - xy: 37, 7 - size: 3, 3 - split: 1, 1, 1, 1 - orig: 3, 3 - offset: 0, 0 - index: -1 -border-white - rotate: false - xy: 58, 2 - size: 12, 12 - split: 4, 4, 4, 4 - orig: 12, 12 - offset: 0, 0 - index: -1 -button - rotate: false - xy: 212, 2 - size: 24, 40 - split: 10, 10, 6, 10 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-blue - rotate: false - xy: 82, 40 - size: 24, 40 - split: 10, 10, 10, 8 - pad: 8, 8, 2, 2 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-blue-down - rotate: false - xy: 448, 40 - size: 24, 40 - split: 10, 10, 10, 8 - pad: 8, 8, 2, 2 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-blue-over - rotate: false - xy: 474, 40 - size: 24, 40 - split: 10, 10, 10, 8 - pad: 8, 8, 2, 2 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-down - rotate: false - xy: 108, 40 - size: 24, 40 - split: 10, 10, 6, 10 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-over - rotate: false - xy: 108, 40 - size: 24, 40 - split: 10, 10, 6, 10 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-gray - rotate: false - xy: 160, 40 - size: 24, 40 - split: 10, 10, 10, 8 - pad: 8, 8, 2, 2 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-gray-over - rotate: false - xy: 134, 40 - size: 24, 40 - split: 10, 10, 10, 8 - pad: 8, 8, 2, 2 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-map - rotate: false - xy: 212, 44 - size: 24, 40 - split: 10, 10, 5, 10 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-map-down - rotate: false - xy: 186, 40 - size: 24, 40 - split: 10, 10, 5, 10 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-map-over - rotate: false - xy: 186, 40 - size: 24, 40 - split: 10, 10, 5, 10 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-red - rotate: false - xy: 238, 44 - size: 24, 40 - split: 10, 10, 10, 8 - pad: 8, 8, 2, 2 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-select - rotate: false - xy: 330, 39 - size: 24, 24 - split: 4, 4, 4, 4 - orig: 24, 24 - offset: 0, 0 - index: -1 -button-window-bg - rotate: false - xy: 264, 44 - size: 24, 40 - split: 10, 10, 10, 8 - pad: 8, 8, 2, 2 - orig: 24, 40 - offset: 0, 0 - index: -1 -button-window-over - rotate: false - xy: 290, 44 - size: 24, 40 - split: 10, 10, 10, 8 - pad: 8, 8, 2, 2 - orig: 24, 40 - offset: 0, 0 - index: -1 -check-off - rotate: false - xy: 474, 6 - size: 28, 32 - orig: 28, 32 - offset: 0, 0 - index: -1 -check-on - rotate: false - xy: 238, 10 - size: 28, 32 - orig: 28, 32 - offset: 0, 0 - index: -1 -check-over - rotate: false - xy: 268, 10 - size: 28, 32 - orig: 28, 32 - offset: 0, 0 - index: -1 -clear - rotate: false - xy: 500, 50 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -color-picker-bar-selector - rotate: false - xy: 495, 98 - size: 14, 28 - orig: 14, 28 - offset: 0, 0 - index: -1 -color-picker-cross - rotate: false - xy: 360, 23 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -color-picker-selector-horizontal - rotate: false - xy: 495, 95 - size: 6, 1 - orig: 6, 1 - offset: 0, 0 - index: -1 -color-picker-selector-vertical - rotate: false - xy: 72, 2 - size: 1, 6 - orig: 1, 6 - offset: 0, 0 - index: -1 -cursor - rotate: false - xy: 316, 44 - size: 4, 4 - orig: 4, 4 - offset: 0, 0 - index: -1 -cursor-normal - rotate: false - xy: 374, 37 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -default-pane - rotate: false - xy: 389, 37 - size: 5, 3 - split: 1, 1, 1, 1 - orig: 5, 3 - offset: 0, 0 - index: -1 -default-pane-no-border - rotate: false - xy: 75, 2 - size: 1, 1 - split: 0, 0, 0, 0 - orig: 1, 1 - offset: 0, 0 - index: -1 -default-select - rotate: false - xy: 2, 12 - size: 54, 48 - split: 8, 32, 0, 48 - orig: 54, 48 - offset: 0, 0 - index: -1 -default-select-selection - rotate: false - xy: 37, 2 - size: 3, 3 - split: 1, 1, 1, 1 - orig: 3, 3 - offset: 0, 0 - index: -1 -grey - rotate: false - xy: 78, 2 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -menu-bg - rotate: false - xy: 78, 2 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -icon-cancel - rotate: false - xy: 356, 49 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-check - rotate: false - xy: 372, 49 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-close - rotate: false - xy: 205, 86 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -icon-close-down - rotate: false - xy: 247, 86 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -icon-close-over - rotate: false - xy: 289, 86 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -icon-cursor - rotate: false - xy: 332, 11 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-defense - rotate: false - xy: 344, 11 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-distribution - rotate: false - xy: 356, 11 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-menu - rotate: false - xy: 368, 11 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-pause - rotate: false - xy: 372, 23 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-play - rotate: false - xy: 380, 11 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-production - rotate: false - xy: 384, 23 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-rotate - rotate: false - xy: 328, 23 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-rotate-arrow - rotate: false - xy: 344, 23 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-settings - rotate: false - xy: 396, 30 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-touch - rotate: false - xy: 396, 18 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -list-selection - rotate: false - xy: 386, 36 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -logotext - rotate: false - xy: 68, 105 - size: 89, 21 - orig: 89, 21 - offset: 0, 0 - index: -1 -logotext-gray - rotate: false - xy: 68, 82 - size: 89, 21 - orig: 89, 21 - offset: 0, 0 - index: -1 -padded-list-selection - rotate: false - xy: 500, 47 - size: 10, 1 - split: 4, 4, 0, 1 - orig: 10, 1 - offset: 0, 0 - index: -1 -pane - rotate: false - xy: 448, 2 - size: 24, 36 - split: 10, 10, 5, 5 - orig: 24, 36 - offset: 0, 0 - index: -1 -progressbar - rotate: false - xy: 324, 52 - size: 1, 32 - orig: 1, 32 - offset: 0, 0 - index: -1 -progressbar-filled - rotate: false - xy: 327, 52 - size: 1, 32 - orig: 1, 32 - offset: 0, 0 - index: -1 -progressbar-filled-vertical - rotate: false - xy: 474, 3 - size: 32, 1 - orig: 32, 1 - offset: 0, 0 - index: -1 -progressbar-vertical - rotate: false - xy: 298, 11 - size: 32, 1 - orig: 32, 1 - offset: 0, 0 - index: -1 -radio-off - rotate: false - xy: 112, 10 - size: 28, 28 - orig: 28, 28 - offset: 0, 0 - index: -1 -radio-on - rotate: false - xy: 142, 10 - size: 28, 28 - orig: 28, 28 - offset: 0, 0 - index: -1 -scroll - rotate: false - xy: 274, 2 - size: 34, 6 - split: 4, 4, 2, 2 - orig: 34, 6 - offset: 0, 0 - index: -1 -scroll-horizontal - rotate: false - xy: 316, 50 - size: 6, 34 - split: 2, 2, 0, 34 - pad: 0, 5, 5, 4 - orig: 6, 34 - offset: 0, 0 - index: -1 -scroll-knob-horizontal - rotate: false - xy: 504, 62 - size: 6, 34 - split: 2, 2, 0, 34 - pad: 0, 5, 13, 12 - orig: 6, 34 - offset: 0, 0 - index: -1 -scroll-knob-vertical - rotate: false - xy: 238, 2 - size: 34, 6 - split: 12, 12, 2, 2 - orig: 34, 6 - offset: 0, 0 - index: -1 -select-box-list-bg - rotate: false - xy: 205, 83 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -window-bg - rotate: false - xy: 205, 83 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -select-down - rotate: false - xy: 2, 2 - size: 14, 8 - orig: 14, 8 - offset: 0, 0 - index: -1 -select-up - rotate: false - xy: 18, 2 - size: 14, 8 - orig: 14, 8 - offset: 0, 0 - index: -1 -selection - rotate: false - xy: 328, 20 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -separator - rotate: false - xy: 404, 15 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -tree-over - rotate: false - xy: 404, 15 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -separator-menu - rotate: false - xy: 392, 20 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -slider - rotate: false - xy: 386, 39 - size: 1, 8 - orig: 1, 8 - offset: 0, 0 - index: -1 -slider-knob - rotate: false - xy: 447, 82 - size: 22, 44 - orig: 22, 44 - offset: 0, 0 - index: -1 -slider-knob-disabled - rotate: false - xy: 471, 82 - size: 22, 44 - orig: 22, 44 - offset: 0, 0 - index: -1 -slider-knob-down - rotate: false - xy: 58, 16 - size: 22, 44 - orig: 22, 44 - offset: 0, 0 - index: -1 -slider-knob-over - rotate: false - xy: 58, 16 - size: 22, 44 - orig: 22, 44 - offset: 0, 0 - index: -1 -slider-vertical - rotate: false - xy: 72, 13 - size: 8, 1 - orig: 8, 1 - offset: 0, 0 - index: -1 -slot - rotate: false - xy: 2, 62 - size: 64, 64 - split: 4, 8, 8, 4 - orig: 64, 64 - offset: 0, 0 - index: -1 -splitpane - rotate: false - xy: 202, 11 - size: 8, 1 - orig: 8, 1 - offset: 0, 0 - index: -1 -splitpane-over - rotate: false - xy: 72, 10 - size: 8, 1 - orig: 8, 1 - offset: 0, 0 - index: -1 -splitpane-vertical - rotate: false - xy: 34, 2 - size: 1, 8 - orig: 1, 8 - offset: 0, 0 - index: -1 -splitpane-vertical-over - rotate: false - xy: 356, 39 - size: 1, 8 - orig: 1, 8 - offset: 0, 0 - index: -1 -sub-menu - rotate: false - xy: 202, 24 - size: 8, 14 - orig: 8, 14 - offset: 0, 0 - index: -1 -textfield - rotate: false - xy: 298, 14 - size: 28, 28 - split: 6, 6, 6, 6 - orig: 28, 28 - offset: 0, 0 - index: -1 -textfield-over - rotate: false - xy: 172, 10 - size: 28, 28 - split: 2, 2, 2, 2 - orig: 28, 28 - offset: 0, 0 - index: -1 -tooltip-bg - rotate: false - xy: 408, 37 - size: 3, 3 - split: 1, 1, 1, 1 - orig: 3, 3 - offset: 0, 0 - index: -1 -touchpad-knob - rotate: false - xy: 159, 82 - size: 44, 44 - orig: 44, 44 - offset: 0, 0 - index: -1 -tree-minus - rotate: false - xy: 392, 6 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -tree-plus - rotate: false - xy: 68, 64 - size: 12, 16 - orig: 12, 16 - offset: 0, 0 - index: -1 -tree-selection - rotate: false - xy: 413, 37 - size: 3, 3 - split: 1, 1, 1, 1 - orig: 3, 3 - offset: 0, 0 - index: -1 -white - rotate: false - xy: 75, 5 - size: 3, 3 - orig: 3, 3 - offset: 0, 0 - index: -1 -window - rotate: false - xy: 418, 65 - size: 27, 61 - split: 8, 8, 44, 11 - orig: 27, 61 - offset: 0, 0 - index: -1 -window-border-bg - rotate: false - xy: 495, 90 - size: 3, 3 - split: 1, 1, 1, 1 - orig: 3, 3 - offset: 0, 0 - index: -1 -window-gray - rotate: false - xy: 331, 65 - size: 27, 61 - split: 5, 4, 52, 4 - orig: 27, 61 - offset: 0, 0 - index: -1 -window-noborder - rotate: false - xy: 360, 65 - size: 27, 61 - split: 5, 4, 53, 3 - orig: 27, 61 - offset: 0, 0 - index: -1 -window-resizable - rotate: false - xy: 389, 42 - size: 27, 84 - split: 3, 19, 2, 20 - pad: 5, 5, 50, 7 - orig: 27, 84 - offset: 0, 0 - index: -1 diff --git a/core/assets/ui/uiskin.json b/core/assets/ui/uiskin.json deleted file mode 100644 index c2420b9fcb..0000000000 --- a/core/assets/ui/uiskin.json +++ /dev/null @@ -1,79 +0,0 @@ -{ -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}, - 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 }, - 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 ce5c64e8bb..c4a571ef1e 100644 --- a/core/src/io/anuke/mindustry/Mindustry.java +++ b/core/src/io/anuke/mindustry/Mindustry.java @@ -1,47 +1,70 @@ package io.anuke.mindustry; +import io.anuke.arc.ApplicationCore; +import io.anuke.arc.Core; +import io.anuke.arc.Events; +import io.anuke.arc.util.Log; +import io.anuke.arc.util.Time; import io.anuke.mindustry.core.*; import io.anuke.mindustry.game.EventType.GameLoadEvent; import io.anuke.mindustry.io.BundleLoader; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.modules.ModuleCore; -import io.anuke.ucore.util.Log; import static io.anuke.mindustry.Vars.*; -public class Mindustry extends ModuleCore{ +public class Mindustry extends ApplicationCore{ @Override - public void init(){ - Timers.mark(); + public void setup(){ + Time.setDeltaProvider(() -> { + float result = Core.graphics.getDeltaTime() * 60f; + return Float.isNaN(result) || Float.isInfinite(result) ? 1f : Math.min(result, 60f / 10f); + }); + + Time.mark(); Vars.init(); Log.setUseColors(false); BundleLoader.load(); content.load(); + content.loadColors(); - module(logic = new Logic()); - module(world = new World()); - module(control = new Control()); - module(renderer = new Renderer()); - module(ui = new UI()); - module(netServer = new NetServer()); - module(netClient = new NetClient()); + add(logic = new Logic()); + add(world = new World()); + add(control = new Control()); + add(renderer = new Renderer()); + add(ui = new UI()); + add(netServer = new NetServer()); + add(netClient = new NetClient()); } @Override - public void postInit(){ - Log.info("Time to load [total]: {0}", Timers.elapsed()); + public void init(){ + super.init(); + + Log.info("Time to load [total]: {0}", Time.elapsed()); Events.fire(new GameLoadEvent()); } @Override - public void render(){ - threads.handleBeginRender(); - super.render(); - threads.handleEndRender(); + public void update(){ + long lastFrameTime = Time.nanos(); + + super.update(); + + int fpsCap = Core.settings.getInt("fpscap", 125); + + if(fpsCap <= 120){ + long target = (1000 * 1000000)/fpsCap; //target in nanos + long elapsed = Time.timeSinceNanos(lastFrameTime); + if(elapsed < target){ + try{ + 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 14636b4abd..9831b5cec4 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -1,58 +1,65 @@ package io.anuke.mindustry; -import com.badlogic.gdx.Application.ApplicationType; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.graphics.Color; +import io.anuke.arc.Application.ApplicationType; +import io.anuke.arc.Core; +import io.anuke.mindustry.entities.Entities; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.impl.EffectEntity; +import io.anuke.mindustry.entities.traits.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.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; 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.traits.SyncTrait; -import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.game.GlobalData; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.entities.Entities; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.impl.EffectEntity; -import io.anuke.ucore.entities.trait.DrawTrait; -import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.util.Translator; import java.util.Arrays; import java.util.Locale; @SuppressWarnings("unchecked") public class Vars{ + /**main application name, capitalized*/ public static final String appName = "Mindustry"; + /**URL for discord invite.*/ public static final String discordURL = "https://discord.gg/mindustry"; + /**URL for Github API for releases*/ public static final String releasesURL = "https://api.github.com/repos/Anuken/Mindustry/releases"; + /**URL for Github API for contributors*/ public static final String contributorsURL = "https://api.github.com/repos/Anuken/Mindustry/contributors"; + /**URL for sending crash reports to*/ public static final String crashReportURL = "http://mindustry.us.to/report"; - //time between waves in frames (on normal mode) - public static final float wavespace = 60 * 60 * 1.5f; - + /**maximum distance between mine and core that supports automatic transferring*/ public static final float mineTransferRange = 220f; - //set ridiculously high for now - public static final float coreBuildRange = 999999f; - //team of the player by default + /**team of the player by default*/ public static final Team defaultTeam = Team.blue; - //team of the enemy in waves + /**team of the enemy in waves/sectors*/ public static final Team waveTeam = Team.red; - public static final float unlockResourceScaling = 1f; + /**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; - public static final int sectorSize = 256; - public static final int invalidSector = Integer.MAX_VALUE; - public static Locale[] locales; + /**all choosable player colors in join/host dialog*/ public static final Color[] playerColors = { Color.valueOf("82759a"), Color.valueOf("c0c1c5"), @@ -71,36 +78,39 @@ public class Vars{ Color.valueOf("4b5ef1"), Color.valueOf("2cabfe"), }; - //server port + /**default server port*/ public static final int port = 6567; + /**if true, UI is not drawn*/ public static boolean disableUI; + /**if true, game is set up in mobile mode, even on desktop. used for debugging*/ public static boolean testMobile; - //shorthand for whether or not this is running on android or ios + /**whether the game is running on a mobile device*/ public static boolean mobile; + /**whether the game is running on an iOS device*/ public static boolean ios; + /**whether the game is running on an Android device*/ public static boolean android; - //main data directory + /**whether the game is running on a headless server*/ + public static boolean headless; + /**application data directory, equivalent to {@link io.anuke.arc.Settings#getDataDirectory()}*/ public static FileHandle dataDirectory; - //subdirectory for screenshots + /**data subdirectory used for screenshots*/ public static FileHandle screenshotDirectory; - //directory for user-created map data + /**data subdirectory used for custom mmaps*/ public static FileHandle customMapDirectory; - //save file directory + /**data subdirectory used for saves*/ public static FileHandle saveDirectory; - public static String mapExtension = "mmap"; - public static String saveExtension = "msav"; - //camera zoom displayed on startup - public static int baseCameraScale; - public static boolean showBlockDebug = false; - public static boolean showFog = true; - public static boolean headless = false; - public static float controllerMin = 0.25f; - public static float baseControllerSpeed = 11f; - public static boolean snapCamera = true; + /**map file extension*/ + public static final String mapExtension = "mmap"; + /**save file extension*/ + public static final String saveExtension = "msav"; + + /**list of all locales that can be switched to*/ + public static Locale[] locales; public static ContentLoader content; public static GameState state; - public static ThreadHandler threads; + public static GlobalData data; public static Control control; public static Logic logic; @@ -110,8 +120,6 @@ public class Vars{ public static NetServer netServer; public static NetClient netClient; - public static Player[] players = {}; - public static EntityGroup playerGroup; public static EntityGroup tileGroup; public static EntityGroup bulletGroup; @@ -122,13 +130,14 @@ public class Vars{ public static EntityGroup fireGroup; public static EntityGroup[] unitGroups; - public static final Translator[] tmptr = new Translator[]{new Translator(), new Translator(), new Translator(), new Translator()}; + /**all local players, currently only has one player. may be used for local co-op in the future*/ + public static Player[] players = {}; public static void init(){ Serialization.init(); //load locales - String[] stra = Gdx.files.internal("locales").readString().split("\n"); + String[] stra = Core.files.internal("locales").readString().split("\n"); locales = new Locale[stra.length]; for(int i = 0; i < locales.length; i++){ String code = stra[i]; @@ -139,7 +148,7 @@ public class Vars{ } } - Arrays.sort(locales, (l1, l2) -> l1.getDisplayName(l1).compareTo(l2.getDisplayName(l2))); + Arrays.sort(locales, Structs.comparing(l -> l.getDisplayName(l), String.CASE_INSENSITIVE_ORDER)); Version.init(); content = new ContentLoader(); @@ -167,16 +176,17 @@ public class Vars{ } state = new GameState(); - threads = new ThreadHandler(); + data = new GlobalData(); - mobile = Gdx.app.getType() == ApplicationType.Android || Gdx.app.getType() == ApplicationType.iOS || testMobile; - ios = Gdx.app.getType() == ApplicationType.iOS; - android = Gdx.app.getType() == ApplicationType.Android; + mobile = Core.app.getType() == ApplicationType.Android || Core.app.getType() == ApplicationType.iOS || testMobile; + ios = Core.app.getType() == ApplicationType.iOS; + android = Core.app.getType() == ApplicationType.Android; - dataDirectory = Settings.getDataDirectory(appName); + Core.settings.setAppName(appName); + + dataDirectory = Core.settings.getDataDirectory(); screenshotDirectory = dataDirectory.child("screenshots/"); customMapDirectory = dataDirectory.child("maps/"); saveDirectory = dataDirectory.child("saves/"); - baseCameraScale = Math.round(Unit.dp.scl(4)); } } diff --git a/core/src/io/anuke/mindustry/ai/BlockIndexer.java b/core/src/io/anuke/mindustry/ai/BlockIndexer.java index 8bc2d080d9..d7ebcad8eb 100644 --- a/core/src/io/anuke/mindustry/ai/BlockIndexer.java +++ b/core/src/io/anuke/mindustry/ai/BlockIndexer.java @@ -1,9 +1,12 @@ package io.anuke.mindustry.ai; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.*; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.arc.Events; +import io.anuke.arc.collection.*; +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.type.TileEntity; import io.anuke.mindustry.game.EventType.TileChangeEvent; import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.Team; @@ -11,17 +14,9 @@ import io.anuke.mindustry.game.Teams.TeamData; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockFlag; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.function.Predicate; -import io.anuke.ucore.util.EnumSet; -import io.anuke.ucore.util.Geometry; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.ThreadArray; 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{ @@ -47,7 +42,7 @@ public class BlockIndexer{ /**Empty set used for returning.*/ private ObjectSet emptySet = new ObjectSet<>(); /**Array used for returning and reusing.*/ - private Array returnArray = new ThreadArray<>(); + private Array returnArray = new Array<>(); public BlockIndexer(){ Events.on(TileChangeEvent.class, event -> { @@ -176,7 +171,7 @@ public class BlockIndexer{ TileEntity e = other.entity; - float ndst = Vector2.dst(x, y, e.x, e.y); + float ndst = Mathf.dst(x, y, e.x, e.y); if(ndst < range && (closest == null || ndst < dst)){ dst = ndst; closest = e; @@ -208,7 +203,7 @@ public class BlockIndexer{ for(int x = Math.max(0, tile.x - oreQuadrantSize / 2); x < tile.x + oreQuadrantSize / 2 && x < world.width(); x++){ for(int y = Math.max(0, tile.y - oreQuadrantSize / 2); y < tile.y + oreQuadrantSize / 2 && y < world.height(); y++){ Tile res = world.tile(x, y); - if(res.block() == Blocks.air && res.floor().drops != null && res.floor().drops.item == item){ + if(res.block() == Blocks.air && res.floor().itemDrop == item){ return res; } } @@ -218,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()); @@ -246,9 +241,9 @@ public class BlockIndexer{ 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); - if( result == null || result.block().drops == null || !scanOres.contains(result.block().drops.item)) continue; + if( result == null || result.floor().itemDrop == null || !scanOres.contains(result.floor().itemDrop)) continue; - itemSet.add(result.block().drops.item); + itemSet.add(result.floor().itemDrop); } } @@ -325,8 +320,8 @@ public class BlockIndexer{ Tile tile = world.tile(x, y); //add position of quadrant to list when an ore is found - if(tile.floor().drops != null && scanOres.contains(tile.floor().drops.item) && tile.block() == Blocks.air){ - ores.get(tile.floor().drops.item).add(world.tile( + if(tile.floor().itemDrop != null && scanOres.contains(tile.floor().itemDrop) && tile.block() == Blocks.air){ + ores.get(tile.floor().itemDrop).add(world.tile( //make sure to clamp quadrant middle position, since it might go off bounds Mathf.clamp(qx * oreQuadrantSize + oreQuadrantSize / 2, 0, world.width() - 1), Mathf.clamp(qy * oreQuadrantSize + oreQuadrantSize / 2, 0, world.height() - 1))); diff --git a/core/src/io/anuke/mindustry/ai/Pathfinder.java b/core/src/io/anuke/mindustry/ai/Pathfinder.java index 0de1e8c7cd..024d83ed4a 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfinder.java +++ b/core/src/io/anuke/mindustry/ai/Pathfinder.java @@ -1,9 +1,12 @@ package io.anuke.mindustry.ai; -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.utils.IntArray; -import com.badlogic.gdx.utils.Queue; -import com.badlogic.gdx.utils.TimeUtils; +import io.anuke.arc.Events; +import io.anuke.arc.collection.IntArray; +import io.anuke.arc.collection.Queue; +import io.anuke.arc.math.geom.Geometry; +import io.anuke.arc.math.geom.Point2; +import io.anuke.arc.util.Structs; +import io.anuke.arc.util.Time; import io.anuke.mindustry.game.EventType.TileChangeEvent; import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.Team; @@ -11,16 +14,12 @@ import io.anuke.mindustry.game.Teams.TeamData; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockFlag; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.util.Geometry; -import io.anuke.ucore.util.Structs; import static io.anuke.mindustry.Vars.state; import static io.anuke.mindustry.Vars.world; public class Pathfinder{ - private long maxUpdate = TimeUtils.millisToNanos(4); + private long maxUpdate = Time.millisToNanos(4); private PathData[] paths; private IntArray blocked = new IntArray(); @@ -63,7 +62,7 @@ public class Pathfinder{ Tile target = null; float tl = 0f; - for(GridPoint2 point : Geometry.d8){ + for(Point2 point : Geometry.d8){ int dx = tile.x + point.x, dy = tile.y + point.y; Tile other = world.tile(dx, dy); @@ -83,7 +82,7 @@ public class Pathfinder{ } public float getValueforTeam(Team team, int x, int y){ - return paths == null || team.ordinal() >= paths.length ? 0 : Structs.inBounds(x, y, paths[team.ordinal()].weights) ? paths[team.ordinal()].weights[x][y] : 0; + return paths == null || paths[team.ordinal()].weights == null || team.ordinal() >= paths.length ? 0 : Structs.inBounds(x, y, paths[team.ordinal()].weights) ? paths[team.ordinal()].weights[x][y] : 0; } private boolean passable(Tile tile, Team team){ @@ -94,7 +93,7 @@ public class Pathfinder{ * This only occurs for active teams.*/ private void update(Tile tile, Team team){ //make sure team exists - if(paths[team.ordinal()] != null){ + if(paths[team.ordinal()] != null && paths[team.ordinal()].weights != null){ PathData path = paths[team.ordinal()]; //impassable tiles have a weight of float.max @@ -105,12 +104,12 @@ public class Pathfinder{ //increment search, clear frontier path.search++; path.frontier.clear(); - path.lastSearchTime = TimeUtils.millis(); + path.lastSearchTime = Time.millis(); //add all targets to the frontier for(Tile other : world.indexer.getEnemy(team, BlockFlag.target)){ path.weights[other.x][other.y] = 0; - path.searches[other.x][other.y] = path.search; + path.searches[other.x][other.y] = (short)path.search; path.frontier.addFirst(other); } } @@ -118,6 +117,8 @@ public class Pathfinder{ private void createFor(Team team){ PathData path = new PathData(); + path.weights = new float[world.width()][world.height()]; + path.searches = new short[world.width()][world.height()]; path.search++; path.frontier.ensureCapacity((world.width() + world.height()) * 3); @@ -127,11 +128,11 @@ 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.weights[x][y] = 0; - path.searches[x][y] = path.search; + path.searches[x][y] = (short)path.search; }else{ path.weights[x][y] = Float.MAX_VALUE; } @@ -144,23 +145,24 @@ public class Pathfinder{ private void updateFrontier(Team team, long nsToRun){ PathData path = paths[team.ordinal()]; - long start = TimeUtils.nanoTime(); + long start = Time.nanos(); - while(path.frontier.size > 0 && (nsToRun < 0 || TimeUtils.timeSinceNanos(start) <= nsToRun)){ + while(path.frontier.size > 0 && (nsToRun < 0 || Time.timeSinceNanos(start) <= nsToRun)){ Tile tile = path.frontier.removeLast(); float cost = path.weights[tile.x][tile.y]; if(cost < Float.MAX_VALUE){ - for(GridPoint2 point : Geometry.d4){ + for(Point2 point : Geometry.d4){ int dx = tile.x + point.x, dy = tile.y + point.y; Tile other = world.tile(dx, dy); if(other != null && (path.weights[dx][dy] > cost + other.cost || path.searches[dx][dy] < path.search) && passable(other, team)){ + if(other.cost < 0) throw new IllegalArgumentException("Tile cost cannot be negative! " + other); path.frontier.addFirst(world.tile(dx, dy)); path.weights[dx][dy] = cost + other.cost; - path.searches[dx][dy] = path.search; + path.searches[dx][dy] = (short)path.search; } } } @@ -168,7 +170,7 @@ public class Pathfinder{ } private void clear(){ - Timers.mark(); + Time.mark(); paths = new PathData[Team.all.length]; blocked.clear(); @@ -181,20 +183,13 @@ public class Pathfinder{ createFor(team); } } - - world.spawner.checkAllQuadrants(); } class PathData{ float[][] weights; - int[][] searches; + short[][] searches; int search = 0; long lastSearchTime; Queue frontier = new Queue<>(); - - PathData(){ - weights = new float[world.width()][world.height()]; - searches = new int[world.width()][world.height()]; - } } } diff --git a/core/src/io/anuke/mindustry/ai/WaveSpawner.java b/core/src/io/anuke/mindustry/ai/WaveSpawner.java index 897cdcda3f..005712e733 100644 --- a/core/src/io/anuke/mindustry/ai/WaveSpawner.java +++ b/core/src/io/anuke/mindustry/ai/WaveSpawner.java @@ -1,18 +1,20 @@ package io.anuke.mindustry.ai; -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.entities.units.BaseUnit; -import io.anuke.mindustry.entities.units.Squad; +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.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.game.Team; -import io.anuke.mindustry.game.Waves; -import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.util.GridBits; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Structs; +import io.anuke.mindustry.world.Pos; import java.io.DataInput; import java.io.DataOutput; @@ -21,239 +23,132 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.*; public class WaveSpawner{ - private static final int quadsize = 6; - - private GridBits quadrants; - + private static final float shockwaveBase = 380f, shockwaveRand = 50f, maxShockwaveDst = shockwaveBase + shockwaveRand; private Array groups; - private boolean dynamicSpawn; - private Array flySpawns = new Array<>(); private Array groundSpawns = new Array<>(); + private IntArray loadedSpawns = new IntArray(); public WaveSpawner(){ - Events.on(WorldLoadEvent.class, this::reset); + Events.on(WorldLoadEvent.class, e -> reset()); } - public void write(DataOutput output) throws IOException{ - output.writeShort(flySpawns.size); - for(FlyerSpawn spawn : flySpawns){ - output.writeFloat(spawn.angle); - } - - output.writeShort(groundSpawns.size); + public void write(DataOutput stream) throws IOException{ + stream.writeInt(groundSpawns.size); for(GroundSpawn spawn : groundSpawns){ - output.writeShort((short) spawn.x); - output.writeShort((short) spawn.y); + stream.writeInt(Pos.get(spawn.x, spawn.y)); } } - public void read(DataInput input) throws IOException{ - short flya = input.readShort(); + public void read(DataInput stream) throws IOException{ + flySpawns.clear(); + groundSpawns.clear(); + loadedSpawns.clear(); - for(int i = 0; i < flya; i++){ - FlyerSpawn spawn = new FlyerSpawn(); - spawn.angle = input.readFloat(); - flySpawns.add(spawn); - } + int amount = stream.readInt(); - short grounda = input.readShort(); - for(int i = 0; i < grounda; i++){ - GroundSpawn spawn = new GroundSpawn(); - spawn.x = input.readShort(); - spawn.y = input.readShort(); - groundSpawns.add(spawn); + 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(){ - int flyGroups = 0; - int groundGroups = 0; - - //count total subgroups spawned by flying/group types - for(SpawnGroup group : groups){ - int amount = group.getGroupsSpawned(state.wave); - if(group.type.isFlying){ - flyGroups += amount; - }else if(dynamicSpawn){ - groundGroups += amount; - } - } - - int addGround = groundGroups - groundSpawns.size, addFly = flyGroups - flySpawns.size; - - //add extra groups if the total exceeds it - if(dynamicSpawn){ - for(int i = 0; i < addGround; i++){ - GroundSpawn spawn = new GroundSpawn(); - findLocation(spawn); - groundSpawns.add(spawn); - } - } - - for(int i = 0; i < addFly; i++){ - FlyerSpawn spawn = new FlyerSpawn(); - findLocation(spawn); - flySpawns.add(spawn); - } - - //store index of last used fly/ground spawn locations - int flyCount = 0, groundCount = 0; for(SpawnGroup group : groups){ - int groups = group.getGroupsSpawned(state.wave); int spawned = group.getUnitsSpawned(state.wave); - for(int i = 0; i < groups; i++){ - Squad squad = new Squad(); - float spawnX, spawnY; - float spread; - - if(!group.type.isFlying && groundCount >= groundSpawns.size) continue; - - if(group.type.isFlying){ - FlyerSpawn spawn = flySpawns.get(flyCount); + float spawnX, spawnY; + float spread; + if(group.type.isFlying){ + for(FlyerSpawn spawn : flySpawns){ float margin = 40f; //how far away from the edge flying units spawn - spawnX = world.width() * tilesize / 2f + Mathf.sqrwavex(spawn.angle) * (world.width() / 2f * tilesize + margin); - spawnY = world.height() * tilesize / 2f + Mathf.sqrwavey(spawn.angle) * (world.height() / 2f * tilesize + margin); + float trns = (world.width() + world.height()) * tilesize; + spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(spawn.angle, trns), -margin, world.width() * tilesize + margin); + spawnY = Mathf.clamp(world.height() * tilesize / 2f + Angles.trnsy(spawn.angle, trns), -margin, world.height() * tilesize + margin); spread = margin / 1.5f; - flyCount++; - }else{ //make sure it works for non-dynamic spawns - GroundSpawn spawn = groundSpawns.get(groundCount); - - if(dynamicSpawn){ - checkQuadrant(spawn.x, spawn.y); - if(!getQuad(spawn.x, spawn.y)){ - findLocation(spawn); - } + for(int i = 0; i < spawned; i++){ + BaseUnit unit = group.createUnit(waveTeam); + unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread)); + unit.add(); } - - spawnX = spawn.x * quadsize * tilesize + quadsize * tilesize / 2f; - spawnY = spawn.y * quadsize * tilesize + quadsize * tilesize / 2f; - spread = quadsize * tilesize / 3f; - - groundCount++; } + }else{ + for(GroundSpawn spawn : groundSpawns){ + spawnX = spawn.x * tilesize; + spawnY = spawn.y * tilesize; + spread = tilesize*2; - for(int j = 0; j < spawned; j++){ - BaseUnit unit = group.createUnit(Team.red); - unit.setWave(); - unit.setSquad(squad); - unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread)); - unit.add(); + for(int i = 0; i < spawned; i++){ + Tmp.v1.rnd(spread); + + BaseUnit unit = group.createUnit(waveTeam); + 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)); } } } } - public void checkAllQuadrants(){ - for(int x = 0; x < quadWidth(); x++){ - for(int y = 0; y < quadHeight(); y++){ - checkQuadrant(x, y); - } - } - } - - private void checkQuadrant(int quadx, int quady){ - setQuad(quadx, quady, true); - - outer: - for(int x = quadx * quadsize; x < world.width() && x < (quadx + 1) * quadsize; x++){ - for(int y = quady * quadsize; y < world.height() && y < (quady + 1) * quadsize; y++){ - Tile tile = world.tile(x, y); - - if(tile == null || tile.solid() || tile.getTeam() == defaultTeam || world.pathfinder.getValueforTeam(Team.red, x, y) == Float.MAX_VALUE || tile.floor().isLiquid){ - setQuad(quadx, quady, false); - break outer; - } - } - } - } - - private void reset(WorldLoadEvent event){ - dynamicSpawn = false; + private void reset(){ flySpawns.clear(); groundSpawns.clear(); - quadrants = new GridBits(quadWidth(), quadHeight()); - - if(world.getSector() == null){ - groups = Waves.getSpawns(); - }else{ - groups = world.getSector().spawns; - } - - dynamicSpawn = true; + groups = state.rules.spawns; for(int x = 0; x < world.width(); x++){ for(int y = 0; y < world.height(); y++){ if(world.tile(x, y).block() == Blocks.spawn){ - dynamicSpawn = false; - GroundSpawn spawn = new GroundSpawn(); - spawn.x = x/quadsize; - spawn.y = y/quadsize; - groundSpawns.add(spawn); + addSpawns(x, y); + + //hide spawnpoints, they have served their purpose + world.tile(x, y).setBlock(Blocks.air); } } } - } - private boolean getQuad(int quadx, int quady){ - return quadrants.get(quadx, quady); - } - - private void setQuad(int quadx, int quady, boolean valid){ - if(quadrants == null){ - quadrants = new GridBits(quadWidth(), quadHeight()); + for(int i = 0; i < loadedSpawns.size; i++){ + int pos = loadedSpawns.get(i); + addSpawns(Pos.x(pos), Pos.y(pos)); } - if(!Structs.inBounds(quadx, quady, quadWidth(), quadHeight())){ - return; - } - - quadrants.set(quadx, quady, valid); + loadedSpawns.clear(); } - //TODO instead of randomly scattering locations around the map, find spawns close to each other - private void findLocation(GroundSpawn spawn){ - spawn.x = Mathf.random(quadWidth()-1); - spawn.y = Mathf.random(quadHeight()-1); + private void addSpawns(int x, int y){ + GroundSpawn spawn = new GroundSpawn(); + spawn.x = x; + spawn.y = y; + groundSpawns.add(spawn); - int shellWidth = quadWidth() * 2 + quadHeight() * 2 * 6; - shellWidth = Math.min(quadWidth() * quadHeight() / 4, shellWidth); + FlyerSpawn fspawn = new FlyerSpawn(); + fspawn.angle = Angles.angle(world.width()/2f, world.height()/2f, x, y); + flySpawns.add(fspawn); + } - Mathf.traverseSpiral(quadWidth(), quadHeight(), Mathf.random(shellWidth), (x, y) -> { - if(getQuad(x, y)){ - spawn.x = x; - spawn.y = y; - return true; - } - - return false; + 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); }); } - //TODO instead of randomly scattering locations around the map, find spawns close to each other - private void findLocation(FlyerSpawn spawn){ - spawn.angle = Mathf.random(360f); - } - - private int quadWidth(){ - return Mathf.ceil(world.width() / (float) quadsize); - } - - private int quadHeight(){ - return Mathf.ceil(world.height() / (float) quadsize); - } - private class FlyerSpawn{ - //square angle float angle; } private class GroundSpawn{ - //quadrant spawn coordinates int x, y; } } diff --git a/core/src/io/anuke/mindustry/content/AmmoTypes.java b/core/src/io/anuke/mindustry/content/AmmoTypes.java deleted file mode 100644 index cd96e8344b..0000000000 --- a/core/src/io/anuke/mindustry/content/AmmoTypes.java +++ /dev/null @@ -1,254 +0,0 @@ -package io.anuke.mindustry.content; - -import io.anuke.mindustry.content.bullets.*; -import io.anuke.mindustry.content.fx.BulletFx; -import io.anuke.mindustry.content.fx.Fx; -import io.anuke.mindustry.content.fx.ShootFx; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.AmmoType; -import io.anuke.mindustry.type.ContentType; - -public class AmmoTypes implements ContentList{ - public static AmmoType - bulletCopper, bulletDense, bulletThorium, bulletSilicon, bulletPyratite, - bulletDenseBig, bulletPyratiteBig, bulletThoriumBig, - shock, bombExplosive, bombIncendiary, bombOil, shellCarbide, flamerThermite, weaponMissile, weaponMissileSwarm, bulletMech, - healBlaster, bulletGlaive, - flakExplosive, flakPlastic, flakSurge, - missileExplosive, missileIncindiary, missileSurge, - artilleryDense, artilleryPlastic, artilleryHoming, artilleryIncindiary, artilleryExplosive, unitArtillery, - basicFlame, lancerLaser, lightning, meltdownLaser, burstLaser, - fuseShotgun, oil, water, lava, cryofluid, arc; - - @Override - public void load(){ - - //weapon specific - - bulletMech = new AmmoType(StandardBullets.mechSmall){{ - shootEffect = ShootFx.shootSmall; - smokeEffect = ShootFx.shootSmallSmoke; - reloadMultiplier = 1f; - inaccuracy = 5f; - }}; - - bulletGlaive = new AmmoType(Items.pyratite, StandardBullets.glaive, 3){{ - shootEffect = ShootFx.shootSmall; - smokeEffect = ShootFx.shootSmallSmoke; - inaccuracy = 3f; - }}; - - healBlaster = new AmmoType(TurretBullets.healBullet){{ - shootEffect = ShootFx.shootHeal; - smokeEffect = BulletFx.hitLaser; - reloadMultiplier = 1f; - inaccuracy = 2f; - }}; - - shock = new AmmoType(TurretBullets.lightning){{ - shootEffect = BulletFx.hitLancer; - smokeEffect = Fx.none; - }}; - - shellCarbide = new AmmoType(WeaponBullets.shellCarbide){{ - shootEffect = ShootFx.shootBig; - smokeEffect = ShootFx.shootBigSmoke; - }}; - - bombExplosive = new AmmoType(WeaponBullets.bombExplosive){{ - shootEffect = Fx.none; - smokeEffect = Fx.none; - }}; - - bombIncendiary = new AmmoType(WeaponBullets.bombIncendiary){{ - shootEffect = Fx.none; - smokeEffect = Fx.none; - }}; - - bombOil = new AmmoType(WeaponBullets.bombOil){{ - shootEffect = Fx.none; - smokeEffect = Fx.none; - }}; - - flamerThermite = new AmmoType(TurretBullets.basicFlame){{ - shootEffect = ShootFx.shootSmallFlame; - }}; - - weaponMissile = new AmmoType(MissileBullets.javelin){{ - shootEffect = BulletFx.hitBulletSmall; - smokeEffect = Fx.none; - reloadMultiplier = 1.2f; - }}; - - weaponMissileSwarm = new AmmoType(MissileBullets.swarm){{ - shootEffect = BulletFx.hitBulletSmall; - smokeEffect = ShootFx.shootSmallSmoke; - reloadMultiplier = 1.2f; - }}; - - //bullets - - bulletCopper = new AmmoType(Items.copper, StandardBullets.copper, 5){{ - shootEffect = ShootFx.shootSmall; - smokeEffect = ShootFx.shootSmallSmoke; - reloadMultiplier = 1f; - inaccuracy = 5f; - }}; - - bulletDense = new AmmoType(Items.densealloy, StandardBullets.dense, 2){{ - shootEffect = ShootFx.shootSmall; - smokeEffect = ShootFx.shootSmallSmoke; - reloadMultiplier = 0.6f; - }}; - - bulletThorium = new AmmoType(Items.thorium, StandardBullets.thorium, 2){{ - shootEffect = ShootFx.shootBig; - smokeEffect = ShootFx.shootBigSmoke; - }}; - - bulletSilicon = new AmmoType(Items.silicon, StandardBullets.homing, 5){{ - shootEffect = ShootFx.shootSmall; - smokeEffect = ShootFx.shootSmallSmoke; - reloadMultiplier = 1.4f; - }}; - - bulletPyratite = new AmmoType(Items.pyratite, StandardBullets.tracer, 3){{ - shootEffect = ShootFx.shootSmall; - smokeEffect = ShootFx.shootSmallSmoke; - inaccuracy = 3f; - }}; - - bulletDenseBig = new AmmoType(Items.densealloy, StandardBullets.denseBig, 1){{ - shootEffect = ShootFx.shootBig; - smokeEffect = ShootFx.shootBigSmoke; - }}; - - bulletThoriumBig = new AmmoType(Items.thorium, StandardBullets.thoriumBig, 1){{ - shootEffect = ShootFx.shootBig; - smokeEffect = ShootFx.shootBigSmoke; - }}; - - bulletPyratiteBig = new AmmoType(Items.pyratite, StandardBullets.tracerBig, 2){{ - shootEffect = ShootFx.shootBig; - smokeEffect = ShootFx.shootBigSmoke; - inaccuracy = 3f; - }}; - - //flak - - flakExplosive = new AmmoType(Items.blastCompound, FlakBullets.explosive, 5){{ - shootEffect = ShootFx.shootBig; - smokeEffect = ShootFx.shootBigSmoke; - }}; - - flakPlastic = new AmmoType(Items.plastanium, FlakBullets.plastic, 5){{ - shootEffect = ShootFx.shootBig; - smokeEffect = ShootFx.shootBigSmoke; - }}; - - flakSurge = new AmmoType(Items.surgealloy, FlakBullets.surge, 5){{ - shootEffect = ShootFx.shootBig; - smokeEffect = ShootFx.shootBigSmoke; - reloadMultiplier = 1/2f; - }}; - - //missiles - - missileExplosive = new AmmoType(Items.blastCompound, MissileBullets.explosive, 1){{ - shootEffect = ShootFx.shootBig2; - smokeEffect = ShootFx.shootBigSmoke2; - reloadMultiplier = 1.2f; - }}; - - missileIncindiary = new AmmoType(Items.pyratite, MissileBullets.incindiary, 1){{ - shootEffect = ShootFx.shootBig2; - smokeEffect = ShootFx.shootBigSmoke2; - reloadMultiplier = 1.0f; - }}; - - missileSurge = new AmmoType(Items.surgealloy, MissileBullets.surge, 1){{ - shootEffect = ShootFx.shootBig2; - smokeEffect = ShootFx.shootBigSmoke2; - reloadMultiplier = 1.1f; - }}; - - //artillery - - artilleryDense = new AmmoType(Items.densealloy, ArtilleryBullets.dense, 2){{ - shootEffect = ShootFx.shootBig2; - smokeEffect = ShootFx.shootBigSmoke2; - }}; - - artilleryPlastic = new AmmoType(Items.plastanium, ArtilleryBullets.plastic, 2){{ - shootEffect = ShootFx.shootBig2; - smokeEffect = ShootFx.shootBigSmoke2; - reloadMultiplier = 1.4f; - }}; - - artilleryHoming = new AmmoType(Items.silicon, ArtilleryBullets.homing, 1){{ - shootEffect = ShootFx.shootBig2; - smokeEffect = ShootFx.shootBigSmoke2; - reloadMultiplier = 0.9f; - }}; - - artilleryIncindiary = new AmmoType(Items.pyratite, ArtilleryBullets.incindiary, 2){{ - shootEffect = ShootFx.shootBig2; - smokeEffect = ShootFx.shootBigSmoke2; - reloadMultiplier = 1.2f; - }}; - - artilleryExplosive = new AmmoType(Items.blastCompound, ArtilleryBullets.explosive, 1){{ - shootEffect = ShootFx.shootBig2; - smokeEffect = ShootFx.shootBigSmoke2; - reloadMultiplier = 1.6f; - }}; - - unitArtillery = new AmmoType(Items.blastCompound, ArtilleryBullets.unit, 1){{ - shootEffect = ShootFx.shootBig2; - smokeEffect = ShootFx.shootBigSmoke2; - reloadMultiplier = 1.6f; - }}; - - - //flame - - basicFlame = new AmmoType(Liquids.oil, TurretBullets.basicFlame, 0.3f){{ - shootEffect = ShootFx.shootSmallFlame; - }}; - - //power - - lancerLaser = new AmmoType(TurretBullets.lancerLaser); - - burstLaser = new AmmoType(TurretBullets.burstLaser){{ - range = 60f; - }}; - - lightning = new AmmoType(TurretBullets.lightning); - - arc = new AmmoType(TurretBullets.arc); - - meltdownLaser = new AmmoType(TurretBullets.meltdownLaser); - - fuseShotgun = new AmmoType(Items.densealloy, TurretBullets.fuseShot, 1f){{ - shootEffect = Fx.none; - smokeEffect = ShootFx.shootBigSmoke2; - }}; - - //liquid - - oil = new AmmoType(Liquids.oil, TurretBullets.oilShot, 0.3f); - - water = new AmmoType(Liquids.water, TurretBullets.waterShot, 0.3f); - - lava = new AmmoType(Liquids.lava, TurretBullets.lavaShot, 0.3f); - - cryofluid = new AmmoType(Liquids.cryofluid, TurretBullets.cryoShot, 0.3f); - - } - - @Override - public ContentType type(){ - return ContentType.ammo; - } -} diff --git a/core/src/io/anuke/mindustry/content/Blocks.java b/core/src/io/anuke/mindustry/content/Blocks.java new file mode 100644 index 0000000000..faa44e129c --- /dev/null +++ b/core/src/io/anuke/mindustry/content/Blocks.java @@ -0,0 +1,1417 @@ +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; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.*; +import io.anuke.mindustry.world.blocks.defense.*; +import io.anuke.mindustry.world.blocks.defense.turrets.*; +import io.anuke.mindustry.world.blocks.distribution.*; +import io.anuke.mindustry.world.blocks.power.*; +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.Vault; +import io.anuke.mindustry.world.blocks.units.MechPad; +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.*; + +public class Blocks implements ContentList{ + public static Block + + //environment + air, part, spawn, deepwater, water, tar, stone, craters, charr, sand, ice, snow, + holostone, rocks, icerocks, cliffs, pine, whiteTree, whiteTreeDead, sporeCluster, + iceSnow, sandWater, duneRocks, stainedRocks, stainedStone, stainedRocksRed, stainedStoneRed, stainedRocksYellow, stainedStoneYellow, stainedBoulder, + metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor5, ignarock, magmarock, hotrock, snowrocks, + + //crafting + siliconSmelter, kiln, graphitePress, plastaniumCompressor, multiPress, phaseWeaver, surgeSmelter, pyratiteMixer, blastMixer, cryofluidMixer, + melter, separator, centrifuge, biomatterCompressor, 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, + + //transport + conveyor, titaniumConveyor, distributor, junction, itemBridge, phaseConveyor, sorter, router, overflowGate, massDriver, + + //liquids + mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, liquidRouter, liquidTank, liquidJunction, bridgeConduit, phaseConduit, + + //power + combustionGenerator, thermalGenerator, turbineGenerator, differentialGenerator, rtgGenerator, solarPanel, largeSolarPanel, thoriumReactor, + impactReactor, battery, batteryLarge, powerNode, powerNodeLarge, surgeTower, + + //production + mechanicalDrill, pneumaticDrill, laserDrill, blastDrill, waterExtractor, oilExtractor, cultivator, + + //storage + 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, repairPoint, + + //upgrades + alphaDartPad, deltaPad, tauPad, omegaPad, javelinPad, tridentPad, glaivePad; + + @Override + public void load(){ + //region environment + + air = new Floor("air"){{ + alwaysReplace = true; + } + + public void draw(Tile tile){} + public void load(){} + public void init(){} + public TextureRegion[] variantRegions(){ + if(variantRegions == null){ + variantRegions = new TextureRegion[]{Core.atlas.find("clear")}; + } + return variantRegions; + } + }; + + part = new BlockPart(); + + spawn = new Block("spawn"){ + public void drawShadow(Tile tile){} + }; + + //Registers build blocks from size 1-6 + //no reference is needed here since they can be looked up by name later + for(int i = 1; i <= 6; i++){ + new BuildBlock("build" + i); + } + + deepwater = new Floor("deepwater"){{ + liquidColor = Color.valueOf("4d5ca4"); + speedMultiplier = 0.2f; + variants = 0; + liquidDrop = Liquids.water; + isLiquid = true; + status = StatusEffects.wet; + statusDuration = 120f; + drownTime = 140f; + cacheLayer = CacheLayer.water; + }}; + + water = new Floor("water"){{ + liquidColor = Color.valueOf("596ab8"); + speedMultiplier = 0.5f; + variants = 0; + status = StatusEffects.wet; + statusDuration = 90f; + liquidDrop = Liquids.water; + isLiquid = true; + cacheLayer = CacheLayer.water; + }}; + + tar = new Floor("tar"){{ + drownTime = 150f; + liquidColor = Color.valueOf("292929"); + status = StatusEffects.tarred; + statusDuration = 240f; + speedMultiplier = 0.19f; + variants = 0; + liquidDrop = Liquids.oil; + isLiquid = true; + cacheLayer = CacheLayer.oil; + }}; + + stone = new Floor("stone"){{ + hasOres = true; + }}; + + craters = new Floor("craters"){{ + variants = 6; + blendGroup = stone; + }}; + + charr = new Floor("char"){{ + blendGroup = stone; + }}; + + 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; + hasOres = true; + playerUnmineable = true; + }}; + + holostone = new Floor("holostone"){{ + hasOres = true; + edgeStyle = "blocky"; + }}; + + iceSnow = new Floor("ice-snow"){{ + variants = 3; + }}; + + 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; + }}; + + 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; + }}; + + stainedStone = new Floor("stained-stone"){{ + edgeStyle = "blocky"; + hasOres = true; + }}; + + stainedRocksRed = new StaticWall("stained-rocks-red"){{ + variants = 2; + }}; + + stainedStoneRed = new Floor("stained-stone-red"){{ + edgeStyle = "blocky"; + hasOres = true; + }}; + + stainedRocksYellow = new StaticWall("stained-rocks-yellow"){{ + variants = 2; + }}; + + stainedStoneYellow = new Floor("stained-stone-yellow"){{ + edgeStyle = "blocky"; + }}; + + 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"){{ + blendGroup = sand; + }}; + + hotrock = new Floor("hotrock"){{ + heat = 0.5f; + blendGroup = sand; + }}; + + magmarock = new Floor("magmarock"){{ + heat = 0.75f; + updateEffect = Fx.magmasmoke; + blendGroup = sand; + }}; + + //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)); + craftEffect = Fx.smeltsmoke; + 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.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"){{ + requirements(Category.crafting, ItemStack.with(Items.silicon, 160, Items.lead, 230, Items.graphite, 120, Items.titanium, 160)); + hasItems = true; + liquidCapacity = 60f; + craftTime = 60f; + output = Items.plastanium; + size = 2; + health = 320; + hasPower = hasLiquids = true; + craftEffect = Fx.formsmoke; + updateEffect = Fx.plasticburn; + + consumes.liquid(Liquids.oil, 0.25f); + 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; + output = Items.phasefabric; + craftTime = 120f; + size = 2; + + consumes.items(new ItemStack(Items.thorium, 4), new ItemStack(Items.sand, 10)); + 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; + output = Items.surgealloy; + craftTime = 75f; + size = 3; + + 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)); + }}; + + cryofluidMixer = new LiquidMixer("cryofluidmixer"){{ + requirements(Category.crafting, ItemStack.with(Items.lead, 130, Items.silicon, 80, Items.thorium, 90)); + outputLiquid = Liquids.cryofluid; + liquidPerItem = 50f; + size = 2; + hasPower = true; + + consumes.power(1f); + consumes.item(Items.titanium); + consumes.liquid(Liquids.water, 0.3f); + }}; + + blastMixer = new GenericCrafter("blast-mixer"){{ + requirements(Category.crafting, ItemStack.with(Items.lead, 60, Items.titanium, 40)); + hasItems = true; + hasPower = true; + output = Items.blastCompound; + size = 2; + + consumes.items(new ItemStack(Items.pyratite, 1), new ItemStack(Items.biomatter, 1)); + consumes.power(0.40f); + }}; + + pyratiteMixer = new PowerSmelter("pyratite-mixer"){{ + requirements(Category.crafting, ItemStack.with(Items.copper, 100, Items.lead, 50)); + flameColor = Color.CLEAR; + hasItems = true; + hasPower = true; + output = Items.pyratite; + + size = 2; + + consumes.power(0.20f); + consumes.items(new ItemStack(Items.coal, 1), new ItemStack(Items.lead, 2), new ItemStack(Items.sand, 2)); + }}; + + melter = new PowerCrafter("melter"){{ + requirements(Category.crafting, ItemStack.with(Items.copper, 60, Items.lead, 70, Items.graphite, 90)); + health = 200; + outputLiquid = Liquids.slag; + outputLiquidAmount = 2f; + craftTime = 10f; + hasLiquids = hasPower = true; + + consumes.power(1f); + consumes.item(Items.scrap, 1); + }}; + + separator = new Separator("separator"){{ + requirements(Category.crafting, ItemStack.with(Items.copper, 60, Items.titanium, 50)); + results = ItemStack.with( + Items.copper, 5, + Items.lead, 3, + Items.graphite, 2, + Items.titanium, 2 + ); + hasPower = true; + filterTime = 30f; + spinnerLength = 1.5f; + spinnerRadius = 3.5f; + spinnerThickness = 1.5f; + spinnerSpeed = 3f; + size = 2; + + consumes.power(1f); + consumes.liquid(Liquids.slag, 0.09f); + }}; + + cultivator = new Cultivator("cultivator"){{ + requirements(Category.crafting, ItemStack.with(Items.copper, 20, Items.lead, 50, Items.silicon, 20)); + output = Items.biomatter; + craftTime = 200; + size = 2; + hasLiquids = true; + hasPower = true; + hasItems = true; + + consumes.power(0.80f); + consumes.liquid(Liquids.water, 0.15f); + }}; + + biomatterCompressor = new Compressor("biomattercompressor"){{ + requirements(Category.crafting, ItemStack.with(Items.lead, 70, Items.silicon, 60)); + liquidCapacity = 60f; + craftTime = 20f; + outputLiquid = Liquids.oil; + outputLiquidAmount = 2.5f; + size = 2; + health = 320; + hasLiquids = true; + + consumes.item(Items.biomatter, 1); + consumes.power(0.60f); + }}; + + pulverizer = new Pulverizer("pulverizer"){{ + requirements(Category.crafting, ItemStack.with(Items.copper, 60, Items.lead, 50)); + output = Items.sand; + craftEffect = Fx.pulverize; + craftTime = 40f; + updateEffect = Fx.pulverizeSmall; + hasItems = hasPower = true; + + consumes.item(Items.scrap, 1); + 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 + //region sandbox + + powerVoid = new PowerVoid("power-void"){{ + requirements(Category.power, () -> state.rules.infiniteResources, ItemStack.with()); + alwaysUnlocked = true; + }}; + powerSource = new PowerSource("power-source"){{ + requirements(Category.power, () -> state.rules.infiniteResources, ItemStack.with()); + alwaysUnlocked = true; + }}; + itemSource = new ItemSource("item-source"){{ + requirements(Category.distribution, () -> state.rules.infiniteResources, ItemStack.with()); + alwaysUnlocked = true; + }}; + itemVoid = new ItemVoid("item-void"){{ + requirements(Category.distribution, () -> state.rules.infiniteResources, ItemStack.with()); + alwaysUnlocked = true; + }}; + liquidSource = new LiquidSource("liquid-source"){{ + requirements(Category.liquid, () -> state.rules.infiniteResources, ItemStack.with()); + alwaysUnlocked = true; + }}; + + //endregion + //region defense + + 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; + }}; + + copperWallLarge = new Wall("copper-wall-large"){{ + requirements(Category.defense, ItemStack.with(Items.copper, 12 * 4)); + health = 80 * 4 * wallHealthMultiplier; + size = 2; + }}; + + titaniumWall = new Wall("titanium-wall"){{ + requirements(Category.defense, ItemStack.with(Items.titanium, 12)); + health = 110 * wallHealthMultiplier; + }}; + + titaniumWallLarge = new Wall("titanium-wall-large"){{ + requirements(Category.defense, ItemStack.with(Items.titanium, 12 * 4)); + health = 110 * wallHealthMultiplier * 4; + size = 2; + }}; + + thoriumWall = new Wall("thorium-wall"){{ + requirements(Category.defense, ItemStack.with(Items.thorium, 12)); + health = 200 * wallHealthMultiplier; + }}; + + thoriumWallLarge = new Wall("thorium-wall-large"){{ + requirements(Category.defense, ItemStack.with(Items.thorium, 12 * 4)); + health = 200 * wallHealthMultiplier * 4; + size = 2; + }}; + + phaseWall = new DeflectorWall("phase-wall"){{ + requirements(Category.defense, ItemStack.with(Items.phasefabric, 12)); + health = 150 * wallHealthMultiplier; + }}; + + phaseWallLarge = new DeflectorWall("phase-wall-large"){{ + requirements(Category.defense, ItemStack.with(Items.phasefabric, 12 * 4)); + health = 150 * 4 * wallHealthMultiplier; + size = 2; + }}; + + surgeWall = new SurgeWall("surge-wall"){{ + requirements(Category.defense, ItemStack.with(Items.surgealloy, 12)); + health = 230 * wallHealthMultiplier; + }}; + + surgeWallLarge = new SurgeWall("surge-wall-large"){{ + requirements(Category.defense, ItemStack.with(Items.surgealloy, 12 * 4)); + health = 230 * 4 * wallHealthMultiplier; + size = 2; + }}; + + door = new Door("door"){{ + requirements(Category.defense, ItemStack.with(Items.titanium, 12, Items.silicon, 8)); + health = 100 * wallHealthMultiplier; + }}; + + doorLarge = new Door("door-large"){{ + requirements(Category.defense, ItemStack.with(Items.titanium, 12 * 4, Items.silicon, 8 * 4)); + openfx = Fx.dooropenlarge; + closefx = Fx.doorcloselarge; + health = 100 * 4 * wallHealthMultiplier; + size = 2; + }}; + + mendProjector = new MendProjector("mend-projector"){{ + 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.silicon, 250)); + consumes.power(3.50f); + size = 2; + 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.silicon, 250)); + size = 3; + consumes.item(Items.phasefabric).optional(true).boost(true); + }}; + + shockMine = new ShockMine("shock-mine"){{ + requirements(Category.effect, ItemStack.with(Items.lead, 50, Items.silicon, 25)); + health = 40; + damage = 11; + tileDamage = 7f; + length = 10; + tendrils = 5; + }}; + + //endregion + //region distribution + + conveyor = new Conveyor("conveyor"){{ + requirements(Category.distribution, ItemStack.with(Items.copper, 1), true); + health = 45; + speed = 0.03f; + }}; + + titaniumConveyor = new Conveyor("titanium-conveyor"){{ + requirements(Category.distribution, ItemStack.with(Items.copper, 2, Items.titanium, 1)); + health = 65; + speed = 0.07f; + }}; + + junction = new Junction("junction"){{ + 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)); + range = 4; + speed = 60f; + bufferCapacity = 15; + }}; + + phaseConveyor = new ItemBridge("phase-conveyor"){{ + requirements(Category.distribution, ItemStack.with(Items.phasefabric, 10, Items.silicon, 15, Items.lead, 20, Items.graphite, 20)); + range = 12; + hasPower = true; + consumes.power(0.30f); + }}; + + sorter = new Sorter("sorter"){{ + requirements(Category.distribution, ItemStack.with(Items.titanium, 4, Items.copper, 4)); + + }}; + + router = new Router("router"){{ + requirements(Category.distribution, ItemStack.with(Items.copper, 6)); + + }}; + + distributor = new Router("distributor"){{ + requirements(Category.distribution, ItemStack.with(Items.titanium, 8, Items.copper, 8)); + size = 2; + }}; + + overflowGate = new OverflowGate("overflow-gate"){{ + requirements(Category.distribution, ItemStack.with(Items.titanium, 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; + range = 440f; + }}; + + //endregion + //region liquid + + 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(1.50f); + 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.30f); + liquidCapacity = 40f; + hasPower = true; + size = 2; + tier = 2; + }}; + + conduit = new Conduit("conduit"){{ + requirements(Category.liquid, ItemStack.with(Items.lead, 1)); + health = 45; + }}; + + pulseConduit = new Conduit("pulse-conduit"){{ + requirements(Category.liquid, ItemStack.with(Items.titanium, 1, Items.lead, 1)); + liquidCapacity = 16f; + liquidFlowFactor = 4.9f; + health = 90; + }}; + + liquidRouter = new LiquidRouter("liquid-router"){{ + requirements(Category.liquid, ItemStack.with(Items.titanium, 4, Items.lead, 4)); + liquidCapacity = 20f; + }}; + + liquidTank = new LiquidTank("liquid-tank"){{ + requirements(Category.liquid, ItemStack.with(Items.titanium, 50, Items.lead, 50)); + size = 3; + liquidCapacity = 1500f; + health = 500; + }}; + + liquidJunction = new LiquidJunction("liquid-junction"){{ + requirements(Category.liquid, ItemStack.with(Items.titanium, 4, Items.lead, 4)); + }}; + + bridgeConduit = new LiquidExtendingBridge("bridge-conduit"){{ + requirements(Category.liquid, ItemStack.with(Items.titanium, 8, Items.lead, 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)); + range = 12; + hasPower = true; + consumes.power(0.30f); + }}; + + //endregion + //region power + + powerNode = new PowerNode("power-node"){{ + requirements(Category.power, ItemStack.with(Items.copper, 2, Items.lead, 6)); + maxNodes = 4; + laserRange = 6; + }}; + + powerNodeLarge = new PowerNode("power-node-large"){{ + requirements(Category.power, ItemStack.with(Items.titanium, 10, Items.lead, 20, Items.silicon, 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(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(20000f, 1f); + }}; + + combustionGenerator = new BurnerGenerator("combustion-generator"){{ + requirements(Category.power, ItemStack.with(Items.copper, 50, Items.lead, 30)); + powerProduction = 1f; + itemDuration = 40f; + }}; + + thermalGenerator = new ThermalGenerator("thermal-generator"){{ + requirements(Category.power, ItemStack.with(Items.copper, 80, Items.graphite, 70, Items.lead, 100, Items.silicon, 70, Items.thorium, 70)); + powerProduction = 3f; + 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 = 6f; + itemDuration = 30f; + consumes.liquid(Liquids.water, 0.05f); + 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 = 16f; + itemDuration = 50f; + consumes.remove(ConsumeItemFilter.class); + consumes.remove(ConsumeLiquidFilter.class); + consumes.item(Items.pyratite); + consumes.liquid(Liquids.cryofluid, 0.12f); + 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 = 3f; + itemDuration = 220f; + }}; + + solarPanel = new SolarGenerator("solar-panel"){{ + requirements(Category.power, ItemStack.with(Items.lead, 20, Items.silicon, 30)); + 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.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 = 12f; + consumes.liquid(Liquids.cryofluid, maxLiquidUse); + }}; + + impactReactor = new ImpactReactor("impact-reactor"){{ + requirements(Category.power, ItemStack.with(Items.lead, 800, Items.silicon, 600, Items.graphite, 600, Items.thorium, 200, Items.surgealloy, 400, Items.metaglass, 200)); + size = 4; + health = 900; + powerProduction = 70f; + consumes.power(23f); + consumes.item(Items.blastCompound); + consumes.liquid(Liquids.water, 0.3f); + }}; + + //endregion power + //region production + + mechanicalDrill = new Drill("mechanical-drill"){{ + requirements(Category.production, ItemStack.with(Items.copper, 25), true); + tier = 2; + drillTime = 600; + size = 2; + drawMineItem = true; + }}; + + pneumaticDrill = new Drill("pneumatic-drill"){{ + requirements(Category.production, ItemStack.with(Items.copper, 60, Items.graphite, 50)); + tier = 3; + drillTime = 480; + size = 2; + drawMineItem = 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 = 3; + hasPower = true; + tier = 4; + updateEffect = Fx.pulverizeMedium; + drillEffect = Fx.mineBig; + + consumes.power(1.10f); + }}; + + blastDrill = new Drill("blast-drill"){{ + requirements(Category.production, ItemStack.with(Items.copper, 130, Items.silicon, 120, Items.titanium, 100, Items.thorium, 60)); + drillTime = 200; + size = 4; + drawRim = true; + hasPower = true; + tier = 5; + updateEffect = Fx.pulverizeRed; + updateEffectChance = 0.03f; + drillEffect = Fx.mineHuge; + rotateSpeed = 6f; + warmupSpeed = 0.01f; + + consumes.power(3f); + }}; + + 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; + size = 2; + liquidCapacity = 30f; + rotateSpeed = 1.4f; + + consumes.power(0.90f); + }}; + + oilExtractor = new Fracker("oil-extractor"){{ + requirements(Category.production, ItemStack.with(Items.copper, 300, Items.graphite, 350, Items.lead, 230, Items.thorium, 230, Items.silicon, 150)); + result = Liquids.oil; + updateEffect = Fx.pulverize; + liquidCapacity = 50f; + updateEffectChance = 0.05f; + pumpAmount = 0.09f; + size = 3; + liquidCapacity = 30f; + + consumes.item(Items.sand); + consumes.power(3f); + consumes.liquid(Liquids.water, 0.15f); + }}; + + //endregion + //region storage + + coreShard = new CoreBlock("core-shard"){{ + requirements(Category.effect, () -> false, ItemStack.with(Items.titanium, 2000)); + alwaysUnlocked = true; + + health = 1100; + 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"){{ + requirements(Category.effect, ItemStack.with(Items.titanium, 500, Items.thorium, 250)); + size = 3; + itemCapacity = 1000; + }}; + + container = new Vault("container"){{ + requirements(Category.effect, ItemStack.with(Items.titanium, 200)); + size = 2; + itemCapacity = 300; + }}; + + unloader = new SortedUnloader("unloader"){{ + requirements(Category.distribution, ItemStack.with(Items.titanium, 50, Items.silicon, 60)); + speed = 7f; + }}; + + launchPad = new LaunchPad("launch-pad"){{ + 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; + hasPower = true; + consumes.power(1f); + }}; + + //endregion + //region turrets + + duo = new DoubleTurret("duo"){{ + requirements(Category.turret, ItemStack.with(Items.copper, 70), true); + ammo( + Items.copper, Bullets.standardCopper, + Items.graphite, Bullets.standardDense, + Items.pyratite, Bullets.standardIncendiary, + Items.silicon, Bullets.standardHoming + ); + reload = 20f; + restitution = 0.03f; + range = 95f; + shootCone = 15f; + ammoUseEffect = Fx.shellEjectSmall; + health = 210; + inaccuracy = 2f; + rotatespeed = 10f; + }}; + + 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 + ); + reload = 60f; + recoil = 2f; + range = 230f; + inaccuracy = 1f; + shootCone = 10f; + health = 120; + }}; + + wave = new LiquidTurret("wave"){{ + requirements(Category.turret, ItemStack.with(Items.titanium, 70, Items.lead, 150)); + ammo( + Liquids.water, Bullets.waterShot, + Liquids.slag, Bullets.slagShot, + Liquids.cryofluid, Bullets.cryoShot, + Liquids.oil, Bullets.oilShot + ); + size = 2; + recoil = 0f; + reload = 3f; + inaccuracy = 5f; + shootCone = 50f; + shootEffect = Fx.shootLiquid; + range = 100f; + health = 360; + + drawer = (tile, entity) -> { + Draw.rect(region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90); + + Draw.color(entity.liquids.current().color); + Draw.alpha(entity.liquids.total() / liquidCapacity); + Draw.rect(name + "-liquid", tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90); + Draw.color(); + }; + }}; + + lancer = new ChargeTurret("lancer"){{ + requirements(Category.turret, ItemStack.with(Items.copper, 50, Items.lead, 100, Items.silicon, 90)); + range = 155f; + chargeTime = 50f; + chargeMaxDelay = 30f; + chargeEffects = 7; + shootType = Bullets.lancerLaser; + recoil = 2f; + reload = 90f; + cooldown = 0.03f; + powerUsed = 1 / 3f; + consumes.powerBuffered(600f); + shootShake = 2f; + shootEffect = Fx.lancerLaserShoot; + smokeEffect = Fx.lancerLaserShootSmoke; + chargeEffect = Fx.lancerLaserCharge; + chargeBeginEffect = Fx.lancerLaserChargeBegin; + heatColor = Color.RED; + size = 2; + health = 320; + targetAir = false; + }}; + + arc = new PowerTurret("arc"){{ + requirements(Category.turret, ItemStack.with(Items.copper, 70, Items.lead, 60)); + shootType = Bullets.arc; + reload = 20f; + shootCone = 40f; + rotatespeed = 8f; + powerUsed = 1f / 2f; + consumes.powerBuffered(80f); + range = 80f; + shootEffect = Fx.lightningShoot; + heatColor = Color.RED; + recoil = 1f; + size = 1; + }}; + + 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 + ); + reload = 50f; + shots = 4; + burstSpacing = 5; + inaccuracy = 10f; + range = 140f; + xRand = 6f; + size = 2; + health = 380; + }}; + + salvo = new BurstTurret("salvo"){{ + requirements(Category.turret, ItemStack.with(Items.copper, 210, Items.graphite, 190, Items.thorium, 130)); + ammo( + Items.copper, Bullets.standardCopper, + Items.graphite, Bullets.standardDense, + Items.pyratite, Bullets.standardIncendiary, + Items.silicon, Bullets.standardHoming, + Items.thorium, Bullets.standardThorium + ); + + size = 2; + range = 120f; + reload = 35f; + restitution = 0.03f; + ammoEjectBack = 3f; + cooldown = 0.03f; + recoil = 3f; + shootShake = 2f; + burstSpacing = 4; + shots = 3; + ammoUseEffect = Fx.shellEjectBig; + health = 360; + }}; + + ripple = new ArtilleryTurret("ripple"){{ + requirements(Category.turret, ItemStack.with(Items.copper, 300, Items.graphite, 220, Items.thorium, 120)); + ammo( + Items.graphite, Bullets.artilleryDense, + Items.silicon, Bullets.artilleryHoming, + Items.pyratite, Bullets.artlleryIncendiary, + Items.blastCompound, Bullets.artilleryExplosive, + Items.plastanium, Bullets.arilleryPlastic + ); + size = 3; + shots = 4; + inaccuracy = 12f; + reload = 60f; + ammoEjectBack = 5f; + ammoUseEffect = Fx.shellEjectBig; + cooldown = 0.03f; + velocityInaccuracy = 0.2f; + restitution = 0.02f; + recoil = 6f; + shootShake = 2f; + range = 290f; + + health = 550; + }}; + + cyclone = new ItemTurret("cyclone"){{ + requirements(Category.turret, ItemStack.with(Items.copper, 400, Items.surgealloy, 200, Items.plastanium, 150)); + ammo( + Items.blastCompound, Bullets.flakExplosive, + Items.plastanium, Bullets.flakPlastic, + Items.surgealloy, Bullets.flakSurge + ); + xRand = 4f; + reload = 8f; + range = 145f; + size = 3; + recoil = 3f; + rotatespeed = 10f; + inaccuracy = 13f; + shootCone = 30f; + + health = 145 * size * size; + }}; + + fuse = new ItemTurret("fuse"){{ + requirements(Category.turret, ItemStack.with(Items.copper, 450, Items.graphite, 450, Items.surgealloy, 250)); + ammo(Items.graphite, Bullets.fuseShot); + reload = 40f; + shootShake = 4f; + range = 80f; + recoil = 5f; + restitution = 0.1f; + size = 3; + + 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 + ); + reload = 6f; + coolantMultiplier = 0.5f; + maxCoolantUsed = 1.5f; + restitution = 0.1f; + ammoUseEffect = Fx.shellEjectBig; + range = 200f; + inaccuracy = 3f; + recoil = 3f; + xRand = 3f; + shotWidth = 4f; + shootShake = 2f; + shots = 2; + size = 4; + shootCone = 24f; + + health = 155 * size * size; + }}; + + meltdown = new LaserTurret("meltdown"){{ + requirements(Category.turret, ItemStack.with(Items.copper, 500, Items.lead, 700, Items.graphite, 600, Items.surgealloy, 650, Items.silicon, 650)); + shootType = Bullets.meltdownLaser; + shootEffect = Fx.shootBigSmoke2; + shootCone = 40f; + recoil = 4f; + size = 4; + shootShake = 2f; + powerUsed = 0.5f; + consumes.powerBuffered(1200f); + range = 160f; + reload = 200f; + firingMoveFract = 0.1f; + shootDuration = 220f; + + health = 165 * size * size; + }}; + + //endregion + //region units + + spiritFactory = new UnitFactory("spirit-factory"){{ + requirements(Category.units, ItemStack.with(Items.copper, 70, Items.lead, 110, Items.silicon, 130)); + type = UnitTypes.spirit; + produceTime = 5700; + size = 2; + consumes.power(0.80f); + consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.lead, 30)); + }}; + + phantomFactory = new UnitFactory("phantom-factory"){{ + requirements(Category.units, ItemStack.with(Items.titanium, 90, Items.thorium, 80, Items.lead, 110, Items.silicon, 210)); + type = UnitTypes.phantom; + produceTime = 7300; + size = 2; + consumes.power(2f); + consumes.items(new ItemStack(Items.silicon, 70), new ItemStack(Items.lead, 80), new ItemStack(Items.titanium, 80)); + }}; + + wraithFactory = new UnitFactory("wraith-factory"){{ + requirements(Category.units, ItemStack.with(Items.titanium, 60, Items.lead, 80, Items.silicon, 90)); + type = UnitTypes.wraith; + produceTime = 1800; + size = 2; + consumes.power(1f); + consumes.items(new ItemStack(Items.silicon, 10), new ItemStack(Items.titanium, 10)); + }}; + + ghoulFactory = new UnitFactory("ghoul-factory"){{ + requirements(Category.units, ItemStack.with(Items.plastanium, 80, Items.titanium, 100, Items.lead, 130, Items.silicon, 220)); + type = UnitTypes.ghoul; + produceTime = 3600; + size = 3; + consumes.power(2f); + consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.titanium, 30), new ItemStack(Items.plastanium, 20)); + }}; + + revenantFactory = new UnitFactory("revenant-factory"){{ + requirements(Category.units, ItemStack.with(Items.plastanium, 300, Items.titanium, 400, Items.lead, 300, Items.silicon, 400, Items.surgealloy, 100)); + type = UnitTypes.revenant; + produceTime = 8000; + size = 4; + consumes.power(3f); + consumes.items(new ItemStack(Items.silicon, 80), new ItemStack(Items.titanium, 80), new ItemStack(Items.plastanium, 50)); + }}; + + daggerFactory = new UnitFactory("dagger-factory"){{ + requirements(Category.units, ItemStack.with(Items.lead, 90, Items.silicon, 70)); + type = UnitTypes.dagger; + produceTime = 1700; + size = 2; + consumes.power(0.50f); + consumes.items(new ItemStack(Items.silicon, 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(1.50f); + consumes.items(new ItemStack(Items.silicon, 20), new ItemStack(Items.thorium, 30)); + }}; + + fortressFactory = new UnitFactory("fortress-factory"){{ + requirements(Category.units, ItemStack.with(Items.thorium, 200, Items.lead, 220, Items.silicon, 150, Items.surgealloy, 100, Items.phasefabric, 50)); + type = UnitTypes.fortress; + produceTime = 5000; + size = 3; + consumes.power(2f); + consumes.items(new ItemStack(Items.silicon, 40), new ItemStack(Items.thorium, 50)); + }}; + + repairPoint = new RepairPoint("repair-point"){{ + requirements(Category.units, ItemStack.with(Items.lead, 30, Items.copper, 30, Items.silicon, 30)); + repairSpeed = 0.1f; + }}; + + //endregion + //region upgrades + + 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; + consumes.powerBuffered(50f); + }}; + + deltaPad = new MechPad("delta-mech-pad"){{ + requirements(Category.upgrade, ItemStack.with(Items.lead, 350, Items.titanium, 350, Items.copper, 400, Items.silicon, 450, Items.thorium, 300)); + mech = Mechs.delta; + size = 2; + consumes.powerBuffered(70f); + }}; + + tauPad = new MechPad("tau-mech-pad"){{ + requirements(Category.upgrade, ItemStack.with(Items.lead, 250, Items.titanium, 250, Items.copper, 250, Items.silicon, 250)); + mech = Mechs.tau; + size = 2; + consumes.powerBuffered(100f); + }}; + + omegaPad = new MechPad("omega-mech-pad"){{ + requirements(Category.upgrade, ItemStack.with(Items.lead, 450, Items.graphite, 550, Items.silicon, 650, Items.thorium, 600, Items.surgealloy, 240)); + mech = Mechs.omega; + size = 3; + consumes.powerBuffered(120f); + }}; + + 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; + size = 2; + consumes.powerBuffered(80f); + }}; + + tridentPad = new MechPad("trident-ship-pad"){{ + requirements(Category.upgrade, ItemStack.with(Items.lead, 250, Items.copper, 250, Items.silicon, 250, Items.titanium, 300, Items.plastanium, 200)); + mech = Mechs.trident; + size = 2; + consumes.powerBuffered(100f); + }}; + + glaivePad = new MechPad("glaive-ship-pad"){{ + requirements(Category.upgrade, ItemStack.with(Items.lead, 450, Items.silicon, 650, Items.titanium, 700, Items.plastanium, 600, Items.surgealloy, 200)); + mech = Mechs.glaive; + size = 3; + consumes.powerBuffered(120f); + }}; + + //endregion + //region ores + + //create ores for every floor and item combination necessary + for(Item item : content.items()){ + if(!item.genOre) continue; + + for(Block block : content.blocks()){ + if(block instanceof Floor && ((Floor) block).hasOres){ + new OreBlock(item, (Floor) block); + } + } + } + + //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 new file mode 100644 index 0000000000..bcc7a59e52 --- /dev/null +++ b/core/src/io/anuke/mindustry/content/Bullets.java @@ -0,0 +1,711 @@ +package io.anuke.mindustry.content; + +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; +import io.anuke.arc.graphics.g2d.Fill; +import io.anuke.arc.graphics.g2d.Lines; +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.Pal; +import io.anuke.mindustry.graphics.Shapes; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.BuildBlock; + +import static io.anuke.mindustry.Vars.world; + +public class Bullets implements ContentList{ + public static BulletType + + //artillery + artilleryDense, arilleryPlastic, artilleryPlasticFrag, artilleryHoming, artlleryIncendiary, artilleryExplosive, artilleryUnit, + + //flak + flakPlastic, flakExplosive, flakSurge, + + //missiles + missileExplosive, missileIncendiary, missileSurge, missileJavelin, missileSwarm, missileRevenant, + + //standard + standardCopper, standardDense, standardThorium, standardHoming, standardIncendiary, standardMechSmall, + standardGlaive, standardDenseBig, standardThoriumBig, standardIncendiaryBig, + + //electric + lancerLaser, meltdownLaser, lightning, arc, damageLightning, + + //liquid + waterShot, cryoShot, slagShot, oilShot, + + //environment, misc. + fireball, basicFlame, fuseShot, driverBolt, healBullet, frag, eruptorShot, + + //bombs + bombExplosive, bombIncendiary, bombOil, explode; + + @Override + public void load(){ + + artilleryDense = new ArtilleryBulletType(3f, 0, "shell"){{ + hitEffect = Fx.flakExplosion; + knockback = 0.8f; + lifetime = 50f; + bulletWidth = bulletHeight = 11f; + collidesTiles = false; + splashDamageRadius = 25f; + splashDamage = 33f; + }}; + + artilleryPlasticFrag = new BasicBulletType(2.5f, 7, "bullet"){{ + bulletWidth = 10f; + bulletHeight = 12f; + bulletShrink = 1f; + lifetime = 15f; + backColor = Pal.plastaniumBack; + frontColor = Pal.plastaniumFront; + despawnEffect = Fx.none; + }}; + + arilleryPlastic = new ArtilleryBulletType(3.4f, 0, "shell"){{ + hitEffect = Fx.plasticExplosion; + knockback = 1f; + lifetime = 55f; + bulletWidth = bulletHeight = 13f; + collidesTiles = false; + splashDamageRadius = 35f; + splashDamage = 45f; + fragBullet = artilleryPlasticFrag; + fragBullets = 10; + backColor = Pal.plastaniumBack; + frontColor = Pal.plastaniumFront; + }}; + + artilleryHoming = new ArtilleryBulletType(3f, 0, "shell"){{ + hitEffect = Fx.flakExplosion; + knockback = 0.8f; + lifetime = 45f; + bulletWidth = bulletHeight = 11f; + collidesTiles = false; + splashDamageRadius = 25f; + splashDamage = 33f; + homingPower = 2f; + homingRange = 50f; + }}; + + artlleryIncendiary = new ArtilleryBulletType(3f, 0, "shell"){{ + hitEffect = Fx.blastExplosion; + knockback = 0.8f; + lifetime = 60f; + bulletWidth = bulletHeight = 13f; + collidesTiles = false; + splashDamageRadius = 25f; + splashDamage = 30f; + incendAmount = 4; + incendSpread = 11f; + frontColor = Pal.lightishOrange; + backColor = Pal.lightOrange; + trailEffect = Fx.incendTrail; + }}; + + artilleryExplosive = new ArtilleryBulletType(2f, 0, "shell"){{ + hitEffect = Fx.blastExplosion; + knockback = 0.8f; + lifetime = 70f; + bulletWidth = bulletHeight = 14f; + collidesTiles = false; + splashDamageRadius = 45f; + splashDamage = 50f; + backColor = Pal.missileYellowBack; + frontColor = Pal.missileYellow; + }}; + + artilleryUnit = new ArtilleryBulletType(2f, 0, "shell"){{ + hitEffect = Fx.blastExplosion; + knockback = 0.8f; + lifetime = 90f; + bulletWidth = bulletHeight = 14f; + collides = true; + collidesTiles = true; + splashDamageRadius = 45f; + splashDamage = 50f; + backColor = Pal.bulletYellowBack; + frontColor = Pal.bulletYellow; + }}; + + flakPlastic = new FlakBulletType(4f, 6){{ + splashDamageRadius = 50f; + fragBullet = artilleryPlasticFrag; + fragBullets = 6; + hitEffect = Fx.plasticExplosion; + 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"){{ + bulletWidth = 8f; + bulletHeight = 8f; + bulletShrink = 0f; + drag = -0.01f; + splashDamageRadius = 30f; + splashDamage = 30f; + lifetime = 150f; + hitEffect = Fx.blastExplosion; + despawnEffect = Fx.blastExplosion; + }}; + + missileIncendiary = new MissileBulletType(2f, 12, "missile"){{ + frontColor = Pal.lightishOrange; + backColor = Pal.lightOrange; + bulletWidth = 7f; + bulletHeight = 8f; + bulletShrink = 0f; + drag = -0.01f; + homingPower = 7f; + splashDamageRadius = 10f; + splashDamage = 10f; + lifetime = 160f; + hitEffect = Fx.blastExplosion; + incendSpread = 10f; + incendAmount = 3; + }}; + + missileSurge = new MissileBulletType(3.5f, 15, "bullet"){{ + bulletWidth = 8f; + bulletHeight = 8f; + bulletShrink = 0f; + drag = -0.01f; + splashDamageRadius = 30f; + splashDamage = 22f; + lifetime = 150f; + hitEffect = Fx.blastExplosion; + despawnEffect = Fx.blastExplosion; + lightining = 2; + lightningLength = 14; + }}; + + missileJavelin = new MissileBulletType(5f, 10.5f, "missile"){{ + bulletWidth = 8f; + bulletHeight = 8f; + bulletShrink = 0f; + drag = -0.003f; + keepVelocity = false; + splashDamageRadius = 20f; + splashDamage = 1f; + lifetime = 90f; + trailColor = Color.valueOf("b6c6fd"); + hitEffect = Fx.blastExplosion; + despawnEffect = Fx.blastExplosion; + backColor = Pal.bulletYellowBack; + frontColor = Pal.bulletYellow; + weaveScale = 8f; + weaveMag = 2f; + }}; + + missileSwarm = new MissileBulletType(2.7f, 12, "missile"){{ + bulletWidth = 8f; + bulletHeight = 8f; + bulletShrink = 0f; + drag = -0.003f; + homingRange = 60f; + keepVelocity = false; + splashDamageRadius = 25f; + splashDamage = 10f; + lifetime = 120f; + trailColor = Color.GRAY; + backColor = Pal.bulletYellowBack; + frontColor = Pal.bulletYellow; + hitEffect = Fx.blastExplosion; + despawnEffect = Fx.blastExplosion; + weaveScale = 8f; + weaveMag = 2f; + }}; + + 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 = 1; + }}; + + standardDense = new BasicBulletType(3.5f, 18, "bullet"){{ + bulletWidth = 9f; + bulletHeight = 12f; + armorPierce = 0.2f; + reloadMultiplier = 0.6f; + ammoMultiplier = 2; + }}; + + standardThorium = new BasicBulletType(4f, 29, "bullet"){{ + bulletWidth = 10f; + bulletHeight = 13f; + armorPierce = 0.5f; + shootEffect = Fx.shootBig; + smokeEffect = Fx.shootBigSmoke; + ammoMultiplier = 2; + }}; + + standardHoming = new BasicBulletType(3f, 9, "bullet"){{ + bulletWidth = 7f; + bulletHeight = 9f; + homingPower = 5f; + reloadMultiplier = 1.4f; + ammoMultiplier = 3; + }}; + + standardIncendiary = new BasicBulletType(3.2f, 11, "bullet"){{ + bulletWidth = 10f; + bulletHeight = 12f; + frontColor = Pal.lightishOrange; + backColor = Pal.lightOrange; + incendSpread = 3f; + incendAmount = 1; + incendChance = 0.3f; + inaccuracy = 3f; + }}; + + standardGlaive = new BasicBulletType(4f, 7.5f, "bullet"){{ + bulletWidth = 10f; + bulletHeight = 12f; + frontColor = Color.valueOf("feb380"); + backColor = Color.valueOf("ea8878"); + incendSpread = 3f; + incendAmount = 1; + incendChance = 0.3f; + }}; + + standardMechSmall = new BasicBulletType(4f, 9, "bullet"){{ + bulletWidth = 11f; + bulletHeight = 14f; + lifetime = 40f; + inaccuracy = 5f; + despawnEffect = Fx.hitBulletSmall; + }}; + + standardDenseBig = new BasicBulletType(7f, 42, "bullet"){{ + 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 = Pal.lightishOrange; + backColor = Pal.lightOrange; + incendSpread = 3f; + incendAmount = 2; + incendChance = 0.3f; + shootEffect = Fx.shootBig; + }}; + + damageLightning = new BulletType(0.0001f, 0f){{ + lifetime = Lightning.lifetime; + hitEffect = Fx.hitLancer; + despawnEffect = Fx.none; + status = StatusEffects.shocked; + statusDuration = 10f; + }}; + + healBullet = new BulletType(5.2f, 13){ + float healPercent = 3f; + + { + hitEffect = Fx.hitLaser; + despawnEffect = Fx.hitLaser; + collidesTeam = true; + } + + @Override + public boolean collides(Bullet b, Tile tile){ + return tile.getTeam() != b.getTeam() || tile.entity.healthf() < 1f; + } + + @Override + public void draw(Bullet b){ + Draw.color(Pal.heal); + Lines.stroke(2f); + Lines.lineAngleCenter(b.x, b.y, b.rot(), 7f); + Draw.color(Color.WHITE); + Lines.lineAngleCenter(b.x, b.y, b.rot(), 3f); + Draw.reset(); + } + + @Override + public void hitTile(Bullet b, Tile tile){ + super.hit(b); + tile = tile.target(); + + if(tile != null && tile.getTeam() == b.getTeam() && !(tile.block() instanceof BuildBlock)){ + Effects.effect(Fx.healBlockFull, Pal.heal, tile.drawx(), tile.drawy(), tile.block().size); + tile.entity.healBy(healPercent / 100f * tile.entity.maxHealth()); + } + } + }; + + fireball = new BulletType(1f, 4){ + { + pierce = true; + hitTiles = false; + collides = false; + collidesTiles = false; + drag = 0.03f; + hitEffect = despawnEffect = Fx.none; + } + + @Override + public void init(Bullet b){ + b.velocity().setLength(0.6f + Mathf.random(2f)); + } + + @Override + public void draw(Bullet b){ + //TODO add color to the bullet depending on the color of the flame it came from + Draw.color(Pal.lightFlame, Pal.darkFlame, Color.GRAY, b.fin()); + Fill.circle(b.x, b.y, 3f * b.fout()); + Draw.reset(); + } + + @Override + public void update(Bullet b){ + if(Mathf.chance(0.04 * Time.delta())){ + Tile tile = world.tileWorld(b.x, b.y); + if(tile != null){ + Fire.create(tile); + } + } + + if(Mathf.chance(0.1 * Time.delta())){ + Effects.effect(Fx.fireballsmoke, b.x, b.y); + } + + if(Mathf.chance(0.1 * Time.delta())){ + Effects.effect(Fx.ballfire, b.x, b.y); + } + } + }; + + basicFlame = new BulletType(2.3f, 5){ + { + hitSize = 7f; + lifetime = 35f; + pierce = true; + drag = 0.05f; + statusDuration = 60f * 4; + shootEffect = Fx.shootSmallFlame; + hitEffect = Fx.hitFlameSmall; + despawnEffect = Fx.none; + status = StatusEffects.burning; + } + + @Override + public void draw(Bullet b){ + } + }; + + lancerLaser = new BulletType(0.001f, 140){ + 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 = 160f; + + { + hitEffect = Fx.hitLancer; + despawnEffect = Fx.none; + hitSize = 4; + lifetime = 16f; + 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); + } + + @Override + public void draw(Bullet b){ + float f = Mathf.curve(b.fin(), 0f, 0.2f); + float baseLen = length * f; + + Lines.lineAngle(b.x, b.y, b.rot(), baseLen); + for(int s = 0; s < 3; s++){ + Draw.color(colors[s]); + for(int i = 0; i < tscales.length; i++){ + Lines.stroke(7f * b.fout() * (s == 0 ? 1.5f : s == 1 ? 1f : 0.3f) * tscales[i]); + Lines.lineAngle(b.x, b.y, b.rot(), baseLen * lenscales[i]); + } + } + Draw.reset(); + } + }; + + 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}; + float[] strokes = {2f, 1.5f, 1f, 0.3f}; + float[] lenscales = {1f, 1.12f, 1.15f, 1.17f}; + float length = 200f; + + { + hitEffect = Fx.hitMeltdown; + despawnEffect = Fx.none; + hitSize = 4; + drawSize = 420f; + lifetime = 16f; + pierce = true; + } + + @Override + public void update(Bullet b){ + if(b.timer.get(1, 5f)){ + Damage.collideLine(b, b.getTeam(), hitEffect, b.x, b.y, b.rot(), length); + } + Effects.shake(1f, 1f, b.x, b.y); + } + + @Override + public void hit(Bullet b, float hitx, float hity){ + Effects.effect(hitEffect, colors[2], hitx, hity); + if(Mathf.chance(0.4)){ + Fire.create(world.tileWorld(hitx+Mathf.range(5f), hity+Mathf.range(5f))); + } + } + + @Override + public void draw(Bullet b){ + float baseLen = (length) * b.fout(); + + Lines.lineAngle(b.x, b.y, b.rot(), baseLen); + for(int s = 0; s < colors.length; s++){ + Draw.color(tmpColor.set(colors[s]).mul(1f + Mathf.absin(Time.time(), 1f, 0.1f))); + for(int i = 0; i < tscales.length; i++){ + Tmp.v1.trns(b.rot() + 180f, (lenscales[i] - 1f) * 35f); + Lines.stroke((9f + Mathf.absin(Time.time(), 0.8f, 1.5f)) * b.fout() * strokes[s] * tscales[i]); + Lines.lineAngle(b.x + Tmp.v1.x, b.y + Tmp.v1.y, b.rot(), baseLen * lenscales[i], CapStyle.none); + } + } + Draw.reset(); + } + }; + + fuseShot = new BulletType(0.01f, 70){ + int rays = 3; + float rayLength = 80f; + { + hitEffect = Fx.hitFuse; + lifetime = 13f; + despawnEffect = Fx.none; + pierce = true; + } + + @Override + public void init(Bullet b) { + for (int i = 0; i < rays; i++) { + Damage.collideLine(b, b.getTeam(), hitEffect, b.x, b.y, b.rot(), rayLength - Math.abs(i - (rays/2))*20f); + } + } + + @Override + public void draw(Bullet b) { + super.draw(b); + 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); + Shapes.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, 4f, sl, b.rot() + 90); + Shapes.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, 4f, sl, b.rot() - 90); + } + Shapes.tri(b.x, b.y, 13f, (rayLength+50) * b.fout(), b.rot()); + Shapes.tri(b.x, b.y, 13f, 10f * b.fout(), b.rot() + 180f); + Draw.reset(); + } + }; + + waterShot = new LiquidBulletType(Liquids.water){{ + knockback = 0.7f; + }}; + + cryoShot = new LiquidBulletType(Liquids.cryofluid){{ + + }}; + + slagShot = new LiquidBulletType(Liquids.slag){{ + damage = 4; + speed = 1.9f; + 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; + }}; + + lightning = new BulletType(0.001f, 12f){ + { + lifetime = 1f; + despawnEffect = Fx.none; + hitEffect = Fx.hitLancer; + keepVelocity = false; + } + + @Override + public void draw(Bullet b){ + } + + @Override + public void init(Bullet b){ + Lightning.create(b.getTeam(), Pal.lancerLaser, damage, b.x, b.y, b.rot(), 30); + } + }; + + arc = new BulletType(0.001f, 20){{ + lifetime = 1; + despawnEffect = Fx.none; + hitEffect = Fx.hitLancer; + } + + @Override + public void draw(Bullet b){} + + @Override + public void init(Bullet b){ + Lightning.create(b.getTeam(), Pal.lancerLaser, damage, b.x, b.y, b.rot(), 14); + } + }; + + driverBolt = new MassDriverBolt(); + + frag = new BasicBulletType(5f, 8, "bullet"){{ + bulletWidth = 8f; + bulletHeight = 9f; + bulletShrink = 0.5f; + lifetime = 50f; + drag = 0.04f; + }}; + + bombExplosive = new BombBulletType(10f, 20f, "shell"){{ + bulletWidth = 9f; + bulletHeight = 13f; + hitEffect = Fx.flakExplosion; + }}; + + bombIncendiary = new BombBulletType(7f, 10f, "shell"){{ + bulletWidth = 8f; + bulletHeight = 12f; + hitEffect = Fx.flakExplosion; + backColor = Pal.lightOrange; + frontColor = Pal.lightishOrange; + incendChance = 1f; + incendAmount = 3; + incendSpread = 10f; + }}; + + bombOil = new BombBulletType(2f, 3f, "shell"){{ + bulletWidth = 8f; + bulletHeight = 12f; + hitEffect = Fx.pulverize; + backColor = new Color(0x4f4f4fff); + frontColor = Color.GRAY; + } + + @Override + public void hit(Bullet b, float x, float y){ + super.hit(b, x, y); + + for(int i = 0; i < 3; i++){ + Tile tile = world.tileWorld(x + Mathf.range(8f), y + Mathf.range(8f)); + Puddle.deposit(tile, Liquids.oil, 5f); + } + } + }; + + explode = new BombBulletType(2f, 3f, "clear"){{ + hitEffect = Fx.pulverize; + lifetime = 23f; + speed = 1f; + splashDamageRadius = 60f; + splashDamage = 30f; + } + + @Override + public void init(Bullet b){ + if(b.getOwner() instanceof Unit){ + Unit unit = (Unit)b.getOwner(); + + unit.damage(unit.maxHealth() + 1); + } + b.time(b.lifetime()); + } + + @Override + public void hit(Bullet b, float x, float y){ + super.hit(b, x, y); + + for(int i = 0; i < 3; i++){ + Tile tile = world.tileWorld(x + Mathf.range(8f), y + Mathf.range(8f)); + Puddle.deposit(tile, Liquids.oil, 5f); + } + } + }; + } +} diff --git a/core/src/io/anuke/mindustry/content/Fx.java b/core/src/io/anuke/mindustry/content/Fx.java new file mode 100644 index 0000000000..83592abc5d --- /dev/null +++ b/core/src/io/anuke/mindustry/content/Fx.java @@ -0,0 +1,1148 @@ +package io.anuke.mindustry.content; + +import io.anuke.arc.Core; +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.Lines; +import io.anuke.arc.math.Angles; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Tmp; +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.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; + +public class Fx implements ContentList{ + public static Effect + + none, placeBlock, breakBlock, smoke, spawn, tapBlock, select, + vtolHover, unitDrop, unitPickup, unitLand, pickup, healWave, heal, landShock, reactorsmoke, nuclearsmoke, nuclearcloud, + redgeneratespark, generatespark, fuelburn, plasticburn, pulverize, pulverizeRed, pulverizeRedder, pulverizeSmall, pulverizeMedium, + producesmoke, smeltsmoke, formsmoke, blastsmoke, lava, doorclose, dooropen, dooropenlarge, doorcloselarge, purify, purifyoil, purifystone, generate, + mine, mineBig, mineHuge, smelt, teleportActivate, teleport, teleportOut, ripple, bubble, launch, + healBlock, healBlockFull, healWaveMend, overdriveWave, overdriveBlockFull, shieldBreak, hitBulletSmall, hitFuse, + hitBulletBig, hitFlameSmall, hitLiquid, hitLaser, hitLancer, hitMeltdown, despawn, flakExplosion, blastExplosion, + plasticExplosion, artilleryTrail, incendTrail, missileTrail, absorb, flakExplosionBig, plasticExplosionFlak, burning, fire, + fireSmoke, steam, fireballsmoke, ballfire, freezing, melting, wet, oily, overdriven, dropItem, shockwave, + 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; + + @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(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(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(Pal.remove); + Lines.stroke(3f - e.fin() * 2f); + Lines.square(e.x, e.y, tilesize / 2f * e.rotation + e.fin() * 3f); + + Angles.randLenVectors(e.id, 3 + (int) (e.rotation * 3), e.rotation * 2f + (tilesize * e.rotation) * e.finpow(), (x, y) -> { + Fill.square(e.x + x, e.y + y, 1f + e.fout() * (3f + e.rotation)); + }); + Draw.reset(); + }); + + select = new Effect(23, e -> { + 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, Pal.darkishGray, e.fin()); + float size = 7f - e.fin() * 7f; + Draw.rect("circle", e.x, e.y, size, size); + Draw.reset(); + }); + + 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(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(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(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); + }); + Draw.reset(); + }); + + unitLand = new GroundEffect(30, e -> { + 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); + }); + Draw.reset(); + }); + + unitPickup = new GroundEffect(18, e -> { + 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(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(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(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(Pal.heal); + Lines.stroke(e.fout() * 2f); + Lines.poly(e.x, e.y, 10, 2f + e.finpow() * 7f); + Draw.color(); + }); + + + hitBulletSmall = new Effect(14, e -> { + Draw.color(Color.WHITE, Pal.lightOrange, e.fin()); + + e.scaled(7f, s -> { + Lines.stroke(0.5f + s.fout()); + Lines.circle(e.x, e.y, s.fin()*5f); + }); + + + Lines.stroke(0.5f + e.fout()); + + Angles.randLenVectors(e.id, 5, e.fin() * 15f, (x, y) -> { + float ang = Mathf.angle(x, y); + Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 3 + 1f); + }); + + Draw.reset(); + }); + + hitFuse = new Effect(14, e -> { + Draw.color(Color.WHITE, Pal.surge, e.fin()); + + e.scaled(7f, s -> { + Lines.stroke(0.5f + s.fout()); + Lines.circle(e.x, e.y, s.fin()*7f); + }); + + + Lines.stroke(0.5f + e.fout()); + + Angles.randLenVectors(e.id, 6, e.fin() * 15f, (x, y) -> { + float ang = Mathf.angle(x, y); + Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 3 + 1f); + }); + + Draw.reset(); + }); + + hitBulletBig = new Effect(13, e -> { + 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) -> { + float ang = Mathf.angle(x, y); + Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 4 + 1.5f); + }); + + Draw.reset(); + }); + + hitFlameSmall = new Effect(14, e -> { + 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) -> { + float ang = Mathf.angle(x, y); + Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 3 + 1f); + }); + + Draw.reset(); + }); + + hitLiquid = new Effect(16, e -> { + Draw.color(e.color); + + Angles.randLenVectors(e.id, 5, e.fin() * 15f, e.rotation + 180f, 60f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 2f); + }); + + Draw.reset(); + }); + + hitLancer = new Effect(12, e -> { + Draw.color(Color.WHITE); + Lines.stroke(e.fout() * 1.5f); + + Angles.randLenVectors(e.id, 8, e.finpow() * 17f, e.rotation, 360f, (x, y) -> { + float ang = Mathf.angle(x, y); + Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 4 + 1f); + }); + + Draw.reset(); + }); + + hitMeltdown = new Effect(12, e -> { + Draw.color(Pal.meltdownHit); + Lines.stroke(e.fout() * 2f); + + Angles.randLenVectors(e.id, 6, e.finpow() * 18f, e.rotation, 360f, (x, y) -> { + float ang = Mathf.angle(x, y); + Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 4 + 1f); + }); + + Draw.reset(); + }); + + hitLaser = new Effect(8, e -> { + 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(Pal.lighterOrange, Color.GRAY, e.fin()); + Lines.stroke(e.fout()); + + Angles.randLenVectors(e.id, 7, e.fin() * 7f, e.rotation, 40f, (x, y) -> { + float ang = Mathf.angle(x, y); + Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 2 + 1f); + }); + + Draw.reset(); + }); + + flakExplosion = new Effect(20, e -> { + + Draw.color(Pal.bulletYellow); + e.scaled(6, i -> { + Lines.stroke(3f * i.fout()); + Lines.circle(e.x, e.y, 3f + i.fin() * 10f); + }); + + Draw.color(Color.GRAY); + + Angles.randLenVectors(e.id, 5, 2f + 23f * e.finpow(), (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 3f + 0.5f); + }); + + Draw.color(Pal.lighterOrange); + Lines.stroke(1f * e.fout()); + + Angles.randLenVectors(e.id + 1, 4, 1f + 23f * e.finpow(), (x, y) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f); + }); + + Draw.reset(); + }); + + plasticExplosion = new Effect(24, e -> { + + Draw.color(Pal.plastaniumFront); + e.scaled(7, i -> { + Lines.stroke(3f * i.fout()); + Lines.circle(e.x, e.y, 3f + i.fin() * 24f); + }); + + Draw.color(Color.GRAY); + + Angles.randLenVectors(e.id, 7, 2f + 28f * e.finpow(), (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f); + }); + + Draw.color(Pal.plastaniumBack); + Lines.stroke(1f * e.fout()); + + Angles.randLenVectors(e.id + 1, 4, 1f + 25f * e.finpow(), (x, y) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f); + }); + + Draw.reset(); + }); + + plasticExplosionFlak = new Effect(28, e -> { + + Draw.color(Pal.plastaniumFront); + e.scaled(7, i -> { + Lines.stroke(3f * i.fout()); + Lines.circle(e.x, e.y, 3f + i.fin() * 34f); + }); + + Draw.color(Color.GRAY); + + Angles.randLenVectors(e.id, 7, 2f + 30f * e.finpow(), (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f); + }); + + Draw.color(Pal.plastaniumBack); + Lines.stroke(1f * e.fout()); + + Angles.randLenVectors(e.id + 1, 4, 1f + 30f * e.finpow(), (x, y) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f); + }); + + Draw.reset(); + }); + + blastExplosion = new Effect(22, e -> { + + Draw.color(Pal.missileYellow); + e.scaled(6, i -> { + Lines.stroke(3f * i.fout()); + Lines.circle(e.x, e.y, 3f + i.fin() * 15f); + }); + + Draw.color(Color.GRAY); + + Angles.randLenVectors(e.id, 5, 2f + 23f * e.finpow(), (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f); + }); + + Draw.color(Pal.missileYellowBack); + Lines.stroke(1f * e.fout()); + + Angles.randLenVectors(e.id + 1, 4, 1f + 23f * e.finpow(), (x, y) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f); + }); + + Draw.reset(); + }); + + artilleryTrail = new Effect(50, e -> { + Draw.color(e.color); + Fill.circle(e.x, e.y, e.rotation * e.fout()); + Draw.reset(); + }); + + incendTrail = new Effect(50, e -> { + Draw.color(Pal.lightOrange); + Fill.circle(e.x, e.y, e.rotation * e.fout()); + Draw.reset(); + }); + + missileTrail = new Effect(50, e -> { + Draw.color(e.color); + Fill.circle(e.x, e.y, e.rotation * e.fout()); + Draw.reset(); + }); + + absorb = new Effect(12, e -> { + Draw.color(Pal.accent); + Lines.stroke(2f * e.fout()); + Lines.circle(e.x, e.y, 5f * e.fout()); + Draw.reset(); + }); + + flakExplosionBig = new Effect(30, e -> { + + Draw.color(Pal.bulletYellowBack); + e.scaled(6, i -> { + Lines.stroke(3f * i.fout()); + Lines.circle(e.x, e.y, 3f + i.fin() * 25f); + }); + + Draw.color(Color.GRAY); + + Angles.randLenVectors(e.id, 6, 2f + 23f * e.finpow(), (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f); + }); + + Draw.color(Pal.bulletYellow); + Lines.stroke(1f * e.fout()); + + Angles.randLenVectors(e.id + 1, 4, 1f + 23f * e.finpow(), (x, y) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f); + }); + + Draw.reset(); + }); + + + burning = new Effect(35f, e -> { + 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); + }); + + Draw.color(); + }); + + fire = new Effect(35f, e -> { + 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); + }); + + Draw.color(); + }); + + fireSmoke = new Effect(35f, e -> { + Draw.color(Color.GRAY); + + Angles.randLenVectors(e.id, 1, 2f + e.fin() * 7f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, 0.2f + e.fslope() * 1.5f); + }); + + Draw.color(); + }); + + steam = new Effect(35f, e -> { + Draw.color(Color.LIGHT_GRAY); + + 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); + }); + + Draw.color(); + }); + + fireballsmoke = new Effect(25f, e -> { + Draw.color(Color.GRAY); + + Angles.randLenVectors(e.id, 1, 2f + e.fin() * 7f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, 0.2f + e.fout() * 1.5f); + }); + + Draw.color(); + }); + + ballfire = new Effect(25f, e -> { + 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); + }); + + Draw.color(); + }); + + freezing = new Effect(40f, e -> { + Draw.color(Liquids.cryofluid.color); + + Angles.randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 1.2f); + }); + + Draw.color(); + }); + + melting = new Effect(40f, e -> { + Draw.color(Liquids.slag.color, Color.WHITE, e.fout() / 5f + Mathf.randomSeedRange(e.id, 0.12f)); + + Angles.randLenVectors(e.id, 2, 1f + e.fin() * 3f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, .2f + e.fout() * 1.2f); + }); + + Draw.color(); + }); + + wet = new Effect(40f, e -> { + Draw.color(Liquids.water.color); + + Angles.randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 1f); + }); + + Draw.color(); + }); + + oily = new Effect(42f, e -> { + Draw.color(Liquids.oil.color); + + Angles.randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 1f); + }); + + Draw.color(); + }); + + overdriven = new Effect(20f, e -> { + 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); + }); + + Draw.color(); + }); + + dropItem = new Effect(20f, e -> { + float length = 20f * e.finpow(); + float size = 7f * e.fout(); + + Draw.rect(((Item) e.data).icon(Icon.large), e.x + Angles.trnsx(e.rotation, length), e.y + Angles.trnsy(e.rotation, length), size, size); + }); + + + shockwave = new Effect(10f, 80f, e -> { + Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin()); + Lines.stroke(e.fout() * 2f + 0.2f); + Lines.circle(e.x, e.y, e.fin() * 28f); + Draw.reset(); + }); + + bigShockwave = new Effect(10f, 80f, e -> { + Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin()); + Lines.stroke(e.fout() * 3f); + Lines.circle(e.x, e.y, e.fin() * 50f); + Draw.reset(); + }); + + nuclearShockwave = new Effect(10f, 200f, e -> { + Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin()); + Lines.stroke(e.fout() * 3f + 0.2f); + Lines.poly(e.x, e.y, 40, e.fin() * 140f); + 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()); + Lines.circle(e.x, e.y, 3f + i.fin() * 10f); + }); + + Draw.color(Color.GRAY); + + Angles.randLenVectors(e.id, 6, 2f + 19f * e.finpow(), (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 3f + 0.5f); + Fill.circle(e.x + x / 2f, e.y + y / 2f, e.fout() * 1f); + }); + + 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) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f); + }); + + Draw.reset(); + }); + + blockExplosion = new Effect(30, e -> { + e.scaled(7, i -> { + Lines.stroke(3.1f * i.fout()); + Lines.circle(e.x, e.y, 3f + i.fin() * 14f); + }); + + Draw.color(Color.GRAY); + + Angles.randLenVectors(e.id, 6, 2f + 19f * e.finpow(), (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 3f + 0.5f); + Fill.circle(e.x + x / 2f, e.y + y / 2f, e.fout() * 1f); + }); + + 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) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * 3f); + }); + + Draw.reset(); + }); + + blockExplosionSmoke = new Effect(30, e -> { + Draw.color(Color.GRAY); + + Angles.randLenVectors(e.id, 6, 4f + 30f * e.finpow(), (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 3f); + Fill.circle(e.x + x / 2f, e.y + y / 2f, e.fout() * 1f); + }); + + Draw.reset(); + }); + + + shootSmall = new Effect(8, e -> { + 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); + Draw.reset(); + }); + + shootHeal = new Effect(8, e -> { + 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); + Draw.reset(); + }); + + shootSmallSmoke = new Effect(20f, e -> { + 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); + }); + + Draw.reset(); + }); + + shootBig = new Effect(9, e -> { + 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); + Draw.reset(); + }); + + shootBig2 = new Effect(10, e -> { + 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); + Draw.reset(); + }); + + shootBigSmoke = new Effect(17f, e -> { + 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); + }); + + Draw.reset(); + }); + + shootBigSmoke2 = new Effect(18f, e -> { + 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); + }); + + Draw.reset(); + }); + + shootSmallFlame = new Effect(32f, e -> { + Draw.color(Pal.lightFlame, Pal.darkFlame, Color.GRAY, e.fin()); + + 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); + }); + + Draw.reset(); + }); + + shootLiquid = new Effect(40f, e -> { + Draw.color(e.color, Color.WHITE, e.fout() / 6f + Mathf.randomSeedRange(e.id, 0.1f)); + + Angles.randLenVectors(e.id, 6, e.finpow() * 60f, e.rotation, 11f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, 0.5f + e.fout() * 2.5f); + }); + + Draw.reset(); + }); + + shellEjectSmall = new GroundEffect(30f, 400f, e -> { + Draw.color(Pal.lightOrange, Color.LIGHT_GRAY, Pal.lightishGray, e.fin()); + float rot = Math.abs(e.rotation) + 90f; + + int i = Mathf.sign(e.rotation); + + float len = (2f + e.finpow() * 6f) * i; + float lr = rot + e.fin() * 30f * i; + Fill.rect(e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), + e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), + 1f, 2f, rot + e.fin() * 50f * i); + + Draw.color(); + }); + + shellEjectMedium = new GroundEffect(34f, 400f, e -> { + 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; + float lr = rot + e.fin() * 20f * i; + Draw.rect(Core.atlas.find("casing"), + e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), + e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), + 2f, 3f, rot); + } + + Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin()); + + for(int i : Mathf.signs){ + Angles.randLenVectors(e.id, 4, 1f + e.finpow() * 11f, e.rotation + 90f * i, 20f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 1.5f); + }); + } + + Draw.color(); + }); + + shellEjectBig = new GroundEffect(22f, 400f, e -> { + 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; + float lr = rot + Mathf.randomSeedRange(e.id + i + 6, 20f * e.fin()) * i; + Draw.rect(Core.atlas.find("casing"), + e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), + e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), + 2.5f, 4f, + rot + e.fin() * 30f * i + Mathf.randomSeedRange(e.id + i + 9, 40f * e.fin())); + } + + Draw.color(Color.LIGHT_GRAY); + + for(int i : Mathf.signs){ + Angles.randLenVectors(e.id, 4, -e.finpow() * 15f, e.rotation + 90f * i, 25f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 2f); + }); + } + + Draw.color(); + }); + + lancerLaserShoot = new Effect(21f, e -> { + Draw.color(Pal.lancerLaser); + + for(int i : Mathf.signs){ + Shapes.tri(e.x, e.y, 4f * e.fout(), 29f, e.rotation + 90f * i); + } + + Draw.reset(); + }); + + lancerLaserShootSmoke = new Effect(26f, e -> { + 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); + }); + + Draw.reset(); + }); + + lancerLaserCharge = new Effect(38f, e -> { + 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); + }); + + Draw.reset(); + }); + + lancerLaserChargeBegin = new Effect(71f, e -> { + Draw.color(Pal.lancerLaser); + Fill.circle(e.x, e.y, e.fin() * 3f); + + Draw.color(); + Fill.circle(e.x, e.y, e.fin() * 2f); + }); + + lightningCharge = new Effect(38f, e -> { + 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)); + }); + + Draw.reset(); + }); + + lightningShoot = new Effect(12f, e -> { + 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) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fin() * 5f + 2f); + }); + + Draw.reset(); + }); + + + reactorsmoke = new Effect(17, e -> { + Angles.randLenVectors(e.id, 4, e.fin() * 8f, (x, y) -> { + float size = 1f + e.fout() * 5f; + Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin()); + Draw.rect("circle", e.x + x, e.y + y, size, size); + Draw.reset(); + }); + }); + nuclearsmoke = new Effect(40, e -> { + Angles.randLenVectors(e.id, 4, e.fin() * 13f, (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(); + }); + }); + nuclearcloud = new Effect(90, 200f, e -> { + Angles.randLenVectors(e.id, 10, e.finpow() * 90f, (x, y) -> { + float size = e.fout() * 14f; + Draw.color(Color.LIME, Color.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(Pal.redSpark, Color.GRAY, e.fin()); + Draw.rect("circle", e.x + x, e.y + y, len, len); + Draw.reset(); + }); + }); + generatespark = new Effect(18, e -> { + Angles.randLenVectors(e.id, 5, e.fin() * 8f, (x, y) -> { + float len = e.fout() * 4f; + Draw.color(Pal.orangeSpark, Color.GRAY, e.fin()); + Draw.rect("circle", e.x + x, e.y + y, len, len); + Draw.reset(); + }); + }); + fuelburn = new Effect(23, e -> { + Angles.randLenVectors(e.id, 5, e.fin() * 9f, (x, y) -> { + float len = e.fout() * 4f; + Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin()); + Draw.rect("circle", e.x + x, e.y + y, len, len); + Draw.reset(); + }); + }); + plasticburn = new Effect(40, e -> { + Angles.randLenVectors(e.id, 5, 3f + e.fin() * 5f, (x, y) -> { + Draw.color(Color.valueOf("e9ead3"), Color.GRAY, e.fin()); + Fill.circle(e.x + x, e.y + y, e.fout() * 1f); + Draw.reset(); + }); + }); + pulverize = new Effect(40, e -> { + Angles.randLenVectors(e.id, 5, 3f + e.fin() * 8f, (x, y) -> { + 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(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(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(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(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, Pal.accent, e.fin()); + Fill.square(e.x + x, e.y + y, 1f + e.fout() * 3f, 45); + Draw.reset(); + }); + }); + smeltsmoke = new Effect(15, e -> { + Angles.randLenVectors(e.id, 6, 4f + e.fin() * 5f, (x, y) -> { + Draw.color(Color.WHITE, e.color, e.fin()); + Fill.square(e.x + x, e.y + y, 0.5f + e.fout() * 2f, 45); + Draw.reset(); + }); + }); + formsmoke = new Effect(40, e -> { + Angles.randLenVectors(e.id, 6, 5f + e.fin() * 8f, (x, y) -> { + 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(); + }); + }); + blastsmoke = new Effect(26, e -> { + Angles.randLenVectors(e.id, 12, 1f + e.fin() * 23f, (x, y) -> { + float size = 2f + e.fout() * 6f; + Draw.color(Color.LIGHT_GRAY, Color.DARK_GRAY, e.fin()); + Draw.rect("circle", e.x + x, e.y + y, size, size); + Draw.reset(); + }); + }); + lava = new Effect(18, e -> { + Angles.randLenVectors(e.id, 3, 1f + e.fin() * 10f, (x, y) -> { + float size = e.fslope() * 4f; + Draw.color(Color.ORANGE, Color.GRAY, e.fin()); + Draw.rect("circle", e.x + x, e.y + y, size, size); + Draw.reset(); + }); + }); + dooropen = new Effect(10, e -> { + Lines.stroke(e.fout() * 1.6f); + Lines.square(e.x, e.y, tilesize / 2f + e.fin() * 2f); + Draw.reset(); + }); + doorclose = new Effect(10, e -> { + Lines.stroke(e.fout() * 1.6f); + Lines.square(e.x, e.y, tilesize / 2f + e.fout() * 2f); + Draw.reset(); + }); + dooropenlarge = new Effect(10, e -> { + Lines.stroke(e.fout() * 1.6f); + Lines.square(e.x, e.y, tilesize + e.fin() * 2f); + Draw.reset(); + }); + doorcloselarge = new Effect(10, e -> { + Lines.stroke(e.fout() * 1.6f); + Lines.square(e.x, e.y, tilesize + e.fout() * 2f); + Draw.reset(); + }); + purify = new Effect(10, e -> { + Draw.color(Color.ROYAL, Color.GRAY, e.fin()); + Lines.stroke(2f); + Lines.spikes(e.x, e.y, e.fin() * 4f, 2, 6); + Draw.reset(); + }); + purifyoil = new Effect(10, e -> { + Draw.color(Color.BLACK, Color.GRAY, e.fin()); + Lines.stroke(2f); + Lines.spikes(e.x, e.y, e.fin() * 4f, 2, 6); + Draw.reset(); + }); + purifystone = new Effect(10, e -> { + Draw.color(Color.ORANGE, Color.GRAY, e.fin()); + Lines.stroke(2f); + Lines.spikes(e.x, e.y, e.fin() * 4f, 2, 6); + Draw.reset(); + }); + generate = new Effect(11, e -> { + Draw.color(Color.ORANGE, Color.YELLOW, e.fin()); + Lines.stroke(1f); + Lines.spikes(e.x, e.y, e.fin() * 5f, 2, 8); + Draw.reset(); + }); + mine = new Effect(20, e -> { + Angles.randLenVectors(e.id, 6, 3f + e.fin() * 6f, (x, y) -> { + Draw.color(e.color, Color.LIGHT_GRAY, e.fin()); + Fill.square(e.x + x, e.y + y, e.fout() * 2f, 45); + Draw.reset(); + }); + }); + mineBig = new Effect(30, e -> { + Angles.randLenVectors(e.id, 6, 4f + e.fin() * 8f, (x, y) -> { + Draw.color(e.color, Color.LIGHT_GRAY, e.fin()); + Fill.square(e.x + x, e.y + y, e.fout() * 2f + 0.2f, 45); + Draw.reset(); + }); + }); + mineHuge = new Effect(40, e -> { + Angles.randLenVectors(e.id, 8, 5f + e.fin() * 10f, (x, y) -> { + Draw.color(e.color, Color.LIGHT_GRAY, e.fin()); + Fill.square(e.x + x, e.y + y, e.fout() * 2f + 0.5f, 45); + Draw.reset(); + }); + }); + smelt = new Effect(20, e -> { + Angles.randLenVectors(e.id, 6, 2f + e.fin() * 5f, (x, y) -> { + Draw.color(Color.WHITE, e.color, e.fin()); + Fill.square(e.x + x, e.y + y, 0.5f + e.fout() * 2f, 45); + Draw.reset(); + }); + }); + teleportActivate = new Effect(50, e -> { + Draw.color(e.color); + + e.scaled(8f, e2 -> { + Lines.stroke(e2.fout() * 4f); + Lines.circle(e2.x, e2.y, 4f + e2.fin() * 27f); + }); + + Lines.stroke(e.fout() * 2f); + + Angles.randLenVectors(e.id, 30, 4f + 40f * e.fin(), (x, y) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fin() * 4f + 1f); + }); + + Draw.reset(); + }); + teleport = new Effect(60, e -> { + Draw.color(e.color); + Lines.stroke(e.fin() * 2f); + Lines.circle(e.x, e.y, 7f + e.fout() * 8f); + + Angles.randLenVectors(e.id, 20, 6f + 20f * e.fout(), (x, y) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fin() * 4f + 1f); + }); + + Draw.reset(); + }); + teleportOut = new Effect(20, e -> { + Draw.color(e.color); + Lines.stroke(e.fout() * 2f); + Lines.circle(e.x, e.y, 7f + e.fin() * 8f); + + Angles.randLenVectors(e.id, 20, 4f + 20f * e.fin(), (x, y) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), e.fslope() * 4f + 1f); + }); + + Draw.reset(); + }); + ripple = new GroundEffect(false, 30, e -> { + 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(); + }); + + bubble = new Effect(20, e -> { + Draw.color(Tmp.c1.set(e.color).shiftValue(0.1f)); + Lines.stroke(e.fout() + 0.2f); + Angles.randLenVectors(e.id, 2, 8f, (x, y) -> { + Lines.circle(e.x + x, e.y + y, 1f + e.fin() * 3f); + }); + Draw.reset(); + }); + + launch = new Effect(28, e -> { + Draw.color(Pal.command); + Lines.stroke(e.fout() * 2f); + Lines.poly(e.x, e.y, 40, 4f + e.finpow() * 120f); + Draw.color(); + }); + + healWaveMend = new Effect(40, e -> { + Draw.color(e.color); + Lines.stroke(e.fout() * 2f); + Lines.poly(e.x, e.y, 30, e.finpow() * e.rotation); + Draw.color(); + }); + + overdriveWave = new Effect(50, e -> { + Draw.color(e.color); + Lines.stroke(e.fout() * 1f); + Lines.poly(e.x, e.y, 30, e.finpow() * e.rotation); + Draw.color(); + }); + + healBlock = new Effect(20, e -> { + 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(); + }); + + healBlockFull = new Effect(20, e -> { + Draw.color(e.color); + Draw.alpha(e.fout()); + Fill.square(e.x, e.y, e.rotation * tilesize / 2f); + Draw.color(); + }); + + overdriveBlockFull = new Effect(60, e -> { + Draw.color(e.color); + Draw.alpha(e.fslope() * 0.4f); + Fill.square(e.x, e.y, e.rotation * tilesize); + Draw.color(); + }); + + shieldBreak = new Effect(40, e -> { + 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 8c1d7064db..b52b169584 100644 --- a/core/src/io/anuke/mindustry/content/Items.java +++ b/core/src/io/anuke/mindustry/content/Items.java @@ -1,14 +1,13 @@ package io.anuke.mindustry.content; -import com.badlogic.gdx.graphics.Color; +import io.anuke.arc.graphics.Color; import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemType; public class Items implements ContentList{ - public static Item stone, copper, lead, densealloy, coal, titanium, thorium, silicon, plastanium, phasefabric, surgealloy, - biomatter, sand, blastCompound, pyratite; + public static Item scrap, copper, lead, graphite, coal, titanium, thorium, silicon, plastanium, phasefabric, surgealloy, + biomatter, sand, blastCompound, pyratite, metaglass; @Override public void load(){ @@ -27,14 +26,19 @@ public class Items implements ContentList{ genOre = true; }}; - densealloy = new Item("dense-alloy", Color.valueOf("b2c6d2")){{ + metaglass = new Item("metaglass", Color.valueOf("ebeef5")){{ type = ItemType.material; - cost = 1.2f; + cost = 2f; + }}; + + graphite = new Item("graphite", Color.valueOf("b2c6d2")){{ + type = ItemType.material; + cost = 1.3f; }}; coal = new Item("coal", Color.valueOf("272727")){{ - explosiveness = 0.2f; - flammability = 0.5f; + explosiveness = 0.4f; + flammability = 1f; hardness = 2; genOre = true; }}; @@ -48,15 +52,15 @@ 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; }}; - stone = new Item("stone", Color.valueOf("777777")){{ - hardness = 3; + scrap = new Item("scrap", Color.valueOf("777777")){{ + genOre = true; }}; silicon = new Item("silicon", Color.valueOf("53565c")){{ @@ -66,16 +70,15 @@ 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")){{ @@ -83,27 +86,21 @@ public class Items implements ContentList{ }}; biomatter = new Item("biomatter", Color.valueOf("648b55")){{ - flammability = 0.55f; - fluxiness = 0.3f; + flammability = 1.05f; }}; sand = new Item("sand", Color.valueOf("e3d39e")){{ - fluxiness = 0.5f; + }}; 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; }}; } - - @Override - public ContentType type(){ - return ContentType.item; - } } diff --git a/core/src/io/anuke/mindustry/content/Liquids.java b/core/src/io/anuke/mindustry/content/Liquids.java index fc8bb44bfb..dadd720f47 100644 --- a/core/src/io/anuke/mindustry/content/Liquids.java +++ b/core/src/io/anuke/mindustry/content/Liquids.java @@ -1,61 +1,42 @@ package io.anuke.mindustry.content; -import com.badlogic.gdx.graphics.Color; +import io.anuke.arc.graphics.Color; import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Liquid; public class Liquids implements ContentList{ - public static Liquid water, lava, oil, cryofluid; + public static Liquid water, slag, oil, cryofluid; @Override public void load(){ - water = new Liquid("water", Color.valueOf("486acd")){ - { - heatCapacity = 0.4f; - tier = 0; - effect = StatusEffects.wet; - } + water = new Liquid("water", Color.valueOf("596ab8")){{ + heatCapacity = 0.4f; + tier = 0; + effect = StatusEffects.wet; + }}; - @Override - public boolean alwaysUnlocked() { - return true; - } - }; + slag = new Liquid("slag", Color.valueOf("ffa166")){{ + temperature = 1f; + viscosity = 0.8f; + tier = 2; + effect = StatusEffects.melting; + }}; - lava = new Liquid("lava", Color.valueOf("e37341")){ - { - temperature = 1f; - viscosity = 0.8f; - tier = 2; - effect = StatusEffects.melting; - } - }; + oil = new Liquid("oil", Color.valueOf("313131")){{ + viscosity = 0.7f; + flammability = 1.2f; + explosiveness = 1.2f; + heatCapacity = 0.7f; + tier = 1; + effect = StatusEffects.tarred; + }}; - oil = new Liquid("oil", Color.valueOf("313131")){ - { - viscosity = 0.7f; - flammability = 0.6f; - explosiveness = 0.6f; - heatCapacity = 0.7f; - tier = 1; - effect = StatusEffects.tarred; - } - }; - - cryofluid = new Liquid("cryofluid", Color.SKY){ - { - heatCapacity = 0.9f; - temperature = 0.25f; - tier = 1; - effect = StatusEffects.freezing; - } - }; - } - - @Override - public ContentType type(){ - return ContentType.liquid; + 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/Mechs.java b/core/src/io/anuke/mindustry/content/Mechs.java index 589ef08b95..5695a681bd 100644 --- a/core/src/io/anuke/mindustry/content/Mechs.java +++ b/core/src/io/anuke/mindustry/content/Mechs.java @@ -1,30 +1,22 @@ package io.anuke.mindustry.content; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.Rectangle; -import io.anuke.mindustry.content.fx.BulletFx; -import io.anuke.mindustry.content.fx.UnitFx; -import io.anuke.mindustry.entities.Player; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Blending; +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.Rectangle; +import io.anuke.arc.util.Time; +import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.effect.Lightning; -import io.anuke.mindustry.entities.units.BaseUnit; -import io.anuke.mindustry.entities.units.types.AlphaDrone; +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.maps.TutorialSector; -import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Mech; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Mathf; - -import static io.anuke.mindustry.Vars.unitGroups; +import io.anuke.mindustry.type.Weapon; public class Mechs implements ContentList{ public static Mech alpha, delta, tau, omega, dart, javelin, trident, glaive; @@ -36,8 +28,6 @@ public class Mechs implements ContentList{ public void load(){ alpha = new Mech("alpha-mech", false){ - int maxDrones = 3; - float buildTime = 20f; { drillPower = 1; @@ -45,36 +35,21 @@ 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 - public void updateAlt(Player player){ - - if(player.isShooting && getDrones(player) < maxDrones && !TutorialSector.supressDrone()){ - player.timer.get(Player.timerAbility, buildTime); - - if(player.timer.getTime(Player.timerAbility) > buildTime/2f){ - if(!Net.client()){ - AlphaDrone drone = (AlphaDrone) UnitTypes.alphaDrone.create(player.getTeam()); - drone.leader = player; - drone.set(player.x, player.y); - drone.add(); - - Effects.effect(UnitFx.unitLand, player); - } - } - } - } - - int getDrones(Player player){ - int sum = 0; - for(BaseUnit unit : unitGroups[player.getTeam().ordinal()].all()){ - if(unit instanceof AlphaDrone && ((AlphaDrone) unit).leader == player) sum ++; - } - return sum; + public boolean alwaysUnlocked(){ + return true; } }; @@ -87,20 +62,30 @@ 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 public void onLand(Player player){ if(player.timer.get(Player.timerAbility, cooldown)){ Effects.shake(1f, 1f, player); - Effects.effect(UnitFx.landShock, player); + Effects.effect(Fx.landShock, player); for(int i = 0; i < 8; i++){ - Timers.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)); } } } @@ -124,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 @@ -137,9 +130,9 @@ public class Mechs implements ContentList{ rect.setSize(healRange*2f).setCenter(player.x, player.y); Units.getNearby(player.getTeam(), rect, unit -> { - if(unit.distanceTo(player) <= healRange){ + if(unit.dst(player) <= healRange){ if(unit.health < unit.maxHealth()){ - Effects.effect(UnitFx.heal, unit); + Effects.effect(Fx.heal, unit); wasHealed = true; } unit.healBy(healAmount); @@ -147,7 +140,7 @@ public class Mechs implements ContentList{ }); if(wasHealed){ - Effects.effect(UnitFx.healWave, player); + Effects.effect(Fx.healWave, player); } } } @@ -166,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 @@ -184,13 +188,13 @@ public class Mechs implements ContentList{ @Override public void load(){ super.load(); - armorRegion = Draw.region(name + "-armor"); + armorRegion = Core.atlas.find(name + "-armor"); } @Override public void updateAlt(Player player){ float scl = 1f - player.shootHeat/2f; - player.getVelocity().scl(scl); + player.velocity().scl(scl); } @Override @@ -202,31 +206,44 @@ public class Mechs implements ContentList{ public void draw(Player player){ if(player.shootHeat <= 0.01f) return; - float alpha = Core.batch.getColor().a; + float alpha = Draw.getColor().a; Shaders.build.progress = player.shootHeat; Shaders.build.region = armorRegion; - Shaders.build.time = Timers.time() / 10f; - Shaders.build.color.set(Palette.accent).a = player.shootHeat; - Graphics.shader(Shaders.build); + Shaders.build.time = Time.time() / 10f; + Shaders.build.color.set(Pal.accent).a = player.shootHeat; + Draw.shader(Shaders.build); Draw.alpha(1f); - Draw.rect(armorRegion, player.snappedX(), player.snappedY(), player.rotation); - Graphics.shader(Shaders.mix); + Draw.rect(armorRegion, player.x, player.y, player.rotation); + Draw.shader(Shaders.mix); Draw.color(1f, 1f, 1f, alpha); } }; - dart = new Mech("dart-ship", true){{ - drillPower = 1; - mineSpeed = 0.9f; - speed = 0.4f; - drag = 0.1f; - armor = 10f; - weapon = Weapons.blasterSmall; - weaponOffsetX = -1; - weaponOffsetY = -1; - trailColor = Palette.lightTrail; - cellTrnsY = 1f; - }}; + dart = new Mech("dart-ship", true){ + { + drillPower = 1; + mineSpeed = 0.9f; + speed = 0.4f; + drag = 0.1f; + health = 180f; + weaponOffsetX = -1; + weaponOffsetY = -1; + engineColor = Pal.lightTrail; + cellTrnsY = 1f; + weapon = new Weapon("blaster"){{ + length = 1.5f; + reload = 20f; + roundrobin = true; + ejectEffect = Fx.shellEjectSmall; + bullet = Bullets.standardCopper; + }}; + } + + @Override + public boolean alwaysUnlocked(){ + return true; + } + }; javelin = new Mech("javelin-ship", true){ float minV = 3.6f; @@ -237,16 +254,26 @@ 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 public void load(){ super.load(); - shield = Draw.region(name + "-shield"); + shield = Core.atlas.find(name + "-shield"); } @Override @@ -257,10 +284,10 @@ public class Mechs implements ContentList{ @Override public void updateAlt(Player player){ float scl = scld(player); - if(Mathf.chance(Timers.delta() * (0.15*scl))){ - Effects.effect(BulletFx.hitLancer, Palette.lancerLaser, player.x, player.y); - Lightning.create(player.getTeam(), Palette.lancerLaser, 10f, - player.x + player.getVelocity().x, player.y + player.getVelocity().y, player.rotation, 14); + if(Mathf.chance(Time.delta() * (0.15*scl))){ + 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); } } @@ -268,20 +295,20 @@ public class Mechs implements ContentList{ public void draw(Player player){ float scl = scld(player); if(scl < 0.01f) return; - float alpha = Core.batch.getColor().a; - Graphics.shader(); - Graphics.setAdditiveBlending(); - Draw.color(Palette.lancerLaser); + float alpha = Draw.getColor().a; + Draw.shader(); + Draw.color(Pal.lancerLaser); Draw.alpha(scl/2f); - Draw.rect(shield, player.snappedX() + Mathf.range(scl/2f), player.snappedY() + Mathf.range(scl/2f), player.rotation - 90); - Graphics.setNormalBlending(); - Graphics.shader(Shaders.mix); + 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){ - return Mathf.clamp((player.getVelocity().len() - minV) / (maxV - minV)); + return Mathf.clamp((player.velocity().len() - minV) / (maxV - minV)); } }; @@ -292,40 +319,53 @@ 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 public boolean canShoot(Player player){ - return player.getVelocity().len() > 1.2f; + return player.velocity().len() > 1.2f; } }; 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; + }}; } }; starterDesktop = alpha; starterMobile = dart; } - - @Override - public ContentType type(){ - return ContentType.mech; - } } diff --git a/core/src/io/anuke/mindustry/content/Recipes.java b/core/src/io/anuke/mindustry/content/Recipes.java deleted file mode 100644 index 9a01f786ab..0000000000 --- a/core/src/io/anuke/mindustry/content/Recipes.java +++ /dev/null @@ -1,200 +0,0 @@ -package io.anuke.mindustry.content; - -import io.anuke.mindustry.content.blocks.*; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.game.GameMode; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Recipe; -import io.anuke.mindustry.type.Recipe.RecipeVisibility; - -import static io.anuke.mindustry.type.Category.*; - -public class Recipes implements ContentList{ - - @Override - public void load(){ - //DEBUG - new Recipe(distribution, DebugBlocks.itemSource).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true); - new Recipe(distribution, DebugBlocks.itemVoid).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true); - new Recipe(liquid, DebugBlocks.liquidSource).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true); - new Recipe(power, DebugBlocks.powerVoid).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true); - new Recipe(power, DebugBlocks.powerInfinite).setMode(GameMode.sandbox).setHidden(true).setAlwaysUnlocked(true); - - //DEFENSE - - //walls - new Recipe(defense, DefenseBlocks.copperWall, new ItemStack(Items.copper, 12)).setAlwaysUnlocked(true); - new Recipe(defense, DefenseBlocks.copperWallLarge, new ItemStack(Items.copper, 12 * 4)).setAlwaysUnlocked(true); - - new Recipe(defense, DefenseBlocks.denseAlloyWall, new ItemStack(Items.densealloy, 12)); - new Recipe(defense, DefenseBlocks.denseAlloyWallLarge, new ItemStack(Items.densealloy, 12 * 4)); - - new Recipe(defense, DefenseBlocks.door, new ItemStack(Items.densealloy, 12), new ItemStack(Items.silicon, 8)); - new Recipe(defense, DefenseBlocks.doorLarge, new ItemStack(Items.densealloy, 12 * 4), new ItemStack(Items.silicon, 8 * 4)); - - new Recipe(defense, DefenseBlocks.thoriumWall, new ItemStack(Items.thorium, 12)); - new Recipe(defense, DefenseBlocks.thoriumWallLarge, new ItemStack(Items.thorium, 12 * 4)); - - new Recipe(defense, DefenseBlocks.phaseWall, new ItemStack(Items.phasefabric, 12)); - new Recipe(defense, DefenseBlocks.phaseWallLarge, new ItemStack(Items.phasefabric, 12 * 4)); - - new Recipe(defense, DefenseBlocks.surgeWall, new ItemStack(Items.surgealloy, 12)); - new Recipe(defense, DefenseBlocks.surgeWallLarge, new ItemStack(Items.surgealloy, 12 * 4)); - - new Recipe(effect, StorageBlocks.container, new ItemStack(Items.densealloy, 200)); - new Recipe(effect, StorageBlocks.vault, new ItemStack(Items.densealloy, 500), new ItemStack(Items.thorium, 250)); - - new Recipe(effect, StorageBlocks.core, - new ItemStack(Items.copper, 2000), new ItemStack(Items.densealloy, 2000), - new ItemStack(Items.silicon, 1750), new ItemStack(Items.thorium, 1000), - new ItemStack(Items.surgealloy, 500), new ItemStack(Items.phasefabric, 750) - ); - - //projectors - new Recipe(effect, DefenseBlocks.mendProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 50), new ItemStack(Items.silicon, 180)); - new Recipe(effect, DefenseBlocks.overdriveProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 150), new ItemStack(Items.silicon, 250)); - new Recipe(effect, DefenseBlocks.forceProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 150), new ItemStack(Items.silicon, 250)); - - new Recipe(effect, DefenseBlocks.shockMine, new ItemStack(Items.lead, 50), new ItemStack(Items.silicon, 25)) - .setDependencies(Items.blastCompound); - - //TURRETS - new Recipe(turret, TurretBlocks.duo, new ItemStack(Items.copper, 40)).setAlwaysUnlocked(true); - new Recipe(turret, TurretBlocks.arc, new ItemStack(Items.copper, 50), new ItemStack(Items.lead, 30), new ItemStack(Items.silicon, 20)); - new Recipe(turret, TurretBlocks.hail, new ItemStack(Items.copper, 60), new ItemStack(Items.densealloy, 35)); - new Recipe(turret, TurretBlocks.lancer, new ItemStack(Items.copper, 50), new ItemStack(Items.lead, 100), new ItemStack(Items.silicon, 90)); - new Recipe(turret, TurretBlocks.wave, new ItemStack(Items.densealloy, 60), new ItemStack(Items.titanium, 70), new ItemStack(Items.lead, 150)); - new Recipe(turret, TurretBlocks.salvo, new ItemStack(Items.copper, 210), new ItemStack(Items.densealloy, 190), new ItemStack(Items.thorium, 130)); - new Recipe(turret, TurretBlocks.swarmer, new ItemStack(Items.densealloy, 70), new ItemStack(Items.titanium, 70), new ItemStack(Items.plastanium, 90), new ItemStack(Items.silicon, 60)); - new Recipe(turret, TurretBlocks.ripple, new ItemStack(Items.copper, 300), new ItemStack(Items.densealloy, 220), new ItemStack(Items.thorium, 120)); - new Recipe(turret, TurretBlocks.cyclone, new ItemStack(Items.copper, 400), new ItemStack(Items.densealloy, 400), new ItemStack(Items.surgealloy, 200), new ItemStack(Items.plastanium, 150)); - new Recipe(turret, TurretBlocks.fuse, new ItemStack(Items.copper, 450), new ItemStack(Items.densealloy, 450), new ItemStack(Items.surgealloy, 250)); - new Recipe(turret, TurretBlocks.spectre, new ItemStack(Items.copper, 700), new ItemStack(Items.densealloy, 600), new ItemStack(Items.surgealloy, 500), new ItemStack(Items.plastanium, 350), new ItemStack(Items.thorium, 500)); - new Recipe(turret, TurretBlocks.meltdown, new ItemStack(Items.copper, 500), new ItemStack(Items.lead, 700), new ItemStack(Items.densealloy, 600), new ItemStack(Items.surgealloy, 650), new ItemStack(Items.silicon, 650)); - - //DISTRIBUTION - new Recipe(distribution, DistributionBlocks.conveyor, new ItemStack(Items.copper, 1)).setAlwaysUnlocked(true); - new Recipe(distribution, DistributionBlocks.titaniumconveyor, new ItemStack(Items.copper, 2), new ItemStack(Items.titanium, 1)); - new Recipe(distribution, DistributionBlocks.phaseConveyor, new ItemStack(Items.phasefabric, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.densealloy, 20)); - - //starter transport - new Recipe(distribution, DistributionBlocks.junction, new ItemStack(Items.copper, 2)).setAlwaysUnlocked(true); - new Recipe(distribution, DistributionBlocks.router, new ItemStack(Items.copper, 6)).setAlwaysUnlocked(true); - - //advanced densealloy transporat - new Recipe(distribution, DistributionBlocks.distributor, new ItemStack(Items.densealloy, 8), new ItemStack(Items.copper, 8)); - new Recipe(distribution, DistributionBlocks.sorter, new ItemStack(Items.densealloy, 4), new ItemStack(Items.copper, 4)); - new Recipe(distribution, DistributionBlocks.overflowGate, new ItemStack(Items.densealloy, 4), new ItemStack(Items.copper, 8)); - new Recipe(distribution, DistributionBlocks.itemBridge, new ItemStack(Items.densealloy, 8), new ItemStack(Items.copper, 8)); - new Recipe(distribution, StorageBlocks.unloader, new ItemStack(Items.densealloy, 50), new ItemStack(Items.silicon, 60)); - new Recipe(distribution, DistributionBlocks.massDriver, new ItemStack(Items.densealloy, 250), new ItemStack(Items.silicon, 150), new ItemStack(Items.lead, 250), new ItemStack(Items.thorium, 100)); - - //CRAFTING - - //smelting - new Recipe(crafting, CraftingBlocks.smelter, new ItemStack(Items.copper, 100)); - new Recipe(crafting, CraftingBlocks.arcsmelter, new ItemStack(Items.copper, 110), new ItemStack(Items.densealloy, 70), new ItemStack(Items.lead, 50)); - new Recipe(crafting, CraftingBlocks.siliconsmelter, new ItemStack(Items.copper, 60), new ItemStack(Items.lead, 50)); - - //advanced fabrication - new Recipe(crafting, CraftingBlocks.plastaniumCompressor, new ItemStack(Items.silicon, 160), new ItemStack(Items.lead, 230), new ItemStack(Items.densealloy, 120), new ItemStack(Items.titanium, 160)); - new Recipe(crafting, CraftingBlocks.phaseWeaver, new ItemStack(Items.silicon, 260), new ItemStack(Items.lead, 240), new ItemStack(Items.thorium, 150)); - new Recipe(crafting, CraftingBlocks.alloySmelter, new ItemStack(Items.silicon, 160), new ItemStack(Items.lead, 160), new ItemStack(Items.thorium, 140)); - - //misc - new Recipe(crafting, CraftingBlocks.pulverizer, new ItemStack(Items.copper, 60), new ItemStack(Items.lead, 50)); - new Recipe(crafting, CraftingBlocks.pyratiteMixer, new ItemStack(Items.copper, 100), new ItemStack(Items.lead, 50)); - new Recipe(crafting, CraftingBlocks.blastMixer, new ItemStack(Items.lead, 60), new ItemStack(Items.densealloy, 40)); - new Recipe(crafting, CraftingBlocks.cryofluidmixer, new ItemStack(Items.lead, 130), new ItemStack(Items.silicon, 80), new ItemStack(Items.thorium, 90)); - - new Recipe(crafting, CraftingBlocks.solidifier, new ItemStack(Items.densealloy, 30), new ItemStack(Items.copper, 20)); - new Recipe(crafting, CraftingBlocks.melter, new ItemStack(Items.copper, 60), new ItemStack(Items.lead, 70), new ItemStack(Items.densealloy, 90)); - new Recipe(crafting, CraftingBlocks.incinerator, new ItemStack(Items.densealloy, 10), new ItemStack(Items.lead, 30)); - - //processing - new Recipe(crafting, CraftingBlocks.biomatterCompressor, new ItemStack(Items.lead, 70), new ItemStack(Items.silicon, 60)); - new Recipe(crafting, CraftingBlocks.separator, new ItemStack(Items.copper, 60), new ItemStack(Items.densealloy, 50)); - new Recipe(crafting, CraftingBlocks.centrifuge, new ItemStack(Items.copper, 130), new ItemStack(Items.densealloy, 130), new ItemStack(Items.silicon, 60), new ItemStack(Items.titanium, 50)); - - //POWER - new Recipe(power, PowerBlocks.powerNode, new ItemStack(Items.copper, 2), new ItemStack(Items.lead, 6)) - .setDependencies(PowerBlocks.combustionGenerator); - new Recipe(power, PowerBlocks.powerNodeLarge, new ItemStack(Items.densealloy, 10), new ItemStack(Items.lead, 20), new ItemStack(Items.silicon, 6)) - .setDependencies(PowerBlocks.powerNode); - new Recipe(power, PowerBlocks.battery, new ItemStack(Items.copper, 8), new ItemStack(Items.lead, 30), new ItemStack(Items.silicon, 4)) - .setDependencies(PowerBlocks.powerNode); - new Recipe(power, PowerBlocks.batteryLarge, new ItemStack(Items.densealloy, 40), new ItemStack(Items.lead, 80), new ItemStack(Items.silicon, 30)) - .setDependencies(PowerBlocks.powerNode); - - //generators - combustion - new Recipe(power, PowerBlocks.combustionGenerator, new ItemStack(Items.copper, 50), new ItemStack(Items.lead, 30)); - new Recipe(power, PowerBlocks.turbineGenerator, new ItemStack(Items.copper, 70), new ItemStack(Items.densealloy, 50), new ItemStack(Items.lead, 80), new ItemStack(Items.silicon, 60)); - new Recipe(power, PowerBlocks.thermalGenerator, new ItemStack(Items.copper, 80), new ItemStack(Items.densealloy, 70), new ItemStack(Items.lead, 100), new ItemStack(Items.silicon, 70), new ItemStack(Items.thorium, 70)); - - //generators - solar - new Recipe(power, PowerBlocks.solarPanel, new ItemStack(Items.lead, 20), new ItemStack(Items.silicon, 30)); - new Recipe(power, PowerBlocks.largeSolarPanel, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 290), new ItemStack(Items.phasefabric, 30)); - - //generators - nuclear - new Recipe(power, PowerBlocks.thoriumReactor, new ItemStack(Items.lead, 600), new ItemStack(Items.silicon, 400), new ItemStack(Items.densealloy, 300), new ItemStack(Items.thorium, 300)); - new Recipe(power, PowerBlocks.rtgGenerator, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 150), new ItemStack(Items.phasefabric, 50), new ItemStack(Items.plastanium, 150), new ItemStack(Items.thorium, 100)); - - //DRILLS, PRODUCERS - new Recipe(production, ProductionBlocks.mechanicalDrill, new ItemStack(Items.copper, 45)).setAlwaysUnlocked(true); - new Recipe(production, ProductionBlocks.pneumaticDrill, new ItemStack(Items.copper, 60), new ItemStack(Items.densealloy, 50)); - new Recipe(production, ProductionBlocks.laserDrill, new ItemStack(Items.copper, 70), new ItemStack(Items.densealloy, 90), new ItemStack(Items.silicon, 60), new ItemStack(Items.titanium, 50)); - new Recipe(production, ProductionBlocks.blastDrill, new ItemStack(Items.copper, 130), new ItemStack(Items.densealloy, 180), new ItemStack(Items.silicon, 120), new ItemStack(Items.titanium, 100), new ItemStack(Items.thorium, 60)); - - new Recipe(production, ProductionBlocks.waterExtractor, new ItemStack(Items.copper, 50), new ItemStack(Items.densealloy, 50), new ItemStack(Items.lead, 40)); - new Recipe(production, ProductionBlocks.cultivator, new ItemStack(Items.copper, 20), new ItemStack(Items.lead, 50), new ItemStack(Items.silicon, 20)); - new Recipe(production, ProductionBlocks.oilExtractor, new ItemStack(Items.copper, 300), new ItemStack(Items.densealloy, 350), new ItemStack(Items.lead, 230), new ItemStack(Items.thorium, 230), new ItemStack(Items.silicon, 150)); - - //UNITS - - //upgrades - new Recipe(upgrade, UpgradeBlocks.dartPad, new ItemStack(Items.lead, 150), new ItemStack(Items.copper, 150), new ItemStack(Items.silicon, 200), new ItemStack(Items.titanium, 240)).setVisible(RecipeVisibility.desktopOnly); - new Recipe(upgrade, UpgradeBlocks.tridentPad, new ItemStack(Items.lead, 250), new ItemStack(Items.copper, 250), new ItemStack(Items.silicon, 250), new ItemStack(Items.titanium, 300), new ItemStack(Items.plastanium, 200)); - new Recipe(upgrade, UpgradeBlocks.javelinPad, new ItemStack(Items.lead, 350), new ItemStack(Items.silicon, 450), new ItemStack(Items.titanium, 500), new ItemStack(Items.plastanium, 400), new ItemStack(Items.phasefabric, 200)); - new Recipe(upgrade, UpgradeBlocks.glaivePad, new ItemStack(Items.lead, 450), new ItemStack(Items.silicon, 650), new ItemStack(Items.titanium, 700), new ItemStack(Items.plastanium, 600), new ItemStack(Items.surgealloy, 200)); - - new Recipe(upgrade, UpgradeBlocks.alphaPad, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 100), new ItemStack(Items.copper, 150)).setVisible(RecipeVisibility.mobileOnly); - new Recipe(upgrade, UpgradeBlocks.tauPad, new ItemStack(Items.lead, 250), new ItemStack(Items.densealloy, 250), new ItemStack(Items.copper, 250), new ItemStack(Items.silicon, 250)); - new Recipe(upgrade, UpgradeBlocks.deltaPad, new ItemStack(Items.lead, 350), new ItemStack(Items.densealloy, 350), new ItemStack(Items.copper, 400), new ItemStack(Items.silicon, 450), new ItemStack(Items.thorium, 300)); - new Recipe(upgrade, UpgradeBlocks.omegaPad, new ItemStack(Items.lead, 450), new ItemStack(Items.densealloy, 550), new ItemStack(Items.silicon, 650), new ItemStack(Items.thorium, 600), new ItemStack(Items.surgealloy, 240)); - - //actual unit related stuff - new Recipe(units, UnitBlocks.spiritFactory, new ItemStack(Items.copper, 70), new ItemStack(Items.lead, 110), new ItemStack(Items.silicon, 130)); - new Recipe(units, UnitBlocks.phantomFactory, new ItemStack(Items.densealloy, 90), new ItemStack(Items.thorium, 80), new ItemStack(Items.lead, 110), new ItemStack(Items.silicon, 210)); - - new Recipe(units, UnitBlocks.daggerFactory, new ItemStack(Items.lead, 90), new ItemStack(Items.silicon, 70)); - new Recipe(units, UnitBlocks.titanFactory, new ItemStack(Items.thorium, 90), new ItemStack(Items.lead, 140), new ItemStack(Items.silicon, 90)); - new Recipe(units, UnitBlocks.fortressFactory, new ItemStack(Items.thorium, 200), new ItemStack(Items.lead, 220), new ItemStack(Items.silicon, 150), new ItemStack(Items.surgealloy, 100), new ItemStack(Items.phasefabric, 50)); - - new Recipe(units, UnitBlocks.wraithFactory, new ItemStack(Items.titanium, 60), new ItemStack(Items.lead, 80), new ItemStack(Items.silicon, 90)); - new Recipe(units, UnitBlocks.ghoulFactory, new ItemStack(Items.plastanium, 80), new ItemStack(Items.titanium, 100), new ItemStack(Items.lead, 130), new ItemStack(Items.silicon, 220)); - new Recipe(units, UnitBlocks.revenantFactory, new ItemStack(Items.plastanium, 300), new ItemStack(Items.titanium, 400), new ItemStack(Items.lead, 300), new ItemStack(Items.silicon, 400), new ItemStack(Items.surgealloy, 100)); - - new Recipe(units, UnitBlocks.repairPoint, new ItemStack(Items.lead, 30), new ItemStack(Items.copper, 30), new ItemStack(Items.silicon, 30)); - new Recipe(units, UnitBlocks.commandCenter, new ItemStack(Items.lead, 100), new ItemStack(Items.densealloy, 100), new ItemStack(Items.silicon, 200)); - - //LIQUIDS - new Recipe(liquid, LiquidBlocks.conduit, new ItemStack(Items.lead, 1)).setDependencies(CraftingBlocks.smelter); - new Recipe(liquid, LiquidBlocks.pulseConduit, new ItemStack(Items.titanium, 1), new ItemStack(Items.lead, 1)); - new Recipe(liquid, LiquidBlocks.phaseConduit, new ItemStack(Items.phasefabric, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.titanium, 20)); - - new Recipe(liquid, LiquidBlocks.liquidRouter, new ItemStack(Items.titanium, 4), new ItemStack(Items.lead, 4)); - new Recipe(liquid, LiquidBlocks.liquidtank, new ItemStack(Items.titanium, 50), new ItemStack(Items.lead, 50)); - new Recipe(liquid, LiquidBlocks.liquidJunction, new ItemStack(Items.titanium, 4), new ItemStack(Items.lead, 4)); - new Recipe(liquid, LiquidBlocks.bridgeConduit, new ItemStack(Items.titanium, 8), new ItemStack(Items.lead, 8)); - - new Recipe(liquid, LiquidBlocks.mechanicalPump, new ItemStack(Items.copper, 30), new ItemStack(Items.lead, 20)).setDependencies(CraftingBlocks.smelter); - new Recipe(liquid, LiquidBlocks.rotaryPump, new ItemStack(Items.copper, 140), new ItemStack(Items.lead, 100), new ItemStack(Items.silicon, 40), new ItemStack(Items.titanium, 70)); - new Recipe(liquid, LiquidBlocks.thermalPump, new ItemStack(Items.copper, 160), new ItemStack(Items.lead, 130), new ItemStack(Items.silicon, 60), new ItemStack(Items.titanium, 80), new ItemStack(Items.thorium, 70)); - } - - @Override - public ContentType type(){ - return ContentType.recipe; - } -} diff --git a/core/src/io/anuke/mindustry/content/StatusEffects.java b/core/src/io/anuke/mindustry/content/StatusEffects.java index 62e1de504f..328a617c1f 100644 --- a/core/src/io/anuke/mindustry/content/StatusEffects.java +++ b/core/src/io/anuke/mindustry/content/StatusEffects.java @@ -1,177 +1,81 @@ package io.anuke.mindustry.content; -import io.anuke.mindustry.content.fx.EnvironmentFx; -import io.anuke.mindustry.entities.StatusController.StatusEntry; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.Effects; +import io.anuke.arc.math.Mathf; import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.StatusEffect; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.util.Mathf; public class StatusEffects implements ContentList{ - public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded, shocked; + public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded, shocked, corroded; @Override public void load(){ - none = new StatusEffect(0); + none = new StatusEffect(); - burning = new StatusEffect(4 * 60f){ - { - oppositeScale = 0.5f; - } + burning = new StatusEffect(){{ + damage = 0.04f; + effect = Fx.burning; - @Override - public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result){ - if(to == tarred){ - unit.damage(1f); - Effects.effect(EnvironmentFx.burning, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f)); - return result.set(this, Math.min(time + newTime, baseDuration + tarred.baseDuration)); - } + opposite(() -> wet, () -> freezing); + trans(() -> tarred, ((unit, time, newTime, result) -> { + unit.damage(1f); + Effects.effect(Fx.burning, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f)); + result.set(this, Math.min(time + newTime, 300f)); + })); + }}; - return super.getTransition(unit, to, time, newTime, result); - } + freezing = new StatusEffect(){{ + speedMultiplier = 0.6f; + armorMultiplier = 0.8f; + effect = Fx.freezing; - @Override - public void update(Unit unit, float time){ - unit.damagePeriodic(0.04f); + opposite(() -> melting, () -> burning); + }}; - if(Mathf.chance(Timers.delta() * 0.2f)){ - Effects.effect(EnvironmentFx.burning, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f)); - } - } - }; + wet = new StatusEffect(){{ + speedMultiplier = 0.9f; + effect = Fx.wet; - freezing = new StatusEffect(5 * 60f){ - { - oppositeScale = 0.4f; - speedMultiplier = 0.6f; - armorMultiplier = 0.8f; - } + trans(() -> shocked, ((unit, time, newTime, result) -> unit.damage(15f))); + opposite(() -> burning, () -> shocked); + }}; - @Override - public void update(Unit unit, float time){ + melting = new StatusEffect(){{ + speedMultiplier = 0.8f; + armorMultiplier = 0.8f; + damage = 0.3f; + effect = Fx.melting; - if(Mathf.chance(Timers.delta() * 0.15f)){ - Effects.effect(EnvironmentFx.freezing, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f)); - } - } - }; + trans(() -> tarred, ((unit, time, newTime, result) -> result.set(this, Math.min(time + newTime / 2f, 140f)))); + opposite(() -> wet, () -> freezing); + }}; - wet = new StatusEffect(3 * 60f){ - { - oppositeScale = 0.5f; - speedMultiplier = 0.9f; - } + tarred = new StatusEffect(){{ + speedMultiplier = 0.6f; + effect = Fx.oily; - @Override - public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result){ - if(to == shocked){ - //get shocked when wet - unit.damage(15f); - return result.set(this, time); - } + trans(() -> melting, ((unit, time, newTime, result) -> result.set(burning, newTime + time))); + trans(() -> burning, ((unit, time, newTime, result) -> result.set(burning, newTime + time))); + }}; - return super.getTransition(unit, to, time, newTime, result); - } + overdrive = new StatusEffect(){{ + armorMultiplier = 0.95f; + speedMultiplier = 1.15f; + damageMultiplier = 1.4f; + damage = -0.01f; + effect = Fx.overdriven; + }}; - @Override - public void update(Unit unit, float time){ - if(Mathf.chance(Timers.delta() * 0.15f)){ - Effects.effect(EnvironmentFx.wet, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f)); - } - } - }; + shielded = new StatusEffect(){{ + armorMultiplier = 3f; + }}; - melting = new StatusEffect(5 * 60f){ - { - oppositeScale = 0.2f; - speedMultiplier = 0.8f; - armorMultiplier = 0.8f; - } + shocked = new StatusEffect(); - @Override - public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result){ - if(to == tarred){ - return result.set(this, Math.min(time + newTime / 2f, baseDuration)); - } - - return super.getTransition(unit, to, time, newTime, result); - } - - @Override - public void update(Unit unit, float time){ - unit.damagePeriodic(0.3f); - - if(Mathf.chance(Timers.delta() * 0.2f)){ - Effects.effect(EnvironmentFx.melting, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f)); - } - } - }; - - tarred = new StatusEffect(4 * 60f){ - { - speedMultiplier = 0.6f; - } - - @Override - public void update(Unit unit, float time){ - if(Mathf.chance(Timers.delta() * 0.15f)){ - Effects.effect(EnvironmentFx.oily, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f)); - } - } - - @Override - public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result){ - if(to == melting || to == burning){ - return result.set(to, newTime + time); - } - - return result.set(to, newTime); - } - }; - - overdrive = new StatusEffect(60f*15){ - { - armorMultiplier = 0.95f; - speedMultiplier = 1.15f; - damageMultiplier = 1.4f; - } - - @Override - public void update(Unit unit, float time){ - //idle regen boosted - unit.health += 0.01f * Timers.delta(); - - if(Mathf.chance(Timers.delta() * 0.25f)){ - Effects.effect(EnvironmentFx.overdriven, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f), 0f, unit); - } - } - }; - - shielded = new StatusEffect(6f){ - { - armorMultiplier = 3f; - } - }; - - shocked = new StatusEffect(1f){ - { - armorMultiplier = 3f; - } - }; - - wet.setOpposites(shocked); - melting.setOpposites(wet, freezing); - wet.setOpposites(burning); - freezing.setOpposites(burning, melting); - burning.setOpposites(wet, freezing); - } - - @Override - public ContentType type(){ - return ContentType.status; + //no effects, just small amounts of damage. + corroded = new StatusEffect(){{ + damage = 0.1f; + }}; } } diff --git a/core/src/io/anuke/mindustry/content/TechTree.java b/core/src/io/anuke/mindustry/content/TechTree.java new file mode 100644 index 0000000000..a656674c91 --- /dev/null +++ b/core/src/io/anuke/mindustry/content/TechTree.java @@ -0,0 +1,298 @@ +package io.anuke.mindustry.content; + +import io.anuke.arc.collection.Array; +import io.anuke.mindustry.game.ContentList; +import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.world.Block; + +import static io.anuke.mindustry.content.Blocks.*; + +public class TechTree implements ContentList{ + public static TechNode root; + + @Override + public void load(){ + root = node(coreShard, () -> { + + node(conveyor, () -> { + node(launchPad, () -> { + + }); + + node(junction, () -> { + node(itemBridge); + node(router, () -> { + node(distributor); + node(overflowGate); + node(sorter); + node(container, () -> { + node(unloader); + node(vault, () -> { + + }); + }); + + node(titaniumConveyor, () -> { + node(phaseConveyor, () -> { + node(massDriver, () -> { + + }); + }); + }); + }); + }); + }); + + node(duo, () -> { + node(hail, () -> { + + node(salvo, () -> { + node(swarmer, () -> { + node(cyclone, () -> { + node(spectre, () -> { + + }); + }); + }); + + node(ripple, () -> { + node(fuse, () -> { + + }); + }); + }); + }); + + node(arc, () -> { + node(wave, () -> { + + }); + + node(lancer, () -> { + node(meltdown, () -> { + + }); + + node(shockMine, () -> { + + }); + }); + }); + + node(copperWall, () -> { + node(copperWallLarge); + node(titaniumWall, () -> { + node(door, () -> { + node(doorLarge); + }); + node(titaniumWallLarge); + node(thoriumWall, () -> { + node(thoriumWallLarge); + node(surgeWall, () -> { + node(surgeWallLarge); + node(phaseWall, () -> { + node(phaseWallLarge); + }); + }); + }); + }); + }); + }); + + node(mechanicalDrill, () -> { + node(pneumaticDrill, () -> { + node(cultivator, () -> { + + }); + + node(laserDrill, () -> { + node(blastDrill, () -> { + + }); + + node(waterExtractor, () -> { + node(oilExtractor, () -> { + + }); + }); + }); + }); + + node(graphitePress, () -> { + node(pyratiteMixer, () -> { + node(blastMixer, () -> { + + }); + }); + + node(siliconSmelter, () -> { + + node(biomatterCompressor, () -> { + node(multiPress, () -> { + + }); + + node(plastaniumCompressor, () -> { + node(phaseWeaver, () -> { + + }); + }); + }); + + node(kiln, () -> { + node(incinerator, () -> { + node(melter, () -> { + node(surgeSmelter, () -> { + + }); + + node(separator, () -> { + node(pulverizer, () -> { + + }); + }); + + node(cryofluidMixer, () -> { + + }); + }); + }); + }); + }); + }); + + + + node(mechanicalPump, () -> { + node(conduit, () -> { + node(liquidJunction, () -> { + node(liquidRouter, () -> { + node(liquidTank); + + node(pulseConduit, () -> { + node(phaseConduit, () -> { + + }); + }); + + node(rotaryPump, () -> { + node(thermalPump, () -> { + + }); + }); + }); + node(bridgeConduit); + }); + }); + }); + }); + + node(powerNode, () -> { + node(combustionGenerator, () -> { + node(powerNodeLarge, () -> { + node(battery, () -> { + node(batteryLarge, () -> { + node(surgeTower, () -> { + + }); + }); + }); + + 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(javelinPad); + node(tauPad, () -> { + node(tridentPad); + node(omegaPad, () -> { + node(glaivePad); + }); + }); + }); + + node(spiritFactory, () -> { + node(daggerFactory, () -> { + node(titanFactory, () -> { + node(fortressFactory); + }); + node(wraithFactory, () -> { + node(phantomFactory); + node(ghoulFactory, () -> { + node(revenantFactory); + }); + }); + }); + }); + }); + }); + }); + } + + 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 * 40); + } + + return new TechNode(block, requirements, children); + } + + private TechNode node(Block block){ + return node(block, () -> {}); + } + + public static class TechNode{ + static TechNode context; + + public final Block block; + public final ItemStack[] requirements; + public final Array children = new Array<>(); + + TechNode(Block block, ItemStack[] requirements, Runnable children){ + if(context != null){ + context.children.add(this); + } + + this.block = block; + this.requirements = requirements; + + TechNode last = context; + context = this; + children.run(); + context = last; + } + } +} diff --git a/core/src/io/anuke/mindustry/content/UnitTypes.java b/core/src/io/anuke/mindustry/content/UnitTypes.java index 8029f0ac00..f841cdb343 100644 --- a/core/src/io/anuke/mindustry/content/UnitTypes.java +++ b/core/src/io/anuke/mindustry/content/UnitTypes.java @@ -1,49 +1,37 @@ package io.anuke.mindustry.content; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.utils.ObjectSet; -import io.anuke.mindustry.entities.units.UnitType; -import io.anuke.mindustry.entities.units.types.*; +import io.anuke.arc.collection.ObjectSet; +import io.anuke.mindustry.entities.type.base.*; import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.type.UnitType; +import io.anuke.mindustry.type.Weapon; public class UnitTypes implements ContentList{ public static UnitType spirit, phantom, - alphaDrone, - wraith, ghoul, revenant, - dagger, titan, fortress; + wraith, ghoul, revenant, lich, reaper, + dagger, crawler, titan, fortress, eruptor, chaosArray, eradicator; @Override public void load(){ - alphaDrone = new UnitType("alpha-drone", AlphaDrone.class, AlphaDrone::new){ - { - isFlying = true; - drag = 0.005f; - speed = 0.6f; - maxVelocity = 1.7f; - range = 40f; - health = 45; - hitsize = 4f; - mass = 0.1f; - weapon = Weapons.droneBlaster; - trailColor = Color.valueOf("ffd37f"); - } - - @Override - public boolean isHidden() { - return true; - } - }; - 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){{ @@ -52,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.1f; + speed = 0.22f; + 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){{ @@ -63,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 = 20000; + 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 = 80000; + 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){{ @@ -85,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){{ @@ -98,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; @@ -125,12 +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 = 4000; + 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 = 15000; + 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 = 20; + 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 = 30000; + 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; + }}; }}; } - - @Override - public ContentType type(){ - return ContentType.unit; - } } 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 480c8988bf..0000000000 --- a/core/src/io/anuke/mindustry/content/Weapons.java +++ /dev/null @@ -1,198 +0,0 @@ -package io.anuke.mindustry.content; - -import io.anuke.mindustry.content.fx.Fx; -import io.anuke.mindustry.content.fx.ShootFx; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.Weapon; - -public class Weapons implements ContentList{ - public static Weapon blaster, blasterSmall, glaiveBlaster, droneBlaster, healBlaster, healBlasterDrone, chainBlaster, shockgun, - sapper, 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 = ShootFx.shellEjectSmall; - ammo = AmmoTypes.bulletMech; - }}; - - blasterSmall = new Weapon("blaster"){{ - length = 1.5f; - reload = 15f; - roundrobin = true; - ejectEffect = ShootFx.shellEjectSmall; - ammo = AmmoTypes.bulletCopper; - }}; - - glaiveBlaster = new Weapon("bomber"){{ - length = 1.5f; - reload = 10f; - roundrobin = true; - ejectEffect = ShootFx.shellEjectSmall; - ammo = AmmoTypes.bulletGlaive; - }}; - - droneBlaster = new Weapon("blaster"){{ - length = 2f; - reload = 25f; - width = 1f; - roundrobin = true; - ejectEffect = ShootFx.shellEjectSmall; - ammo = AmmoTypes.bulletCopper; - }}; - - healBlaster = new Weapon("heal-blaster"){{ - length = 1.5f; - reload = 24f; - roundrobin = false; - ejectEffect = Fx.none; - recoil = 2f; - ammo = AmmoTypes.healBlaster; - }}; - - missiles = new Weapon("missiles"){{ - length = 1.5f; - reload = 60f; - shots = 4; - inaccuracy = 2f; - roundrobin = true; - ejectEffect = Fx.none; - velocityRnd = 0.2f; - spacing = 1f; - ammo = AmmoTypes.weaponMissile; - }}; - - 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 = AmmoTypes.weaponMissileSwarm; - }}; - - chainBlaster = new Weapon("chain-blaster"){{ - length = 1.5f; - reload = 28f; - roundrobin = true; - ejectEffect = ShootFx.shellEjectSmall; - ammo = AmmoTypes.bulletCopper; - }}; - - shockgun = new Weapon("shockgun"){{ - length = 1f; - reload = 40f; - roundrobin = true; - shots = 1; - inaccuracy = 0f; - velocityRnd = 0.2f; - ejectEffect = Fx.none; - ammo = AmmoTypes.shock; - }}; - - flakgun = new Weapon("flakgun"){{ - length = 1f; - reload = 70f; - roundrobin = true; - shots = 1; - inaccuracy = 3f; - recoil = 3f; - velocityRnd = 0.1f; - ejectEffect = ShootFx.shellEjectMedium; - ammo = AmmoTypes.shellCarbide; - }}; - - flamethrower = new Weapon("flamethrower"){{ - length = 1f; - reload = 14f; - roundrobin = true; - recoil = 1f; - ejectEffect = Fx.none; - ammo = AmmoTypes.flamerThermite; - }}; - - artillery = new Weapon("artillery"){{ - length = 1f; - reload = 60f; - roundrobin = true; - recoil = 5f; - shake = 2f; - ejectEffect = ShootFx.shellEjectMedium; - ammo = AmmoTypes.unitArtillery; - }}; - - sapper = new Weapon("sapper"){{ - length = 1.5f; - reload = 12f; - roundrobin = true; - ejectEffect = ShootFx.shellEjectSmall; - ammo = AmmoTypes.bulletDense; - }}; - - bomber = new Weapon("bomber"){{ - length = 0f; - width = 2f; - reload = 12f; - roundrobin = true; - ejectEffect = Fx.none; - velocityRnd = 1f; - inaccuracy = 40f; - ammo = AmmoTypes.bombExplosive; - }}; - - bomberTrident = new Weapon("bomber"){{ - length = 0f; - width = 2f; - reload = 8f; - shots = 2; - roundrobin = true; - ejectEffect = Fx.none; - velocityRnd = 1f; - inaccuracy = 40f; - ammo = AmmoTypes.bombExplosive; - }}; - - laserBurster = new Weapon("bomber"){{ - reload = 80f; - shake = 3f; - width = 0f; - roundrobin = true; - ejectEffect = Fx.none; - ammo = AmmoTypes.lancerLaser; - }}; - - healBlasterDrone = new Weapon("heal-blaster"){{ - length = 1.5f; - reload = 40f; - width = 0.5f; - roundrobin = true; - ejectEffect = Fx.none; - recoil = 2f; - ammo = AmmoTypes.healBlaster; - }}; - - healBlasterDrone2 = new Weapon("heal-blaster"){{ - length = 1.5f; - reload = 20f; - width = 0.5f; - roundrobin = true; - ejectEffect = Fx.none; - recoil = 2f; - ammo = AmmoTypes.healBlaster; - }}; - } - - @Override - public ContentType type(){ - return ContentType.weapon; - } -} diff --git a/core/src/io/anuke/mindustry/content/Zones.java b/core/src/io/anuke/mindustry/content/Zones.java new file mode 100644 index 0000000000..628e9673e8 --- /dev/null +++ b/core/src/io/anuke/mindustry/content/Zones.java @@ -0,0 +1,581 @@ +package io.anuke.mindustry.content; + +import io.anuke.arc.collection.Array; +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; + + @Override + public void load(){ + + groundZero = new Zone("groundZero", new MapGenerator("groundZero", 1)){{ + deployCost = ItemStack.with(); + startingItems = ItemStack.with(Items.copper, 50); + alwaysUnlocked = true; + conditionWave = 10; + launchPeriod = 5; + resources = new Item[]{Items.copper, Items.scrap}; + rules = () -> new Rules(){{ + waves = true; + waveTimer = true; + waveSpacing = 60 * 60 * 2; //2 mins + spawns = Array.with( + new SpawnGroup(UnitTypes.dagger){{ + unitScaling = 1.5f; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 10; + unitScaling = 2; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 15; + unitScaling = 1; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 20; + unitScaling = 1; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 25; + unitScaling = 1; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 30; + unitScaling = 1; + }} + ); + }}; + }}; + + craters = new Zone("craters", new MapGenerator("craters", 1).dist(0)){{ + deployCost = ItemStack.with(Items.copper, 200); + startingItems = ItemStack.with(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 * 60 * 1.5f; + spawns = Array.with( + new SpawnGroup(UnitTypes.dagger){{ + unitScaling = 1.5f; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + begin = 5; + unitAmount = 2; + spacing = 2; + unitScaling = 2; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 10; + unitScaling = 1; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + begin = 15; + unitScaling = 1; + unitAmount = 2; + }}, + + new SpawnGroup(UnitTypes.dagger){{ + begin = 20; + unitScaling = 1; + }}, + + new SpawnGroup(UnitTypes.crawler){{ + begin = 25; + unitScaling = 1; + unitAmount = 2; + }} + ); + }}; + }}; + + frozenForest = new Zone("frozenForest", new MapGenerator("frozenForest", 2) + .decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.02)) + .core(Blocks.coreFoundation)){{ + deployCost = ItemStack.with(Items.copper, 500); + startingItems = ItemStack.with(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; + }} + ); + }}; + }}; + + ruinousShores = new Zone("ruinousShores", new MapGenerator("ruinousShores", 1) + .core(Blocks.coreFoundation)){{ + deployCost = ItemStack.with(Items.copper, 600, Items.graphite, 50); + startingItems = ItemStack.with(Items.copper, 400); + conditionWave = 20; + launchPeriod = 20; + zoneRequirements = new Zone[]{frozenForest}; + 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 * 60; + 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; + }} + ); + }}; + }}; + + /* + crags = new Zone("crags", 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; + }}; + }};*/ + + stainedMountains = new Zone("stainedMountains", new MapGenerator("stainedMountains", 2) + .dist(2.5f, true) + .decor(new Decoration(Blocks.stainedStone, Blocks.stainedBoulder, 0.01)) + .core(Blocks.coreFoundation)){{ + deployCost = ItemStack.with(Items.copper, 500, Items.lead, 300, Items.silicon, 100); + startingItems = ItemStack.with(Items.copper, 400, Items.lead, 100); + conditionWave = 10; + launchPeriod = 10; + zoneRequirements = new Zone[]{frozenForest}; + 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 * 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; + }} + ); + }}; + }}; + + impact = new Zone("impact0079", new MapGenerator("impact0079", 2) + .decor( + new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01), + new Decoration(Blocks.metalFloor, Blocks.metalFloorDamaged, 0.02) + ).drops(ItemStack.with(Items.copper, 2000, Items.lead, 1500, Items.silicon, 1000, Items.graphite, 1000, Items.pyratite, 2000, Items.titanium, 2000, Items.metaglass, 1000))){{ + deployCost = ItemStack.with(Items.copper, 2500, Items.lead, 1000, Items.silicon, 300); + startingItems = ItemStack.with(Items.copper, 2000, Items.lead, 500, Items.silicon, 200); + itemRequirements = ItemStack.with(Items.silicon, 8000, Items.titanium, 6000, Items.graphite, 4000); + conditionWave = 20; + zoneRequirements = new Zone[]{stainedMountains}; + blockRequirements = new Block[]{Blocks.launchPad, Blocks.unloader}; + resources = new Item[]{Items.scrap}; + rules = () -> new Rules(){{ + waves = true; + waveTimer = true; + waveSpacing = 60 * 60; + + spawns = Array.with( + new SpawnGroup(UnitTypes.titan){{ + unitScaling = 2; + spacing = 2; + end = 10; + }}, + + 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.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; + }} + ); + }}; + }}; + + desolateRift = new Zone("desolateRift", new MapGenerator("desolateRift") + .core(Blocks.coreNucleus).dist(2f)){{ + deployCost = ItemStack.with(Items.copper, 2000); + startingItems = ItemStack.with(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}; + rules = () -> new Rules(){{ + waves = true; + waveTimer = true; + waveSpacing = 30 * 60; + spawns = Array.with( + new SpawnGroup(UnitTypes.crawler){{ + unitScaling = 1; + spacing = 2; + end = 10; + }}, + + 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; + }} + ); + }}; + }}; + + /* + 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("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)) + .core(Blocks.coreFoundation)){{ + deployCost = ItemStack.with(Items.copper, 3000, Items.lead, 2000, Items.silicon, 1000, Items.metaglass, 500); + startingItems = ItemStack.with(Items.copper, 2500, Items.lead, 1500, 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[]{impact}; + blockRequirements = new Block[]{Blocks.blastDrill, Blocks.thermalGenerator}; + resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.thorium}; + rules = () -> new Rules(){{ + waves = true; + waveTimer = true; + waveSpacing = 60 * 60 * 2; + + spawns = Array.with( + new SpawnGroup(UnitTypes.titan){{ + unitScaling = 2; + spacing = 2; + end = 10; + }}, + + 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.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; + }} + ); + }}; + }}; + + /* + 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; + }}; + }};*/ + } +} diff --git a/core/src/io/anuke/mindustry/content/blocks/BlockList.java b/core/src/io/anuke/mindustry/content/blocks/BlockList.java deleted file mode 100644 index 85cf617fd9..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/BlockList.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.ContentType; - -public abstract class BlockList implements ContentList{ - - @Override - public ContentType type(){ - return ContentType.item; - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/Blocks.java b/core/src/io/anuke/mindustry/content/blocks/Blocks.java deleted file mode 100644 index cce8774a04..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/Blocks.java +++ /dev/null @@ -1,179 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.content.StatusEffects; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.graphics.CacheLayer; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.*; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.Mathf; - -public class Blocks extends BlockList implements ContentList{ - public static Block air, blockpart, spawn, space, metalfloor, deepwater, water, lava, tar, stone, - blackstone, dirt, sand, ice, snow, grass, shrub, rock, icerock, blackrock; - - - @Override - public void load(){ - air = new Floor("air"){ - { - blend = false; - alwaysReplace = true; - } - - public void draw(Tile tile){} - public void load(){} - public void init(){} - }; - - blockpart = new BlockPart(); - - spawn = new Block("spawn"){ - - public void drawShadow(Tile tile){} - - public void draw(Tile tile){ - Draw.color(Color.SCARLET); - Lines.circle(tile.worldx(), tile.worldy(), 4f +Mathf.absin(Timers.time(), 6f, 6f)); - Draw.color(); - } - }; - - //Registers build blocks from size 1-6 - //no reference is needed here since they can be looked up by name later - for(int i = 1; i <= 6; i++){ - new BuildBlock("build" + i); - } - - space = new Floor("space"){{ - placeableOn = false; - variants = 0; - cacheLayer = CacheLayer.space; - solid = true; - blend = false; - minimapColor = Color.valueOf("000001"); - }}; - - metalfloor = new Floor("metalfloor"){{ - variants = 6; - }}; - - deepwater = new Floor("deepwater"){{ - liquidColor = Color.valueOf("546bb3"); - speedMultiplier = 0.2f; - variants = 0; - liquidDrop = Liquids.water; - isLiquid = true; - status = StatusEffects.wet; - statusIntensity = 1f; - drownTime = 140f; - cacheLayer = CacheLayer.water; - minimapColor = Color.valueOf("465a96"); - }}; - - water = new Floor("water"){{ - liquidColor = Color.valueOf("546bb3"); - speedMultiplier = 0.5f; - variants = 0; - status = StatusEffects.wet; - statusIntensity = 0.9f; - liquidDrop = Liquids.water; - isLiquid = true; - cacheLayer = CacheLayer.water; - minimapColor = Color.valueOf("506eb4"); - }}; - - lava = new Floor("lava"){{ - drownTime = 100f; - liquidColor = Color.valueOf("ed5334"); - speedMultiplier = 0.2f; - damageTaken = 0.5f; - status = StatusEffects.melting; - statusIntensity = 0.8f; - variants = 0; - liquidDrop = Liquids.lava; - isLiquid = true; - cacheLayer = CacheLayer.lava; - minimapColor = Color.valueOf("ed5334"); - }}; - - tar = new Floor("tar"){{ - drownTime = 150f; - liquidColor = Color.valueOf("292929"); - status = StatusEffects.tarred; - statusIntensity = 1f; - speedMultiplier = 0.19f; - variants = 0; - liquidDrop = Liquids.oil; - isLiquid = true; - cacheLayer = CacheLayer.oil; - minimapColor = Color.valueOf("292929"); - }}; - - stone = new Floor("stone"){{ - hasOres = true; - drops = new ItemStack(Items.stone, 1); - blends = block -> block != this && !(block instanceof OreBlock); - minimapColor = Color.valueOf("323232"); - playerUnmineable = true; - }}; - - blackstone = new Floor("blackstone"){{ - drops = new ItemStack(Items.stone, 1); - minimapColor = Color.valueOf("252525"); - playerUnmineable = true; - hasOres = true; - }}; - - dirt = new Floor("dirt"){{ - minimapColor = Color.valueOf("6e501e"); - }}; - - sand = new Floor("sand"){{ - drops = new ItemStack(Items.sand, 1); - 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"); - hasOres = true; - }}; - - grass = new Floor("grass"){{ - hasOres = true; - minimapColor = Color.valueOf("549d5b"); - }}; - - shrub = new Rock("shrub"){{ - shadow = "shrubshadow"; - }}; - - rock = new Rock("rock"){{ - variants = 2; - }}; - - icerock = new Rock("icerock"){{ - variants = 2; - }}; - - blackrock = new Rock("blackrock"){{ - variants = 1; - }}; - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/CraftingBlocks.java b/core/src/io/anuke/mindustry/content/blocks/CraftingBlocks.java deleted file mode 100644 index de9b602fe2..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/CraftingBlocks.java +++ /dev/null @@ -1,239 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.content.fx.BlockFx; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.production.*; - -public class CraftingBlocks extends BlockList implements ContentList{ - public static Block smelter, arcsmelter, siliconsmelter, plastaniumCompressor, phaseWeaver, alloySmelter, - pyratiteMixer, blastMixer, - cryofluidmixer, melter, separator, centrifuge, biomatterCompressor, pulverizer, solidifier, incinerator; - - @Override - public void load(){ - smelter = new Smelter("smelter"){{ - health = 70; - result = Items.densealloy; - craftTime = 45f; - burnDuration = 46f; - useFlux = true; - - consumes.items(new ItemStack[]{new ItemStack(Items.copper, 1), new ItemStack(Items.lead, 2)}); - consumes.item(Items.coal).optional(true); - }}; - - arcsmelter = new PowerSmelter("arc-smelter"){{ - health = 90; - craftEffect = BlockFx.smeltsmoke; - result = Items.densealloy; - craftTime = 30f; - size = 2; - - useFlux = true; - fluxNeeded = 2; - - consumes.items(new ItemStack[]{new ItemStack(Items.copper, 1), new ItemStack(Items.lead, 2)}); - consumes.power(0.1f); - }}; - - siliconsmelter = new PowerSmelter("silicon-smelter"){{ - health = 90; - craftEffect = BlockFx.smeltsmoke; - result = Items.silicon; - craftTime = 40f; - powerCapacity = 20f; - size = 2; - hasLiquids = false; - flameColor = Color.valueOf("ffef99"); - - consumes.items(new ItemStack[]{new ItemStack(Items.coal, 1), new ItemStack(Items.sand, 2)}); - consumes.power(0.05f); - }}; - - plastaniumCompressor = new PlastaniumCompressor("plastanium-compressor"){{ - hasItems = true; - liquidCapacity = 60f; - craftTime = 60f; - output = Items.plastanium; - itemCapacity = 30; - powerCapacity = 40f; - size = 2; - health = 320; - hasPower = hasLiquids = true; - craftEffect = BlockFx.formsmoke; - updateEffect = BlockFx.plasticburn; - - consumes.liquid(Liquids.oil, 0.25f); - consumes.power(0.3f); - consumes.item(Items.titanium, 2); - }}; - - phaseWeaver = new PhaseWeaver("phase-weaver"){{ - craftEffect = BlockFx.smeltsmoke; - result = Items.phasefabric; - craftTime = 120f; - powerCapacity = 50f; - size = 2; - - consumes.items(new ItemStack[]{new ItemStack(Items.thorium, 4), new ItemStack(Items.sand, 10)}); - consumes.power(0.5f); - }}; - - alloySmelter = new PowerSmelter("alloy-smelter"){{ - craftEffect = BlockFx.smeltsmoke; - result = Items.surgealloy; - craftTime = 75f; - powerCapacity = 60f; - size = 2; - - useFlux = true; - fluxNeeded = 3; - - consumes.power(0.4f); - consumes.items(new ItemStack[]{new ItemStack(Items.titanium, 2), new ItemStack(Items.lead, 4), new ItemStack(Items.silicon, 3), new ItemStack(Items.copper, 3)}); - }}; - - cryofluidmixer = new LiquidMixer("cryofluidmixer"){{ - outputLiquid = Liquids.cryofluid; - liquidPerItem = 50f; - itemCapacity = 50; - size = 2; - hasPower = true; - - consumes.power(0.1f); - consumes.item(Items.titanium); - consumes.liquid(Liquids.water, 0.3f); - }}; - - blastMixer = new GenericCrafter("blast-mixer"){{ - itemCapacity = 20; - 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); - }}; - - pyratiteMixer = new PowerSmelter("pyratite-mixer"){{ - flameColor = Color.CLEAR; - itemCapacity = 20; - hasItems = true; - hasPower = true; - result = Items.pyratite; - - size = 2; - - consumes.power(0.02f); - consumes.items(new ItemStack[]{new ItemStack(Items.coal, 1), new ItemStack(Items.lead, 2), new ItemStack(Items.sand, 2)}); - }}; - - melter = new PowerCrafter("melter"){{ - health = 200; - outputLiquid = Liquids.lava; - outputLiquidAmount = 1f; - itemCapacity = 20; - craftTime = 10f; - hasLiquids = hasPower = true; - - consumes.power(0.1f); - consumes.item(Items.stone, 1); - }}; - - separator = new Separator("separator"){{ - results = new ItemStack[]{ - new ItemStack(null, 10), - new ItemStack(Items.sand, 10), - new ItemStack(Items.stone, 9), - new ItemStack(Items.copper, 4), - new ItemStack(Items.lead, 2), - new ItemStack(Items.coal, 2), - new ItemStack(Items.titanium, 1), - }; - filterTime = 40f; - itemCapacity = 40; - health = 50; - - consumes.item(Items.stone, 2); - consumes.liquid(Liquids.water, 0.3f); - }}; - - centrifuge = new Separator("centrifuge"){{ - results = new ItemStack[]{ - new ItemStack(null, 13), - new ItemStack(Items.sand, 12), - new ItemStack(Items.stone, 11), - new ItemStack(Items.copper, 5), - new ItemStack(Items.lead, 3), - new ItemStack(Items.coal, 3), - new ItemStack(Items.titanium, 2), - new ItemStack(Items.thorium, 1) - }; - - hasPower = true; - filterTime = 15f; - itemCapacity = 60; - health = 50 * 4; - spinnerLength = 1.5f; - spinnerRadius = 3.5f; - spinnerThickness = 1.5f; - spinnerSpeed = 3f; - size = 2; - - consumes.item(Items.stone, 2); - consumes.power(0.2f); - consumes.liquid(Liquids.water, 0.5f); - }}; - - biomatterCompressor = new Compressor("biomattercompressor"){{ - liquidCapacity = 60f; - itemCapacity = 50; - craftTime = 20f; - outputLiquid = Liquids.oil; - outputLiquidAmount = 2.5f; - size = 2; - health = 320; - hasLiquids = true; - - consumes.item(Items.biomatter, 1); - consumes.power(0.06f); - }}; - - pulverizer = new Pulverizer("pulverizer"){{ - itemCapacity = 40; - output = Items.sand; - health = 80; - craftEffect = BlockFx.pulverize; - craftTime = 40f; - updateEffect = BlockFx.pulverizeSmall; - hasItems = hasPower = true; - - consumes.item(Items.stone, 1); - consumes.power(0.05f); - }}; - - solidifier = new GenericCrafter("solidifer"){{ - liquidCapacity = 21f; - craftTime = 14; - output = Items.stone; - itemCapacity = 20; - health = 80; - craftEffect = BlockFx.purifystone; - hasLiquids = hasItems = true; - - consumes.liquid(Liquids.lava, 1f); - }}; - - incinerator = new Incinerator("incinerator"){{ - health = 90; - }}; - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java b/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java deleted file mode 100644 index 53ac78afb1..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/DebugBlocks.java +++ /dev/null @@ -1,197 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import com.badlogic.gdx.utils.Array; -import io.anuke.annotations.Annotations.Loc; -import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.world.BarType; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.PowerBlock; -import io.anuke.mindustry.world.blocks.distribution.Sorter; -import io.anuke.mindustry.world.blocks.power.PowerNode; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.scene.ui.ButtonGroup; -import io.anuke.ucore.scene.ui.ImageButton; -import io.anuke.ucore.scene.ui.layout.Table; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import static io.anuke.mindustry.Vars.*; - -public class DebugBlocks extends BlockList implements ContentList{ - public static Block powerVoid, powerInfinite, itemSource, liquidSource, itemVoid; - - @Remote(targets = Loc.both, called = Loc.both, forward = true) - public static void setLiquidSourceLiquid(Player player, Tile tile, Liquid liquid){ - LiquidSourceEntity entity = tile.entity(); - entity.source = liquid; - } - - @Override - public void load(){ - powerVoid = new PowerBlock("powervoid"){ - { - powerCapacity = Float.MAX_VALUE; - shadow = "shadow-round-1"; - } - - @Override - public void setBars(){ - super.setBars(); - bars.remove(BarType.power); - } - - @Override - public void init(){ - super.init(); - stats.remove(BlockStat.powerCapacity); - } - }; - - powerInfinite = new PowerNode("powerinfinite"){ - { - powerCapacity = 10000f; - maxNodes = 100; - outputsPower = true; - consumesPower = false; - shadow = "shadow-round-1"; - } - - @Override - public void update(Tile tile){ - super.update(tile); - tile.entity.power.amount = powerCapacity; - } - }; - - itemSource = new Sorter("itemsource"){ - { - hasItems = true; - } - - @Override - public boolean outputsItems(){ - return true; - } - - @Override - public void setBars(){ - super.setBars(); - bars.remove(BarType.inventory); - } - - @Override - public void update(Tile tile){ - SorterEntity entity = tile.entity(); - if(entity.sortItem == null) return; - - entity.items.set(entity.sortItem, 1); - tryDump(tile, entity.sortItem); - entity.items.set(entity.sortItem, 0); - } - - @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - return false; - } - }; - - liquidSource = new Block("liquidsource"){ - { - update = true; - solid = true; - hasLiquids = true; - liquidCapacity = 100f; - configurable = true; - outputsLiquid = true; - } - - @Override - public void update(Tile tile){ - LiquidSourceEntity entity = tile.entity(); - - tile.entity.liquids.add(entity.source, liquidCapacity); - tryDumpLiquid(tile, entity.source); - } - - @Override - public void draw(Tile tile){ - super.draw(tile); - - LiquidSourceEntity entity = tile.entity(); - - Draw.color(entity.source.color); - Draw.rect("blank", tile.worldx(), tile.worldy(), 4f, 4f); - Draw.color(); - } - - @Override - public void buildTable(Tile tile, Table table){ - LiquidSourceEntity entity = tile.entity(); - - Array items = content.liquids(); - - ButtonGroup group = new ButtonGroup<>(); - Table cont = new Table(); - - for(int i = 0; i < items.size; i++){ - if(!control.unlocks.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(); - button.setChecked(entity.source.id == f); - - if(i % 4 == 3){ - cont.row(); - } - } - - table.add(cont); - } - - @Override - public TileEntity newEntity(){ - return new LiquidSourceEntity(); - } - }; - - itemVoid = new Block("itemvoid"){ - { - update = solid = true; - } - - @Override - public void handleItem(Item item, Tile tile, Tile source){ - } - - @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - return true; - } - }; - } - - class LiquidSourceEntity extends TileEntity{ - public Liquid source = Liquids.water; - - @Override - public void writeConfig(DataOutput stream) throws IOException{ - stream.writeByte(source.id); - } - - @Override - public void readConfig(DataInput stream) throws IOException{ - source = content.liquid(stream.readByte()); - } - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/DefenseBlocks.java b/core/src/io/anuke/mindustry/content/blocks/DefenseBlocks.java deleted file mode 100644 index 6a8b586c7b..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/DefenseBlocks.java +++ /dev/null @@ -1,99 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.fx.BlockFx; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.defense.*; - -public class DefenseBlocks extends BlockList implements ContentList{ - public static Block copperWall, copperWallLarge, denseAlloyWall, denseAlloyWallLarge, thoriumWall, thoriumWallLarge, door, doorLarge, - phaseWall, phaseWallLarge, surgeWall, surgeWallLarge, mendProjector, overdriveProjector, forceProjector, shockMine; - - @Override - public void load(){ - int wallHealthMultiplier = 3; - - copperWall = new Wall("copper-wall"){{ - health = 80 * wallHealthMultiplier; - }}; - - copperWallLarge = new Wall("copper-wall-large"){{ - health = 80 * 4 * wallHealthMultiplier; - size = 2; - }}; - - denseAlloyWall = new Wall("dense-alloy-wall"){{ - health = 110 * wallHealthMultiplier; - }}; - - denseAlloyWallLarge = new Wall("dense-alloy-wall-large"){{ - health = 110 * wallHealthMultiplier * 4; - size = 2; - }}; - - thoriumWall = new Wall("thorium-wall"){{ - health = 200 * wallHealthMultiplier; - }}; - - thoriumWallLarge = new Wall("thorium-wall-large"){{ - health = 200 * wallHealthMultiplier * 4; - size = 2; - }}; - - phaseWall = new DeflectorWall("phase-wall"){{ - health = 150 * wallHealthMultiplier; - }}; - - phaseWallLarge = new DeflectorWall("phase-wall-large"){{ - health = 150 * 4 * wallHealthMultiplier; - size = 2; - }}; - - surgeWall = new SurgeWall("surge-wall"){{ - health = 230 * wallHealthMultiplier; - }}; - - surgeWallLarge = new SurgeWall("surge-wall-large"){{ - health = 230 * 4 * wallHealthMultiplier; - size = 2; - }}; - - door = new Door("door"){{ - health = 100 * wallHealthMultiplier; - }}; - - doorLarge = new Door("door-large"){{ - openfx = BlockFx.dooropenlarge; - closefx = BlockFx.doorcloselarge; - health = 100 * 4 * wallHealthMultiplier; - size = 2; - }}; - - mendProjector = new MendProjector("mend-projector"){{ - consumes.power(0.2f); - size = 2; - consumes.item(Items.phasefabric).optional(true); - }}; - - overdriveProjector = new OverdriveProjector("overdrive-projector"){{ - consumes.power(0.35f); - size = 2; - consumes.item(Items.phasefabric).optional(true); - }}; - - forceProjector = new ForceProjector("force-projector"){{ - consumes.power(0.2f); - size = 3; - consumes.item(Items.phasefabric).optional(true); - }}; - - shockMine = new ShockMine("shock-mine"){{ - health = 40; - damage = 11; - tileDamage = 7f; - length = 10; - tendrils = 5; - }}; - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/DistributionBlocks.java b/core/src/io/anuke/mindustry/content/blocks/DistributionBlocks.java deleted file mode 100644 index df4ab9ea20..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/DistributionBlocks.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.distribution.*; - -public class DistributionBlocks extends BlockList implements ContentList{ - public static Block conveyor, titaniumconveyor, distributor, junction, - itemBridge, phaseConveyor, sorter, router, overflowGate, massDriver; - - @Override - public void load(){ - - conveyor = new Conveyor("conveyor"){{ - health = 45; - speed = 0.03f; - }}; - - titaniumconveyor = new Conveyor("titanium-conveyor"){{ - health = 65; - speed = 0.07f; - }}; - - junction = new Junction("junction"){{ - speed = 26; - capacity = 32; - }}; - - itemBridge = new BufferedItemBridge("bridge-conveyor"){{ - range = 4; - speed = 60f; - bufferCapacity = 15; - }}; - - phaseConveyor = new ItemBridge("phase-conveyor"){{ - range = 12; - hasPower = true; - consumes.power(0.03f); - }}; - - sorter = new Sorter("sorter"); - - router = new Router("router"); - - distributor = new Router("distributor"){{ - size = 2; - }}; - - overflowGate = new OverflowGate("overflow-gate"); - - massDriver = new MassDriver("mass-driver"){{ - size = 3; - itemCapacity = 60; - range = 440f; - }}; - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/LiquidBlocks.java b/core/src/io/anuke/mindustry/content/blocks/LiquidBlocks.java deleted file mode 100644 index e4eb6ff040..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/LiquidBlocks.java +++ /dev/null @@ -1,75 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.distribution.*; -import io.anuke.mindustry.world.blocks.production.Pump; - -public class LiquidBlocks extends BlockList implements ContentList{ - public static Block mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, liquidRouter, liquidtank, liquidJunction, bridgeConduit, phaseConduit; - - @Override - public void load(){ - - mechanicalPump = new Pump("mechanical-pump"){{ - shadow = "shadow-round-1"; - pumpAmount = 0.1f; - tier = 0; - }}; - - rotaryPump = new Pump("rotary-pump"){{ - shadow = "shadow-rounded-2"; - pumpAmount = 0.2f; - consumes.power(0.015f); - liquidCapacity = 30f; - powerCapacity = 20f; - hasPower = true; - size = 2; - tier = 1; - }}; - - thermalPump = new Pump("thermal-pump"){{ - shadow = "shadow-rounded-2"; - pumpAmount = 0.275f; - consumes.power(0.03f); - liquidCapacity = 40f; - hasPower = true; - powerCapacity = 20f; - size = 2; - tier = 2; - }}; - - conduit = new Conduit("conduit"){{ - health = 45; - }}; - - pulseConduit = new Conduit("pulse-conduit"){{ - liquidCapacity = 16f; - liquidFlowFactor = 4.9f; - health = 90; - }}; - - liquidRouter = new LiquidRouter("liquid-router"){{ - liquidCapacity = 20f; - }}; - - liquidtank = new LiquidTank("liquid-tank"){{ - size = 3; - liquidCapacity = 1500f; - health = 500; - }}; - - liquidJunction = new LiquidJunction("liquid-junction"); - - bridgeConduit = new LiquidExtendingBridge("bridge-conduit"){{ - range = 4; - hasPower = false; - }}; - - phaseConduit = new LiquidBridge("phase-conduit"){{ - range = 12; - hasPower = true; - consumes.power(0.03f); - }}; - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/OreBlocks.java b/core/src/io/anuke/mindustry/content/blocks/OreBlocks.java deleted file mode 100644 index 83f16dc29f..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/OreBlocks.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import com.badlogic.gdx.utils.ObjectMap; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.mindustry.world.blocks.OreBlock; - -import static io.anuke.mindustry.Vars.content; - -public class OreBlocks extends BlockList{ - private static final ObjectMap> oreBlockMap = new ObjectMap<>(); - - 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!"); - return oreBlockMap.get(item).get(floor); - } - - @Override - public void load(){ - - for(Item item : content.items()){ - if(!item.genOre) continue; - ObjectMap map = new ObjectMap<>(); - oreBlockMap.put(item, map); - - for(Block block : content.blocks()){ - if(block instanceof Floor && ((Floor) block).hasOres){ - map.put(block, new OreBlock(item, (Floor) block)); - } - } - } - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java b/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java deleted file mode 100644 index 1101a106e8..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/PowerBlocks.java +++ /dev/null @@ -1,88 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.content.fx.BlockFx; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.power.*; - -public class PowerBlocks extends BlockList implements ContentList{ - public static Block combustionGenerator, thermalGenerator, turbineGenerator, rtgGenerator, solarPanel, largeSolarPanel, - thoriumReactor, fusionReactor, battery, batteryLarge, powerNode, powerNodeLarge; - - @Override - public void load(){ - combustionGenerator = new BurnerGenerator("combustion-generator"){{ - powerOutput = 0.09f; - powerCapacity = 40f; - itemDuration = 40f; - }}; - - thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{ - maxLiquidGenerate = 2f; - powerCapacity = 40f; - powerPerLiquid = 0.35f; - generateEffect = BlockFx.redgeneratespark; - size = 2; - }}; - - turbineGenerator = new TurbineGenerator("turbine-generator"){{ - powerOutput = 0.28f; - powerCapacity = 40f; - itemDuration = 30f; - powerPerLiquid = 0.7f; - consumes.liquid(Liquids.water, 0.05f); - size = 2; - }}; - - rtgGenerator = new DecayGenerator("rtg-generator"){{ - powerCapacity = 40f; - size = 2; - powerOutput = 0.3f; - itemDuration = 220f; - }}; - - solarPanel = new SolarGenerator("solar-panel"){{ - generation = 0.0045f; - }}; - - largeSolarPanel = new SolarGenerator("solar-panel-large"){{ - size = 3; - generation = 0.055f; - }}; - - thoriumReactor = new NuclearReactor("thorium-reactor"){{ - size = 3; - health = 700; - powerMultiplier = 1.1f; - }}; - - fusionReactor = new FusionReactor("fusion-reactor"){{ - size = 4; - health = 600; - }}; - - battery = new Battery("battery"){{ - powerCapacity = 320f; - }}; - - batteryLarge = new Battery("battery-large"){{ - size = 3; - powerCapacity = 2000f; - }}; - - powerNode = new PowerNode("power-node"){{ - shadow = "shadow-round-1"; - maxNodes = 4; - laserRange = 6; - }}; - - powerNodeLarge = new PowerNode("power-node-large"){{ - size = 2; - maxNodes = 6; - laserRange = 9.5f; - shadow = "shadow-round-2"; - }}; - - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java b/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java deleted file mode 100644 index 389cb425c7..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java +++ /dev/null @@ -1,112 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.content.fx.BlockFx; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.production.Cultivator; -import io.anuke.mindustry.world.blocks.production.Drill; -import io.anuke.mindustry.world.blocks.production.Fracker; -import io.anuke.mindustry.world.blocks.production.SolidPump; - -public class ProductionBlocks extends BlockList implements ContentList{ - public static Block mechanicalDrill, pneumaticDrill, laserDrill, blastDrill, plasmaDrill, waterExtractor, oilExtractor, cultivator; - - @Override - public void load(){ - mechanicalDrill = new Drill("mechanical-drill"){{ - tier = 2; - drillTime = 300; - size = 2; - drawMineItem = true; - }}; - - pneumaticDrill = new Drill("pneumatic-drill"){{ - tier = 3; - drillTime = 240; - size = 2; - drawMineItem = true; - }}; - - laserDrill = new Drill("laser-drill"){{ - drillTime = 140; - size = 2; - hasPower = true; - tier = 4; - updateEffect = BlockFx.pulverizeMedium; - drillEffect = BlockFx.mineBig; - - consumes.power(0.11f); - }}; - - blastDrill = new Drill("blast-drill"){{ - drillTime = 60; - size = 3; - drawRim = true; - hasPower = true; - tier = 5; - updateEffect = BlockFx.pulverizeRed; - updateEffectChance = 0.03f; - drillEffect = BlockFx.mineHuge; - rotateSpeed = 6f; - warmupSpeed = 0.01f; - - consumes.power(0.3f); - }}; - - plasmaDrill = new Drill("plasma-drill"){{ - heatColor = Color.valueOf("ff461b"); - drillTime = 50; - size = 4; - hasLiquids = true; - hasPower = true; - tier = 5; - rotateSpeed = 9f; - drawRim = true; - updateEffect = BlockFx.pulverizeRedder; - updateEffectChance = 0.04f; - drillEffect = BlockFx.mineHuge; - warmupSpeed = 0.005f; - - consumes.power(0.7f); - }}; - - waterExtractor = new SolidPump("water-extractor"){{ - result = Liquids.water; - pumpAmount = 0.065f; - size = 2; - liquidCapacity = 30f; - rotateSpeed = 1.4f; - - consumes.power(0.09f); - }}; - - oilExtractor = new Fracker("oil-extractor"){{ - result = Liquids.oil; - updateEffect = BlockFx.pulverize; - liquidCapacity = 50f; - updateEffectChance = 0.05f; - pumpAmount = 0.09f; - size = 3; - liquidCapacity = 30f; - - consumes.item(Items.sand); - consumes.power(0.3f); - consumes.liquid(Liquids.water, 0.15f); - }}; - - cultivator = new Cultivator("cultivator"){{ - result = Items.biomatter; - drillTime = 200; - size = 2; - hasLiquids = true; - hasPower = true; - - consumes.power(0.08f); - consumes.liquid(Liquids.water, 0.15f); - }}; - - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/StorageBlocks.java b/core/src/io/anuke/mindustry/content/blocks/StorageBlocks.java deleted file mode 100644 index 9972317a99..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/StorageBlocks.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.storage.CoreBlock; -import io.anuke.mindustry.world.blocks.storage.SortedUnloader; -import io.anuke.mindustry.world.blocks.storage.Vault; - -public class StorageBlocks extends BlockList implements ContentList{ - public static Block core, vault, container, unloader; - - @Override - public void load(){ - core = new CoreBlock("core"){{ - health = 1100; - itemCapacity = 3000; - }}; - - vault = new Vault("vault"){{ - size = 3; - itemCapacity = 1000; - }}; - - container = new Vault("container"){{ - size = 2; - itemCapacity = 300; - }}; - - unloader = new SortedUnloader("unloader"){{ - speed = 7f; - }}; - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/TurretBlocks.java b/core/src/io/anuke/mindustry/content/blocks/TurretBlocks.java deleted file mode 100644 index 9569fd7826..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/TurretBlocks.java +++ /dev/null @@ -1,256 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import io.anuke.mindustry.content.AmmoTypes; -import io.anuke.mindustry.content.fx.ShootFx; -import io.anuke.mindustry.type.AmmoType; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.defense.turrets.*; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; - -public class TurretBlocks extends BlockList implements ContentList{ - public static Block duo, /*scatter,*/ - scorch, hail, wave, lancer, arc, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown; - - @Override - public void load(){ - duo = new DoubleTurret("duo"){{ - ammoTypes = new AmmoType[]{AmmoTypes.bulletCopper, AmmoTypes.bulletDense, AmmoTypes.bulletPyratite, AmmoTypes.bulletSilicon}; - reload = 25f; - restitution = 0.03f; - range = 90f; - shootCone = 15f; - ammoUseEffect = ShootFx.shellEjectSmall; - health = 80; - inaccuracy = 2f; - rotatespeed = 10f; - }}; - - hail = new ArtilleryTurret("hail"){{ - ammoTypes = new AmmoType[]{AmmoTypes.artilleryDense, AmmoTypes.artilleryHoming, AmmoTypes.artilleryIncindiary}; - reload = 60f; - recoil = 2f; - range = 230f; - inaccuracy = 1f; - shootCone = 10f; - health = 120; - }}; - - scorch = new LiquidTurret("scorch"){ - protected TextureRegion shootRegion; - - @Override - public void load(){ - super.load(); - shootRegion = Draw.region(name + "-shoot"); - } - - { - ammoTypes = new AmmoType[]{AmmoTypes.basicFlame}; - recoil = 0f; - reload = 4f; - shootCone = 50f; - ammoUseEffect = ShootFx.shellEjectSmall; - health = 160; - - drawer = (tile, entity) -> Draw.rect(entity.target != null ? shootRegion : region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90); - } - }; - - wave = new LiquidTurret("wave"){{ - ammoTypes = new AmmoType[]{AmmoTypes.water, AmmoTypes.lava, AmmoTypes.cryofluid, AmmoTypes.oil}; - size = 2; - recoil = 0f; - reload = 4f; - inaccuracy = 5f; - shootCone = 50f; - shootEffect = ShootFx.shootLiquid; - range = 90f; - health = 360; - - drawer = (tile, entity) -> { - Draw.rect(region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90); - - Draw.color(entity.liquids.current().color); - Draw.alpha(entity.liquids.total() / liquidCapacity); - Draw.rect(name + "-liquid", tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90); - Draw.color(); - }; - }}; - - lancer = new ChargeTurret("lancer"){{ - range = 90f; - chargeTime = 60f; - chargeMaxDelay = 30f; - chargeEffects = 7; - shootType = AmmoTypes.lancerLaser; - recoil = 2f; - reload = 100f; - cooldown = 0.03f; - powerUsed = 20f; - powerCapacity = 60f; - shootShake = 2f; - shootEffect = ShootFx.lancerLaserShoot; - smokeEffect = ShootFx.lancerLaserShootSmoke; - chargeEffect = ShootFx.lancerLaserCharge; - chargeBeginEffect = ShootFx.lancerLaserChargeBegin; - heatColor = Color.RED; - size = 2; - health = 320; - targetAir = false; - }}; - - arc = new PowerTurret("arc"){{ - shootType = AmmoTypes.arc; - reload = 85f; - shootShake = 1f; - shootCone = 40f; - rotatespeed = 8f; - powerUsed = 10f; - powerCapacity = 30f; - range = 150f; - shootEffect = ShootFx.lightningShoot; - heatColor = Color.RED; - recoil = 1f; - size = 1; - }}; - - swarmer = new BurstTurret("swarmer"){{ - ammoTypes = new AmmoType[]{AmmoTypes.missileExplosive, AmmoTypes.missileIncindiary, AmmoTypes.missileSurge}; - reload = 50f; - shots = 4; - burstSpacing = 5; - inaccuracy = 10f; - range = 140f; - xRand = 6f; - size = 2; - health = 380; - }}; - - salvo = new BurstTurret("salvo"){ - TextureRegion[] panels = new TextureRegion[2]; - - @Override - public void load() { - super.load(); - panels[0] = Draw.region(name + "-panel-left"); - panels[1] = Draw.region(name + "-panel-right"); - } - - { - size = 2; - range = 120f; - ammoTypes = new AmmoType[]{AmmoTypes.bulletCopper, AmmoTypes.bulletDense, AmmoTypes.bulletPyratite, AmmoTypes.bulletThorium, AmmoTypes.bulletSilicon}; - reload = 35f; - restitution = 0.03f; - ammoEjectBack = 3f; - cooldown = 0.03f; - recoil = 3f; - shootShake = 2f; - burstSpacing = 4; - shots = 3; - ammoUseEffect = ShootFx.shellEjectBig; - - drawer = (tile, entity) -> { - Draw.rect(region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90); - float offsetx = (int) (Mathf.abscurve(Mathf.curve(entity.reload / reload, 0.3f, 0.2f)) * 3f); - float offsety = -(int) (Mathf.abscurve(Mathf.curve(entity.reload / reload, 0.3f, 0.2f)) * 2f); - - for(int i : Mathf.signs){ - float rot = entity.rotation + 90 * i; - Draw.rect(panels[i == -1 ? 0 : 1], - tile.drawx() + tr2.x + Angles.trnsx(rot, offsetx, offsety), - tile.drawy() + tr2.y + Angles.trnsy(rot, -offsetx, offsety), entity.rotation - 90); - } - }; - - health = 360; - } - }; - - ripple = new ArtilleryTurret("ripple"){{ - ammoTypes = new AmmoType[]{AmmoTypes.artilleryDense, AmmoTypes.artilleryHoming, AmmoTypes.artilleryIncindiary, AmmoTypes.artilleryExplosive, AmmoTypes.artilleryPlastic}; - size = 3; - shots = 4; - inaccuracy = 12f; - reload = 60f; - ammoEjectBack = 5f; - ammoUseEffect = ShootFx.shellEjectBig; - cooldown = 0.03f; - velocityInaccuracy = 0.2f; - restitution = 0.02f; - recoil = 6f; - shootShake = 2f; - range = 320f; - - health = 550; - }}; - - cyclone = new ItemTurret("cyclone"){{ - ammoTypes = new AmmoType[]{AmmoTypes.flakExplosive, AmmoTypes.flakPlastic, AmmoTypes.flakSurge}; - xRand = 4f; - reload = 8f; - range = 145f; - size = 3; - recoil = 3f; - rotatespeed = 10f; - inaccuracy = 13f; - shootCone = 30f; - - health = 145 * size * size; - }}; - - fuse = new ItemTurret("fuse"){{ - ammoTypes = new AmmoType[]{AmmoTypes.fuseShotgun}; - reload = 50f; - shootShake = 4f; - range = 80f; - recoil = 5f; - restitution = 0.1f; - size = 3; - - health = 155 * size * size; - }}; - - spectre = new DoubleTurret("spectre"){{ - ammoTypes = new AmmoType[]{AmmoTypes.bulletDenseBig, AmmoTypes.bulletPyratiteBig, AmmoTypes.bulletThoriumBig}; - reload = 6f; - coolantMultiplier = 0.5f; - maxCoolantUsed = 1.5f; - restitution = 0.1f; - ammoUseEffect = ShootFx.shellEjectBig; - range = 200f; - inaccuracy = 3f; - recoil = 3f; - xRand = 3f; - shotWidth = 4f; - shootShake = 2f; - shots = 2; - size = 4; - shootCone = 24f; - - health = 155 * size * size; - }}; - - meltdown = new LaserTurret("meltdown"){{ - shootType = AmmoTypes.meltdownLaser; - shootEffect = ShootFx.shootBigSmoke2; - shootCone = 40f; - recoil = 4f; - size = 4; - shootShake = 2f; - powerUsed = 60f; - powerCapacity = 120f; - range = 160f; - reload = 200f; - firingMoveFract = 0.1f; - shootDuration = 220f; - - health = 165 * size * size; - }}; - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/UnitBlocks.java b/core/src/io/anuke/mindustry/content/blocks/UnitBlocks.java deleted file mode 100644 index 7f4a40d602..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/UnitBlocks.java +++ /dev/null @@ -1,100 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.UnitTypes; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.units.*; - -public class UnitBlocks extends BlockList implements ContentList{ - public static Block - spiritFactory, phantomFactory, - wraithFactory, ghoulFactory, revenantFactory, - daggerFactory, titanFactory, fortressFactory, - reconstructor, repairPoint, commandCenter; - - @Override - public void load(){ - spiritFactory = new UnitFactory("spirit-factory"){{ - type = UnitTypes.spirit; - produceTime = 5700; - size = 2; - consumes.power(0.08f); - consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.lead, 30)); - }}; - - phantomFactory = new UnitFactory("phantom-factory"){{ - type = UnitTypes.phantom; - produceTime = 7300; - size = 2; - consumes.power(0.2f); - consumes.items(new ItemStack(Items.silicon, 70), new ItemStack(Items.lead, 80), new ItemStack(Items.titanium, 80)); - }}; - - wraithFactory = new UnitFactory("wraith-factory"){{ - type = UnitTypes.wraith; - produceTime = 1800; - size = 2; - consumes.power(0.1f); - consumes.items(new ItemStack(Items.silicon, 10), new ItemStack(Items.titanium, 10)); - }}; - - ghoulFactory = new UnitFactory("ghoul-factory"){{ - type = UnitTypes.ghoul; - produceTime = 3600; - size = 3; - consumes.power(0.2f); - shadow = "shadow-round-3"; - consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.titanium, 30), new ItemStack(Items.plastanium, 20)); - }}; - - revenantFactory = new UnitFactory("revenant-factory"){{ - type = UnitTypes.revenant; - produceTime = 8000; - size = 4; - consumes.power(0.3f); - shadow = "shadow-round-4"; - consumes.items(new ItemStack(Items.silicon, 80), new ItemStack(Items.titanium, 80), new ItemStack(Items.plastanium, 50)); - }}; - - daggerFactory = new UnitFactory("dagger-factory"){{ - type = UnitTypes.dagger; - produceTime = 1700; - size = 2; - consumes.power(0.05f); - consumes.items(new ItemStack(Items.silicon, 10)); - }}; - - titanFactory = new UnitFactory("titan-factory"){{ - type = UnitTypes.titan; - produceTime = 3400; - size = 3; - consumes.power(0.15f); - shadow = "shadow-round-3"; - consumes.items(new ItemStack(Items.silicon, 20), new ItemStack(Items.thorium, 30)); - }}; - - fortressFactory = new UnitFactory("fortress-factory"){{ - type = UnitTypes.fortress; - produceTime = 5000; - size = 3; - consumes.power(0.2f); - shadow = "shadow-round-3"; - consumes.items(new ItemStack(Items.silicon, 40), new ItemStack(Items.thorium, 50)); - }}; - - repairPoint = new RepairPoint("repair-point"){{ - shadow = "shadow-round-1"; - repairSpeed = 0.1f; - }}; - - reconstructor = new Reconstructor("reconstructor"){{ - size = 2; - }}; - - commandCenter = new CommandCenter("command-center"){{ - size = 2; - }}; - } -} diff --git a/core/src/io/anuke/mindustry/content/blocks/UpgradeBlocks.java b/core/src/io/anuke/mindustry/content/blocks/UpgradeBlocks.java deleted file mode 100644 index 5e991fd9e7..0000000000 --- a/core/src/io/anuke/mindustry/content/blocks/UpgradeBlocks.java +++ /dev/null @@ -1,64 +0,0 @@ -package io.anuke.mindustry.content.blocks; - -import io.anuke.mindustry.content.Mechs; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.units.MechPad; - -public class UpgradeBlocks extends BlockList{ - public static Block alphaPad, deltaPad, tauPad, omegaPad, dartPad, javelinPad, tridentPad, glaivePad; - - @Override - public void load(){ - alphaPad = new MechPad("alpha-mech-pad"){{ - mech = Mechs.alpha; - size = 2; - powerCapacity = 50f; - }}; - - deltaPad = new MechPad("delta-mech-pad"){{ - mech = Mechs.delta; - size = 2; - powerCapacity = 70f; - }}; - - tauPad = new MechPad("tau-mech-pad"){{ - mech = Mechs.tau; - size = 2; - powerCapacity = 100f; - }}; - - omegaPad = new MechPad("omega-mech-pad"){{ - mech = Mechs.omega; - size = 3; - powerCapacity = 120f; - }}; - - dartPad = new MechPad("dart-ship-pad"){{ - mech = Mechs.dart; - size = 2; - powerCapacity = 50f; - shadow = "shadow-rounded-2"; - }}; - - javelinPad = new MechPad("javelin-ship-pad"){{ - mech = Mechs.javelin; - size = 2; - powerCapacity = 80f; - shadow = "shadow-rounded-2"; - }}; - - tridentPad = new MechPad("trident-ship-pad"){{ - mech = Mechs.trident; - size = 2; - powerCapacity = 100f; - shadow = "shadow-rounded-2"; - }}; - - glaivePad = new MechPad("glaive-ship-pad"){{ - mech = Mechs.glaive; - size = 3; - powerCapacity = 120f; - shadow = "shadow-round-3"; - }}; - } -} diff --git a/core/src/io/anuke/mindustry/content/bullets/ArtilleryBullets.java b/core/src/io/anuke/mindustry/content/bullets/ArtilleryBullets.java deleted file mode 100644 index 0bb8857f22..0000000000 --- a/core/src/io/anuke/mindustry/content/bullets/ArtilleryBullets.java +++ /dev/null @@ -1,123 +0,0 @@ -package io.anuke.mindustry.content.bullets; - -import io.anuke.mindustry.content.fx.BulletFx; -import io.anuke.mindustry.content.fx.Fx; -import io.anuke.mindustry.entities.bullet.ArtilleryBulletType; -import io.anuke.mindustry.entities.bullet.BasicBulletType; -import io.anuke.mindustry.entities.bullet.BulletType; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.game.ContentList; - -public class ArtilleryBullets extends BulletList implements ContentList{ - public static BulletType dense, plastic, plasticFrag, homing, incindiary, explosive, surge, unit; - - @Override - public void load(){ - - dense = new ArtilleryBulletType(3f, 0, "shell"){ - { - hiteffect = BulletFx.flakExplosion; - knockback = 0.8f; - lifetime = 50f; - bulletWidth = bulletHeight = 11f; - collidesTiles = false; - splashDamageRadius = 25f; - splashDamage = 33f; - } - }; - - plasticFrag = new BasicBulletType(2.5f, 6, "bullet"){ - { - bulletWidth = 10f; - bulletHeight = 12f; - bulletShrink = 1f; - lifetime = 15f; - backColor = Palette.plastaniumBack; - frontColor = Palette.plastaniumFront; - despawneffect = Fx.none; - } - }; - - plastic = new ArtilleryBulletType(3.3f, 0, "shell"){ - { - hiteffect = BulletFx.plasticExplosion; - knockback = 1f; - lifetime = 55f; - bulletWidth = bulletHeight = 13f; - collidesTiles = false; - splashDamageRadius = 35f; - splashDamage = 35f; - fragBullet = plasticFrag; - fragBullets = 9; - backColor = Palette.plastaniumBack; - frontColor = Palette.plastaniumFront; - } - }; - - homing = new ArtilleryBulletType(3f, 0, "shell"){ - { - hiteffect = BulletFx.flakExplosion; - knockback = 0.8f; - lifetime = 45f; - bulletWidth = bulletHeight = 11f; - collidesTiles = false; - splashDamageRadius = 25f; - splashDamage = 33f; - homingPower = 2f; - homingRange = 50f; - } - }; - - incindiary = new ArtilleryBulletType(3f, 0, "shell"){ - { - hiteffect = BulletFx.blastExplosion; - knockback = 0.8f; - lifetime = 60f; - bulletWidth = bulletHeight = 13f; - collidesTiles = false; - splashDamageRadius = 25f; - splashDamage = 30f; - incendAmount = 4; - incendSpread = 11f; - frontColor = Palette.lightishOrange; - backColor = Palette.lightOrange; - trailEffect = BulletFx.incendTrail; - } - }; - - explosive = new ArtilleryBulletType(2f, 0, "shell"){ - { - hiteffect = BulletFx.blastExplosion; - knockback = 0.8f; - lifetime = 70f; - bulletWidth = bulletHeight = 14f; - collidesTiles = false; - splashDamageRadius = 45f; - splashDamage = 50f; - backColor = Palette.missileYellowBack; - frontColor = Palette.missileYellow; - } - }; - - unit = new ArtilleryBulletType(2f, 0, "shell"){ - { - hiteffect = BulletFx.blastExplosion; - knockback = 0.8f; - lifetime = 90f; - bulletWidth = bulletHeight = 14f; - collides = true; - collidesTiles = true; - splashDamageRadius = 45f; - splashDamage = 50f; - backColor = Palette.bulletYellowBack; - frontColor = Palette.bulletYellow; - } - }; - - surge = new ArtilleryBulletType(3f, 0, "shell"){ - { - //TODO - } - }; - } -} diff --git a/core/src/io/anuke/mindustry/content/bullets/BulletList.java b/core/src/io/anuke/mindustry/content/bullets/BulletList.java deleted file mode 100644 index cfe4921b93..0000000000 --- a/core/src/io/anuke/mindustry/content/bullets/BulletList.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.anuke.mindustry.content.bullets; - -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.ContentType; - -public abstract class BulletList implements ContentList{ - - @Override - public ContentType type(){ - return ContentType.bullet; - } -} diff --git a/core/src/io/anuke/mindustry/content/bullets/FlakBullets.java b/core/src/io/anuke/mindustry/content/bullets/FlakBullets.java deleted file mode 100644 index 158c4240fa..0000000000 --- a/core/src/io/anuke/mindustry/content/bullets/FlakBullets.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.anuke.mindustry.content.bullets; - -import io.anuke.mindustry.content.fx.BulletFx; -import io.anuke.mindustry.entities.bullet.Bullet; -import io.anuke.mindustry.entities.bullet.BulletType; -import io.anuke.mindustry.entities.bullet.FlakBulletType; -import io.anuke.mindustry.entities.effect.Lightning; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.game.ContentList; -import io.anuke.ucore.util.Mathf; - -public class FlakBullets extends BulletList implements ContentList{ - public static BulletType plastic, explosive, surge; - - @Override - public void load(){ - - - plastic = new FlakBulletType(4f, 5){ - { - splashDamageRadius = 40f; - fragBullet = ArtilleryBullets.plasticFrag; - fragBullets = 4; - hiteffect = BulletFx.plasticExplosion; - frontColor = Palette.plastaniumFront; - backColor = Palette.plastaniumBack; - } - }; - - explosive = new FlakBulletType(4f, 5){ - { - //default bullet type, no changes - } - }; - - surge = new FlakBulletType(4f, 7){ - { - splashDamage = 33f; - } - - @Override - public void despawned(Bullet b) { - super.despawned(b); - - for (int i = 0; i < 2; i++) { - Lightning.create(b.getTeam(), Palette.surge, damage, b.x, b.y, Mathf.random(360f), 12); - } - } - }; - } -} diff --git a/core/src/io/anuke/mindustry/content/bullets/MissileBullets.java b/core/src/io/anuke/mindustry/content/bullets/MissileBullets.java deleted file mode 100644 index 0e0dc3a8fb..0000000000 --- a/core/src/io/anuke/mindustry/content/bullets/MissileBullets.java +++ /dev/null @@ -1,124 +0,0 @@ -package io.anuke.mindustry.content.bullets; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.content.fx.BulletFx; -import io.anuke.mindustry.entities.bullet.Bullet; -import io.anuke.mindustry.entities.bullet.BulletType; -import io.anuke.mindustry.entities.bullet.MissileBulletType; -import io.anuke.mindustry.entities.effect.Lightning; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.game.ContentList; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.util.Mathf; - -public class MissileBullets extends BulletList implements ContentList{ - public static BulletType explosive, incindiary, surge, javelin, swarm; - - @Override - public void load(){ - - explosive = new MissileBulletType(1.8f, 10, "missile"){ - { - bulletWidth = 8f; - bulletHeight = 8f; - bulletShrink = 0f; - drag = -0.01f; - splashDamageRadius = 30f; - splashDamage = 30f; - lifetime = 150f; - hiteffect = BulletFx.blastExplosion; - despawneffect = BulletFx.blastExplosion; - } - }; - - incindiary = new MissileBulletType(2f, 12, "missile"){ - { - frontColor = Palette.lightishOrange; - backColor = Palette.lightOrange; - bulletWidth = 7f; - bulletHeight = 8f; - bulletShrink = 0f; - drag = -0.01f; - homingPower = 7f; - splashDamageRadius = 10f; - splashDamage = 10f; - lifetime = 160f; - hiteffect = BulletFx.blastExplosion; - incendSpread = 10f; - incendAmount = 3; - } - }; - - surge = new MissileBulletType(3.5f, 15, "bullet"){ - { - bulletWidth = 8f; - bulletHeight = 8f; - bulletShrink = 0f; - drag = -0.01f; - splashDamageRadius = 30f; - splashDamage = 22f; - lifetime = 150f; - hiteffect = BulletFx.blastExplosion; - despawneffect = BulletFx.blastExplosion; - } - - @Override - public void hit(Bullet b) { - super.hit(b); - - for (int i = 0; i < 2; i++) { - Lightning.create(b.getTeam(), Palette.surge, damage, b.x, b.y, Mathf.random(360f), 14); - } - } - }; - - javelin = new MissileBulletType(5f, 10.5f, "missile"){ - { - bulletWidth = 8f; - bulletHeight = 8f; - bulletShrink = 0f; - drag = -0.003f; - keepVelocity = false; - splashDamageRadius = 20f; - splashDamage = 1f; - lifetime = 90f; - trailColor = Color.valueOf("b6c6fd"); - hiteffect = BulletFx.blastExplosion; - despawneffect = BulletFx.blastExplosion; - backColor = Palette.bulletYellowBack; - frontColor = Palette.bulletYellow; - } - - @Override - public void update(Bullet b){ - super.update(b); - b.getVelocity().rotate(Mathf.sin(Timers.time() + b.id * 4422, 8f, 2f)); - } - }; - - swarm = new MissileBulletType(2.7f, 12, "missile"){ - { - bulletWidth = 8f; - bulletHeight = 8f; - bulletShrink = 0f; - drag = -0.003f; - homingRange = 60f; - keepVelocity = false; - splashDamageRadius = 25f; - splashDamage = 10f; - lifetime = 120f; - trailColor = Color.GRAY; - backColor = Palette.bulletYellowBack; - frontColor = Palette.bulletYellow; - hiteffect = BulletFx.blastExplosion; - despawneffect = BulletFx.blastExplosion; - } - - @Override - public void update(Bullet b){ - super.update(b); - b.getVelocity().rotate(Mathf.sin(Timers.time() + b.id * 4422, 8f, 2f)); - } - }; - } -} diff --git a/core/src/io/anuke/mindustry/content/bullets/StandardBullets.java b/core/src/io/anuke/mindustry/content/bullets/StandardBullets.java deleted file mode 100644 index 57c888aa47..0000000000 --- a/core/src/io/anuke/mindustry/content/bullets/StandardBullets.java +++ /dev/null @@ -1,108 +0,0 @@ -package io.anuke.mindustry.content.bullets; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.content.fx.BulletFx; -import io.anuke.mindustry.entities.bullet.BasicBulletType; -import io.anuke.mindustry.entities.bullet.BulletType; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.game.ContentList; - -public class StandardBullets extends BulletList implements ContentList{ - public static BulletType copper, dense, thorium, homing, tracer, mechSmall, glaive, denseBig, thoriumBig, tracerBig; - - @Override - public void load(){ - - copper = new BasicBulletType(2.5f, 7, "bullet"){ - { - bulletWidth = 7f; - bulletHeight = 9f; - } - }; - - dense = new BasicBulletType(3.5f, 18, "bullet"){ - { - bulletWidth = 9f; - bulletHeight = 12f; - armorPierce = 0.2f; - } - }; - - thorium = new BasicBulletType(4f, 29, "bullet"){ - { - bulletWidth = 10f; - bulletHeight = 13f; - armorPierce = 0.5f; - } - }; - - homing = new BasicBulletType(3f, 9, "bullet"){ - { - bulletWidth = 7f; - bulletHeight = 9f; - homingPower = 5f; - } - }; - - tracer = new BasicBulletType(3.2f, 11, "bullet"){ - { - bulletWidth = 10f; - bulletHeight = 12f; - frontColor = Palette.lightishOrange; - backColor = Palette.lightOrange; - incendSpread = 3f; - incendAmount = 1; - incendChance = 0.3f; - } - }; - - glaive = new BasicBulletType(4f, 7.5f, "bullet"){ - { - bulletWidth = 10f; - bulletHeight = 12f; - frontColor = Color.valueOf("feb380"); - backColor = Color.valueOf("ea8878"); - incendSpread = 3f; - incendAmount = 1; - incendChance = 0.3f; - } - }; - - mechSmall = new BasicBulletType(4f, 9, "bullet"){ - { - bulletWidth = 11f; - bulletHeight = 14f; - lifetime = 40f; - despawneffect = BulletFx.hitBulletSmall; - } - }; - - denseBig = new BasicBulletType(7f, 42, "bullet"){ - { - bulletWidth = 15f; - bulletHeight = 21f; - armorPierce = 0.2f; - } - }; - - thoriumBig = new BasicBulletType(8f, 65, "bullet"){ - { - bulletWidth = 16f; - bulletHeight = 23f; - armorPierce = 0.5f; - } - }; - - tracerBig = new BasicBulletType(7f, 38, "bullet"){ - { - bulletWidth = 16f; - bulletHeight = 21f; - frontColor = Palette.lightishOrange; - backColor = Palette.lightOrange; - incendSpread = 3f; - incendAmount = 2; - incendChance = 0.3f; - } - }; - } -} diff --git a/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java b/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java deleted file mode 100644 index 1ec5252b02..0000000000 --- a/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java +++ /dev/null @@ -1,424 +0,0 @@ -package io.anuke.mindustry.content.bullets; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.content.StatusEffects; -import io.anuke.mindustry.content.fx.BlockFx; -import io.anuke.mindustry.content.fx.BulletFx; -import io.anuke.mindustry.content.fx.EnvironmentFx; -import io.anuke.mindustry.content.fx.Fx; -import io.anuke.mindustry.entities.Damage; -import io.anuke.mindustry.entities.bullet.Bullet; -import io.anuke.mindustry.entities.bullet.BulletType; -import io.anuke.mindustry.entities.bullet.LiquidBulletType; -import io.anuke.mindustry.entities.effect.Fire; -import io.anuke.mindustry.entities.effect.Lightning; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.BuildBlock; -import io.anuke.mindustry.world.blocks.distribution.MassDriver.DriverBulletData; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.*; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; - -import static io.anuke.mindustry.Vars.content; -import static io.anuke.mindustry.Vars.world; - -public class TurretBullets extends BulletList implements ContentList{ - public static BulletType fireball, basicFlame, lancerLaser, burstLaser, meltdownLaser, - fuseShot, waterShot, cryoShot, lavaShot, oilShot, lightning, driverBolt, healBullet, arc, damageLightning; - - @Override - public void load(){ - - damageLightning = new BulletType(0.0001f, 0f){ - { - lifetime = Lightning.lifetime; - hiteffect = BulletFx.hitLancer; - despawneffect = Fx.none; - status = StatusEffects.shocked; - statusIntensity = 1f; - } - }; - - healBullet = new BulletType(5.2f, 13){ - float healPercent = 3f; - - { - hiteffect = BulletFx.hitLaser; - despawneffect = BulletFx.hitLaser; - collidesTeam = true; - } - - @Override - public boolean collides(Bullet b, Tile tile){ - return tile.getTeam() != b.getTeam() || tile.entity.healthf() < 1f; - } - - @Override - public void draw(Bullet b){ - Draw.color(Palette.heal); - Lines.stroke(2f); - Lines.lineAngleCenter(b.x, b.y, b.angle(), 7f); - Draw.color(Color.WHITE); - Lines.lineAngleCenter(b.x, b.y, b.angle(), 3f); - Draw.reset(); - } - - @Override - public void hitTile(Bullet b, Tile tile){ - super.hit(b); - tile = tile.target(); - - if(tile != null && tile.getTeam() == b.getTeam() && !(tile.block() instanceof BuildBlock)){ - Effects.effect(BlockFx.healBlockFull, Palette.heal, tile.drawx(), tile.drawy(), tile.block().size); - tile.entity.healBy(healPercent / 100f * tile.entity.maxHealth()); - } - } - }; - - fireball = new BulletType(1f, 4){ - { - pierce = true; - hitTiles = false; - collides = false; - collidesTiles = false; - drag = 0.03f; - hiteffect = despawneffect = Fx.none; - } - - @Override - public void init(Bullet b){ - b.getVelocity().setLength(0.6f + Mathf.random(2f)); - } - - @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()); - Fill.circle(b.x, b.y, 3f * b.fout()); - Draw.reset(); - } - - @Override - public void update(Bullet b){ - if(Mathf.chance(0.04 * Timers.delta())){ - Tile tile = world.tileWorld(b.x, b.y); - if(tile != null){ - Fire.create(tile); - } - } - - if(Mathf.chance(0.1 * Timers.delta())){ - Effects.effect(EnvironmentFx.fireballsmoke, b.x, b.y); - } - - if(Mathf.chance(0.1 * Timers.delta())){ - Effects.effect(EnvironmentFx.ballfire, b.x, b.y); - } - } - }; - - basicFlame = new BulletType(2.3f, 5){ - { - hitsize = 7f; - lifetime = 35f; - pierce = true; - drag = 0.05f; - hiteffect = BulletFx.hitFlameSmall; - despawneffect = Fx.none; - status = StatusEffects.burning; - } - - @Override - public void draw(Bullet b){ - } - }; - - lancerLaser = new BulletType(0.001f, 140){ - Color[] colors = {Palette.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Palette.lancerLaser, Color.WHITE}; - float[] tscales = {1f, 0.7f, 0.5f, 0.2f}; - float[] lenscales = {1f, 1.1f, 1.13f, 1.14f}; - float length = 100f; - - { - hiteffect = BulletFx.hitLancer; - despawneffect = Fx.none; - hitsize = 4; - lifetime = 16f; - pierce = true; - } - - @Override - public void init(Bullet b){ - Damage.collideLine(b, b.getTeam(), hiteffect, b.x, b.y, b.angle(), length); - } - - @Override - public void draw(Bullet b){ - float f = Mathf.curve(b.fin(), 0f, 0.2f); - float baseLen = length * f; - - Lines.lineAngle(b.x, b.y, b.angle(), baseLen); - for(int s = 0; s < 3; s++){ - Draw.color(colors[s]); - for(int i = 0; i < tscales.length; i++){ - Lines.stroke(7f * b.fout() * (s == 0 ? 1.5f : s == 1 ? 1f : 0.3f) * tscales[i]); - Lines.lineAngle(b.x, b.y, b.angle(), baseLen * lenscales[i]); - } - } - Draw.reset(); - } - }; - - meltdownLaser = new BulletType(0.001f, 26){ - 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}; - float[] strokes = {2f, 1.5f, 1f, 0.3f}; - float[] lenscales = {1f, 1.12f, 1.15f, 1.17f}; - float length = 200f; - - { - hiteffect = BulletFx.hitMeltdown; - despawneffect = Fx.none; - hitsize = 4; - drawSize = 420f; - lifetime = 16f; - pierce = true; - } - - @Override - public void update(Bullet b){ - if(b.timer.get(1, 5f)){ - Damage.collideLine(b, b.getTeam(), hiteffect, b.x, b.y, b.angle(), length); - } - Effects.shake(1f, 1f, b.x, b.y); - } - - @Override - public void hit(Bullet b, float hitx, float hity){ - Effects.effect(hiteffect, colors[2], hitx, hity); - if(Mathf.chance(0.4)){ - Fire.create(world.tileWorld(hitx+Mathf.range(5f), hity+Mathf.range(5f))); - } - } - - @Override - public void draw(Bullet b){ - float baseLen = (length) * b.fout(); - - Lines.lineAngle(b.x, b.y, b.angle(), baseLen); - for(int s = 0; s < colors.length; s++){ - Draw.color(tmpColor.set(colors[s]).mul(1f + Mathf.absin(Timers.time(), 1f, 0.1f))); - for(int i = 0; i < tscales.length; i++){ - vector.trns(b.angle() + 180f, (lenscales[i] - 1f) * 35f); - Lines.stroke((9f + Mathf.absin(Timers.time(), 0.8f, 1.5f)) * b.fout() * strokes[s] * tscales[i]); - Lines.lineAngle(b.x + vector.x, b.y + vector.y, b.angle(), baseLen * lenscales[i], CapStyle.none); - } - } - Draw.reset(); - } - }; - - fuseShot = new BulletType(0.01f, 70){ - int rays = 3; - float raySpace = 2f; - float rayLength = 80f; - { - hiteffect = BulletFx.hitFuse; - lifetime = 13f; - despawneffect = Fx.none; - pierce = true; - } - - @Override - public void init(Bullet b) { - for (int i = 0; i < rays; i++) { - float offset = (i-rays/2)*raySpace; - vector.trns(b.angle(), 0.01f, offset); - Damage.collideLine(b, b.getTeam(), hiteffect, b.x, b.y, b.angle(), rayLength - Math.abs(i - (rays/2))*20f); - } - } - - @Override - public void draw(Bullet b) { - super.draw(b); - Draw.color(Color.WHITE, Palette.surge, b.fin()); - for(int i = 0; i < 7; i++){ - vector.trns(b.angle(), i * 8f); - float sl = Mathf.clamp(b.fout()-0.5f) * (80f - i *10); - Shapes.tri(b.x + vector.x, b.y + vector.y, 4f, sl, b.angle() + 90); - Shapes.tri(b.x + vector.x, b.y + vector.y, 4f, sl, b.angle() - 90); - } - Shapes.tri(b.x, b.y, 13f, (rayLength+50) * b.fout(), b.angle()); - Shapes.tri(b.x, b.y, 13f, 10f * b.fout(), b.angle() + 180f); - Draw.reset(); - } - - //TODO - }; - - waterShot = new LiquidBulletType(Liquids.water){ - { - status = StatusEffects.wet; - statusIntensity = 0.5f; - knockback = 0.65f; - } - }; - cryoShot = new LiquidBulletType(Liquids.cryofluid){ - { - status = StatusEffects.freezing; - statusIntensity = 0.5f; - } - }; - lavaShot = new LiquidBulletType(Liquids.lava){ - { - damage = 4; - speed = 1.9f; - drag = 0.03f; - status = StatusEffects.melting; - statusIntensity = 0.5f; - } - }; - oilShot = new LiquidBulletType(Liquids.oil){ - { - speed = 2f; - drag = 0.03f; - status = StatusEffects.tarred; - statusIntensity = 0.5f; - } - }; - - lightning = new BulletType(0.001f, 12f){ - { - lifetime = 1f; - despawneffect = Fx.none; - hiteffect = BulletFx.hitLancer; - keepVelocity = false; - } - - @Override - public void draw(Bullet b){ - } - - @Override - public void init(Bullet b){ - Lightning.create(b.getTeam(), Palette.lancerLaser, damage, b.x, b.y, b.angle(), 30); - } - }; - - arc = new BulletType(0.001f, 26){ - { - lifetime = 1; - despawneffect = Fx.none; - hiteffect = BulletFx.hitLancer; - } - - @Override - public void draw(Bullet b){ - } - - @Override - public void init(Bullet b){ - Lightning.create(b.getTeam(), Palette.lancerLaser, damage, b.x, b.y, b.angle(), 36); - } - }; - - driverBolt = new BulletType(5.3f, 50){ - { - collidesTiles = false; - lifetime = 200f; - despawneffect = BlockFx.smeltsmoke; - hiteffect = BulletFx.hitBulletBig; - drag = 0.005f; - } - - @Override - public void draw(Bullet b){ - float w = 11f, h = 13f; - - Draw.color(Palette.bulletYellowBack); - Draw.rect("shell-back", b.x, b.y, w, h, b.angle() + 90); - - Draw.color(Palette.bulletYellow); - Draw.rect("shell", b.x, b.y, w, h, b.angle() + 90); - - Draw.reset(); - } - - @Override - public void update(Bullet b){ - //data MUST be an instance of DriverBulletData - if(!(b.getData() instanceof DriverBulletData)){ - hit(b); - return; - } - - float hitDst = 7f; - - DriverBulletData data = (DriverBulletData) b.getData(); - - //if the target is dead, just keep flying until the bullet explodes - if(data.to.isDead()){ - return; - } - - float baseDst = data.from.distanceTo(data.to); - float dst1 = b.distanceTo(data.from); - float dst2 = b.distanceTo(data.to); - - boolean intersect = false; - - //bullet has gone past the destination point: but did it intersect it? - if(dst1 > baseDst){ - float angleTo = b.angleTo(data.to); - float baseAngle = data.to.angleTo(data.from); - - //if angles are nearby, then yes, it did - if(Mathf.angNear(angleTo, baseAngle, 2f)){ - intersect = true; - //snap bullet position back; this is used for low-FPS situations - b.set(data.to.x + Angles.trnsx(baseAngle, hitDst), data.to.y + Angles.trnsy(baseAngle, hitDst)); - } - } - - //if on course and it's in range of the target - if(Math.abs(dst1 + dst2 - baseDst) < 4f && dst2 <= hitDst){ - intersect = true; - } //else, bullet has gone off course, does not get recieved. - - if(intersect){ - data.to.handlePayload(b, data); - } - } - - @Override - public void despawned(Bullet b){ - super.despawned(b); - - if(!(b.getData() instanceof DriverBulletData)) return; - - DriverBulletData data = (DriverBulletData) b.getData(); - data.to.isRecieving = false; - - for(int i = 0; i < data.items.length; i++){ - int amountDropped = Mathf.random(0, data.items[i]); - if(amountDropped > 0){ - float angle = b.angle() + Mathf.range(100f); - Effects.effect(EnvironmentFx.dropItem, Color.WHITE, b.x, b.y, angle, content.item(i)); - } - } - } - - @Override - public void hit(Bullet b, float hitx, float hity){ - super.hit(b, hitx, hity); - despawned(b); - } - }; - } -} diff --git a/core/src/io/anuke/mindustry/content/bullets/WeaponBullets.java b/core/src/io/anuke/mindustry/content/bullets/WeaponBullets.java deleted file mode 100644 index 514b6e5a12..0000000000 --- a/core/src/io/anuke/mindustry/content/bullets/WeaponBullets.java +++ /dev/null @@ -1,99 +0,0 @@ -package io.anuke.mindustry.content.bullets; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.content.fx.BlockFx; -import io.anuke.mindustry.content.fx.BulletFx; -import io.anuke.mindustry.entities.bullet.BasicBulletType; -import io.anuke.mindustry.entities.bullet.BombBulletType; -import io.anuke.mindustry.entities.bullet.Bullet; -import io.anuke.mindustry.entities.bullet.BulletType; -import io.anuke.mindustry.entities.effect.Fire; -import io.anuke.mindustry.entities.effect.Puddle; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.util.Mathf; - -import static io.anuke.mindustry.Vars.world; - -public class WeaponBullets extends BulletList{ - public static BulletType tungstenShotgun, bombExplosive, bombIncendiary, bombOil, shellCarbide; - - @Override - public void load(){ - tungstenShotgun = new BasicBulletType(5f, 8, "bullet"){ - { - bulletWidth = 8f; - bulletHeight = 9f; - bulletShrink = 0.5f; - lifetime = 50f; - drag = 0.04f; - } - }; - - bombExplosive = new BombBulletType(10f, 20f, "shell"){ - { - bulletWidth = 9f; - bulletHeight = 13f; - hiteffect = BulletFx.flakExplosion; - } - }; - - bombIncendiary = new BombBulletType(7f, 10f, "shell"){ - { - bulletWidth = 8f; - bulletHeight = 12f; - hiteffect = BulletFx.flakExplosion; - backColor = Palette.lightOrange; - frontColor = Palette.lightishOrange; - } - - @Override - public void hit(Bullet b, float x, float y){ - super.hit(b, x, y); - - for(int i = 0; i < 3; i++){ - float cx = x + Mathf.range(10f); - float cy = y + Mathf.range(10f); - Tile tile = world.tileWorld(cx, cy); - if(tile != null){ - Fire.create(tile); - } - } - } - }; - - bombOil = new BombBulletType(2f, 3f, "shell"){ - { - bulletWidth = 8f; - bulletHeight = 12f; - hiteffect = BlockFx.pulverize; - backColor = new Color(0x4f4f4fff); - frontColor = Color.GRAY; - } - - @Override - public void hit(Bullet b, float x, float y){ - super.hit(b, x, y); - - for(int i = 0; i < 3; i++){ - Tile tile = world.tileWorld(x + Mathf.range(8f), y + Mathf.range(8f)); - Puddle.deposit(tile, Liquids.oil, 5f); - } - } - }; - - shellCarbide = new BasicBulletType(3.4f, 20, "bullet"){ - { - bulletWidth = 10f; - bulletHeight = 12f; - bulletShrink = 0.4f; - lifetime = 40f; - drag = 0.025f; - fragBullets = 5; - hiteffect = BulletFx.flakExplosion; - fragBullet = tungstenShotgun; - } - }; - } -} diff --git a/core/src/io/anuke/mindustry/content/fx/BlockFx.java b/core/src/io/anuke/mindustry/content/fx/BlockFx.java deleted file mode 100644 index 2319d71586..0000000000 --- a/core/src/io/anuke/mindustry/content/fx/BlockFx.java +++ /dev/null @@ -1,331 +0,0 @@ -package io.anuke.mindustry.content.fx; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.entities.effect.GroundEffectEntity.GroundEffect; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.game.ContentList; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.graphics.Hue; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Tmp; - -import static io.anuke.mindustry.Vars.tilesize; - -public class BlockFx extends FxList implements ContentList{ - public static Effect reactorsmoke, nuclearsmoke, nuclearcloud, redgeneratespark, generatespark, fuelburn, plasticburn, - pulverize, pulverizeRed, pulverizeRedder, pulverizeSmall, pulverizeMedium, producesmoke, smeltsmoke, formsmoke, blastsmoke, - lava, dooropen, doorclose, dooropenlarge, doorcloselarge, purify, purifyoil, purifystone, generate, mine, mineBig, mineHuge, - smelt, teleportActivate, teleport, teleportOut, ripple, bubble, commandSend, healBlock, healBlockFull, healWaveMend, overdriveWave, - overdriveBlockFull, shieldBreak; - - @Override - public void load(){ - - reactorsmoke = new Effect(17, e -> { - Angles.randLenVectors(e.id, 4, e.fin() * 8f, (x, y) -> { - float size = 1f + e.fout() * 5f; - Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin()); - Draw.rect("circle", e.x + x, e.y + y, size, size); - Draw.reset(); - }); - }); - nuclearsmoke = new Effect(40, e -> { - Angles.randLenVectors(e.id, 4, e.fin() * 13f, (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(); - }); - }); - nuclearcloud = new Effect(90, 200f, e -> { - Angles.randLenVectors(e.id, 10, e.finpow() * 90f, (x, y) -> { - float size = e.fout() * 14f; - Draw.color(Color.LIME, Color.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.rect("circle", e.x + x, e.y + y, len, len); - Draw.reset(); - }); - }); - 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.rect("circle", e.x + x, e.y + y, len, len); - Draw.reset(); - }); - }); - fuelburn = new Effect(23, e -> { - Angles.randLenVectors(e.id, 5, e.fin() * 9f, (x, y) -> { - float len = e.fout() * 4f; - Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin()); - Draw.rect("circle", e.x + x, e.y + y, len, len); - Draw.reset(); - }); - }); - plasticburn = new Effect(40, e -> { - Angles.randLenVectors(e.id, 5, 3f + e.fin() * 5f, (x, y) -> { - Draw.color(Color.valueOf("e9ead3"), Color.GRAY, e.fin()); - Fill.circle(e.x + x, e.y + y, e.fout() * 1f); - Draw.reset(); - }); - }); - pulverize = new Effect(40, e -> { - Angles.randLenVectors(e.id, 5, 3f + e.fin() * 8f, (x, y) -> { - Draw.color(Palette.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()); - 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()); - 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); - 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); - 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()); - Fill.square(e.x + x, e.y + y, 1f + e.fout() * 3f, 45); - Draw.reset(); - }); - }); - smeltsmoke = new Effect(15, e -> { - Angles.randLenVectors(e.id, 6, 4f + e.fin() * 5f, (x, y) -> { - Draw.color(Color.WHITE, e.color, e.fin()); - Fill.square(e.x + x, e.y + y, 0.5f + e.fout() * 2f, 45); - Draw.reset(); - }); - }); - 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()); - Fill.square(e.x + x, e.y + y, 0.2f + e.fout() * 2f, 45); - Draw.reset(); - }); - }); - blastsmoke = new Effect(26, e -> { - Angles.randLenVectors(e.id, 12, 1f + e.fin() * 23f, (x, y) -> { - float size = 2f + e.fout() * 6f; - Draw.color(Color.LIGHT_GRAY, Color.DARK_GRAY, e.fin()); - Draw.rect("circle", e.x + x, e.y + y, size, size); - Draw.reset(); - }); - }); - lava = new Effect(18, e -> { - Angles.randLenVectors(e.id, 3, 1f + e.fin() * 10f, (x, y) -> { - float size = e.fslope() * 4f; - Draw.color(Color.ORANGE, Color.GRAY, e.fin()); - Draw.rect("circle", e.x + x, e.y + y, size, size); - Draw.reset(); - }); - }); - dooropen = new Effect(10, e -> { - Lines.stroke(e.fout() * 1.6f); - Lines.square(e.x, e.y, tilesize / 2f + e.fin() * 2f); - Draw.reset(); - }); - doorclose = new Effect(10, e -> { - Lines.stroke(e.fout() * 1.6f); - Lines.square(e.x, e.y, tilesize / 2f + e.fout() * 2f); - Draw.reset(); - }); - dooropenlarge = new Effect(10, e -> { - Lines.stroke(e.fout() * 1.6f); - Lines.square(e.x, e.y, tilesize + e.fin() * 2f); - Draw.reset(); - }); - doorcloselarge = new Effect(10, e -> { - Lines.stroke(e.fout() * 1.6f); - Lines.square(e.x, e.y, tilesize + e.fout() * 2f); - Draw.reset(); - }); - purify = new Effect(10, e -> { - Draw.color(Color.ROYAL, Color.GRAY, e.fin()); - Lines.stroke(2f); - Lines.spikes(e.x, e.y, e.fin() * 4f, 2, 6); - Draw.reset(); - }); - purifyoil = new Effect(10, e -> { - Draw.color(Color.BLACK, Color.GRAY, e.fin()); - Lines.stroke(2f); - Lines.spikes(e.x, e.y, e.fin() * 4f, 2, 6); - Draw.reset(); - }); - purifystone = new Effect(10, e -> { - Draw.color(Color.ORANGE, Color.GRAY, e.fin()); - Lines.stroke(2f); - Lines.spikes(e.x, e.y, e.fin() * 4f, 2, 6); - Draw.reset(); - }); - generate = new Effect(11, e -> { - Draw.color(Color.ORANGE, Color.YELLOW, e.fin()); - Lines.stroke(1f); - Lines.spikes(e.x, e.y, e.fin() * 5f, 2, 8); - Draw.reset(); - }); - mine = new Effect(20, e -> { - Angles.randLenVectors(e.id, 6, 3f + e.fin() * 6f, (x, y) -> { - Draw.color(e.color, Color.LIGHT_GRAY, e.fin()); - Fill.square(e.x + x, e.y + y, e.fout() * 2f, 45); - Draw.reset(); - }); - }); - mineBig = new Effect(30, e -> { - Angles.randLenVectors(e.id, 6, 4f + e.fin() * 8f, (x, y) -> { - Draw.color(e.color, Color.LIGHT_GRAY, e.fin()); - Fill.square(e.x + x, e.y + y, e.fout() * 2f + 0.2f, 45); - Draw.reset(); - }); - }); - mineHuge = new Effect(40, e -> { - Angles.randLenVectors(e.id, 8, 5f + e.fin() * 10f, (x, y) -> { - Draw.color(e.color, Color.LIGHT_GRAY, e.fin()); - Fill.square(e.x + x, e.y + y, e.fout() * 2f + 0.5f, 45); - Draw.reset(); - }); - }); - smelt = new Effect(20, e -> { - Angles.randLenVectors(e.id, 6, 2f + e.fin() * 5f, (x, y) -> { - Draw.color(Color.WHITE, e.color, e.fin()); - Fill.square(e.x + x, e.y + y, 0.5f + e.fout() * 2f, 45); - Draw.reset(); - }); - }); - teleportActivate = new Effect(50, e -> { - Draw.color(e.color); - - e.scaled(8f, e2 -> { - Lines.stroke(e2.fout() * 4f); - Lines.circle(e2.x, e2.y, 4f + e2.fin() * 27f); - }); - - Lines.stroke(e.fout() * 2f); - - Angles.randLenVectors(e.id, 30, 4f + 40f * e.fin(), (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), e.fin() * 4f + 1f); - }); - - Draw.reset(); - }); - teleport = new Effect(60, e -> { - Draw.color(e.color); - Lines.stroke(e.fin() * 2f); - Lines.circle(e.x, e.y, 7f + e.fout() * 8f); - - Angles.randLenVectors(e.id, 20, 6f + 20f * e.fout(), (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), e.fin() * 4f + 1f); - }); - - Draw.reset(); - }); - teleportOut = new Effect(20, e -> { - Draw.color(e.color); - Lines.stroke(e.fout() * 2f); - Lines.circle(e.x, e.y, 7f + e.fin() * 8f); - - Angles.randLenVectors(e.id, 20, 4f + 20f * e.fin(), (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), e.fslope() * 4f + 1f); - }); - - Draw.reset(); - }); - ripple = new GroundEffect(false, 30, e -> { - Draw.color(Hue.shift(Tmp.c1.set(e.color), 2, 0.1f)); - Lines.stroke(e.fout() + 0.4f); - Lines.circle(e.x, e.y, 2f + e.fin() * 4f); - Draw.reset(); - }); - - bubble = new Effect(20, e -> { - Draw.color(Hue.shift(Tmp.c1.set(e.color), 2, 0.1f)); - Lines.stroke(e.fout() + 0.2f); - Angles.randLenVectors(e.id, 2, 8f, (x, y) -> { - Lines.circle(e.x + x, e.y + y, 1f + e.fin() * 3f); - }); - Draw.reset(); - }); - - commandSend = new Effect(28, e -> { - Draw.color(Palette.command); - Lines.stroke(e.fout() * 2f); - Lines.poly(e.x, e.y, 40, 4f + e.finpow() * 120f); - Draw.color(); - }); - - healWaveMend = new Effect(40, e -> { - Draw.color(e.color); - Lines.stroke(e.fout() * 2f); - Lines.poly(e.x, e.y, 30, e.finpow() * e.rotation); - Draw.color(); - }); - - overdriveWave = new Effect(50, e -> { - Draw.color(e.color); - Lines.stroke(e.fout() * 1f); - Lines.poly(e.x, e.y, 30, e.finpow() * e.rotation); - Draw.color(); - }); - - healBlock = new Effect(20, e -> { - Draw.color(Palette.heal); - Lines.stroke(2f * e.fout() + 0.5f); - Lines.square(e.x, e.y, 1f + (e.fin() * e.rotation * tilesize/2f-1f)); - Draw.color(); - }); - - healBlockFull = new Effect(20, e -> { - Draw.color(e.color); - Draw.alpha(e.fout()); - Fill.square(e.x, e.y, e.rotation * tilesize); - Draw.color(); - }); - - overdriveBlockFull = new Effect(60, e -> { - Draw.color(e.color); - Draw.alpha(e.fslope() * 0.4f); - Fill.square(e.x, e.y, e.rotation * tilesize); - Draw.color(); - }); - - shieldBreak = new Effect(40, e -> { - Draw.color(Palette.accent); - Lines.stroke(3f * e.fout()); - Lines.poly(e.x, e.y, 6, e.rotation + e.fin(), 90); - Draw.reset(); - }); - } -} diff --git a/core/src/io/anuke/mindustry/content/fx/BulletFx.java b/core/src/io/anuke/mindustry/content/fx/BulletFx.java deleted file mode 100644 index 5bcfb50a7f..0000000000 --- a/core/src/io/anuke/mindustry/content/fx/BulletFx.java +++ /dev/null @@ -1,281 +0,0 @@ -package io.anuke.mindustry.content.fx; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.game.ContentList; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; - -public class BulletFx extends FxList implements ContentList{ - public static Effect hitBulletSmall, hitFuse, hitBulletBig, hitFlameSmall, hitLiquid, hitLaser, hitLancer, hitMeltdown, despawn, flakExplosion, blastExplosion, plasticExplosion, - artilleryTrail, incendTrail, missileTrail, absorb, flakExplosionBig, plasticExplosionFlak; - - @Override - public void load(){ - - hitBulletSmall = new Effect(14, e -> { - Draw.color(Color.WHITE, Palette.lightOrange, e.fin()); - - e.scaled(7f, s -> { - Lines.stroke(0.5f + s.fout()); - Lines.circle(e.x, e.y, s.fin()*5f); - }); - - - Lines.stroke(0.5f + e.fout()); - - Angles.randLenVectors(e.id, 5, e.fin() * 15f, (x, y) -> { - float ang = Mathf.atan2(x, y); - Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 3 + 1f); - }); - - Draw.reset(); - }); - - hitFuse = new Effect(14, e -> { - Draw.color(Color.WHITE, Palette.surge, e.fin()); - - e.scaled(7f, s -> { - Lines.stroke(0.5f + s.fout()); - Lines.circle(e.x, e.y, s.fin()*7f); - }); - - - Lines.stroke(0.5f + e.fout()); - - Angles.randLenVectors(e.id, 6, e.fin() * 15f, (x, y) -> { - float ang = Mathf.atan2(x, y); - Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 3 + 1f); - }); - - Draw.reset(); - }); - - hitBulletBig = new Effect(13, e -> { - Draw.color(Color.WHITE, Palette.lightOrange, e.fin()); - Lines.stroke(0.5f + e.fout() * 1.5f); - - Angles.randLenVectors(e.id, 8, e.finpow() * 30f, e.rotation, 50f, (x, y) -> { - float ang = Mathf.atan2(x, y); - Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 4 + 1.5f); - }); - - Draw.reset(); - }); - - hitFlameSmall = new Effect(14, e -> { - Draw.color(Palette.lightFlame, Palette.darkFlame, e.fin()); - Lines.stroke(0.5f + e.fout()); - - Angles.randLenVectors(e.id, 5, e.fin() * 15f, e.rotation, 50f, (x, y) -> { - float ang = Mathf.atan2(x, y); - Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 3 + 1f); - }); - - Draw.reset(); - }); - - hitLiquid = new Effect(16, e -> { - Draw.color(e.color); - - Angles.randLenVectors(e.id, 5, e.fin() * 15f, e.rotation + 180f, 60f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 2f); - }); - - Draw.reset(); - }); - - hitLancer = new Effect(12, e -> { - Draw.color(Color.WHITE); - Lines.stroke(e.fout() * 1.5f); - - Angles.randLenVectors(e.id, 8, e.finpow() * 17f, e.rotation, 360f, (x, y) -> { - float ang = Mathf.atan2(x, y); - Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 4 + 1f); - }); - - Draw.reset(); - }); - - hitMeltdown = new Effect(12, e -> { - Draw.color(Palette.meltdownHit); - Lines.stroke(e.fout() * 2f); - - Angles.randLenVectors(e.id, 6, e.finpow() * 18f, e.rotation, 360f, (x, y) -> { - float ang = Mathf.atan2(x, y); - Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 4 + 1f); - }); - - Draw.reset(); - }); - - hitLaser = new Effect(8, e -> { - Draw.color(Color.WHITE, Palette.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()); - Lines.stroke(e.fout()); - - Angles.randLenVectors(e.id, 7, e.fin() * 7f, e.rotation, 40f, (x, y) -> { - float ang = Mathf.atan2(x, y); - Lines.lineAngle(e.x + x, e.y + y, ang, e.fout() * 2 + 1f); - }); - - Draw.reset(); - }); - - flakExplosion = new Effect(20, e -> { - - Draw.color(Palette.bulletYellow); - e.scaled(6, i -> { - Lines.stroke(3f * i.fout()); - Lines.circle(e.x, e.y, 3f + i.fin() * 10f); - }); - - Draw.color(Color.GRAY); - - Angles.randLenVectors(e.id, 5, 2f + 23f * e.finpow(), (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 3f + 0.5f); - }); - - Draw.color(Palette.lighterOrange); - Lines.stroke(1f * e.fout()); - - Angles.randLenVectors(e.id + 1, 4, 1f + 23f * e.finpow(), (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), 1f + e.fout() * 3f); - }); - - Draw.reset(); - }); - - plasticExplosion = new Effect(24, e -> { - - Draw.color(Palette.plastaniumFront); - e.scaled(7, i -> { - Lines.stroke(3f * i.fout()); - Lines.circle(e.x, e.y, 3f + i.fin() * 24f); - }); - - Draw.color(Color.GRAY); - - Angles.randLenVectors(e.id, 7, 2f + 28f * e.finpow(), (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f); - }); - - Draw.color(Palette.plastaniumBack); - Lines.stroke(1f * e.fout()); - - Angles.randLenVectors(e.id + 1, 4, 1f + 25f * e.finpow(), (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), 1f + e.fout() * 3f); - }); - - Draw.reset(); - }); - - plasticExplosionFlak = new Effect(28, e -> { - - Draw.color(Palette.plastaniumFront); - e.scaled(7, i -> { - Lines.stroke(3f * i.fout()); - Lines.circle(e.x, e.y, 3f + i.fin() * 34f); - }); - - Draw.color(Color.GRAY); - - Angles.randLenVectors(e.id, 7, 2f + 30f * e.finpow(), (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f); - }); - - Draw.color(Palette.plastaniumBack); - Lines.stroke(1f * e.fout()); - - Angles.randLenVectors(e.id + 1, 4, 1f + 30f * e.finpow(), (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), 1f + e.fout() * 3f); - }); - - Draw.reset(); - }); - - blastExplosion = new Effect(22, e -> { - - Draw.color(Palette.missileYellow); - e.scaled(6, i -> { - Lines.stroke(3f * i.fout()); - Lines.circle(e.x, e.y, 3f + i.fin() * 15f); - }); - - Draw.color(Color.GRAY); - - Angles.randLenVectors(e.id, 5, 2f + 23f * e.finpow(), (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f); - }); - - Draw.color(Palette.missileYellowBack); - Lines.stroke(1f * e.fout()); - - Angles.randLenVectors(e.id + 1, 4, 1f + 23f * e.finpow(), (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), 1f + e.fout() * 3f); - }); - - Draw.reset(); - }); - - artilleryTrail = new Effect(50, e -> { - Draw.color(e.color); - Fill.circle(e.x, e.y, e.rotation * e.fout()); - Draw.reset(); - }); - - incendTrail = new Effect(50, e -> { - Draw.color(Palette.lightOrange); - Fill.circle(e.x, e.y, e.rotation * e.fout()); - Draw.reset(); - }); - - missileTrail = new Effect(50, e -> { - Draw.color(e.color); - Fill.circle(e.x, e.y, e.rotation * e.fout()); - Draw.reset(); - }); - - absorb = new Effect(12, e -> { - Draw.color(Palette.accent); - Lines.stroke(2f * e.fout()); - Lines.circle(e.x, e.y, 5f * e.fout()); - Draw.reset(); - }); - - flakExplosionBig = new Effect(30, e -> { - - Draw.color(Palette.bulletYellowBack); - e.scaled(6, i -> { - Lines.stroke(3f * i.fout()); - Lines.circle(e.x, e.y, 3f + i.fin() * 25f); - }); - - Draw.color(Color.GRAY); - - Angles.randLenVectors(e.id, 6, 2f + 23f * e.finpow(), (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.5f); - }); - - Draw.color(Palette.bulletYellow); - Lines.stroke(1f * e.fout()); - - Angles.randLenVectors(e.id + 1, 4, 1f + 23f * e.finpow(), (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), 1f + e.fout() * 3f); - }); - - Draw.reset(); - }); - } - -} diff --git a/core/src/io/anuke/mindustry/content/fx/EnvironmentFx.java b/core/src/io/anuke/mindustry/content/fx/EnvironmentFx.java deleted file mode 100644 index 6dfb5f5b5c..0000000000 --- a/core/src/io/anuke/mindustry/content/fx/EnvironmentFx.java +++ /dev/null @@ -1,137 +0,0 @@ -package io.anuke.mindustry.content.fx; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.type.Item; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; - -public class EnvironmentFx extends FxList implements ContentList{ - public static Effect burning, fire, smoke, steam, fireballsmoke, ballfire, freezing, melting, wet, oily, overdriven, dropItem; - - @Override - public void load(){ - - burning = new Effect(35f, e -> { - Draw.color(Palette.lightFlame, Palette.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); - }); - - Draw.color(); - }); - - fire = new Effect(35f, e -> { - Draw.color(Palette.lightFlame, Palette.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); - }); - - Draw.color(); - }); - - smoke = new Effect(35f, e -> { - Draw.color(Color.GRAY); - - Angles.randLenVectors(e.id, 1, 2f + e.fin() * 7f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, 0.2f + e.fslope() * 1.5f); - }); - - Draw.color(); - }); - - steam = new Effect(35f, e -> { - Draw.color(Color.LIGHT_GRAY); - - 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); - }); - - Draw.color(); - }); - - fireballsmoke = new Effect(25f, e -> { - Draw.color(Color.GRAY); - - Angles.randLenVectors(e.id, 1, 2f + e.fin() * 7f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, 0.2f + e.fout() * 1.5f); - }); - - Draw.color(); - }); - - ballfire = new Effect(25f, e -> { - Draw.color(Palette.lightFlame, Palette.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); - }); - - Draw.color(); - }); - - freezing = new Effect(40f, e -> { - Draw.color(Liquids.cryofluid.color); - - Angles.randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 1.2f); - }); - - Draw.color(); - }); - - melting = new Effect(40f, e -> { - Draw.color(Liquids.lava.color, Color.WHITE, e.fout() / 5f + Mathf.randomSeedRange(e.id, 0.12f)); - - Angles.randLenVectors(e.id, 2, 1f + e.fin() * 3f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, .2f + e.fout() * 1.2f); - }); - - Draw.color(); - }); - - wet = new Effect(40f, e -> { - Draw.color(Liquids.water.color); - - Angles.randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 1f); - }); - - Draw.color(); - }); - - oily = new Effect(42f, e -> { - Draw.color(Liquids.oil.color); - - Angles.randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 1f); - }); - - Draw.color(); - }); - - overdriven = new Effect(20f, e -> { - Draw.color(Palette.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); - }); - - Draw.color(); - }); - - dropItem = new Effect(20f, e -> { - 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); - }); - } -} diff --git a/core/src/io/anuke/mindustry/content/fx/ExplosionFx.java b/core/src/io/anuke/mindustry/content/fx/ExplosionFx.java deleted file mode 100644 index d6d41c9d66..0000000000 --- a/core/src/io/anuke/mindustry/content/fx/ExplosionFx.java +++ /dev/null @@ -1,97 +0,0 @@ -package io.anuke.mindustry.content.fx; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.game.ContentList; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; - -public class ExplosionFx extends FxList implements ContentList{ - public static Effect shockwave, bigShockwave, nuclearShockwave, explosion, blockExplosion, blockExplosionSmoke; - - @Override - public void load(){ - - shockwave = new Effect(10f, 80f, e -> { - Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin()); - Lines.stroke(e.fout() * 2f + 0.2f); - Lines.circle(e.x, e.y, e.fin() * 28f); - Draw.reset(); - }); - - bigShockwave = new Effect(10f, 80f, e -> { - Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin()); - Lines.stroke(e.fout() * 3f); - Lines.circle(e.x, e.y, e.fin() * 50f); - Draw.reset(); - }); - - nuclearShockwave = new Effect(10f, 200f, e -> { - Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin()); - Lines.stroke(e.fout() * 3f + 0.2f); - Lines.poly(e.x, e.y, 40, e.fin() * 140f); - Draw.reset(); - }); - - explosion = new Effect(30, e -> { - e.scaled(7, i -> { - Lines.stroke(3f * i.fout()); - Lines.circle(e.x, e.y, 3f + i.fin() * 10f); - }); - - Draw.color(Color.GRAY); - - Angles.randLenVectors(e.id, 6, 2f + 19f * e.finpow(), (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 3f + 0.5f); - Fill.circle(e.x + x / 2f, e.y + y / 2f, e.fout() * 1f); - }); - - Draw.color(Palette.lighterOrange, Palette.lightOrange, Color.GRAY, e.fin()); - Lines.stroke(1.5f * e.fout()); - - Angles.randLenVectors(e.id + 1, 8, 1f + 23f * e.finpow(), (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), 1f + e.fout() * 3f); - }); - - Draw.reset(); - }); - - blockExplosion = new Effect(30, e -> { - e.scaled(7, i -> { - Lines.stroke(3.1f * i.fout()); - Lines.circle(e.x, e.y, 3f + i.fin() * 14f); - }); - - Draw.color(Color.GRAY); - - Angles.randLenVectors(e.id, 6, 2f + 19f * e.finpow(), (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 3f + 0.5f); - Fill.circle(e.x + x / 2f, e.y + y / 2f, e.fout() * 1f); - }); - - Draw.color(Palette.lighterOrange, Palette.lightOrange, Color.GRAY, e.fin()); - Lines.stroke(1.7f * e.fout()); - - Angles.randLenVectors(e.id + 1, 9, 1f + 23f * e.finpow(), (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), 1f + e.fout() * 3f); - }); - - Draw.reset(); - }); - - blockExplosionSmoke = new Effect(30, e -> { - Draw.color(Color.GRAY); - - Angles.randLenVectors(e.id, 6, 4f + 30f * e.finpow(), (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 3f); - Fill.circle(e.x + x / 2f, e.y + y / 2f, e.fout() * 1f); - }); - - Draw.reset(); - }); - } -} diff --git a/core/src/io/anuke/mindustry/content/fx/Fx.java b/core/src/io/anuke/mindustry/content/fx/Fx.java deleted file mode 100644 index 23ad56d6c9..0000000000 --- a/core/src/io/anuke/mindustry/content/fx/Fx.java +++ /dev/null @@ -1,69 +0,0 @@ -package io.anuke.mindustry.content.fx; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.game.ContentList; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.Angles; - -import static io.anuke.mindustry.Vars.tilesize; - -public class Fx extends FxList implements ContentList{ - public static Effect none, placeBlock, breakBlock, smoke, spawn, tapBlock, select; - - @Override - public void load(){ - - none = new Effect(0, 0f, e -> { - }); - - placeBlock = new Effect(16, e -> { - Draw.color(Palette.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); - 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); - Lines.stroke(3f - e.fin() * 2f); - Lines.square(e.x, e.y, tilesize / 2f * e.rotation + e.fin() * 3f); - - Angles.randLenVectors(e.id, 3 + (int) (e.rotation * 3), e.rotation * 2f + (tilesize * e.rotation) * e.finpow(), (x, y) -> { - Fill.square(e.x + x, e.y + y, 1f + e.fout() * (3f + e.rotation)); - }); - Draw.reset(); - }); - - select = new Effect(23, e -> { - Draw.color(Palette.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()); - float size = 7f - e.fin() * 7f; - Draw.rect("circle", e.x, e.y, size, size); - Draw.reset(); - }); - - spawn = new Effect(23, e -> { - Lines.stroke(2f * e.fout()); - Draw.color(Palette.accent); - Lines.poly(e.x, e.y, 4, 3f + e.fin() * 8f); - Draw.reset(); - }); - } -} diff --git a/core/src/io/anuke/mindustry/content/fx/FxList.java b/core/src/io/anuke/mindustry/content/fx/FxList.java deleted file mode 100644 index 3809d32391..0000000000 --- a/core/src/io/anuke/mindustry/content/fx/FxList.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.anuke.mindustry.content.fx; - -import io.anuke.mindustry.game.ContentList; -import io.anuke.mindustry.type.ContentType; - -public abstract class FxList implements ContentList{ - - @Override - public ContentType type(){ - return ContentType.effect; - } -} diff --git a/core/src/io/anuke/mindustry/content/fx/ShootFx.java b/core/src/io/anuke/mindustry/content/fx/ShootFx.java deleted file mode 100644 index 4e82b9a70e..0000000000 --- a/core/src/io/anuke/mindustry/content/fx/ShootFx.java +++ /dev/null @@ -1,225 +0,0 @@ -package io.anuke.mindustry.content.fx; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.entities.effect.GroundEffectEntity.GroundEffect; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.game.ContentList; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.graphics.Shapes; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; - -public class ShootFx extends FxList implements ContentList{ - public static Effect shootSmall, shootHeal, shootSmallSmoke, shootBig, shootBig2, shootBigSmoke, shootBigSmoke2, shootSmallFlame, shootLiquid, shellEjectSmall, shellEjectMedium, shellEjectBig, lancerLaserShoot, lancerLaserShootSmoke, lancerLaserCharge, lancerLaserChargeBegin, lightningCharge, lightningShoot; - - @Override - public void load(){ - - shootSmall = new Effect(8, e -> { - Draw.color(Palette.lighterOrange, Palette.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); - Draw.reset(); - }); - - shootHeal = new Effect(8, e -> { - Draw.color(Palette.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); - Draw.reset(); - }); - - shootSmallSmoke = new Effect(20f, e -> { - Draw.color(Palette.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); - }); - - Draw.reset(); - }); - - shootBig = new Effect(9, e -> { - Draw.color(Palette.lighterOrange, Palette.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); - Draw.reset(); - }); - - shootBig2 = new Effect(10, e -> { - Draw.color(Palette.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); - Draw.reset(); - }); - - shootBigSmoke = new Effect(17f, e -> { - Draw.color(Palette.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); - }); - - Draw.reset(); - }); - - shootBigSmoke2 = new Effect(18f, e -> { - Draw.color(Palette.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); - }); - - Draw.reset(); - }); - - shootSmallFlame = new Effect(30f, e -> { - Draw.color(Palette.lightFlame, Palette.darkFlame, Color.GRAY, e.fin()); - - Angles.randLenVectors(e.id, 8, e.finpow() * 36f, e.rotation, 10f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, 0.65f + e.fout() * 1.5f); - }); - - Draw.reset(); - }); - - shootLiquid = new Effect(40f, e -> { - Draw.color(e.color, Color.WHITE, e.fout() / 6f + Mathf.randomSeedRange(e.id, 0.1f)); - - Angles.randLenVectors(e.id, 6, e.finpow() * 60f, e.rotation, 11f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, 0.5f + e.fout() * 2.5f); - }); - - Draw.reset(); - }); - - shellEjectSmall = new GroundEffect(30f, 400f, e -> { - Draw.color(Palette.lightOrange, Color.LIGHT_GRAY, Palette.lightishGray, e.fin()); - float rot = Math.abs(e.rotation) + 90f; - - int i = Mathf.sign(e.rotation); - - float len = (2f + e.finpow() * 6f) * i; - float lr = rot + e.fin() * 30f * i; - Draw.rect("white", - e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), - e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), - 1f, 2f, rot + e.fin() * 50f * i); - - Draw.color(); - }); - - shellEjectMedium = new GroundEffect(34f, 400f, e -> { - Draw.color(Palette.lightOrange, Color.LIGHT_GRAY, Palette.lightishGray, e.fin()); - float rot = e.rotation + 90f; - for(int i : Mathf.signs){ - float len = (2f + e.finpow() * 10f) * i; - float lr = rot + e.fin() * 20f * i; - Draw.rect("casing", - e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), - e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), - 2f, 3f, rot); - } - - Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin()); - - for(int i : Mathf.signs){ - Angles.randLenVectors(e.id, 4, 1f + e.finpow() * 11f, e.rotation + 90f * i, 20f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 1.5f); - }); - } - - Draw.color(); - }); - - shellEjectBig = new GroundEffect(22f, 400f, e -> { - Draw.color(Palette.lightOrange, Color.LIGHT_GRAY, Palette.lightishGray, e.fin()); - float rot = e.rotation + 90f; - for(int i : Mathf.signs){ - float len = (4f + e.finpow() * 8f) * i; - float lr = rot + Mathf.randomSeedRange(e.id + i + 6, 20f * e.fin()) * i; - Draw.rect("casing", - e.x + Angles.trnsx(lr, len) + Mathf.randomSeedRange(e.id + i + 7, 3f * e.fin()), - e.y + Angles.trnsy(lr, len) + Mathf.randomSeedRange(e.id + i + 8, 3f * e.fin()), - 2.5f, 4f, - rot + e.fin() * 30f * i + Mathf.randomSeedRange(e.id + i + 9, 40f * e.fin())); - } - - Draw.color(Color.LIGHT_GRAY); - - for(int i : Mathf.signs){ - Angles.randLenVectors(e.id, 4, -e.finpow() * 15f, e.rotation + 90f * i, 25f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 2f); - }); - } - - Draw.color(); - }); - - lancerLaserShoot = new Effect(21f, e -> { - Draw.color(Palette.lancerLaser); - - for(int i : Mathf.signs){ - Shapes.tri(e.x, e.y, 4f * e.fout(), 29f, e.rotation + 90f * i); - } - - Draw.reset(); - }); - - lancerLaserShootSmoke = new Effect(26f, e -> { - Draw.color(Palette.lancerLaser); - - Angles.randLenVectors(e.id, 7, 80f, e.rotation, 0f, (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), e.fout() * 9f); - }); - - Draw.reset(); - }); - - lancerLaserCharge = new Effect(38f, e -> { - Draw.color(Palette.lancerLaser); - - Angles.randLenVectors(e.id, 2, 1f + 20f * e.fout(), e.rotation, 120f, (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), e.fslope() * 3f + 1f); - }); - - Draw.reset(); - }); - - lancerLaserChargeBegin = new Effect(71f, e -> { - Draw.color(Palette.lancerLaser); - Fill.circle(e.x, e.y, e.fin() * 3f); - - Draw.color(); - Fill.circle(e.x, e.y, e.fin() * 2f); - }); - - lightningCharge = new Effect(38f, e -> { - Draw.color(Palette.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.atan2(x, y)); - }); - - Draw.reset(); - }); - - lightningShoot = new Effect(12f, e -> { - Draw.color(Color.WHITE, Palette.lancerLaser, e.fin()); - Lines.stroke(e.fout() * 1.2f + 0.5f); - - Angles.randLenVectors(e.id, 7, 25f * e.finpow(), e.rotation, 50f, (x, y) -> { - Lines.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), e.fin() * 5f + 2f); - }); - - Draw.reset(); - }); - } -} diff --git a/core/src/io/anuke/mindustry/content/fx/UnitFx.java b/core/src/io/anuke/mindustry/content/fx/UnitFx.java deleted file mode 100644 index 9efcb08699..0000000000 --- a/core/src/io/anuke/mindustry/content/fx/UnitFx.java +++ /dev/null @@ -1,78 +0,0 @@ -package io.anuke.mindustry.content.fx; - -import io.anuke.mindustry.entities.effect.GroundEffectEntity.GroundEffect; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.game.ContentList; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; - -public class UnitFx extends FxList implements ContentList{ - public static Effect vtolHover, unitDrop, unitPickup, unitLand, pickup, healWave, heal, landShock; - - @Override - public void load(){ - - 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()); - 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); - Angles.randLenVectors(e.id, 9, 3 + 20f * e.finpow(), (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.4f); - }); - Draw.reset(); - }); - - unitLand = new GroundEffect(30, e -> { - Draw.color(Palette.lightishGray, e.color, e.rotation); - Angles.randLenVectors(e.id, 6, 17f * e.finpow(), (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.3f); - }); - Draw.reset(); - }); - - unitPickup = new GroundEffect(18, e -> { - Draw.color(Palette.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); - 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); - 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); - 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); - Lines.stroke(e.fout() * 2f); - Lines.poly(e.x, e.y, 10, 2f + e.finpow() * 7f); - Draw.color(); - }); - } -} diff --git a/core/src/io/anuke/mindustry/core/ContentLoader.java b/core/src/io/anuke/mindustry/core/ContentLoader.java index 9f32f06c27..317a6a04bd 100644 --- a/core/src/io/anuke/mindustry/core/ContentLoader.java +++ b/core/src/io/anuke/mindustry/core/ContentLoader.java @@ -1,13 +1,14 @@ package io.anuke.mindustry.core; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.ObjectMap; -import com.badlogic.gdx.utils.ObjectSet; +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.content.blocks.*; -import io.anuke.mindustry.content.bullets.*; -import io.anuke.mindustry.content.fx.*; -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; @@ -20,13 +21,11 @@ import io.anuke.mindustry.game.MappableContent; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.type.Recipe; +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 io.anuke.ucore.function.Consumer; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.ThreadArray; + +import static io.anuke.arc.Core.files; /** * Loads all game content. @@ -42,66 +41,19 @@ public class ContentLoader{ private MappableContent[][] temporaryMapper; private ObjectSet> initialization = new ObjectSet<>(); private ContentList[] content = { - //effects - new BlockFx(), - new BulletFx(), - new EnvironmentFx(), - new ExplosionFx(), new Fx(), - new ShootFx(), - new UnitFx(), - - //items new Items(), - - //status effects new StatusEffects(), - - //liquids new Liquids(), - - //bullets - new ArtilleryBullets(), - new FlakBullets(), - new MissileBullets(), - new StandardBullets(), - new TurretBullets(), - new WeaponBullets(), - - - //ammotypes - new AmmoTypes(), - - //weapons - new Weapons(), - - //mechs + new Bullets(), new Mechs(), - - //units new UnitTypes(), - - //blocks new Blocks(), - new DefenseBlocks(), - new DistributionBlocks(), - new ProductionBlocks(), - new TurretBlocks(), - new DebugBlocks(), - new LiquidBlocks(), - new StorageBlocks(), - new UnitBlocks(), - new PowerBlocks(), - new CraftingBlocks(), - new UpgradeBlocks(), - new OreBlocks(), + new TechTree(), + new Zones(), - //not really a content class, but this makes initialization easier - new ColorMapper(), + //these are not really content classes, but this makes initialization easier new LegacyColorMapper(), - - //recipes - new Recipes(), }; /**Creates all content types.*/ @@ -114,7 +66,7 @@ public class ContentLoader{ registerTypes(); for(ContentType type : ContentType.values()){ - contentMap[type.ordinal()] = new ThreadArray<>(); + contentMap[type.ordinal()] = new Array<>(); contentNameMap[type.ordinal()] = new ObjectMap<>(); } @@ -178,6 +130,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; } @@ -217,7 +185,7 @@ public class ContentLoader{ } if(id >= contentMap[type.ordinal()].size || id < 0){ - throw new RuntimeException("No " + type.name() + " with ID '" + id + "' found!"); + return null; } return (T)contentMap[type.ordinal()].get(id); } @@ -236,14 +204,6 @@ public class ContentLoader{ return (Block) getByID(ContentType.block, id); } - public Array recipes(){ - return getBy(ContentType.recipe); - } - - public Recipe recipe(int id){ - return (Recipe) getByID(ContentType.recipe, id); - } - public Array items(){ return getBy(ContentType.item); } @@ -268,6 +228,10 @@ public class ContentLoader{ return (BulletType) getByID(ContentType.bullet, id); } + public Array zones(){ + return getBy(ContentType.zone); + } + /** * Registers sync IDs for all types of sync entities. * Do not register units here! @@ -280,7 +244,5 @@ public class ContentLoader{ TypeTrait.registerType(Lightning.class, Lightning::new); } - private class ImpendingDoomException extends RuntimeException{ - public ImpendingDoomException(String s){ super(s); } - } + private class ImpendingDoomException extends RuntimeException{ ImpendingDoomException(String s){ super(s); }} } diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index ae61933103..b1f7c806a1 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -1,35 +1,40 @@ package io.anuke.mindustry.core; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; +import io.anuke.arc.ApplicationListener; +import io.anuke.arc.Core; +import io.anuke.arc.Events; +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.TileEntity; +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.game.Unlocks; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.input.DefaultKeybinds; +import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.input.DesktopInput; 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.ItemStack; -import io.anuke.mindustry.type.Recipe; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.ui.dialogs.FloatingDialog; -import io.anuke.ucore.core.*; -import io.anuke.ucore.entities.EntityQuery; -import io.anuke.ucore.modules.Module; -import io.anuke.ucore.util.Atlas; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Strings; -import io.anuke.ucore.util.Timer; +import io.anuke.mindustry.world.Tile; import java.io.IOException; +import static io.anuke.arc.Core.scene; import static io.anuke.mindustry.Vars.*; /** @@ -38,36 +43,36 @@ import static io.anuke.mindustry.Vars.*; * Should not handle any logic-critical state. * This class is not created in the headless server. */ -public class Control extends Module{ +public class Control implements ApplicationListener{ public final Saves saves; - public final Unlocks unlocks; - private Timer timerRPC = new Timer(), timerUnlock = new Timer(); + private Interval timer = new Interval(2); private boolean hiscore = false; private boolean wasPaused = false; private InputHandler[] inputs = {}; - private Throwable error; public Control(){ saves = new Saves(); - unlocks = new Unlocks(); + data = new GlobalData(); - Inputs.useControllers(true); - - Gdx.input.setCatchBackKey(true); + Core.input.setCatch(KeyCode.BACK, true); Effects.setShakeFalloff(10000f); content.initialize(Content::init); - Core.atlas = new Atlas("sprites.atlas"); - Core.atlas.setErrorRegion("error"); + Core.atlas = new TextureAtlas("sprites/sprites.atlas"); + Draw.scl = 1f / Core.atlas.find("scale_marker").getWidth(); content.initialize(Content::load); - unlocks.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."); + } - DefaultKeybinds.load(); + data.load(); - Settings.defaultList( + Core.settings.setAppName(appName); + Core.settings.defaults( "ip", "localhost", "color-0", Color.rgba8888(playerColors[8]), "color-1", Color.rgba8888(playerColors[11]), @@ -77,15 +82,13 @@ public class Control extends Module{ "lastBuild", 0 ); - KeyBinds.load(); - addPlayer(0); saves.load(); Events.on(StateChangeEvent.class, event -> { if((event.from == State.playing && event.to == State.menu) || (event.from == State.menu && event.to != State.menu)){ - Timers.runTask(5f, Platform.instance::updateRPC); + Time.runTask(5f, Platform.instance::updateRPC); } }); @@ -97,9 +100,9 @@ public class Control extends Module{ state.set(State.playing); }); - Events.on(WorldLoadGraphicsEvent.class, event -> { + Events.on(WorldLoadEvent.class, event -> { if(mobile){ - Gdx.app.postRunnable(() -> Core.camera.position.set(players[0].x, players[0].y, 0)); + Core.app.post(() -> Core.camera.position.set(players[0])); } }); @@ -113,46 +116,61 @@ public class Control extends Module{ saves.resetSave(); }); - Events.on(WaveEvent.class, event -> { - - int last = Settings.getInt("hiscore" + world.getMap().name, 0); - - if(state.wave > last && !state.mode.infiniteResources && !state.mode.disableWaveTimer && world.getSector() == null){ - Settings.putInt("hiscore" + world.getMap().name, state.wave); - Settings.save(); - hiscore = true; - } - - Platform.instance.updateRPC(); - }); + //todo high scores for custom maps, as well as other statistics Events.on(GameOverEvent.class, event -> { - //delete saves for game-over sectors - if(world.getSector() != null && world.getSector().hasSave()){ - world.getSector().getSave().delete(); - } - - threads.runGraphics(() -> { - Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); - //the restart dialog can show info for any number of scenarios - Call.onGameOver(event.winner); - }); - }); - - //autohost for pvp sectors - Events.on(WorldLoadEvent.class, event -> { - if(state.mode.isPvp && !Net.active()){ - try{ - Net.host(port); - players[0].isAdmin = true; - }catch(IOException e){ - ui.showError(Bundles.format("text.server.error", Strings.parseException(e, false))); - threads.runDelay(() -> state.set(State.menu)); + state.stats.wavesLasted = state.wave; + Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); + //the restart dialog can show info for any number of scenarios + Call.onGameOver(event.winner); + if(state.rules.zone != -1){ + //remove zone save on game over + if(saves.getZoneSlot() != null){ + saves.getZoneSlot().delete(); } } }); - Events.on(WorldLoadEvent.class, event -> threads.runGraphics(() -> Events.fire(new WorldLoadGraphicsEvent()))); + //autohost for pvp sectors + Events.on(WorldLoadEvent.class, event -> { + if(state.rules.pvp && !Net.active()){ + try{ + Net.host(port); + players[0].isAdmin = true; + }catch(IOException e){ + ui.showError(Core.bundle.format("server.error", Strings.parseException(e, false))); + Core.app.post(() -> state.set(State.menu)); + } + } + }); + + Events.on(UnlockEvent.class, e -> ui.hudfrag.showUnlock(e.content)); + + Events.on(BlockBuildEndEvent.class, e -> { + if(e.team == players[0].getTeam()){ + if(e.breaking){ + state.stats.buildingsDeconstructed++; + }else{ + state.stats.buildingsBuilt ++; + } + } + }); + + Events.on(BlockDestroyEvent.class, e -> { + if(e.tile.getTeam() == players[0].getTeam()){ + state.stats.buildingsDestroyed ++; + } + }); + + Events.on(UnitDestroyEvent.class, e -> { + if(e.unit.getTeam() != players[0].getTeam()){ + state.stats.enemyUnitsDestroyed ++; + } + }); + + Events.on(ZoneCompleteEvent.class, e -> { + ui.hudfrag.showToast(Core.bundle.get("zone.complete")); + }); } public void addPlayer(int index){ @@ -171,9 +189,9 @@ public class Control extends Module{ Player setTo = (index == 0 ? null : players[0]); Player player = new Player(); - player.name = Settings.getString("name"); + player.name = Core.settings.getString("name"); player.mech = mobile ? Mechs.starterMobile : Mechs.starterDesktop; - player.color.set(Settings.getInt("color-" + index)); + player.color.set(Core.settings.getInt("color-" + index)); player.isLocal = true; player.playerIndex = index; player.isMobile = mobile; @@ -196,7 +214,7 @@ public class Control extends Module{ } inputs[index] = input; - Inputs.addProcessor(input); + Core.input.addProcessor(input); } public void removePlayer(){ @@ -212,17 +230,14 @@ public class Control extends Module{ System.arraycopy(oldi, 0, inputs, 0, inputs.length); } - public void setError(Throwable error){ - this.error = error; - } - public InputHandler input(int index){ return inputs[index]; } - public void playMap(Map map){ - ui.loadLogic(() -> { + public void playMap(Map map, Rules rules){ + ui.loadAnd(() -> { logic.reset(); + state.rules = rules; world.loadMap(map); logic.play(); }); @@ -232,35 +247,8 @@ public class Control extends Module{ return hiscore; } - private void checkUnlockableBlocks(){ - TileEntity entity = players[0].getClosestCore(); - - if(entity == null) return; - - entity.items.forEach((item, amount) -> unlocks.unlockContent(item)); - - if(players[0].inventory.hasItem()){ - unlocks.unlockContent(players[0].inventory.getItem().item); - } - - outer: - for(int i = 0; i < content.recipes().size; i ++){ - Recipe recipe = content.recipes().get(i); - if(!recipe.isHidden() && recipe.requirements != null){ - for(ItemStack stack : recipe.requirements){ - if(!entity.items.has(stack.item, Math.min((int) (stack.amount * unlockResourceScaling), 2000))) continue outer; - } - - if(unlocks.unlockContent(recipe)){ - ui.hudfrag.showUnlock(recipe); - } - } - } - } - @Override public void dispose(){ - Platform.instance.onGameExit(); content.dispose(); Net.dispose(); ui.editor.dispose(); @@ -287,16 +275,16 @@ public class Control extends Module{ Platform.instance.updateRPC(); - if(!Settings.getBool("4.0-warning-2", false)){ + if(!Core.settings.getBool("4.0-warning-2", false)){ - Timers.run(5f, () -> { - FloatingDialog dialog = new FloatingDialog("[accent]WARNING![]"); - dialog.buttons().addButton("$text.ok", () -> { + Time.run(5f, () -> { + FloatingDialog dialog = new FloatingDialog("WARNING!"); + dialog.buttons.addButton("$ok", () -> { dialog.hide(); - Settings.putBool("4.0-warning-2", true); - Settings.save(); + Core.settings.put("4.0-warning-2", true); + Core.settings.save(); }).size(100f, 60f); - dialog.content().add("Reminder: The beta 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 4.0 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); @@ -305,65 +293,59 @@ public class Control extends Module{ } } - /** Called from main logic thread.*/ - public void runUpdateLogic(){ - if(!state.is(State.menu)){ - renderer.minimap.updateUnitArray(); - } - } - @Override public void update(){ - if(error != null){ - throw new RuntimeException(error); - } - saves.update(); for(InputHandler inputHandler : inputs){ inputHandler.updateController(); } + //autosave global data every second if it's modified + if(timer.get(1, 60)){ + data.checkSave(); + } + if(!state.is(State.menu)){ for(InputHandler input : inputs){ input.update(); } - //auto-update rpc every 5 seconds - if(timerRPC.get(60 * 5)){ - Platform.instance.updateRPC(); - } - - //check unlocks every 2 seconds - if(!state.mode.infiniteResources && timerUnlock.get(120)){ - checkUnlockableBlocks(); - - //save if the unlocks changed - if(unlocks.isDirty()){ - unlocks.save(); + 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); + } + } } } - if(Inputs.keyTap("pause") && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){ + //auto-update rpc every 5 seconds + if(timer.get(0, 60 * 5)){ + Platform.instance.updateRPC(); + } + + if(Core.input.keyTap(Binding.pause) && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){ state.set(state.is(State.playing) ? State.paused : State.playing); } - if(Inputs.keyTap("menu") && !ui.restart.isShown()){ + if(Core.input.keyTap(Binding.menu) && !ui.restart.isShown()){ if(ui.chatfrag.chatOpen()){ ui.chatfrag.hide(); - }else if(!ui.paused.isShown() && !ui.hasDialog()){ + }else if(!ui.paused.isShown() && !scene.hasDialog()){ ui.paused.show(); state.set(State.paused); } } - if(!mobile && Inputs.keyTap("screenshot") && !ui.chatfrag.chatOpen()){ + if(!mobile && Core.input.keyTap(Binding.screenshot) && !(scene.getKeyboardFocus() instanceof TextField) && !ui.chatfrag.chatOpen()){ renderer.takeMapScreenshot(); } }else{ if(!state.isPaused()){ - Timers.update(); + Time.update(); } } } diff --git a/core/src/io/anuke/mindustry/core/GameState.java b/core/src/io/anuke/mindustry/core/GameState.java index 96a36fad8a..fd521bf2c0 100644 --- a/core/src/io/anuke/mindustry/core/GameState.java +++ b/core/src/io/anuke/mindustry/core/GameState.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.core; -import io.anuke.mindustry.game.Difficulty; +import io.anuke.arc.Events; import io.anuke.mindustry.game.EventType.StateChangeEvent; -import io.anuke.mindustry.game.GameMode; +import io.anuke.mindustry.game.Rules; +import io.anuke.mindustry.game.Stats; import io.anuke.mindustry.game.Teams; import io.anuke.mindustry.net.Net; -import io.anuke.ucore.core.Events; import static io.anuke.mindustry.Vars.unitGroups; import static io.anuke.mindustry.Vars.waveTeam; @@ -16,11 +16,11 @@ public class GameState{ /**Wave countdown in ticks.*/ public float wavetime; /**Whether the game is in game over state.*/ - public boolean gameOver = false; - /**The current game mode.*/ - public GameMode mode = GameMode.waves; - /**The current difficulty for wave modes.*/ - public Difficulty difficulty = Difficulty.normal; + public boolean gameOver = false, launched = false; + /**The current game rules.*/ + public Rules rules = new Rules(); + /**Statistics for this save/game. Displayed after game over.*/ + public Stats stats = new Stats(); /**Team data. Gets reset every new game.*/ public Teams teams = new Teams(); /**Number of enemies in the game; only used clientside in servers.*/ @@ -38,7 +38,7 @@ public class GameState{ } public boolean isPaused(){ - return is(State.paused) && !Net.active(); + return (is(State.paused) && !Net.active()) || gameOver; } 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 5f7035cb7e..28a4e44461 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -1,27 +1,23 @@ package io.anuke.mindustry.core; -import com.badlogic.gdx.utils.Array; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.Vars; +import io.anuke.arc.ApplicationListener; +import io.anuke.arc.Events; +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.GameMode; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.game.Teams; -import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.mindustry.gen.Call; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Recipe; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.Entities; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.EntityQuery; -import io.anuke.ucore.modules.Module; import static io.anuke.mindustry.Vars.*; @@ -33,12 +29,12 @@ import static io.anuke.mindustry.Vars.*; *

* This class should not call any outside methods to change state of modules, but instead fire events. */ -public class Logic extends Module{ +public class Logic implements ApplicationListener{ public Logic(){ - Events.on(TileChangeEvent.class, event -> { - if(event.tile.getTeam() == defaultTeam && Recipe.getByResult(event.tile.block()) != null){ - handleContent(Recipe.getByResult(event.tile.block())); + Events.on(WaveEvent.class, event -> { + if(world.isZone()){ + data.updateWaveScore(world.getZone(), state.wave); } }); } @@ -54,38 +50,28 @@ public class Logic extends Module{ /**Handles the event of content being used by either the player or some block.*/ public void handleContent(UnlockableContent content){ - if(world.getSector() != null){ - world.getSector().currentMission().onContentUsed(content); - } - if(!headless){ - control.unlocks.unlockContent(content); + data.unlockContent(content); } } public void play(){ state.set(State.playing); - state.wavetime = wavespace * state.difficulty.timeScaling * 2; - - for(Tile tile : state.teams.get(defaultTeam).cores){ - if(world.getSector() != null){ - Array items = world.getSector().startingItems; - for(ItemStack stack : items){ - tile.entity.items.add(stack.item, stack.amount); - } - } - } + state.wavetime = state.rules.waveSpacing * 2; //grace period of 2x wave time before game starts Events.fire(new PlayEvent()); } public void reset(){ state.wave = 1; - state.wavetime = wavespace * state.difficulty.timeScaling; - state.gameOver = false; + state.wavetime = state.rules.waveSpacing; + state.gameOver = state.launched = false; state.teams = new Teams(); + state.rules = new Rules(); + state.rules.spawns = Waves.getDefaultSpawns(); + state.stats = new Stats(); - Timers.clear(); + Time.clear(); Entities.clear(); TileEntity.sleepingEntities = 0; @@ -95,16 +81,16 @@ public class Logic extends Module{ public void runWave(){ world.spawner.spawnEnemies(); state.wave++; - state.wavetime = wavespace * state.difficulty.timeScaling; + state.wavetime = state.rules.waveSpacing; Events.fire(new WaveEvent()); } private void checkGameOver(){ - if(!state.mode.isPvp && state.teams.get(defaultTeam).cores.size == 0 && !state.gameOver){ + if(!state.rules.pvp && state.teams.get(defaultTeam).cores.size == 0 && !state.gameOver){ state.gameOver = true; Events.fire(new GameOverEvent(waveTeam)); - }else if(state.mode.isPvp){ + }else if(state.rules.pvp){ Team alive = null; for(Team team : Team.all){ @@ -123,74 +109,50 @@ public class Logic extends Module{ } } - private void updateSectors(){ - if(world.getSector() == null || state.gameOver) return; + @Remote(called = Loc.both) + public static void launchZone(){ + Effects.effect(Fx.launchFull, 0, 0); - world.getSector().currentMission().update(); - - //check unlocked sectors - while(!world.getSector().complete && world.getSector().currentMission().isComplete()){ - Call.onMissionFinish(world.getSector().completedMissions); + for(Tile tile : new ObjectSetIterator<>(state.teams.get(defaultTeam).cores)){ + Effects.effect(Fx.launch, tile); } - //check if all assigned missions are complete - if(!world.getSector().complete && world.getSector().completedMissions >= world.getSector().missions.size){ - Call.onSectorComplete(); - } + 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) / playerGroup.size()); + } + world.removeBlock(tile); + } + state.launched = true; + }); } @Remote(called = Loc.both) public static void onGameOver(Team winner){ - threads.runGraphics(() -> ui.restart.show(winner)); + ui.restart.show(winner); netClient.setQuiet(); } - @Remote(called = Loc.server) - public static void onMissionFinish(int index){ - world.getSector().missions.get(index).onComplete(); - world.getSector().completedMissions = index + 1; - - state.mode = world.getSector().currentMission().getMode(); - world.getSector().currentMission().onBegin(); - world.sectors.save(); - } - - @Remote(called = Loc.server) - public static void onSectorComplete(){ - state.mode = GameMode.victory; - - world.sectors.completeSector(world.getSector().x, world.getSector().y); - world.sectors.save(); - - if(!headless && !Net.client()){ - ui.missions.show(world.getSector()); - } - - Events.fire(new SectorCompleteEvent()); - } - @Override public void update(){ - if(Vars.control != null){ - control.runUpdateLogic(); - } - if(!state.is(State.menu)){ if(!state.isPaused()){ - Timers.update(); + Time.update(); - if(!state.mode.disableWaveTimer && !state.mode.disableWaves && !state.gameOver){ - state.wavetime -= Timers.delta(); + if(state.rules.waves && state.rules.waveTimer && !state.gameOver){ + state.wavetime = Math.max(state.wavetime - Time.delta(), 0); } - if(!Net.client() && state.wavetime <= 0 && !state.mode.disableWaves){ + if(!Net.client() && state.wavetime <= 0 && state.rules.waves){ runWave(); } - if(!Entities.defaultGroup().isEmpty()) - throw new RuntimeException("Do not add anything to the default group!"); + if(!Entities.defaultGroup().isEmpty()){ + throw new IllegalArgumentException("Do not add anything to the default group!"); + } if(!headless){ Entities.update(effectGroup); @@ -226,7 +188,6 @@ public class Logic extends Module{ } if(!Net.client() && !world.isInvalidMap()){ - updateSectors(); checkGameOver(); } } diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index bf124f9be2..3a47eee4ff 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -1,17 +1,23 @@ package io.anuke.mindustry.core; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.utils.Base64Coder; -import com.badlogic.gdx.utils.IntSet; -import com.badlogic.gdx.utils.TimeUtils; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.PacketPriority; import io.anuke.annotations.Annotations.Remote; 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.mindustry.entities.Entities; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.util.Interval; +import io.anuke.arc.util.Log; +import io.anuke.arc.util.Time; +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.type.Player; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; import io.anuke.mindustry.entities.traits.SyncTrait; import io.anuke.mindustry.entities.traits.TypeTrait; @@ -25,16 +31,6 @@ import io.anuke.mindustry.net.Packets.*; import io.anuke.mindustry.net.ValidateException; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.modules.ItemModule; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.Entities; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.io.ReusableByteArrayInputStream; -import io.anuke.ucore.modules.Module; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Timer; import java.io.DataInputStream; import java.io.IOException; @@ -43,12 +39,12 @@ import java.util.zip.InflaterInputStream; import static io.anuke.mindustry.Vars.*; -public class NetClient extends Module{ +public class NetClient implements ApplicationListener{ private final static float dataTimeout = 60 * 18; private final static float playerSyncTime = 2; public final static float viewScale = 2f; - private Timer timer = new Timer(5); + private Interval timer = new Interval(5); /**Whether the client is currently connecting.*/ private boolean connecting = false; /**If true, no message will be shown on disconnect.*/ @@ -58,16 +54,6 @@ public class NetClient extends Module{ /**Last sent client snapshot ID.*/ private int lastSent; - /**Last snapshot ID recieved.*/ - private int lastSnapshotBaseID = -1; - - /**Current snapshot that is being built from chinks.*/ - private byte[] currentSnapshot; - /**Counter of how many chunks have been recieved.*/ - private int recievedChunkCounter; - /**ID of snapshot that is currently being constructed.*/ - private int currentSnapshotID = -1; - /**List of entities that were removed, and need not be added while syncing.*/ private IntSet removed = new IntSet(); /**Byte stream for reading in snapshots.*/ @@ -84,7 +70,7 @@ public class NetClient extends Module{ reset(); ui.loadfrag.hide(); - ui.loadfrag.show("$text.connecting.data"); + ui.loadfrag.show("$connecting.data"); ui.loadfrag.setButton(() -> { ui.loadfrag.hide(); @@ -102,7 +88,7 @@ public class NetClient extends Module{ c.uuid = Platform.instance.getUUID(); if(c.uuid == null){ - ui.showError("$text.invalidid"); + ui.showError("$invalidid"); ui.loadfrag.hide(); disconnectQuietly(); return; @@ -114,11 +100,11 @@ public class NetClient extends Module{ Net.handleClient(Disconnect.class, packet -> { if(quiet) return; - Timers.runTask(3f, ui.loadfrag::hide); + Time.runTask(3f, ui.loadfrag::hide); state.set(State.menu); - ui.showError("$text.disconnect"); + ui.showError("$disconnect"); connecting = false; Platform.instance.updateRPC(); @@ -168,21 +154,19 @@ public class NetClient extends Module{ netClient.disconnectQuietly(); state.set(State.menu); - threads.runGraphics(() -> { - if(!reason.quiet){ - if(reason.extraText() != null){ - ui.showText(reason.toString(), reason.extraText()); - }else{ - ui.showText("$text.disconnect", reason.toString()); - } + if(!reason.quiet){ + if(reason.extraText() != null){ + ui.showText(reason.toString(), reason.extraText()); + }else{ + ui.showText("$disconnect", reason.toString()); } - ui.loadfrag.hide(); - }); + } + ui.loadfrag.hide(); } @Remote(variants = Variant.both) public static void onInfoMessage(String message){ - threads.runGraphics(() -> ui.showText("", message)); + ui.showText("", message); } @Remote(variants = Variant.both) @@ -193,15 +177,13 @@ public class NetClient extends Module{ ui.chatfrag.clearMessages(); Net.setClientLoaded(false); - threads.runGraphics(() -> { - ui.loadfrag.show("$text.connecting.data"); + ui.loadfrag.show("$connecting.data"); - ui.loadfrag.setButton(() -> { - ui.loadfrag.hide(); - netClient.connecting = false; - netClient.quiet = true; - Net.disconnect(); - }); + ui.loadfrag.setButton(() -> { + ui.loadfrag.hide(); + netClient.connecting = false; + netClient.quiet = true; + Net.disconnect(); }); } @@ -217,97 +199,11 @@ public class NetClient extends Module{ } @Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true) - public static void onSnapshot(byte[] chunk, int snapshotID, short chunkID, int totalLength, int uncompressedLength){ - int totalChunks = Mathf.ceil((float) totalLength / NetServer.maxSnapshotSize); - - if(NetServer.debugSnapshots) - Log.info("Recieved snapshot: len {0} ID {1} chunkID {2} / "+totalChunks+" totalLength {3} bclient-base {4}", chunk.length, snapshotID, chunkID, totalLength, netClient.lastSnapshotBaseID); - - //skip snapshot IDs that have already been recieved OR snapshots that are too far in front - if(snapshotID < netClient.lastSnapshotBaseID){ - if(NetServer.debugSnapshots) Log.info("//SKIP SNAPSHOT"); - return; - } - + public static void onEntitySnapshot(byte groupID, short amount, short dataLen, byte[] data){ try{ - byte[] snapshot; - - //total length exceeds that needed to hold one snapshot, therefore, it is split into chunks - if(totalLength > NetServer.maxSnapshotSize){ - //total amount of chunks to recieve - - //reset status when a new snapshot sending begins - if(netClient.currentSnapshotID != snapshotID || netClient.currentSnapshot == null){ - netClient.currentSnapshotID = snapshotID; - netClient.currentSnapshot = new byte[totalLength]; - netClient.recievedChunkCounter = 0; - } - - netClient.recievedChunkCounter++; //update recieved status - //copy the recieved bytes into the holding array - System.arraycopy(chunk, 0, netClient.currentSnapshot, chunkID * NetServer.maxSnapshotSize, - Math.min(NetServer.maxSnapshotSize, totalLength - chunkID * NetServer.maxSnapshotSize)); - - //when all chunks have been recieved, begin - if(netClient.recievedChunkCounter >= totalChunks && netClient.currentSnapshot != null){ - snapshot = netClient.currentSnapshot; - }else{ - return; - } - }else{ - snapshot = chunk; - } - - if(NetServer.debugSnapshots) - Log.info("Finished recieving snapshot ID {0} length {1}", snapshotID, chunk.length); - - byte[] result = Net.decompressSnapshot(snapshot, uncompressedLength); - int length = result.length; - - netClient.lastSnapshotBaseID = snapshotID; - - //set stream bytes to begin snapshot reading - netClient.byteStream.setBytes(result, 0, length); - - //get data input for reading from the stream + netClient.byteStream.setBytes(Net.decompressSnapshot(data, dataLen)); DataInputStream input = netClient.dataStream; - netClient.readSnapshot(input); - - //confirm that snapshot has been recieved - netClient.lastSnapshotBaseID = snapshotID; - }catch(Exception e){ - throw new RuntimeException(e); - } - } - - public void readSnapshot(DataInputStream input) throws IOException{ - - //read wave info - state.wavetime = input.readFloat(); - state.wave = input.readInt(); - state.enemies = input.readInt(); - - byte cores = input.readByte(); - for(int i = 0; i < cores; i++){ - int pos = input.readInt(); - Tile tile = world.tile(pos); - if(tile != null && tile.entity != null){ - tile.entity.items.read(input); - }else{ - new ItemModule().read(input); - } - } - - long timestamp = input.readLong(); - - byte totalGroups = input.readByte(); - //for each group... - for(int i = 0; i < totalGroups; i++){ - //read group info - byte groupID = input.readByte(); - short amount = input.readShort(); - EntityGroup group = Entities.getGroup(groupID); //go through each entity @@ -328,13 +224,41 @@ public class NetClient extends Module{ } //read the entity - entity.read(input, timestamp); + entity.read(input); if(add){ entity.add(); netClient.addRemovedEntity(entity.getID()); } } + }catch(IOException e){ + throw new RuntimeException(e); + } + } + + @Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true) + public static void onStateSnapshot(float waveTime, int wave, int enemies, short coreDataLen, byte[] coreData){ + try{ + state.wavetime = waveTime; + state.wave = wave; + state.enemies = enemies; + + netClient.byteStream.setBytes(Net.decompressSnapshot(coreData, coreDataLen)); + DataInputStream input = netClient.dataStream; + + byte cores = input.readByte(); + for(int i = 0; i < cores; i++){ + int pos = input.readInt(); + Tile tile = world.tile(pos); + if(tile != null && tile.entity != null){ + tile.entity.items.read(input); + }else{ + new ItemModule().read(input); + } + } + + }catch(IOException e){ + throw new RuntimeException(e); } } @@ -347,12 +271,12 @@ public class NetClient extends Module{ }else if(!connecting){ Net.disconnect(); }else{ //...must be connecting - timeoutTime += Timers.delta(); + timeoutTime += Time.delta(); if(timeoutTime > dataTimeout){ Log.err("Failed to load data!"); ui.loadfrag.hide(); quiet = true; - ui.showError("$text.disconnect.data"); + ui.showError("$disconnect.data"); Net.disconnect(); timeoutTime = 0f; } @@ -369,8 +293,8 @@ public class NetClient extends Module{ ui.loadfrag.hide(); ui.join.hide(); Net.setClientLoaded(true); - Gdx.app.postRunnable(Call::connectConfirm); - Timers.runTask(40f, Platform.instance::updateRPC); + Core.app.post(Call::connectConfirm); + Time.runTask(40f, Platform.instance::updateRPC); } private void reset(){ @@ -380,9 +304,6 @@ public class NetClient extends Module{ connecting = true; quiet = false; lastSent = 0; - currentSnapshot = null; - currentSnapshotID = -1; - lastSnapshotBaseID = -1; Entities.clear(); ui.chatfrag.clearMessages(); @@ -416,19 +337,21 @@ public class NetClient extends Module{ Player player = players[0]; BuildRequest[] requests; + //limit to 10 to prevent buffer overflows + int usedRequests = Math.min(player.getPlaceQueue().size, 10); - requests = new BuildRequest[player.getPlaceQueue().size]; - for(int i = 0; i < requests.length; i++){ + requests = new BuildRequest[usedRequests]; + for(int i = 0; i < usedRequests; i++){ requests[i] = player.getPlaceQueue().get(i); } - Call.onClientShapshot(lastSent++, TimeUtils.millis(), player.x, player.y, + Call.onClientShapshot(lastSent++, player.x, player.y, player.pointerX, player.pointerY, player.rotation, player.baseRotation, - player.getVelocity().x, player.getVelocity().y, + player.velocity().x, player.velocity().y, player.getMineTile(), player.isBoosting, player.isShooting, requests, Core.camera.position.x, Core.camera.position.y, - Core.camera.viewportWidth * Core.camera.zoom * viewScale, Core.camera.viewportHeight * Core.camera.zoom * viewScale); + Core.camera.width * viewScale, Core.camera.height * viewScale); } if(timer.get(1, 60)){ @@ -437,14 +360,14 @@ public class NetClient extends Module{ } String getUsid(String ip){ - if(Settings.getString("usid-" + ip, null) != null){ - return Settings.getString("usid-" + ip, null); + if(Core.settings.getString("usid-" + ip, null) != null){ + return Core.settings.getString("usid-" + ip, null); }else{ byte[] bytes = new byte[8]; new Random().nextBytes(bytes); String result = new String(Base64Coder.encode(bytes)); - Settings.putString("usid-" + ip, result); - Settings.save(); + Core.settings.put("usid-" + ip, result); + Core.settings.save(); return result; } } diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index a88ea19301..7e0cdbef72 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -1,19 +1,30 @@ package io.anuke.mindustry.core; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.Colors; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.IntMap; -import com.badlogic.gdx.utils.ObjectSet; -import com.badlogic.gdx.utils.TimeUtils; 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.collection.Array; +import io.anuke.arc.collection.IntMap; +import io.anuke.arc.collection.ObjectSet; +import io.anuke.mindustry.entities.Entities; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.EntityQuery; +import io.anuke.mindustry.entities.traits.Entity; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.Colors; +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.Log; +import io.anuke.arc.util.Structs; +import io.anuke.arc.util.Time; +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.Blocks; +import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; import io.anuke.mindustry.entities.traits.SyncTrait; import io.anuke.mindustry.game.EventType.WorldLoadEvent; @@ -21,35 +32,25 @@ import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.gen.RemoteReadServer; -import io.anuke.mindustry.net.*; +import io.anuke.mindustry.net.Administration; import io.anuke.mindustry.net.Administration.PlayerInfo; +import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.NetConnection; +import io.anuke.mindustry.net.NetworkIO; import io.anuke.mindustry.net.Packets.*; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.Entities; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.EntityQuery; -import io.anuke.ucore.entities.trait.Entity; -import io.anuke.ucore.io.ByteBufferOutput; -import io.anuke.ucore.io.CountableByteArrayOutputStream; -import io.anuke.ucore.modules.Module; -import io.anuke.ucore.util.Structs; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.Mathf; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.nio.ByteBuffer; -import java.util.Arrays; import java.util.zip.DeflaterOutputStream; import static io.anuke.mindustry.Vars.*; -public class NetServer extends Module{ - public final static int maxSnapshotSize = 2047; +public class NetServer implements ApplicationListener{ + public final static int maxSnapshotSize = 430; public final static boolean debugSnapshots = false; public final static float maxSnapshotDelay = 200; @@ -122,7 +123,7 @@ public class NetServer extends Module{ return; } - if(TimeUtils.millis() - info.lastKicked < kickDuration){ + if(Time.millis() - info.lastKicked < kickDuration){ kick(id, KickReason.recentKick); return; } @@ -155,7 +156,7 @@ public class NetServer extends Module{ 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; @@ -192,7 +193,8 @@ public class NetServer extends Module{ return; } - if(state.mode.isPvp){ + //playing in pvp mode automatically assigns players to teams + if(state.rules.pvp){ //find team with minimum amount of players and auto-assign player to that. Team min = Structs.findMin(Team.all, team -> { if(state.teams.isActive(team)){ @@ -224,45 +226,6 @@ public class NetServer extends Module{ }); } - /** Sends a raw byte[] snapshot to a client, splitting up into chunks when needed.*/ - private static void sendSplitSnapshot(int userid, byte[] bytes, int snapshotID, int uncompressedLength){ - if(bytes.length < maxSnapshotSize){ - scheduleSnapshot(() -> Call.onSnapshot(userid, bytes, snapshotID, (short) 0, bytes.length, uncompressedLength)); - }else{ - int remaining = bytes.length; - int offset = 0; - int chunkid = 0; - while(remaining > 0){ - int used = Math.min(remaining, maxSnapshotSize); - byte[] toSend; - //re-use sent byte arrays when possible - if(used == maxSnapshotSize && !debugSnapshots){ - toSend = reusableSnapArray; - System.arraycopy(bytes, offset, toSend, 0, Math.min(offset + maxSnapshotSize, bytes.length) - offset); - }else{ - toSend = Arrays.copyOfRange(bytes, offset, Math.min(offset + maxSnapshotSize, bytes.length)); - } - - short fchunk = (short)chunkid; - scheduleSnapshot(() -> Call.onSnapshot(userid, toSend, snapshotID, fchunk, bytes.length, uncompressedLength)); - - remaining -= used; - offset += used; - chunkid++; - } - } - } - - private static void scheduleSnapshot(Runnable r){ - if(debugSnapshots){ - if(!Mathf.chance(snapshotDropchance)){ - Timers.run(maxSnapshotDelay / 1000f * 60f, r); - } - }else{ - r.run(); - } - } - public void sendWorldData(Player player, int clientID){ ByteArrayOutputStream stream = new ByteArrayOutputStream(); DeflaterOutputStream def = new DeflaterOutputStream(stream); @@ -271,7 +234,7 @@ public class NetServer extends Module{ 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){ @@ -296,7 +259,7 @@ public class NetServer extends Module{ @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, @@ -309,16 +272,16 @@ public class NetServer extends Module{ 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 = TimeUtils.millis() - 16; + if(connection.lastRecievedClientTime == 0) connection.lastRecievedClientTime = Time.millis() - 16; connection.viewX = viewX; connection.viewY = viewY; connection.viewWidth = viewWidth; connection.viewHeight = viewHeight; - long elapsed = TimeUtils.timeSinceMillis(connection.lastRecievedClientTime); + long elapsed = Time.timeSinceMillis(connection.lastRecievedClientTime); float maxSpeed = boosting && !player.mech.flying ? player.mech.boostSpeed : player.mech.speed; float maxMove = elapsed / 1000f * 60f * Math.min(compound(maxSpeed, player.mech.drag) * 1.25f, player.mech.maxSpeed * 1.1f); @@ -333,7 +296,7 @@ public class NetServer extends Module{ //auto-skip done requests if(req.breaking && world.tile(req.x, req.y).block() == Blocks.air){ continue; - }else if(!req.breaking && world.tile(req.x, req.y).block() == req.recipe.result && (!req.recipe.result.rotate || world.tile(req.x, req.y).getRotation() == req.rotation)){ + }else if(!req.breaking && world.tile(req.x, req.y).block() == req.block && (!req.block.rotate || world.tile(req.x, req.y).getRotation() == req.rotation)){ continue; } player.getPlaceQueue().addLast(req); @@ -357,7 +320,7 @@ public class NetServer extends Module{ player.y = prevy; newx = x; newy = y; - }else if(Vector2.dst(x, y, newx, newy) > correctDist){ + }else if(Mathf.dst(x, y, newx, newy) > correctDist){ Call.onPositionSet(player.con.id, newx, newy); //teleport and correct position when necessary } @@ -366,24 +329,24 @@ public class NetServer extends Module{ 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.getVelocity().set(xVelocity, yVelocity); //only for visual calculation purposes, doesn't actually update the player + 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; - connection.lastRecievedClientTime = TimeUtils.millis(); + connection.lastRecievedClientTime = Time.millis(); } @Remote(targets = Loc.client, called = Loc.server) 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; } @@ -420,7 +383,7 @@ public class NetServer extends Module{ } public boolean isWaitingForPlayers(){ - if(state.mode.isPvp){ + if(state.rules.pvp){ int used = 0; for(Team t : Team.all){ if(playerGroup.count(p -> p.getTeam() == t) > 0){ @@ -436,8 +399,8 @@ public class NetServer extends Module{ if(!headless && !closing && Net.server() && state.is(State.menu)){ closing = true; - threads.runGraphics(() -> ui.loadfrag.show("$text.server.closing")); - Timers.runTask(5f, () -> { + ui.loadfrag.show("$server.closing"); + Time.runTask(5f, () -> { Net.closeServer(); ui.loadfrag.hide(); closing = false; @@ -469,45 +432,34 @@ public class NetServer extends Module{ if(player != null && (reason == KickReason.kick || reason == KickReason.banned) && player.uuid != null){ PlayerInfo info = admins.getInfo(player.uuid); info.timesKicked++; - info.lastKicked = TimeUtils.millis(); + info.lastKicked = Time.millis(); } Call.onKick(connection, reason); - Timers.runTask(2f, con::close); + Time.runTask(2f, con::close); admins.save(); } - public void writeSnapshot(Player player, DataOutputStream dataStream) throws IOException{ - viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY); - - //write wave datas - dataStream.writeFloat(state.wavetime); - dataStream.writeInt(state.wave); - dataStream.writeInt(state.enemies()); - + public void writeSnapshot(Player player) throws IOException{ + syncStream.reset(); ObjectSet cores = state.teams.get(player.getTeam()).cores; dataStream.writeByte(cores.size); - //write all core inventory data for(Tile tile : cores){ dataStream.writeInt(tile.pos()); tile.entity.items.write(dataStream); } - //write timestamp - dataStream.writeLong(TimeUtils.millis()); + dataStream.close(); + byte[] stateBytes = syncStream.toByteArray(); - int totalGroups = 0; + //write basic state data. + Call.onStateSnapshot(player.con.id, state.wavetime, state.wave, state.enemies, (short)stateBytes.length, Net.compressSnapshot(stateBytes)); - for(EntityGroup group : Entities.getAllGroups()){ - if(!group.isEmpty() && (group.all().get(0) instanceof SyncTrait)) totalGroups++; - } - - //write total amount of serializable groups - dataStream.writeByte(totalGroups); + viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY); //check for syncable groups for(EntityGroup group : Entities.getAllGroups()){ @@ -535,15 +487,32 @@ public class NetServer extends Module{ } } - //write group ID + group size - dataStream.writeByte(group.getID()); - dataStream.writeShort(returnArray.size); + syncStream.reset(); + + int sent = 0; for(Entity entity : returnArray){ //write all entities now dataStream.writeInt(entity.getID()); //write id dataStream.writeByte(((SyncTrait) entity).getTypeID()); //write type ID ((SyncTrait) entity).write(dataStream); //write entity + + sent ++; + + if(syncStream.position() > maxSnapshotSize){ + dataStream.close(); + byte[] syncBytes = syncStream.toByteArray(); + Call.onEntitySnapshot(player.con.id, (byte)group.getID(), (short)sent, (short)syncBytes.length, Net.compressSnapshot(syncBytes)); + sent = 0; + syncStream.reset(); + } + } + + if(sent > 0){ + dataStream.close(); + + byte[] syncBytes = syncStream.toByteArray(); + Call.onEntitySnapshot(player.con.id, (byte)group.getID(), (short)sent, (short)syncBytes.length, Net.compressSnapshot(syncBytes)); } } } @@ -617,21 +586,7 @@ public class NetServer extends Module{ if(!player.timer.get(Player.timerSync, serverSyncTime) || !connection.hasConnected) continue; - //reset stream to begin writing - Timers.mark(); - syncStream.reset(); - - writeSnapshot(player, dataStream); - - dataStream.close(); - - byte[] bytes = syncStream.toByteArray(); - int uncompressed = bytes.length; - bytes = Net.compressSnapshot(bytes); - int snapid = connection.lastSentSnapshotID ++; - - if(debugSnapshots) Log.info("Sent snapshot: {0} bytes.", bytes.length); - sendSplitSnapshot(connection.id, bytes, snapid, uncompressed); + writeSnapshot(player); } }catch(IOException e){ diff --git a/core/src/io/anuke/mindustry/core/Platform.java b/core/src/io/anuke/mindustry/core/Platform.java index 0064c066c3..999c57fa7f 100644 --- a/core/src/io/anuke/mindustry/core/Platform.java +++ b/core/src/io/anuke/mindustry/core/Platform.java @@ -1,15 +1,11 @@ package io.anuke.mindustry.core; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.utils.Base64Coder; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.scene.ui.Dialog; -import io.anuke.ucore.scene.ui.TextField; +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.scene.ui.TextField; +import io.anuke.arc.util.serialization.Base64Coder; import java.util.Random; @@ -28,46 +24,20 @@ public abstract class Platform { if(!mobile) return; //this is mobile only, desktop doesn't need dialogs field.tapped(() -> { - Dialog dialog = new Dialog("", "dialog"); - dialog.setFillParent(true); - dialog.content().top(); - dialog.content().defaults().height(65f); - - TextField[] use = {null}; - - dialog.content().addImageButton("icon-copy", "clear", 16*3, () -> use[0].copy()) - .visible(() -> !use[0].getSelection().isEmpty()).width(65f); - - dialog.content().addImageButton("icon-paste", "clear", 16*3, () -> - use[0].paste(Gdx.app.getClipboard().getContents(), false)) - .visible(() -> Gdx.app.getClipboard() != null && Gdx.app.getClipboard().getContents() != null && !Gdx.app.getClipboard().getContents().isEmpty()).width(65f); - - TextField to = dialog.content().addField(field.getText(), t-> {}).pad(15).width(250f).get(); - to.setMaxLength(maxLength); - to.keyDown(Keys.ENTER, () -> dialog.content().find("okb").fireClick()); - - use[0] = to; - - dialog.content().addButton("$text.ok", () -> { + TextInput input = new TextInput(); + input.text = field.getText(); + input.maxLength = maxLength; + input.accepted = text -> { field.clearText(); - field.appendText(to.getText()); + field.appendText(text); field.change(); - dialog.hide(); - Gdx.input.setOnscreenKeyboardVisible(false); - }).width(90f).name("okb"); - - dialog.show(); - Timers.runTask(1f, () -> { - to.setCursorPosition(to.getText().length()); - Core.scene.setKeyboardFocus(to); - Gdx.input.setOnscreenKeyboardVisible(true); - }); + Core.input.setOnscreenKeyboardVisible(false); + }; + Core.input.getTextInput(input); }); } /**Update discord RPC.*/ public void updateRPC(){} - /**Called when the game is exited.*/ - public void onGameExit(){} /**Open donation dialog. Currently android only.*/ public void openDonations(){} /**Whether donating is supported.*/ @@ -76,13 +46,13 @@ public abstract class Platform { } /**Must be a base64 string 8 bytes in length.*/ public String getUUID(){ - String uuid = Settings.getString("uuid", ""); + String uuid = Core.settings.getString("uuid", ""); if(uuid.isEmpty()){ byte[] result = new byte[8]; new Random().nextBytes(result); uuid = new String(Base64Coder.encode(result)); - Settings.putString("uuid", uuid); - Settings.save(); + Core.settings.put("uuid", uuid); + Core.settings.save(); return uuid; } return uuid; diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index df097fc0f9..cb33334a45 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -1,85 +1,80 @@ package io.anuke.mindustry.core; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.PixmapIO; -import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.BufferUtils; -import com.badlogic.gdx.utils.ScreenUtils; -import com.badlogic.gdx.utils.TimeUtils; -import io.anuke.mindustry.content.fx.Fx; +import io.anuke.arc.ApplicationListener; +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.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.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 io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.entities.EntityDraw; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.impl.EffectEntity; -import io.anuke.ucore.entities.trait.DrawTrait; -import io.anuke.ucore.entities.trait.Entity; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.function.Predicate; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.graphics.Surface; -import io.anuke.ucore.modules.RendererModule; -import io.anuke.ucore.scene.utils.Cursors; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Pooling; -import io.anuke.ucore.util.Translator; +import static io.anuke.arc.Core.*; import static io.anuke.mindustry.Vars.*; -import static io.anuke.ucore.core.Core.batch; -import static io.anuke.ucore.core.Core.camera; -public class Renderer extends RendererModule{ - public final Surface effectSurface; +public class Renderer implements ApplicationListener{ public final BlockRenderer blocks = new BlockRenderer(); public final MinimapRenderer minimap = new MinimapRenderer(); public final OverlayRenderer overlays = new OverlayRenderer(); - public final FogRenderer fog = new FogRenderer(); - private int targetscale = baseCameraScale; + private 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 Translator(); + private Vector2 avgPosition = new Vector2(); + private float shakeIntensity, shaketime; public Renderer(){ - Core.batch = new SpriteBatch(4096); - + batch = new SpriteBatch(4096); + camera = new Camera(); Lines.setCircleVertices(14); - Shaders.init(); - Core.cameraScale = baseCameraScale; + Effects.setScreenShakeProvider((intensity, duration) -> { + shakeIntensity = Math.max(intensity, shakeIntensity); + shaketime = Math.max(shaketime, duration); + }); + Effects.setEffectProvider((effect, color, x, y, rotation, data) -> { if(effect == Fx.none) return; - if(Settings.getBool("effects")){ - Rectangle view = rect.setSize(camera.viewportWidth, camera.viewportHeight) + if(Core.settings.getBool("effects")){ + Rectangle view = rect.setSize(camera.width, camera.height) .setCenter(camera.position.x, camera.position.y); Rectangle pos = rect2.setSize(effect.size).setCenter(x, y); if(view.overlaps(pos)){ if(!(effect instanceof GroundEffect)){ - EffectEntity entity = Pooling.obtain(EffectEntity.class, EffectEntity::new); + 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++; @@ -87,11 +82,11 @@ public class Renderer extends RendererModule{ if(data instanceof Entity){ entity.setParent((Entity) data); } - threads.runGraphics(() -> effectGroup.add(entity)); + effectGroup.add(entity); }else{ - GroundEffectEntity entity = Pooling.obtain(GroundEffectEntity.class, GroundEffectEntity::new); + 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; @@ -99,30 +94,13 @@ public class Renderer extends RendererModule{ if(data instanceof Entity){ entity.setParent((Entity) data); } - threads.runGraphics(() -> groundEffectGroup.add(entity)); + groundEffectGroup.add(entity); } } } }); - Cursors.cursorScaling = 3; - Cursors.outlineColor = Color.valueOf("444444"); - - Cursors.arrow = Cursors.loadCursor("cursor"); - Cursors.hand = Cursors.loadCursor("hand"); - Cursors.ibeam = Cursors.loadCursor("ibar"); - Cursors.restoreCursor(); - Cursors.loadCustom("drill"); - Cursors.loadCustom("unload"); - clearColor = new Color(0f, 0f, 0f, 1f); - - effectSurface = Graphics.createSurface(Core.cameraScale); - pixelSurface = Graphics.createSurface(Core.cameraScale); - } - - @Override - public void init(){ } @Override @@ -130,113 +108,80 @@ public class Renderer extends RendererModule{ //TODO hack, find source of this bug Color.WHITE.set(1f, 1f, 1f, 1f); - if(Core.cameraScale != targetscale){ - float targetzoom = (float) Core.cameraScale / targetscale; - camera.zoom = Mathf.lerpDelta(camera.zoom, targetzoom, 0.2f); - - if(Mathf.in(camera.zoom, targetzoom, 0.005f)){ - camera.zoom = 1f; - Graphics.setCameraScale(targetscale); - for(Player player : players){ - control.input(player.playerIndex).resetCursor(); - } - } - }else{ - camera.zoom = Mathf.lerpDelta(camera.zoom, 1f, 0.2f); - } + camerascale = Mathf.lerpDelta(camerascale, targetscale, 0.1f); + camera.width = graphics.getWidth() / camerascale; + camera.height = graphics.getHeight() / camerascale; if(state.is(State.menu)){ - Graphics.clear(Color.BLACK); + graphics.clear(Color.BLACK); }else{ Vector2 position = averagePosition(); if(players[0].isDead()){ TileEntity core = players[0].getClosestCore(); - if(core != null && players[0].spawner == Unit.noSpawner){ - smoothCamera(core.x, core.y, 0.08f); + if(core != null && players[0].spawner == null){ + camera.position.lerpDelta(core.x, core.y, 0.08f); }else{ - smoothCamera(position.x + 0.0001f, position.y + 0.0001f, 0.08f); + camera.position.lerpDelta(position, 0.08f); } }else if(!mobile){ - setCamera(position.x + 0.0001f, position.y + 0.0001f); + 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); - float prex = camera.position.x, prey = camera.position.y; updateShake(0.75f); - float deltax = camera.position.x - prex, deltay = camera.position.y - prey; - float lastx = camera.position.x, lasty = camera.position.y; - - if(snapCamera){ - camera.position.set((int) camera.position.x, (int) camera.position.y, 0); - } - - if(Gdx.graphics.getHeight() / Core.cameraScale % 2 == 1){ - camera.position.add(0, -0.5f, 0); - } - - if(Gdx.graphics.getWidth() / Core.cameraScale % 2 == 1){ - camera.position.add(-0.5f, 0, 0); - } - draw(); - - camera.position.set(lastx - deltax, lasty - deltay, 0); } if(!ui.chatfrag.chatOpen()){ - renderer.record(); //this only does something if GdxGifRecorder is on the class path, which it usually isn't + ScreenRecorder.record(); //this only does something if CoreGifRecorder is on the class path, which it usually isn't + } + } + + void updateShake(float scale){ + if(shaketime > 0){ + float intensity = shakeIntensity * (settings.getInt("screenshake", 4) / 4f) * scale; + camera.position.add(Mathf.range(intensity), Mathf.range(intensity)); + shakeIntensity -= 0.25f * Time.delta(); + shaketime -= Time.delta(); + shakeIntensity = Mathf.clamp(shakeIntensity, 0f, 100f); + }else{ + shakeIntensity = 0f; } } - @Override public void draw(){ camera.update(); - if(Float.isNaN(Core.camera.position.x) || Float.isNaN(Core.camera.position.y)){ - Core.camera.position.x = players[0].x; - Core.camera.position.y = players[0].y; + + if(Float.isNaN(camera.position.x) || Float.isNaN(camera.position.y)){ + camera.position.x = players[0].x; + camera.position.y = players[0].y; } - Graphics.clear(clearColor); + graphics.clear(clearColor); - batch.setProjectionMatrix(camera.combined); + Draw.proj(camera.projection()); - Graphics.surface(pixelSurface, false); - - Graphics.clear(clearColor); - - blocks.drawFloor(); + blocks.floor.drawFloor(); drawAndInterpolate(groundEffectGroup, e -> e instanceof BelowLiquidTrait); drawAndInterpolate(puddleGroup); drawAndInterpolate(groundEffectGroup, e -> !(e instanceof BelowLiquidTrait)); blocks.processBlocks(); + blocks.drawShadows(); - for(Team team : Team.all){ - if(blocks.isTeamShown(team)){ - boolean outline = team != players[0].getTeam() && team != Team.none; - if(outline){ - Shaders.outline.color.set(team.color); - Shaders.outline.color.a = 0.8f; - Graphics.beginShaders(Shaders.outline); - } + blocks.floor.beginDraw(); + blocks.floor.drawLayer(CacheLayer.walls); + blocks.floor.endDraw(); - blocks.drawTeamBlocks(Layer.block, team); + blocks.drawBlocks(Layer.block); + blocks.drawFog(); - if(outline){ - Graphics.endShaders(); - } - } - } - blocks.skipLayer(Layer.block); - - Graphics.shader(Shaders.blockbuild, false); + Draw.shader(Shaders.blockbuild, true); blocks.drawBlocks(Layer.placement); - Graphics.shader(); + Draw.shader(); blocks.drawBlocks(Layer.overlay); @@ -255,39 +200,38 @@ public class Renderer extends RendererModule{ overlays.drawBottom(); drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests); - Graphics.beginShaders(Shaders.shield); - EntityDraw.draw(shieldGroup); - EntityDraw.drawWith(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawOver()); - Draw.color(Palette.accent); - Graphics.endShaders(); - Draw.color(); + if(EntityDraw.countInBounds(shieldGroup) > 0){ + if(graphics.getWidth() >= 2 && graphics.getHeight() >= 2 && (shieldBuffer.getWidth() != graphics.getWidth() || shieldBuffer.getHeight() != graphics.getHeight())){ + shieldBuffer.resize(graphics.getWidth(), graphics.getHeight()); + } + + Draw.flush(); + shieldBuffer.begin(); + graphics.clear(Color.CLEAR); + EntityDraw.draw(shieldGroup); + EntityDraw.drawWith(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawOver()); + 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(); - if(showFog){ - Graphics.surface(); - }else{ - Graphics.flushSurface(); - } - - batch.end(); - - if(showFog){ - fog.draw(); - } - - Graphics.beginCam(); EntityDraw.setClip(false); drawAndInterpolate(playerGroup, p -> !p.isDead() && !p.isLocal, Player::drawName); EntityDraw.setClip(true); - Graphics.end(); + Draw.color(); + Draw.flush(); } private void drawFlyerShadows(){ - Graphics.surface(effectSurface, true, false); - float trnsX = -12, trnsY = -13; + Draw.color(0, 0, 0, 0.15f); for(EntityGroup group : unitGroups){ if(!group.isEmpty()){ @@ -299,8 +243,6 @@ public class Renderer extends RendererModule{ drawAndInterpolate(playerGroup, unit -> unit.isFlying() && !unit.isDead(), player -> player.drawShadow(trnsX, trnsY)); } - Draw.color(0, 0, 0, 0.15f); - Graphics.flushSurface(); Draw.color(); } @@ -312,18 +254,18 @@ public class Renderer extends RendererModule{ 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); - Graphics.shader(Shaders.mix, true); + //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); - Graphics.shader(); + Draw.shader(); blocks.drawTeamBlocks(Layer.turret, team); - Graphics.endShaders(); + //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); @@ -342,20 +284,8 @@ public class Renderer extends RendererModule{ EntityDraw.drawWith(group, toDraw, drawer); } - @Override - public void resize(int width, int height){ - float lastX = camera.position.x, lastY = camera.position.y; - super.resize(width, height); - for(Player player : players){ - control.input(player.playerIndex).resetCursor(); - } - camera.update(); - camera.position.set(lastX, lastY, 0f); - } - - @Override - public void dispose(){ - fog.dispose(); + public float cameraScale(){ + return camerascale; } public Vector2 averagePosition(){ @@ -367,43 +297,35 @@ public class Renderer extends RendererModule{ return avgPosition; } - public void setCameraScale(int amount){ - targetscale = amount; + public void scaleCamera(float amount){ + targetscale += amount; clampScale(); - //scale up all surfaces in preparation for the zoom - for(Surface surface : Graphics.getSurfaces()){ - surface.setScale(targetscale); - } - } - - public void scaleCamera(int amount){ - setCameraScale(targetscale + amount); } public void clampScale(){ - float s = io.anuke.ucore.scene.ui.layout.Unit.dp.scl(1f); - targetscale = Mathf.clamp(targetscale, Math.round(s * 2), Math.round(s * 5)); + 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(){ - float vpW = Core.camera.viewportWidth, vpH = Core.camera.viewportHeight; + //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(); - showFog = false; disableUI = true; pixelSurface.setSize(w, h, true); Graphics.getEffectSurface().setSize(w, h, true); - Core.camera.viewportWidth = w; - Core.camera.viewportHeight = h; - Core.camera.position.x = w/2f + tilesize/2f; - Core.camera.position.y = h/2f + tilesize/2f; + camera.width = w; + camera.height = h; + camera.position.x = w/2f + tilesize/2f; + camera.position.y = h/2f + tilesize/2f; draw(); - showFog = true; disableUI = false; - Core.camera.viewportWidth = vpW; - Core.camera.viewportHeight = vpH; + camera.width = vpW; + camera.height = vpH; pixelSurface.getBuffer().begin(); byte[] lines = ScreenUtils.getFrameBufferPixels(0, 0, w, h, true); @@ -415,14 +337,14 @@ public class Renderer extends RendererModule{ Pixmap fullPixmap = new Pixmap(w, h, Pixmap.Format.RGBA8888); BufferUtils.copy(lines, 0, fullPixmap.getPixels(), lines.length); - FileHandle file = screenshotDirectory.child("screenshot-" + TimeUtils.millis() + ".png"); + 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(Bundles.format("text.screenshot", file.toString())); + ui.showInfoFade(Core.bundle.format("screenshot", file.toString()));*/ } } diff --git a/core/src/io/anuke/mindustry/core/ThreadHandler.java b/core/src/io/anuke/mindustry/core/ThreadHandler.java deleted file mode 100644 index 700b816a92..0000000000 --- a/core/src/io/anuke/mindustry/core/ThreadHandler.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.anuke.mindustry.core; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.utils.TimeUtils; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.core.Timers; - -public class ThreadHandler{ - private long lastFrameTime; - - public ThreadHandler(){ - Timers.setDeltaProvider(() -> { - float result = Gdx.graphics.getDeltaTime() * 60f; - return Float.isNaN(result) || Float.isInfinite(result) ? 1f : Math.min(result, 60f / 10f); - }); - } - - public void run(Runnable r){ - r.run(); - } - - public void runGraphics(Runnable r){ - r.run(); - } - - public void runDelay(Runnable r){ - Gdx.app.postRunnable(r); - } - - public long getFrameID(){ - return Gdx.graphics.getFrameId(); - } - - public void handleBeginRender(){ - lastFrameTime = TimeUtils.millis(); - } - - public void handleEndRender(){ - int fpsCap = Settings.getInt("fpscap", 125); - - if(fpsCap <= 120){ - long target = 1000/fpsCap; - long elapsed = TimeUtils.timeSinceMillis(lastFrameTime); - if(elapsed < target){ - try{ - Thread.sleep(target - elapsed); - }catch(InterruptedException e){ - e.printStackTrace(); - } - } - } - } - -} diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index 27e8fd3569..85cf266f77 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -1,51 +1,54 @@ package io.anuke.mindustry.core; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.Colors; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; -import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter; -import com.badlogic.gdx.math.Interpolation; -import com.badlogic.gdx.utils.Align; +import io.anuke.arc.ApplicationListener; +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.freetype.FreeTypeFontGenerator; +import io.anuke.arc.freetype.FreeTypeFontGenerator.FreeTypeFontParameter; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.Colors; +import io.anuke.arc.graphics.g2d.BitmapFont; +import io.anuke.arc.input.KeyCode; +import io.anuke.arc.math.Interpolation; +import io.anuke.arc.scene.Group; +import io.anuke.arc.scene.Scene; +import io.anuke.arc.scene.Skin; +import io.anuke.arc.scene.actions.Actions; +import io.anuke.arc.scene.ui.Dialog; +import io.anuke.arc.scene.ui.TextField; +import io.anuke.arc.scene.ui.TextField.TextFieldFilter; +import io.anuke.arc.scene.ui.TooltipManager; +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.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.input.InputHandler; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.ui.dialogs.*; import io.anuke.mindustry.ui.fragments.*; -import io.anuke.ucore.core.*; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.modules.SceneModule; -import io.anuke.ucore.scene.Group; -import io.anuke.ucore.scene.Skin; -import io.anuke.ucore.scene.actions.Actions; -import io.anuke.ucore.scene.ui.Dialog; -import io.anuke.ucore.scene.ui.TextField; -import io.anuke.ucore.scene.ui.TextField.TextFieldFilter; -import io.anuke.ucore.scene.ui.TooltipManager; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.util.Strings; -import static io.anuke.mindustry.Vars.*; -import static io.anuke.ucore.scene.actions.Actions.*; +import static io.anuke.arc.scene.actions.Actions.*; +import static io.anuke.mindustry.Vars.control; +import static io.anuke.mindustry.Vars.disableUI; -public class UI extends SceneModule{ +public class UI implements ApplicationListener{ private FreeTypeFontGenerator generator; - public final MenuFragment menufrag = new MenuFragment(); - public final HudFragment hudfrag = new HudFragment(); - public final ChatFragment chatfrag = new ChatFragment(); - public final PlayerListFragment listfrag = new PlayerListFragment(); - public final BackgroundFragment backfrag = new BackgroundFragment(); - public final LoadingFragment loadfrag = new LoadingFragment(); + public MenuFragment menufrag; + public HudFragment hudfrag; + public ChatFragment chatfrag; + public PlayerListFragment listfrag; + public BackgroundFragment backfrag; + public LoadingFragment loadfrag; public AboutDialog about; - public RestartDialog restart; - public CustomGameDialog levels; + public GameOverDialog restart; + public CustomGameDialog custom; public MapsDialog maps; public LoadDialog load; public DiscordDialog discord; @@ -61,16 +64,29 @@ public class UI extends SceneModule{ public TraceDialog traces; public ChangelogDialog changelog; public LocalPlayerDialog localplayers; - public UnlocksDialog unlocks; + public DatabaseDialog database; public ContentInfoDialog content; - public SectorsDialog sectors; - public MissionDialog missions; + public DeployDialog deploy; + public TechTreeDialog tech; + + public Cursor drillCursor, unloadCursor; public UI(){ + Skin skin = new Skin(Core.atlas); + generateFonts(skin); + skin.load(Core.files.internal("sprites/uiskin.json")); + + for(BitmapFont font : skin.getAll(BitmapFont.class).values()){ + font.setUseIntegerPositions(true); + } + + Core.scene = new Scene(skin); + Core.input.addProcessor(Core.scene); + Dialog.setShowAction(() -> sequence( alpha(0f), originCenter(), - moveToAligned(Gdx.graphics.getWidth() / 2f, Gdx.graphics.getHeight() / 2f, Align.center), + moveToAligned(Core.graphics.getWidth() / 2f, Core.graphics.getHeight() / 2f, Align.center), scaleTo(0.0f, 1f), parallel( scaleTo(1f, 1f, 0.1f, Interpolation.fade), @@ -87,16 +103,31 @@ public class UI extends SceneModule{ TooltipManager.getInstance().animations = false; - Settings.setErrorHandler(() -> Timers.run(1f, () -> showError("[crimson]Failed to access local storage.\nSettings will not be saved."))); + Core.settings.setErrorHandler(e -> { + e.printStackTrace(); + Core.app.post(() -> showError("Failed to access local storage.\nSettings will not be saved.")); + }); - Dialog.closePadR = -1; - Dialog.closePadT = 5; + Colors.put("accent", Pal.accent); - Colors.put("accent", Palette.accent); + loadCursors(); + } + + void loadCursors(){ + int cursorScaling = 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)); + + Core.graphics.restoreCursor(); } - void generateFonts(){ - generator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/pixel.ttf")); + void generateFonts(Skin skin){ + generator = new FreeTypeFontGenerator(Core.files.internal("fonts/pixel.ttf")); FreeTypeFontParameter param = new FreeTypeFontParameter(); param.size = (int)(14*2 * Math.max(Unit.dp.scl(1f), 0.5f)); param.shadowColor = Color.DARK_GRAY; @@ -109,55 +140,32 @@ public class UI extends SceneModule{ skin.getFont("default-font").setOwnsTexture(false); } - @Override - protected void loadSkin(){ - skin = new Skin(Core.atlas); - generateFonts(); - skin.load(Gdx.files.internal("ui/uiskin.json")); - - for(BitmapFont font : skin.getAll(BitmapFont.class).values()){ - font.setUseIntegerPositions(true); - //font.getData().setScale(Vars.fontScale); - } - } - @Override public void update(){ if(disableUI) return; - if(Graphics.drawing()) Graphics.end(); - - act(); - - Graphics.begin(); - - for(int i = 0; i < players.length; i++){ - InputHandler input = control.input(i); - - if(input.isCursorVisible()){ - Draw.color(); - - float scl = Unit.dp.scl(3f); - - Draw.rect("controller-cursor", input.getMouseX(), Gdx.graphics.getHeight() - input.getMouseY(), 16 * scl, 16 * scl); - } - } - - Graphics.end(); - Draw.color(); + Core.scene.act(); + Core.scene.draw(); } @Override public void init(){ + menufrag = new MenuFragment(); + hudfrag = new HudFragment(); + chatfrag = new ChatFragment(); + listfrag = new PlayerListFragment(); + backfrag = new BackgroundFragment(); + loadfrag = new LoadingFragment(); + editor = new MapEditorDialog(); controls = new ControlsDialog(); - restart = new RestartDialog(); + restart = new GameOverDialog(); join = new JoinDialog(); discord = new DiscordDialog(); load = new LoadDialog(); - levels = new CustomGameDialog(); + custom = new CustomGameDialog(); language = new LanguageDialog(); - unlocks = new UnlocksDialog(); + database = new DatabaseDialog(); settings = new SettingsMenuDialog(); host = new HostDialog(); paused = new PausedDialog(); @@ -169,13 +177,13 @@ public class UI extends SceneModule{ maps = new MapsDialog(); localplayers = new LocalPlayerDialog(); content = new ContentInfoDialog(); - sectors = new SectorsDialog(); - missions = new MissionDialog(); + deploy = new DeployDialog(); + tech = new TechTreeDialog(); - Group group = Core.scene.getRoot(); + Group group = Core.scene.root; backfrag.build(group); - control.input(0).getFrag().build(Core.scene.getRoot()); + control.input(0).getFrag().build(group); hudfrag.build(group); menufrag.build(group); chatfrag.container().build(group); @@ -185,55 +193,40 @@ public class UI extends SceneModule{ @Override public void resize(int width, int height){ - super.resize(width, height); - + Core.scene.resize(width, height); Events.fire(new ResizeEvent()); } @Override public void dispose(){ - super.dispose(); generator.dispose(); } - public void loadGraphics(Runnable call){ - loadGraphics("$text.loading", call); + public void loadAnd(Runnable call){ + loadAnd("$loading", call); } - public void loadGraphics(String text, Runnable call){ + public void loadAnd(String text, Runnable call){ loadfrag.show(text); - Timers.runTask(7f, () -> { + Time.runTask(7f, () -> { call.run(); loadfrag.hide(); }); } - public void loadLogic(Runnable call){ - loadLogic("$text.loading", call); - } - - public void loadLogic(String text, Runnable call){ - loadfrag.show(text); - Timers.runTask(7f, () -> - threads.run(() -> { - call.run(); - threads.runGraphics(loadfrag::hide); - })); - } - - public void showTextInput(String title, String text, String def, TextFieldFilter filter, Consumer confirmed){ - new Dialog(title, "dialog"){{ - content().margin(30).add(text).padRight(6f); - TextField field = content().addField(def, t -> { + public void showTextInput(String titleText, String text, String def, TextFieldFilter filter, Consumer confirmed){ + new Dialog(titleText, "dialog"){{ + cont.margin(30).add(text).padRight(6f); + TextField field = cont.addField(def, t -> { }).size(170f, 50f).get(); field.setTextFieldFilter((f, c) -> field.getText().length() < 12 && filter.acceptChar(f, c)); Platform.instance.addDialog(field); - buttons().defaults().size(120, 54).pad(4); - buttons().addButton("$text.ok", () -> { + buttons.defaults().size(120, 54).pad(4); + buttons.addButton("$ok", () -> { confirmed.accept(field.getText()); hide(); }).disabled(b -> field.getText().isEmpty()); - buttons().addButton("$text.cancel", this::hide); + buttons.addButton("$cancel", this::hide); }}.show(); } @@ -245,23 +238,23 @@ public class UI extends SceneModule{ Table table = new Table(); table.setFillParent(true); table.actions(Actions.fadeOut(7f, Interpolation.fade), Actions.removeActor()); - table.top().add(info).padTop(8); + table.top().add(info).padTop(10); Core.scene.add(table); } public void showInfo(String info){ new Dialog("", "dialog"){{ - getCell(content()).growX(); - content().margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center); - buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4); + getCell(cont).growX(); + cont.margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center); + buttons.addButton("$ok", this::hide).size(90, 50).pad(4); }}.show(); } public void showInfo(String info, Runnable clicked){ new Dialog("", "dialog"){{ - getCell(content()).growX(); - content().margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center); - buttons().addButton("$text.ok", () -> { + 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); @@ -269,31 +262,31 @@ public class UI extends SceneModule{ } public void showError(String text){ - new Dialog("$text.error.title", "dialog"){{ - content().margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center); - buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4); + new Dialog("$error.title", "dialog"){{ + cont.margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center); + buttons.addButton("$ok", this::hide).size(90, 50).pad(4); }}.show(); } - public void showText(String title, String text){ - new Dialog(title, "dialog"){{ - content().margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center); - buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4); + public void showText(String titleText, String text){ + new Dialog(titleText, "dialog"){{ + cont.margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center); + 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.content().add(text).width(400f).wrap().pad(4f).get().setAlignment(Align.center, Align.center); - dialog.buttons().defaults().size(200f, 54f).pad(2f); + 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("$text.cancel", dialog::hide); - dialog.buttons().addButton("$text.ok", () -> { + dialog.buttons.addButton("$cancel", dialog::hide); + dialog.buttons.addButton("$ok", () -> { dialog.hide(); confirmed.run(); }); - dialog.keyDown(Keys.ESCAPE, dialog::hide); - dialog.keyDown(Keys.BACK, dialog::hide); + dialog.keyDown(KeyCode.ESCAPE, dialog::hide); + dialog.keyDown(KeyCode.BACK, dialog::hide); dialog.show(); } diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index 58dedd6e2a..48572dc653 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -1,55 +1,56 @@ package io.anuke.mindustry.core; -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.ObjectMap; +import io.anuke.arc.ApplicationListener; +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.mindustry.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.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.Blocks; +import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.EventType.TileChangeEvent; import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.io.MapIO; -import io.anuke.mindustry.maps.*; -import io.anuke.mindustry.maps.generation.WorldGenerator; +import io.anuke.mindustry.maps.Map; +import io.anuke.mindustry.maps.MapTileData; +import io.anuke.mindustry.maps.MapTileData.TileDataMarker; +import io.anuke.mindustry.maps.Maps; +import io.anuke.mindustry.maps.generators.Generator; +import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.type.Zone; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Pos; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.OreBlock; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.EntityQuery; -import io.anuke.ucore.modules.Module; -import io.anuke.ucore.util.*; import static io.anuke.mindustry.Vars.*; -public class World extends Module{ +public class World implements ApplicationListener{ public final Maps maps = new Maps(); - public final Sectors sectors = new Sectors(); - public final WorldGenerator generator = new WorldGenerator(); public final BlockIndexer indexer = new BlockIndexer(); public final WaveSpawner spawner = new WaveSpawner(); public final Pathfinder pathfinder = new Pathfinder(); private Map currentMap; - private Sector currentSector; private Tile[][] tiles; - private Array tempTiles = new ThreadArray<>(); + private Array tempTiles = new Array<>(); private boolean generating, invalidMap; public World(){ maps.load(); } - @Override - public void init(){ - sectors.load(); - } - @Override public void dispose(){ maps.dispose(); @@ -84,14 +85,6 @@ public class World extends Module{ return currentMap; } - public Sector getSector(){ - return currentSector; - } - - public void setSector(Sector currentSector){ - this.currentSector = currentSector; - } - public void setMap(Map map){ this.currentMap = map; } @@ -121,11 +114,11 @@ public class World extends Module{ } public Tile tileWorld(float x, float y){ - return tile(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize)); + return tile(Math.round(x / tilesize), Math.round(y / tilesize)); } public int toTile(float coord){ - return Mathf.scl2(coord, tilesize); + return Math.round(coord / tilesize); } public Tile[][] getTiles(){ @@ -184,17 +177,15 @@ public class World extends Module{ Tile tile = tiles[x][y]; tile.updateOcclusion(); - if(tile.floor() instanceof OreBlock && tile.hasCliffs()){ - tile.setFloor(((OreBlock) tile.floor()).base); - } - if(tile.entity != null){ tile.entity.updateProximity(); } } } - EntityQuery.resizeTree(0, 0, tiles.length * tilesize, tiles[0].length * tilesize); + addDarkness(tiles); + + EntityQuery.resizeTree(-finalWorldBounds, -finalWorldBounds, tiles.length * tilesize + finalWorldBounds, tiles[0].length * tilesize + finalWorldBounds); generating = false; Events.fire(new WorldLoadEvent()); @@ -204,34 +195,42 @@ public class World extends Module{ return generating; } - /**Loads up a sector map. This does not call play(), but calls reset().*/ - public void loadSector(Sector sector){ - currentSector = sector; - state.difficulty = sectors.getDifficulty(sector); - state.mode = sector.currentMission().getMode(); - Timers.mark(); - Timers.mark(); + public boolean isZone(){ + return getZone() != null; + } - logic.reset(); + public Zone getZone(){ + return content.getByID(ContentType.zone, state.rules.zone); + } + public void playZone(Zone zone){ + 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){ + core.entity.items.add(stack.item, stack.amount); + } + } + state.set(State.playing); + control.saves.zoneSave(); + logic.play(); + }); + } + + public void loadGenerator(Generator generator){ beginMapLoad(); - int width = sectorSize, height = sectorSize; - - Tile[][] tiles = createTiles(width, height); - - Map map = new Map("Sector " + sector.x + ", " + sector.y, new MapMeta(0, new ObjectMap<>(), width, height, null), true, () -> null); - setMap(map); - - EntityQuery.resizeTree(0, 0, width * tilesize, height * tilesize); - - generator.generateMap(tiles, sector); + createTiles(generator.width, generator.height); + generator.generate(tiles); + prepareTiles(tiles); endMapLoad(); } public void loadMap(Map map){ - currentSector = null; beginMapLoad(); this.currentMap = map; @@ -239,15 +238,13 @@ public class World extends Module{ createTiles(width, height); - EntityQuery.resizeTree(0, 0, width * tilesize, height * tilesize); - try{ - generator.loadTileData(tiles, MapIO.readTileData(map, true), map.meta.hasOreGen(), Mathf.random(99999)); - } catch(Exception e){ + loadTileData(tiles, MapIO.readTileData(map, true)); + }catch(Exception e){ Log.err(e); if(!headless){ - ui.showError("$text.map.invalid"); - threads.runDelay(() -> state.set(State.menu)); + ui.showError("$map.invalid"); + Core.app.post(() -> state.set(State.menu)); invalidMap = true; } generating = false; @@ -260,9 +257,9 @@ public class World extends Module{ if(!headless){ if(state.teams.get(players[0].getTeam()).cores.size == 0){ - ui.showError("$text.map.nospawn"); + ui.showError("$map.nospawn"); invalidMap = true; - }else if(state.mode.isPvp){ + }else if(state.rules.pvp){ //pvp maps need two cores to be valid invalidMap = true; for(Team team : Team.all){ if(state.teams.get(team).cores.size != 0 && team != players[0].getTeam()){ @@ -270,20 +267,17 @@ public class World extends Module{ } } if(invalidMap){ - ui.showError("$text.map.nospawn.pvp"); + ui.showError("$map.nospawn.pvp"); } } - }else{ - invalidMap = false; } - if(invalidMap) threads.runDelay(() -> state.set(State.menu)); - + if(invalidMap) Core.app.post(() -> state.set(State.menu)); } public void notifyChanged(Tile tile){ if(!generating){ - threads.runDelay(() -> Events.fire(new TileChangeEvent(tile))); + Core.app.post(() -> Events.fire(new TileChangeEvent(tile))); } } @@ -334,9 +328,9 @@ public class World extends Module{ /** * Raycast, but with world coordinates. */ - public GridPoint2 raycastWorld(float x, float y, float x2, float y2){ - return raycast(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize), - Mathf.scl2(x2, tilesize), Mathf.scl2(y2, tilesize)); + public Point2 raycastWorld(float x, float y, float x2, float y2){ + return raycast(Math.round(x / tilesize), Math.round(y / tilesize), + Math.round(x2 / tilesize), Math.round(y2 / tilesize)); } /** @@ -344,7 +338,7 @@ public class World extends Module{ * * @return null if no collisions found, block position otherwise. */ - public GridPoint2 raycast(int x0f, int y0f, int x1, int y1){ + public Point2 raycast(int x0f, int y0f, int x1, int y1){ int x0 = x0f; int y0 = y0f; int dx = Math.abs(x1 - x0); @@ -409,6 +403,126 @@ public class World extends Module{ } } + /**Loads raw map tile data into a Tile[][] array, setting up multiblocks, cliffs and ores. */ + void loadTileData(Tile[][] tiles, MapTileData data){ + 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); + + tiles[x][y] = new Tile(x, y, marker.floor, marker.wall == Blocks.part.id ? 0 : marker.wall, marker.rotation, marker.team); + } + } + + prepareTiles(tiles); + } + + public void addDarkness(Tile[][] tiles){ + + byte[][] dark = new byte[tiles.length][tiles[0].length]; + byte[][] writeBuffer = new byte[tiles.length][tiles[0].length]; + + byte darkIterations = 4; + 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().synthetic() && tile.block().fillsTile){ + dark[x][y] = darkIterations; + } + } + } + + for(int i = 0; i < darkIterations; i++){ + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ + boolean min = false; + for(Point2 point : Geometry.d4){ + int newX = x + point.x, newY = y + point.y; + if(Structs.inBounds(newX, newY, tiles) && dark[newX][newY] < dark[x][y]){ + min = true; + break; + } + } + writeBuffer[x][y] = (byte)Math.max(0, dark[x][y] - Mathf.num(min)); + } + } + + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ + dark[x][y] = writeBuffer[x][y]; + } + } + } + + 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().synthetic()){ + tiles[x][y].setRotation(dark[x][y]); + } + } + } + } + + /**'Prepares' a tile array by:
+ * - setting up multiblocks
+ * - updating occlusion
+ * Usually used before placing structures on a tile array.*/ + public void prepareTiles(Tile[][] tiles){ + + //find multiblocks + IntArray multiblocks = new IntArray(); + + 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().isMultiblock()){ + multiblocks.add(tile.pos()); + } + } + } + + //place multiblocks now + for(int i = 0; i < multiblocks.size; i++){ + int pos = multiblocks.get(i); + + int x = Pos.x(pos); + int y = Pos.y(pos); + + Block result = tiles[x][y].block(); + Team team = tiles[x][y].getTeam(); + + int offsetx = -(result.size - 1) / 2; + int offsety = -(result.size - 1) / 2; + + for(int dx = 0; dx < result.size; dx++){ + for(int dy = 0; dy < result.size; dy++){ + int worldx = dx + offsetx + x; + int worldy = dy + offsety + y; + if(!(worldx == x && worldy == y)){ + Tile toplace = world.tile(worldx, worldy); + if(toplace != null){ + toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety)); + toplace.setTeam(team); + } + } + } + } + } + + //update cliffs, occlusion data + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ + Tile tile = tiles[x][y]; + + tile.updateOcclusion(); + } + } + } + public interface Raycaster{ boolean accept(int x, int y); } diff --git a/core/src/io/anuke/mindustry/editor/DrawOperation.java b/core/src/io/anuke/mindustry/editor/DrawOperation.java index d2b434e21f..b6b7d13f76 100755 --- a/core/src/io/anuke/mindustry/editor/DrawOperation.java +++ b/core/src/io/anuke/mindustry/editor/DrawOperation.java @@ -1,10 +1,10 @@ package io.anuke.mindustry.editor; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.IntSet; +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.IntSet; +import io.anuke.arc.util.Pack; import io.anuke.mindustry.maps.MapTileData; import io.anuke.mindustry.maps.MapTileData.TileDataMarker; -import io.anuke.ucore.util.Bits; public class DrawOperation{ /** @@ -29,7 +29,7 @@ public class DrawOperation{ } public boolean checkDuplicate(short x, short y){ - int i = Bits.packInt(x, y); + int i = Pack.shortInt(x, y); if(checks.contains(i)) return true; checks.add(i); diff --git a/core/src/io/anuke/mindustry/editor/EditorTool.java b/core/src/io/anuke/mindustry/editor/EditorTool.java index 6eca7e8fd4..3ec34b21da 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 com.badlogic.gdx.utils.IntArray; -import io.anuke.mindustry.content.blocks.Blocks; +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.maps.MapTileData; import io.anuke.mindustry.maps.MapTileData.DataPosition; import io.anuke.mindustry.maps.MapTileData.TileDataMarker; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.ucore.function.IntPositionConsumer; -import io.anuke.ucore.util.Structs; -import io.anuke.ucore.util.Bits; import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.ui; @@ -24,8 +26,8 @@ public enum EditorTool{ byte link = editor.getMap().read(x, y, DataPosition.link); if(link != 0){ - x -= (Bits.getLeftByte(link) - 8); - y -= (Bits.getRightByte(link) - 8); + x -= (Pack.leftByte(link) - 8); + y -= (Pack.rightByte(link) - 8); bf = editor.getMap().read(x, y, DataPosition.floor); bw = editor.getMap().read(x, y, DataPosition.wall); } @@ -43,7 +45,7 @@ public enum EditorTool{ @Override public void touched(MapEditor editor, int x, int y){ - editor.draw(x, y); + editor.draw(x, y, isPaint()); } }, eraser{ @@ -54,10 +56,10 @@ 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); } }, - elevation{ + spray{ { edit = true; draggable = true; @@ -65,7 +67,7 @@ public enum EditorTool{ @Override public void touched(MapEditor editor, int x, int y){ - editor.elevate(x, y); + editor.draw(x, y, isPaint(), editor.getDrawBlock(), 0.012); } }, line{ @@ -99,9 +101,8 @@ public enum EditorTool{ byte bf = data.read(x, y, DataPosition.floor); byte bw = data.read(x, y, DataPosition.wall); - be = data.read(x, y, DataPosition.elevation); boolean synth = editor.getDrawBlock().synthetic(); - byte brt = Bits.packByte((byte) editor.getDrawRotation(), (byte) editor.getDrawTeam().ordinal()); + byte brt = Pack.byteByte((byte) editor.getDrawRotation(), (byte) editor.getDrawTeam().ordinal()); dest = floor ? bf : bw; byte draw = editor.getDrawBlock().id; @@ -113,13 +114,6 @@ public enum EditorTool{ width = editor.getMap().width(); int height = editor.getMap().height(); - int x1; - boolean spanAbove, spanBelow; - - stack.clear(); - - stack.add(asi(x, y)); - IntPositionConsumer writer = (px, py) -> { TileDataMarker prev = editor.getPrev(px, py, false); @@ -136,32 +130,49 @@ 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); + } } + } + }else{ + int x1; + boolean spanAbove, spanBelow; - 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; - } + 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++; + } } } } @@ -182,6 +193,14 @@ 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 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 532e720622..b70ab01467 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditor.java +++ b/core/src/io/anuke/mindustry/editor/MapEditor.java @@ -1,8 +1,11 @@ package io.anuke.mindustry.editor; -import com.badlogic.gdx.utils.ObjectMap; +import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Pack; +import io.anuke.arc.util.Structs; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.blocks.Blocks; +import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.editor.DrawOperation.TileOperation; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.maps.MapTileData; @@ -10,19 +13,17 @@ import io.anuke.mindustry.maps.MapTileData.DataPosition; import io.anuke.mindustry.maps.MapTileData.TileDataMarker; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.ucore.util.Structs; -import io.anuke.ucore.util.Bits; -import io.anuke.ucore.util.Mathf; + import static io.anuke.mindustry.Vars.content; + public class MapEditor{ - public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15}; + public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15, 20}; private MapTileData map; private ObjectMap tags = new ObjectMap<>(); private MapRenderer renderer = new MapRenderer(this); private int brushSize = 1; - private byte elevation; private int rotation; private Block drawBlock = Blocks.stone; private Team drawTeam = Team.blue; @@ -52,14 +53,6 @@ public class MapEditor{ renderer.resize(map.width(), map.height()); } - public byte getDrawElevation(){ - return elevation; - } - - public void setDrawElevation(int elevation){ - this.elevation = (byte) elevation; - } - public int getDrawRotation(){ return rotation; } @@ -92,18 +85,18 @@ 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){ - if(x < 0 || y < 0 || x >= map.width() || y >= map.height()){ - return; - } + 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, boolean paint, Block drawBlock, double chance){ byte writeID = drawBlock.id; - byte partID = Blocks.blockpart.id; - byte rotationTeam = Bits.packByte(drawBlock.rotate ? (byte) rotation : 0, drawBlock.synthetic() ? (byte) drawTeam.ordinal() : 0); + byte partID = Blocks.part.id; + byte rotationTeam = Pack.byteByte(drawBlock.rotate ? (byte)rotation : 0, drawBlock.synthetic() ? (byte)drawTeam.ordinal() : 0); boolean isfloor = drawBlock instanceof Floor && drawBlock != Blocks.air; @@ -126,13 +119,13 @@ public class MapEditor{ if(i == 1){ map.write(worldx, worldy, DataPosition.wall, partID); map.write(worldx, worldy, DataPosition.rotationTeam, rotationTeam); - map.write(worldx, worldy, DataPosition.link, Bits.packByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8))); + map.write(worldx, worldy, DataPosition.link, Pack.byteByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8))); }else{ byte link = map.read(worldx, worldy, DataPosition.link); byte block = map.read(worldx, worldy, DataPosition.wall); if(link != 0){ - removeLinked(worldx - (Bits.getLeftByte(link) - 8), worldy - (Bits.getRightByte(link) - 8)); + removeLinked(worldx - (Pack.leftByte(link) - 8), worldy - (Pack.rightByte(link) - 8)); }else if(content.block(block).isMultiblock()){ removeLinked(worldx, worldy); } @@ -152,13 +145,12 @@ public class MapEditor{ onWrite(x, y, prev); }else{ - for(int rx = -brushSize; rx <= brushSize; rx++){ for(int ry = -brushSize; ry <= brushSize; ry++){ - if(Mathf.dst(rx, ry) <= brushSize - 0.5f){ + 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; } @@ -170,13 +162,12 @@ public class MapEditor{ if(content.block(map.read(wx, wy, DataPosition.wall)).isMultiblock()){ removeLinked(wx, wy); }else if(link != 0){ - removeLinked(wx - (Bits.getLeftByte(link) - 8), wy - (Bits.getRightByte(link) - 8)); + removeLinked(wx - (Pack.leftByte(link) - 8), wy - (Pack.rightByte(link) - 8)); } } if(isfloor){ map.write(wx, wy, DataPosition.floor, writeID); - map.write(wx, wy, DataPosition.elevation, elevation); }else{ map.write(wx, wy, DataPosition.wall, writeID); map.write(wx, wy, DataPosition.link, (byte) 0); @@ -190,30 +181,6 @@ public class MapEditor{ } } - public void elevate(int x, int y){ - if(x < 0 || y < 0 || x >= map.width() || y >= map.height()){ - return; - } - - for(int rx = -brushSize; rx <= brushSize; rx++){ - for(int ry = -brushSize; ry <= brushSize; ry++){ - if(Mathf.dst(rx, ry) <= brushSize - 0.5f){ - int wx = x + rx, wy = y + ry; - - if(wx < 0 || wy < 0 || wx >= map.width() || wy >= map.height()){ - continue; - } - - TileDataMarker prev = getPrev(wx, wy, true); - - map.write(wx, wy, DataPosition.elevation, elevation); - - onWrite(x + rx, y + ry, prev); - } - } - } - } - private void removeLinked(int x, int y){ Block block = content.block(map.read(x, y, DataPosition.wall)); @@ -269,10 +236,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 1fe31ead15..17155c2af1 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java @@ -1,43 +1,34 @@ package io.anuke.mindustry.editor; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Align; -import com.badlogic.gdx.utils.Disposable; -import com.badlogic.gdx.utils.ObjectMap; +import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.Pixmap; +import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.input.KeyCode; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.scene.actions.Actions; +import io.anuke.arc.scene.style.TextureRegionDrawable; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.scene.ui.layout.Unit; +import io.anuke.arc.scene.utils.UIUtils; +import io.anuke.arc.util.*; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.blocks.StorageBlocks; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.maps.MapMeta; import io.anuke.mindustry.maps.MapTileData; -import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.world.Block; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.core.Inputs; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.input.Input; -import io.anuke.ucore.scene.actions.Actions; -import io.anuke.ucore.scene.ui.*; -import io.anuke.ucore.scene.ui.layout.Stack; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.scene.utils.UIUtils; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Strings; +import io.anuke.mindustry.world.Block.Icon; +import io.anuke.mindustry.world.blocks.OreBlock; import java.io.DataInputStream; import java.io.InputStream; @@ -54,6 +45,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ private FloatingDialog menu; private boolean saved = false; private boolean shownWithMap = false; + private Array blocksOut = new Array<>(); private ButtonGroup blockgroup; @@ -67,36 +59,36 @@ public class MapEditorDialog extends Dialog implements Disposable{ infoDialog = new MapInfoDialog(editor); - menu = new FloatingDialog("$text.menu"); + menu = new FloatingDialog("$menu"); menu.addCloseButton(); float isize = 16 * 2f; float swidth = 180f; - menu.content().table(t -> { + menu.cont.table(t -> { t.defaults().size(swidth, 60f).padBottom(5).padRight(5).padLeft(5); - t.addImageTextButton("$text.editor.savemap", "icon-floppy-16", isize, this::save).size(swidth * 2f + 10, 60f).colspan(2); + t.addImageTextButton("$editor.savemap", "icon-floppy-16", isize, this::save).size(swidth * 2f + 10, 60f).colspan(2); t.row(); - t.addImageTextButton("$text.editor.mapinfo", "icon-pencil", isize, () -> { + t.addImageTextButton("$editor.mapinfo", "icon-pencil", isize, () -> { infoDialog.show(); menu.hide(); }); - t.addImageTextButton("$text.editor.resize", "icon-resize", isize, () -> { + t.addImageTextButton("$editor.resize", "icon-resize", isize, () -> { resizeDialog.show(); menu.hide(); }); t.row(); - t.addImageTextButton("$text.editor.import", "icon-load-map", isize, () -> - createDialog("$text.editor.import", - "$text.editor.importmap", "$text.editor.importmap.description", "icon-load-map", (Runnable) loadDialog::show, - "$text.editor.importfile", "$text.editor.importfile.description", "icon-file", (Runnable) () -> - Platform.instance.showFileChooser("$text.loadimage", "Map Files", file -> ui.loadGraphics(() -> { + t.addImageTextButton("$editor.import", "icon-load-map", isize, () -> + createDialog("$editor.import", + "$editor.importmap", "$editor.importmap.description", "icon-load-map", (Runnable) loadDialog::show, + "$editor.importfile", "$editor.importfile.description", "icon-file", (Runnable) () -> + Platform.instance.showFileChooser("$loadimage", "Map Files", file -> ui.loadAnd(() -> { try{ DataInputStream stream = new DataInputStream(file.read()); @@ -106,32 +98,32 @@ public class MapEditorDialog extends Dialog implements Disposable{ editor.beginEdit(data, meta.tags, false); view.clearStack(); }catch(Exception e){ - ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false))); Log.err(e); } }), true, mapExtension), - "$text.editor.importimage", "$text.editor.importimage.description", "icon-file-image", (Runnable)() -> - Platform.instance.showFileChooser("$text.loadimage", "Image Files", file -> - ui.loadGraphics(() -> { + "$editor.importimage", "$editor.importimage.description", "icon-file-image", (Runnable)() -> + Platform.instance.showFileChooser("$loadimage", "Image Files", file -> + ui.loadAnd(() -> { try{ MapTileData data = MapIO.readLegacyPixmap(new Pixmap(file)); editor.beginEdit(data, editor.getTags(), false); view.clearStack(); }catch (Exception e){ - ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false))); Log.err(e); } }), true, "png") )); - t.addImageTextButton("$text.editor.export", "icon-save-map", isize, () -> createDialog("$text.editor.export", - "$text.editor.exportfile", "$text.editor.exportfile.description", "icon-file", (Runnable) () -> - Platform.instance.showFileChooser("$text.saveimage", "Map Files", file -> { + t.addImageTextButton("$editor.export", "icon-save-map", isize, () -> createDialog("$editor.export", + "$editor.exportfile", "$editor.exportfile.description", "icon-file", (Runnable) () -> + Platform.instance.showFileChooser("$saveimage", "Map Files", file -> { file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension); FileHandle result = file; - ui.loadGraphics(() -> { + ui.loadAnd(() -> { try{ if(!editor.getTags().containsKey("name")){ @@ -139,7 +131,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ } MapIO.writeMap(result.write(false), editor.getTags(), editor.getMap()); }catch(Exception e){ - ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorimagesave", Strings.parseException(e, false))); Log.err(e); } }); @@ -150,16 +142,16 @@ public class MapEditorDialog extends Dialog implements Disposable{ t.row(); }); - menu.content().row(); + menu.cont.row(); - menu.content().addImageTextButton("$text.quit", "icon-back", isize, () -> { + menu.cont.addImageTextButton("$quit", "icon-back", isize, () -> { tryExit(); menu.hide(); }).padTop(-5).size(swidth * 2f + 10, 60f); resizeDialog = new MapResizeDialog(editor, (x, y) -> { if(!(editor.getMap().width() == x && editor.getMap().height() == y)){ - ui.loadGraphics(() -> { + ui.loadAnd(() -> { editor.resize(x, y); view.clearStack(); }); @@ -167,7 +159,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ }); loadDialog = new MapLoadDialog(map -> - ui.loadGraphics(() -> { + ui.loadAnd(() -> { try(DataInputStream stream = new DataInputStream(map.stream.get())){ MapMeta meta = MapIO.readMapMeta(stream); MapTileData data = MapIO.readTileData(stream, meta, false); @@ -175,7 +167,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ editor.beginEdit(data, meta.tags, false); view.clearStack(); }catch(Exception e){ - ui.showError(Bundles.format("text.editor.errormapload", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false))); Log.err(e); } })); @@ -191,7 +183,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ return; } - Vector2 v = pane.stageToLocalCoordinates(Graphics.mouse()); + Vector2 v = pane.stageToLocalCoordinates(Core.input.mouse()); if(v.x >= 0 && v.y >= 0 && v.x <= pane.getWidth() && v.y <= pane.getHeight()){ Core.scene.setScrollFocus(pane); @@ -210,11 +202,11 @@ 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; - Timers.runTask(10f, Platform.instance::updateRPC); + Time.runTask(10f, Platform.instance::updateRPC); }); hidden(() -> { @@ -224,22 +216,22 @@ public class MapEditorDialog extends Dialog implements Disposable{ } @Override - protected void drawBackground(Batch batch, float parentAlpha, float x, float y){ - drawDefaultBackground(batch, parentAlpha, x, y); + protected void drawBackground(float x, float y){ + drawDefaultBackground(x, y); } private void save(){ String name = editor.getTags().get("name", ""); if(name.isEmpty()){ - ui.showError("$text.editor.save.noname"); + ui.showError("$editor.save.noname"); }else{ Map map = world.maps.getByName(name); if(map != null && !map.custom){ - ui.showError("$text.editor.save.overwrite"); + ui.showError("$editor.save.overwrite"); }else{ world.maps.saveMap(name, editor.getMap(), editor.getTags()); - ui.showInfoFade("$text.editor.saved"); + ui.showInfoFade("$editor.saved"); } } @@ -259,7 +251,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ float h = 90f; - dialog.content().defaults().size(360f, h).padBottom(5).padRight(5).padLeft(5); + dialog.cont.defaults().size(360f, h).padBottom(5).padRight(5).padLeft(5); for(int i = 0; i < arguments.length; i += 4){ String name = (String) arguments[i]; @@ -267,7 +259,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ String iconname = (String) arguments[i + 2]; Runnable listenable = (Runnable) arguments[i + 3]; - TextButton button = dialog.content().addButton(name, () -> { + TextButton button = dialog.cont.addButton(name, () -> { listenable.run(); dialog.hide(); menu.hide(); @@ -283,7 +275,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ button.row(); - dialog.content().row(); + dialog.cont.row(); } dialog.addCloseButton(); @@ -301,7 +293,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ } public void beginEditMap(InputStream is){ - ui.loadGraphics(() -> { + ui.loadAnd(() -> { try{ shownWithMap = true; DataInputStream stream = new DataInputStream(is); @@ -311,7 +303,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ show(); }catch(Exception e){ Log.err(e); - ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false))); } }); } @@ -326,7 +318,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ public void updateSelectedBlock(){ Block block = editor.getDrawBlock(); - for(int j = 0; j < content.blocks().size; j++){ + for(int j = 0; j < Vars.content.blocks().size; j++){ if(block.id == j && j < blockgroup.getButtons().size){ blockgroup.getButtons().get(j).setChecked(true); break; @@ -341,8 +333,8 @@ public class MapEditorDialog extends Dialog implements Disposable{ public void build(){ float amount = 10f, baseSize = 60f; - float size = mobile ? (int) (Math.min(Gdx.graphics.getHeight(), Gdx.graphics.getWidth()) / amount / Unit.dp.scl(1f)) : - Math.min(Gdx.graphics.getDisplayMode().height / amount, baseSize); + float size = mobile ? (int) (Math.min(Core.graphics.getHeight(), Core.graphics.getWidth()) / amount / Unit.dp.scl(1f)) : + Math.min(Core.graphics.getDisplayMode().height / amount, baseSize); clearChildren(); table(cont -> { @@ -398,7 +390,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ tools.row(); addTool.accept(EditorTool.fill); - addTool.accept(EditorTool.elevation); + addTool.accept(EditorTool.spray); ImageButton rotate = tools.addImageButton("icon-arrow-16", "clear", 16 * 2f, () -> editor.setDrawRotation((editor.getDrawRotation() + 1) % 4)).get(); rotate.getImage().update(() -> { @@ -408,8 +400,8 @@ public class MapEditorDialog extends Dialog implements Disposable{ tools.row(); - tools.table("underline", t -> t.add("$text.editor.teams")) - .colspan(3).height(40).width(size * 3f).padBottom(3); + tools.table("underline", t -> t.add("$editor.teams")) + .colspan(3).height(40).width(size * 3f + 3f).padBottom(3); tools.row(); @@ -439,29 +431,10 @@ public class MapEditorDialog extends Dialog implements Disposable{ slider.moved(f -> editor.setBrushSize(MapEditor.brushSizes[(int) (float) f])); t.top(); - t.add("$text.editor.brush"); + t.add("$editor.brush"); t.row(); t.add(slider).width(size * 3f - 20).padTop(4f); - }).padTop(5).growX().growY().top(); - - mid.row(); - - mid.table("underline", t -> t.add("$text.editor.elevation")) - .colspan(3).height(40).width(size * 3f); - - mid.row(); - - mid.table("underline", t -> { - t.margin(0); - t.addImageButton("icon-arrow-left", "clear-partial", 16 * 2f, () -> editor.setDrawElevation(editor.getDrawElevation() - 1)) - .disabled(b -> editor.getDrawElevation() <= -1).size(size); - - t.label(() -> editor.getDrawElevation() == -1 ? "$text.editor.slope" : (editor.getDrawElevation() + "")) - .size(size).get().setAlignment(Align.center, Align.center); - - t.addImageButton("icon-arrow-right", "clear-partial", 16 * 2f, () -> editor.setDrawElevation(editor.getDrawElevation() + 1)) - .disabled(b -> editor.getDrawElevation() >= 63).size(size); - }).colspan(3).height(size).width(size * 3f); + }).padTop(5).growX().top(); }).margin(0).left().growY(); @@ -476,35 +449,35 @@ public class MapEditorDialog extends Dialog implements Disposable{ private void doInput(){ //tool select for(int i = 0; i < EditorTool.values().length; i++){ - if(Inputs.keyTap(Input.valueOf("NUM_" + (i + 1)))){ + if(Core.input.keyTap(KeyCode.valueOf("NUM_" + (i + 1)))){ view.setTool(EditorTool.values()[i]); break; } } - if(Inputs.keyTap(Input.R)){ + if(Core.input.keyTap(KeyCode.R)){ editor.setDrawRotation((editor.getDrawRotation() + 1) % 4); } - if(Inputs.keyTap(Input.E)){ + if(Core.input.keyTap(KeyCode.E)){ editor.setDrawRotation(Mathf.mod((editor.getDrawRotation() + 1), 4)); } //ctrl keys (undo, redo, save) if(UIUtils.ctrl()){ - if(Inputs.keyTap(Input.Z)){ + if(Core.input.keyTap(KeyCode.Z)){ view.undo(); } - if(Inputs.keyTap(Input.Y)){ + if(Core.input.keyTap(KeyCode.Y)){ view.redo(); } - if(Inputs.keyTap(Input.S)){ + if(Core.input.keyTap(KeyCode.S)){ save(); } - if(Inputs.keyTap(Input.G)){ + if(Core.input.keyTap(KeyCode.G)){ view.setGrid(!view.isGrid()); } } @@ -512,7 +485,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ private void tryExit(){ if(!saved){ - ui.showConfirm("$text.confirm", "$text.editor.unsaved", this::hide); + ui.showConfirm("$confirm", "$editor.unsaved", this::hide); }else{ hide(); } @@ -528,29 +501,21 @@ public class MapEditorDialog extends Dialog implements Disposable{ int i = 0; - for(Block block : Vars.content.blocks()){ - TextureRegion[] regions = block.getCompactIcon(); - if((block.synthetic() && (Recipe.getByResult(block) == null || !control.unlocks.isUnlocked(Recipe.getByResult(block)))) - && block != StorageBlocks.core){ - continue; - } + 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)); - if(Recipe.getByResult(block) != null && !Recipe.getByResult(block).visibility.shown()){ - continue; - } + for(Block block : blocksOut){ + TextureRegion region = block.icon(Icon.medium); - if(regions.length == 0 || regions[0] == Draw.region("jjfgj")) continue; - - Stack stack = new Stack(); - - for(TextureRegion region : regions){ - stack.add(new Image(region)); - } + if(region == Core.atlas.find("jjfgj")) continue; ImageButton button = new ImageButton("white", "clear-toggle"); + button.getStyle().imageUp = new TextureRegionDrawable(region); button.clicked(() -> editor.setDrawBlock(block)); button.resizeImage(8 * 4f); - button.replaceImage(stack); button.update(() -> button.setChecked(editor.getDrawBlock() == block)); group.add(button); content.add(button).size(50f); diff --git a/core/src/io/anuke/mindustry/editor/MapInfoDialog.java b/core/src/io/anuke/mindustry/editor/MapInfoDialog.java index 6f4a046d45..f1e81e7ab0 100644 --- a/core/src/io/anuke/mindustry/editor/MapInfoDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapInfoDialog.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.editor; -import com.badlogic.gdx.utils.ObjectMap; +import io.anuke.arc.Core; +import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.scene.ui.TextArea; +import io.anuke.arc.scene.ui.TextField; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.ui.dialogs.FloatingDialog; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.scene.ui.TextArea; -import io.anuke.ucore.scene.ui.TextField; public class MapInfoDialog extends FloatingDialog{ private final MapEditor editor; @@ -15,7 +15,7 @@ public class MapInfoDialog extends FloatingDialog{ private TextField name; public MapInfoDialog(MapEditor editor){ - super("$text.editor.mapinfo"); + super("$editor.mapinfo"); this.editor = editor; addCloseButton(); @@ -28,44 +28,37 @@ public class MapInfoDialog extends FloatingDialog{ } private void setup(){ - content().clear(); + cont.clear(); ObjectMap tags = editor.getTags(); - content().add("$text.editor.name").padRight(8).left(); + cont.add("$editor.name").padRight(8).left(); - content().defaults().padTop(15); + cont.defaults().padTop(15); - name = content().addField(tags.get("name", ""), text -> { + name = cont.addField(tags.get("name", ""), text -> { tags.put("name", text); }).size(400, 55f).get(); - name.setMessageText("$text.unknown"); + name.setMessageText("$unknown"); - content().row(); + cont.row(); - content().add("$text.editor.description").padRight(8).left(); + cont.add("$editor.description").padRight(8).left(); - description = content().addArea(tags.get("description", ""), "textarea", text -> { + description = cont.addArea(tags.get("description", ""), "textarea", text -> { tags.put("description", text); }).size(400f, 140f).get(); - content().row(); + cont.row(); - content().add("$text.editor.author").padRight(8).left(); + cont.add("$editor.author").padRight(8).left(); - author = content().addField(tags.get("author", Settings.getString("mapAuthor", "")), text -> { + author = cont.addField(tags.get("author", Core.settings.getString("mapAuthor", "")), text -> { tags.put("author", text); - Settings.putString("mapAuthor", text); - Settings.save(); + Core.settings.put("mapAuthor", text); + Core.settings.save(); }).size(400, 55f).get(); - author.setMessageText("$text.unknown"); - - content().row(); - - content().add().padRight(8).left(); - content().addCheck("$text.editor.oregen", enabled -> { - tags.put("oregen", enabled ? "1" : "0"); - }).update(c -> c.setChecked(!tags.get("oregen", "0").equals("0"))).left(); + author.setMessageText("$unknown"); name.change(); description.change(); diff --git a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java index c819cd0a3a..0955dcdc6a 100644 --- a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java @@ -1,14 +1,14 @@ package io.anuke.mindustry.editor; -import com.badlogic.gdx.utils.Scaling; +import io.anuke.arc.util.Scaling; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.ui.BorderImage; import io.anuke.mindustry.ui.dialogs.FloatingDialog; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.scene.ui.ButtonGroup; -import io.anuke.ucore.scene.ui.ScrollPane; -import io.anuke.ucore.scene.ui.TextButton; -import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.scene.ui.ButtonGroup; +import io.anuke.arc.scene.ui.ScrollPane; +import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.scene.ui.layout.Table; import static io.anuke.mindustry.Vars.world; @@ -16,12 +16,12 @@ public class MapLoadDialog extends FloatingDialog{ private Map selected = null; public MapLoadDialog(Consumer loader){ - super("$text.editor.loadmap"); + super("$editor.loadmap"); shown(this::rebuild); rebuild(); - TextButton button = new TextButton("$text.load"); + TextButton button = new TextButton("$load"); button.setDisabled(() -> selected == null); button.clicked(() -> { if(selected != null){ @@ -30,13 +30,13 @@ public class MapLoadDialog extends FloatingDialog{ } }); - buttons().defaults().size(200f, 50f); - buttons().addButton("$text.cancel", this::hide); - buttons().add(button); + buttons.defaults().size(200f, 50f); + buttons.addButton("$cancel", this::hide); + buttons.add(button); } public void rebuild(){ - content().clear(); + cont.clear(); if(world.maps.all().size > 0){ selected = world.maps.all().first(); } @@ -67,13 +67,13 @@ public class MapLoadDialog extends FloatingDialog{ } if(world.maps.all().size == 0){ - table.add("$text.maps.none").center(); + table.add("$maps.none").center(); }else{ - content().add("$text.editor.loadmap"); + cont.add("$editor.loadmap"); } - content().row(); - content().add(pane); + cont.row(); + cont.add(pane); } } diff --git a/core/src/io/anuke/mindustry/editor/MapRenderer.java b/core/src/io/anuke/mindustry/editor/MapRenderer.java index bd4b7b8f43..5917cd67a2 100644 --- a/core/src/io/anuke/mindustry/editor/MapRenderer.java +++ b/core/src/io/anuke/mindustry/editor/MapRenderer.java @@ -1,21 +1,20 @@ package io.anuke.mindustry.editor; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.utils.Disposable; -import com.badlogic.gdx.utils.IntSet; -import com.badlogic.gdx.utils.IntSet.IntSetIterator; +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.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.maps.MapTileData.DataPosition; import io.anuke.mindustry.world.Block; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.IndexedRenderer; -import io.anuke.ucore.util.Structs; -import io.anuke.ucore.util.Bits; -import io.anuke.ucore.util.Geometry; +import io.anuke.mindustry.world.Block.Icon; import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.tilesize; @@ -27,7 +26,6 @@ public class MapRenderer implements Disposable{ private IntSet delayedUpdates = new IntSet(); private MapEditor editor; private int width, height; - private Color tmpColor = Color.WHITE.cpy(); public MapRenderer(MapEditor editor){ this.editor = editor; @@ -56,7 +54,7 @@ public class MapRenderer implements Disposable{ public void draw(float tx, float ty, float tw, float th){ - Graphics.end(); + Draw.flush(); IntSetIterator it = updates.iterator(); while(it.hasNext){ @@ -79,15 +77,12 @@ public class MapRenderer implements Disposable{ mesh = chunks[x][y]; } - mesh.getTransformMatrix().setToTranslation(tx, ty, 0).scl(tw / (width * tilesize), - th / (height * tilesize), 1f); - mesh.setProjectionMatrix(Core.batch.getProjectionMatrix()); + mesh.getTransformMatrix().setToTranslation(tx, ty).scale(tw / (width * tilesize), th / (height * tilesize)); + mesh.setProjectionMatrix(Draw.proj()); mesh.render(Core.atlas.getTextures().first()); } } - - Graphics.begin(); } public void updatePoint(int x, int y){ @@ -106,75 +101,58 @@ public class MapRenderer implements Disposable{ private void render(int wx, int wy){ int x = wx / chunksize, y = wy / chunksize; IndexedRenderer mesh = chunks[x][y]; - //TileDataMarker data = editor.getMap().readAt(wx, wy); byte bf = editor.getMap().read(wx, wy, DataPosition.floor); byte bw = editor.getMap().read(wx, wy, DataPosition.wall); byte btr = editor.getMap().read(wx, wy, DataPosition.rotationTeam); - byte elev = editor.getMap().read(wx, wy, DataPosition.elevation); - byte rotation = Bits.getLeftByte(btr); - Team team = Team.all[Bits.getRightByte(btr)]; + byte rotation = Pack.leftByte(btr); + Team team = Team.all[Pack.rightByte(btr)]; Block floor = content.block(bf); Block wall = content.block(bw); TextureRegion region; - if(bw != 0){ - region = wall.getEditorIcon(); + int idxWall = (wx % chunksize) + (wy % chunksize) * chunksize; + 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); if(wall.rotate){ - mesh.draw((wx % chunksize) + (wy % chunksize) * chunksize, region, + mesh.draw(idxWall, region, wx * tilesize + wall.offset(), wy * tilesize + wall.offset(), - region.getRegionWidth(), region.getRegionHeight(), rotation * 90 - 90); + region.getWidth() * Draw.scl, region.getHeight() * Draw.scl, rotation * 90 - 90); }else{ - mesh.draw((wx % chunksize) + (wy % chunksize) * chunksize, region, - wx * tilesize + wall.offset() + (tilesize - region.getRegionWidth())/2f, - wy * tilesize + wall.offset() + (tilesize - region.getRegionHeight())/2f, - region.getRegionWidth(), region.getRegionHeight()); + mesh.draw(idxWall, region, + wx * tilesize + wall.offset() + (tilesize - region.getWidth() * Draw.scl)/2f, + wy * tilesize + wall.offset() + (tilesize - region.getHeight() * Draw.scl)/2f, + region.getWidth() * Draw.scl, region.getHeight() * Draw.scl); } }else{ - region = floor.getEditorIcon(); + region = floor.variantRegions()[Mathf.randomSeed(idxWall, 0, floor.variantRegions().length-1)]; - mesh.draw((wx % chunksize) + (wy % chunksize) * chunksize, region, wx * tilesize, wy * tilesize, 8, 8); + mesh.draw(idxWall, region, wx * tilesize, wy * tilesize, 8, 8); } - boolean check = checkElevation(elev, wx, wy); + float offsetX = -(wall.size/3)*tilesize, offsetY = -(wall.size/3) * tilesize; if(wall.update || wall.destructible){ mesh.setColor(team.color); - region = Draw.region("block-border"); - }else if(elev > 0 && check){ - mesh.setColor(tmpColor.fromHsv((360f * elev / 127f * 4f) % 360f, 0.5f + (elev / 4f) % 0.5f, 1f)); - region = Draw.region("block-elevation"); - }else if(elev == -1){ - region = Draw.region("block-slope"); + region = Core.atlas.find("block-border"); + }else if(!wall.synthetic() && bw != 0){ + region = wall.icon(Icon.full) == Core.atlas.find("____") ? Core.atlas.find("clear") : wall.icon(Icon.full); + offsetX = tilesize/2f - region.getWidth()/2f * Draw.scl; + offsetY = tilesize/2f - region.getHeight()/2f * Draw.scl; }else{ - region = Draw.region("clear"); + region = Core.atlas.find("clear"); } - mesh.draw((wx % chunksize) + (wy % chunksize) * chunksize + chunksize * chunksize, region, - wx * tilesize - (wall.size/3) * tilesize, wy * tilesize - (wall.size/3) * tilesize, - region.getRegionWidth(), region.getRegionHeight()); + mesh.draw(idxDecal, region, + wx * tilesize + offsetX, wy * tilesize + offsetY, + region.getWidth() * Draw.scl, region.getHeight() * Draw.scl); mesh.setColor(Color.WHITE); } - private boolean checkElevation(byte elev, int x, int y){ - for(GridPoint2 p : Geometry.d4){ - int wx = x + p.x, wy = y + p.y; - if(!Structs.inBounds(wx, wy, editor.getMap().width(), editor.getMap().height())){ - return true; - } - byte value = editor.getMap().read(wx, wy, DataPosition.elevation); - - if(value < elev){ - return true; - }else if(value > elev){ - delayedUpdates.add(wx + wy * width); - } - } - return false; - } - @Override public void dispose(){ if(chunks == null){ diff --git a/core/src/io/anuke/mindustry/editor/MapResizeDialog.java b/core/src/io/anuke/mindustry/editor/MapResizeDialog.java index 84f2ae4d51..b0a9ec2cfb 100644 --- a/core/src/io/anuke/mindustry/editor/MapResizeDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapResizeDialog.java @@ -1,21 +1,19 @@ package io.anuke.mindustry.editor; +import io.anuke.arc.function.BiConsumer; +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; -import io.anuke.ucore.function.BiConsumer; -import io.anuke.ucore.scene.ui.ButtonGroup; -import io.anuke.ucore.scene.ui.TextButton; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Mathf; 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){ - super("$text.editor.resizemap"); + super("$editor.resizemap"); shown(() -> { - content().clear(); + cont.clear(); MapTileData data = editor.getMap(); width = data.width(); height = data.height(); @@ -23,41 +21,39 @@ 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); + table.defaults().height(60f).padTop(8); + table.addButton("<", () -> { + if(w) + width = move(width, -1); + else + height = move(height, -1); + }).size(60f); - table.add(w ? "$text.width" : "$text.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.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(); } - content().row(); - content().add(table); + cont.row(); + cont.add(table); }); - buttons().defaults().size(200f, 50f); - buttons().addButton("$text.cancel", this::hide); - buttons().addButton("$text.editor.resize", () -> { + buttons.defaults().size(200f, 50f); + buttons.addButton("$cancel", this::hide); + buttons.addButton("$editor.resize", () -> { 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/MapSaveDialog.java b/core/src/io/anuke/mindustry/editor/MapSaveDialog.java index a8a377b921..7d00f33d22 100644 --- a/core/src/io/anuke/mindustry/editor/MapSaveDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapSaveDialog.java @@ -3,9 +3,9 @@ package io.anuke.mindustry.editor; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.ui.dialogs.FloatingDialog; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.scene.ui.TextButton; -import io.anuke.ucore.scene.ui.TextField; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.scene.ui.TextField; import static io.anuke.mindustry.Vars.ui; import static io.anuke.mindustry.Vars.world; @@ -15,34 +15,34 @@ public class MapSaveDialog extends FloatingDialog{ private Consumer listener; public MapSaveDialog(Consumer cons){ - super("$text.editor.savemap"); + super("$editor.savemap"); field = new TextField(); listener = cons; Platform.instance.addDialog(field); shown(() -> { - content().clear(); - content().label(() -> { + cont.clear(); + cont.label(() -> { Map map = world.maps.getByName(field.getText()); if(map != null){ if(map.custom){ - return "$text.editor.overwrite"; + return "$editor.overwrite"; }else{ - return "$text.editor.failoverwrite"; + return "$editor.failoverwrite"; } } return ""; }).colspan(2); - content().row(); - content().add("$text.editor.mapname").padRight(14f); - content().add(field).size(220f, 48f); + cont.row(); + cont.add("$editor.mapname").padRight(14f); + cont.add(field).size(220f, 48f); }); - buttons().defaults().size(200f, 50f).pad(2f); - buttons().addButton("$text.cancel", this::hide); + buttons.defaults().size(200f, 50f).pad(2f); + buttons.addButton("$cancel", this::hide); - TextButton button = new TextButton("$text.save"); + TextButton button = new TextButton("$save"); button.clicked(() -> { if(!invalid()){ cons.accept(field.getText()); @@ -50,14 +50,14 @@ public class MapSaveDialog extends FloatingDialog{ } }); button.setDisabled(this::invalid); - buttons().add(button); + buttons.add(button); } public void save(){ if(!invalid()){ listener.accept(field.getText()); }else{ - ui.showError("$text.editor.failoverwrite"); + ui.showError("$editor.failoverwrite"); } } diff --git a/core/src/io/anuke/mindustry/editor/MapView.java b/core/src/io/anuke/mindustry/editor/MapView.java index baa0edca5c..d382439978 100644 --- a/core/src/io/anuke/mindustry/editor/MapView.java +++ b/core/src/io/anuke/mindustry/editor/MapView.java @@ -1,32 +1,27 @@ package io.anuke.mindustry.editor; -import com.badlogic.gdx.Input.Buttons; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.input.GestureDetector; -import com.badlogic.gdx.input.GestureDetector.GestureListener; -import com.badlogic.gdx.math.Bresenham2; -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Array; +import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; +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.ScissorStack; +import io.anuke.arc.input.GestureDetector; +import io.anuke.arc.input.GestureDetector.GestureListener; +import io.anuke.arc.input.KeyCode; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.*; +import io.anuke.arc.scene.Element; +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.ui.TextField; +import io.anuke.arc.scene.ui.layout.Unit; +import io.anuke.arc.util.Tmp; import io.anuke.mindustry.editor.DrawOperation.TileOperation; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.ui.GridImage; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.core.Inputs; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.scene.Element; -import io.anuke.ucore.scene.event.InputEvent; -import io.anuke.ucore.scene.event.InputListener; -import io.anuke.ucore.scene.event.Touchable; -import io.anuke.ucore.scene.ui.TextField; -import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.util.Geometry; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Tmp; import static io.anuke.mindustry.Vars.mobile; import static io.anuke.mindustry.Vars.ui; @@ -57,11 +52,13 @@ public class MapView extends Element implements GestureListener{ for(int i = 0; i < MapEditor.brushSizes.length; i++){ float size = MapEditor.brushSizes[i]; - brushPolygons[i] = Geometry.pixelCircle(size, (index, x, y) -> Vector2.dst(x, y, index, index) <= index - 0.5f); + brushPolygons[i] = Geometry.pixelCircle(size, (index, x, y) -> Mathf.dst(x, y, index, index) <= index - 0.5f); } - Inputs.addProcessor(0, new GestureDetector(20, 0.5f, 2, 0.15f, this)); - setTouchable(Touchable.enabled); + Core.input.getInputProcessors().insert(0, new GestureDetector(20, 0.5f, 2, 0.15f, this)); + touchable(Touchable.enabled); + + Point2 firstTouch = new Point2(); addListener(new InputListener(){ @@ -72,18 +69,17 @@ public class MapView extends Element implements GestureListener{ return false; } - @Override - public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){ + public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){ if(pointer != 0){ return false; } - if(!mobile && button != Buttons.LEFT && button != Buttons.MIDDLE){ + if(!mobile && button != KeyCode.MOUSE_LEFT && button != KeyCode.MOUSE_MIDDLE){ return true; } - if(button == Buttons.MIDDLE){ + if(button == KeyCode.MOUSE_MIDDLE){ lastTool = tool; tool = EditorTool.zoom; } @@ -95,12 +91,13 @@ public class MapView extends Element implements GestureListener{ updated = false; - GridPoint2 p = project(x, y); + Point2 p = project(x, y); lastx = p.x; lasty = p.y; startx = p.x; starty = p.y; tool.touched(editor, p.x, p.y); + firstTouch.set(p); if(tool.edit){ updated = true; @@ -112,20 +109,28 @@ public class MapView extends Element implements GestureListener{ } @Override - public void touchUp(InputEvent event, float x, float y, int pointer, int button){ - if(!mobile && button != Buttons.LEFT && button != Buttons.MIDDLE){ + public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){ + if(!mobile && button != KeyCode.MOUSE_LEFT && button != KeyCode.MOUSE_MIDDLE){ return; } drawing = false; - GridPoint2 p = project(x, y); + 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(GridPoint2 point : points){ - editor.draw(point.x, point.y); + Array points = br.line(startx, starty, p.x, p.y); + for(Point2 point : points){ + editor.draw(point.x, point.y, EditorTool.isPaint()); } updated = true; } @@ -137,7 +142,7 @@ public class MapView extends Element implements GestureListener{ op = null; } - if(lastTool != null){ + if(button == KeyCode.MOUSE_MIDDLE && lastTool != null){ tool = lastTool; lastTool = null; } @@ -146,21 +151,33 @@ public class MapView extends Element implements GestureListener{ @Override public void touchDragged(InputEvent event, float x, float y, int pointer){ + mousex = x; mousey = y; - GridPoint2 p = project(x, y); + Point2 p = project(x, y); - if(drawing && tool.draggable){ + if(drawing && tool.draggable && !(p.x == lastx && p.y == lasty)){ ui.editor.resetSaved(); - Array points = br.line(lastx, lasty, p.x, p.y); - for(GridPoint2 point : points){ + Array points = br.line(lastx, lasty, p.x, p.y); + for(Point2 point : points){ tool.touched(editor, point.x, point.y); } 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; + } } }); } @@ -214,24 +231,34 @@ public class MapView extends Element implements GestureListener{ super.act(delta); if(Core.scene.getKeyboardFocus() == null || !(Core.scene.getKeyboardFocus() instanceof TextField) && - !Inputs.keyDown(io.anuke.ucore.input.Input.CONTROL_LEFT)){ - float ax = Inputs.getAxis("move_x"); - float ay = Inputs.getAxis("move_y"); + !Core.input.keyDown(KeyCode.CONTROL_LEFT)){ + float ax = Core.input.axis(Binding.move_x); + float ay = Core.input.axis(Binding.move_y); offsetx -= ax * 15f / zoom; 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 += Inputs.scroll() / 10f * zoom; + zoom += Core.input.axis(KeyCode.SCROLL) / 10f * zoom; clampZoom(); } private void clampZoom(){ - zoom = Mathf.clamp(zoom, 0.2f, 12f); + zoom = Mathf.clamp(zoom, 0.2f, 20f); } - private GridPoint2 project(float x, float y){ + private Point2 project(float x, float y){ float ratio = 1f / ((float) editor.getMap().width() / editor.getMap().height()); float size = Math.min(width, height); float sclwidth = size * zoom; @@ -258,7 +285,7 @@ public class MapView extends Element implements GestureListener{ } @Override - public void draw(Batch batch, float alpha){ + public void draw(){ float ratio = 1f / ((float) editor.getMap().width() / editor.getMap().height()); float size = Math.min(width, height); float sclwidth = size * zoom; @@ -268,18 +295,24 @@ public class MapView extends Element implements GestureListener{ image.setImageSize(editor.getMap().width(), editor.getMap().height()); - Graphics.beginClip(x, y, width, height); + if(!ScissorStack.pushScissors(rect.set(x, y, width, height))){ + 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); Draw.reset(); + if(!ScissorStack.pushScissors(rect.set(x, y, width, height))){ + return; + } + if(grid){ Draw.color(Color.GRAY); image.setBounds(centerx - sclwidth / 2, centery - sclheight / 2, sclwidth, sclheight); - image.draw(batch, alpha); + image.draw(); Draw.color(); } @@ -293,10 +326,10 @@ public class MapView extends Element implements GestureListener{ float scaling = zoom * Math.min(width, height) / editor.getMap().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; @@ -306,14 +339,14 @@ public class MapView extends Element implements GestureListener{ Lines.poly(brushPolygons[index], v2.x, v2.y, scaling); } - if(tool.edit && (!mobile || drawing)){ - GridPoint2 p = project(mousex, mousey); + 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); } }else{ if((tool.edit || tool == EditorTool.line) && (!mobile || drawing)){ - GridPoint2 p = project(mousex, mousey); + Point2 p = project(mousex, mousey); Vector2 v = unproject(p.x, p.y).add(x, y); float offset = (editor.getDrawBlock().size % 2 == 0 ? scaling / 2f : 0f); Lines.square( @@ -323,51 +356,27 @@ public class MapView extends Element implements GestureListener{ } } - Graphics.endClip(); - - Draw.color(Palette.accent); + Draw.color(Pal.accent); Lines.stroke(Unit.dp.scl(3f)); Lines.rect(x, y, width, height); Draw.reset(); + + ScissorStack.popScissors(); + ScissorStack.popScissors(); } private boolean active(){ return Core.scene.getKeyboardFocus() != null && Core.scene.getKeyboardFocus().isDescendantOf(ui.editor) && ui.editor.isShown() && tool == EditorTool.zoom && - Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true) == this; - } - - @Override - public boolean touchDown(float x, float y, int pointer, int button){ - return false; - } - - @Override - public boolean tap(float x, float y, int count, int button){ - return false; - } - - @Override - public boolean longPress(float x, float y){ - return false; - } - - @Override - public boolean fling(float velocityX, float velocityY, int button){ - return false; + Core.scene.hit(Core.input.mouse().x, Core.input.mouse().y, true) == this; } @Override public boolean pan(float x, float y, float deltaX, float deltaY){ if(!active()) return false; offsetx += deltaX / zoom; - offsety -= deltaY / zoom; - return false; - } - - @Override - public boolean panStop(float x, float y, int pointer, int button){ + offsety += deltaY / zoom; return false; } diff --git a/core/src/io/anuke/mindustry/editor/OperationStack.java b/core/src/io/anuke/mindustry/editor/OperationStack.java index 402da3cf5e..aa53bb3afa 100755 --- a/core/src/io/anuke/mindustry/editor/OperationStack.java +++ b/core/src/io/anuke/mindustry/editor/OperationStack.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.editor; -import com.badlogic.gdx.utils.Array; +import io.anuke.arc.collection.Array; public class OperationStack{ private final static int maxSize = 10; @@ -22,7 +22,7 @@ public class OperationStack{ stack.add(action); if(stack.size > maxSize){ - stack.removeIndex(0); + stack.remove(0); } } diff --git a/core/src/io/anuke/mindustry/entities/Damage.java b/core/src/io/anuke/mindustry/entities/Damage.java index 23f00d7e10..79194260c7 100644 --- a/core/src/io/anuke/mindustry/entities/Damage.java +++ b/core/src/io/anuke/mindustry/entities/Damage.java @@ -1,26 +1,24 @@ package io.anuke.mindustry.entities; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.content.bullets.TurretBullets; -import io.anuke.mindustry.content.fx.ExplosionFx; -import io.anuke.mindustry.content.fx.Fx; +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; +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.mindustry.content.Bullets; +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 io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.function.Predicate; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Physics; -import io.anuke.ucore.util.Translator; import static io.anuke.mindustry.Vars.*; @@ -28,41 +26,41 @@ import static io.anuke.mindustry.Vars.*; public class Damage{ private static Rectangle rect = new Rectangle(); private static Rectangle hitrect = new Rectangle(); - private static Translator tr = new Translator(); + private static Vector2 tr = new Vector2(); /**Creates a dynamic explosion based on specified parameters.*/ 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); - Timers.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))); } for(int i = 0; i < Mathf.clamp(flammability / 4, 0, 30); i++){ - Timers.run(i / 2f, () -> Call.createBullet(TurretBullets.fireball, x, y, Mathf.random(360f))); + Time.run(i / 2f, () -> Call.createBullet(Bullets.fireball, x, y, Mathf.random(360f))); } int waves = Mathf.clamp((int) (explosiveness / 4), 0, 30); for(int i = 0; i < waves; i++){ int f = i; - Timers.run(i * 2f, () -> { - threads.run(() -> Damage.damage(x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 2f)); - Effects.effect(ExplosionFx.blockExplosionSmoke, x + Mathf.range(radius), y + Mathf.range(radius)); + Time.run(i * 2f, () -> { + Damage.damage(x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 2f); + Effects.effect(Fx.blockExplosionSmoke, x + Mathf.range(radius), y + Mathf.range(radius)); }); } if(explosiveness > 15f){ - Effects.effect(ExplosionFx.shockwave, x, y); + Effects.effect(Fx.shockwave, x, y); } if(explosiveness > 30f){ - Effects.effect(ExplosionFx.bigShockwave, x, y); + Effects.effect(Fx.bigShockwave, x, y); } float shake = Math.min(explosiveness / 4f + 3f, 9f); Effects.shake(shake, shake, x, y); - Effects.effect(ExplosionFx.blockExplosion, x, y); + Effects.effect(Fx.blockExplosion, x, y); } public static void createIncend(float x, float y, float range, int amount){ @@ -111,15 +109,15 @@ public class Damage{ rect.width += expand * 2; rect.height += expand * 2; - Consumer cons = e -> { - e.getHitbox(hitrect); + Consumer cons = e -> { + e.hitbox(hitrect); Rectangle other = hitrect; other.y -= expand; other.x -= expand; other.width += expand * 2; other.height += expand * 2; - Vector2 vec = Physics.raycastRect(x, y, x2, y2, other); + Vector2 vec = Geometry.raycastRect(x, y, x2, y2, other); if(vec != null){ Effects.effect(effect, vec.x, vec.y); @@ -132,11 +130,11 @@ 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.getHitbox(hitrect); + entity.hitbox(hitrect); if(!hitrect.overlaps(rect)){ return; } @@ -160,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.distanceTo(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.getVelocity().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); @@ -180,8 +178,8 @@ public class Damage{ int trad = (int) (radius / tilesize); for(int dx = -trad; dx <= trad; dx++){ for(int dy = -trad; dy <= trad; dy++){ - Tile tile = world.tile(Mathf.scl2(x, tilesize) + dx, Mathf.scl2(y, tilesize) + dy); - if(tile != null && tile.entity != null && (team == null || state.teams.areEnemies(team, tile.getTeam())) && Vector2.dst(dx, dy, 0, 0) <= trad){ + Tile tile = world.tile(Math.round(x / tilesize) + dx, Math.round(y / tilesize) + dy); + if(tile != null && tile.entity != null && (team == null || state.teams.areEnemies(team, tile.getTeam())) && Mathf.dst(dx, dy, 0, 0) <= trad){ float amount = calculateDamage(x, y, tile.worldx(), tile.worldy(), radius, damage); tile.entity.damage(amount); } @@ -191,7 +189,7 @@ public class Damage{ } private static float calculateDamage(float x, float y, float tx, float ty, float radius, float damage){ - float dist = Vector2.dst(x, y, tx, ty); + float dist = Mathf.dst(x, y, tx, ty); float falloff = 0.4f; float scaled = Mathf.lerp(1f - dist / radius, 1f, falloff); return damage * scaled; 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/Predict.java b/core/src/io/anuke/mindustry/entities/Predict.java index 09d589bffd..d4a935c173 100644 --- a/core/src/io/anuke/mindustry/entities/Predict.java +++ b/core/src/io/anuke/mindustry/entities/Predict.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.entities; -import com.badlogic.gdx.math.Vector2; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Vector2; import io.anuke.mindustry.entities.traits.TargetTrait; -import io.anuke.ucore.util.Mathf; /** * Class for predicting shoot angles based on velocities of targets. 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 b4b19d65e8..0000000000 --- a/core/src/io/anuke/mindustry/entities/UnitInventory.java +++ /dev/null @@ -1,89 +0,0 @@ -package io.anuke.mindustry.entities; - -import io.anuke.mindustry.content.Items; -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(Items.stone, 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 0d0584371c..d9c82f7ec0 100644 --- a/core/src/io/anuke/mindustry/entities/Units.java +++ b/core/src/io/anuke/mindustry/entities/Units.java @@ -1,18 +1,19 @@ package io.anuke.mindustry.entities; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; +import io.anuke.arc.collection.EnumSet; +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; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.EntityQuery; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.function.Predicate; -import io.anuke.ucore.util.EnumSet; -import io.anuke.ucore.util.Geometry; import static io.anuke.mindustry.Vars.*; @@ -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. @@ -38,7 +38,7 @@ public class Units{ * @return whether the target is invalid */ public static boolean invalidateTarget(TargetTrait target, Team team, float x, float y, float range){ - return target == null || (range != Float.MAX_VALUE && target.distanceTo(x, y) > range) || target.getTeam() == team || !target.isValid(); + return target == null || (range != Float.MAX_VALUE && target.dst(x, y) > range) || target.getTeam() == team || !target.isValid(); } /**See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}*/ @@ -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().getRange()); + return invalidateTarget(target, targeter.getTeam(), targeter.x, targeter.y, targeter.getWeapon().bullet.range()); } /**Returns whether there are any entities on this tile.*/ @@ -67,7 +67,7 @@ public class Units{ Units.getNearby(rect, unit -> { if(boolResult) return; if(!unit.isFlying()){ - unit.getHitbox(hitrect); + unit.hitbox(hitrect); if(hitrect.overlaps(rect)){ boolResult = true; @@ -89,7 +89,7 @@ public class Units{ Units.getNearby(rect, unit -> { if(value[0] || !pred.test(unit) || unit.isDead()) return; if(!unit.isFlying()){ - unit.getHitbox(hitrect); + unit.hitbox(hitrect); if(hitrect.overlaps(rect)){ value[0] = true; @@ -101,18 +101,18 @@ public class Units{ } /**Returns the neareset damaged tile.*/ - public static TileEntity findDamagedTile(Team team, float x, float y){ + public static io.anuke.mindustry.entities.type.TileEntity findDamagedTile(Team team, float x, float y){ Tile tile = Geometry.findClosest(x, y, world.indexer.getDamaged(team)); return tile == null ? null : tile.entity; } /**Returns the neareset ally tile in a range.*/ - public static TileEntity findAllyTile(Team team, float x, float y, float range, Predicate pred){ + public static io.anuke.mindustry.entities.type.TileEntity findAllyTile(Team team, float x, float y, float range, Predicate pred){ return world.indexer.findTile(team, x, y, range, pred); } /**Returns the neareset enemy tile in a range.*/ - public static TileEntity findEnemyTile(Team team, float x, float y, float range, Predicate pred){ + public static io.anuke.mindustry.entities.type.TileEntity findEnemyTile(Team team, float x, float y, float range, Predicate pred){ for(Team enemy : state.teams.enemiesOf(team)){ TileEntity entity = world.indexer.findTile(enemy, x, y, range, pred); if(entity != null){ @@ -134,7 +134,7 @@ public class Units{ } //then check all player groups - for(Player player : playerGroup.all()){ + for(io.anuke.mindustry.entities.type.Player player : playerGroup.all()){ cons.accept(player); } } @@ -165,7 +165,7 @@ public class Units{ if(e.isDead() || !predicate.test(e)) return; - float dist = Vector2.dst(e.x, e.y, x, y); + float dist = Mathf.dst(e.x, e.y, x, y); if(dist < range){ if(result == null || dist < cdist){ result = e; @@ -188,7 +188,7 @@ public class Units{ if(!predicate.test(e)) return; - float dist = Vector2.dst(e.x, e.y, x, y); + float dist = Mathf.dst(e.x, e.y, x, y); if(dist < range){ if(result == null || dist < cdist){ result = e; @@ -210,7 +210,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); }); } @@ -221,7 +221,7 @@ public class Units{ EntityGroup group = unitGroups[team.ordinal()]; if(!group.isEmpty()){ EntityQuery.getNearby(group, rect, entity -> { - if(entity.distanceTo(x, y) <= radius){ + if(entity.dst(x, y) <= radius){ cons.accept((Unit) entity); } }); @@ -229,7 +229,7 @@ public class Units{ //now check all players EntityQuery.getNearby(playerGroup, rect, player -> { - if(((Unit) player).team == team && player.distanceTo(x, y) <= radius){ + if(((Unit) player).getTeam() == team && player.dst(x, y) <= radius){ cons.accept((Unit) player); } }); @@ -262,7 +262,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 e0c9af0c27..5c74a9f9f7 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/ArtilleryBulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/ArtilleryBulletType.java @@ -1,13 +1,13 @@ package io.anuke.mindustry.entities.bullet; -import io.anuke.mindustry.content.fx.BulletFx; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.graphics.Draw; +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; //TODO scale velocity depending on fslope() public class ArtilleryBulletType extends BasicBulletType{ - protected Effect trailEffect = BulletFx.artilleryTrail; + protected Effect trailEffect = Fx.artilleryTrail; public ArtilleryBulletType(float speed, float damage, String bulletSprite){ super(speed, damage, bulletSprite); @@ -34,9 +34,9 @@ public class ArtilleryBulletType extends BasicBulletType{ float height = bulletHeight * ((1f - bulletShrink) + bulletShrink * b.fout()); Draw.color(backColor); - Draw.rect(backRegion, b.x, b.y, bulletWidth * scale, height * scale, b.angle() - 90); + Draw.rect(backRegion, b.x, b.y, bulletWidth * scale, height * scale, b.rot() - 90); Draw.color(frontColor); - Draw.rect(frontRegion, b.x, b.y, bulletWidth * scale, height * scale, b.angle() - 90); + Draw.rect(frontRegion, b.x, b.y, bulletWidth * scale, height * scale, b.rot() - 90); Draw.color(); } } diff --git a/core/src/io/anuke/mindustry/entities/bullet/BasicBulletType.java b/core/src/io/anuke/mindustry/entities/bullet/BasicBulletType.java index d130585cae..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 com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; +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.arc.math.Angles; +import io.anuke.arc.math.Mathf; 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.ucore.core.Effects; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; +import io.anuke.mindustry.graphics.Pal; -/** - * A BulletType for most ammo-based bullets shot from turrets and units. - */ +/**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; @@ -35,6 +34,9 @@ public class BasicBulletType extends BulletType{ public float homingPower = 0f; public float homingRange = 50f; + public int lightining; + public int lightningLength = 5; + public TextureRegion backRegion; public TextureRegion frontRegion; @@ -47,8 +49,8 @@ public class BasicBulletType extends BulletType{ @Override public void load(){ - backRegion = Draw.region(bulletSprite + "-back"); - frontRegion = Draw.region(bulletSprite); + backRegion = Core.atlas.find(bulletSprite + "-back"); + frontRegion = Core.atlas.find(bulletSprite); } @Override @@ -56,9 +58,9 @@ public class BasicBulletType extends BulletType{ float height = bulletHeight * ((1f - bulletShrink) + bulletShrink * b.fout()); Draw.color(backColor); - Draw.rect(backRegion, b.x, b.y, bulletWidth, height, b.angle() - 90); + Draw.rect(backRegion, b.x, b.y, bulletWidth, height, b.rot() - 90); Draw.color(frontColor); - Draw.rect(frontRegion, b.x, b.y, bulletWidth, height, b.angle() - 90); + Draw.rect(frontRegion, b.x, b.y, bulletWidth, height, b.rot() - 90); Draw.color(); } @@ -69,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.getVelocity().setAngle(Angles.moveToward(b.getVelocity().angle(), b.angleTo(target), homingPower * Timers.delta())); + b.velocity().setAngle(Mathf.slerpDelta(b.velocity().angle(), b.angleTo(target), 0.08f)); } } } @@ -103,5 +105,9 @@ public class BasicBulletType extends BulletType{ if(fragBullet != null || splashDamageRadius > 0){ hit(b); } + + for (int i = 0; i < lightining; i++) { + 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 f918d6ce8b..9206c8d6c3 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java +++ b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java @@ -1,24 +1,22 @@ package io.anuke.mindustry.entities.bullet; -import com.badlogic.gdx.math.Vector2; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.impl.SolidEntity; +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.Interval; +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.traits.*; +import io.anuke.mindustry.entities.type.Unit; 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.game.Team; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.impl.BulletEntity; -import io.anuke.ucore.entities.trait.Entity; -import io.anuke.ucore.entities.trait.SolidTrait; -import io.anuke.ucore.entities.trait.VelocityTrait; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Pooling; -import io.anuke.ucore.util.Timer; import java.io.DataInput; import java.io.DataOutput; @@ -26,14 +24,18 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.*; -public class Bullet extends BulletEntity implements TeamTrait, SyncTrait, AbsorbTrait{ - private static Vector2 vector = new Vector2(); - public Timer timer = new Timer(3); +public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Poolable, DrawTrait, VelocityTrait, TimeTrait, TeamTrait, SyncTrait, AbsorbTrait{ + public Interval timer = new Interval(3); + private float lifeScl; private Team team; private Object data; private boolean supressCollision, supressOnce, initialized; + protected BulletType type; + protected Entity owner; + protected float time; + /**Internal use only!*/ public Bullet(){ } @@ -55,21 +57,21 @@ public class Bullet extends BulletEntity implements TeamTrait, SyncT } public static Bullet create(BulletType type, Entity owner, Team team, float x, float y, float angle, float velocityScl, float lifetimeScl, Object data){ - Bullet bullet = Pooling.obtain(Bullet.class, Bullet::new); + Bullet bullet = Pools.obtain(Bullet.class, Bullet::new); bullet.type = type; bullet.owner = owner; bullet.data = data; bullet.velocity.set(0, type.speed).setAngle(angle).scl(velocityScl); if(type.keepVelocity){ - bullet.velocity.add(owner instanceof VelocityTrait ? ((VelocityTrait) owner).getVelocity() : Vector2.Zero); + bullet.velocity.add(owner instanceof VelocityTrait ? ((VelocityTrait) owner).velocity() : Vector2.ZERO); } bullet.team = team; bullet.type = type; bullet.lifeScl = lifetimeScl; - bullet.set(x - bullet.velocity.x * Timers.delta(), y - bullet.velocity.y * Timers.delta()); + bullet.set(x - bullet.velocity.x * Time.delta(), y - bullet.velocity.y * Time.delta()); bullet.add(); return bullet; @@ -83,11 +85,16 @@ public class Bullet extends BulletEntity implements TeamTrait, SyncT return create(type, parent.owner, parent.team, x, y, angle, velocityScl); } + /**Internal use only.*/ @Remote(called = Loc.server) public static void createBullet(BulletType type, float x, float y, float angle){ create(type, null, Team.none, x, y, angle); } + public Entity getOwner(){ + return owner; + } + public boolean collidesTiles(){ return type.collidesTiles; } @@ -97,12 +104,6 @@ public class Bullet extends BulletEntity implements TeamTrait, SyncT supressOnce = true; } - @Override - public void absorb(){ - supressCollision = true; - remove(); - } - public BulletType getBulletType(){ return type; } @@ -124,22 +125,29 @@ public class Bullet extends BulletEntity implements TeamTrait, SyncT this.data = data; } + @Override + public void absorb(){ + supressCollision = true; + remove(); + } + @Override public float drawSize(){ return type.drawSize; } @Override - public float getDamage(){ + public float damage(){ + //todo hacky way to get damage, refactor if(owner instanceof Unit){ - return super.getDamage() * ((Unit) owner).getDamageMultipler(); + return type.damage * ((Unit) owner).getDamageMultipler(); } if(owner instanceof Lightning && data instanceof Float){ return (Float)data; } - return super.getDamage(); + return type.damage; } @Override @@ -158,7 +166,7 @@ public class Bullet extends BulletEntity implements TeamTrait, SyncT } @Override - public void read(DataInput data, long time) throws IOException{ + public void read(DataInput data) throws IOException{ x = data.readFloat(); y = data.readFloat(); velocity.x = data.readFloat(); @@ -172,35 +180,44 @@ public class Bullet extends BulletEntity implements TeamTrait, SyncT return team; } - @Override - public void draw(){ - type.draw(this); - } - @Override public float getShieldDamage(){ - return Math.max(getDamage(), type.splashDamage); + return Math.max(damage(), type.splashDamage); } @Override public boolean collides(SolidTrait other){ - return type.collides && super.collides(other) && !supressCollision && !(other instanceof Unit && ((Unit) other).isFlying() && !type.collidesAir); + return type.collides && (other != owner && !(other instanceof DamageTrait)) && !supressCollision && !(other instanceof Unit && ((Unit) other).isFlying() && !type.collidesAir); } @Override public void collision(SolidTrait other, float x, float y){ - super.collision(other, x, y); + if(!type.pierce) remove(); + type.hit(this, x, y); if(other instanceof Unit){ Unit unit = (Unit) other; - unit.getVelocity().add(vector.set(other.getX(), other.getY()).sub(x, y).setLength(type.knockback / unit.getMass())); - unit.applyEffect(type.status, type.statusIntensity); + unit.velocity().add(Tmp.v3.set(other.getX(), other.getY()).sub(x, y).setLength(type.knockback / unit.mass())); + unit.applyEffect(type.status, type.statusDuration); } } @Override public void update(){ - super.update(); + type.update(this); + + x += velocity.x * Time.delta(); + y += velocity.y * Time.delta(); + + velocity.scl(Mathf.clamp(1f - type.drag * Time.delta())); + + time += Time.delta() * 1f/(lifeScl); + time = Mathf.clamp(time, 0, type.lifetime); + + if(time >= type.lifetime){ + if(!supressCollision) type.despawned(this); + remove(); + } if(type.hitTiles && collidesTiles() && !supressCollision && initialized){ world.raycastEach(world.toTile(lastPosition().x), world.toTile(lastPosition().y), world.toTile(x), world.toTile(y), (x, y) -> { @@ -234,20 +251,12 @@ public class Bullet extends BulletEntity implements TeamTrait, SyncT initialized = true; } - @Override - protected void updateLife(){ - time += Timers.delta() * 1f/(lifeScl); - time = Mathf.clamp(time, 0, type.lifetime()); - - if(time >= type.lifetime){ - if(!supressCollision) type.despawned(this); - remove(); - } - } - @Override public void reset(){ - super.reset(); + type = null; + owner = null; + velocity.setZero(); + time = 0f; timer.clear(); lifeScl = 1f; team = null; @@ -257,13 +266,78 @@ public class Bullet extends BulletEntity implements TeamTrait, SyncT initialized = false; } + @Override + public void hitbox(Rectangle rectangle){ + rectangle.setSize(type.hitSize).setCenter(x, y); + } + + @Override + public void hitboxTile(Rectangle rectangle){ + rectangle.setSize(type.hitSize).setCenter(x, y); + } + + @Override + public float lifetime(){ + return type.lifetime; + } + + @Override + public void time(float time){ + this.time = time; + } + + @Override + public float time(){ + return time; + } + @Override public void removed(){ - Pooling.free(this); + Pools.free(this); } @Override public EntityGroup targetGroup(){ return bulletGroup; } + + @Override + public void added(){ + type.init(this); + } + + @Override + public void draw(){ + type.draw(this); + } + + @Override + public float fin(){ + return time / type.lifetime; + } + + @Override + public Vector2 velocity(){ + return velocity; + } + + public void velocity(float speed, float angle){ + velocity.set(0, speed).setAngle(angle); + } + + public void limit(float f){ + velocity.limit(f); + } + + /** Sets the bullet's rotation in degrees.*/ + public void rot(float angle){ + velocity.setAngle(angle); + } + + /** @return the bullet's rotation.*/ + public float rot(){ + float angle = Mathf.atan2(velocity.x, velocity.y) * Mathf.radiansToDegrees; + if(angle < 0) angle += 360; + return angle; + } } diff --git a/core/src/io/anuke/mindustry/entities/bullet/BulletType.java b/core/src/io/anuke/mindustry/entities/bullet/BulletType.java index b6220dd9dd..198adaaf37 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/BulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/BulletType.java @@ -1,25 +1,36 @@ package io.anuke.mindustry.entities.bullet; +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.BulletFx; +import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.game.Content; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.StatusEffect; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.entities.impl.BaseBulletType; -import io.anuke.ucore.util.Translator; -public abstract class BulletType extends Content implements BaseBulletType{ +public abstract class BulletType extends Content{ public float lifetime; public float speed; public float damage; - public float hitsize = 4; - public float drawSize = 20f; + public float hitSize = 4; + public float drawSize = 40f; public float drag = 0f; public boolean pierce; - public Effect hiteffect, despawneffect; + public Effect hitEffect, despawnEffect; + + /**Effect created when shooting.*/ + public Effect shootEffect = Fx.shootSmall; + /**Extra smoke effect created when shooting.*/ + public Effect smokeEffect = Fx.shootSmallSmoke; + /**Extra inaccuracy when firing.*/ + public float inaccuracy = 0f; + /**How many bullets get created per ammo item/liquid.*/ + public float ammoMultiplier = 1f; + /**Multiplied by turret reload speed to get final shoot speed.*/ + public float reloadMultiplier = 1f; + /**Recoil from shooter entities.*/ + public float recoil; public float splashDamage = 0f; /**Knockback in velocity.*/ @@ -29,7 +40,7 @@ public abstract class BulletType extends Content implements BaseBulletType { if(b.getData() instanceof Float) return; - if(unit.distanceTo(b) < explodeRange){ + if(unit.dst(b) < explodeRange){ b.setData(0); - Timers.run(5f, () -> { + Time.run(5f, () -> { if(b.getData() instanceof Integer){ b.time(b.lifetime()); } diff --git a/core/src/io/anuke/mindustry/entities/bullet/LiquidBulletType.java b/core/src/io/anuke/mindustry/entities/bullet/LiquidBulletType.java index fa8b7164ee..6b4c7d8bb9 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/LiquidBulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/LiquidBulletType.java @@ -1,18 +1,17 @@ package io.anuke.mindustry.entities.bullet; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.GridPoint2; -import io.anuke.mindustry.content.fx.BulletFx; -import io.anuke.mindustry.content.fx.Fx; +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; +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.entities.effect.Fire; import io.anuke.mindustry.entities.effect.Puddle; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.util.Geometry; -import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; @@ -21,14 +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; - despawneffect = Fx.none; - hiteffect = BulletFx.hitLiquid; - drag = 0.01f; - knockback = 0.5f; + lifetime = 74f; + status = liquid.effect; + statusDuration = 90f; + despawnEffect = Fx.none; + hitEffect = Fx.hitLiquid; + shootEffect = Fx.none; + drag = 0.009f; + knockback = 0.55f; + } + + @Override + public float range(){ + return speed * lifetime /2f; } @Override @@ -54,13 +61,13 @@ public class LiquidBulletType extends BulletType{ @Override public void hit(Bullet b, float hitx, float hity){ - Effects.effect(hiteffect, liquid.color, hitx, hity); + Effects.effect(hitEffect, liquid.color, hitx, hity); Puddle.deposit(world.tileWorld(hitx, hity), liquid, 5f); if(liquid.temperature <= 0.5f && liquid.flammability < 0.3f){ float intensity = 400f; Fire.extinguish(world.tileWorld(hitx, hity), intensity); - for(GridPoint2 p : Geometry.d4){ + for(Point2 p : Geometry.d4){ Fire.extinguish(world.tileWorld(hitx + p.x * tilesize, hity + p.y * tilesize), intensity); } } diff --git a/core/src/io/anuke/mindustry/entities/bullet/MassDriverBolt.java b/core/src/io/anuke/mindustry/entities/bullet/MassDriverBolt.java new file mode 100644 index 0000000000..237aa09a15 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/bullet/MassDriverBolt.java @@ -0,0 +1,107 @@ +package io.anuke.mindustry.entities.bullet; + +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.Pal; +import io.anuke.mindustry.world.blocks.distribution.MassDriver.DriverBulletData; + +import static io.anuke.mindustry.Vars.content; + +public class MassDriverBolt extends BulletType{ + + public MassDriverBolt(){ + super(5.3f, 50); + collidesTiles = false; + lifetime = 200f; + despawnEffect = Fx.smeltsmoke; + hitEffect = Fx.hitBulletBig; + drag = 0.005f; + } + + @Override + public void draw(Bullet b){ + float w = 11f, h = 13f; + + Draw.color(Pal.bulletYellowBack); + Draw.rect("shell-back", b.x, b.y, w, h, b.rot() + 90); + + Draw.color(Pal.bulletYellow); + Draw.rect("shell", b.x, b.y, w, h, b.rot() + 90); + + Draw.reset(); + } + + @Override + public void update(Bullet b){ + //data MUST be an instance of DriverBulletData + if(!(b.getData() instanceof DriverBulletData)){ + hit(b); + return; + } + + float hitDst = 7f; + + DriverBulletData data = (DriverBulletData) b.getData(); + + //if the target is dead, just keep flying until the bullet explodes + if(data.to.isDead()){ + return; + } + + float baseDst = data.from.dst(data.to); + float dst1 = b.dst(data.from); + float dst2 = b.dst(data.to); + + boolean intersect = false; + + //bullet has gone past the destination point: but did it intersect it? + if(dst1 > baseDst){ + float angleTo = b.angleTo(data.to); + float baseAngle = data.to.angleTo(data.from); + + //if angles are nearby, then yes, it did + if(Angles.near(angleTo, baseAngle, 2f)){ + intersect = true; + //snap bullet position back; this is used for low-FPS situations + b.set(data.to.x + Angles.trnsx(baseAngle, hitDst), data.to.y + Angles.trnsy(baseAngle, hitDst)); + } + } + + //if on course and it's in range of the target + if(Math.abs(dst1 + dst2 - baseDst) < 4f && dst2 <= hitDst){ + intersect = true; + } //else, bullet has gone off course, does not get recieved. + + if(intersect){ + data.to.handlePayload(b, data); + } + } + + @Override + public void despawned(Bullet b){ + super.despawned(b); + + if(!(b.getData() instanceof DriverBulletData)) return; + + DriverBulletData data = (DriverBulletData) b.getData(); + data.to.isRecieving = false; + + for(int i = 0; i < data.items.length; i++){ + int amountDropped = Mathf.random(0, data.items[i]); + if(amountDropped > 0){ + float angle = b.rot() + Mathf.range(100f); + Effects.effect(Fx.dropItem, Color.WHITE, b.x, b.y, angle, content.item(i)); + } + } + } + + @Override + public void hit(Bullet b, float hitx, float hity){ + super.hit(b, hitx, hity); + despawned(b); + } +} diff --git a/core/src/io/anuke/mindustry/entities/bullet/MissileBulletType.java b/core/src/io/anuke/mindustry/entities/bullet/MissileBulletType.java index 7e75370183..351078866d 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/MissileBulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/MissileBulletType.java @@ -1,19 +1,22 @@ package io.anuke.mindustry.entities.bullet; -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.content.fx.BulletFx; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.util.Mathf; +import io.anuke.arc.graphics.Color; +import io.anuke.mindustry.content.Fx; +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; } @@ -21,8 +24,12 @@ public class MissileBulletType extends BasicBulletType{ public void update(Bullet b){ super.update(b); - if(Mathf.chance(Timers.delta() * 0.2)){ - Effects.effect(BulletFx.missileTrail, trailColor, b.x, b.y, 2f); + if(Mathf.chance(Time.delta() * 0.2)){ + Effects.effect(Fx.missileTrail, trailColor, b.x, b.y, 2f); + } + + if(weaveMag > 0){ + b.velocity().rotate(Mathf.sin(Time.time() + b.id * 4422, weaveScale, weaveMag)); } } } diff --git a/core/src/io/anuke/mindustry/entities/effect/Decal.java b/core/src/io/anuke/mindustry/entities/effect/Decal.java index 64c9facba6..1cb773a3cc 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Decal.java +++ b/core/src/io/anuke/mindustry/entities/effect/Decal.java @@ -1,12 +1,12 @@ package io.anuke.mindustry.entities.effect; -import com.badlogic.gdx.graphics.Color; +import io.anuke.arc.graphics.Color; import io.anuke.mindustry.entities.traits.BelowLiquidTrait; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.impl.TimedEntity; -import io.anuke.ucore.entities.trait.DrawTrait; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Mathf; +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; import static io.anuke.mindustry.Vars.groundEffectGroup; @@ -14,7 +14,7 @@ import static io.anuke.mindustry.Vars.groundEffectGroup; * Class for creating block rubble on the ground. */ public abstract class Decal extends TimedEntity implements BelowLiquidTrait, DrawTrait{ - private static final Color color = Color.valueOf("52504e"); + private static final Color color = Color.valueOf("3a3635"); @Override public float lifetime(){ diff --git a/core/src/io/anuke/mindustry/entities/effect/Fire.java b/core/src/io/anuke/mindustry/entities/effect/Fire.java index bf6e58c698..9689824893 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Fire.java +++ b/core/src/io/anuke/mindustry/entities/effect/Fire.java @@ -1,29 +1,29 @@ package io.anuke.mindustry.entities.effect; -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.utils.IntMap; -import com.badlogic.gdx.utils.Pool.Poolable; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; +import io.anuke.arc.collection.IntMap; +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; +import io.anuke.arc.util.Structs; +import io.anuke.arc.util.Time; +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.StatusEffects; -import io.anuke.mindustry.content.bullets.TurretBullets; -import io.anuke.mindustry.content.fx.EnvironmentFx; +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.Tile; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.impl.TimedEntity; -import io.anuke.ucore.util.Structs; -import io.anuke.ucore.util.Geometry; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Pooling; import java.io.DataInput; import java.io.DataOutput; @@ -51,7 +51,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ Fire fire = map.get(tile.pos()); if(fire == null){ - fire = Pooling.obtain(Fire.class, Fire::new); + fire = Pools.obtain(Fire.class, Fire::new); fire.tile = tile; fire.lifetime = baseLifetime; fire.set(tile.worldx(), tile.worldy()); @@ -76,7 +76,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ */ public static void extinguish(Tile tile, float intensity){ if(tile != null && map.containsKey(tile.pos())){ - map.get(tile.pos()).time += intensity * Timers.delta(); + map.get(tile.pos()).time += intensity * Time.delta(); } } @@ -92,19 +92,19 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ @Override public void update(){ - if(Mathf.chance(0.1 * Timers.delta())){ - Effects.effect(EnvironmentFx.fire, x + Mathf.range(4f), y + Mathf.range(4f)); + if(Mathf.chance(0.1 * Time.delta())){ + Effects.effect(Fx.fire, x + Mathf.range(4f), y + Mathf.range(4f)); } - if(Mathf.chance(0.05 * Timers.delta())){ - Effects.effect(EnvironmentFx.smoke, x + Mathf.range(4f), y + Mathf.range(4f)); + if(Mathf.chance(0.05 * Time.delta())){ + Effects.effect(Fx.fireSmoke, x + Mathf.range(4f), y + Mathf.range(4f)); } if(Net.client()){ return; } - time = Mathf.clamp(time + Timers.delta(), 0, lifetime()); + time = Mathf.clamp(time + Time.delta(), 0, lifetime()); if(time >= lifetime() || tile == null){ Call.onFireRemoved(getID()); @@ -118,7 +118,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ float flammability = baseFlammability + puddleFlammability; if(!damage && flammability <= 0){ - time += Timers.delta() * 8; + time += Time.delta() * 8; } if(baseFlammability < 0 || block != tile.block()){ @@ -127,20 +127,20 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ } if(damage){ - lifetime += Mathf.clamp(flammability / 8f, 0f, 0.6f) * Timers.delta(); + lifetime += Mathf.clamp(flammability / 8f, 0f, 0.6f) * Time.delta(); } - if(flammability > 1f && Mathf.chance(spreadChance * Timers.delta() * Mathf.clamp(flammability / 5f, 0.3f, 2f))){ - GridPoint2 p = Mathf.select(Geometry.d4); + if(flammability > 1f && Mathf.chance(spreadChance * Time.delta() * Mathf.clamp(flammability / 5f, 0.3f, 2f))){ + Point2 p = Geometry.d4[Mathf.random(3)]; Tile other = world.tile(tile.x + p.x, tile.y + p.y); create(other); - if(Mathf.chance(fireballChance * Timers.delta() * Mathf.clamp(flammability / 10.0))){ - Call.createBullet(TurretBullets.fireball, x, y, Mathf.random(360f)); + if(Mathf.chance(fireballChance * Time.delta() * Mathf.clamp(flammability / 10f))){ + Call.createBullet(Bullets.fireball, x, y, Mathf.random(360f)); } } - if(Mathf.chance(0.1 * Timers.delta())){ + if(Mathf.chance(0.1 * Time.delta())){ Puddle p = Puddle.getPuddle(tile); if(p != null){ puddleFlammability = p.getFlammability() / 3f; @@ -151,7 +151,9 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ if(damage){ entity.damage(0.4f); } - Damage.damageUnits(null, tile.worldx(), tile.worldy(), tilesize, 3f, unit -> !unit.isFlying(), unit -> unit.applyEffect(StatusEffects.burning, 0.8f)); + Damage.damageUnits(null, tile.worldx(), tile.worldy(), tilesize, 3f, + unit -> !unit.isFlying() && !unit.isImmune(StatusEffects.burning), + unit -> unit.applyEffect(StatusEffects.burning, 60 * 5)); } } @@ -177,7 +179,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{ } @Override - public void read(DataInput data, long time) throws IOException{ + public void read(DataInput data) throws IOException{ x = data.readFloat(); y = data.readFloat(); } diff --git a/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java b/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java index ceaceb8ba7..bc98f1619a 100644 --- a/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java +++ b/core/src/io/anuke/mindustry/entities/effect/GroundEffectEntity.java @@ -1,13 +1,13 @@ package io.anuke.mindustry.entities.effect; +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; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.impl.EffectEntity; -import io.anuke.ucore.core.Effects.EffectRenderer; -import io.anuke.ucore.util.Mathf; /** * A ground effect contains an effect that is rendered on the ground layer as opposed to the top layer. @@ -20,7 +20,7 @@ public class GroundEffectEntity extends EffectEntity{ GroundEffect effect = (GroundEffect) this.effect; if(effect.isStatic){ - time += Timers.delta(); + time += Time.delta(); time = Mathf.clamp(time, 0, effect.staticLife); diff --git a/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java b/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java index 90e35dd496..5083897a33 100644 --- a/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java +++ b/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java @@ -1,26 +1,25 @@ package io.anuke.mindustry.entities.effect; -import com.badlogic.gdx.math.Interpolation; -import com.badlogic.gdx.math.Vector2; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.entities.Unit; -import io.anuke.mindustry.graphics.Palette; +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; +import io.anuke.arc.math.Interpolation; +import io.anuke.arc.math.Mathf; +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.type.Unit; +import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.impl.TimedEntity; -import io.anuke.ucore.entities.trait.DrawTrait; -import io.anuke.ucore.entities.trait.PosTrait; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Pooling; import static io.anuke.mindustry.Vars.effectGroup; -import static io.anuke.mindustry.Vars.threads; public class ItemTransfer extends TimedEntity implements DrawTrait{ private Vector2 from = new Vector2(); @@ -28,7 +27,7 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{ private Vector2 tovec = new Vector2(); private Item item; private float seed; - private PosTrait to; + private Position to; private Runnable done; public ItemTransfer(){ @@ -44,21 +43,21 @@ 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) public static void transferItemTo(Item item, int amount, float x, float y, Tile tile){ if(tile == null || tile.entity == null || tile.entity.items == null) return; for(int i = 0; i < Mathf.clamp(amount / 3, 1, 8); i++){ - Timers.run(i * 3, () -> create(item, x, y, tile, () -> { + Time.run(i * 3, () -> create(item, x, y, tile, () -> { })); } tile.entity.items.add(item, amount); } - public static void create(Item item, float fromx, float fromy, PosTrait to, Runnable done){ - ItemTransfer tr = Pooling.obtain(ItemTransfer.class, ItemTransfer::new); + public static void create(Item item, float fromx, float fromy, Position to, Runnable done){ + ItemTransfer tr = Pools.obtain(ItemTransfer.class, ItemTransfer::new); tr.item = item; tr.from.set(fromx, fromy); tr.to = to; @@ -86,9 +85,9 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{ @Override public void removed(){ if(done != null){ - threads.run(done); + done.run(); } - Pooling.free(this); + Pools.free(this); } @Override @@ -106,14 +105,9 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{ @Override public void draw(){ - float length = fslope() * 6f; - float angle = current.set(x, y).sub(from).angle(); - Draw.color(Palette.accent); - Lines.stroke(fslope() * 2f); + Lines.stroke(fslope() * 2f, Pal.accent); Lines.circle(x, y, fslope() * 2f); - Lines.lineAngleCenter(x, y, angle, length); - Lines.lineAngle(x, y, angle, fout() * 6f); Draw.color(item.color); Fill.circle(x, y, fslope() * 1.5f); diff --git a/core/src/io/anuke/mindustry/entities/effect/Lightning.java b/core/src/io/anuke/mindustry/entities/effect/Lightning.java index 1cf162f286..7a89b29f9d 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Lightning.java +++ b/core/src/io/anuke/mindustry/entities/effect/Lightning.java @@ -1,27 +1,33 @@ package io.anuke.mindustry.entities.effect; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.IntSet; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.content.bullets.TurretBullets; -import io.anuke.mindustry.entities.Unit; +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.IntSet; +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.math.Angles; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.RandomXS128; +import io.anuke.arc.math.geom.Geometry; +import io.anuke.arc.math.geom.Position; +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.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.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.impl.TimedEntity; -import io.anuke.ucore.entities.trait.DrawTrait; -import io.anuke.ucore.entities.trait.PosTrait; -import io.anuke.ucore.entities.trait.TimeTrait; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.*; +import io.anuke.mindustry.graphics.Pal; import java.io.DataInput; import java.io.DataOutput; @@ -31,7 +37,7 @@ import static io.anuke.mindustry.Vars.bulletGroup; public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, TimeTrait{ public static final float lifetime = 10f; - private static final SeedRandom random = new SeedRandom(); + private static final RandomXS128 random = new RandomXS128(); private static final Rectangle rect = new Rectangle(); private static final Array entities = new Array<>(); private static final IntSet hit = new IntSet(); @@ -39,8 +45,8 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time private static final float hitRange = 30f; private static int lastSeed = 0; - private Array lines = new Array<>(); - private Color color = Palette.lancerLaser; + private Array lines = new Array<>(); + private Color color = Pal.lancerLaser; /**For pooling use only. Do not call directly!*/ public Lightning(){ @@ -55,7 +61,7 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time @Remote(called = Loc.server) public static void createLighting(int seed, Team team, Color color, float damage, float x, float y, float rotation, int length){ - Lightning l = Pooling.obtain(Lightning.class, Lightning::new); + Lightning l = Pools.obtain(Lightning.class, Lightning::new); Float dmg = damage; l.x = x; @@ -67,8 +73,8 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time hit.clear(); for (int i = 0; i < length/2; i++) { - Bullet.create(TurretBullets.damageLightning, l, team, x, y, 0f, 1f, 1f, dmg); - l.lines.add(new Translator(x + Mathf.range(3f), y + Mathf.range(3f))); + Bullet.create(Bullets.damageLightning, l, team, x, y, 0f, 1f, 1f, dmg); + l.lines.add(new Vector2(x + Mathf.range(3f), y + Mathf.range(3f))); rect.setSize(hitRange).setCenter(x, y); entities.clear(); @@ -103,7 +109,7 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time public void write(DataOutput data){} @Override - public void read(DataInput data, long time){} + public void read(DataInput data){} @Override public float lifetime(){ @@ -113,42 +119,34 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time @Override public void reset(){ super.reset(); - color = Palette.lancerLaser; + color = Pal.lancerLaser; lines.clear(); } @Override public void removed(){ super.removed(); - Pooling.free(this); + Pools.free(this); } @Override public void draw(){ - float lx = x, ly = y; + Lines.stroke(3f * fout()); Draw.color(color, Color.WHITE, fin()); - for(int i = 0; i < lines.size; i++){ - PosTrait v = lines.get(i); + Lines.beginLine(); - float f = (float) i / lines.size; - - Lines.stroke(fout() * 3f * (1.5f - f)); - - 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)); - // Lines.lineAngleCenter(lx, ly, Angles.angle(lx, ly, v.getX(), v.getY()) + 90f, 20f); - - lx = v.getX(); - ly = v.getY(); + Lines.linePoint(x, y); + for(Position p : lines){ + Lines.linePoint(p.getX(), p.getY()); } - Draw.color(); + Lines.endLine(); + + int i = 0; + + 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 ce9dfc4926..8c3eb67ff7 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Puddle.java +++ b/core/src/io/anuke/mindustry/entities/effect/Puddle.java @@ -1,17 +1,27 @@ package io.anuke.mindustry.entities.effect; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.utils.IntMap; -import com.badlogic.gdx.utils.Pool.Poolable; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; +import io.anuke.arc.collection.IntMap; +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; +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.Point2; +import io.anuke.arc.math.geom.Rectangle; +import io.anuke.arc.util.Time; +import io.anuke.arc.util.pooling.Pool.Poolable; +import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.content.bullets.TurretBullets; -import io.anuke.mindustry.content.fx.BlockFx; -import io.anuke.mindustry.content.fx.EnvironmentFx; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.content.Bullets; +import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.SaveTrait; import io.anuke.mindustry.entities.traits.SyncTrait; @@ -19,18 +29,6 @@ import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.impl.SolidEntity; -import io.anuke.ucore.entities.trait.DrawTrait; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.graphics.Hue; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Geometry; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Pooling; import java.io.DataInput; import java.io.DataOutput; @@ -85,10 +83,10 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai Puddle p = map.get(tile.pos()); - if(generation == 0 && p != null && p.lastRipple <= Timers.time() - 40f){ - Effects.effect(BlockFx.ripple, tile.floor().liquidDrop.color, + if(generation == 0 && p != null && p.lastRipple <= Time.time() - 40f){ + Effects.effect(Fx.ripple, tile.floor().liquidDrop.color, (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); - p.lastRipple = Timers.time(); + p.lastRipple = Time.time(); } return; } @@ -97,7 +95,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai if(p == null){ if(Net.client()) return; //not clientside. - Puddle puddle = Pooling.obtain(Puddle.class, Puddle::new); + Puddle puddle = Pools.obtain(Puddle.class, Puddle::new); puddle.tile = tile; puddle.liquid = liquid; puddle.amount = amount; @@ -108,9 +106,9 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai }else if(p.liquid == liquid){ p.accepting = Math.max(amount, p.accepting); - if(generation == 0 && p.lastRipple <= Timers.time() - 40f && p.amount >= maxLiquid / 2f){ - Effects.effect(BlockFx.ripple, p.liquid.color, (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); - p.lastRipple = Timers.time(); + if(generation == 0 && p.lastRipple <= Time.time() - 40f && p.amount >= maxLiquid / 2f){ + Effects.effect(Fx.ripple, p.liquid.color, (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); + p.lastRipple = Time.time(); } }else{ p.amount += reactPuddle(p.liquid, liquid, amount, p.tile, p.x, p.y); @@ -131,16 +129,16 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai (liquid.flammability > 0.3f && dest.temperature > 0.7f)){ //flammable liquid + hot liquid Fire.create(tile); if(Mathf.chance(0.006 * amount)){ - Call.createBullet(TurretBullets.fireball, x, y, Mathf.random(360f)); + Call.createBullet(Bullets.fireball, x, y, Mathf.random(360f)); } }else if(dest.temperature > 0.7f && liquid.temperature < 0.55f){ //cold liquid poured onto hot puddle if(Mathf.chance(0.5f * amount)){ - Effects.effect(EnvironmentFx.steam, x, y); + Effects.effect(Fx.steam, x, y); } return -0.1f * amount; }else if(liquid.temperature > 0.7f && dest.temperature < 0.55f){ //hot liquid poured onto cold puddle if(Mathf.chance(0.8f * amount)){ - Effects.effect(EnvironmentFx.steam, x, y); + Effects.effect(Fx.steam, x, y); } return -0.4f * amount; } @@ -157,12 +155,12 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai } @Override - public void getHitbox(Rectangle rectangle){ + public void hitbox(Rectangle rectangle){ rectangle.setCenter(x, y).setSize(tilesize); } @Override - public void getHitboxTile(Rectangle rectangle){ + public void hitboxTile(Rectangle rectangle){ rectangle.setCenter(x, y).setSize(0f); } @@ -176,16 +174,16 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai //update code float addSpeed = accepting > 0 ? 3f : 0f; - amount -= Timers.delta() * (1f - liquid.viscosity) / (5f + addSpeed); + amount -= Time.delta() * (1f - liquid.viscosity) / (5f + addSpeed); amount += accepting; accepting = 0f; if(amount >= maxLiquid / 1.5f && generation < maxGeneration){ - float deposited = Math.min((amount - maxLiquid / 1.5f) / 4f, 0.3f) * Timers.delta(); - for(GridPoint2 point : Geometry.d4){ + float deposited = Math.min((amount - maxLiquid / 1.5f) / 4f, 0.3f) * Time.delta(); + for(Point2 point : Geometry.d4){ Tile other = world.tile(tile.x + point.x, tile.y + point.y); - if(other != null && other.block() == Blocks.air && !other.hasCliffs()){ + if(other != null && other.block() == Blocks.air){ deposit(other, tile, liquid, deposited, generation + 1); amount -= deposited / 2f; //tweak to speed up/slow down puddle propagation } @@ -204,24 +202,24 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai Units.getNearby(rect.setSize(Mathf.clamp(amount / (maxLiquid / 1.5f)) * 10f).setCenter(x, y), unit -> { if(unit.isFlying()) return; - unit.getHitbox(rect2); + unit.hitbox(rect2); if(!rect.overlaps(rect2)) return; - unit.applyEffect(liquid.effect, 0.5f); + unit.applyEffect(liquid.effect, 60 * 2); - if(unit.getVelocity().len() > 0.1){ - Effects.effect(BlockFx.ripple, liquid.color, unit.x, unit.y); + if(unit.velocity().len() > 0.1){ + Effects.effect(Fx.ripple, liquid.color, unit.x, unit.y); } }); - if(liquid.temperature > 0.7f && tile.entity != null && Mathf.chance(0.3 * Timers.delta())){ + if(liquid.temperature > 0.7f && (tile.target().entity != null) && Mathf.chance(0.3 * Time.delta())){ Fire.create(tile); } updateTime = 20f; } - updateTime -= Timers.delta(); + updateTime -= Time.delta(); } @Override @@ -232,11 +230,11 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai float smag = onLiquid ? 0.8f : 0f; float sscl = 20f; - Draw.color(Hue.shift(tmp.set(liquid.color), 2, -0.05f)); - Fill.circle(x + Mathf.sin(Timers.time() + seeds * 532, sscl, smag), y + Mathf.sin(Timers.time() + seeds * 53, sscl, smag), f * 8f); + Draw.color(tmp.set(liquid.color).shiftValue(-0.05f)); + Fill.circle(x + Mathf.sin(Time.time() + seeds * 532, sscl, smag), y + Mathf.sin(Time.time() + seeds * 53, sscl, smag), f * 8f); Angles.randLenVectors(id, 3, f * 6f, (ex, ey) -> { - Fill.circle(x + ex + Mathf.sin(Timers.time() + seeds * 532, sscl, smag), - y + ey + Mathf.sin(Timers.time() + seeds * 53, sscl, smag), f * 5f); + Fill.circle(x + ex + Mathf.sin(Time.time() + seeds * 532, sscl, smag), + y + ey + Mathf.sin(Time.time() + seeds * 53, sscl, smag), f * 5f); seeds++; }); Draw.color(); @@ -302,7 +300,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai } @Override - public void read(DataInput data, long time) throws IOException{ + public void read(DataInput data) throws IOException{ x = data.readFloat(); y = data.readFloat(); liquid = content.liquid(data.readByte()); diff --git a/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java b/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java index 8fb5dedf98..51dda93718 100644 --- a/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java +++ b/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java @@ -1,7 +1,8 @@ package io.anuke.mindustry.entities.effect; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Mathf; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.math.Mathf; public class RubbleDecal extends Decal{ private int size; @@ -20,7 +21,7 @@ public class RubbleDecal extends Decal{ public void drawDecal(){ String region = "rubble-" + size + "-" + Mathf.randomSeed(id, 0, 1); - if(!Draw.hasRegion(region)){ + if(!Core.atlas.has(region)){ remove(); return; } diff --git a/core/src/io/anuke/mindustry/entities/effect/ScorchDecal.java b/core/src/io/anuke/mindustry/entities/effect/ScorchDecal.java index 7bfc3e369e..b9a4d35f84 100644 --- a/core/src/io/anuke/mindustry/entities/effect/ScorchDecal.java +++ b/core/src/io/anuke/mindustry/entities/effect/ScorchDecal.java @@ -1,11 +1,13 @@ package io.anuke.mindustry.entities.effect; -import com.badlogic.gdx.graphics.g2d.TextureRegion; +import io.anuke.arc.Core; +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.mindustry.world.Tile; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; +import static io.anuke.mindustry.Vars.headless; import static io.anuke.mindustry.Vars.world; public class ScorchDecal extends Decal{ @@ -13,9 +15,10 @@ 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] = Draw.region("scorch" + (i + 1)); + regions[i] = Core.atlas.find("scorch" + (i + 1)); } } @@ -30,12 +33,16 @@ public class ScorchDecal extends Decal{ @Override public void drawDecal(){ - for(int i = 0; i < 5; i++){ TextureRegion region = regions[Mathf.randomSeed(id - i, 0, scorches - 1)]; float rotation = Mathf.randomSeed(id + i, 0, 360); float space = 1.5f + Mathf.randomSeed(id + i + 1, 0, 20) / 10f; - Draw.grect(region, x + Angles.trnsx(rotation, space), y + Angles.trnsy(rotation, space), rotation - 90); + Draw.rect(region, + x + Angles.trnsx(rotation, space), + y + Angles.trnsy(rotation, space) + region.getHeight()/2f*Draw.scl, + region.getWidth() * Draw.scl, + region.getHeight() * Draw.scl, + region.getWidth()/2f*Draw.scl, 0, rotation - 90); } } } 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 445533dda3..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.ucore.entities.trait.DamageTrait; -import io.anuke.ucore.entities.trait.Entity; - public interface AbsorbTrait extends Entity, TeamTrait, DamageTrait{ void absorb(); @@ -11,6 +8,6 @@ public interface AbsorbTrait extends Entity, TeamTrait, DamageTrait{ } default float getShieldDamage(){ - return getDamage(); + return damage(); } } diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java index d4aad07db6..c9cc53e521 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java @@ -1,36 +1,36 @@ package io.anuke.mindustry.entities.traits; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Queue; +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.graphics.Color; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.Fill; +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.util.Time; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.content.fx.BlockFx; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.content.Fx; +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; -import io.anuke.mindustry.type.Recipe; +import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Build; import io.anuke.mindustry.world.Pos; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.BuildBlock; import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.trait.Entity; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.graphics.Shapes; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; import java.io.DataInput; import java.io.DataOutput; @@ -42,8 +42,9 @@ 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; float mineDistance = 70f; Array removal = new Array<>(); @@ -79,7 +80,7 @@ public interface BuilderTrait extends Entity{ output.writeInt(Pos.get(request.x, request.y)); output.writeFloat(request.progress); if(!request.breaking){ - output.writeByte(request.recipe.id); + output.writeByte(request.block.id); output.writeByte(request.rotation); } }else{ @@ -103,9 +104,9 @@ public interface BuilderTrait extends Entity{ if(type == 1){ //remove request = new BuildRequest(Pos.x(position), Pos.y(position)); }else{ //place - byte recipe = input.readByte(); + byte block = input.readByte(); byte rotation = input.readByte(); - request = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.recipe(recipe)); + request = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.block(block)); } request.progress = progress; @@ -123,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, Recipe recipe){ - for(BuildRequest request : getPlaceQueue()){ - if(request.x == x && request.y == y){ - clearBuilding(); - addBuildRequest(request); - return; - } - } - - addBuildRequest(new BuildRequest(x, y, rotation, recipe)); - } - /**Clears the placement queue.*/ default void clearBuilding(){ getPlaceQueue().clear(); @@ -170,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()){ @@ -181,9 +167,8 @@ 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.recipe.result.rotate) - && world.tile(request.x, request.y).block() == request.recipe.result))){ + (!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); } } @@ -193,7 +178,7 @@ public interface BuilderTrait extends Entity{ //update mining here if(current == null){ if(getMineTile() != null){ - updateMining(unit); + updateMining(); } return; }else{ @@ -202,15 +187,19 @@ public interface BuilderTrait extends Entity{ Tile tile = world.tile(current.x, current.y); - if(unit.distanceTo(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.recipe.result, current.rotation)){ - Build.beginPlace(unit.getTeam(), current.x, current.y, current.recipe, 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; @@ -232,7 +221,7 @@ public interface BuilderTrait extends Entity{ return; } - if(unit.distanceTo(tile) <= placeDistance){ + if(unit.dst(tile) <= placeDistance){ unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(entity), 0.4f); } @@ -240,9 +229,9 @@ public interface BuilderTrait extends Entity{ if(!Net.client()){ //deconstructing is 2x as fast if(current.breaking){ - entity.deconstruct(unit, core, 2f / entity.buildCost * Timers.delta() * getBuildPower(tile)); + entity.deconstruct(unit, core, 2f / entity.buildCost * Time.delta() * getBuildPower(tile)); }else{ - entity.construct(unit, core, 1f / entity.buildCost * Timers.delta() * getBuildPower(tile)); + entity.construct(unit, core, 1f / entity.buildCost * Time.delta() * getBuildPower(tile)); } current.progress = entity.progress(); @@ -251,30 +240,31 @@ public interface BuilderTrait extends Entity{ } if(!current.initialized){ - Gdx.app.postRunnable(() -> Events.fire(new BuildSelectEvent(tile, unit.getTeam(), this, current.breaking))); + Core.app.post(() -> Events.fire(new BuildSelectEvent(tile, unit.getTeam(), this, current.breaking))); current.initialized = true; } } /**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.distanceTo(tile.worldx(), tile.worldy()) > mineDistance - || tile.floor().drops == null || !unit.inventory.canAcceptItem(tile.floor().drops.item) || !canMine(tile.floor().drops.item)){ + 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().drops.item; + Item item = tile.floor().itemDrop; unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(tile.worldx(), tile.worldy()), 0.4f); - if(Mathf.chance(Timers.delta() * (0.06 - item.hardness * 0.01) * getMinePower())){ + if(Mathf.chance(Time.delta() * (0.06 - item.hardness * 0.01) * getMinePower())){ - if(unit.distanceTo(core) < mineTransferRange && core.tile.block().acceptStack(item, 1, core.tile, unit) == 1){ + if(unit.dst(core) < mineTransferRange && core.tile.block().acceptStack(item, 1, core.tile, unit) == 1){ 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), @@ -282,8 +272,8 @@ public interface BuilderTrait extends Entity{ } } - if(Mathf.chance(0.06 * Timers.delta())){ - Effects.effect(BlockFx.pulverizeSmall, + if(Mathf.chance(0.06 * Time.delta())){ + Effects.effect(Fx.pulverizeSmall, tile.worldx() + Mathf.range(tilesize / 2f), tile.worldy() + Mathf.range(tilesize / 2f), 0f, item.color); } @@ -291,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; } @@ -304,12 +295,12 @@ public interface BuilderTrait extends Entity{ Tile tile = world.tile(request.x, request.y); - if(unit.distanceTo(tile) > placeDistance){ + if(dst(tile) > placeDistance){ return; } - Draw.color(Palette.accent); - float focusLen = 3.8f + Mathf.absin(Timers.time(), 1.1f, 0.6f); + 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); @@ -322,7 +313,7 @@ public interface BuilderTrait extends Entity{ tmptr[3].set(tile.drawx() + sz, tile.drawy() + sz); Arrays.sort(tmptr, (a, b) -> -Float.compare(Angles.angleDist(Angles.angle(unit.x, unit.y, a.x, a.y), ang), - Angles.angleDist(Angles.angle(unit.x, unit.y, b.x, b.y), ang))); + Angles.angleDist(Angles.angle(unit.x, unit.y, b.x, b.y), ang))); float x1 = tmptr[0].x, y1 = tmptr[0].y, x3 = tmptr[1].x, y3 = tmptr[1].y; @@ -332,33 +323,35 @@ public interface BuilderTrait extends Entity{ Lines.line(px, py, x1, y1); Lines.line(px, py, x3, y3); - Fill.circle(px, py, 1.6f + Mathf.absin(Timers.time(), 0.8f, 1.5f)); + Fill.circle(px, py, 1.6f + Mathf.absin(Time.time(), 0.8f, 1.5f)); Draw.color(); } /**Internal use only.*/ - default void drawMining(Unit unit){ + default void drawMining(){ + Unit unit = (Unit)this; Tile tile = getMineTile(); if(tile == null) return; - float focusLen = 4f + Mathf.absin(Timers.time(), 1.1f, 0.5f); + float focusLen = 4f + Mathf.absin(Time.time(), 1.1f, 0.5f); float swingScl = 12f, swingMag = tilesize / 8f; float flashScl = 0.3f; float px = unit.x + Angles.trnsx(unit.rotation, focusLen); float py = unit.y + Angles.trnsy(unit.rotation, focusLen); - float ex = tile.worldx() + Mathf.sin(Timers.time() + 48, swingScl, swingMag); - float ey = tile.worldy() + Mathf.sin(Timers.time() + 48, swingScl + 2f, swingMag); + float ex = tile.worldx() + Mathf.sin(Time.time() + 48, swingScl, swingMag); + float ey = tile.worldy() + Mathf.sin(Time.time() + 48, swingScl + 2f, swingMag); + + Draw.color(Color.LIGHT_GRAY, Color.WHITE, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl)); - Draw.color(Color.LIGHT_GRAY, Color.WHITE, 1f - flashScl + Mathf.absin(Timers.time(), 0.5f, flashScl)); Shapes.laser("minelaser", "minelaser-end", px, py, ex, ey); if(unit instanceof Player && ((Player) unit).isLocal){ - Draw.color(Palette.accent); - Lines.poly(tile.worldx(), tile.worldy(), 4, tilesize / 2f * Mathf.sqrt2, Timers.time()); + Lines.stroke(1f, Pal.accent); + Lines.poly(tile.worldx(), tile.worldy(), 4, tilesize / 2f * Mathf.sqrt2, Time.time()); } Draw.color(); @@ -367,18 +360,18 @@ public interface BuilderTrait extends Entity{ /**Class for storing build requests. Can be either a place or remove request.*/ class BuildRequest{ public final int x, y, rotation; - public final Recipe recipe; + public final Block block; public final boolean breaking; public float progress; public boolean initialized; /**This creates a build request.*/ - public BuildRequest(int x, int y, int rotation, Recipe recipe){ + public BuildRequest(int x, int y, int rotation, Block block){ this.x = x; this.y = y; this.rotation = rotation; - this.recipe = recipe; + this.block = block; this.breaking = false; } @@ -387,7 +380,7 @@ public interface BuilderTrait extends Entity{ this.x = x; this.y = y; this.rotation = -1; - this.recipe = Recipe.getByResult(world.tile(x, y).block()); + this.block = world.tile(x, y).block(); this.breaking = true; } @@ -397,7 +390,7 @@ public interface BuilderTrait extends Entity{ "x=" + x + ", y=" + y + ", rotation=" + rotation + - ", recipe=" + recipe + + ", recipe=" + block + ", breaking=" + breaking + ", progress=" + progress + ", initialized=" + initialized + 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 296b782154..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.ucore.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 fdc052f787..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.UnitFx; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.gen.Call; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.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(UnitFx.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(UnitFx.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 4e7009771e..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.ucore.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 12df85dda1..ca3010eec3 100644 --- a/core/src/io/anuke/mindustry/entities/traits/ShooterTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/ShooterTrait.java @@ -1,12 +1,11 @@ package io.anuke.mindustry.entities.traits; +import io.anuke.arc.util.Interval; import io.anuke.mindustry.type.Weapon; -import io.anuke.ucore.entities.trait.VelocityTrait; -import io.anuke.ucore.util.Timer; -public interface ShooterTrait extends VelocityTrait, TeamTrait, InventoryTrait{ +public interface ShooterTrait extends VelocityTrait, TeamTrait{ - Timer getTimer(); + Interval getTimer(); int getShootTimer(boolean left); 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..cb98c0086a 100644 --- a/core/src/io/anuke/mindustry/entities/traits/SpawnerTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/SpawnerTrait.java @@ -1,12 +1,15 @@ package io.anuke.mindustry.entities.traits; -import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.world.Tile; -public interface SpawnerTrait{ +public interface SpawnerTrait extends TargetTrait{ 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 9509e4eb68..cbcc0317ee 100644 --- a/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java @@ -2,9 +2,8 @@ package io.anuke.mindustry.entities.traits; import io.anuke.mindustry.core.NetClient; import io.anuke.mindustry.net.Interpolator; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.entities.trait.Entity; -import io.anuke.ucore.util.Tmp; +import io.anuke.arc.Core; +import io.anuke.arc.util.Tmp; import java.io.DataInput; import java.io.DataOutput; @@ -33,8 +32,7 @@ public interface SyncTrait extends Entity, TypeTrait{ if(isClipped()){ //move off screen when no longer in bounds - Tmp.r1.setSize(Core.camera.viewportWidth * Core.camera.zoom * NetClient.viewScale, - Core.camera.viewportHeight * Core.camera.zoom * NetClient.viewScale) + Tmp.r1.setSize(Core.camera.width * NetClient.viewScale, Core.camera.height * NetClient.viewScale) .setCenter(Core.camera.position.x, Core.camera.position.y); if(!Tmp.r1.contains(getX(), getY()) && !Tmp.r1.contains(getInterpolator().last.x, getInterpolator().last.y)){ @@ -67,5 +65,5 @@ public interface SyncTrait extends Entity, TypeTrait{ //Read and write sync data, usually position void write(DataOutput data) throws IOException; - void read(DataInput data, long time) throws IOException; + void read(DataInput 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 bdeea6ea33..dcc7a876b9 100644 --- a/core/src/io/anuke/mindustry/entities/traits/TargetTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/TargetTrait.java @@ -1,14 +1,12 @@ package io.anuke.mindustry.entities.traits; +import io.anuke.arc.math.geom.Position; import io.anuke.mindustry.game.Team; -import io.anuke.ucore.entities.trait.PosTrait; -import io.anuke.ucore.entities.trait.SolidTrait; -import io.anuke.ucore.entities.trait.VelocityTrait; /** * Base interface for targetable entities. */ -public interface TargetTrait extends PosTrait, VelocityTrait{ +public interface TargetTrait extends Position, VelocityTrait{ boolean isDead(); @@ -18,14 +16,14 @@ public interface TargetTrait extends PosTrait, VelocityTrait{ if(this instanceof SolidTrait){ return ((SolidTrait) this).getDeltaX(); } - return getVelocity().x; + return velocity().x; } default float getTargetVelocityY(){ if(this instanceof SolidTrait){ return ((SolidTrait) this).getDeltaY(); } - return getVelocity().y; + return velocity().y; } /** diff --git a/core/src/io/anuke/mindustry/entities/traits/TeamTrait.java b/core/src/io/anuke/mindustry/entities/traits/TeamTrait.java index 3c7cbf7dd3..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.ucore.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/TypeTrait.java b/core/src/io/anuke/mindustry/entities/traits/TypeTrait.java index 774b2b4143..663575bb5f 100644 --- a/core/src/io/anuke/mindustry/entities/traits/TypeTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/TypeTrait.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.entities.traits; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.ObjectIntMap; -import io.anuke.ucore.function.Supplier; +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.ObjectIntMap; +import io.anuke.arc.function.Supplier; public interface TypeTrait{ int[] lastRegisteredID = {0}; 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 64% rename from core/src/io/anuke/mindustry/entities/units/BaseUnit.java rename to core/src/io/anuke/mindustry/entities/type/BaseUnit.java index f40e21c2c2..fe2e74e53c 100644 --- a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java @@ -1,34 +1,30 @@ -package io.anuke.mindustry.entities.units; +package io.anuke.mindustry.entities.type; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.Rectangle; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; +import io.anuke.arc.Core; +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.math.geom.Geometry; +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.ExplosionFx; -import io.anuke.mindustry.entities.Damage; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.Unit; +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.blocks.units.CommandCenter.CommandCenterEntity; import io.anuke.mindustry.world.meta.BlockFlag; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.*; import java.io.DataInput; import java.io.DataOutput; @@ -46,12 +42,10 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ protected static final int timerShootRight = timerIndex++; protected UnitType type; - protected Timer timer = new Timer(5); + protected Interval timer = new Interval(5); 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*/ @@ -66,28 +60,17 @@ 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(ExplosionFx.explosion, unit); - Effects.shake(2f, 2f, unit); - //must run afterwards so the unit's group is not null when sending the removal packet - threads.runDelay(unit::remove); + Core.app.post(unit::remove); } @Override - public float getDrag(){ + public float drag(){ return type.drag; } - /**Called when a command is recieved from the command center.*/ - public abstract void onCommand(UnitCommand command); - /**Initialize the type and team of this unit. Only call once!*/ public void init(UnitType type, Team team){ if(this.type != null) throw new RuntimeException("This unit is already initialized!"); @@ -96,17 +79,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ this.team = team; } - public boolean isCommanded(){ - return !isWave && world.indexer.getAllied(team, BlockFlag.comandCenter).size != 0 && world.indexer.getAllied(team, BlockFlag.comandCenter).first().entity instanceof CommandCenterEntity; - } - - public UnitCommand getCommand(){ - if(isCommanded()){ - return world.indexer.getAllied(team, BlockFlag.comandCenter).first().entity().command; - } - return null; - } - public UnitType getType(){ return type; } @@ -115,36 +87,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){ @@ -180,7 +128,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } public void targetClosest(){ - target = Units.getClosestTarget(team, x, y, Math.max(getWeapon().getAmmo().getRange(), 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(){ @@ -200,15 +148,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); @@ -216,13 +163,18 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } } + @Override + public boolean isImmune(StatusEffect effect){ + return type.immunities.contains(effect); + } + @Override public boolean isValid(){ return super.isValid() && isAdded(); } @Override - public Timer getTimer(){ + public Interval getTimer(){ return timer; } @@ -260,18 +212,13 @@ 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 getMass(){ + public float mass(){ return type.mass; } @@ -282,10 +229,9 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ @Override public void update(){ - hitTime -= Timers.delta(); + hitTime -= Time.delta(); if(isDead()){ - updateRespawning(); return; } @@ -301,10 +247,6 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ damage(health); } - if(squad != null){ - squad.update(); - } - updateTargeting(); state.update(); @@ -312,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 @@ -322,18 +265,23 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } @Override - public float getMaxVelocity(){ + public float maxVelocity(){ return type.maxVelocity; } @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 @@ -346,19 +294,15 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ state.set(getStartState()); health(maxHealth()); - - if(isCommanded()){ - onCommand(getCommand()); - } } @Override - public void getHitbox(Rectangle rectangle){ + public void hitbox(Rectangle rectangle){ rectangle.setSize(type.hitsize).setCenter(x, y); } @Override - public void getHitboxTile(Rectangle rectangle){ + public void hitboxTile(Rectangle rectangle){ rectangle.setSize(type.hitsizeTile).setCenter(x, y); } @@ -371,7 +315,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); } @@ -379,7 +322,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); @@ -393,12 +335,12 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } @Override - public void read(DataInput data, long time) throws IOException{ + public void read(DataInput data) throws IOException{ float lastx = x, lasty = y, lastrot = rotation; super.readSave(data); this.type = content.getByID(ContentType.unit, data.readByte()); - interpolator.read(lastx, lasty, x, y, time, rotation); + interpolator.read(lastx, lasty, x, y, rotation); rotation = lastrot; } 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..4a45929f39 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java @@ -0,0 +1,223 @@ +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.graphics.Shaders; +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.target); + 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.alpha(Draw.getShader() != Shaders.mix ? 1f : hitTime / hitDuration); + Draw.rect(type.region, x, y, rotation - 90); + + drawWeapons(); + drawItems(); + + Draw.alpha(1f); + } + + 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 56% rename from core/src/io/anuke/mindustry/entities/units/GroundUnit.java rename to core/src/io/anuke/mindustry/entities/type/GroundUnit.java index db01ba1ab1..56523419bc 100644 --- a/core/src/io/anuke/mindustry/entities/units/GroundUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java @@ -1,37 +1,30 @@ -package io.anuke.mindustry.entities.units; +package io.anuke.mindustry.entities.type; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.Vector2; +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.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.type.AmmoType; -import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.type.Weapon; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Translator; -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{ - protected static Translator vec = new Translator(); + protected static Vector2 vec = new Vector2(); protected float walkTime; protected float stuckTime; protected float baseRotation; - protected Weapon weapon; public final UnitState @@ -42,13 +35,13 @@ public abstract class GroundUnit extends BaseUnit{ public void update(){ TileEntity core = getClosestEnemyCore(); - float dst = core == null ? 0 : distanceTo(core); + float dst = core == null ? 0 : dst(core); - if(core != null && dst < getWeapon().getAmmo().getRange() / 1.1f){ + if(core != null && dst < getWeapon().bullet.range() / 1.1f){ target = core; } - if(dst > getWeapon().getAmmo().getRange() * 0.5f){ + if(dst > getWeapon().bullet.range() * 0.5f){ moveToCore(); } } @@ -57,42 +50,15 @@ public abstract class GroundUnit extends BaseUnit{ public void update(){ TileEntity target = getClosestCore(); if(target != null){ - if(distanceTo(target) > 400f){ + if(dst(target) > 400f){ moveAwayFromCore(); }else{ patrol(); } } } - }, - retreat = new UnitState(){ - public void entered(){ - target = null; - } - - public void update(){ - if(health >= maxHealth() && !isCommanded()){ - state.set(attack); - } - - moveAwayFromCore(); - } }; - @Override - public void onCommand(UnitCommand command){ - state.set(command == UnitCommand.retreat ? retreat : - command == UnitCommand.attack ? attack : - command == UnitCommand.patrol ? patrol : - null); - } - - @Override - public void init(UnitType type, Team team){ - super.init(type, team); - this.weapon = type.weapon; - } - @Override public void interpolate(){ super.interpolate(); @@ -105,7 +71,7 @@ public abstract class GroundUnit extends BaseUnit{ @Override public void move(float x, float y){ if(Mathf.dst(x, y) > 0.01f){ - baseRotation = Mathf.slerpDelta(baseRotation, Mathf.atan2(x, y), type.baseRotateSpeed); + baseRotation = Mathf.slerpDelta(baseRotation, Mathf.angle(x, y), type.baseRotateSpeed); } super.move(x, y); } @@ -119,31 +85,27 @@ public abstract class GroundUnit extends BaseUnit{ public void update(){ super.update(); - stuckTime = !vec.set(x, y).sub(lastPosition()).isZero(0.0001f) ? 0f : stuckTime + Timers.delta(); + stuckTime = !vec.set(x, y).sub(lastPosition()).isZero(0.0001f) ? 0f : stuckTime + Time.delta(); if(!velocity.isZero()){ baseRotation = Mathf.slerpDelta(baseRotation, velocity.angle(), 0.05f); } if(stuckTime < 1f){ - walkTime += Timers.delta(); + walkTime += Time.delta(); } } @Override public Weapon getWeapon(){ - return weapon; - } - - public void setWeapon(Weapon weapon){ - this.weapon = weapon; + return type.weapon; } @Override public void draw(){ - Draw.alpha(hitTime / hitDuration); + Draw.alpha(Draw.getShader() != Shaders.mix ? 1f : 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(); @@ -155,7 +117,7 @@ public abstract class GroundUnit extends BaseUnit{ 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){ @@ -169,11 +131,11 @@ 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(); @@ -183,18 +145,15 @@ public abstract class GroundUnit extends BaseUnit{ @Override public void behavior(){ - if(health <= health * type.retreatPercent && !isCommanded()){ - setState(retreat); - } if(!Units.invalidateTarget(target, this)){ - if(distanceTo(target) < getWeapon().getAmmo().getRange()){ + if(dst(target) < getWeapon().bullet.range()){ rotate(angleTo(target)); - if(Mathf.angNear(angleTo(target), rotation, 13f)){ - AmmoType ammo = getWeapon().getAmmo(); + if(Angles.near(angleTo(target), rotation, 13f)){ + BulletType ammo = getWeapon().bullet; - Vector2 to = Predict.intercept(GroundUnit.this, target, ammo.bullet.speed); + Vector2 to = Predict.intercept(GroundUnit.this, target, ammo.speed); getWeapon().update(GroundUnit.this, to.x, to.y); } @@ -213,37 +172,13 @@ 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, long time) throws IOException{ - super.read(data, time); - 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 * Timers.delta()); + vec.trns(baseRotation, type.speed * Time.delta()); velocity.add(vec.x, vec.y); vec.trns(baseRotation, type.hitsizeTile); Tile tile = world.tileWorld(x + vec.x, y + vec.y); if((tile == null || tile.solid() || tile.floor().drownTime > 0) || stuckTime > 10f){ - baseRotation += Mathf.sign(id % 2 - 0.5f) * Timers.delta() * 3f; + baseRotation += Mathf.sign(id % 2 - 0.5f) * Time.delta() * 3f; } rotation = Mathf.slerpDelta(rotation, velocity.angle(), type.rotatespeed); @@ -258,7 +193,7 @@ public abstract class GroundUnit extends BaseUnit{ vec.rotate((circleLength - vec.len()) / circleLength * 180f); } - vec.setLength(type.speed * Timers.delta()); + vec.setLength(type.speed * Time.delta()); velocity.add(vec); } @@ -272,8 +207,10 @@ public abstract class GroundUnit extends BaseUnit{ float angle = angleTo(targetTile); - velocity.add(vec.trns(angleTo(targetTile), type.speed*Timers.delta())); - rotation = Mathf.slerpDelta(rotation, angle, type.rotatespeed); + velocity.add(vec.trns(angleTo(targetTile), type.speed*Time.delta())); + if(Units.invalidateTarget(target, this)){ + rotation = Mathf.slerpDelta(rotation, angle, type.rotatespeed); + } } protected void moveAwayFromCore(){ @@ -292,11 +229,11 @@ public abstract class GroundUnit extends BaseUnit{ Tile targetTile = world.pathfinder.getTargetTile(enemy, tile); TileEntity core = getClosestCore(); - if(tile == targetTile || core == null || distanceTo(core) < 90f) return; + if(tile == targetTile || core == null || dst(core) < 90f) return; float angle = angleTo(targetTile); - velocity.add(vec.trns(angleTo(targetTile), type.speed*Timers.delta())); + velocity.add(vec.trns(angleTo(targetTile), type.speed*Time.delta())); rotation = Mathf.slerpDelta(rotation, angle, type.rotatespeed); } } diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/type/Player.java similarity index 64% rename from core/src/io/anuke/mindustry/entities/Player.java rename to core/src/io/anuke/mindustry/entities/type/Player.java index fe59b17711..c22a184ae0 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/type/Player.java @@ -1,36 +1,38 @@ -package io.anuke.mindustry.entities; +package io.anuke.mindustry.entities.type; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.GlyphLayout; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Queue; 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.graphics.Color; +import io.anuke.arc.graphics.g2d.*; +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.Rectangle; +import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.util.*; +import io.anuke.arc.util.pooling.Pools; +import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.content.Mechs; -import io.anuke.mindustry.content.fx.UnitFx; -import io.anuke.mindustry.entities.effect.ScorchDecal; -import io.anuke.mindustry.entities.traits.*; +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.Trail; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.graphics.Shaders; +import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.io.TypeIO; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetConnection; import io.anuke.mindustry.type.*; 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 io.anuke.ucore.core.*; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.EntityQuery; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Hue; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.*; import java.io.DataInput; import java.io.DataOutput; @@ -38,7 +40,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; @@ -54,25 +56,23 @@ 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; public boolean isLocal = false; - public Timer timer = new Timer(4); + public Interval timer = new Interval(4); public TargetTrait target; public TargetTrait moveTarget; private float walktime; private Queue placeQueue = new Queue<>(); private Tile mining; - private CarriableTrait carrying; - private Trail trail = new Trail(12); - private Vector2 movement = new Translator(); + private Vector2 movement = new Vector2(); private boolean moved; //endregion @@ -85,34 +85,48 @@ 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 - public void getHitbox(Rectangle rectangle){ + public void hitbox(Rectangle rectangle){ rectangle.setSize(mech.hitsize).setCenter(x, y); } @Override - public void getHitboxTile(Rectangle rectangle){ + public void hitboxTile(Rectangle rectangle){ rectangle.setSize(mech.hitsize * 2f / 3f).setCenter(x, y); } @Override - public float getDrag(){ + public void onRespawn(Tile tile){ + boostHeat = 1f; + achievedFlight = true; + } + + @Override + public void move(float x, float y){ + if(!mech.flying){ + EntityQuery.collisions().move(this, x, y); + }else{ + moveBy(x, y); + } + } + + @Override + public boolean collidesGrid(int x, int y){ + Tile tile = world.tile(x, y); + return !isFlying() || (!mech.flying && tile != null && !tile.block().synthetic() && tile.block().solid); + } + + @Override + public float drag(){ return mech.drag; } @Override - public Timer getTimer(){ + public Interval getTimer(){ return timer; } @@ -150,25 +164,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra } if(interpolator.target.dst(interpolator.last) > 1f){ - walktime += Timers.delta(); + walktime += Time.delta(); } } - @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; @@ -176,7 +175,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra @Override public float maxHealth(){ - return 200; + return mech.health; } @Override @@ -195,8 +194,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 @@ -205,13 +204,13 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra } @Override - public float getMass(){ + public float mass(){ return mech.mass; } @Override public boolean isFlying(){ - return mech.flying || boostHeat > liftoffBoost || isCarried(); + return mech.flying || boostHeat > liftoffBoost; } @Override @@ -238,7 +237,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra } @Override - public float getMaxVelocity(){ + public float maxVelocity(){ return mech.maxSpeed; } @@ -252,16 +251,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; @@ -282,7 +271,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra @Override public void drawShadow(float offsetX, float offsetY){ - float x = snappedX(), y = snappedY(); float scl = mech.flying ? 1f : boostHeat / 2f; Draw.rect(mech.iconRegion, x + offsetX * scl, y + offsetY * scl, rotation - 90); @@ -292,10 +280,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra public void draw(){ if(dead) return; - float x = snappedX(), y = snappedY(); - 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); } @@ -304,7 +290,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra Floor floor = getFloorOn(); Draw.color(); - Draw.alpha(hitTime / hitDuration); + Draw.alpha(Draw.getShader() != Shaders.mix ? 1f : hitTime / hitDuration); if(!mech.flying){ if(floor.isLiquid){ @@ -319,7 +305,9 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra Draw.rect(mech.legRegion, x + Angles.trnsx(baseRotation, ft * i + boostTrnsY, -boostTrnsX * i), y + Angles.trnsy(baseRotation, ft * i + boostTrnsY, -boostTrnsX * i), - mech.legRegion.getRegionWidth() * i, mech.legRegion.getRegionHeight() - Mathf.clamp(ft * i, 0, 2), baseRotation - 90 + boostAng * i); + mech.legRegion.getWidth() * i * Draw.scl, + (mech.legRegion.getHeight() - Mathf.clamp(ft * i, 0, 2)) * Draw.scl, + baseRotation - 90 + boostAng * i); } Draw.rect(mech.baseRegion, x, y, baseRotation - 90); @@ -337,21 +325,24 @@ 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.getRegionWidth() : mech.weapon.equipRegion.getRegionWidth(); - 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, mech.weapon.equipRegion.getRegionHeight(), rotation - 90); + y + Angles.trnsy(tra, (mech.weaponOffsetX + mech.spreadX(this)) * i, trY), + w * 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); @@ -363,9 +354,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra @Override public void drawStats(){ - float x = snappedX(), y = snappedY(); - - Draw.color(Color.BLACK, team.color, healthf() + Mathf.absin(Timers.time(), healthf() * 5f, 1f - healthf())); + 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(); @@ -375,97 +364,99 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra public void drawOver(){ if(dead) return; - drawBuilding(this); - - if(mech.flying || boostHeat > 0.001f){ - float wobblyness = 0.6f; - if(!state.isPaused()) trail.update(x + Angles.trnsx(rotation + 180f, 5f) + Mathf.range(wobblyness), - y + Angles.trnsy(rotation + 180f, 5f) + Mathf.range(wobblyness)); - trail.draw(Hue.mix(mech.trailColor, mech.trailColorTo, mech.flying ? 0f : boostHeat, Tmp.c1), 5f * (isFlying() ? 1f : boostHeat)); - }else{ - trail.clear(); - } + drawBuilding(); } - public float snappedX(){ - return snapCamera && isLocal ? (int) (x + 0.0001f) : x; - } + @Override + public void drawUnder(){ + float size = mech.engineSize * (mech.flying ? 1f : boostHeat); - public float snappedY(){ - return snapCamera && isLocal ? (int) (y + 0.0001f) : y; + 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(){ - GlyphLayout layout = Pooling.obtain(GlyphLayout.class, GlyphLayout::new); + BitmapFont font = Core.scene.skin.getFont("default-font"); + GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new); - boolean ints = Core.font.usesIntegerPositions(); - Core.font.setUseIntegerPositions(false); - Draw.tscl(0.25f / io.anuke.ucore.scene.ui.layout.Unit.dp.scl(1f)); - layout.setText(Core.font, name); + boolean ints = font.usesIntegerPositions(); + font.setUseIntegerPositions(false); + font.getData().setScale(0.25f / io.anuke.arc.scene.ui.layout.Unit.dp.scl(1f)); + layout.setText(font, name); Draw.color(0f, 0f, 0f, 0.3f); - Draw.rect("blank", x, y + 8 - layout.height / 2, layout.width + 2, layout.height + 3); + Fill.rect(x, y + 8 - layout.height / 2, layout.width + 2, layout.height + 3); Draw.color(); - Draw.tcolor(color); - Draw.text(name, x, y + 8); + font.setColor(color); + + font.draw(name, x, y + 8, 0, Align.center, false); if(isAdmin){ float s = 3f; Draw.color(color.r * 0.5f, color.g * 0.5f, color.b * 0.5f, 1f); - Draw.rect("icon-admin-small", x + layout.width / 2f + 2 + 1, y + 6.5f, s, s); + Draw.rect(Core.atlas.find("icon-admin-small"), x + layout.width / 2f + 2 + 1, y + 6.5f, s, s); Draw.color(color); - Draw.rect("icon-admin-small", x + layout.width / 2f + 2 + 1, y + 7f, s, s); + Draw.rect(Core.atlas.find("icon-admin-small"), x + layout.width / 2f + 2 + 1, y + 7f, s, s); } Draw.reset(); - Pooling.free(layout); - Draw.tscl(1f); - Core.font.setUseIntegerPositions(ints); + 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); - - Draw.color(Palette.removeBack); - - float rad = Mathf.absin(Timers.time(), 7f, 1f) + block.size * tilesize / 2f - 1; + Lines.stroke(2f, Pal.removeBack); + float rad = Mathf.absin(Time.time(), 7f, 1f) + block.size * tilesize / 2f - 1; Lines.square( request.x * tilesize + block.offset(), request.y * tilesize + block.offset() - 1, rad); - Draw.color(Palette.remove); + Draw.color(Pal.remove); Lines.square( request.x * tilesize + block.offset(), request.y * tilesize + block.offset(), rad); }else{ + float rad = Mathf.absin(Time.time(), 7f, 1f) - 1.5f + request.block.size * tilesize / 2f; + //draw place request - Lines.stroke(2f); - - Draw.color(Palette.accentBack); - - float rad = Mathf.absin(Timers.time(), 7f, 1f) - 2f + request.recipe.result.size * tilesize / 2f; + Lines.stroke(1f, Pal.accentBack); Lines.square( - request.x * tilesize + request.recipe.result.offset(), - request.y * tilesize + request.recipe.result.offset() - 1, + request.x * tilesize + request.block.offset(), + request.y * tilesize + request.block.offset() - 1, rad); - Draw.color(Palette.accent); + Draw.color(); + + 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); + + + Draw.color(Pal.accent); Lines.square( - request.x * tilesize + request.recipe.result.offset(), - request.y * tilesize + request.recipe.result.offset(), + request.x * tilesize + request.block.offset(), + request.y * tilesize + request.block.offset(), rad); } } @@ -479,7 +470,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra @Override public void update(){ - hitTime -= Timers.delta(); + hitTime -= Time.delta(); if(Float.isNaN(x) || Float.isNaN(y)){ velocity.set(0f, 0f); @@ -492,13 +483,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); @@ -518,7 +519,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra if(mech.shake > 1f){ Effects.shake(mech.shake, mech.shake, this); } - Effects.effect(UnitFx.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; @@ -526,22 +527,17 @@ 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 } return; }else{ //unlock mech when used - control.unlocks.unlockContent(mech); + data.unlockContent(mech); } if(mobile){ @@ -550,16 +546,17 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra updateMech(); } - updateBuilding(this); + updateBuilding(); - x = Mathf.clamp(x, tilesize, world.width() * tilesize - tilesize); - y = Mathf.clamp(y, tilesize, world.height() * tilesize - tilesize); + if(!mech.flying){ + clampPosition(); + } } protected void updateMech(){ Tile tile = world.tileWorld(x, y); - isBoosting = Inputs.keyDown("dash") && !mech.flying; + isBoosting = Core.input.keyDown(Binding.dash) && !mech.flying; //if player is in solid block if(tile != null && tile.solid()){ @@ -567,10 +564,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 @@ -578,53 +571,28 @@ 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() && Inputs.keyTap("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.getMass() <= mech.carryWeight); - - if(unit != null){ - carry(unit); - } - } - } - movement.setZero(); - String section = control.input(playerIndex).section; - - float xa = Inputs.getAxis(section, "move_x"); - float ya = Inputs.getAxis(section, "move_y"); - if(!Inputs.keyDown("gridMode")){ + float xa = Core.input.axis(Binding.move_x); + float ya = Core.input.axis(Binding.move_y); + if(!Core.input.keyDown(Binding.gridMode)){ movement.y += ya * speed; movement.x += xa * speed; } - Vector2 vec = Graphics.world(control.input(playerIndex).getMouseX(), control.input(playerIndex).getMouseY()); + Vector2 vec = Core.input.mouseWorld(control.input(playerIndex).getMouseX(), control.input(playerIndex).getMouseY()); pointerX = vec.x; pointerY = vec.y; updateShooting(); - movement.limit(speed).scl(Timers.delta()); + 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 = distanceTo(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); @@ -647,7 +615,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 && distanceTo(target) < getWeapon().getAmmo().getRange())){ + mech.canHeal && dst(target) < getWeapon().bullet.range())){ target = null; } @@ -664,10 +632,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra velocity.setAngle(Mathf.slerpDelta(velocity.angle(), angleTo(moveTarget), 0.1f)); } - if(distanceTo(moveTarget) < 2f){ - if(moveTarget instanceof CarriableTrait){ - carry((CarriableTrait) moveTarget); - }else if(tapping){ + if(dst(moveTarget) < 2f){ + if(tapping){ Tile tile = ((TileEntity) moveTarget).tile; tile.block().tapped(tile, this); } @@ -678,45 +644,39 @@ 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)); - if(distanceTo(targetX, targetY) < attractDst){ + if(dst(targetX, targetY) < attractDst){ movement.setZero(); } float expansion = 3f; - getHitbox(rect); + hitbox(rect); rect.x -= expansion; rect.y -= expansion; rect.width += expansion * 2f; rect.height += expansion * 2f; - isBoosting = EntityQuery.collisions().overlapsTile(rect) || distanceTo(targetX, targetY) > 85f; + isBoosting = EntityQuery.collisions().overlapsTile(rect) || dst(targetX, targetY) > 85f; - velocity.add(movement.scl(Timers.delta())); + velocity.add(movement.scl(Time.delta())); if(velocity.len() <= 0.2f && mech.flying){ - rotation += Mathf.sin(Timers.time() + id * 99, 10f, 1f); + rotation += Mathf.sin(Time.time() + id * 99, 10f, 1f); }else if(target == null){ rotation = Mathf.slerpDelta(rotation, velocity.angle(), velocity.len() / 10f); } float lx = x, ly = y; updateVelocityStatus(); - moved = distanceTo(lx, ly) > 0.001f && !isCarried(); + moved = dst(lx, ly) > 0.001f; if(mech.flying){ //hovering effect - x += Mathf.sin(Timers.time() + id * 999, 25f, 0.08f); - y += Mathf.cos(Timers.time() + id * 999, 25f, 0.08f); + x += Mathf.sin(Time.time() + id * 999, 25f, 0.08f); + y += Mathf.cos(Time.time() + id * 999, 25f, 0.08f); } //update shooting if not building, not mining and there's ammo left @@ -726,12 +686,12 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra if(mobile){ if(target == null){ isShooting = false; - if(Settings.getBool("autotarget")){ - target = Units.getClosestTarget(team, x, y, getWeapon().getAmmo().getRange()); + if(Core.settings.getBool("autotarget")){ + target = Units.getClosestTarget(team, x, y, getWeapon().bullet.range()); if(mech.canHeal && target == null){ target = Geometry.findClosest(x, y, world.indexer.getDamaged(Team.blue)); - if(target != null && distanceTo(target) > getWeapon().getAmmo().getRange()){ + if(target != null && dst(target) > getWeapon().bullet.range()){ target = null; }else if(target != null){ target = ((Tile) target).entity; @@ -743,14 +703,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 && distanceTo(target) < getWeapon().getAmmo().getRange())){ + 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.getVelocity().x - velocity.x, target.getVelocity().y - velocity.y, getWeapon().getAmmo().bullet.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; @@ -760,7 +720,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra } }else if(isShooting()){ - Vector2 vec = Graphics.world(control.input(playerIndex).getMouseX(), + Vector2 vec = Core.input.mouseWorld(control.input(playerIndex).getMouseX(), control.input(playerIndex).getMouseY()); pointerX = vec.x; pointerY = vec.y; @@ -784,13 +744,11 @@ 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; - trail.clear(); target = null; moveTarget = null; - carrier = null; health = maxHealth(); boostHeat = drownTime = hitTime = 0f; mech = (isMobile ? Mechs.starterMobile : Mechs.starterDesktop); @@ -803,23 +761,25 @@ 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(); } } } 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 @@ -872,18 +832,18 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra public void write(DataOutput buffer) throws IOException{ super.writeSave(buffer, !isLocal); TypeIO.writeStringData(buffer, name); //TODO writing strings is very inefficient - buffer.writeByte(Bits.toByte(isAdmin) | (Bits.toByte(dead) << 1) | (Bits.toByte(isBoosting) << 2)); + 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(spawner == null ? noSpawner : spawner.getTile().pos()); buffer.writeShort((short) (baseRotation * 2)); writeBuilding(buffer); } @Override - public void read(DataInput buffer, long time) throws IOException{ + public void read(DataInput buffer) throws IOException{ float lastx = x, lasty = y, lastrot = rotation; super.readSave(buffer); name = TypeIO.readStringData(buffer); @@ -899,7 +859,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra readBuilding(buffer, !isLocal); - interpolator.read(lastx, lasty, x, y, time, rotation, baseRotation); + interpolator.read(lastx, lasty, x, y, rotation, baseRotation); rotation = lastrot; if(isLocal){ @@ -908,7 +868,12 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra }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 81% rename from core/src/io/anuke/mindustry/entities/TileEntity.java rename to core/src/io/anuke/mindustry/entities/type/TileEntity.java index 7df1e6d659..350857ee18 100644 --- a/core/src/io/anuke/mindustry/entities/TileEntity.java +++ b/core/src/io/anuke/mindustry/entities/type/TileEntity.java @@ -1,14 +1,23 @@ -package io.anuke.mindustry.entities; +package io.anuke.mindustry.entities.type; -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.ObjectSet; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.content.fx.Fx; +import io.anuke.arc.Events; +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.ObjectSet; +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; +import io.anuke.arc.util.Interval; +import io.anuke.arc.util.Time; +import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.traits.TargetTrait; +import io.anuke.mindustry.game.EventType.BlockDestroyEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.world.Block; @@ -20,13 +29,6 @@ import io.anuke.mindustry.world.modules.ConsumeModule; import io.anuke.mindustry.world.modules.ItemModule; import io.anuke.mindustry.world.modules.LiquidModule; import io.anuke.mindustry.world.modules.PowerModule; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.impl.BaseEntity; -import io.anuke.ucore.entities.trait.HealthTrait; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Timer; import java.io.DataInput; import java.io.DataOutput; @@ -42,7 +44,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ public static int sleepingEntities = 0; public Tile tile; - public Timer timer; + public Interval timer; public float health; public float timeScale = 1f, timeScaleDuration; @@ -71,16 +73,16 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ } /**Sets this tile entity data to this tile, and adds it if necessary.*/ - public TileEntity init(Tile tile, boolean added){ + public TileEntity init(Tile tile, boolean shouldAdd){ this.tile = tile; x = tile.drawx(); y = tile.drawy(); health = tile.block().health; - timer = new Timer(tile.block().timers); + timer = new Interval(tile.block().timers); - if(added){ + if(shouldAdd){ add(); } @@ -89,12 +91,12 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ /**Scaled delta.*/ public float delta(){ - return Timers.delta() * timeScale; + return Time.delta() * timeScale; } /**Call when nothing is happening to the entity. This increments the internal sleep timer.*/ public void sleep(){ - sleepTime += Timers.delta(); + sleepTime += Time.delta(); if(!sleeping && sleepTime >= timeToSleep){ remove(); sleeping = true; @@ -149,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); } } @@ -169,8 +171,8 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ public void removeFromProximity(){ tile.block().onProximityRemoved(tile); - GridPoint2[] nearby = Edges.getEdges(tile.block().size); - for(GridPoint2 point : nearby){ + Point2[] nearby = Edges.getEdges(tile.block().size); + for(Point2 point : nearby){ Tile other = world.tile(tile.x + point.x, tile.y + point.y); //remove this tile from all nearby tile's proximities if(other != null){ @@ -187,8 +189,8 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ tmpTiles.clear(); proximity.clear(); - GridPoint2[] nearby = Edges.getEdges(tile.block().size); - for(GridPoint2 point : nearby){ + Point2[] nearby = Edges.getEdges(tile.block().size); + for(Point2 point : nearby){ Tile other = world.tile(tile.x + point.x, tile.y + point.y); if(other == null) continue; @@ -244,6 +246,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ dead = true; Block block = tile.block(); + Events.fire(new BlockDestroyEvent(tile)); block.onDestroyed(tile); world.removeBlock(tile); block.afterDestroyed(tile, this); @@ -257,20 +260,20 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ } @Override - public Vector2 getVelocity(){ - return Vector2.Zero; + public Vector2 velocity(){ + return Vector2.ZERO; } @Override public void update(){ //TODO better smoke effect, this one is awful if(health != 0 && health < tile.block().health && !(tile.block() instanceof Wall) && - Mathf.chance(0.009f * Timers.delta() * (1f - health / tile.block().health))){ + Mathf.chance(0.009f * Time.delta() * (1f - health / tile.block().health))){ Effects.effect(Fx.smoke, x + Mathf.range(4), y + Mathf.range(4)); } - timeScaleDuration -= Timers.delta(); + timeScaleDuration -= Time.delta(); if(timeScaleDuration <= 0f || !tile.block().canOverdrive){ timeScale = 1f; } @@ -281,7 +284,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(); } } @@ -289,4 +292,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 63% rename from core/src/io/anuke/mindustry/entities/Unit.java rename to core/src/io/anuke/mindustry/entities/type/Unit.java index 198d44b283..cdfa1b9dcc 100644 --- a/core/src/io/anuke/mindustry/entities/Unit.java +++ b/core/src/io/anuke/mindustry/entities/type/Unit.java @@ -1,39 +1,45 @@ -package io.anuke.mindustry.entities; +package io.anuke.mindustry.entities.type; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.content.blocks.Blocks; +import io.anuke.arc.Core; +import io.anuke.arc.Events; +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.Rectangle; +import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.util.Time; +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; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.impl.DestructibleEntity; -import io.anuke.ucore.entities.trait.DamageTrait; -import io.anuke.ucore.entities.trait.DrawTrait; -import io.anuke.ucore.entities.trait.SolidTrait; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.util.Geometry; -import io.anuke.ucore.util.Mathf; 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.*/ @@ -45,16 +51,14 @@ 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(){ @@ -62,18 +66,8 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } @Override - public UnitInventory getInventory(){ - return inventory; - } - - @Override - public CarryTrait getCarrier(){ - return carrier; - } - - @Override - public void setCarrier(CarryTrait carrier){ - this.carrier = carrier; + public boolean collidesGrid(int x, int y){ + return !isFlying(); } @Override @@ -117,13 +111,22 @@ 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)); } @Override - public Vector2 getVelocity(){ + public Vector2 velocity(){ return velocity; } @@ -136,6 +139,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); @@ -151,9 +159,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; @@ -172,12 +183,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(){ @@ -189,12 +219,12 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } public void avoidOthers(float scaling){ - getHitbox(queryRect); + hitbox(queryRect); queryRect.setSize(queryRect.getWidth() * scaling); Units.getNearby(queryRect, t -> { - if(t == this || t.getCarrier() == this || getCarrier() == t || t.isFlying() != isFlying()) return; - float dst = distanceTo(t); + 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); }); @@ -216,30 +246,24 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ return tile == null ? (Floor) Blocks.air : tile.floor(); } - @Override - public boolean isValid(){ - return !isDead() && isAdded(); - } + public void onRespawn(Tile tile){} /**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.getVelocity()); - return; - } - Tile tile = world.tileWorld(x, y); status.update(this); - velocity.limit(getMaxVelocity()).scl(1f + (status.getSpeedMultiplier()-1f) * Timers.delta()); + 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()){ - x += velocity.x * Timers.delta(); - y += velocity.y * Timers.delta(); + move(velocity.x * Time.delta(), velocity.y * Time.delta()); }else{ boolean onLiquid = floor.isLiquid; @@ -248,19 +272,14 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ if(tile.block() != Blocks.air){ onLiquid = false; } - - //on slope - if(tile.getElevation() == -1){ - velocity.scl(0.7f); - } } - if(onLiquid && velocity.len() > 0.4f && Mathf.chance((velocity.len() * floor.speedMultiplier) * 0.06f * Timers.delta())){ + if(onLiquid && velocity.len() > 0.4f && Mathf.chance((velocity.len() * floor.speedMultiplier) * 0.06f * Time.delta())){ Effects.effect(floor.walkEffect, floor.liquidColor, x, y); } if(onLiquid){ - status.handleApply(this, floor.status, floor.statusIntensity); + status.handleApply(this, floor.status, floor.statusDuration); if(floor.damageTaken > 0f){ damagePeriodic(floor.damageTaken); @@ -268,8 +287,8 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } if(onLiquid && floor.drownTime > 0){ - drownTime += Timers.delta() * 1f / floor.drownTime; - if(Mathf.chance(Timers.delta() * 0.05f)){ + drownTime += Time.delta() * 1f / floor.drownTime; + if(Mathf.chance(Time.delta() * 0.05f)){ Effects.effect(floor.drownUpdateEffect, floor.liquidColor, x, y); } }else{ @@ -283,21 +302,46 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } float px = x, py = y; - move(velocity.x * floor.speedMultiplier * Timers.delta(), velocity.y * floor.speedMultiplier * Timers.delta()); + move(velocity.x * floor.speedMultiplier * Time.delta(), velocity.y * floor.speedMultiplier * Time.delta()); if(Math.abs(px - x) <= 0.0001f) velocity.x = 0f; if(Math.abs(py - y) <= 0.0001f) velocity.y = 0f; } - velocity.scl(Mathf.clamp(1f - getDrag() * (isFlying() ? 1f : floor.dragMultiplier) * Timers.delta())); + velocity.scl(Mathf.clamp(1f - drag() * (isFlying() ? 1f : floor.dragMultiplier) * Time.delta())); } - public void applyEffect(StatusEffect effect, float intensity){ + 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 ? 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, intensity); + status.handleApply(this, effect, duration); } public void damagePeriodic(float amount){ - damage(amount * Timers.delta(), hitTime <= -20 + hitDuration); + damage(amount * Time.delta(), hitTime <= -20 + hitDuration); } public void damage(float amount, boolean withEffect){ @@ -317,14 +361,14 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } public void drawStats(){ - Draw.color(Color.BLACK, team.color, healthf() + Mathf.absin(Timers.time(), healthf()*5f, 1f - healthf())); + 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(); } public TextureRegion getPowerCellRegion(){ - return Draw.region("power-cell"); + return Core.atlas.find("power-cell"); } public void drawAll(){ @@ -338,23 +382,13 @@ 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 abstract TextureRegion getIconRegion(); public abstract Weapon getWeapon(); public abstract int getItemCapacity(); - public abstract float getArmor(); - - public abstract float getMass(); + public abstract float mass(); public abstract boolean isFlying(); 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 81% 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 b47215d4ea..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,21 @@ -package io.anuke.mindustry.entities.units.types; +package io.anuke.mindustry.entities.type.base; -import com.badlogic.gdx.utils.Queue; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.TileEntity; +import io.anuke.arc.Events; +import io.anuke.arc.collection.Queue; +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.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.units.UnitCommand; +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; -import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.ItemType; @@ -20,11 +23,6 @@ import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.BuildBlock; import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; import io.anuke.mindustry.world.meta.BlockFlag; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.util.Geometry; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Structs; import java.io.DataInput; import java.io.DataOutput; @@ -34,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<>(); @@ -63,17 +59,17 @@ public class Drone extends FlyingUnit implements BuilderTrait{ if(core == null) return; if((entity.progress() < 1f || entity.progress() > 0f) && entity.tile.block() instanceof BuildBlock){ //building is valid - if(!isBuilding() && distanceTo(target) < placeDistance * 0.9f){ //within distance, begin placing + if(!isBuilding() && dst(target) < placeDistance * 0.9f){ //within distance, begin placing if(isBreaking){ getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y)); }else{ - getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.getRotation(), entity.recipe)); + getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.getRotation(), entity.block)); } } //if it's missing requirements, try and mine them - if(entity.recipe != null){ - for(ItemStack stack : entity.recipe.requirements){ + if(entity.block != null){ + for(ItemStack stack : entity.block.buildRequirements){ if(!core.items.has(stack.item, stack.amount) && type.toMine.contains(stack.item)){ targetItem = stack.item; getPlaceQueue().clear(); @@ -108,7 +104,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ if(target == null) return; - if(target.distanceTo(Drone.this) > type.range){ + if(target.dst(Drone.this) > type.range){ circle(type.range*0.9f); }else{ getWeapon().update(Drone.this, target.getX(), target.getY()); @@ -137,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; } @@ -158,7 +154,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ if(target instanceof Tile){ moveTo(type.range / 1.5f); - if(distanceTo(target) < type.range && mineTile != target){ + if(dst(target) < type.range && mineTile != target){ setMineTile((Tile) target); } @@ -179,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; } @@ -196,10 +192,10 @@ public class Drone extends FlyingUnit implements BuilderTrait{ TileEntity tile = (TileEntity) target; - if(distanceTo(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(dst(target) < type.range){ + 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); @@ -254,7 +250,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ } private void notifyPlaced(BuildEntity entity, boolean isBreaking){ - float dist = Math.min(entity.distanceTo(x, y) - placeDistance, 0); + float dist = Math.min(entity.dst(x, y) - placeDistance, 0); if(!state.is(build) && dist / type.maxVelocity < entity.buildCost * 0.9f){ target = entity; @@ -263,11 +259,6 @@ public class Drone extends FlyingUnit implements BuilderTrait{ } } - @Override - public void onCommand(UnitCommand command){ - //no - } - @Override public boolean canMine(Item item){ return type.toMine.contains(item); @@ -306,12 +297,12 @@ public class Drone extends FlyingUnit implements BuilderTrait{ target = null; } - updateBuilding(this); + updateBuilding(); } @Override protected void updateRotation(){ - if(target != null && ((state.is(repair) && target.distanceTo(this) < type.range) || state.is(mine))){ + if(target != null && ((state.is(repair) && target.dst(this) < type.range) || state.is(mine))){ rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.3f); }else{ rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.3f); @@ -333,8 +324,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ @Override public void drawOver(){ - trail.draw(Palette.lightTrail, 3f); - drawBuilding(this); + drawBuilding(); } @Override @@ -364,8 +354,8 @@ public class Drone extends FlyingUnit implements BuilderTrait{ } @Override - public void read(DataInput data, long time) throws IOException{ - super.read(data, time); + public void read(DataInput data) throws IOException{ + super.read(data); int mined = data.readInt(); int repairing = data.readInt(); 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 e72390c51e..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java +++ /dev/null @@ -1,262 +0,0 @@ -package io.anuke.mindustry.entities.units; - -import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.entities.Predict; -import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.entities.traits.CarriableTrait; -import io.anuke.mindustry.entities.traits.CarryTrait; -import io.anuke.mindustry.graphics.Trail; -import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.type.AmmoType; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockFlag; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.*; - -import static io.anuke.mindustry.Vars.world; - -public abstract class FlyingUnit extends BaseUnit implements CarryTrait{ - protected static Translator vec = new Translator(); - protected static float wobblyness = 0.6f; - - protected Trail trail = new Trail(8); - protected CarriableTrait carrying; - protected final UnitState - - idle = new UnitState(){ - public void update(){ - if(!isCommanded()){ - 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 && isCommanded() && getCommand() == UnitCommand.patrol){ - setState(patrol); - return; - } - - if(target == null) targetClosestEnemyFlag(BlockFlag.target); - if(target == null) targetClosestEnemyFlag(BlockFlag.producer); - if(target == null) targetClosestEnemyFlag(BlockFlag.turret); - - if(target == null && !isCommanded()){ - setState(idle); - } - }); - }else{ - attack(150f); - - if((Mathf.angNear(angleTo(target), rotation, 15f) || !getWeapon().getAmmo().bullet.keepVelocity) //bombers don't care about rotation - && distanceTo(target) < Math.max(getWeapon().getAmmo().getRange(), type.range)){ - AmmoType ammo = getWeapon().getAmmo(); - - Vector2 to = Predict.intercept(FlyingUnit.this, target, ammo.bullet.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(Timers.time() + id * 23525, 70f, 1200f)); - } - } - }, - retreat = new UnitState(){ - public void entered(){ - target = null; - } - - public void update(){ - if(health >= maxHealth() && !isCommanded()){ - 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 onCommand(UnitCommand command){ - state.set(command == UnitCommand.retreat ? retreat : - command == UnitCommand.attack ? attack : - command == UnitCommand.patrol ? patrol : - null); - } - - @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(); - } - - trail.update(x + Angles.trnsx(rotation + 180f, 6f) + Mathf.range(wobblyness), - y + Angles.trnsy(rotation + 180f, 6f) + Mathf.range(wobblyness)); - } - - @Override - public void draw(){ - Draw.alpha(hitTime / hitDuration); - - Draw.rect(type.name, x, y, rotation - 90); - - drawItems(); - - Draw.alpha(1f); - } - - @Override - public void drawOver(){ - trail.draw(type.trailColor, 5f); - } - - @Override - public void behavior(){ - if(health <= health * type.retreatPercent && !isCommanded() && - 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(Timers.time() + id * 999, 25f, 0.08f)*Timers.delta(); - y += Mathf.cos(Timers.time() + id * 999, 25f, 0.08f)*Timers.delta(); - - if(velocity.len() <= 0.05f){ - rotation += Mathf.sin(Timers.time() + id * 99, 10f, 2.5f)*Timers.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 * Timers.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((distanceTo(target) - circleLength) / 100f, -1f, 1f); - - vec.setLength(type.speed * Timers.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 * Timers.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 1068de0a6b..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/Squad.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.anuke.mindustry.entities.units; - -import com.badlogic.gdx.math.Vector2; -import io.anuke.ucore.util.Translator; - -import static io.anuke.mindustry.Vars.threads; - -/** - * 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 Translator(); - public int units; - - private long lastUpdated; - - protected void update(){ - if(threads.getFrameID() != lastUpdated){ - direction.setZero(); - lastUpdated = threads.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 74% rename from core/src/io/anuke/mindustry/entities/StatusController.java rename to core/src/io/anuke/mindustry/entities/units/Statuses.java index 2df186d4c8..90fc24b270 100644 --- a/core/src/io/anuke/mindustry/entities/StatusController.java +++ b/core/src/io/anuke/mindustry/entities/units/Statuses.java @@ -1,52 +1,47 @@ -package io.anuke.mindustry.entities; +package io.anuke.mindustry.entities.units; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.utils.Array; +import io.anuke.arc.collection.Array; +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; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.util.Pooling; -import io.anuke.ucore.util.ThreadArray; -import io.anuke.ucore.util.Tmp; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.content; -/** - * Class for controlling status effects on an entity. - */ -public class StatusController implements Saveable{ +/** Class for controlling status effects on an entity.*/ +public class Statuses implements Saveable{ private static final StatusEntry globalResult = new StatusEntry(); - private static final Array removals = new ThreadArray<>(); + private static final Array removals = new Array<>(); - private Array statuses = new ThreadArray<>(); + private Array statuses = new Array<>(); private float speedMultiplier; private float damageMultiplier; private float armorMultiplier; - public void handleApply(Unit unit, StatusEffect effect, float intensity){ - if(effect == StatusEffects.none) return; //don't apply empty effects - - float newTime = effect.baseDuration * intensity; + 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 for(StatusEntry entry : statuses){ //extend effect if(entry.effect == effect){ - entry.time = Math.max(entry.time, newTime); + entry.time = Math.max(entry.time, duration); return; - }else if(entry.effect.isOpposite(effect)){ //find opposite - entry.effect.getTransition(unit, effect, entry.time, newTime, globalResult); + }else if(entry.effect.reactsWith(effect)){ //find opposite + entry.effect.getTransition(unit, effect, entry.time, duration, globalResult); entry.time = globalResult.time; if(globalResult.effect != entry.effect){ - entry.effect.onTransition(unit, globalResult.effect); entry.effect = globalResult.effect; } @@ -57,8 +52,8 @@ public class StatusController implements Saveable{ } //otherwise, no opposites found, add direct effect - StatusEntry entry = Pooling.obtain(StatusEntry.class, StatusEntry::new); - entry.set(effect, newTime); + StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new); + entry.set(effect, duration); statuses.add(entry); } @@ -88,10 +83,10 @@ public class StatusController implements Saveable{ removals.clear(); for(StatusEntry entry : statuses){ - entry.time = Math.max(entry.time - Timers.delta(), 0); + entry.time = Math.max(entry.time - Time.delta(), 0); if(entry.time <= 0){ - Pooling.free(entry); + Pools.free(entry); removals.add(entry); }else{ speedMultiplier *= entry.effect.speedMultiplier; @@ -137,7 +132,7 @@ public class StatusController implements Saveable{ @Override public void readSave(DataInput stream) throws IOException{ for(StatusEntry effect : statuses){ - Pooling.free(effect); + Pools.free(effect); } statuses.clear(); @@ -146,7 +141,7 @@ public class StatusController implements Saveable{ for(int i = 0; i < amount; i++){ byte id = stream.readByte(); float time = stream.readShort() / 2f; - StatusEntry entry = Pooling.obtain(StatusEntry.class, StatusEntry::new); + 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/UnitCommand.java b/core/src/io/anuke/mindustry/entities/units/UnitCommand.java deleted file mode 100644 index a6e8c2a005..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/UnitCommand.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.anuke.mindustry.entities.units; - -import io.anuke.ucore.util.Bundles; - -public enum UnitCommand{ - attack, retreat, patrol; - - private final String localized; - - UnitCommand(){ - localized = Bundles.get("command." + name()); - } - - public String localized(){ - return localized; - } -} diff --git a/core/src/io/anuke/mindustry/entities/units/UnitDrops.java b/core/src/io/anuke/mindustry/entities/units/UnitDrops.java index 3780465876..84c47a4457 100644 --- a/core/src/io/anuke/mindustry/entities/units/UnitDrops.java +++ b/core/src/io/anuke/mindustry/entities/units/UnitDrops.java @@ -2,17 +2,18 @@ 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.ucore.util.Mathf; +import io.anuke.arc.math.Mathf; public class UnitDrops{ private static Item[] dropTable; public static void dropItems(BaseUnit unit){ //items only dropped in waves for enemy team - if(unit.getTeam() != Vars.waveTeam || Vars.state.mode.disableWaves){ + if(unit.getTeam() != Vars.waveTeam || !Vars.state.rules.unitDrops){ return; } @@ -23,13 +24,13 @@ public class UnitDrops{ } if(dropTable == null){ - dropTable = new Item[]{Items.densealloy, Items.silicon, Items.lead, Items.copper}; + dropTable = new Item[]{Items.titanium, Items.silicon, Items.lead, Items.copper}; } for(int i = 0; i < 3; i++){ for(Item item : dropTable){ //only drop unlocked items - if(!Vars.headless && !Vars.control.unlocks.isUnlocked(item)){ + if(!Vars.headless && !Vars.data.isUnlocked(item)){ continue; } diff --git a/core/src/io/anuke/mindustry/entities/units/types/AlphaDrone.java b/core/src/io/anuke/mindustry/entities/units/types/AlphaDrone.java deleted file mode 100644 index 478854cfc0..0000000000 --- a/core/src/io/anuke/mindustry/entities/units/types/AlphaDrone.java +++ /dev/null @@ -1,113 +0,0 @@ -package io.anuke.mindustry.entities.units.types; - -import com.badlogic.gdx.math.Vector2; -import io.anuke.annotations.Annotations.Loc; -import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.fx.UnitFx; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.Predict; -import io.anuke.mindustry.entities.traits.TargetTrait; -import io.anuke.mindustry.entities.units.BaseUnit; -import io.anuke.mindustry.entities.units.FlyingUnit; -import io.anuke.mindustry.entities.units.UnitCommand; -import io.anuke.mindustry.entities.units.UnitState; -import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.type.AmmoType; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.util.Mathf; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import static io.anuke.mindustry.Vars.*; - -public class AlphaDrone extends FlyingUnit { - static final float followDistance = 80f; - - public Player leader; - - public final UnitState attack = new UnitState() { - @Override - public void update() { - if(leader == null || leader.isDead() || !leader.isAdded()){ - damage(99999f); - return; - } - TargetTrait last = target; - target = leader; - - if(last == null){ - circle(leader.isShooting ? 60f : 0f); - } - - target = last; - if(distanceTo(leader) < followDistance){ - targetClosest(); - }else{ - target = null; - } - - if(target != null){ - attack(50f); - - if((Mathf.angNear(angleTo(target), rotation, 15f) && distanceTo(target) < getWeapon().getAmmo().getRange())){ - AmmoType ammo = getWeapon().getAmmo(); - - Vector2 to = Predict.intercept(AlphaDrone.this, target, ammo.bullet.speed); - getWeapon().update(AlphaDrone.this, to.x, to.y); - } - } - - if(!leader.isShooting && distanceTo(leader) < 7f){ - Call.onAlphaDroneFade(AlphaDrone.this); - } - } - }; - - @Remote(called = Loc.server) - public static void onAlphaDroneFade(BaseUnit drone){ - if(drone == null) return; - Effects.effect(UnitFx.pickup, drone); - //must run afterwards so the unit's group is not null when sending the removal packet - threads.runDelay(drone::remove); - } - - @Override - public void onCommand(UnitCommand command){ - //nuh - } - - @Override - public void behavior(){ - //nope - } - - @Override - public UnitState getStartState() { - return attack; - } - - @Override - public void write(DataOutput stream) throws IOException { - super.write(stream); - stream.writeInt(leader == null ? -1 : leader.id); - } - - @Override - public void read(DataInput stream, long time) throws IOException { - super.read(stream, time); - leader = Vars.playerGroup.getByID(stream.readInt()); - } - - @Override - public void readSave(DataInput stream) throws IOException{ - super.readSave(stream); - - if(!Net.active() && !headless){ - leader = players[0]; - } - } -} 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/ContentList.java b/core/src/io/anuke/mindustry/game/ContentList.java index 838777cb84..8fc59c8bf2 100644 --- a/core/src/io/anuke/mindustry/game/ContentList.java +++ b/core/src/io/anuke/mindustry/game/ContentList.java @@ -1,12 +1,7 @@ package io.anuke.mindustry.game; -import io.anuke.mindustry.type.ContentType; - /**Interface for a list of content to be loaded in {@link io.anuke.mindustry.core.ContentLoader}.*/ public interface ContentList{ /**This method should create all the content.*/ void load(); - - /**This method should return the type of content being loaded.*/ - ContentType type(); } diff --git a/core/src/io/anuke/mindustry/game/Difficulty.java b/core/src/io/anuke/mindustry/game/Difficulty.java index bfbbdd1e90..ae19a30f49 100644 --- a/core/src/io/anuke/mindustry/game/Difficulty.java +++ b/core/src/io/anuke/mindustry/game/Difficulty.java @@ -1,30 +1,28 @@ package io.anuke.mindustry.game; -import io.anuke.ucore.util.Bundles; +import io.anuke.arc.Core; +/**Presets for time between waves. + * TODO specify correct time*/ public enum Difficulty{ - training(3f, 3f), - easy(1.4f, 1.5f), - normal(1f, 1f), - hard(0.5f, 0.75f), - insane(0.25f, 0.5f); + easy(1.4f), + normal(1f), + hard(0.5f), + insane(0.25f); /**Multiplier of the time between waves.*/ - public final float timeScaling; - /**Multiplier of spawner grace period.*/ - public final float spawnerScaling; + public final float waveTime; private String value; - Difficulty(float timeScaling, float spawnerScaling){ - this.timeScaling = timeScaling; - this.spawnerScaling = spawnerScaling; + Difficulty(float waveTime){ + this.waveTime = waveTime; } @Override public String toString(){ if(value == null){ - value = Bundles.get("setting.difficulty." + name()); + value = Core.bundle.get("setting.difficulty." + name()); } return value; } diff --git a/core/src/io/anuke/mindustry/game/EventType.java b/core/src/io/anuke/mindustry/game/EventType.java index 0724be398a..40754f6604 100644 --- a/core/src/io/anuke/mindustry/game/EventType.java +++ b/core/src/io/anuke/mindustry/game/EventType.java @@ -1,16 +1,24 @@ package io.anuke.mindustry.game; +import io.anuke.arc.Events.Event; import io.anuke.mindustry.core.GameState.State; +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; -import io.anuke.ucore.core.Events.Event; 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 the game is first loaded.*/ public static class GameLoadEvent implements Event{ } @@ -35,22 +43,11 @@ public class EventType{ } } - /** - * This event is called from the logic thread. - * DO NOT INITIALIZE GRAPHICS HERE. - */ + /**Called when a game begins and the world is loaded.*/ public static class WorldLoadEvent implements Event{ } - /** - * Called after the WorldLoadEvent is, and all logic has been loaded. - * It is safe to intialize graphics here. - */ - public static class WorldLoadGraphicsEvent implements Event{ - - } - /**Called from the logic thread. Do not access graphics here!*/ public static class TileChangeEvent implements Event{ public final Tile tile; @@ -70,9 +67,9 @@ public class EventType{ } public static class UnlockEvent implements Event{ - public final Content content; + public final UnlockableContent content; - public UnlockEvent(Content content){ + public UnlockEvent(UnlockableContent content){ this.content = content; } } @@ -91,6 +88,18 @@ public class EventType{ } } + public static class BlockBuildEndEvent implements Event{ + public final Tile tile; + public final Team team; + public final boolean breaking; + + public BlockBuildEndEvent(Tile tile, Team team, boolean breaking){ + this.tile = tile; + this.team = team; + this.breaking = breaking; + } + } + /**Called when a player or drone begins building something. * This does not necessarily happen when a new BuildBlock is created.*/ public static class BuildSelectEvent implements Event{ @@ -107,6 +116,22 @@ public class EventType{ } } + public static class BlockDestroyEvent implements Event{ + public final Tile tile; + + public BlockDestroyEvent(Tile tile){ + this.tile = tile; + } + } + + public static class UnitDestroyEvent implements Event{ + public final Unit unit; + + public UnitDestroyEvent(Unit unit){ + this.unit = unit; + } + } + public static class ResizeEvent implements Event{ } diff --git a/core/src/io/anuke/mindustry/game/GameMode.java b/core/src/io/anuke/mindustry/game/GameMode.java deleted file mode 100644 index cd4057012a..0000000000 --- a/core/src/io/anuke/mindustry/game/GameMode.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.anuke.mindustry.game; - -import io.anuke.ucore.util.Bundles; - -public enum GameMode{ - waves, - sandbox{{ - infiniteResources = true; - disableWaveTimer = true; - }}, - freebuild{{ - disableWaveTimer = true; - }}, - attack{{ - disableWaves = true; - enemyCheat = true; - }}, - victory{{ - disableWaves = true; - hidden = true; - enemyCheat = false; - showMission = false; - }}, - pvp{{ - disableWaves = true; - isPvp = true; - enemyCoreBuildRadius = 600f; - respawnTime = 60 * 10; - }}; - - public boolean infiniteResources, disableWaveTimer, disableWaves, showMission = true, hidden, enemyCheat, isPvp; - public float enemyCoreBuildRadius = 400f; - public float respawnTime = 60 * 4; - - public String description(){ - return Bundles.get("mode." + name() + ".description"); - } - - @Override - public String toString(){ - return Bundles.get("mode." + name() + ".name"); - } - -} diff --git a/core/src/io/anuke/mindustry/game/GlobalData.java b/core/src/io/anuke/mindustry/game/GlobalData.java new file mode 100644 index 0000000000..87e52ab512 --- /dev/null +++ b/core/src/io/anuke/mindustry/game/GlobalData.java @@ -0,0 +1,137 @@ +package io.anuke.mindustry.game; + +import io.anuke.arc.Core; +import io.anuke.arc.Events; +import io.anuke.arc.collection.ObjectIntMap; +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.game.EventType.UnlockEvent; +import io.anuke.mindustry.game.EventType.ZoneCompleteEvent; +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.*; + +/**Stores player unlocks. Clientside only.*/ +public class GlobalData{ + private ObjectMap> unlocked = new ObjectMap<>(); + private ObjectIntMap items = new ObjectIntMap<>(); + private boolean modified; + + 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())); + } + + 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; + if(wave == zone.conditionWave + 1){ + Events.fire(new ZoneCompleteEvent(zone)); + } + } + } + + public int getWaveScore(Zone zone){ + return Core.settings.getInt(zone.name + "-wave", 0); + } + + public boolean isCompleted(Zone zone){ + return getWaveScore(zone) >= zone.conditionWave; + } + + public int getItem(Item item){ + return items.get(item, 0); + } + + public void addItem(Item item, int amount){ + modified = true; + items.getAndIncrement(item, 0, amount); + state.stats.itemsDelivered.getAndIncrement(item, 0, amount); + } + + public boolean hasItems(ItemStack[] stacks){ + for(ItemStack stack : stacks){ + if(items.get(stack.item, 0) < stack.amount){ + return false; + } + } + return true; + } + + public void removeItems(ItemStack[] stacks){ + for(ItemStack stack : stacks){ + items.getAndIncrement(stack.item, 0, -stack.amount); + } + modified = true; + } + + public boolean has(Item item, int amount){ + return items.get(item, 0) >= amount; + } + + public ObjectIntMap items(){ + return items; + } + + /** Returns whether or not this piece of content is unlocked yet.*/ + public boolean isUnlocked(UnlockableContent content){ + return content.alwaysUnlocked() || unlocked.getOr(content.getContentType(), ObjectSet::new).contains(content.getContentName()); + } + + /** + * Makes this piece of content 'unlocked', if possible. + * If this piece of content is already unlocked or cannot be unlocked due to dependencies, nothing changes. + * Results are not saved until you call {@link #save()}. + */ + public void unlockContent(UnlockableContent content){ + if(content.alwaysUnlocked()) return; + + //fire unlock event so other classes can use it + if(unlocked.getOr(content.getContentType(), ObjectSet::new).add(content.getContentName())){ + modified = true; + content.onUnlock(); + Events.fire(new UnlockEvent(content)); + } + } + + /** Clears all unlocked content. Automatically saves.*/ + public void reset(){ + save(); + } + + public void checkSave(){ + if(modified){ + save(); + modified = false; + } + } + + @SuppressWarnings("unchecked") + public void load(){ + unlocked = Core.settings.getObject("unlocks", ObjectMap.class, ObjectMap::new); + for(Item item : Vars.content.items()){ + items.put(item, Core.settings.getInt("item-" + item.name, 0)); + } + + //set up default values + if(!Core.settings.has("item-" + Items.copper.name)){ + addItem(Items.copper, 300); + } + } + + public void save(){ + Core.settings.putObject("unlocks", unlocked); + for(Item item : Vars.content.items()){ + Core.settings.put("item-" + item.name, items.get(item, 0)); + } + Core.settings.save(); + } + +} diff --git a/core/src/io/anuke/mindustry/game/MappableContent.java b/core/src/io/anuke/mindustry/game/MappableContent.java index 71e33745ae..69fff736ec 100644 --- a/core/src/io/anuke/mindustry/game/MappableContent.java +++ b/core/src/io/anuke/mindustry/game/MappableContent.java @@ -5,7 +5,6 @@ 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. - * (e.g. having a recipe and a block, both with name "wall" is fine, as they are different types). */ public abstract String getContentName(); diff --git a/core/src/io/anuke/mindustry/game/Rank.java b/core/src/io/anuke/mindustry/game/Rank.java new file mode 100644 index 0000000000..aab896325b --- /dev/null +++ b/core/src/io/anuke/mindustry/game/Rank.java @@ -0,0 +1,5 @@ +package io.anuke.mindustry.game; + +public enum Rank{ + SS, S, A, B, C, D, F +} diff --git a/core/src/io/anuke/mindustry/game/RulePreset.java b/core/src/io/anuke/mindustry/game/RulePreset.java new file mode 100644 index 0000000000..566c632159 --- /dev/null +++ b/core/src/io/anuke/mindustry/game/RulePreset.java @@ -0,0 +1,48 @@ +package io.anuke.mindustry.game; + +import io.anuke.arc.Core; +import io.anuke.arc.function.Supplier; + +/**Defines preset rule sets..*/ +public enum RulePreset{ + survival(() -> new Rules(){{ + waveTimer = true; + waves = true; + unitDrops = true; + spawns = Waves.getDefaultSpawns(); + }}), + sandbox(() -> new Rules(){{ + infiniteResources = true; + waves = true; + waveTimer = false; + spawns = Waves.getDefaultSpawns(); + }}), + attack(() -> new Rules(){{ + enemyCheat = true; + unitDrops = true; + }}), + pvp(() -> new Rules(){{ + pvp = true; + enemyCoreBuildRadius = 600f; + respawnTime = 60 * 10; + }}); + + private final Supplier rules; + + RulePreset(Supplier rules){ + this.rules = rules; + } + + public Rules get(){ + return rules.get(); + } + + public String description(){ + return Core.bundle.get("mode." + name() + ".description"); + } + + @Override + public String toString(){ + return Core.bundle.get("mode." + name() + ".name"); + } +} diff --git a/core/src/io/anuke/mindustry/game/Rules.java b/core/src/io/anuke/mindustry/game/Rules.java new file mode 100644 index 0000000000..b7d9c86dc7 --- /dev/null +++ b/core/src/io/anuke/mindustry/game/Rules.java @@ -0,0 +1,32 @@ +package io.anuke.mindustry.game; + +import io.anuke.annotations.Annotations.Serialize; +import io.anuke.arc.collection.Array; + +/**Defines current rules on how the game should function. + * Does not store game state, just configuration.*/ +@Serialize +public class Rules{ + /**Whether the player has infinite resources.*/ + public boolean infiniteResources; + /**Whether the waves come automatically on a timer. If not, waves come when the play button is pressed.*/ + public boolean waveTimer = true; + /**Whether waves are spawnable at all.*/ + public boolean waves; + /**Whether the enemy AI has infinite resources in most of their buildings and turrets.*/ + public boolean enemyCheat; + /**Whether the game objective is PvP. Note that this enables automatic hosting.*/ + public boolean pvp; + /**Whether enemy units drop random items on death.*/ + public boolean unitDrops; + /**No-build zone around enemy core radius.*/ + public float enemyCoreBuildRadius = 400f; + /**Player respawn time in ticks.*/ + public float respawnTime = 60 * 4; + /**Time between waves in ticks.*/ + 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<>(); +} diff --git a/core/src/io/anuke/mindustry/game/Saves.java b/core/src/io/anuke/mindustry/game/Saves.java index 9e40b65e3c..5555684cef 100644 --- a/core/src/io/anuke/mindustry/game/Saves.java +++ b/core/src/io/anuke/mindustry/game/Saves.java @@ -1,20 +1,21 @@ package io.anuke.mindustry.game; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.IntArray; -import com.badlogic.gdx.utils.IntMap; -import com.badlogic.gdx.utils.TimeUtils; +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.IntMap; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.util.Strings; +import io.anuke.arc.util.Time; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.EventType.StateChangeEvent; import io.anuke.mindustry.io.SaveIO; +import io.anuke.mindustry.io.SaveIO.SaveException; import io.anuke.mindustry.io.SaveMeta; import io.anuke.mindustry.maps.Map; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.util.Strings; -import io.anuke.ucore.util.ThreadArray; +import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.type.Zone; import java.io.IOException; import java.text.SimpleDateFormat; @@ -24,7 +25,7 @@ import static io.anuke.mindustry.Vars.*; public class Saves{ private int nextSlot; - private Array saves = new ThreadArray<>(); + private Array saves = new Array<>(); private IntMap saveMap = new IntMap<>(); private SaveSlot current; private boolean saving; @@ -36,18 +37,16 @@ public class Saves{ public Saves(){ Events.on(StateChangeEvent.class, event -> { if(event.to == State.menu){ - threads.run(() -> { - totalPlaytime = 0; - lastTimestamp = 0; - current = null; - }); + totalPlaytime = 0; + lastTimestamp = 0; + current = null; } }); } public void load(){ saves.clear(); - IntArray slots = Settings.getObject("save-slots", IntArray.class, IntArray::new); + IntArray slots = Core.settings.getObject("save-slots", IntArray.class, IntArray::new); for(int i = 0; i < slots.size; i ++){ int index = slots.get(i); @@ -69,19 +68,19 @@ public class Saves{ SaveSlot current = this.current; if(current != null && !state.is(State.menu) - && !(state.isPaused() && ui.hasDialog())){ + && !(state.isPaused() && Core.scene.hasDialog())){ if(lastTimestamp != 0){ - totalPlaytime += TimeUtils.timeSinceMillis(lastTimestamp); + totalPlaytime += Time.timeSinceMillis(lastTimestamp); } - lastTimestamp = TimeUtils.millis(); + lastTimestamp = Time.millis(); } if(!state.is(State.menu) && !state.gameOver && current != null && current.isAutosave()){ - time += Timers.delta(); - if(time > Settings.getInt("saveinterval") * 60){ + time += Time.delta(); + if(time > Core.settings.getInt("saveinterval") * 60){ saving = true; - Timers.runTask(2f, () -> { + Time.runTask(2f, () -> { try{ current.save(); }catch(Exception e){ @@ -109,6 +108,16 @@ public class Saves{ return saving; } + public void zoneSave(){ + SaveSlot slot = new SaveSlot(-1); + slot.setName("zone"); + saves.remove(s -> s.index == -1); + saves.add(slot); + saveMap.put(slot.index, slot); + slot.save(); + saveSlots(); + } + public SaveSlot addSave(String name){ SaveSlot slot = new SaveSlot(nextSlot); nextSlot++; @@ -129,11 +138,15 @@ public class Saves{ saveMap.put(slot.index, slot); slot.meta = SaveIO.getData(slot.index); current = slot; - slot.meta.sector = invalidSector; saveSlots(); return slot; } + public SaveSlot getZoneSlot(){ + SaveSlot slot = getByID(-1); + return slot == null || slot.getZone() == null ? null : slot; + } + public SaveSlot getByID(int id){ return saveMap.get(id); } @@ -146,8 +159,8 @@ public class Saves{ IntArray result = new IntArray(saves.size); for(int i = 0; i < saves.size; i++) result.add(saves.get(i).index); - Settings.putObject("save-slots", result); - Settings.save(); + Core.settings.putObject("save-slots", result); + Core.settings.save(); } public class SaveSlot{ @@ -158,16 +171,19 @@ public class Saves{ this.index = index; } - public void load(){ - SaveIO.loadFromSlot(index); - meta = SaveIO.getData(index); - current = this; - totalPlaytime = meta.timePlayed; + public void load() throws SaveException{ + try{ + SaveIO.loadFromSlot(index); + meta = SaveIO.getData(index); + current = this; + totalPlaytime = meta.timePlayed; + }catch(Exception e){ + throw new SaveException(e); + } } public void save(){ long time = totalPlaytime; - renderer.fog.writeFog(); long prev = totalPlaytime; totalPlaytime = time; @@ -181,7 +197,7 @@ public class Saves{ } public boolean isHidden(){ - return meta.sector != invalidSector; + return false; } public String getPlayTime(){ @@ -201,12 +217,16 @@ public class Saves{ } public String getName(){ - return Settings.getString("save-" + index + "-name", "untittled"); + return Core.settings.getString("save-" + index + "-name", "untittled"); } public void setName(String name){ - Settings.putString("save-" + index + "-name", name); - Settings.save(); + Core.settings.put("save-" + index + "-name", name); + Core.settings.save(); + } + + public Zone getZone(){ + return content.getByID(ContentType.zone, meta.rules.zone); } public int getBuild(){ @@ -217,21 +237,13 @@ public class Saves{ return meta.wave; } - public Difficulty getDifficulty(){ - return meta.difficulty; - } - - public GameMode getMode(){ - return meta.mode; - } - public boolean isAutosave(){ - return Settings.getBool("save-" + index + "-autosave", true); + return Core.settings.getBool("save-" + index + "-autosave", true); } public void setAutosave(boolean save){ - Settings.putBool("save-" + index + "-autosave", save); - Settings.save(); + Core.settings.put("save-" + index + "-autosave", save); + Core.settings.save(); } public void importFile(FileHandle file) throws IOException{ diff --git a/core/src/io/anuke/mindustry/game/SpawnGroup.java b/core/src/io/anuke/mindustry/game/SpawnGroup.java index 93cbc2a30d..dbdaaa8a7d 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,53 +11,23 @@ import io.anuke.mindustry.type.Weapon; * Each spawn group can have multiple sub-groups spawned in different areas of the map. */ public class SpawnGroup{ - /** - * The unit type spawned - */ + /**The unit type spawned*/ public final UnitType type; - /** - * When this spawn should end - */ + /**When this spawn should end*/ protected int end = Integer.MAX_VALUE; - /** - * When this spawn should start - */ + /**When this spawn should start*/ protected int begin; - /** - * The spacing, in waves, of spawns. For example, 2 = spawns every other wave - */ + /**The spacing, in waves, of spawns. For example, 2 = spawns every other wave*/ protected int spacing = 1; - /** - * Maximum amount of units that spawn - */ + /**Maximum amount of units that spawn*/ protected int max = 60; - /** - * How many waves need to pass before the amount of units spawned increases by 1 - */ + /**How many waves need to pass before the amount of units spawned increases by 1*/ protected float unitScaling = 9999f; - /** - * How many waves need to pass before the amount of instances of this group increases by 1 - */ - protected float groupScaling = 9999f; - /** - * Amount of enemies spawned initially, with no scaling - */ + /**Amount of enemies spawned initially, with no scaling*/ protected int unitAmount = 1; - /** - * Amount of enemies spawned initially, with no scaling - */ - protected int groupAmount = 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. - */ + /**Status effect applied to the spawned unit. Null to disable.*/ protected StatusEffect effect; - /** - * Items this unit spawns with. Null to disable. - */ + /**Items this unit spawns with. Null to disable.*/ protected ItemStack items; public SpawnGroup(UnitType type){ @@ -75,18 +43,7 @@ public class SpawnGroup{ } float scaling = this.unitScaling; - return Math.min(unitAmount - 1 + Math.max((int) ((wave / spacing) / scaling), 1), max); - } - - /** - * Returns the amount of different unit groups at a specific wave. - */ - public int getGroupsSpawned(int wave){ - if(wave < begin || wave > end || (wave - begin) % spacing != 0){ - return 0; - } - - return Math.min(groupAmount - 1 + Math.max((int) ((wave / spacing) / groupScaling), 1), max); + return Math.min(unitAmount - 1 + Math.max((int) (((wave - begin) / spacing) / scaling), 1), max); } /** @@ -96,18 +53,29 @@ 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, 10000f); + unit.applyEffect(effect, 999999f); } if(items != null){ - unit.inventory.addItem(items.item, items.amount); + unit.addItem(items.item, items.amount); } return unit; } + + @Override + public String toString(){ + return "SpawnGroup{" + + "type=" + type + + ", end=" + end + + ", begin=" + begin + + ", spacing=" + spacing + + ", max=" + max + + ", unitScaling=" + unitScaling + + ", unitAmount=" + unitAmount + + ", effect=" + effect + + ", items=" + items + + '}'; + } } diff --git a/core/src/io/anuke/mindustry/game/Stats.java b/core/src/io/anuke/mindustry/game/Stats.java new file mode 100644 index 0000000000..8ef12eee15 --- /dev/null +++ b/core/src/io/anuke/mindustry/game/Stats.java @@ -0,0 +1,27 @@ +package io.anuke.mindustry.game; + +import io.anuke.annotations.Annotations.Serialize; +import io.anuke.arc.collection.ObjectIntMap; +import io.anuke.mindustry.type.Item; + +@Serialize +public class Stats{ + /**Items delivered to global resoure counter. Zones only.*/ + public ObjectIntMap itemsDelivered = new ObjectIntMap<>(); + /**Enemy (red team) units destroyed.*/ + public int enemyUnitsDestroyed; + /**Total waves lasted.*/ + public int wavesLasted; + /**Total (ms) time lasted in this save/zone.*/ + public long timeLasted; + /**Friendly buildings fully built.*/ + public int buildingsBuilt; + /**Friendly buildings fully deconstructed.*/ + public int buildingsDeconstructed; + /**Friendly buildings destroyed.*/ + public int buildingsDestroyed; + + public Rank calculateRank(boolean launched){ + return Rank.F; + } +} diff --git a/core/src/io/anuke/mindustry/game/Team.java b/core/src/io/anuke/mindustry/game/Team.java index 2bace764e2..429e6e970a 100644 --- a/core/src/io/anuke/mindustry/game/Team.java +++ b/core/src/io/anuke/mindustry/game/Team.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.game; -import com.badlogic.gdx.graphics.Color; -import io.anuke.ucore.util.Bundles; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; public enum Team{ none(Color.valueOf("4d4e58")), @@ -21,6 +21,6 @@ public enum Team{ } public String localized(){ - return Bundles.get("team." + name() + ".name"); + return Core.bundle.get("team." + name() + ".name"); } } diff --git a/core/src/io/anuke/mindustry/game/Teams.java b/core/src/io/anuke/mindustry/game/Teams.java index 7b004b37d2..7fac1100ad 100644 --- a/core/src/io/anuke/mindustry/game/Teams.java +++ b/core/src/io/anuke/mindustry/game/Teams.java @@ -1,14 +1,11 @@ package io.anuke.mindustry.game; -import com.badlogic.gdx.utils.ObjectSet; +import io.anuke.arc.collection.EnumSet; +import io.anuke.arc.collection.ObjectSet; import io.anuke.mindustry.Vars; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.util.EnumSet; -import io.anuke.ucore.util.ThreadSet; -/** - * Class for various team-based utilities. - */ +/**Class for various team-based utilities.*/ public class Teams{ private TeamData[] map = new TeamData[Team.all.length]; @@ -38,7 +35,7 @@ public class Teams{ /**Returns whether a team is active, e.g. whether it has any cores remaining.*/ public boolean isActive(Team team){ //the enemy wave team is always active - return (!Vars.state.mode.disableWaves && team == Vars.waveTeam) || get(team).cores.size > 0; + return (Vars.state.rules.waves && team == Vars.waveTeam) || get(team).cores.size > 0; } /**Returns a set of all teams that are enemies of this team.*/ @@ -52,7 +49,7 @@ public class Teams{ } public class TeamData{ - public final ObjectSet cores = new ThreadSet<>(); + public final ObjectSet cores = new ObjectSet<>(); public final EnumSet enemies; public final Team team; diff --git a/core/src/io/anuke/mindustry/game/UnlockableContent.java b/core/src/io/anuke/mindustry/game/UnlockableContent.java index fc90949927..b5dbb56619 100644 --- a/core/src/io/anuke/mindustry/game/UnlockableContent.java +++ b/core/src/io/anuke/mindustry/game/UnlockableContent.java @@ -1,9 +1,8 @@ package io.anuke.mindustry.game; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import io.anuke.ucore.scene.ui.layout.Table; - -import static io.anuke.mindustry.Vars.control; +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{ @@ -29,23 +28,11 @@ public abstract class UnlockableContent extends MappableContent{ return false; } - /**Lists the content that must be unlocked in order for this specific content to become unlocked. May return null.*/ - public UnlockableContent[] getDependencies(){ - return null; + public final boolean unlocked(){ + return Vars.data.isUnlocked(this); } - /**Returns whether dependencies are satisfied for unlocking this content.*/ - public boolean canBeUnlocked(){ - UnlockableContent[] depend = getDependencies(); - if(depend == null){ - return true; - }else{ - for(UnlockableContent cont : depend){ - if(!control.unlocks.isUnlocked(cont)){ - return false; - } - } - return true; - } + public final boolean locked(){ + return !unlocked(); } } diff --git a/core/src/io/anuke/mindustry/game/Unlocks.java b/core/src/io/anuke/mindustry/game/Unlocks.java deleted file mode 100644 index 04109296ca..0000000000 --- a/core/src/io/anuke/mindustry/game/Unlocks.java +++ /dev/null @@ -1,78 +0,0 @@ -package io.anuke.mindustry.game; - -import com.badlogic.gdx.utils.ObjectMap; -import com.badlogic.gdx.utils.ObjectSet; -import io.anuke.mindustry.game.EventType.UnlockEvent; -import io.anuke.mindustry.type.ContentType; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.core.Settings; - -/**Stores player unlocks. Clientside only.*/ -public class Unlocks{ - private ObjectMap> unlocked = new ObjectMap<>(); - private boolean dirty; - - static{ - Settings.setSerializer(ContentType.class, (stream, t) -> stream.writeInt(t.ordinal()), stream -> ContentType.values()[stream.readInt()]); - } - - /** Returns whether or not this piece of content is unlocked yet.*/ - public boolean isUnlocked(UnlockableContent content){ - if(content.alwaysUnlocked()) return true; - - if(!unlocked.containsKey(content.getContentType())){ - unlocked.put(content.getContentType(), new ObjectSet<>()); - } - - ObjectSet set = unlocked.get(content.getContentType()); - - return set.contains(content.getContentName()); - } - - /** - * Makes this piece of content 'unlocked', if possible. - * If this piece of content is already unlocked or cannot be unlocked due to dependencies, nothing changes. - * Results are not saved until you call {@link #save()}. - * - * @return whether or not this content was newly unlocked. - */ - public boolean unlockContent(UnlockableContent content){ - if(!content.canBeUnlocked() || content.alwaysUnlocked()) return false; - - if(!unlocked.containsKey(content.getContentType())){ - unlocked.put(content.getContentType(), new ObjectSet<>()); - } - - boolean ret = unlocked.get(content.getContentType()).add(content.getContentName()); - - //fire unlock event so other classes can use it - if(ret){ - content.onUnlock(); - Events.fire(new UnlockEvent(content)); - dirty = true; - } - - return ret; - } - - /** Returns whether unlockables have changed since the last save.*/ - public boolean isDirty(){ - return dirty; - } - - /** Clears all unlocked content. Automatically saves.*/ - public void reset(){ - save(); - } - - @SuppressWarnings("unchecked") - public void load(){ - unlocked = Settings.getObject("unlockset", ObjectMap.class, ObjectMap::new); - } - - public void save(){ - Settings.putObject("unlockset", unlocked); - Settings.save(); - } - -} diff --git a/core/src/io/anuke/mindustry/game/Version.java b/core/src/io/anuke/mindustry/game/Version.java index 44d4aac4b1..276dd04354 100644 --- a/core/src/io/anuke/mindustry/game/Version.java +++ b/core/src/io/anuke/mindustry/game/Version.java @@ -1,10 +1,10 @@ package io.anuke.mindustry.game; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.utils.ObjectMap; -import com.badlogic.gdx.utils.PropertiesUtils; -import io.anuke.ucore.util.Strings; +import io.anuke.arc.Core; +import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.util.Strings; +import io.anuke.arc.util.io.PropertiesUtils; import java.io.IOException; @@ -22,7 +22,7 @@ public class Version{ public static void init(){ try{ - FileHandle file = Gdx.files.internal("version.properties"); + FileHandle file = Core.files.internal("version.properties"); ObjectMap map = new ObjectMap<>(); PropertiesUtils.load(map, file.reader()); diff --git a/core/src/io/anuke/mindustry/game/Waves.java b/core/src/io/anuke/mindustry/game/Waves.java index 12fe04c959..865ae15424 100644 --- a/core/src/io/anuke/mindustry/game/Waves.java +++ b/core/src/io/anuke/mindustry/game/Waves.java @@ -1,16 +1,17 @@ package io.anuke.mindustry.game; -import com.badlogic.gdx.utils.Array; +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{ + private static Array spawns; - public static Array getSpawns(){ - return Array.with( + public static Array getDefaultSpawns(){ + if(spawns == null){ + spawns = Array.with( new SpawnGroup(UnitTypes.dagger){{ end = 8; unitScaling = 3; @@ -48,7 +49,6 @@ public class Waves{ begin = 28; spacing = 3; unitScaling = 2; - weapon = Weapons.flamethrower; end = 40; }}, @@ -56,7 +56,6 @@ public class Waves{ begin = 45; spacing = 3; unitScaling = 2; - weapon = Weapons.flamethrower; effect = StatusEffects.overdrive; }}, @@ -65,7 +64,6 @@ public class Waves{ spacing = 2; unitScaling = 3; unitAmount = 5; - weapon = Weapons.flakgun; effect = StatusEffects.overdrive; }}, @@ -82,7 +80,6 @@ public class Waves{ begin = 82; spacing = 3; unitAmount = 4; - groupAmount = 2; unitScaling = 3; effect = StatusEffects.overdrive; }}, @@ -108,7 +105,6 @@ public class Waves{ begin = 35; spacing = 3; unitAmount = 4; - groupAmount = 2; effect = StatusEffects.overdrive; items = new ItemStack(Items.blastCompound, 60); end = 60; @@ -118,7 +114,6 @@ public class Waves{ begin = 42; spacing = 3; unitAmount = 4; - groupAmount = 2; effect = StatusEffects.overdrive; items = new ItemStack(Items.pyratite, 100); end = 130; @@ -137,7 +132,6 @@ public class Waves{ unitAmount = 4; unitScaling = 3; spacing = 5; - groupAmount = 2; effect = StatusEffects.overdrive; max = 8; }}, @@ -147,7 +141,6 @@ public class Waves{ unitAmount = 4; unitScaling = 3; spacing = 5; - groupAmount = 2; max = 8; }}, @@ -168,25 +161,22 @@ public class Waves{ max = 8; end = 74; }} - ); + ); + } + return spawns; } - public static void testWaves(int from, int to){ - Array spawns = getSpawns(); + 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) * spawn.getGroupsSpawned(i); + 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(" "); } } diff --git a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java index 5b679ccdf4..35b0d9952e 100644 --- a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java @@ -1,103 +1,160 @@ package io.anuke.mindustry.graphics; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.IntSet; -import com.badlogic.gdx.utils.Sort; -import io.anuke.mindustry.content.blocks.Blocks; +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.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.type.Unit; import io.anuke.mindustry.game.EventType.TileChangeEvent; -import io.anuke.mindustry.game.EventType.WorldLoadGraphicsEvent; +import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Surface; -import io.anuke.ucore.util.Mathf; +import static io.anuke.arc.Core.camera; import static io.anuke.mindustry.Vars.*; -import static io.anuke.ucore.core.Core.camera; public class BlockRenderer{ private final static int initialRequests = 32 * 32; private final static int expandr = 6; + private final static boolean disableShadows = false; + private final static Color shadowColor = new Color(0, 0, 0, 0.19f); - private FloorRenderer floorRenderer; + public final FloorRenderer floor = new FloorRenderer(); private Array requests = new Array<>(true, initialRequests, BlockRequest.class); - private IntSet teamChecks = new IntSet(); private int lastCamX, lastCamY, lastRangeX, lastRangeY; - private Layer lastLayer; private int requestidx = 0; private int iterateidx = 0; - private Surface shadows = Graphics.createSurface().setSize(2, 2); + private FrameBuffer shadows = new FrameBuffer(2, 2); + private FrameBuffer fog = new FrameBuffer(2, 2); public BlockRenderer(){ - floorRenderer = new FloorRenderer(); for(int i = 0; i < requests.size; i++){ requests.set(i, new BlockRequest()); } - Events.on(WorldLoadGraphicsEvent.class, event -> { + 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 -> { - threads.runGraphics(() -> { - int avgx = Mathf.scl(camera.position.x, tilesize); - int avgy = Mathf.scl(camera.position.y, tilesize); - int rangex = (int) (camera.viewportWidth * camera.zoom / tilesize / 2) + 2; - int rangey = (int) (camera.viewportHeight * camera.zoom / tilesize / 2) + 2; + int avgx = (int)(camera.position.x / tilesize); + int avgy = (int)(camera.position. y/ tilesize); + int rangex = (int) (camera.width / tilesize / 2) + 2; + int rangey = (int) (camera.height / tilesize / 2) + 2; - if(Math.abs(avgx - event.tile.x) <= rangex && Math.abs(avgy - event.tile.y) <= rangey){ - lastCamY = lastCamX = -99; //invalidate camera position so blocks get updated - } - }); + if(Math.abs(avgx - event.tile.x) <= rangex && Math.abs(avgy - event.tile.y) <= rangey){ + lastCamY = lastCamX = -99; //invalidate camera position so blocks get updated + } }); } + 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(){ - Draw.color(0, 0, 0, 0.15f); - Draw.rect(shadows.texture(), - Core.camera.position.x - Core.camera.position.x % tilesize, - Core.camera.position.y - Core.camera.position.y % tilesize, - shadows.width(), -shadows.height()); + 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.shadow.color.set(shadowColor); + Shaders.shadow.scl = renderer.cameraScale()/3f; + Shaders.shadow.region = Tmp.tr1; + + Draw.flush(); + shadows.begin(); + Core.graphics.clear(Color.CLEAR); + + floor.beginDraw(); + floor.drawLayer(CacheLayer.walls); + floor.endDraw(); + + drawBlocks(Layer.shadow); + + EntityDraw.drawWith(playerGroup, player -> !player.isDead(), Unit::draw); + for(EntityGroup group : unitGroups){ + EntityDraw.drawWith(group, unit -> !unit.isDead(), Unit::draw); + } + + Draw.color(); + Draw.flush(); + shadows.end(); + + Draw.shader(Shaders.shadow); + Draw.rect(Draw.wrap(shadows.getTexture()), + camera.position.x, + camera.position.y, + camera.width, -camera.height); + Draw.shader(); } - public boolean isTeamShown(Team team){ - return teamChecks.contains(team.ordinal()); - } - - /**Process all blocks to draw, simultaneously updating the block shadow framebuffer.*/ + /**Process all blocks to draw.*/ public void processBlocks(){ iterateidx = 0; - lastLayer = null; - int avgx = Mathf.scl(camera.position.x, tilesize); - int avgy = Mathf.scl(camera.position.y, tilesize); + int avgx = (int)(camera.position.x / tilesize); + int avgy = (int)(camera.position.y / tilesize); - int rangex = (int) (camera.viewportWidth * camera.zoom / tilesize / 2) + 2; - int rangey = (int) (camera.viewportHeight * camera.zoom / tilesize / 2) + 2; + int rangex = (int) (camera.width / tilesize / 2) + 3; + int rangey = (int) (camera.height / tilesize / 2) + 3; if(avgx == lastCamX && avgy == lastCamY && lastRangeX == rangex && lastRangeY == rangey){ return; } - int shadowW = rangex * tilesize*2, shadowH = rangey * tilesize*2; - - teamChecks.clear(); requestidx = 0; - Graphics.end(); - if(shadows.width() != shadowW || shadows.height() != shadowH){ - shadows.setSize(shadowW, shadowH); - } - Core.batch.getProjectionMatrix().setToOrtho2D(Mathf.round(Core.camera.position.x, tilesize)-shadowW/2f, Mathf.round(Core.camera.position.y, tilesize)-shadowH/2f, shadowW, shadowH); - Graphics.surface(shadows); - int minx = Math.max(avgx - rangex - expandr, 0); int miny = Math.max(avgy - rangey - expandr, 0); int maxx = Math.min(world.width() - 1, avgx + rangex + expandr); @@ -107,40 +164,28 @@ 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); + Block block = tile.block(); - if(tile != null){ - Block block = tile.block(); - Team team = tile.getTeam(); - - if(!expanded && block != Blocks.air && world.isAccessible(x, y)){ - tile.block().drawShadow(tile); + if(block != Blocks.air && block.cacheLayer == CacheLayer.normal){ + if(!expanded){ + addRequest(tile, Layer.block); } - if(block != Blocks.air){ - if(!expanded){ - addRequest(tile, Layer.block); - teamChecks.add(team.ordinal()); + if(block.expanded || !expanded){ + addRequest(tile, Layer.shadow); + + if(block.layer != null && block.isLayer(tile)){ + addRequest(tile, block.layer); } - if(block.expanded || !expanded){ - if(block.layer != null && block.isLayer(tile)){ - addRequest(tile, block.layer); - } - - if(block.layer2 != null && block.isLayer2(tile)){ - addRequest(tile, block.layer2); - } + if(block.layer2 != null && block.isLayer2(tile)){ + addRequest(tile, block.layer2); } } } } } - Graphics.surface(); - Graphics.end(); - Core.batch.setProjectionMatrix(camera.combined); - Graphics.begin(); - Sort.instance().sort(requests.items, 0, requestidx); lastCamX = avgx; @@ -149,10 +194,6 @@ public class BlockRenderer{ lastRangeY = rangey; } - public int getRequests(){ - return requestidx; - } - public void drawBlocks(Layer stopAt){ for(; iterateidx < requestidx; iterateidx++){ @@ -162,23 +203,20 @@ public class BlockRenderer{ } BlockRequest req = requests.get(iterateidx); - - if(req.layer != lastLayer){ - if(lastLayer != null) layerEnds(lastLayer); - layerBegins(req.layer); - } - Block block = req.tile.block(); - if(req.layer == Layer.block){ + if(req.layer == Layer.shadow){ + block.drawShadow(req.tile); + }else if(req.layer == Layer.block){ block.draw(req.tile); + if(block.synthetic() && req.tile.getTeam() != players[0].getTeam()){ + block.drawTeam(req.tile); + } }else if(req.layer == block.layer){ block.drawLayer(req.tile); }else if(req.layer == block.layer2){ block.drawLayer2(req.tile); } - - lastLayer = req.layer; } } @@ -208,7 +246,6 @@ public class BlockRenderer{ } public void skipLayer(Layer stopAt){ - for(; iterateidx < requestidx; iterateidx++){ if(iterateidx < requests.size && requests.get(iterateidx).layer.ordinal() > stopAt.ordinal()){ break; @@ -216,24 +253,6 @@ public class BlockRenderer{ } } - public void beginFloor(){ - floorRenderer.beginDraw(); - } - - public void endFloor(){ - floorRenderer.endDraw(); - } - - public void drawFloor(){ - floorRenderer.drawFloor(); - } - - private void layerBegins(Layer layer){ - } - - private void layerEnds(Layer layer){ - } - private void addRequest(Tile tile, Layer layer){ if(requestidx >= requests.size){ requests.add(new BlockRequest()); diff --git a/core/src/io/anuke/mindustry/graphics/CacheLayer.java b/core/src/io/anuke/mindustry/graphics/CacheLayer.java index 4a13487541..e84bd0a823 100644 --- a/core/src/io/anuke/mindustry/graphics/CacheLayer.java +++ b/core/src/io/anuke/mindustry/graphics/CacheLayer.java @@ -1,59 +1,12 @@ package io.anuke.mindustry.graphics; -import com.badlogic.gdx.graphics.Color; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Shader; - -import static io.anuke.mindustry.Vars.renderer; - public enum CacheLayer{ - water{ - @Override - public void begin(){ - beginShader(); - } - - @Override - public void end(){ - endShader(Shaders.water); - } - }, - lava{ - @Override - public void begin(){ - beginShader(); - } - - @Override - public void end(){ - endShader(Shaders.lava); - } - }, - oil{ - @Override - public void begin(){ - beginShader(); - } - - @Override - public void end(){ - endShader(Shaders.oil); - } - }, - space{ - @Override - public void begin(){ - beginShader(); - } - - @Override - public void end(){ - endShader(Shaders.space); - } - }, - normal; + water, + lava, + oil, + space, + normal, + walls; public void begin(){ @@ -62,27 +15,4 @@ public enum CacheLayer{ public void end(){ } - - protected void beginShader(){ - //renderer.getBlocks().endFloor(); - renderer.effectSurface.getBuffer().begin(); - Graphics.clear(Color.CLEAR); - //renderer.getBlocks().beginFloor(); - } - - public void endShader(Shader shader){ - renderer.blocks.endFloor(); - - //renderer.effectSurface.getBuffer().end(); - - renderer.pixelSurface.getBuffer().begin(); - - Graphics.shader(shader); - Graphics.begin(); - Draw.rect(renderer.effectSurface.texture(), Core.camera.position.x, Core.camera.position.y, - Core.camera.viewportWidth * Core.camera.zoom, -Core.camera.viewportHeight * Core.camera.zoom); - Graphics.end(); - Graphics.shader(); - renderer.blocks.beginFloor(); - } } diff --git a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java index 36510734d7..cac217ce05 100644 --- a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java @@ -1,27 +1,24 @@ package io.anuke.mindustry.graphics; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.GL20; -import com.badlogic.gdx.graphics.OrthographicCamera; -import com.badlogic.gdx.utils.IntArray; -import com.badlogic.gdx.utils.IntSet; -import com.badlogic.gdx.utils.IntSet.IntSetIterator; -import com.badlogic.gdx.utils.ObjectSet; -import io.anuke.mindustry.game.EventType.WorldLoadGraphicsEvent; -import io.anuke.mindustry.maps.Sector; +import io.anuke.arc.Core; +import io.anuke.arc.Events; +import io.anuke.arc.collection.IntArray; +import io.anuke.arc.collection.IntSet; +import io.anuke.arc.collection.IntSet.IntSetIterator; +import io.anuke.arc.collection.ObjectSet; +import io.anuke.arc.graphics.Camera; +import io.anuke.arc.graphics.GL20; +import io.anuke.arc.graphics.g2d.CacheBatch; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.SpriteBatch; +import io.anuke.arc.graphics.g2d.SpriteCache; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Log; +import io.anuke.arc.util.Structs; +import io.anuke.arc.util.Time; +import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.CacheBatch; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Structs; import java.util.Arrays; @@ -35,9 +32,10 @@ public class FloorRenderer{ private CacheBatch cbatch; private IntSet drawnLayerSet = new IntSet(); private IntArray drawnLayers = new IntArray(); + private ObjectSet used = new ObjectSet<>(); public FloorRenderer(){ - Events.on(WorldLoadGraphicsEvent.class, event -> clearTiles()); + Events.on(WorldLoadEvent.class, event -> clearTiles()); } public void drawFloor(){ @@ -45,13 +43,13 @@ public class FloorRenderer{ return; } - OrthographicCamera camera = Core.camera; + Camera camera = Core.camera; - int crangex = (int) (camera.viewportWidth * camera.zoom / (chunksize * tilesize)) + 1; - int crangey = (int) (camera.viewportHeight * camera.zoom / (chunksize * tilesize)) + 1; + int crangex = (int) (camera.width / (chunksize * tilesize)) + 1; + int crangey = (int) (camera.height / (chunksize * tilesize)) + 1; - int camx = Mathf.scl(camera.position.x, chunksize * tilesize); - int camy = Mathf.scl(camera.position.y, chunksize * tilesize); + int camx = (int)(camera.position.x / (chunksize * tilesize)); + int camy = (int)(camera.position.y / (chunksize * tilesize)); int layers = CacheLayer.values().length; @@ -85,7 +83,7 @@ public class FloorRenderer{ drawnLayers.sort(); - Graphics.end(); + Draw.flush(); beginDraw(); for(int i = 0; i < drawnLayers.size; i++){ @@ -95,7 +93,6 @@ public class FloorRenderer{ } endDraw(); - Graphics.begin(); } public void beginDraw(){ @@ -103,10 +100,10 @@ public class FloorRenderer{ return; } - cbatch.setProjectionMatrix(Core.camera.combined); + cbatch.setProjection(Core.camera.projection()); cbatch.beginDraw(); - Gdx.gl.glEnable(GL20.GL_BLEND); + Core.gl.glEnable(GL20.GL_BLEND); } public void endDraw(){ @@ -122,17 +119,19 @@ public class FloorRenderer{ return; } - OrthographicCamera camera = Core.camera; + Camera camera = Core.camera; - int crangex = (int) (camera.viewportWidth * camera.zoom / (chunksize * tilesize)) + 1; - int crangey = (int) (camera.viewportHeight * camera.zoom / (chunksize * tilesize)) + 1; + int crangex = (int) (camera.width / (chunksize * tilesize)) + 1; + int crangey = (int) (camera.height / (chunksize * tilesize)) + 1; + SpriteBatch batch = Core.batch; + Core.batch = cbatch; layer.begin(); for(int x = -crangex; x <= crangex; x++){ for(int y = -crangey; y <= crangey; y++){ - int worldx = Mathf.scl(camera.position.x, chunksize * tilesize) + x; - int worldy = Mathf.scl(camera.position.y, chunksize * tilesize) + y; + int worldx = (int)(camera.position.x / (chunksize * tilesize)) + x; + int worldy = (int)(camera.position.y / (chunksize * tilesize)) + y; if(!Structs.inBounds(worldx, worldy, cache)){ continue; @@ -145,27 +144,23 @@ public class FloorRenderer{ } layer.end(); - } - - private void fillChunk(float x, float y){ - Draw.color(Color.BLACK); - Fill.crect(x, y, chunksize * tilesize, chunksize * tilesize); - Draw.color(); + Core.batch = batch; } private void cacheChunk(int cx, int cy){ + used.clear(); Chunk chunk = cache[cx][cy]; - ObjectSet used = new ObjectSet<>(); - - Sector sector = world.getSector(); - for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize; tilex++){ for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize; tiley++){ Tile tile = world.tile(tilex, tiley); if(tile != null){ - used.add(tile.floor().cacheLayer); + if(tile.block().cacheLayer != CacheLayer.normal){ + used.add(tile.block().cacheLayer); + }else{ + used.add(tile.floor().cacheLayer); + } } } } @@ -176,11 +171,10 @@ public class FloorRenderer{ } private void cacheChunkLayer(int cx, int cy, Chunk chunk, CacheLayer layer){ + SpriteBatch current = Core.batch; + Core.batch = cbatch; - Graphics.useBatch(cbatch); - cbatch.begin(); - - Sector sector = world.getSector(); + cbatch.beginCache(); for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize; tilex++){ for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize; tiley++){ @@ -193,28 +187,27 @@ public class FloorRenderer{ floor = tile.floor(); } - if(floor.cacheLayer == layer){ + if(tile.block().cacheLayer == layer && layer == CacheLayer.walls){ + tile.block().draw(tile); + }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()){ - floor.drawNonLayer(tile); } } } - - cbatch.end(); - Graphics.popBatch(); - chunk.caches[layer.ordinal()] = cbatch.getLastCache(); + Core.batch = current; + chunk.caches[layer.ordinal()] = cbatch.endCache(); } public void clearTiles(){ if(cbatch != null) cbatch.dispose(); int chunksx = Mathf.ceil((float) (world.width()) / chunksize), - chunksy = Mathf.ceil((float) (world.height()) / chunksize) ; + chunksy = Mathf.ceil((float) (world.height()) / chunksize) ; cache = new Chunk[chunksx][chunksy]; - cbatch = new CacheBatch(world.width() * world.height() * 4 * 4); + SpriteCache sprites = new SpriteCache(world.width() * world.height() * 5, (world.width() / chunksize) * (world.height() / chunksize) * 2, false); + cbatch = new CacheBatch(sprites); - Timers.mark(); + Time.mark(); for(int x = 0; x < chunksx; x++){ for(int y = 0; y < chunksy; y++){ @@ -225,7 +218,7 @@ public class FloorRenderer{ } } - Log.info("Time to cache: {0}", Timers.elapsed()); + Log.info("Time to cache: {0}", Time.elapsed()); } private class Chunk{ diff --git a/core/src/io/anuke/mindustry/graphics/FogRenderer.java b/core/src/io/anuke/mindustry/graphics/FogRenderer.java deleted file mode 100644 index 7c920c78b0..0000000000 --- a/core/src/io/anuke/mindustry/graphics/FogRenderer.java +++ /dev/null @@ -1,177 +0,0 @@ -package io.anuke.mindustry.graphics; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.GL20; -import com.badlogic.gdx.graphics.Pixmap.Format; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.glutils.FrameBuffer; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Disposable; -import io.anuke.mindustry.entities.Unit; -import io.anuke.mindustry.game.EventType.TileChangeEvent; -import io.anuke.mindustry.game.EventType.WorldLoadGraphicsEvent; -import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.entities.EntityDraw; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; - -import java.nio.ByteBuffer; - -import static io.anuke.mindustry.Vars.*; - -/**Used for rendering fog of war. A framebuffer is used for this.*/ -public class FogRenderer implements Disposable{ - private TextureRegion region = new TextureRegion(); - private FrameBuffer buffer; - private ByteBuffer pixelBuffer; - private Array changeQueue = new Array<>(); - private int shadowPadding; - private boolean dirty; - - public FogRenderer(){ - Events.on(WorldLoadGraphicsEvent.class, event -> { - dispose(); - - shadowPadding = -1; - - buffer = new FrameBuffer(Format.RGBA8888, world.width(), world.height(), false); - changeQueue.clear(); - - //clear buffer to black - buffer.begin(); - Graphics.clear(0, 0, 0, 1f); - buffer.end(); - - for(int x = 0; x < world.width(); x++){ - for(int y = 0; y < world.height(); y++){ - Tile tile = world.tile(x, y); - if(tile.getTeam() == players[0].getTeam() && tile.block().synthetic() && tile.block().viewRange > 0){ - changeQueue.add(tile); - } - } - } - - pixelBuffer = ByteBuffer.allocateDirect(world.width() * world.height() * 4); - dirty = true; - }); - - Events.on(TileChangeEvent.class, event -> threads.runGraphics(() -> { - if(event.tile.getTeam() == players[0].getTeam() && event.tile.block().synthetic() && event.tile.block().viewRange > 0){ - changeQueue.add(event.tile); - } - })); - } - - public void writeFog(){ - if(buffer == null) return; - - buffer.begin(); - pixelBuffer.position(0); - Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1); - Gdx.gl.glReadPixels(0, 0, world.width(), world.height(), GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, pixelBuffer); - - pixelBuffer.position(0); - for(int i = 0; i < world.width() * world.height(); i++){ - int x = i % world.width(); - int y = i / world.width(); - byte r = pixelBuffer.get(); - if(r != 0){ - world.tile(x, y).setVisibility((byte)1); - } - pixelBuffer.position(pixelBuffer.position() + 3); - } - buffer.end(); - } - - public int getPadding(){ - return -shadowPadding; - } - - public void draw(){ - if(buffer == null) return; - - float vw = Core.camera.viewportWidth * Core.camera.zoom; - float vh = Core.camera.viewportHeight * Core.camera.zoom; - - float px = Core.camera.position.x - vw / 2f; - float py = Core.camera.position.y - vh / 2f; - - float u = (px / tilesize) / buffer.getWidth(); - float v = (py / tilesize) / buffer.getHeight(); - - float u2 = ((px + vw) / tilesize) / buffer.getWidth(); - float v2 = ((py + vh) / tilesize) / buffer.getHeight(); - - Core.batch.getProjectionMatrix().setToOrtho2D(0, 0, buffer.getWidth() * tilesize, buffer.getHeight() * tilesize); - - Draw.color(Color.WHITE); - - buffer.begin(); - - Graphics.beginClip((-shadowPadding), (-shadowPadding), (world.width() + shadowPadding*2), (world.height() + shadowPadding*2)); - - Graphics.begin(); - EntityDraw.setClip(false); - - renderer.drawAndInterpolate(playerGroup, player -> !player.isDead() && player.getTeam() == players[0].getTeam(), Unit::drawView); - renderer.drawAndInterpolate(unitGroups[players[0].getTeam().ordinal()], unit -> !unit.isDead(), Unit::drawView); - - for(Tile tile : changeQueue){ - float viewRange = tile.block().viewRange; - if(viewRange < 0) continue; - Fill.circle(tile.drawx(), tile.drawy(), tile.block().viewRange); - } - - changeQueue.clear(); - - if(dirty){ - for(int x = 0; x < world.width(); x++){ - for(int y = 0; y < world.height(); y++){ - Tile tile = world.tile(x, y); - if(tile.discovered()){ - Fill.rect(tile.worldx(), tile.worldy(), tilesize, tilesize); - } - } - } - dirty = false; - } - - EntityDraw.setClip(true); - Graphics.end(); - buffer.end(); - - Graphics.endClip(); - - region.setTexture(buffer.getColorBufferTexture()); - region.setRegion(u, v2, u2, v); - - Core.batch.setProjectionMatrix(Core.camera.combined); - Graphics.shader(Shaders.fog); - renderer.pixelSurface.getBuffer().begin(); - Graphics.begin(); - - Core.batch.draw(region, px, py, vw, vh); - - Graphics.end(); - renderer.pixelSurface.getBuffer().end(); - Graphics.shader(); - - Graphics.setScreen(); - Core.batch.draw(renderer.pixelSurface.texture(), 0, Gdx.graphics.getHeight(), Gdx.graphics.getWidth(), -Gdx.graphics.getHeight()); - Graphics.end(); - } - - public Texture getTexture(){ - return buffer.getColorBufferTexture(); - } - - @Override - public void dispose(){ - if(buffer != null) buffer.dispose(); - } -} diff --git a/core/src/io/anuke/mindustry/graphics/IndexedRenderer.java b/core/src/io/anuke/mindustry/graphics/IndexedRenderer.java new file mode 100644 index 0000000000..c082b7c8a9 --- /dev/null +++ b/core/src/io/anuke/mindustry/graphics/IndexedRenderer.java @@ -0,0 +1,214 @@ +package io.anuke.mindustry.graphics; + +import io.anuke.arc.Core; +import io.anuke.arc.graphics.*; +import io.anuke.arc.graphics.VertexAttributes.Usage; +import io.anuke.arc.graphics.g2d.BatchShader; +import io.anuke.arc.graphics.g2d.TextureRegion; +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; + +//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 Mesh mesh; + private float[] tmpVerts = new float[vsize * 6]; + private float[] vertices; + + private Matrix3 projMatrix = new Matrix3(); + private Matrix3 transMatrix = new Matrix3(); + private Matrix3 combined = new Matrix3(); + private float color = Color.WHITE.toFloatBits(); + + public IndexedRenderer(int sprites){ + resize(sprites); + } + + public void render(Texture texture){ + Core.gl.glEnable(GL20.GL_BLEND); + + updateMatrix(); + + program.begin(); + + texture.bind(); + + program.setUniformMatrix4("u_projTrans", BatchShader.copyTransform(combined)); + program.setUniformi("u_texture", 0); + + mesh.render(program, GL20.GL_TRIANGLES, 0, vertices.length / vsize); + + program.end(); + } + + public void setColor(Color color){ + this.color = color.toFloatBits(); + } + + public void draw(int index, TextureRegion region, float x, float y, float w, float h){ + final float fx2 = x + w; + final float fy2 = y + h; + final float u = region.getU(); + final float v = region.getV2(); + final float u2 = region.getU2(); + final float v2 = region.getV(); + + float[] vertices = tmpVerts; + + int idx = 0; + vertices[idx++] = x; + vertices[idx++] = y; + vertices[idx++] = color; + vertices[idx++] = u; + vertices[idx++] = v; + + vertices[idx++] = x; + vertices[idx++] = fy2; + vertices[idx++] = color; + vertices[idx++] = u; + vertices[idx++] = v2; + + vertices[idx++] = fx2; + vertices[idx++] = fy2; + vertices[idx++] = color; + vertices[idx++] = u2; + vertices[idx++] = v2; + + //tri2 + vertices[idx++] = x; + vertices[idx++] = y; + vertices[idx++] = color; + vertices[idx++] = u; + vertices[idx++] = v; + + vertices[idx++] = fx2; + vertices[idx++] = y; + vertices[idx++] = color; + vertices[idx++] = u2; + vertices[idx++] = v; + + vertices[idx++] = fx2; + vertices[idx++] = fy2; + vertices[idx++] = color; + vertices[idx++] = u2; + vertices[idx++] = v2; + + mesh.updateVertices(index * vsize * 6, vertices); + } + + public void draw(int index, TextureRegion region, float x, float y, float w, float h, float rotation){ + final float u = region.getU(); + final float v = region.getV2(); + final float u2 = region.getU2(); + final float v2 = region.getV(); + + final float originX = w / 2, originY = h / 2; + + final float cos = Mathf.cosDeg(rotation); + final float sin = Mathf.sinDeg(rotation); + + float fx = -originX; + float fy = -originY; + float fx2 = w - originX; + float fy2 = h - originY; + + final float worldOriginX = x + originX; + final float worldOriginY = y + originY; + + float x1 = cos * fx - sin * fy; + float y1 = sin * fx + cos * fy; + + float x2 = cos * fx - sin * fy2; + float y2 = sin * fx + cos * fy2; + + float x3 = cos * fx2 - sin * fy2; + float y3 = sin * fx2 + cos * fy2; + + float x4 = x1 + (x3 - x2); + float y4 = y3 - (y2 - y1); + + x1 += worldOriginX; + y1 += worldOriginY; + x2 += worldOriginX; + y2 += worldOriginY; + x3 += worldOriginX; + y3 += worldOriginY; + x4 += worldOriginX; + y4 += worldOriginY; + + float[] vertices = tmpVerts; + + int idx = 0; + vertices[idx++] = x1; + vertices[idx++] = y1; + vertices[idx++] = color; + vertices[idx++] = u; + vertices[idx++] = v; + + vertices[idx++] = x3; + vertices[idx++] = y3; + vertices[idx++] = color; + vertices[idx++] = u2; + vertices[idx++] = v2; + + vertices[idx++] = x4; + vertices[idx++] = y4; + vertices[idx++] = color; + vertices[idx++] = u; + vertices[idx++] = v2; + + //tri2 + vertices[idx++] = x1; + vertices[idx++] = y1; + vertices[idx++] = color; + vertices[idx++] = u; + vertices[idx++] = v; + + vertices[idx++] = x2; + vertices[idx++] = y2; + vertices[idx++] = color; + vertices[idx++] = u2; + vertices[idx++] = v; + + vertices[idx++] = x3; + vertices[idx++] = y3; + vertices[idx++] = color; + vertices[idx++] = u2; + vertices[idx++] = v2; + + mesh.updateVertices(index * vsize * 6, vertices); + } + + public Matrix3 getTransformMatrix(){ + return transMatrix; + } + + public void setProjectionMatrix(Matrix3 matrix){ + projMatrix = matrix; + } + + public void resize(int sprites){ + if(mesh != null) mesh.dispose(); + + mesh = new Mesh(true, 6 * sprites, 0, + new VertexAttribute(Usage.Position, 2, "a_position"), + new VertexAttribute(Usage.ColorPacked, 4, "a_color"), + new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoord0")); + vertices = new float[6 * sprites * vsize]; + mesh.setVertices(vertices); + } + + private void updateMatrix(){ + combined.set(projMatrix).mul(transMatrix); + } + + @Override + public void dispose(){ + mesh.dispose(); + program.dispose(); + } +} diff --git a/core/src/io/anuke/mindustry/graphics/Layer.java b/core/src/io/anuke/mindustry/graphics/Layer.java index f04144a2cd..493a13deba 100644 --- a/core/src/io/anuke/mindustry/graphics/Layer.java +++ b/core/src/io/anuke/mindustry/graphics/Layer.java @@ -1,28 +1,18 @@ package io.anuke.mindustry.graphics; public enum Layer{ - /** - * Base block layer. - */ + /**Drawn under everything.*/ + shadow, + /**Base block layer.*/ block, - /** - * for placement - */ + /**for placement*/ placement, - /** - * First overlay. Stuff like conveyor items. - */ + /**First overlay. Stuff like conveyor items.*/ overlay, - /** - * "High" blocks, like turrets. - */ + /**"High" blocks, like turrets.*/ turret, - /** - * Power lasers. - */ + /**Power lasers.*/ power, - /** - * Extra lasers, like healing turrets. - */ + /**Extra lasers, like healing turrets.*/ laser } diff --git a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java index e900b2feef..5c938d2b8c 100644 --- a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java @@ -1,54 +1,53 @@ package io.anuke.mindustry.graphics; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.Pixmap.Format; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Disposable; -import io.anuke.mindustry.entities.Unit; +import io.anuke.arc.Core; +import io.anuke.arc.Events; +import io.anuke.arc.collection.Array; +import io.anuke.arc.graphics.Pixmap; +import io.anuke.arc.graphics.Pixmap.Format; +import io.anuke.arc.graphics.Pixmaps; +import io.anuke.arc.graphics.Texture; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.Fill; +import io.anuke.arc.graphics.g2d.ScissorStack; +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.type.Unit; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.game.EventType.TileChangeEvent; -import io.anuke.mindustry.game.EventType.WorldLoadGraphicsEvent; -import io.anuke.mindustry.world.ColorMapper; +import io.anuke.mindustry.game.EventType.WorldLoadEvent; +import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Pixmaps; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.ThreadArray; import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; public class MinimapRenderer implements Disposable{ private static final int baseSize = 16; - private final Array units = new ThreadArray<>(); + private final Array units = new Array<>(); private Pixmap pixmap; private Texture texture; private TextureRegion region; - private Rectangle rect = new Rectangle(); + private Rectangle rect = new Rectangle(), scissor = new Rectangle(); private int zoom = 4; public MinimapRenderer(){ - Events.on(WorldLoadGraphicsEvent.class, event -> { + Events.on(WorldLoadEvent.class, event -> { reset(); updateAll(); }); //make sure to call on the graphics thread - Events.on(TileChangeEvent.class, event -> Gdx.app.postRunnable(() -> update(event.tile))); + Events.on(TileChangeEvent.class, event -> Core.app.post(() -> update(event.tile))); } public Texture getTexture(){ return texture; } - public void zoomBy(int amount){ + public void zoomBy(float amount){ zoom += amount; zoom = Mathf.clamp(zoom, 1, Math.min(world.width(), world.height()) / baseSize / 2); } @@ -68,24 +67,29 @@ public class MinimapRenderer implements Disposable{ } public void drawEntities(float x, float y, float w, float h){ + updateUnitArray(); + int sz = baseSize * zoom; float dx = (Core.camera.position.x / tilesize); float dy = (Core.camera.position.y / tilesize); dx = Mathf.clamp(dx, sz, world.width() - sz); dy = Mathf.clamp(dy, sz, world.height() - sz); + if(!ScissorStack.pushScissors(scissor.set(x, y, w, h))){ + return; + } + rect.set((dx - sz) * tilesize, (dy - sz) * tilesize, sz * 2 * tilesize, sz * 2 * tilesize); - Graphics.beginClip(x, y, w, h); for(Unit unit : units){ float rx = (unit.x - rect.x) / rect.width * w, ry = (unit.y - rect.y) / rect.width * h; Draw.color(unit.getTeam().color); - Draw.crect(Draw.getBlankRegion(), x + rx, y + ry, w / (sz * 2), h / (sz * 2)); + Fill.crect(x + rx, y + ry, w / (sz * 2), h / (sz * 2)); } Draw.color(); - Graphics.endClip(); + ScissorStack.popScissors(); } public TextureRegion getRegion(){ @@ -99,7 +103,7 @@ public class MinimapRenderer implements Disposable{ float invTexWidth = 1f / texture.getWidth(); float invTexHeight = 1f / texture.getHeight(); float x = dx - sz, y = world.height() - dy - sz, width = sz * 2, height = sz * 2; - region.setRegion(x * invTexWidth, y * invTexHeight, (x + width) * invTexWidth, (y + height) * invTexHeight); + region.set(x * invTexWidth, y * invTexHeight, (x + width) * invTexWidth, (y + height) * invTexHeight); return region; } @@ -133,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(), tile.getElevation(), tile.getCliffs()); + 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 3c070132fa..2d9f50b4b5 100644 --- a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java @@ -1,27 +1,20 @@ package io.anuke.mindustry.graphics; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.MathUtils; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.content.blocks.Blocks; -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.graphics.g2d.Lines; +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.Time; +import io.anuke.arc.util.Tmp; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.input.InputHandler; -import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockBar; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Tmp; import static io.anuke.mindustry.Vars.*; @@ -34,32 +27,24 @@ public class OverlayRenderer{ for(Player player : players){ InputHandler input = control.input(player.playerIndex); - if(world.getSector() != null){ - world.getSector().currentMission().drawOverlay(); - } - if(!input.isDrawing() || player.isDead()) continue; - Shaders.outline.color.set(Palette.accent); - Graphics.beginShaders(Shaders.outline); + Shaders.outline.color.set(Pal.accent); input.drawOutlined(); - - Graphics.endShaders(); } } public void drawTop(){ for(Player player : playerGroup.all()){ - if(Settings.getBool("indicators") && player != players[0] && player.getTeam() == players[0].getTeam()){ - if(!rect.setSize(Core.camera.viewportWidth * Core.camera.zoom * 0.9f, Core.camera.viewportHeight * Core.camera.zoom * 0.9f) + if(Core.settings.getBool("indicators") && player != players[0] && player.getTeam() == players[0].getTeam()){ + if(!rect.setSize(Core.camera.width * 0.9f, Core.camera.height * 0.9f) .setCenter(Core.camera.position.x, Core.camera.position.y).contains(player.x, player.y)){ Tmp.v1.set(player.x, player.y).sub(Core.camera.position.x, Core.camera.position.y).setLength(indicatorLength); - Draw.color(player.getTeam().color); - Lines.stroke(2f); + Lines.stroke(2f, player.getTeam().color); Lines.lineAngle(Core.camera.position.x + Tmp.v1.x, Core.camera.position.y + Tmp.v1.y, Tmp.v1.angle(), 4f); Draw.reset(); } @@ -87,12 +72,12 @@ public class OverlayRenderer{ if(buildFadeTime > 0.005f){ for(Team enemy : state.teams.enemiesOf(player.getTeam())){ for(Tile core : state.teams.get(enemy).cores){ - float dst = Vector2.dst(player.x, player.y, core.drawx(), core.drawy()); - if(dst < state.mode.enemyCoreBuildRadius * 1.5f){ + float dst = Mathf.dst(player.x, player.y, core.drawx(), core.drawy()); + if(dst < state.rules.enemyCoreBuildRadius * 1.5f){ Draw.color(Color.DARK_GRAY); - Lines.poly(core.drawx(), core.drawy() - 2, 200, state.mode.enemyCoreBuildRadius); - Draw.color(Palette.accent, enemy.color, 0.5f + Mathf.absin(Timers.time(), 10f, 0.5f)); - Lines.poly(core.drawx(), core.drawy(), 200, state.mode.enemyCoreBuildRadius); + Lines.poly(core.drawx(), core.drawy() - 2, 200, state.rules.enemyCoreBuildRadius); + 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); } } } @@ -101,129 +86,32 @@ public class OverlayRenderer{ Draw.reset(); //draw selected block bars and info - if(input.recipe == null && !ui.hasMouse()){ - Vector2 vec = Graphics.world(input.getMouseX(), input.getMouseY()); + if(input.block == null && !Core.scene.hasMouse()){ + Vector2 vec = Core.input.mouseWorld(input.getMouseX(), input.getMouseY()); Tile tile = world.tileWorld(vec.x, vec.y); if(tile != null && tile.block() != Blocks.air && tile.target().getTeam() == players[0].getTeam()){ Tile target = tile.target(); - - if(showBlockDebug && target.entity != null){ - Draw.color(Color.RED); - Lines.crect(target.drawx(), target.drawy(), target.block().size * tilesize, target.block().size * tilesize); - Vector2 v = new Vector2(); - - Draw.tcolor(Color.YELLOW); - Draw.tscl(0.25f); - Array arr = target.block().getDebugInfo(target); - StringBuilder result = new StringBuilder(); - for(int i = 0; i < arr.size / 2; i++){ - result.append(arr.get(i * 2)); - result.append(": "); - result.append(arr.get(i * 2 + 1)); - result.append("\n"); - } - Draw.textc(result.toString(), target.drawx(), target.drawy(), v); - Draw.color(0f, 0f, 0f, 0.5f); - Fill.rect(target.drawx(), target.drawy(), v.x, v.y); - Draw.textc(result.toString(), target.drawx(), target.drawy(), v); - Draw.tscl(1f); - Draw.reset(); - } - - Block block = target.block(); - TileEntity entity = target.entity; - - if(entity != null){ - int[] values = {0, 0}; - boolean[] doDraw = {false}; - - Runnable drawbars = () -> { - for(BlockBar bar : block.bars.list()){ - float offset = Mathf.sign(bar.top) * (block.size / 2f * tilesize + 2f + (bar.top ? values[0] : values[1])); - - float value = bar.value.get(target); - - if(MathUtils.isEqual(value, -1f)) continue; - - if(doDraw[0]){ - drawBar(bar.type.color, target.drawx(), target.drawy() + offset, value); - } - - if(bar.top) - values[0]++; - else - values[1]++; - } - }; - - drawbars.run(); - - if(values[0] > 0){ - drawEncloser(target.drawx(), target.drawy() + block.size * tilesize / 2f + 2f, values[0]); - } - - if(values[1] > 0){ - drawEncloser(target.drawx(), target.drawy() - block.size * tilesize / 2f - 2f - values[1], values[1]); - } - - doDraw[0] = true; - values[0] = 0; - values[1] = 1; - - drawbars.run(); - } - - target.block().drawSelect(target); - } } if(input.isDroppingItem()){ - Vector2 v = Graphics.world(input.getMouseX(), input.getMouseY()); + 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); - Lines.circle(v.x, v.y, 6 + Mathf.absin(Timers.time(), 5f, 1f)); + 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); - Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f + 1 + Mathf.absin(Timers.time(), 5f, 1f)); + if(tile != null && tile.getTeam() == 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(); } } } } - - void drawBar(Color color, float x, float y, float finion){ - if(finion > 0.9f) finion = 1f; //fixes precision errors - finion = Mathf.clamp(finion); - - if(finion > 0.001f) finion = Mathf.clamp(finion, 0.24f, 1f); - - float len = 3; - - float w = (int) (len * 2 * finion); - - Draw.color(Color.BLACK); - Fill.crect(x - len, y, len * 2f, 1); - if(finion > 0){ - Draw.color(color); - Fill.crect(x - len, y, Math.max(1, w), 1); - } - Draw.color(); - } - - void drawEncloser(float x, float y, float height){ - - float len = 4; - - Draw.color(Palette.bar); - Fill.crect(x - len, y - 1, len * 2f, height + 2f); - Draw.color(); - } } diff --git a/core/src/io/anuke/mindustry/graphics/Palette.java b/core/src/io/anuke/mindustry/graphics/Pal.java similarity index 85% rename from core/src/io/anuke/mindustry/graphics/Palette.java rename to core/src/io/anuke/mindustry/graphics/Pal.java index 437a36034c..cad77809cb 100644 --- a/core/src/io/anuke/mindustry/graphics/Palette.java +++ b/core/src/io/anuke/mindustry/graphics/Pal.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.graphics; -import com.badlogic.gdx.graphics.Color; +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,14 +38,13 @@ public class Palette{ lancerLaser = Color.valueOf("a9d8ff"), stoneGray = Color.valueOf("8f8f8f"), + engine = Color.valueOf("ffbb64"), - portalLight = Color.valueOf("9054ea"), - portal = Color.valueOf("6344d7"), - portalDark = Color.valueOf("3f3dac"), - + health = Color.valueOf("ff341c"), heal = Color.valueOf("98ffa9"), bar = Color.SLATE, accent = Color.valueOf("ffd37f"), + locked = Color.valueOf("989aa4"), accentBack = Color.valueOf("d4816b"), place = Color.valueOf("6335f8"), remove = Color.valueOf("e55454"), @@ -54,7 +54,10 @@ public class Palette{ range = Color.valueOf("f4ba6e"), power = Color.valueOf("fbad67"), powerLight = Color.valueOf("fbd367"), - placing = Color.valueOf("616161"), + placing = accent, + + unitFront = Color.valueOf("ffa665"), + unitBack = Color.valueOf("d06b53"), lightTrail = Color.valueOf("ffe2a9"), diff --git a/core/src/io/anuke/mindustry/graphics/Shaders.java b/core/src/io/anuke/mindustry/graphics/Shaders.java index 254234f419..2d8219127d 100644 --- a/core/src/io/anuke/mindustry/graphics/Shaders.java +++ b/core/src/io/anuke/mindustry/graphics/Shaders.java @@ -1,26 +1,18 @@ package io.anuke.mindustry.graphics; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Shader; -import io.anuke.ucore.scene.ui.layout.Unit; - -import static io.anuke.mindustry.Vars.tilesize; -import static io.anuke.mindustry.Vars.world; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.glutils.Shader; +import io.anuke.arc.scene.ui.layout.Unit; +import io.anuke.arc.util.Time; 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; @@ -29,21 +21,18 @@ public class Shaders{ 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 Shader("fullmix", "default"); + fullMix = new LoadShader("fullmix", "default"); menu = new MenuShader(); } - public static class MenuShader extends Shader{ + public static class MenuShader extends LoadShader{ float time = 0f; public MenuShader(){ @@ -54,21 +43,21 @@ public class Shaders{ public void apply(){ time = time % 158; - shader.setUniformf("u_resolution", Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); - shader.setUniformi("u_time", (int)(time += Gdx.graphics.getDeltaTime() * 60f)); - shader.setUniformf("u_uv", Draw.getBlankRegion().getU(), Draw.getBlankRegion().getV()); - shader.setUniformf("u_scl", Unit.dp.scl(1f)); - shader.setUniformf("u_uv2", Draw.getBlankRegion().getU2(), Draw.getBlankRegion().getV2()); + setUniformf("u_resolution", Core.graphics.getWidth(), Core.graphics.getHeight()); + setUniformi("u_time", (int)(time += Core.graphics.getDeltaTime() * 60f)); + setUniformf("u_uv", Core.atlas.white().getU(), Core.atlas.white().getV()); + setUniformf("u_scl", Unit.dp.scl(1f)); + setUniformf("u_uv2", Core.atlas.white().getU2(), Core.atlas.white().getV2()); } } - public static class FogShader extends Shader{ + public static class FogShader extends LoadShader{ public FogShader(){ super("fog", "default"); } } - public static class MixShader extends Shader{ + public static class MixShader extends LoadShader{ public Color color = new Color(Color.WHITE); public MixShader(){ @@ -78,24 +67,11 @@ public class Shaders{ @Override public void apply(){ super.apply(); - shader.setUniformf("u_color", color); + setUniformf("u_color", color); } } - public static class Space extends SurfaceShader{ - - public Space(){ - super("space2"); - } - - @Override - public void apply(){ - super.apply(); - shader.setUniformf("u_center", world.width() * tilesize / 2f, world.height() * tilesize / 2f); - } - } - - public static class UnitBuild extends Shader{ + public static class UnitBuild extends LoadShader{ public float progress, time; public Color color = new Color(); public TextureRegion region; @@ -106,17 +82,19 @@ public class Shaders{ @Override public void apply(){ - shader.setUniformf("u_time", time); - shader.setUniformf("u_color", color); - shader.setUniformf("u_progress", progress); - shader.setUniformf("u_uv", region.getU(), region.getV()); - shader.setUniformf("u_uv2", region.getU2(), region.getV2()); - shader.setUniformf("u_texsize", region.getTexture().getWidth(), region.getTexture().getHeight()); + setUniformf("u_time", time); + setUniformf("u_color", color); + setUniformf("u_progress", progress); + 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 Outline extends Shader{ + public static class Outline extends LoadShader{ public Color color = new Color(); + public TextureRegion region = new TextureRegion(); + public float scl; public Outline(){ super("outline", "default"); @@ -124,14 +102,33 @@ public class Shaders{ @Override public void apply(){ - shader.setUniformf("u_color", color); - shader.setUniformf("u_texsize", region.getTexture().getWidth(), region.getTexture().getHeight()); + setUniformf("u_color", color); + setUniformf("u_scl", scl); + setUniformf("u_texsize", region.getTexture().getWidth(), region.getTexture().getHeight()); } } - public static class BlockBuild extends Shader{ + public static class Shadow extends LoadShader{ + public Color color = new Color(); + public TextureRegion region = new TextureRegion(); + public float scl; + + public Shadow(){ + super("shadow", "default"); + } + + @Override + public void apply(){ + setUniformf("u_color", color); + setUniformf("u_scl", scl); + setUniformf("u_texsize", region.getTexture().getWidth(), region.getTexture().getHeight()); + } + } + + public static class BlockBuild extends LoadShader{ public Color color = new Color(); public float progress; + public TextureRegion region = new TextureRegion(); public BlockBuild(){ super("blockbuild", "default"); @@ -139,17 +136,18 @@ public class Shaders{ @Override public void apply(){ - shader.setUniformf("u_progress", progress); - shader.setUniformf("u_color", color); - shader.setUniformf("u_uv", region.getU(), region.getV()); - shader.setUniformf("u_uv2", region.getU2(), region.getV2()); - shader.setUniformf("u_time", Timers.time()); - shader.setUniformf("u_texsize", region.getTexture().getWidth(), region.getTexture().getHeight()); + setUniformf("u_progress", progress); + setUniformf("u_color", color); + setUniformf("u_uv", region.getU(), region.getV()); + setUniformf("u_uv2", region.getU2(), region.getV2()); + setUniformf("u_time", Time.time()); + setUniformf("u_texsize", region.getTexture().getWidth(), region.getTexture().getHeight()); } } - public static class BlockPreview extends Shader{ + public static class BlockPreview extends LoadShader{ public Color color = new Color(); + public TextureRegion region = new TextureRegion(); public BlockPreview(){ super("blockpreview", "default"); @@ -157,14 +155,14 @@ public class Shaders{ @Override public void apply(){ - shader.setUniformf("u_color", color); - shader.setUniformf("u_uv", region.getU(), region.getV()); - shader.setUniformf("u_uv2", region.getU2(), region.getV2()); - shader.setUniformf("u_texsize", region.getTexture().getWidth(), region.getTexture().getHeight()); + 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 Shader{ + public static class Shield extends LoadShader{ public Shield(){ super("shield", "default"); @@ -172,30 +170,19 @@ public class Shaders{ @Override public void apply(){ - shader.setUniformf("u_dp", Unit.dp.scl(1f)); - shader.setUniformf("u_time", Timers.time() / Unit.dp.scl(1f)); - shader.setUniformf("u_offset", - Core.camera.position.x - Core.camera.viewportWidth / 2 * Core.camera.zoom, - Core.camera.position.y - Core.camera.viewportHeight / 2 * Core.camera.zoom); - shader.setUniformf("u_texsize", Core.camera.viewportWidth * Core.camera.zoom, - Core.camera.viewportHeight * Core.camera.zoom); + setUniformf("u_dp", Unit.dp.scl(1f)); + setUniformf("u_time", Time.time() / Unit.dp.scl(1f)); + setUniformf("u_offset", + Core.camera.position.x - Core.camera.width / 2 , + Core.camera.position.y - Core.camera.height / 2 ); + setUniformf("u_texsize", Core.camera.width , + Core.camera.height ); } } - - public static class SurfaceShader extends Shader{ - - public SurfaceShader(String frag){ - super(frag, "default"); - } - - @Override - public void apply(){ - shader.setUniformf("camerapos", - Core.camera.position.x - Core.camera.viewportWidth / 2 * Core.camera.zoom, - Core.camera.position.y - Core.camera.viewportHeight / 2 * Core.camera.zoom); - shader.setUniformf("screensize", Core.camera.viewportWidth* Core.camera.zoom, - Core.camera.viewportHeight * Core.camera.zoom); - shader.setUniformf("time", Timers.time()); + + public static class LoadShader extends Shader{ + public LoadShader(String frag, String vert){ + super(Core.files.internal("shaders/" + vert + ".vertex"), Core.files.internal("shaders/" + frag + ".fragment")); } } } diff --git a/core/src/io/anuke/mindustry/graphics/Shapes.java b/core/src/io/anuke/mindustry/graphics/Shapes.java new file mode 100644 index 0000000000..5d87feaefd --- /dev/null +++ b/core/src/io/anuke/mindustry/graphics/Shapes.java @@ -0,0 +1,38 @@ +package io.anuke.mindustry.graphics; + +import io.anuke.arc.Core; +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.math.Mathf; + +//TODO remove +public class Shapes{ + + public static void laser(String line, String edge, float x, float y, float x2, float y2, float scale){ + laser(line, edge, x, y, x2, y2, Mathf.angle(x2 - x, y2 - y), scale); + } + + public static void laser(String line, String edge, float x, float y, float x2, float y2){ + laser(line, edge, x, y, x2, y2, Mathf.angle(x2 - x, y2 - y), 1f); + } + + 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); + + Draw.rect(Core.atlas.find(edge), x2, y2, region.getWidth() * Draw.scl, region.getHeight() * scale * Draw.scl, rotation); + } + + public static void tri(float x, float y, float width, float length, float rotation){ + float oy = 17f / 63f * length; + Draw.rect(Core.atlas.find("shape-3"), x, y - oy + length/2f, width, length, width / 2f, oy, rotation - 90); + } +} diff --git a/core/src/io/anuke/mindustry/graphics/Trail.java b/core/src/io/anuke/mindustry/graphics/Trail.java deleted file mode 100644 index bd34dc7002..0000000000 --- a/core/src/io/anuke/mindustry/graphics/Trail.java +++ /dev/null @@ -1,66 +0,0 @@ -package io.anuke.mindustry.graphics; - -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.FloatArray; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.Mathf; - -/** - * Class that renders a colored trail. - */ -public class Trail{ - private final static float maxJump = 15f; - private final int length; - private final FloatArray points = new FloatArray(); - private float lastX, lastY; - - public Trail(int length){ - this.length = length; - } - - public void update(float curx, float cury){ - if(Vector2.dst(curx, cury, lastX, lastY) >= maxJump){ - points.clear(); - } - - points.add(curx, cury); - - while(points.size > (int)(length * 2 / Math.min(Timers.delta(), 1f))){ - float[] items = points.items; - System.arraycopy(items, 2, items, 0, points.size - 2); - points.size -= 2; - } - - lastX = curx; - lastY = cury; - } - - public void clear(){ - points.clear(); - } - - public void draw(Color color, float stroke){ - Draw.color(color); - - for(int i = 0; i < points.size - 2; i += 2){ - float x = points.get(i); - float y = points.get(i + 1); - float x2 = points.get(i + 2); - float y2 = points.get(i + 3); - float s = Mathf.clamp((float) (i) / points.size); - - Lines.stroke(s * stroke); - Lines.line(x, y, x2, y2); - } - - if(points.size >= 2){ - Fill.circle(points.get(points.size - 2), points.get(points.size - 1), stroke / 2f); - } - - Draw.reset(); - } -} diff --git a/core/src/io/anuke/mindustry/input/Binding.java b/core/src/io/anuke/mindustry/input/Binding.java new file mode 100644 index 0000000000..78049ad0c9 --- /dev/null +++ b/core/src/io/anuke/mindustry/input/Binding.java @@ -0,0 +1,46 @@ +package io.anuke.mindustry.input; + +import io.anuke.arc.Application.ApplicationType; +import io.anuke.arc.Core; +import io.anuke.arc.KeyBinds.Axis; +import io.anuke.arc.KeyBinds.KeyBind; +import io.anuke.arc.KeyBinds.KeybindValue; +import io.anuke.arc.input.InputDevice.DeviceType; +import io.anuke.arc.input.KeyCode; + +public enum Binding implements KeyBind{ + move_x(new Axis(KeyCode.A, KeyCode.D), "general"), + move_y(new Axis(KeyCode.S, KeyCode.W)), + select(KeyCode.MOUSE_LEFT), + 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.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)), + + ; + + private final KeybindValue defaultValue; + private final String category; + + Binding(KeybindValue defaultValue, String category){ this.defaultValue = defaultValue; this.category = category; } + Binding(KeybindValue defaultValue){ this(defaultValue, null); } + + @Override public KeybindValue defaultValue(DeviceType type){ return defaultValue; } + @Override public String category(){ return category; } +} diff --git a/core/src/io/anuke/mindustry/input/CursorType.java b/core/src/io/anuke/mindustry/input/CursorType.java deleted file mode 100644 index fa26e5f0e9..0000000000 --- a/core/src/io/anuke/mindustry/input/CursorType.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.anuke.mindustry.input; - -import io.anuke.ucore.scene.utils.Cursors; - -/** - * Type of cursor for displaying on desktop. - */ -public enum CursorType{ - normal(Cursors::restoreCursor), - hand(Cursors::setHand), - drill(() -> Cursors.set("drill")), - unload(() -> Cursors.set("unload")); - - private final Runnable call; - - CursorType(Runnable call){ - this.call = call; - } - - /** - * Sets the current system cursor to this. - */ - void set(){ - call.run(); - } -} diff --git a/core/src/io/anuke/mindustry/input/DefaultKeybinds.java b/core/src/io/anuke/mindustry/input/DefaultKeybinds.java deleted file mode 100644 index 19639b7466..0000000000 --- a/core/src/io/anuke/mindustry/input/DefaultKeybinds.java +++ /dev/null @@ -1,71 +0,0 @@ -package io.anuke.mindustry.input; - -import com.badlogic.gdx.Application.ApplicationType; -import com.badlogic.gdx.Gdx; -import io.anuke.ucore.core.Inputs.Axis; -import io.anuke.ucore.core.Inputs.DeviceType; -import io.anuke.ucore.core.KeyBinds; -import io.anuke.ucore.core.KeyBinds.Category; -import io.anuke.ucore.input.Input; - -public class DefaultKeybinds{ - - public static void load(){ - String[] sections = {"player_1"}; - - for(String section : sections){ - - KeyBinds.defaultSection(section, DeviceType.keyboard, - new Category("general"), - "move_x", new Axis(Input.A, Input.D), - "move_y", new Axis(Input.S, Input.W), - "select", Input.MOUSE_LEFT, - "deselect", Input.MOUSE_RIGHT, - "break", Input.MOUSE_RIGHT, - "rotate", new Axis(Input.SCROLL), - "dash", Input.SHIFT_LEFT, - "drop_unit", Input.SHIFT_LEFT, - "gridMode", Input.CONTROL_LEFT, - "gridModeShift", Input.SHIFT_LEFT, - new Category("view"), - "zoom_hold", Input.CONTROL_LEFT, - "zoom", new Axis(Input.SCROLL), - "zoom_minimap", new Axis(Input.MINUS, Input.PLUS), - "menu", Gdx.app.getType() == ApplicationType.Android ? Input.BACK : Input.ESCAPE, - "pause", Input.SPACE, - "toggle_menus", Input.C, - "screenshot", Input.P, - new Category("multiplayer"), - "player_list", Input.TAB, - "chat", Input.ENTER, - "chat_history_prev", Input.UP, - "chat_history_next", Input.DOWN, - "chat_scroll", new Axis(Input.SCROLL) - ); - - KeyBinds.defaultSection(section, DeviceType.controller, - new Category("general"), - "move_x", new Axis(Input.CONTROLLER_L_STICK_HORIZONTAL_AXIS), - "move_y", new Axis(Input.CONTROLLER_L_STICK_VERTICAL_AXIS), - "cursor_x", new Axis(Input.CONTROLLER_R_STICK_HORIZONTAL_AXIS), - "cursor_y", new Axis(Input.CONTROLLER_R_STICK_VERTICAL_AXIS), - //"select", Input.CONTROLLER_R_BUMPER, - //"break", Input.CONTROLLER_L_BUMPER, - //"shoot", Input.CONTROLLER_R_TRIGGER, - "dash", Input.CONTROLLER_Y, - "rotate_alt", new Axis(Input.CONTROLLER_DPAD_RIGHT, Input.CONTROLLER_DPAD_LEFT), - "rotate", new Axis(Input.CONTROLLER_A, Input.CONTROLLER_B), - new Category("view"), - "zoom_hold", Input.ANY_KEY, - "zoom", new Axis(Input.CONTROLLER_DPAD_DOWN, Input.CONTROLLER_DPAD_UP), - "menu", Input.CONTROLLER_X, - "pause", Input.CONTROLLER_L_TRIGGER, - new Category("multiplayer"), - "player_list", Input.CONTROLLER_START - ); - - } - - KeyBinds.setSectionAlias("default", "player_1"); - } -} diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index d6881fc58a..2abb278ff9 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -1,37 +1,31 @@ package io.anuke.mindustry.input; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import io.anuke.mindustry.content.blocks.Blocks; +import io.anuke.arc.Core; +import io.anuke.arc.Graphics.Cursor; +import io.anuke.arc.Graphics.Cursor.SystemCursor; +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; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Block.Icon; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.core.Inputs; -import io.anuke.ucore.core.Inputs.DeviceType; -import io.anuke.ucore.core.KeyBinds; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.*; -import static io.anuke.mindustry.input.CursorType.*; 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 CursorType cursorType = normal; + private Cursor cursorType = SystemCursor.arrow; /**Position where the player started dragging a line.*/ private int selectX, selectY; @@ -42,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.*/ @@ -50,45 +43,63 @@ public class DesktopInput extends InputHandler{ if(validPlace(x, y, block, rotation)){ Draw.color(); - TextureRegion[] regions = block.getBlockIcon(); + TextureRegion region = block.icon(Icon.full); - for(TextureRegion region : regions){ - Draw.rect(region, x * tilesize + block.offset(), y * tilesize + block.offset(), - region.getRegionWidth() * selectScale, region.getRegionHeight() * selectScale, block.rotate ? rotation * 90 : 0); + 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); + + 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); } } @Override public boolean isDrawing(){ - return mode != none || recipe != null; + return mode != none || block != null; } @Override public void drawOutlined(){ - int cursorX = tileX(Gdx.input.getX()); - int cursorY = tileY(Gdx.input.getY()); + Lines.stroke(1f); + int cursorX = tileX(Core.input.mouseX()); + int cursorY = tileY(Core.input.mouseY()); //draw selection(s) - if(mode == placing && recipe != null){ + if(mode == placing && block != null){ NormalizeResult result = PlaceUtils.normalizeArea(selectX, selectY, cursorX, cursorY, rotation, true, maxLength); - for(int i = 0; i <= result.getLength(); i += recipe.result.size){ - int x = selectX + i * Mathf.sign(cursorX - selectX) * Mathf.bool(result.isX()); - int y = selectY + i * Mathf.sign(cursorY - selectY) * Mathf.bool(!result.isX()); + for(int i = 0; i <= result.getLength(); i += block.size){ + int x = selectX + i * Mathf.sign(cursorX - selectX) * Mathf.num(result.isX()); + int y = selectY + i * Mathf.sign(cursorY - selectY) * Mathf.num(!result.isX()); - if(i + recipe.result.size > result.getLength() && recipe.result.rotate){ - Draw.color(!validPlace(x, y, recipe.result, result.rotation) ? Palette.remove : Palette.placeRotate); - Draw.grect("place-arrow", x * tilesize + recipe.result.offset(), - y * tilesize + recipe.result.offset(), result.rotation * 90 - 90); + if(i + block.size > result.getLength() && block.rotate){ + 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) ? 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, result.rotation * 90 - 90); } - drawPlace(x, y, recipe.result, result.rotation); + drawPlace(x, y, block, result.rotation); } Draw.reset(); @@ -102,25 +113,35 @@ 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(recipe.result.rotate){ - Draw.color(!validPlace(cursorX, cursorY, recipe.result, rotation) ? Palette.remove : Palette.placeRotate); - Draw.grect("place-arrow", cursorX * tilesize + recipe.result.offset(), - cursorY * tilesize + recipe.result.offset(), rotation * 90 - 90); + if(block.rotate){ + 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) ? Pal.remove : Pal.accent); + Draw.rect(Core.atlas.find("place-arrow"), + cursorX * tilesize + block.offset(), + cursorY * tilesize + block.offset(), + Core.atlas.find("place-arrow").getWidth() * Draw.scl, + Core.atlas.find("place-arrow").getHeight() * Draw.scl, rotation * 90 - 90); } - drawPlace(cursorX, cursorY, recipe.result, rotation); - recipe.result.drawPlace(cursorX, cursorY, rotation, validPlace(cursorX, cursorY, recipe.result, rotation)); + drawPlace(cursorX, cursorY, block, rotation); + block.drawPlace(cursorX, cursorY, rotation, validPlace(cursorX, cursorY, block, rotation)); } Draw.reset(); @@ -128,24 +149,22 @@ public class DesktopInput extends InputHandler{ @Override public void update(){ - if(Net.active() && Inputs.keyTap("player_list")){ + if(Net.active() && Core.input.keyTap(Binding.player_list)){ ui.listfrag.toggle(); } - if(Inputs.keyRelease(section, "select")){ + if(Core.input.keyRelease(Binding.select)){ player.isShooting = false; } - if(state.is(State.menu) || ui.hasDialog()) return; - - boolean controller = KeyBinds.getSection(section).device.type == DeviceType.controller; + if(state.is(State.menu) || Core.scene.hasDialog()) return; //zoom and rotate things - if(Inputs.getAxisActive("zoom") && (Inputs.keyDown(section, "zoom_hold") || controller)){ - renderer.scaleCamera((int) Inputs.getAxisTapped(section, "zoom")); + if(Math.abs(Core.input.axisTap(Binding.zoom)) > 0 && (Core.input.keyDown(Binding.zoom_hold))){ + renderer.scaleCamera(Core.input.axisTap(Binding.zoom)); } - renderer.minimap.zoomBy(-(int) Inputs.getAxisTapped(section, "zoom_minimap")); + renderer.minimap.zoomBy(-Core.input.axisTap(Binding.zoom_minimap)); if(player.isDead()) return; @@ -161,90 +180,90 @@ public class DesktopInput extends InputHandler{ } if(isPlacing()){ - cursorType = hand; + cursorType = SystemCursor.hand; selectScale = Mathf.lerpDelta(selectScale, 1f, 0.2f); }else{ selectScale = 0f; } - rotation = Mathf.mod(rotation + (int) Inputs.getAxisTapped(section, "rotate"), 4); + rotation = Mathf.mod(rotation + (int) Core.input.axisTap(Binding.rotate), 4); - Tile cursor = tileAt(Gdx.input.getX(), Gdx.input.getY()); + Tile cursor = tileAt(Core.input.mouseX(), Core.input.mouseY()); if(player.isDead()){ - cursorType = normal; + cursorType = SystemCursor.arrow; }else if(cursor != null){ cursor = cursor.target(); cursorType = cursor.block().getCursor(cursor); if(isPlacing()){ - cursorType = hand; + cursorType = SystemCursor.hand; } if(!isPlacing() && canMine(cursor)){ - cursorType = drill; + cursorType = ui.drillCursor; } - if(canTapPlayer(Graphics.mouseWorld().x, Graphics.mouseWorld().y)){ - cursorType = unload; + if(canTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y)){ + cursorType = ui.unloadCursor; } } - if(!ui.hasMouse()){ - cursorType.set(); + if(!Core.scene.hasMouse()){ + Core.graphics.cursor(cursorType); } - cursorType = normal; + cursorType = SystemCursor.arrow; } void pollInput(){ - Tile selected = tileAt(Gdx.input.getX(), Gdx.input.getY()); - int cursorX = tileX(Gdx.input.getX()); - int cursorY = tileY(Gdx.input.getY()); + Tile selected = tileAt(Core.input.mouseX(), Core.input.mouseY()); + int cursorX = tileX(Core.input.mouseX()); + int cursorY = tileY(Core.input.mouseY()); - if(Inputs.keyTap(section, "deselect")){ + if(Core.input.keyTap(Binding.deselect)){ player.setMineTile(null); } - if(Inputs.keyTap(section, "select") && !ui.hasMouse()){ + if(Core.input.keyTap(Binding.select) && !Core.scene.hasMouse()){ if(isPlacing()){ selectX = cursorX; selectY = cursorY; mode = placing; }else if(selected != null){ //only begin shooting if there's no cursor event - if (!tileTapped(selected) && !tryTapPlayer(Graphics.mouseWorld().x, Graphics.mouseWorld().y) && player.getPlaceQueue().size == 0 && !droppingItem && + if (!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && player.getPlaceQueue().size == 0 && !droppingItem && !tryBeginMine(selected) && player.getMineTile() == null && !ui.chatfrag.chatOpen()) { player.isShooting = true; } }else if(!ui.chatfrag.chatOpen()){ //if it's out of bounds, shooting is just fine player.isShooting = true; } - }else if(Inputs.keyTap(section, "deselect") && (recipe != null || mode != none || player.isBuilding()) && - !(player.getCurrentRequest() != null && player.getCurrentRequest().breaking && KeyBinds.get(section, "deselect") == KeyBinds.get(section, "break"))){ - if(recipe == null){ + }else if(Core.input.keyTap(Binding.deselect) && (block != null || mode != none || player.isBuilding()) && + !(player.getCurrentRequest() != null && player.getCurrentRequest().breaking && Core.keybinds.get(Binding.deselect) == Core.keybinds.get(Binding.break_block))){ + if(block == null){ player.clearBuilding(); } - recipe = null; + block = null; mode = none; - }else if(Inputs.keyTap(section, "break") && !ui.hasMouse()){ + }else if(Core.input.keyTap(Binding.break_block) && !Core.scene.hasMouse()){ //is recalculated because setting the mode to breaking removes potential multiblock cursor offset mode = breaking; - selectX = tileX(Gdx.input.getX()); - selectY = tileY(Gdx.input.getY()); + selectX = tileX(Core.input.mouseX()); + selectY = tileY(Core.input.mouseY()); } - if(Inputs.keyRelease(section, "break") || Inputs.keyRelease(section, "select")){ + if(Core.input.keyRelease(Binding.break_block) || Core.input.keyRelease(Binding.select)){ - if(mode == placing){ //touch up while placing, place everything in selection + if(mode == placing && block != null){ //touch up while placing, place everything in selection NormalizeResult result = PlaceUtils.normalizeArea(selectX, selectY, cursorX, cursorY, rotation, true, maxLength); - for(int i = 0; i <= result.getLength(); i += recipe.result.size){ - int x = selectX + i * Mathf.sign(cursorX - selectX) * Mathf.bool(result.isX()); - int y = selectY + i * Mathf.sign(cursorY - selectY) * Mathf.bool(!result.isX()); + for(int i = 0; i <= result.getLength(); i += block.size){ + int x = selectX + i * Mathf.sign(cursorX - selectX) * Mathf.num(result.isX()); + int y = selectY + i * Mathf.sign(cursorY - selectY) * Mathf.num(!result.isX()); rotation = result.rotation; @@ -263,7 +282,7 @@ public class DesktopInput extends InputHandler{ } if(selected != null){ - tryDropItems(selected.target(), Graphics.mouseWorld().x, Graphics.mouseWorld().y); + tryDropItems(selected.target(), Core.input.mouseWorld().x, Core.input.mouseWorld().y); } mode = none; @@ -278,61 +297,20 @@ public class DesktopInput extends InputHandler{ @Override public float getMouseX(){ - return !controlling ? Gdx.input.getX() : controlx; + return Core.input.mouseX(); } @Override public float getMouseY(){ - return !controlling ? Gdx.input.getY() : controly; - } - - @Override - public boolean isCursorVisible(){ - return controlling; + return Core.input.mouseY(); } @Override public void updateController(){ - //TODO no controller support - //TODO move controller input to new class, ControllerInput - boolean mousemove = Gdx.input.getDeltaX() > 1 || Gdx.input.getDeltaY() > 1; if(state.is(State.menu)){ droppingItem = false; } - - if(KeyBinds.getSection(section).device.type == DeviceType.controller && (!mousemove || player.playerIndex > 0)){ - if(player.playerIndex > 0){ - controlling = true; - } - - float xa = Inputs.getAxis(section, "cursor_x"); - float ya = Inputs.getAxis(section, "cursor_y"); - - if(Math.abs(xa) > controllerMin || Math.abs(ya) > controllerMin){ - float scl = Settings.getInt("sensitivity", 100) / 100f * Unit.dp.scl(1f); - controlx += xa * baseControllerSpeed * scl; - controly -= ya * baseControllerSpeed * scl; - controlling = true; - - if(player.playerIndex == 0){ - Gdx.input.setCursorCatched(true); - } - - Inputs.getProcessor().touchDragged((int) getMouseX(), (int) getMouseY(), player.playerIndex); - } - - controlx = Mathf.clamp(controlx, 0, Gdx.graphics.getWidth()); - controly = Mathf.clamp(controly, 0, Gdx.graphics.getHeight()); - }else{ - controlling = false; - Gdx.input.setCursorCatched(false); - } - - if(!controlling){ - controlx = Gdx.input.getX(); - controly = Gdx.input.getY(); - } } } diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index ac8007737c..c9551a5a5d 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -1,118 +1,111 @@ package io.anuke.mindustry.input; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.InputAdapter; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.Vector2; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.content.fx.EnvironmentFx; -import io.anuke.mindustry.entities.Player; +import io.anuke.arc.Core; +import io.anuke.mindustry.entities.Effects; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.input.InputProcessor; +import io.anuke.arc.math.Angles; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Vector2; +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.type.Player; import io.anuke.mindustry.entities.effect.ItemTransfer; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; +import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.ValidateException; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.ui.fragments.OverlayFragment; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Build; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.core.Inputs; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Translator; import static io.anuke.mindustry.Vars.*; -public abstract class InputHandler extends InputAdapter{ +public abstract class InputHandler implements InputProcessor{ /**Used for dropping items.*/ final static float playerSelectRange = mobile ? 17f : 11f; /**Maximum line length.*/ final static int maxLength = 100; - final static Translator stackTrns = new Translator(); + final static Vector2 stackTrns = new Vector2(); /**Distance on the back from where items originate.*/ final static float backTrns = 3f; public final Player player; - public final String section; public final OverlayFragment frag = new OverlayFragment(this); - public Recipe recipe; + public Block block; public int rotation; public boolean droppingItem; public InputHandler(Player player){ this.player = player; - this.section = "player_" + (player.playerIndex + 1); } //methods to override @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(EnvironmentFx.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."); } - threads.run(() -> { - if(player == null || tile.entity == null) return; + if(player == null || tile.entity == null) return; - player.isTransferring = true; + player.isTransferring = true; - Item item = player.inventory.getItem().item; - int amount = player.inventory.getItem().amount; - int accepted = tile.block().acceptStack(item, amount, tile, player); - player.inventory.getItem().amount -= accepted; + Item item = player.item().item; + int amount = player.item().amount; + int accepted = tile.block().acceptStack(item, amount, tile, player); + player.item().amount -= accepted; - int sent = Mathf.clamp(accepted / 4, 1, 8); - int removed = accepted / sent; - int[] remaining = {accepted, accepted}; - Block block = tile.block(); + int sent = Mathf.clamp(accepted / 4, 1, 8); + int removed = accepted / sent; + int[] remaining = {accepted, accepted}; + Block block = tile.block(); - for(int i = 0; i < sent; i++){ - boolean end = i == sent - 1; - Timers.run(i * 3, () -> { - tile.block().getStackOffset(item, tile, stackTrns); + for(int i = 0; i < sent; i++){ + boolean end = i == sent - 1; + Time.run(i * 3, () -> { + tile.block().getStackOffset(item, tile, stackTrns); - ItemTransfer.create(item, - player.x + Angles.trnsx(player.rotation + 180f, backTrns), player.y + Angles.trnsy(player.rotation + 180f, backTrns), - new Translator(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> { - if(tile.block() != block || tile.entity == null || tile.entity.items == null) return; + ItemTransfer.create(item, + player.x + Angles.trnsx(player.rotation + 180f, backTrns), player.y + Angles.trnsy(player.rotation + 180f, backTrns), + new Vector2(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> { + if(tile.block() != block || tile.entity == null || tile.entity.items == null) return; - tile.block().handleStack(item, removed, tile, player); - remaining[1] -= removed; + tile.block().handleStack(item, removed, tile, player); + remaining[1] -= removed; - if(end && remaining[1] > 0){ - tile.block().handleStack(item, remaining[1], tile, player); - } - }); + if(end && remaining[1] > 0){ + tile.block().handleStack(item, remaining[1], tile, player); + } + }); - remaining[0] -= removed; + remaining[0] -= removed; - if(end){ - player.isTransferring = false; - } - }); - } - }); + if(end){ + player.isTransferring = false; + } + }); + } } @Remote(targets = Loc.both, called = Loc.server, forward = true) @@ -130,19 +123,11 @@ public abstract class InputHandler extends InputAdapter{ } public float getMouseX(){ - return Gdx.input.getX(); + return Core.input.mouseX(); } public float getMouseY(){ - return Gdx.input.getY(); - } - - public void resetCursor(){ - - } - - public boolean isCursorVisible(){ - return false; + return Core.input.mouseY(); } public void buildUI(Table table){ @@ -169,7 +154,7 @@ public abstract class InputHandler extends InputAdapter{ boolean tileTapped(Tile tile){ tile = tile.target(); - boolean consumed = false, showedInventory = false, showedConsume = false; + boolean consumed = false, showedInventory = false; //check if tapped block is configurable if(tile.block().configurable && tile.getTeam() == player.getTeam()){ @@ -200,7 +185,7 @@ public abstract class InputHandler extends InputAdapter{ //consume tap event if necessary if(tile.getTeam() == player.getTeam() && tile.block().consumesTap){ consumed = true; - }else if(tile.getTeam() == player.getTeam() && tile.block().synthetic() && !consumed){ + }else if((tile.getTeam() == player.getTeam() || tile.getTeam() == Team.none) && tile.block().synthetic() && !consumed){ if(tile.block().hasItems && tile.entity.items.total() > 0){ frag.inv.showFor(tile); consumed = true; @@ -214,7 +199,7 @@ public abstract class InputHandler extends InputAdapter{ if(!consumed && player.isBuilding()){ player.clearBuilding(); - recipe = null; + block = null; return true; } @@ -231,7 +216,7 @@ public abstract class InputHandler extends InputAdapter{ } boolean canTapPlayer(float x, float y){ - return Vector2.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.*/ @@ -245,11 +230,11 @@ public abstract class InputHandler extends InputAdapter{ } boolean canMine(Tile tile){ - return !ui.hasMouse() - && tile.floor().drops != null && tile.floor().drops.item.hardness <= player.mech.drillPower + return !Core.scene.hasMouse() + && tile.floor().itemDrop != null && tile.floor().itemDrop.hardness <= player.mech.drillPower && !tile.floor().playerUnmineable - && player.inventory.canAcceptItem(tile.floor().drops.item) - && tile.block() == Blocks.air && player.distanceTo(tile.worldx(), tile.worldy()) <= Player.mineDistance; + && player.acceptsItem(tile.floor().itemDrop) + && tile.block() == Blocks.air && player.dst(tile.worldx(), tile.worldy()) <= Player.mineDistance; } /**Returns the tile at the specified MOUSE coordinates.*/ @@ -258,17 +243,17 @@ public abstract class InputHandler extends InputAdapter{ } int tileX(float cursorX){ - Vector2 vec = Graphics.world(cursorX, 0); + Vector2 vec = Core.input.mouseWorld(cursorX, 0); if(selectedBlock()){ - vec.sub(recipe.result.offset(), recipe.result.offset()); + vec.sub(block.offset(), block.offset()); } return world.toTile(vec.x); } int tileY(float cursorY){ - Vector2 vec = Graphics.world(0, cursorY); + Vector2 vec = Core.input.mouseWorld(0, cursorY); if(selectedBlock()){ - vec.sub(recipe.result.offset(), recipe.result.offset()); + vec.sub(block.offset(), block.offset()); } return world.toTile(vec.y); } @@ -278,20 +263,20 @@ public abstract class InputHandler extends InputAdapter{ } public boolean isPlacing(){ - return recipe != null; + return block != null; } public float mouseAngle(float x, float y){ - return Graphics.world(getMouseX(), getMouseY()).sub(x, y).angle(); + return Core.input.mouseWorld(getMouseX(), getMouseY()).sub(x, y).angle(); } public void remove(){ - Inputs.removeProcessor(this); + Core.input.removeProcessor(this); frag.remove(); } public boolean canShoot(){ - return recipe == null && !ui.hasMouse() && !onConfigurable() && !isDroppingItem(); + return block == null && !Core.scene.hasMouse() && !onConfigurable() && !isDroppingItem(); } public boolean onConfigurable(){ @@ -303,14 +288,14 @@ public abstract class InputHandler extends InputAdapter{ } 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)){ 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){ Call.transferInventory(player, tile); @@ -324,8 +309,8 @@ public abstract class InputHandler extends InputAdapter{ } public void tryPlaceBlock(int x, int y){ - if(recipe != null && validPlace(x, y, recipe.result, rotation) && cursorNear()){ - placeBlock(x, y, recipe, rotation); + if(block != null && validPlace(x, y, block, rotation) && cursorNear()){ + placeBlock(x, y, block, rotation); } } @@ -336,22 +321,16 @@ public abstract class InputHandler extends InputAdapter{ } public boolean validPlace(int x, int y, Block type, int rotation){ - for(Tile tile : state.teams.get(player.getTeam()).cores){ - if(tile.distanceTo(x * tilesize, y * tilesize) < coreBuildRange){ - return Build.validPlace(player.getTeam(), x, y, type, rotation) && - Vector2.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance; - } - } - - return false; + return Build.validPlace(player.getTeam(), x, y, type, rotation) && + Mathf.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance; } public boolean validBreak(int x, int y){ - return Build.validBreak(player.getTeam(), x, y) && Vector2.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance; + return Build.validBreak(player.getTeam(), x, y) && Mathf.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance; } - public void placeBlock(int x, int y, Recipe recipe, int rotation){ - player.addBuildRequest(new BuildRequest(x, y, rotation, recipe)); + public void placeBlock(int x, int y, Block block, int rotation){ + player.addBuildRequest(new BuildRequest(x, y, rotation, block)); } public void breakBlock(int x, int y){ diff --git a/core/src/io/anuke/mindustry/input/MobileInput.java b/core/src/io/anuke/mindustry/input/MobileInput.java index f4272a40cb..b6f7467520 100644 --- a/core/src/io/anuke/mindustry/input/MobileInput.java +++ b/core/src/io/anuke/mindustry/input/MobileInput.java @@ -1,37 +1,41 @@ package io.anuke.mindustry.input; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.input.GestureDetector; -import com.badlogic.gdx.input.GestureDetector.GestureListener; -import com.badlogic.gdx.math.Interpolation; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Align; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.ObjectSet; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.content.fx.Fx; +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.graphics.g2d.TextureRegion; +import io.anuke.arc.input.GestureDetector; +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.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.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.graphics.Shaders; import io.anuke.mindustry.input.PlaceUtils.NormalizeDrawResult; import io.anuke.mindustry.input.PlaceUtils.NormalizeResult; -import io.anuke.mindustry.type.Recipe; 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.Tile; -import io.anuke.ucore.core.*; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.input.PlaceMode.*; @@ -41,12 +45,12 @@ public class MobileInput extends InputHandler implements GestureListener{ private static final float maxPanSpeed = 1.3f; private static Rectangle r1 = new Rectangle(), r2 = new Rectangle(); /** Distance to edge of screen to start panning. */ - private final float edgePan = io.anuke.ucore.scene.ui.layout.Unit.dp.scl(60f); + private final float edgePan = io.anuke.arc.scene.ui.layout.Unit.dp.scl(60f); //gesture data private Vector2 vector = new Vector2(); + private float lastDistance = -1f; private boolean canPan; - private boolean zoomed = false; /** Set of completed guides. */ private ObjectSet guides = new ObjectSet<>(); @@ -70,13 +74,13 @@ public class MobileInput extends InputHandler implements GestureListener{ /** Current place mode. */ private PlaceMode mode = none; /** Whether no recipe was available when switching to break mode. */ - private Recipe lastRecipe; + private Block lastBlock; /** Last placed request. Used for drawing block overlay. */ private PlaceRequest lastPlaced; public MobileInput(Player player){ super(player); - Inputs.addProcessor(new GestureDetector(20, 0.5f, 0.4f, 0.15f, this)); + Core.input.addProcessor(new GestureDetector(20, 0.5f, 0.4f, 0.15f, this)); } //region utility methods @@ -118,8 +122,8 @@ public class MobileInput extends InputHandler implements GestureListener{ if(other == null || req.remove) continue; - r1.setSize(req.recipe.result.size * tilesize); - r1.setCenter(other.worldx() + req.recipe.result.offset(), other.worldy() + req.recipe.result.offset()); + r1.setSize(req.block.size * tilesize); + r1.setCenter(other.worldx() + req.block.offset(), other.worldy() + req.block.offset()); if(r2.overlaps(r1)){ return true; @@ -139,8 +143,8 @@ public class MobileInput extends InputHandler implements GestureListener{ if(other == null) continue; if(!req.remove){ - r1.setSize(req.recipe.result.size * tilesize); - r1.setCenter(other.worldx() + req.recipe.result.offset(), other.worldy() + req.recipe.result.offset()); + r1.setSize(req.block.size * tilesize); + r1.setCenter(other.worldx() + req.block.offset(), other.worldy() + req.block.offset()); if(r2.overlaps(r1)){ return req; @@ -168,38 +172,47 @@ public class MobileInput extends InputHandler implements GestureListener{ if(!request.remove){ //draw placing request - float offset = request.recipe.result.offset(); - TextureRegion[] regions = request.recipe.result.getBlockIcon(); + 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.tint(Color.WHITE, Pal.breakInvalid, request.redness); - for(TextureRegion region : regions){ - Draw.rect(region, tile.worldx() + offset, tile.worldy() + offset, - region.getRegionWidth() * request.scale, region.getRegionHeight() * request.scale, - request.recipe.result.rotate ? request.rotation * 90 : 0); + 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.alpha(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 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); } } void showGuide(String type){ - if(!guides.contains(type) && !Settings.getBool(type, false)){ - FloatingDialog dialog = new FloatingDialog("$text." + type + ".title"); + if(!guides.contains(type) && !Core.settings.getBool(type, false)){ + FloatingDialog dialog = new FloatingDialog("$" + type + ".title"); dialog.addCloseButton(); - dialog.content().left(); - dialog.content().add("$text." + type).growX().wrap(); - dialog.content().row(); - dialog.content().addCheck("$text.showagain", false, checked -> { - Settings.putBool(type, checked); - Settings.save(); + dialog.cont.left(); + dialog.cont.add("$" + type).growX().wrap(); + dialog.cont.row(); + dialog.cont.addCheck("$showagain", false, checked -> { + Core.settings.put(type, checked); + Core.settings.save(); }).growX().left().get().left(); dialog.show(); guides.add(type); @@ -212,13 +225,13 @@ public class MobileInput extends InputHandler implements GestureListener{ @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); table.addImageButton("icon-break", "clear-toggle-partial", 16 * 2f, () -> { - mode = mode == breaking ? recipe == null ? none : placing : breaking; - lastRecipe = recipe; + mode = mode == breaking ? block == null ? none : placing : breaking; + lastBlock = block; if(mode == breaking){ showGuide("deconstruction"); } @@ -228,13 +241,13 @@ public class MobileInput extends InputHandler implements GestureListener{ table.addImageButton("icon-cancel", "clear-partial", 16 * 2f, () -> { player.clearBuilding(); mode = none; - recipe = null; - }).visible(() -> player.isBuilding() || recipe != null || mode == breaking); + block = null; + }).visible(() -> player.isBuilding() || block != null || mode == breaking); //rotate button table.addImageButton("icon-arrow", "clear-partial", 16 * 2f, () -> rotation = Mathf.mod(rotation + 1, 4)) .update(i -> i.getImage().setRotationOrigin(rotation * 90, Align.center)) - .visible(() -> recipe != null && recipe.result.rotate); + .visible(() -> block != null && block.rotate); //confirm button table.addImageButton("icon-check", "clear-partial", 16 * 2f, () -> { @@ -245,10 +258,10 @@ public class MobileInput extends InputHandler implements GestureListener{ if(tile != null){ if(!request.remove){ rotation = request.rotation; - Recipe before = recipe; - recipe = request.recipe; + Block before = block; + block = request.block; tryPlaceBlock(tile.x, tile.y); - recipe = before; + block = before; }else{ tryBreakBlock(tile.x, tile.y); } @@ -276,8 +289,8 @@ public class MobileInput extends InputHandler implements GestureListener{ public void drawOutlined(){ Lines.stroke(1f); - Shaders.mix.color.set(Palette.accent); - Graphics.shader(Shaders.mix); + Shaders.mix.color.set(Pal.accent); + Draw.shader(Shaders.mix); //draw removals for(PlaceRequest request : removals){ @@ -297,7 +310,7 @@ public class MobileInput extends InputHandler implements GestureListener{ if(tile == null) continue; - if((!request.remove && validPlace(tile.x, tile.y, request.recipe.result, request.rotation)) + if((!request.remove && validPlace(tile.x, tile.y, request.block, request.rotation)) || (request.remove && validBreak(tile.x, tile.y))){ request.scale = Mathf.lerpDelta(request.scale, 1f, 0.2f); request.redness = Mathf.lerpDelta(request.redness, 0f, 0.2f); @@ -310,47 +323,55 @@ public class MobileInput extends InputHandler implements GestureListener{ drawRequest(request); //draw last placed request - if(!request.remove && request == lastPlaced && request.recipe != null){ - request.recipe.result.drawPlace(tile.x, tile.y, rotation, validPlace(tile.x, tile.y, request.recipe.result, rotation)); + if(!request.remove && request == lastPlaced && request.block != null){ + request.block.drawPlace(tile.x, tile.y, rotation, validPlace(tile.x, tile.y, request.block, rotation)); } } - Graphics.shader(); + Draw.shader(); - Draw.color(Palette.accent); + Draw.color(Pal.accent); //Draw lines if(lineMode){ - int tileX = tileX(Gdx.input.getX()); - int tileY = tileY(Gdx.input.getY()); + int tileX = tileX(Core.input.mouseX()); + int tileY = tileY(Core.input.mouseY()); //draw placing - if(mode == placing && recipe != null){ - NormalizeDrawResult dresult = PlaceUtils.normalizeDrawArea(recipe.result, lineStartX, lineStartY, tileX, tileY, true, maxLength, lineScale); + 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); //go through each cell and draw the block to place if valid - for(int i = 0; i <= result.getLength(); i += recipe.result.size){ - int x = lineStartX + i * Mathf.sign(tileX - lineStartX) * Mathf.bool(result.isX()); - int y = lineStartY + i * Mathf.sign(tileY - lineStartY) * Mathf.bool(!result.isX()); + for(int i = 0; i <= result.getLength(); i += block.size){ + int x = lineStartX + i * Mathf.sign(tileX - lineStartX) * Mathf.num(result.isX()); + int y = lineStartY + i * Mathf.sign(tileY - lineStartY) * Mathf.num(!result.isX()); - if(!checkOverlapPlacement(x, y, recipe.result) && validPlace(x, y, recipe.result, result.rotation)){ + if(!checkOverlapPlacement(x, y, block) && validPlace(x, y, block, result.rotation)){ Draw.color(); - TextureRegion[] regions = recipe.result.getBlockIcon(); + TextureRegion region = block.icon(Icon.full); - for(TextureRegion region : regions){ - Draw.rect(region, x * tilesize + recipe.result.offset(), y * tilesize + recipe.result.offset(), - region.getRegionWidth() * lineScale, region.getRegionHeight() * lineScale, recipe.result.rotate ? result.rotation * 90 : 0); + Draw.rect(region, x * tilesize + block.offset(), y * tilesize + block.offset(), + 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); - Lines.square(x * tilesize + recipe.result.offset(), y * tilesize + recipe.result.offset() - 1, recipe.result.size * tilesize / 2f); - Draw.color(Palette.remove); - Lines.square(x * tilesize + recipe.result.offset(), y * tilesize + recipe.result.offset(), recipe.result.size * tilesize / 2f); + Draw.color(Pal.removeBack); + Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset() - 1, block.size * tilesize / 2f); + Draw.color(Pal.remove); + Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset(), block.size * tilesize / 2f); } } @@ -365,16 +386,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); } @@ -392,13 +413,13 @@ 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); - Lines.poly(target.getX(), target.getY(), 4, 7f * radius, Timers.time() * 1.5f); - Lines.spikes(target.getX(), target.getY(), 3f * radius, 6f * radius, 4, Timers.time() * 1.5f); + Lines.poly(target.getX(), target.getY(), 4, 7f * radius, Time.time() * 1.5f); + Lines.spikes(target.getX(), target.getY(), 3f * radius, 6f * radius, 4, Time.time() * 1.5f); } Draw.reset(); @@ -409,16 +430,16 @@ public class MobileInput extends InputHandler implements GestureListener{ //region input events @Override - public boolean touchDown(int screenX, int screenY, int pointer, int button){ + public boolean touchDown(int screenX, int screenY, int pointer, KeyCode button){ if(state.is(State.menu) || player.isDead()) return false; //get tile on cursor Tile cursor = tileAt(screenX, screenY); - float worldx = Graphics.world(screenX, screenY).x, worldy = Graphics.world(screenX, screenY).y; + float worldx = Core.input.mouseWorld(screenX, screenY).x, worldy = Core.input.mouseWorld(screenX, screenY).y; //ignore off-screen taps - if(cursor == null || ui.hasMouse(screenX, screenY)) return false; + if(cursor == null || Core.scene.hasMouse(screenX, screenY)) return false; //only begin selecting if the tapped block is a request selecting = hasRequest(cursor) && isPlacing() && mode == placing; @@ -432,14 +453,14 @@ public class MobileInput extends InputHandler implements GestureListener{ } @Override - public boolean touchUp(int screenX, int screenY, int pointer, int button){ + public boolean touchUp(int screenX, int screenY, int pointer, KeyCode button){ //place down a line if in line mode if(lineMode){ int tileX = tileX(screenX); int tileY = tileY(screenY); - if(mode == placing && recipe != null){ + if(mode == placing && block != null){ //normalize area NormalizeResult result = PlaceUtils.normalizeArea(lineStartX, lineStartY, tileX, tileY, rotation, true, 100); @@ -447,12 +468,12 @@ public class MobileInput extends InputHandler implements GestureListener{ rotation = result.rotation; //place blocks on line - for(int i = 0; i <= result.getLength(); i += recipe.result.size){ - int x = lineStartX + i * Mathf.sign(tileX - lineStartX) * Mathf.bool(result.isX()); - int y = lineStartY + i * Mathf.sign(tileY - lineStartY) * Mathf.bool(!result.isX()); + for(int i = 0; i <= result.getLength(); i += block.size){ + int x = lineStartX + i * Mathf.sign(tileX - lineStartX) * Mathf.num(result.isX()); + int y = lineStartY + i * Mathf.sign(tileY - lineStartY) * Mathf.num(!result.isX()); - if(!checkOverlapPlacement(x, y, recipe.result) && validPlace(x, y, recipe.result, result.rotation)){ - PlaceRequest request = new PlaceRequest(x * tilesize + recipe.result.offset(), y * tilesize + recipe.result.offset(), recipe, result.rotation); + if(!checkOverlapPlacement(x, y, block) && validPlace(x, y, block, result.rotation)){ + PlaceRequest request = new PlaceRequest(x * tilesize + block.offset(), y * tilesize + block.offset(), block, result.rotation); request.scale = 1f; selection.add(request); } @@ -492,7 +513,7 @@ public class MobileInput extends InputHandler implements GestureListener{ if(tile == null) return false; - tryDropItems(tile.target(), Graphics.world(screenX, screenY).x, Graphics.world(screenX, screenY).y); + tryDropItems(tile.target(), Core.input.mouseWorld(screenX, screenY).x, Core.input.mouseWorld(screenX, screenY).y); } return false; } @@ -505,7 +526,7 @@ public class MobileInput extends InputHandler implements GestureListener{ Tile cursor = tileAt(x, y); //ignore off-screen taps - if(cursor == null || ui.hasMouse(x, y)) return false; + if(cursor == null || Core.scene.hasMouse(x, y)) return false; //remove request if it's there //long pressing enables line mode otherwise @@ -515,58 +536,39 @@ public class MobileInput extends InputHandler implements GestureListener{ if(mode == breaking){ Effects.effect(Fx.tapBlock, cursor.worldx(), cursor.worldy(), 1f); - }else if(recipe != null){ - Effects.effect(Fx.tapBlock, cursor.worldx() + recipe.result.offset(), cursor.worldy() + recipe.result.offset(), recipe.result.size); + }else if(block != null){ + Effects.effect(Fx.tapBlock, cursor.worldx() + block.offset(), cursor.worldy() + block.offset(), block.size); } return false; } @Override - public boolean tap(float x, float y, int count, int button){ + public boolean tap(float x, float y, int count, KeyCode button){ if(state.is(State.menu) || lineMode) return false; - float worldx = Graphics.world(x, y).x, worldy = Graphics.world(x, y).y; + float worldx = Core.input.mouseWorld(x, y).x, worldy = Core.input.mouseWorld(x, y).y; //get tile on cursor Tile cursor = tileAt(x, y); //ignore off-screen taps - if(cursor == null || ui.hasMouse(x, y)) return false; + if(cursor == null || Core.scene.hasMouse(x, y)) return false; checkTargets(worldx, worldy); //remove if request present if(hasRequest(cursor)){ removeRequest(getRequest(cursor)); - }else if(mode == placing && isPlacing() && validPlace(cursor.x, cursor.y, recipe.result, rotation) && !checkOverlapPlacement(cursor.x, cursor.y, recipe.result)){ + }else if(mode == placing && isPlacing() && validPlace(cursor.x, cursor.y, block, rotation) && !checkOverlapPlacement(cursor.x, cursor.y, block)){ //add to selection queue if it's a valid place position - selection.add(lastPlaced = new PlaceRequest(cursor.worldx() + recipe.result.offset(), cursor.worldy() + recipe.result.offset(), recipe, rotation)); + selection.add(lastPlaced = new PlaceRequest(cursor.worldx() + block.offset(), cursor.worldy() + block.offset(), block, rotation)); }else if(mode == breaking && validBreak(cursor.target().x, cursor.target().y) && !hasRequest(cursor.target())){ //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(), Graphics.world(x, y).x, Graphics.world(x, y).y, 4f, u -> !u.isFlying() && u.getMass() <= 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; @@ -588,35 +590,35 @@ public class MobileInput extends InputHandler implements GestureListener{ selection.clear(); } - if(lineMode && mode == placing && recipe == null){ + if(lineMode && mode == placing && block == null){ lineMode = false; } //if there is no mode and there's a recipe, switch to placing - if(recipe != null && mode == none){ + if(block != null && mode == none){ mode = placing; } - if(recipe != null){ + if(block != null){ showGuide("construction"); } - if(recipe == null && mode == placing){ + if(block == null && mode == placing){ mode = none; } //automatically switch to placing after a new recipe is selected - if(lastRecipe != recipe && mode == breaking && recipe != null){ + if(lastBlock != block && mode == breaking && block != null){ mode = placing; - lastRecipe = recipe; + lastBlock = block; } if(lineMode){ lineScale = Mathf.lerpDelta(lineScale, 1f, 0.1f); //When in line mode, pan when near screen edges automatically - if(Gdx.input.isTouched(0) && lineMode){ - float screenX = Graphics.mouse().x, screenY = Graphics.mouse().y; + if(Core.input.isTouched(0) && lineMode){ + float screenX = Core.input.mouseX(), screenY = Core.input.mouseY(); float panX = 0, panY = 0; @@ -624,19 +626,19 @@ public class MobileInput extends InputHandler implements GestureListener{ panX = -(edgePan - screenX); } - if(screenX >= Gdx.graphics.getWidth() - edgePan){ - panX = (screenX - Gdx.graphics.getWidth()) + edgePan; + if(screenX >= Core.graphics.getWidth() - edgePan){ + panX = (screenX - Core.graphics.getWidth()) + edgePan; } if(screenY <= edgePan){ panY = -(edgePan - screenY); } - if(screenY >= Gdx.graphics.getHeight() - edgePan){ - panY = (screenY - Gdx.graphics.getHeight()) + edgePan; + if(screenY >= Core.graphics.getHeight() - edgePan){ + panY = (screenY - Core.graphics.getHeight()) + edgePan; } - vector.set(panX, panY).scl((Core.camera.viewportWidth * Core.camera.zoom) / Gdx.graphics.getWidth()); + vector.set(panX, panY).scl((Core.camera.width ) / Core.graphics.getWidth()); vector.limit(maxPanSpeed); //pan view @@ -652,7 +654,7 @@ public class MobileInput extends InputHandler implements GestureListener{ PlaceRequest request = removals.get(i); if(request.scale <= 0.0001f){ - removals.removeIndex(i); + removals.remove(i); i--; } } @@ -660,74 +662,47 @@ 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; //can't pan in line mode with one finger or while dropping items! - if((lineMode && !Gdx.input.isTouched(1)) || droppingItem){ + if((lineMode && !Core.input.isTouched(1)) || droppingItem){ return false; } - float dx = deltaX * Core.camera.zoom / Core.cameraScale, dy = deltaY * Core.camera.zoom / Core.cameraScale; - if(selecting){ //pan all requests for(PlaceRequest req : selection){ if(req.remove) continue; //don't shift removal requests - req.x += dx; - req.y -= dy; + req.x += deltaX; + req.y += deltaY; } }else{ //pan player - Core.camera.position.x -= dx; - Core.camera.position.y += dy; + Core.camera.position.x -= deltaX; + Core.camera.position.y -= deltaY; } return false; } - @Override - public boolean panStop(float x, float y, int pointer, int button){ - return false; - } - - @Override - public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2){ - return false; - } - @Override public boolean zoom(float initialDistance, float distance){ + if(lastDistance == -1) lastDistance = initialDistance; - if(Math.abs(distance - initialDistance) > io.anuke.ucore.scene.ui.layout.Unit.dp.scl(100f) && !zoomed){ - int amount = (distance > initialDistance ? 1 : -1); - renderer.scaleCamera(Math.round(io.anuke.ucore.scene.ui.layout.Unit.dp.scl(amount))); - zoomed = true; - return true; - } - - return false; - } - - @Override - public void pinchStop(){ - zoomed = false; - } - - @Override - public boolean touchDown(float x, float y, int pointer, int button){ - canPan = !ui.hasMouse(); - return false; - } - - @Override - public boolean fling(float velocityX, float velocityY, int button){ - return false; + 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; } //endregion class PlaceRequest{ float x, y; - Recipe recipe; + Block block; int rotation; boolean remove; @@ -735,10 +710,10 @@ public class MobileInput extends InputHandler implements GestureListener{ float scale; float redness; - PlaceRequest(float x, float y, Recipe recipe, int rotation){ + PlaceRequest(float x, float y, Block block, int rotation){ this.x = x; this.y = y; - this.recipe = recipe; + this.block = block; this.rotation = rotation; this.remove = false; } @@ -750,7 +725,7 @@ public class MobileInput extends InputHandler implements GestureListener{ } Tile tile(){ - return world.tileWorld(x - (recipe == null ? 0 : recipe.result.offset()), y - (recipe == null ? 0 : recipe.result.offset())); + return world.tileWorld(x - (block == null ? 0 : block.offset()), y - (block == null ? 0 : block.offset())); } } -} \ No newline at end of file +} diff --git a/core/src/io/anuke/mindustry/input/PlaceUtils.java b/core/src/io/anuke/mindustry/input/PlaceUtils.java index b74b5b31a8..c2e3370eed 100644 --- a/core/src/io/anuke/mindustry/input/PlaceUtils.java +++ b/core/src/io/anuke/mindustry/input/PlaceUtils.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.input; import io.anuke.mindustry.world.Block; -import io.anuke.ucore.util.Mathf; +import io.anuke.arc.math.Mathf; import static io.anuke.mindustry.Vars.tilesize; diff --git a/core/src/io/anuke/mindustry/io/BundleLoader.java b/core/src/io/anuke/mindustry/io/BundleLoader.java index 53643dc81f..497d7f14cb 100644 --- a/core/src/io/anuke/mindustry/io/BundleLoader.java +++ b/core/src/io/anuke/mindustry/io/BundleLoader.java @@ -1,13 +1,12 @@ package io.anuke.mindustry.io; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.utils.I18NBundle; +import io.anuke.arc.Core; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.util.I18NBundle; import io.anuke.mindustry.Vars; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.util.Log; +import io.anuke.arc.util.Time; +import io.anuke.arc.util.Log; +import io.anuke.mindustry.input.Binding; import java.util.Locale; @@ -16,13 +15,14 @@ import static io.anuke.mindustry.Vars.headless; public class BundleLoader{ public static void load(){ - Settings.defaults("locale", "default"); - Settings.load(Vars.appName, headless ? "io.anuke.mindustry.server" : "io.anuke.mindustry"); + Core.settings.defaults("locale", "default"); + Core.keybinds.setDefaults(Binding.values()); + Core.settings.load(); loadBundle(); } private static Locale getLocale(){ - String loc = Settings.getString("locale"); + String loc = Core.settings.getString("locale"); if(loc.equals("default")){ return Locale.getDefault(); }else{ @@ -39,22 +39,21 @@ public class BundleLoader{ } private static void loadBundle(){ - I18NBundle.setExceptionOnMissingKey(false); try{ //try loading external bundle - FileHandle handle = Gdx.files.local("bundle"); + FileHandle handle = Core.files.local("bundle"); Locale locale = Locale.ENGLISH; Core.bundle = I18NBundle.createBundle(handle, locale); Log.info("NOTE: external translation bundle has been loaded."); if(!headless){ - Timers.run(10f, () -> Vars.ui.showInfo("Note: You have successfully loaded an external translation bundle.")); + Time.run(10f, () -> Vars.ui.showInfo("Note: You have successfully loaded an external translation bundle.")); } }catch(Throwable e){ //no external bundle found - FileHandle handle = Gdx.files.internal("bundles/bundle"); + FileHandle handle = Core.files.internal("bundles/bundle"); Locale locale = getLocale(); Locale.setDefault(locale); diff --git a/core/src/io/anuke/mindustry/io/Changelogs.java b/core/src/io/anuke/mindustry/io/Changelogs.java index e1b28c71ed..6dfcf6ce3c 100644 --- a/core/src/io/anuke/mindustry/io/Changelogs.java +++ b/core/src/io/anuke/mindustry/io/Changelogs.java @@ -1,10 +1,10 @@ package io.anuke.mindustry.io; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.JsonReader; -import com.badlogic.gdx.utils.JsonValue; +import io.anuke.arc.collection.Array; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.util.serialization.JsonReader; +import io.anuke.arc.util.serialization.JsonValue; import io.anuke.mindustry.net.Net; -import io.anuke.ucore.function.Consumer; import static io.anuke.mindustry.Vars.releasesURL; diff --git a/core/src/io/anuke/mindustry/io/Contributors.java b/core/src/io/anuke/mindustry/io/Contributors.java index f7c6e0f4b1..9924e8e44c 100644 --- a/core/src/io/anuke/mindustry/io/Contributors.java +++ b/core/src/io/anuke/mindustry/io/Contributors.java @@ -1,10 +1,10 @@ package io.anuke.mindustry.io; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.JsonReader; -import com.badlogic.gdx.utils.JsonValue; +import io.anuke.arc.collection.Array; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.util.serialization.JsonReader; +import io.anuke.arc.util.serialization.JsonValue; import io.anuke.mindustry.net.Net; -import io.anuke.ucore.function.Consumer; import static io.anuke.mindustry.Vars.contributorsURL; diff --git a/core/src/io/anuke/mindustry/io/MapIO.java b/core/src/io/anuke/mindustry/io/MapIO.java index 7dea904ef3..2e83e14d31 100644 --- a/core/src/io/anuke/mindustry/io/MapIO.java +++ b/core/src/io/anuke/mindustry/io/MapIO.java @@ -1,13 +1,14 @@ package io.anuke.mindustry.io; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.Pixmap.Format; -import com.badlogic.gdx.utils.IntIntMap; -import com.badlogic.gdx.utils.ObjectMap; -import com.badlogic.gdx.utils.ObjectMap.Entry; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.content.blocks.StorageBlocks; +import io.anuke.arc.collection.IntIntMap; +import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.collection.ObjectMap.Entry; +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.Team; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.maps.MapMeta; @@ -16,11 +17,8 @@ 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.ColorMapper; import io.anuke.mindustry.world.LegacyColorMapper; import io.anuke.mindustry.world.LegacyColorMapper.LegacyBlock; -import io.anuke.ucore.util.Bits; -import io.anuke.ucore.util.Structs; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -51,10 +49,9 @@ public class MapIO{ for(int y = 0; y < data.height(); y++){ for(int x = 0; x < data.width(); x++){ data.read(marker); - byte elev = y >= data.height() - 1 ? 0 : data.read(x, y + 1, DataPosition.elevation); Block floor = content.block(marker.floor); Block wall = content.block(marker.wall); - int color = ColorMapper.colorFor(floor, wall, Team.all[marker.team], marker.elevation + 1, elev > marker.elevation ? (byte)(1 << 6) : (byte)0); + int color = colorFor(floor, wall, Team.all[marker.team]); pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, color); } } @@ -74,12 +71,7 @@ public class MapIO{ LegacyBlock block = LegacyColorMapper.get(color); data.write(x, y, DataPosition.floor, block.floor.id); - data.write(x, y, DataPosition.elevation, (byte)block.elevation); - - //place spawn - if(color == Color.rgba8888(Color.RED)){ - data.write(x, y, DataPosition.wall, Blocks.spawn.id); - } + data.write(x, y, DataPosition.wall, block.wall.id); //place core if(color == Color.rgba8888(Color.GREEN)){ @@ -89,15 +81,15 @@ public class MapIO{ int worldy = dy - 1 + y; if(Structs.inBounds(worldx, worldy, pixmap.getWidth(), pixmap.getHeight())){ - data.write(worldx, worldy, DataPosition.wall, Blocks.blockpart.id); - data.write(worldx, worldy, DataPosition.rotationTeam, Bits.packByte((byte)0, (byte)Team.blue.ordinal())); - data.write(worldx, worldy, DataPosition.link, Bits.packByte((byte) (dx - 1 + 8), (byte) (dy - 1 + 8))); + 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, StorageBlocks.core.id); - data.write(x, y, DataPosition.rotationTeam, Bits.packByte((byte)0, (byte)Team.blue.ordinal())); + data.write(x, y, DataPosition.wall, Blocks.coreShard.id); + data.write(x, y, DataPosition.rotationTeam, Pack.byteByte((byte)0, (byte)Team.blue.ordinal())); } } } @@ -169,7 +161,6 @@ public class MapIO{ String name = stream.readUTF(); Block block = content.getByName(ContentType.block, name); if(block == null){ - //Log.info("Map load info: No block with name {0} found.", name); block = Blocks.air; } map.put(id, block.id); @@ -199,4 +190,11 @@ public class MapIO{ 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 0b4b40f5d2..eebe565662 100644 --- a/core/src/io/anuke/mindustry/io/SaveFileVersion.java +++ b/core/src/io/anuke/mindustry/io/SaveFileVersion.java @@ -1,22 +1,22 @@ package io.anuke.mindustry.io; -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.content.blocks.StorageBlocks; +import io.anuke.arc.collection.Array; +import io.anuke.mindustry.entities.Entities; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.traits.Entity; +import io.anuke.arc.util.Pack; +import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.entities.traits.SaveTrait; import io.anuke.mindustry.entities.traits.TypeTrait; import io.anuke.mindustry.game.Content; -import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.MappableContent; +import io.anuke.mindustry.game.Rules; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.maps.Map; +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.ucore.entities.Entities; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.trait.Entity; -import io.anuke.ucore.util.Bits; +import io.anuke.mindustry.world.blocks.storage.CoreBlock; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -35,12 +35,11 @@ public abstract class SaveFileVersion{ long time = stream.readLong(); long playtime = stream.readLong(); int build = stream.readInt(); - int sector = stream.readInt(); - byte mode = stream.readByte(); + + Rules rules = Serialization.readRules(stream); String map = stream.readUTF(); int wave = stream.readInt(); - byte difficulty = stream.readByte(); - return new SaveMeta(version, time, playtime, build, sector, mode, map, wave, Difficulty.values()[difficulty]); + return new SaveMeta(version, time, playtime, build, map, wave, rules); } public void writeMap(DataOutputStream stream) throws IOException{ @@ -54,12 +53,11 @@ public abstract class SaveFileVersion{ stream.writeByte(tile.getFloorID()); stream.writeByte(tile.getBlockID()); - stream.writeByte(tile.getElevation()); if(tile.block() instanceof BlockPart){ stream.writeByte(tile.link); }else if(tile.entity != null){ - stream.writeByte(Bits.packByte(tile.getTeamID(), tile.getRotation())); //team + rotation + stream.writeByte(Pack.byteByte(tile.getTeamID(), tile.getRotation())); //team + rotation stream.writeShort((short) tile.entity.health); //health if(tile.entity.items != null) tile.entity.items.write(stream); @@ -75,7 +73,7 @@ public abstract class SaveFileVersion{ 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 || nextTile.getElevation() != tile.getElevation()){ + if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air){ break; } @@ -86,40 +84,12 @@ public abstract class SaveFileVersion{ i += consecutives; } } - - //write visibility, length-run encoded - for(int i = 0; i < world.width() * world.height(); i++){ - Tile tile = world.tile(i % world.width(), i / world.width()); - boolean discovered = tile.discovered(); - - int consecutives = 0; - - for(int j = i + 1; j < world.width() * world.height() && consecutives < 32767*2-1; j++){ - Tile nextTile = world.tile(j % world.width(), j / world.width()); - - if(nextTile.discovered() != discovered){ - break; - } - - consecutives++; - } - - stream.writeBoolean(discovered); - stream.writeShort(consecutives); - i += consecutives; - } } public void readMap(DataInputStream stream) throws IOException{ short width = stream.readShort(); short height = stream.readShort(); - if(world.getSector() != null){ - world.setMap(new Map("Sector " + world.getSector().x + ", " + world.getSector().y, width, height)); - }else if(world.getMap() == null){ - world.setMap(new Map("unknown", width, height)); - } - world.beginMapLoad(); Tile[][] tiles = world.createTiles(width, height); @@ -128,19 +98,17 @@ public abstract class SaveFileVersion{ int x = i % width, y = i / width; byte floorid = stream.readByte(); byte wallid = stream.readByte(); - byte elevation = stream.readByte(); Tile tile = new Tile(x, y, floorid, wallid); - tile.setElevation(elevation); - if(wallid == Blocks.blockpart.id){ + if(wallid == Blocks.part.id){ tile.link = stream.readByte(); }else if(tile.entity != null){ byte tr = stream.readByte(); short health = stream.readShort(); - byte team = Bits.getLeftByte(tr); - byte rotation = Bits.getRightByte(tr); + byte team = Pack.leftByte(tr); + byte rotation = Pack.rightByte(tr); Team t = Team.all[team]; @@ -156,7 +124,7 @@ public abstract class SaveFileVersion{ tile.entity.readConfig(stream); tile.entity.read(stream); - if(tile.block() == StorageBlocks.core){ + if(tile.block() instanceof CoreBlock){ state.teams.get(t).cores.add(tile); } }else if(wallid == 0){ @@ -165,7 +133,6 @@ public abstract class SaveFileVersion{ 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); - newTile.setElevation(elevation); tiles[newx][newy] = newTile; } @@ -175,18 +142,6 @@ public abstract class SaveFileVersion{ tiles[x][y] = tile; } - for(int i = 0; i < width * height; i++){ - boolean discovered = stream.readBoolean(); - int consecutives = stream.readUnsignedShort(); - if(discovered){ - for(int j = i + 1; j < i + 1 + consecutives; j++){ - int newx = j % width, newy = j / width; - tiles[newx][newy].setVisibility((byte) 1); - } - } - i += consecutives; - } - content.setTemporaryMapper(null); world.endMapLoad(); } diff --git a/core/src/io/anuke/mindustry/io/SaveIO.java b/core/src/io/anuke/mindustry/io/SaveIO.java index c13fe96662..10846a4268 100644 --- a/core/src/io/anuke/mindustry/io/SaveIO.java +++ b/core/src/io/anuke/mindustry/io/SaveIO.java @@ -1,9 +1,9 @@ package io.anuke.mindustry.io; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.IntArray; -import com.badlogic.gdx.utils.IntMap; +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.IntArray; +import io.anuke.arc.collection.IntMap; +import io.anuke.arc.files.FileHandle; import io.anuke.mindustry.Vars; import io.anuke.mindustry.io.versions.Save16; @@ -13,6 +13,7 @@ import java.util.zip.InflaterInputStream; import static io.anuke.mindustry.Vars.*; +//TODO load backup meta if possible public class SaveIO{ public static final IntArray breakingVersions = IntArray.with(47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 63); public static final IntMap versions = new IntMap<>(); @@ -42,7 +43,7 @@ public class SaveIO{ } } - public static void loadFromSlot(int slot){ + public static void loadFromSlot(int slot) throws SaveException{ load(fileFor(slot)); } @@ -65,9 +66,7 @@ public class SaveIO{ public static boolean isSaveValid(DataInputStream stream){ try{ - int version = stream.readInt(); - SaveFileVersion ver = versions.get(version); - ver.getData(stream); + getData(stream); return true; }catch(Exception e){ e.printStackTrace(); @@ -118,40 +117,41 @@ public class SaveIO{ } } - public static void load(FileHandle file){ + public static void load(FileHandle file) throws SaveException{ try{ + //try and load; if any exception at all occurs load(new InflaterInputStream(file.read())); - }catch(RuntimeException e){ + }catch(SaveException e){ e.printStackTrace(); FileHandle backup = file.sibling(file.name() + "-backup." + file.extension()); if(backup.exists()){ load(new InflaterInputStream(backup.read())); }else{ - throw new RuntimeException(e); + throw new SaveException(e.getCause()); } } } - public static void load(InputStream is){ - logic.reset(); - - DataInputStream stream; - - try{ - stream = new DataInputStream(is); + public static void load(InputStream is) throws SaveException{ + try(DataInputStream stream = new DataInputStream(is)){ + logic.reset(); int version = stream.readInt(); SaveFileVersion ver = versions.get(version); ver.read(stream); - - stream.close(); }catch(Exception e){ content.setTemporaryMapper(null); - throw new RuntimeException(e); + throw new SaveException(e); } } public static SaveFileVersion getVersion(){ return versionArray.peek(); } + + public static class SaveException extends RuntimeException{ + public SaveException(Throwable throwable){ + super(throwable); + } + } } diff --git a/core/src/io/anuke/mindustry/io/SaveMeta.java b/core/src/io/anuke/mindustry/io/SaveMeta.java index 61e035a356..cfe0be8231 100644 --- a/core/src/io/anuke/mindustry/io/SaveMeta.java +++ b/core/src/io/anuke/mindustry/io/SaveMeta.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.io; -import io.anuke.mindustry.game.Difficulty; -import io.anuke.mindustry.game.GameMode; +import io.anuke.mindustry.game.Rules; import io.anuke.mindustry.maps.Map; import static io.anuke.mindustry.Vars.world; @@ -11,21 +10,17 @@ public class SaveMeta{ public int build; public long timestamp; public long timePlayed; - public int sector; - public GameMode mode; public Map map; public int wave; - public Difficulty difficulty; + public Rules rules; - public SaveMeta(int version, long timestamp, long timePlayed, int build, int sector, int mode, String map, int wave, Difficulty difficulty){ + public SaveMeta(int version, long timestamp, long timePlayed, int build, String map, int wave, Rules rules){ this.version = version; this.build = build; this.timestamp = timestamp; this.timePlayed = timePlayed; - this.sector = sector; - this.mode = GameMode.values()[mode]; this.map = world.maps.getByName(map); this.wave = wave; - this.difficulty = difficulty; + this.rules = rules; } } diff --git a/core/src/io/anuke/mindustry/io/TypeIO.java b/core/src/io/anuke/mindustry/io/TypeIO.java index 2d0f9feb08..937440a425 100644 --- a/core/src/io/anuke/mindustry/io/TypeIO.java +++ b/core/src/io/anuke/mindustry/io/TypeIO.java @@ -1,18 +1,18 @@ package io.anuke.mindustry.io; -import com.badlogic.gdx.graphics.Color; import io.anuke.annotations.Annotations.ReadClass; import io.anuke.annotations.Annotations.WriteClass; -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.arc.graphics.Color; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.Unit; 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.units.UnitCommand; +import io.anuke.mindustry.entities.type.BaseUnit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.net.Packets.AdminAction; import io.anuke.mindustry.net.Packets.KickReason; @@ -20,9 +20,6 @@ import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Pos; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.entities.Entities; import java.io.DataInput; import java.io.DataOutput; @@ -93,46 +90,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()); @@ -173,7 +130,7 @@ public class TypeIO{ buffer.put(request.breaking ? (byte) 1 : 0); buffer.putInt(Pos.get(request.x, request.y)); if(!request.breaking){ - buffer.put(request.recipe.id); + buffer.put(request.block.id); buffer.put((byte) request.rotation); } } @@ -191,9 +148,9 @@ public class TypeIO{ if(type == 1){ //remove currentRequest = new BuildRequest(Pos.x(position), Pos.y(position)); }else{ //place - byte recipe = buffer.get(); + byte block = buffer.get(); byte rotation = buffer.get(); - currentRequest = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.recipe(recipe)); + currentRequest = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.block(block)); } reqs[i] = (currentRequest); @@ -232,16 +189,6 @@ public class TypeIO{ return AdminAction.values()[buffer.get()]; } - @WriteClass(UnitCommand.class) - public static void writeCommand(ByteBuffer buffer, UnitCommand reason){ - buffer.put((byte) reason.ordinal()); - } - - @ReadClass(UnitCommand.class) - public static UnitCommand readCommand(ByteBuffer buffer){ - return UnitCommand.values()[buffer.get()]; - } - @WriteClass(Effect.class) public static void writeEffect(ByteBuffer buffer, Effect effect){ buffer.putShort((short) effect.id); @@ -262,16 +209,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); @@ -292,16 +229,6 @@ public class TypeIO{ return content.liquid(buffer.get()); } - @WriteClass(AmmoType.class) - public static void writeAmmo(ByteBuffer buffer, AmmoType type){ - buffer.put(type.id); - } - - @ReadClass(AmmoType.class) - public static AmmoType readAmmo(ByteBuffer buffer){ - return content.getByID(ContentType.weapon, buffer.get()); - } - @WriteClass(BulletType.class) public static void writeBulletType(ByteBuffer buffer, BulletType type){ buffer.put(type.id); @@ -323,16 +250,6 @@ public class TypeIO{ return id == -1 ? null : content.item(id); } - @WriteClass(Recipe.class) - public static void writeRecipe(ByteBuffer buffer, Recipe recipe){ - buffer.put(recipe.id); - } - - @ReadClass(Recipe.class) - public static Recipe readRecipe(ByteBuffer buffer){ - return content.recipe(buffer.get()); - } - @WriteClass(String.class) public static void writeString(ByteBuffer buffer, String string){ if(string != null){ diff --git a/core/src/io/anuke/mindustry/io/versions/Save16.java b/core/src/io/anuke/mindustry/io/versions/Save16.java index 7a4fc1e79e..35bf6ba75a 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save16.java +++ b/core/src/io/anuke/mindustry/io/versions/Save16.java @@ -1,11 +1,12 @@ package io.anuke.mindustry.io.versions; -import com.badlogic.gdx.utils.TimeUtils; -import io.anuke.mindustry.game.Difficulty; -import io.anuke.mindustry.game.GameMode; +import io.anuke.arc.util.Time; import io.anuke.mindustry.game.Version; +import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.io.SaveFileVersion; import io.anuke.mindustry.maps.Map; +import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.type.Zone; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -24,31 +25,29 @@ public class Save16 extends SaveFileVersion{ stream.readLong(); //time stream.readLong(); //total playtime stream.readInt(); //build - int sector = stream.readInt(); //sector ID //general state - byte mode = stream.readByte(); + state.rules = Serialization.readRules(stream); + //load zone spawn patterns if applicable + if(content.getByID(ContentType.zone, state.rules.zone) != null){ + state.rules.spawns = content.getByID(ContentType.zone, state.rules.zone).rules.get().spawns; + } String mapname = stream.readUTF(); Map map = world.maps.getByName(mapname); + if(map == null) map = new Map("unknown", 1, 1); world.setMap(map); - world.setSector(world.sectors.get(sector)); - int wave = stream.readInt(); - byte difficulty = stream.readByte(); float wavetime = stream.readFloat(); - state.difficulty = Difficulty.values()[difficulty]; - state.mode = GameMode.values()[mode]; state.wave = wave; state.wavetime = wavetime; + state.stats = Serialization.readStats(stream); + world.spawner.read(stream); content.setTemporaryMapper(readContentHeader(stream)); - world.spawner.read(stream); - readEntities(stream); - readMap(stream); } @@ -56,22 +55,21 @@ public class Save16 extends SaveFileVersion{ public void write(DataOutputStream stream) throws IOException{ //--META-- stream.writeInt(version); //version id - stream.writeLong(TimeUtils.millis()); //last saved + stream.writeLong(Time.millis()); //last saved stream.writeLong(headless ? 0 : control.saves.getTotalPlaytime()); //playtime stream.writeInt(Version.build); //build - stream.writeInt(world.getSector() == null ? invalidSector : world.getSector().pos()); //sector ID //--GENERAL STATE-- - stream.writeByte(state.mode.ordinal()); //gamemode - stream.writeUTF(world.getMap().name); //map ID + Serialization.writeRules(stream, state.rules); + stream.writeUTF(world.getMap().name); //map name stream.writeInt(state.wave); //wave - stream.writeByte(state.difficulty.ordinal()); //difficulty ordinal stream.writeFloat(state.wavetime); //wave countdown - writeContentHeader(stream); + Serialization.writeStats(stream, state.stats); + world.spawner.write(stream); - world.spawner.write(stream); //spawnes + writeContentHeader(stream); //--ENTITIES-- diff --git a/core/src/io/anuke/mindustry/maps/Map.java b/core/src/io/anuke/mindustry/maps/Map.java index 1ad60c0e1d..2481d42344 100644 --- a/core/src/io/anuke/mindustry/maps/Map.java +++ b/core/src/io/anuke/mindustry/maps/Map.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.maps; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.utils.ObjectMap; -import io.anuke.ucore.function.Supplier; +import io.anuke.arc.graphics.Texture; +import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.function.Supplier; import java.io.InputStream; diff --git a/core/src/io/anuke/mindustry/maps/MapMeta.java b/core/src/io/anuke/mindustry/maps/MapMeta.java index 2f13ee59b9..36f815b63f 100644 --- a/core/src/io/anuke/mindustry/maps/MapMeta.java +++ b/core/src/io/anuke/mindustry/maps/MapMeta.java @@ -1,9 +1,10 @@ package io.anuke.mindustry.maps; -import com.badlogic.gdx.utils.IntIntMap; -import com.badlogic.gdx.utils.ObjectMap; -import io.anuke.ucore.util.Bundles; +import io.anuke.arc.Core; +import io.anuke.arc.collection.IntIntMap; +import io.anuke.arc.collection.ObjectMap; +//todo: specify preferred game rules here; can be overriden public class MapMeta{ public final int version; public final ObjectMap tags; @@ -31,11 +32,7 @@ public class MapMeta{ } public String tag(String name){ - return tags.containsKey(name) && !tags.get(name).trim().isEmpty() ? tags.get(name): Bundles.get("text.unknown"); - } - - public boolean hasOreGen(){ - return !tags.get("oregen", "0").equals("0"); + return tags.containsKey(name) && !tags.get(name).trim().isEmpty() ? tags.get(name): Core.bundle.get("unknown"); } @Override diff --git a/core/src/io/anuke/mindustry/maps/MapTileData.java b/core/src/io/anuke/mindustry/maps/MapTileData.java index e48b902032..15d6e30506 100644 --- a/core/src/io/anuke/mindustry/maps/MapTileData.java +++ b/core/src/io/anuke/mindustry/maps/MapTileData.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.maps; -import com.badlogic.gdx.utils.IntIntMap; +import io.anuke.arc.collection.IntIntMap; +import io.anuke.arc.util.Pack; +import io.anuke.arc.util.Structs; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.blocks.Blocks; +import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.world.Block; -import io.anuke.ucore.util.Bits; -import io.anuke.ucore.util.Structs; import java.nio.ByteBuffer; @@ -48,7 +48,7 @@ public class MapTileData{ read(marker); //strip blockparts from map data, as they can be invalid - if(marker.wall == Blocks.blockpart.id){ + if(marker.wall == Blocks.part.id){ marker.wall = Blocks.air.id; } @@ -72,8 +72,8 @@ public class MapTileData{ int worldy = dy + offsety + y; if(Structs.inBounds(worldx, worldy, width, height) && !(dx + offsetx == 0 && dy + offsety == 0)){ - write(worldx, worldy, DataPosition.wall, Blocks.blockpart.id); - write(worldx, worldy, DataPosition.link, Bits.packByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8))); + write(worldx, worldy, DataPosition.wall, Blocks.part.id); + write(worldx, worldy, DataPosition.link, Pack.byteByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8))); } } } @@ -154,8 +154,8 @@ public class MapTileData{ link = buffer.get(); byte rt = buffer.get(); elevation = buffer.get(); - rotation = Bits.getLeftByte(rt); - team = Bits.getRightByte(rt); + rotation = Pack.leftByte(rt); + team = Pack.rightByte(rt); if(map != null){ floor = (byte) map.get(floor, Blocks.stone.id); @@ -168,7 +168,7 @@ public class MapTileData{ buffer.put(floor); buffer.put(wall); buffer.put(link); - buffer.put(Bits.packByte(rotation, team)); + buffer.put(Pack.byteByte(rotation, team)); buffer.put(elevation); } } diff --git a/core/src/io/anuke/mindustry/maps/Maps.java b/core/src/io/anuke/mindustry/maps/Maps.java index 74936f00f8..2bd7823ad5 100644 --- a/core/src/io/anuke/mindustry/maps/Maps.java +++ b/core/src/io/anuke/mindustry/maps/Maps.java @@ -1,15 +1,14 @@ package io.anuke.mindustry.maps; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Disposable; -import com.badlogic.gdx.utils.ObjectMap; +import io.anuke.arc.Core; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.graphics.Texture; +import io.anuke.arc.collection.Array; +import io.anuke.arc.util.Disposable; +import io.anuke.arc.collection.ObjectMap; import io.anuke.mindustry.io.MapIO; -import io.anuke.ucore.function.Supplier; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.ThreadArray; +import io.anuke.arc.function.Supplier; +import io.anuke.arc.util.Log; import java.io.DataInputStream; import java.io.IOException; @@ -19,16 +18,16 @@ import static io.anuke.mindustry.Vars.*; public class Maps implements Disposable{ /**List of all built-in maps.*/ - private static final String[] defaultMapNames = {"sandbox"}; + private static final String[] defaultMapNames = {}; /**Tile format version.*/ private static final int version = 0; /**Maps map names to the real maps.*/ private ObjectMap maps = new ObjectMap<>(); /**All maps stored in an ordered array.*/ - private Array allMaps = new ThreadArray<>(); + private Array allMaps = new Array<>(); /**Temporary array used for returning things.*/ - private Array returnArray = new ThreadArray<>(); + private Array returnArray = new Array<>(); /**Returns a list of all maps, including custom ones.*/ public Array all(){ @@ -55,14 +54,26 @@ 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. + * Does not add this map to the map list.*/ + public Map loadInternalMap(String name){ + FileHandle file = Core.files.internal("maps/" + name + "." + mapExtension); + + try(DataInputStream ds = new DataInputStream(file.read())) { + return new Map(name, MapIO.readMapMeta(ds), false, file::read); + }catch(IOException e){ + throw new RuntimeException(e); + } } /**Load all maps. Should be called at application start.*/ public void load(){ - try { + try{ for (String name : defaultMapNames) { - FileHandle file = Gdx.files.internal("maps/" + name + "." + mapExtension); + FileHandle file = Core.files.internal("maps/" + name + "." + mapExtension); loadMap(file.nameWithoutExtension(), file::read, false); } }catch (IOException e){ @@ -125,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/Sector.java b/core/src/io/anuke/mindustry/maps/Sector.java deleted file mode 100644 index e184409ae1..0000000000 --- a/core/src/io/anuke/mindustry/maps/Sector.java +++ /dev/null @@ -1,73 +0,0 @@ -package io.anuke.mindustry.maps; - -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.utils.Array; -import io.anuke.annotations.Annotations.Serialize; -import io.anuke.mindustry.game.Saves.SaveSlot; -import io.anuke.mindustry.game.SpawnGroup; -import io.anuke.mindustry.maps.missions.*; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.ucore.util.Bits; - -import static io.anuke.mindustry.Vars.control; -import static io.anuke.mindustry.Vars.headless; - -@Serialize -public class Sector{ - private static final Mission victoryMission = new VictoryMission(); - - /**Position on the map, can be positive or negative.*/ - public short x, y; - /**Whether this sector has already been completed.*/ - public boolean complete; - /**Slot ID of this sector's save. -1 means no save has been created.*/ - public int saveID = -1; - /**Num of missions in this sector that have been completed so far.*/ - public int completedMissions; - - /**Display texture. Needs to be disposed.*/ - public transient Texture texture; - /**Missions of this sector-- what needs to be accomplished to unlock it.*/ - public transient Array missions = new Array<>(); - /**Enemies spawned at this sector.*/ - public transient Array spawns; - /**Difficulty of the sector, measured by calculating distance from origin and applying scaling.*/ - public transient int difficulty; - /**Items the player starts with on this sector.*/ - public transient Array startingItems; - - public Mission getDominantMission(){ - for(Mission mission : missions){ - if(mission instanceof WaveMission || mission instanceof BattleMission){ - return mission; - } - } - - for(Mission mission : missions){ - if(mission instanceof BlockMission){ - return mission; - } - } - return missions.first(); - } - - public Mission currentMission(){ - return completedMissions >= missions.size ? victoryMission : missions.get(completedMissions); - } - - public int getSeed(){ - return Bits.packInt(x, y); - } - - public SaveSlot getSave(){ - return !hasSave() ? null : control.saves.getByID(saveID); - } - - public boolean hasSave(){ - return !headless && control.saves.getByID(saveID) != null; - } - - public int pos(){ - return Bits.packInt(x, y); - } -} diff --git a/core/src/io/anuke/mindustry/maps/SectorPresets.java b/core/src/io/anuke/mindustry/maps/SectorPresets.java deleted file mode 100644 index 08fa7f1b19..0000000000 --- a/core/src/io/anuke/mindustry/maps/SectorPresets.java +++ /dev/null @@ -1,92 +0,0 @@ -package io.anuke.mindustry.maps; - -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.content.Mechs; -import io.anuke.mindustry.content.UnitTypes; -import io.anuke.mindustry.content.blocks.CraftingBlocks; -import io.anuke.mindustry.content.blocks.ProductionBlocks; -import io.anuke.mindustry.content.blocks.UnitBlocks; -import io.anuke.mindustry.content.blocks.UpgradeBlocks; -import io.anuke.mindustry.entities.units.UnitCommand; -import io.anuke.mindustry.maps.missions.*; -import io.anuke.mindustry.type.Item; -import io.anuke.ucore.util.GridMap; -import io.anuke.ucore.util.Structs; - -import static io.anuke.mindustry.Vars.mobile; - -public class SectorPresets{ - private final GridMap presets = new GridMap<>(); - private final GridMap> orePresets = new GridMap<>(); - - public SectorPresets(){ - - //base tutorial mission - add(new SectorPreset(0, 0, - TutorialSector.getMissions(), - Array.with(Items.copper, Items.coal, Items.lead))); - - //command center mission - add(new SectorPreset(0, 1, - Structs.array( - Missions.blockRecipe(UnitBlocks.daggerFactory), - new UnitMission(UnitTypes.dagger), - Missions.blockRecipe(UnitBlocks.commandCenter), - new CommandMission(UnitCommand.retreat), - new CommandMission(UnitCommand.attack), - new BattleMission() - ), - Array.with(Items.copper, Items.lead, Items.coal))); - - //pad mission - add(new SectorPreset(0, -2, - Structs.array( - Missions.blockRecipe(mobile ? UpgradeBlocks.alphaPad : UpgradeBlocks.dartPad), - new MechMission(mobile ? Mechs.alpha : Mechs.dart), - new WaveMission(15) - ), - Array.with(Items.copper, Items.lead, Items.coal, Items.titanium))); - - //oil mission - add(new SectorPreset(-2, 0, - Structs.array( - Missions.blockRecipe(ProductionBlocks.cultivator), - Missions.blockRecipe(ProductionBlocks.waterExtractor), - new ContentMission(Items.biomatter), - Missions.blockRecipe(CraftingBlocks.biomatterCompressor), - new ContentMission(Liquids.oil), - new BattleMission() - ), - Array.with(Items.copper, Items.lead, Items.coal, Items.titanium))); - } - - public Array getOres(int x, int y){ - return orePresets.get(x, y); - } - - public SectorPreset get(int x, int y){ - return presets.get(x, y); - } - - public GridMap getPresets() { return presets; } - - private void add(SectorPreset preset){ - presets.put(preset.x, preset.y, preset); - orePresets.put(preset.x, preset.y, preset.ores); - } - - public static class SectorPreset{ - public final Array missions; - public final Array ores; - public final int x, y; - - public SectorPreset(int x, int y, Array missions, Array ores){ - this.missions = missions; - this.x = x; - this.y = y; - this.ores = ores; - } - } -} diff --git a/core/src/io/anuke/mindustry/maps/Sectors.java b/core/src/io/anuke/mindustry/maps/Sectors.java deleted file mode 100644 index b2d4b6cb1b..0000000000 --- a/core/src/io/anuke/mindustry/maps/Sectors.java +++ /dev/null @@ -1,320 +0,0 @@ -package io.anuke.mindustry.maps; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.Pixmap.Format; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Array.ArrayIterable; -import com.badlogic.gdx.utils.async.AsyncExecutor; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.game.Difficulty; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.io.SaveIO; -import io.anuke.mindustry.maps.SectorPresets.SectorPreset; -import io.anuke.mindustry.maps.generation.Generation; -import io.anuke.mindustry.maps.generation.WorldGenerator.GenResult; -import io.anuke.mindustry.maps.missions.BattleMission; -import io.anuke.mindustry.maps.missions.Mission; -import io.anuke.mindustry.maps.missions.Missions; -import io.anuke.mindustry.maps.missions.WaveMission; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Recipe; -import io.anuke.mindustry.type.Recipe.RecipeVisibility; -import io.anuke.mindustry.world.ColorMapper; -import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.mindustry.world.blocks.defense.Wall; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.util.*; - -import static io.anuke.mindustry.Vars.*; - -public class Sectors{ - public static final int sectorImageSize = 32; - - private final GridMap grid = new GridMap<>(); - private final SectorPresets presets = new SectorPresets(); - private final Array allOres = Item.getAllOres(); - private final AsyncExecutor executor = new AsyncExecutor(6); - - public void playSector(Sector sector){ - if(!headless && sector.hasSave() && SaveIO.breakingVersions.contains(sector.getSave().getBuild())){ - sector.getSave().delete(); - ui.showInfo("$text.save.old"); - } - - if(!sector.hasSave()){ - for(Mission mission : sector.missions){ - mission.reset(); - } - world.loadSector(sector); - logic.play(); - if(!headless){ - sector.saveID = control.saves.addSave("sector-" + sector.pos()).index; - } - world.sectors.save(); - world.setSector(sector); - if(!sector.complete) sector.currentMission().onBegin(); - }else if(SaveIO.breakingVersions.contains(sector.getSave().getBuild())){ - ui.showInfo("$text.save.old"); - }else try{ - sector.getSave().load(); - world.setSector(sector); - state.set(State.playing); - if(!sector.complete) sector.currentMission().onBegin(); - }catch(Exception e){ - Log.err(e); - sector.getSave().delete(); - - playSector(sector); - - if(!headless){ - threads.runGraphics(() -> ui.showError("$text.sector.corrupted")); - } - } - } - - /**If a sector is not yet unlocked, returns null.*/ - public Sector get(int x, int y){ - return grid.get(x, y); - } - - public Sector get(int position){ - return grid.get(Bits.getLeftShort(position), Bits.getRightShort(position)); - } - - public Iterable getSectors(){ - return grid.values(); - } - - public Difficulty getDifficulty(Sector sector){ - if(sector.difficulty == 0){ - return Difficulty.hard; - }else if(sector.difficulty < 4){ - return Difficulty.normal; - }else if(sector.difficulty < 9){ - return Difficulty.hard; - }else{ - return Difficulty.insane; - } - } - - public Array getOres(int x, int y){ - return presets.getOres(x, y) == null ? allOres : presets.getOres(x, y); - } - - /**Unlocks a sector. This shows nearby sectors.*/ - public void completeSector(int x, int y){ - createSector(x, y); - Sector sector = get(x, y); - sector.complete = true; - - for(GridPoint2 g : Geometry.d4){ - createSector(x + g.x, y + g.y); - } - } - - /**Creates a sector at a location if it is not present, but does not complete it.*/ - public void createSector(int x, int y){ - - if(grid.containsKey(x, y)) return; - - Sector sector = new Sector(); - sector.x = (short)x; - sector.y = (short)y; - sector.complete = false; - initSector(sector); - - grid.put(sector.x, sector.y, sector); - - if(sector.texture == null){ - threads.runGraphics(() -> createTexture(sector)); - } - - if(sector.missions.size == 0){ - completeSector(sector.x, sector.y); - } - } - - public void abandonSector(Sector sector){ - if(sector.hasSave()){ - sector.getSave().delete(); - } - sector.completedMissions = 0; - sector.complete = false; - initSector(sector); - - grid.put(sector.x, sector.y, sector); - - threads.runGraphics(() -> createTexture(sector)); - - save(); - } - - @SuppressWarnings("unchecked") - public void load(){ - for(Sector sector : grid.values()){ - sector.texture.dispose(); - } - grid.clear(); - - Array out = Settings.getObject("sector-data-2", Array.class, Array::new); - - for(Sector sector : out){ - - createTexture(sector); - initSector(sector); - grid.put(sector.x, sector.y, sector); - } - - if(out.size == 0){ - createSector(0, 0); - } - } - - public void clear(){ - grid.clear(); - save(); - createSector(0, 0); - } - - public void save(){ - Array out = new Array<>(); - - for(Sector sector : grid.values()){ - if(sector != null && !out.contains(sector, true)){ - out.add(sector); - } - } - - Settings.putObject("sector-data-2", out); - Settings.save(); - } - - private void initSector(Sector sector){ - sector.difficulty = (int)(Mathf.dst(sector.x, sector.y)); - - if(presets.get(sector.x, sector.y) != null){ - SectorPreset p = presets.get(sector.x, sector.y); - sector.missions.addAll(p.missions); - sector.x = (short)p.x; - sector.y = (short)p.y; - }else{ - generate(sector); - } - - sector.spawns = new Array<>(); - - for(Mission mission : sector.missions){ - sector.spawns.addAll(mission.getWaves(sector)); - } - - //set starter items - if(sector.difficulty > 12){ //now with titanium - sector.startingItems = Array.with(new ItemStack(Items.copper, 1900), new ItemStack(Items.lead, 500), new ItemStack(Items.densealloy, 470), new ItemStack(Items.silicon, 460), new ItemStack(Items.titanium, 230)); - }else if(sector.difficulty > 8){ //just more resources - sector.startingItems = Array.with(new ItemStack(Items.copper, 1500), new ItemStack(Items.lead, 400), new ItemStack(Items.densealloy, 340), new ItemStack(Items.silicon, 250)); - }else if(sector.difficulty > 5){ //now with silicon - sector.startingItems = Array.with(new ItemStack(Items.copper, 950), new ItemStack(Items.lead, 300), new ItemStack(Items.densealloy, 190), new ItemStack(Items.silicon, 140)); - }else if(sector.difficulty > 3){ //now with carbide - sector.startingItems = Array.with(new ItemStack(Items.copper, 700), new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 130)); - }else if(sector.difficulty > 2){ //more starter items for faster start - sector.startingItems = Array.with(new ItemStack(Items.copper, 400), new ItemStack(Items.lead, 100)); - }else{ //empty default - sector.startingItems = Array.with(); - } - } - - /**Generates a mission for a sector. This is deterministic and the same for each client.*/ - private void generate(Sector sector){ - - //50% chance to get a wave mission - if(Mathf.randomSeed(sector.getSeed() + 7) < 0.5){ - //recipe mission (maybe) - addRecipeMission(sector, 3); - sector.missions.add(new WaveMission(sector.difficulty*5 + Mathf.randomSeed(sector.getSeed(), 1, 4)*5)); - }else{ - //battle missions don't get recipes - sector.missions.add(new BattleMission()); - } - - //possibly add another recipe mission - addRecipeMission(sector, 11); - - Generation gen = new Generation(sector, null, sectorSize, sectorSize, null); - - Array points = new Array<>(); - for(Mission mission : sector.missions){ - points.addAll(mission.getSpawnPoints(gen)); - } - - GenResult result = new GenResult(); - - for(GridPoint2 point : new ArrayIterable<>(points)){ - world.generator.generateTile(result, sector.x, sector.y, point.x, point.y, true, null, null); - if(((Floor)result.floor).isLiquid || result.wall.solid){ - sector.missions.clear(); - break; - } - } - } - - private void addRecipeMission(Sector sector, int offset){ - //build list of locked recipes to add mission for obtaining it - if(Mathf.randomSeed(sector.getSeed() + offset) < 0.5){ - Array recipes = new Array<>(); - for(Recipe r : content.recipes()){ - if(r.result instanceof Wall || (r.visibility != RecipeVisibility.all) || r.cost < 10f) continue; - recipes.add(r); - } - float maxdiff = 8f; - recipes.sort((r1, r2) -> Float.compare(r1.cost, r2.cost)); - int end = (int)(Mathf.clamp(sector.difficulty / maxdiff + 0.25f) * (recipes.size - 1)); - int start = (int)(Mathf.clamp(sector.difficulty / maxdiff) * (recipes.size / 2f)); - - if(recipes.size > 0 && end > start){ - Recipe recipe = recipes.get(Mathf.randomSeed(sector.getSeed() + 10, start, end)); - sector.missions.addAll(Missions.blockRecipe(recipe.result)); - } - } - } - - private void createTexture(Sector sector){ - if(headless) return; //obviously not created or needed on server - - if(sector.texture != null){ - sector.texture.dispose(); - } - - executor.submit(() -> { - Pixmap pixmap = new Pixmap(sectorImageSize, sectorImageSize, Format.RGBA8888); - GenResult result = new GenResult(); - GenResult secResult = new GenResult(); - - for(int x = 0; x < pixmap.getWidth(); x++){ - for(int y = 0; y < pixmap.getHeight(); y++){ - int toX = x * sectorSize / sectorImageSize; - int toY = y * sectorSize / sectorImageSize; - - world.generator.generateTile(result, sector.x, sector.y, toX, toY, false, null, null); - world.generator.generateTile(secResult, sector.x, sector.y, toX, ((y+1) * sectorSize / sectorImageSize), false, null, null); - - int color = ColorMapper.colorFor(result.floor, result.wall, Team.none, result.elevation, secResult.elevation > result.elevation ? (byte)(1 << 6) : (byte)0); - pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, color); - } - } - - Gdx.app.postRunnable(() -> { - sector.texture = new Texture(pixmap); - pixmap.dispose(); - }); - - return null; - }); - } - - -} diff --git a/core/src/io/anuke/mindustry/maps/TutorialSector.java b/core/src/io/anuke/mindustry/maps/TutorialSector.java deleted file mode 100644 index b597cc9ec0..0000000000 --- a/core/src/io/anuke/mindustry/maps/TutorialSector.java +++ /dev/null @@ -1,125 +0,0 @@ -package io.anuke.mindustry.maps; - -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.blocks.CraftingBlocks; -import io.anuke.mindustry.content.blocks.ProductionBlocks; -import io.anuke.mindustry.content.blocks.StorageBlocks; -import io.anuke.mindustry.content.blocks.UnitBlocks; -import io.anuke.mindustry.maps.missions.BlockMission; -import io.anuke.mindustry.maps.missions.ItemMission; -import io.anuke.mindustry.maps.missions.Mission; -import io.anuke.mindustry.maps.missions.WaveMission; -import io.anuke.mindustry.world.Block; - -import static io.anuke.mindustry.Vars.*; - -/**Just a class for returning the list of tutorial missions.*/ -public class TutorialSector{ - private static int droneIndex; - - public static Array getMissions(){ -/* - Array missions = Array.with( - new ItemMission(Items.copper, 60).setMessage("$tutorial.begin"), - - new BlockMission(ProductionBlocks.mechanicalDrill).setMessage("$tutorial.drill"), - - new BlockMission(DistributionBlocks.conveyor).setShowComplete(false).setMessage("$tutorial.conveyor"), - - new ItemMission(Items.copper, 100).setMessage("$tutorial.morecopper"), - - new BlockMission(TurretBlocks.duo).setMessage("$tutorial.turret"), - / - //new BlockMission(ProductionBlocks.mechanicalDrill).setMessage("$tutorial.drillturret"), - - // Create a wave mission which spawns the core at 60, 60 rather than in the center of the map - new WaveMission(2, 60, 60).setMessage("$tutorial.waves"), - - new ItemMission(Items.lead, 150).setMessage("$tutorial.lead"), - new ItemMission(Items.copper, 250).setMessage("$tutorial.morecopper"), - - new BlockMission(CraftingBlocks.smelter).setMessage("$tutorial.smelter"), - - //drills for smelter - new BlockMission(ProductionBlocks.mechanicalDrill), - new BlockMission(ProductionBlocks.mechanicalDrill), - new BlockMission(ProductionBlocks.mechanicalDrill), - - new ItemMission(Items.densealloy, 20).setMessage("$tutorial.densealloy"), - - new MarkerBlockMission(CraftingBlocks.siliconsmelter).setMessage("$tutorial.siliconsmelter"), - - //coal line - new BlockMission(ProductionBlocks.mechanicalDrill).setMessage("$tutorial.silicondrill"), - - //sand line - new BlockMission(ProductionBlocks.mechanicalDrill), - new BlockMission(ProductionBlocks.mechanicalDrill), - - - new BlockMission(PowerBlocks.combustionGenerator).setMessage("$tutorial.generator"), - new BlockMission(ProductionBlocks.mechanicalDrill).setMessage("$tutorial.generatordrill"), - new BlockMission(PowerBlocks.powerNode).setMessage("$tutorial.node"), - //TODO fix positions - new ConditionMission(Bundles.get("text.mission.linknode"), () -> world.tile(54, 52).entity != null && world.tile(54, 52).entity.power != null && world.tile(54, 52).entity.power.amount >= 0.01f) - .setMessage("$tutorial.nodelink"), - - new ItemMission(Items.silicon, 70).setMessage("$tutorial.silicon"), - - new BlockMission(UnitBlocks.daggerFactory).setMessage("$tutorial.daggerfactory"), - - //power for dagger factory - new BlockMission(PowerBlocks.powerNode), - new BlockMission(PowerBlocks.powerNode), - - new UnitMission(UnitTypes.dagger).setMessage("$tutorial.dagger"), - new ActionMission(TutorialSector::generateBase), - new BattleMission(){ - public void generate(Generation gen){} //no - }.setMessage("$tutorial.battle") - ); - - //find drone marker mission - for(int i = 0; i < missions.size; i++){ - if(missions.get(i) instanceof MarkerBlockMission){ - droneIndex = i; - break; - } - }*/ - - return Array.with( - //intentionally unlocalized - new ItemMission(Items.copper, 50).setMessage("An updated tutorial will return next build.\nFor now, you'll have to deal with... this."), - - new BlockMission(ProductionBlocks.mechanicalDrill), - - new ItemMission(Items.copper, 100), - new ItemMission(Items.lead, 50), - - new BlockMission(CraftingBlocks.smelter), - new ItemMission(Items.densealloy, 10), - new WaveMission(5) - ); - } - - public static boolean supressDrone(){ - return world.getSector() != null && world.getSector().x == 0 && world.getSector().y == 0 && world.getSector().completedMissions < droneIndex; - } - - private static void generateBase(){ - int x = sectorSize - 50, y = sectorSize - 50; - world.setBlock(world.tile(x, y), StorageBlocks.core, waveTeam); - world.setBlock(world.tile(x - 1, y + 2), UnitBlocks.daggerFactory, waveTeam); - world.setBlock(world.tile(x - 1, y - 3), UnitBlocks.daggerFactory, waveTeam); - - //since placed() is not called here, add core manually - state.teams.get(waveTeam).cores.add(world.tile(x, y)); - } - - private static class MarkerBlockMission extends BlockMission{ - public MarkerBlockMission(Block block){ - super(block); - } - } -} diff --git a/core/src/io/anuke/mindustry/maps/generation/FortressGenerator.java b/core/src/io/anuke/mindustry/maps/generation/FortressGenerator.java deleted file mode 100644 index def5cf1e0c..0000000000 --- a/core/src/io/anuke/mindustry/maps/generation/FortressGenerator.java +++ /dev/null @@ -1,220 +0,0 @@ -package io.anuke.mindustry.maps.generation; - -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.IntIntMap; -import com.badlogic.gdx.utils.Predicate; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.Liquids; -import io.anuke.mindustry.content.blocks.*; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.type.AmmoType; -import io.anuke.mindustry.type.Recipe; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Edges; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.PowerBlock; -import io.anuke.mindustry.world.blocks.defense.Door; -import io.anuke.mindustry.world.blocks.defense.ForceProjector; -import io.anuke.mindustry.world.blocks.defense.MendProjector; -import io.anuke.mindustry.world.blocks.defense.Wall; -import io.anuke.mindustry.world.blocks.defense.turrets.ItemTurret; -import io.anuke.mindustry.world.blocks.defense.turrets.LiquidTurret; -import io.anuke.mindustry.world.blocks.defense.turrets.PowerTurret; -import io.anuke.mindustry.world.blocks.defense.turrets.Turret; -import io.anuke.mindustry.world.blocks.power.NuclearReactor; -import io.anuke.mindustry.world.blocks.power.PowerGenerator; -import io.anuke.mindustry.world.blocks.power.SolarGenerator; -import io.anuke.mindustry.world.blocks.storage.CoreBlock; -import io.anuke.mindustry.world.blocks.storage.StorageBlock; -import io.anuke.mindustry.world.blocks.units.UnitFactory; -import io.anuke.ucore.function.BiFunction; -import io.anuke.ucore.function.IntPositionConsumer; -import io.anuke.ucore.function.TriFunction; -import io.anuke.ucore.util.Geometry; -import io.anuke.ucore.util.Mathf; - -import static io.anuke.mindustry.Vars.content; - -public class FortressGenerator{ - private final static int coreDst = 60; - - private int enemyX, enemyY, coreX, coreY; - private Team team; - private Generation gen; - - public void generate(Generation gen, Team team, int coreX, int coreY, int enemyX, int enemyY){ - this.enemyX = enemyX; - this.enemyY = enemyY; - this.coreX = coreX; - this.coreY = coreY; - this.gen = gen; - this.team = team; - - gen(); - } - - void gen(){ - gen.setBlock(enemyX, enemyY, StorageBlocks.core, team); - gen.random.nextBoolean(); - - float difficultyScl = Mathf.clamp(gen.sector.difficulty / 20f + gen.random.range(0.25f), 0f, 0.9999f); - float dscl2 = Mathf.clamp(0.5f + gen.sector.difficulty / 20f + gen.random.range(0.1f), 0f, 1.5f); - - Array turrets = find(b -> b instanceof ItemTurret); - Array powerTurrets = find(b -> b instanceof PowerTurret); - Array walls = find(b -> b instanceof Wall && !(b instanceof Door) && b.size == 1); - - Block wall = walls.get((int)(difficultyScl * walls.size)); - - Turret powerTurret = (Turret) powerTurrets.get((int)(difficultyScl * powerTurrets.size)); - Turret bigTurret = (Turret) turrets.get(Mathf.clamp((int)((difficultyScl+0.2f+gen.random.range(0.2f)) * turrets.size), 0, turrets.size-1)); - Turret turret1 = (Turret) turrets.get(Mathf.clamp((int)((difficultyScl+gen.random.range(0.2f)) * turrets.size), 0, turrets.size-1)); - Turret turret2 = (Turret) turrets.get(Mathf.clamp((int)((difficultyScl+gen.random.range(0.2f)) * turrets.size), 0, turrets.size-1)); - float placeChance = difficultyScl*0.75f+0.25f; - - IntIntMap ammoPerType = new IntIntMap(); - for(Block turret : turrets){ - if(!(turret instanceof ItemTurret)) continue; - ItemTurret t = (ItemTurret)turret; - int size = t.getAmmoTypes().length; - ammoPerType.put(t.id, Mathf.clamp((int)(size* difficultyScl) + gen.random.range(1), 0, size - 1)); - } - - TriFunction, Boolean> checker = (current, block, pred) -> { - for(GridPoint2 point : Edges.getEdges(block.size)){ - Tile tile = gen.tile(current.x + point.x, current.y + point.y); - if(tile != null){ - tile = tile.target(); - if(tile.getTeamID() == team.ordinal() && pred.evaluate(tile)){ - return true; - } - } - } - return false; - }; - - BiFunction, IntPositionConsumer> seeder = (block, pred) -> (x, y) -> { - if(gen.canPlace(x, y, block) && ((block instanceof Wall && block.size == 1) || gen.random.chance(placeChance)) && checker.get(gen.tile(x, y), block, pred)){ - gen.setBlock(x, y, block, team); - } - }; - - BiFunction placer = (block, chance) -> (x, y) -> { - if(gen.canPlace(x, y, block) && gen.random.chance(chance)){ - gen.setBlock(x, y, block, team); - } - }; - - Array passes = Array.with( - //initial seeding solar panels - placer.get(PowerBlocks.largeSolarPanel, 0.001f), - - //extra seeding - seeder.get(PowerBlocks.solarPanel, tile -> tile.block() == PowerBlocks.largeSolarPanel && gen.random.chance(0.3)), - - //coal gens - seeder.get(PowerBlocks.combustionGenerator, tile -> tile.block() instanceof SolarGenerator && gen.random.chance(0.2)), - - //water extractors - seeder.get(ProductionBlocks.waterExtractor, tile -> tile.block() instanceof NuclearReactor && gen.random.chance(0.5)), - - //mend projectors - seeder.get(DefenseBlocks.mendProjector, tile -> tile.block() instanceof PowerGenerator && gen.random.chance(0.04)), - - //power turrets - seeder.get(powerTurret, tile -> tile.block() instanceof PowerGenerator && gen.random.chance(0.04)), - - //repair point - seeder.get(UnitBlocks.repairPoint, tile -> tile.block() instanceof PowerGenerator && gen.random.chance(0.1)), - - //turrets1 - seeder.get(turret1, tile -> tile.block() instanceof PowerBlock && gen.random.chance(0.22 - turret1.size*0.02)), - - //turrets2 - seeder.get(turret2, tile -> tile.block() instanceof PowerBlock && gen.random.chance(0.12 - turret2.size*0.02)), - - //shields - seeder.get(DefenseBlocks.forceProjector, tile -> (tile.block() instanceof CoreBlock || tile.block() instanceof UnitFactory) && gen.random.chance(0.2 * dscl2)), - - //unit pads (assorted) - seeder.get(UnitBlocks.daggerFactory, tile -> (tile.block() instanceof MendProjector || tile.block() instanceof ForceProjector) && gen.random.chance(0.3 * dscl2)), - - //unit pads (assorted) - seeder.get(UnitBlocks.wraithFactory, tile -> (tile.block() instanceof MendProjector || tile.block() instanceof ForceProjector) && gen.random.chance(0.3 * dscl2)), - - //unit pads (assorted) - seeder.get(UnitBlocks.titanFactory, tile -> (tile.block() instanceof MendProjector || tile.block() instanceof ForceProjector) && gen.random.chance(0.23 * dscl2)), - - //unit pads (assorted) - seeder.get(UnitBlocks.ghoulFactory, tile -> (tile.block() instanceof MendProjector || tile.block() instanceof ForceProjector) && gen.random.chance(0.23 * dscl2)), - - //vaults - seeder.get(StorageBlocks.vault, tile -> (tile.block() instanceof CoreBlock || tile.block() instanceof ForceProjector) && gen.random.chance(0.4)), - - //big turrets - seeder.get(bigTurret, tile -> tile.block() instanceof StorageBlock && gen.random.chance(0.65)), - - //walls - (x, y) -> { - if(!gen.canPlace(x, y, wall)) return; - - for(GridPoint2 point : Geometry.d8){ - Tile tile = gen.tile(x + point.x, y + point.y); - if(tile != null){ - tile = tile.target(); - if(tile.getTeamID() == team.ordinal() && !(tile.block() instanceof Wall) && !(tile.block() instanceof UnitFactory)){ - gen.setBlock(x, y, wall, team); - break; - } - } - } - }, - - //mines - placer.get(DefenseBlocks.shockMine, 0.02f * difficultyScl), - - //fill up turrets w/ ammo - (x, y) -> { - Tile tile = gen.tile(x, y); - Block block = tile.block(); - - if(block instanceof PowerTurret){ - tile.entity.power.amount = block.powerCapacity; - }else if(block instanceof ItemTurret){ - ItemTurret turret = (ItemTurret)block; - AmmoType[] type = turret.getAmmoTypes(); - int index = ammoPerType.get(block.id, 0); - block.handleStack(type[index].item, block.acceptStack(type[index].item, 1000, tile, null), tile, null); - }else if(block instanceof NuclearReactor){ - tile.entity.items.add(Items.thorium, 30); - }else if(block instanceof LiquidTurret){ - tile.entity.liquids.add(Liquids.water, tile.block().liquidCapacity); - } - } - ); - - for(IntPositionConsumer i : passes){ - for(int x = 0; x < gen.width; x++){ - for(int y = 0; y < gen.height; y++){ - if(Vector2.dst(x, y, enemyX, enemyY) > coreDst){ - continue; - } - - i.accept(x, y); - } - } - } - } - - Array find(Predicate pred){ - Array out = new Array<>(); - for(Block block : content.blocks()){ - if(pred.evaluate(block) && Recipe.getByResult(block) != null){ - out.add(block); - } - } - return out; - } -} diff --git a/core/src/io/anuke/mindustry/maps/generation/Generation.java b/core/src/io/anuke/mindustry/maps/generation/Generation.java deleted file mode 100644 index 3929a160ad..0000000000 --- a/core/src/io/anuke/mindustry/maps/generation/Generation.java +++ /dev/null @@ -1,106 +0,0 @@ -package io.anuke.mindustry.maps.generation; - -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.maps.Sector; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.production.Drill; -import io.anuke.ucore.util.Structs; -import io.anuke.ucore.util.SeedRandom; - -public class Generation{ - public final Sector sector; - public final Tile[][] tiles; - public final int width, height; - public final SeedRandom random; - - public Generation(Sector sector, Tile[][] tiles, int width, int height, SeedRandom random){ - this.sector = sector; - this.tiles = tiles; - this.width = width; - this.height = height; - this.random = random; - } - - Tile tile(int x, int y){ - if(!Structs.inBounds(x, y, tiles)){ - return null; - } - return tiles[x][y]; - } - - Item drillItem(int x, int y, Drill block){ - if(block.isMultiblock()){ - Item result = null; - int offsetx = -(block.size - 1) / 2; - int offsety = -(block.size - 1) / 2; - - for(int dx = 0; dx < block.size; dx++){ - for(int dy = 0; dy < block.size; dy++){ - int worldx = dx + offsetx + x; - int worldy = dy + offsety + y; - if(!Structs.inBounds(worldx, worldy, tiles)){ - return null; - } - - if(!block.isValid(tiles[worldx][worldy]) || tiles[worldx][worldy].floor().drops == null) continue; - - Item drop = tiles[worldx][worldy].floor().drops.item; - - if(result == null || drop.id < result.id){ - result = drop; - } - - } - } - return result; - }else{ - return tiles[x][y].floor().drops == null ? null : tiles[x][y].floor().drops.item; - } - } - - - - public boolean canPlace(int x, int y, Block block){ - if(block.isMultiblock()){ - int offsetx = -(block.size - 1) / 2; - int offsety = -(block.size - 1) / 2; - - for(int dx = 0; dx < block.size; dx++){ - for(int dy = 0; dy < block.size; dy++){ - int worldx = dx + offsetx + x; - int worldy = dy + offsety + y; - if(!Structs.inBounds(worldx, worldy, tiles) || !tiles[worldx][worldy].block().alwaysReplace || tiles[worldx][worldy].floor().isLiquid){ - return false; - } - } - } - return true; - }else{ - return tiles[x][y].block().alwaysReplace && !tiles[x][y].floor().isLiquid; - } - } - - public void setBlock(int x, int y, Block block, Team team){ - tiles[x][y].setBlock(block, team); - if(block.isMultiblock()){ - int offsetx = -(block.size - 1) / 2; - int offsety = -(block.size - 1) / 2; - - for(int dx = 0; dx < block.size; dx++){ - for(int dy = 0; dy < block.size; dy++){ - int worldx = dx + offsetx + x; - int worldy = dy + offsety + y; - if(!(worldx == x && worldy == y) && Structs.inBounds(worldx, worldy, tiles)){ - Tile toplace = tiles[worldx][worldy]; - if(toplace != null){ - toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety)); - toplace.setTeam(team); - } - } - } - } - } - } -} diff --git a/core/src/io/anuke/mindustry/maps/generation/WorldGenerator.java b/core/src/io/anuke/mindustry/maps/generation/WorldGenerator.java deleted file mode 100644 index 8686b6c80d..0000000000 --- a/core/src/io/anuke/mindustry/maps/generation/WorldGenerator.java +++ /dev/null @@ -1,434 +0,0 @@ -package io.anuke.mindustry.maps.generation; - -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.IntArray; -import com.badlogic.gdx.utils.ObjectMap; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.content.blocks.OreBlocks; -import io.anuke.mindustry.content.blocks.StorageBlocks; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.maps.MapTileData; -import io.anuke.mindustry.maps.MapTileData.TileDataMarker; -import io.anuke.mindustry.maps.Sector; -import io.anuke.mindustry.maps.missions.Mission; -import io.anuke.mindustry.type.Item; -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.ucore.noise.RidgedPerlin; -import io.anuke.ucore.noise.Simplex; -import io.anuke.ucore.util.Geometry; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.SeedRandom; -import io.anuke.ucore.util.Structs; - -import static io.anuke.mindustry.Vars.*; - - -public class WorldGenerator{ - private static final int baseSeed = 0; - private int oreIndex = 0; - - private Simplex sim = new Simplex(baseSeed); - private Simplex sim2 = new Simplex(baseSeed + 1); - private Simplex sim3 = new Simplex(baseSeed + 2); - private RidgedPerlin rid = new RidgedPerlin(baseSeed + 4, 1); - private SeedRandom random = new SeedRandom(baseSeed + 3); - - private GenResult result = new GenResult(); - private ObjectMap decoration; - - public WorldGenerator(){ - decoration = Structs.map( - Blocks.grass, Blocks.shrub, - Blocks.stone, Blocks.rock, - Blocks.ice, Blocks.icerock, - Blocks.snow, Blocks.icerock, - Blocks.blackstone, Blocks.blackrock - ); - } - - /**Loads raw map tile data into a Tile[][] array, setting up multiblocks, cliffs and ores. */ - public void loadTileData(Tile[][] tiles, MapTileData data, boolean genOres, int seed){ - 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); - - tiles[x][y] = new Tile(x, y, marker.floor, marker.wall == Blocks.blockpart.id ? 0 : marker.wall, marker.rotation, marker.team, marker.elevation); - } - } - - prepareTiles(tiles); - - generateOres(tiles, seed, genOres, null); - } - - /**'Prepares' a tile array by:
- * - setting up multiblocks
- * - updating cliff data
- * - removing ores on cliffs
- * Usually used before placing structures on a tile array.*/ - public void prepareTiles(Tile[][] tiles){ - - //find multiblocks - IntArray multiblocks = new IntArray(); - - 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().isMultiblock()){ - multiblocks.add(tile.pos()); - } - } - } - - //place multiblocks now - for(int i = 0; i < multiblocks.size; i++){ - int pos = multiblocks.get(i); - - int x = Pos.x(pos); - int y = Pos.y(pos); - - Block result = tiles[x][y].block(); - Team team = tiles[x][y].getTeam(); - - int offsetx = -(result.size - 1) / 2; - int offsety = -(result.size - 1) / 2; - - for(int dx = 0; dx < result.size; dx++){ - for(int dy = 0; dy < result.size; dy++){ - int worldx = dx + offsetx + x; - int worldy = dy + offsety + y; - if(!(worldx == x && worldy == y)){ - Tile toplace = world.tile(worldx, worldy); - if(toplace != null){ - toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety)); - toplace.setTeam(team); - } - } - } - } - } - - //update cliffs, occlusion data - for(int x = 0; x < tiles.length; x++){ - for(int y = 0; y < tiles[0].length; y++){ - Tile tile = tiles[x][y]; - - tile.updateOcclusion(); - - //fix things on cliffs that shouldn't be - if(tile.block() != Blocks.air && tile.hasCliffs() && !tile.block().isMultiblock() && tile.block() != Blocks.blockpart){ - tile.setBlock(Blocks.air); - } - - //remove ore veins on cliffs - if(tile.floor() instanceof OreBlock && tile.hasCliffs()){ - tile.setFloor(((OreBlock)tile.floor()).base); - } - } - } - } - - public void playRandomMap(){ - ui.loadLogic(() -> { - world.setSector(null); - logic.reset(); - - int sx = (short)Mathf.range(Short.MAX_VALUE/2); - int sy = (short)Mathf.range(Short.MAX_VALUE/2); - int width = 380; - int height = 380; - Array spawns = new Array<>(); - Array ores = Item.getAllOres(); - - if(state.mode.isPvp){ - int scaling = 10; - spawns.add(new GridPoint2(width/scaling, height/scaling)); - spawns.add(new GridPoint2(width - 1 - width/scaling, height - 1 - height/scaling)); - }else{ - spawns.add(new GridPoint2(width/2, height/2)); - } - - Tile[][] tiles = world.createTiles(width, height); - world.setMap(new Map("Generated Map", width, height)); - world.beginMapLoad(); - - for(int x = 0; x < width; x++){ - for(int y = 0; y < height; y++){ - generateTile(result, sx, sy, x, y, true, spawns, ores); - tiles[x][y] = new Tile(x, y, result.floor.id, result.wall.id, (byte)0, (byte)0, result.elevation); - } - } - - prepareTiles(tiles); - - for(int x = 0; x < width; x++){ - for(int y = 0; y < height; y++){ - Tile tile = tiles[x][y]; - - byte elevation = tile.getElevation(); - - for(GridPoint2 point : Geometry.d4){ - if(!Structs.inBounds(x + point.x, y + point.y, width, height)) continue; - if(tiles[x + point.x][y + point.y].getElevation() < elevation){ - - if(sim2.octaveNoise2D(1, 1, 1.0 / 8, x, y) > 0.8){ - tile.setElevation(-1); - } - break; - } - } - } - } - - world.setBlock(tiles[spawns.get(0).x][spawns.get(0).y], StorageBlocks.core, Team.blue); - - if(state.mode.isPvp){ - world.setBlock(tiles[spawns.get(1).x][spawns.get(1).y], StorageBlocks.core, Team.red); - } - - world.endMapLoad(); - logic.play(); - }); - } - - public void generateOres(Tile[][] tiles, long seed, boolean genOres, Array usedOres){ - oreIndex = 0; - - if(genOres){ - Array baseOres = Array.with( - new OreEntry(Items.copper, 0.3f, seed), - new OreEntry(Items.coal, 0.284f, seed), - new OreEntry(Items.lead, 0.28f, seed), - new OreEntry(Items.titanium, 0.27f, seed), - new OreEntry(Items.thorium, 0.26f, seed) - ); - - Array ores = new Array<>(); - if(usedOres == null){ - ores.addAll(baseOres); - }else{ - for(Item item : usedOres){ - ores.add(baseOres.select(entry -> entry.item == item).iterator().next()); - } - } - - for(int x = 0; x < tiles.length; x++){ - for(int y = 0; y < tiles[0].length; y++){ - - Tile tile = tiles[x][y]; - - if(!tile.floor().hasOres || tile.hasCliffs() || tile.block() != Blocks.air){ - continue; - } - - for(int i = ores.size - 1; i >= 0; i--){ - OreEntry entry = ores.get(i); - if(entry.noise.octaveNoise2D(1, 0.7, 1f / (4 + i * 2), x, y) / 4f + - Math.abs(0.5f - entry.noise.octaveNoise2D(2, 0.7, 1f / (50 + i * 2), x, y)) > 0.48f && - Math.abs(0.5f - entry.noise.octaveNoise2D(1, 1, 1f / (55 + i * 4), x, y)) > 0.22f){ - tile.setFloor((Floor) OreBlocks.get(tile.floor(), entry.item)); - break; - } - } - } - } - } - } - - public void generateMap(Tile[][] tiles, Sector sector){ - int width = tiles.length, height = tiles[0].length; - SeedRandom rnd = new SeedRandom(sector.getSeed()); - Generation gena = new Generation(sector, tiles, tiles.length, tiles[0].length, rnd); - Array spawnpoints = sector.currentMission().getSpawnPoints(gena); - Array ores = world.sectors.getOres(sector.x, sector.y); - - for(int x = 0; x < width; x++){ - for(int y = 0; y < height; y++){ - GenResult result = generateTile(this.result, sector.x, sector.y, x, y, true, spawnpoints, ores); - Tile tile = new Tile(x, y, result.floor.id, result.wall.id, (byte)0, (byte)0, result.elevation); - tiles[x][y] = tile; - } - } - - for(int x = 0; x < width; x++){ - for(int y = 0; y < height; y++){ - Tile tile = tiles[x][y]; - - byte elevation = tile.getElevation(); - - for(GridPoint2 point : Geometry.d4){ - if(!Structs.inBounds(x + point.x, y + point.y, width, height)) continue; - if(tiles[x + point.x][y + point.y].getElevation() < elevation){ - - if(sim2.octaveNoise2D(1, 1, 1.0 / 8, x, y) > 0.8){ - tile.setElevation(-1); - } - break; - } - } - } - } - - for(int x = 0; x < tiles.length; x++){ - for(int y = 0; y < tiles[0].length; y++){ - Tile tile = tiles[x][y]; - - tile.updateOcclusion(); - } - } - - Generation gen = new Generation(sector, tiles, tiles.length, tiles[0].length, random); - - for(Mission mission : sector.missions){ - mission.generate(gen); - } - - prepareTiles(tiles); - } - - public GenResult generateTile(int sectorX, int sectorY, int localX, int localY){ - return generateTile(sectorX, sectorY, localX, localY, true); - } - - public GenResult generateTile(int sectorX, int sectorY, int localX, int localY, boolean detailed){ - return generateTile(result, sectorX, sectorY, localX, localY, detailed, null, null); - } - - /** - * Gets the generation result from a specific sector at specific coordinates. - * @param result where to put the generation results - * @param sectorX X of the sector in terms of sector coordinates - * @param sectorY Y of the sector in terms of sector coordinates - * @param localX X in terms of local sector tile coordinates - * @param localY Y in terms of local sector tile coordinates - * @param detailed whether the tile result is 'detailed' (e.g. previews should not be detailed) - * @param spawnpoints list of player spawnpoints, can be null - * @return the GenResult passed in with its values modified - */ - public GenResult generateTile(GenResult result, int sectorX, int sectorY, int localX, int localY, boolean detailed, Array spawnpoints, Array ores){ - int x = sectorX * sectorSize + localX + Short.MAX_VALUE; - int y = sectorY * sectorSize + localY + Short.MAX_VALUE; - - Block floor; - Block wall = Blocks.air; - - double ridge = rid.getValue(x, y, 1f / 400f); - double iceridge = rid.getValue(x+99999, y, 1f / 300f) + sim3.octaveNoise2D(2, 1f, 1f/14f, x, y)/11f; - double elevation = elevationOf(x, y, detailed); - double temp = - + sim3.octaveNoise2D(detailed ? 12 : 9, 0.6, 1f / 1100f, x - 120, y); - double lake = sim2.octaveNoise2D(1, 1, 1f / 110f, x, y); - - elevation -= Math.pow(lake + 0.15, 5); - - int lerpDst = 20; - lerpDst *= lerpDst; - float minDst = Float.MAX_VALUE; - - if(detailed && spawnpoints != null){ - for(GridPoint2 p : spawnpoints){ - float dst = Vector2.dst2(p.x, p.y, localX, localY); - minDst = Math.min(minDst, dst); - - if(dst < lerpDst){ - float targetElevation = Math.max(0.86f, (float)elevationOf(sectorX * sectorSize + p.x + Short.MAX_VALUE, sectorY * sectorSize + p.y + Short.MAX_VALUE, true)); - elevation = Mathf.lerp((float)elevation, targetElevation, Mathf.clamp(1.5f*(1f-(dst / lerpDst)))); - } - } - } - - if(elevation < 0.7){ - floor = Blocks.deepwater; - }else if(elevation < 0.79){ - floor = Blocks.water; - }else if(elevation < 0.85){ - floor = Blocks.sand; - }else if (elevation < 2.5 && temp > 0.5){ - floor = Blocks.sand; - }else if(temp < 0.42){ - floor = Blocks.snow; - }else if(temp < 0.5){ - floor = Blocks.stone; - }else if(temp < 0.6){ - floor = Blocks.grass; - }else if(temp + ridge/2f < 0.8 || elevation < 1.3){ - floor = Blocks.blackstone; - - if(iceridge > 0.25 && minDst > lerpDst/1.5f){ - elevation ++; - } - }else if(minDst > lerpDst/1.5f){ - floor = Blocks.lava; - }else{ - floor = Blocks.blackstone; - } - - if(elevation > 3.3 && iceridge > 0.25 && temp < 0.6f){ - elevation ++; - floor = Blocks.ice; - } - - if(((Floor)floor).liquidDrop != null){ - elevation = 0; - } - - if(detailed && wall == Blocks.air && decoration.containsKey(floor) && random.chance(0.03)){ - wall = decoration.get(floor); - } - - if(ores != null && ((Floor) floor).hasOres){ - int offsetX = x - 4, offsetY = y + 23; - for(int i = ores.size - 1; i >= 0; i--){ - Item entry = ores.get(i); - if(Math.abs(0.5f - sim.octaveNoise2D(2, 0.7, 1f / (50 + i * 2), offsetX, offsetY)) > 0.23f && - Math.abs(0.5f - sim2.octaveNoise2D(1, 1, 1f / (40 + i * 4), offsetX, offsetY)) > 0.32f){ - floor = OreBlocks.get(floor, entry); - break; - } - } - } - - result.wall = wall; - result.floor = floor; - result.elevation = (byte) Math.max(elevation, 0); - return result; - } - - double elevationOf(int x, int y, boolean detailed){ - double ridge = rid.getValue(x, y, 1f / 400f); - return sim.octaveNoise2D(detailed ? 7 : 5, 0.62, 1f / 800, x, y) * 6.1 - 1 - ridge; - } - - public static class GenResult{ - public Block floor, wall; - public byte elevation; - } - - public class OreEntry{ - final float frequency; - final Item item; - final Simplex noise; - final RidgedPerlin ridge; - final int index; - - OreEntry(Item item, float frequency, long seed){ - this.frequency = frequency; - this.item = item; - this.noise = new Simplex(seed + oreIndex); - this.ridge = new RidgedPerlin((int)(seed + oreIndex), 2); - this.index = oreIndex++; - } - } -} diff --git a/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java b/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java new file mode 100644 index 0000000000..e348bca08b --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java @@ -0,0 +1,58 @@ +package io.anuke.mindustry.maps.generators; + +import io.anuke.arc.collection.Array; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.noise.Simplex; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.Floor; +import io.anuke.mindustry.world.blocks.OreBlock; + +public class BasicGenerator extends RandomGenerator{ + private Array ores; + private Simplex sim = new Simplex(); + private Simplex sim2 = new Simplex(); + + public BasicGenerator(int width, int height, Item... ores){ + super(width, height); + this.ores = Array.with(ores); + } + + @Override + public void generate(Tile[][] tiles){ + int seed = Mathf.random(99999999); + sim.setSeed(seed); + sim2.setSeed(seed + 1); + super.generate(tiles); + } + + @Override + public void generate(int x, int y){ + floor = Blocks.stone; + + if(ores != null && ((Floor) floor).hasOres){ + int offsetX = x - 4, offsetY = y + 23; + for(int i = ores.size - 1; i >= 0; i--){ + Item entry = ores.get(i); + if(Math.abs(0.5f - sim.octaveNoise2D(2, 0.7, 1f / (50 + i * 2), offsetX, offsetY)) > 0.23f && + Math.abs(0.5f - sim2.octaveNoise2D(1, 1, 1f / (40 + i * 4), offsetX, offsetY)) > 0.32f){ + floor = OreBlock.get(floor, entry); + break; + } + } + } + + //rock outcrops + double rocks = sim.octaveNoise2D(3, 0.7, 1f / 70f, x, y); + double edgeDist = Math.min(x, Math.min(y, Math.min(Math.abs(x - (width - 1)), Math.abs(y - (height - 1))))); + double transition = 8; + if(edgeDist < transition){ + rocks += (transition - edgeDist) / transition / 1.5; + } + + if(rocks > 0.64){ + block = Blocks.rocks; + } + } +} diff --git a/core/src/io/anuke/mindustry/maps/generators/Generator.java b/core/src/io/anuke/mindustry/maps/generators/Generator.java new file mode 100644 index 0000000000..dac0b08093 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/generators/Generator.java @@ -0,0 +1,20 @@ +package io.anuke.mindustry.maps.generators; + +import io.anuke.mindustry.world.Tile; + +public abstract class Generator{ + public int width, height; + + public Generator(int width, int height){ + this.width = width; + this.height = height; + } + + public Generator(){} + + public void init(){ + + } + + public abstract void generate(Tile[][] tiles); +} diff --git a/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java b/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java new file mode 100644 index 0000000000..3a85a83aac --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java @@ -0,0 +1,200 @@ +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.game.Team; +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.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.*; + +public class MapGenerator extends Generator{ + private Map map; + private String mapName; + private Array decorations = new Array<>(); + /**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 Block coreBlock; + + public MapGenerator(String mapName){ + this.mapName = mapName; + } + + public MapGenerator(String mapName, int enemySpawns){ + this.mapName = mapName; + this.enemySpawns = enemySpawns; + } + + public MapGenerator core(Block block){ + this.coreBlock = block; + return this; + } + + 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(){ + map = world.maps.loadInternalMap(mapName); + width = map.meta.width; + height = map.meta.height; + } + + @Override + public void generate(Tile[][] tiles){ + MapTileData data = MapIO.readTileData(map, true); + + data.position(0, 0); + TileDataMarker marker = data.newDataMarker(); + Array players = new Array<>(); + Array coreTypes = new Array<>(); + Array enemies = new Array<>(); + + for(int y = 0; y < data.height(); y++){ + for(int x = 0; x < data.width(); x++){ + data.read(marker); + + if(content.block(marker.wall) instanceof CoreBlock){ + players.add(new Point2(x, y)); + coreTypes.add(content.block(marker.wall)); + marker.wall = 0; + } + + if(enemySpawns != -1 && content.block(marker.wall) == Blocks.spawn){ + enemies.add(new Point2(x, y)); + marker.wall = 0; + } + + tiles[x][y] = new Tile(x, y, marker.floor, marker.wall == Blocks.part.id ? 0 : marker.wall, marker.rotation, marker.team); + } + } + + Simplex simplex = new Simplex(Mathf.random(99999)); + + 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((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.getTeam() == Team.none && tile.block() instanceof StorageBlock){ + for(ItemStack stack : storageDrops){ + if(Mathf.chance(0.3)){ + tile.entity.items.add(stack.item, Mathf.random(stack.amount)); + } + } + } + } + } + + 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); + } + } + } + } + } + } + + Point2 core = players.random(); + if(core == null){ + throw new IllegalArgumentException("All zone maps must have a core."); + } + + tiles[core.x][core.y].setBlock(coreBlock == null ? coreTypes.get(players.indexOf(core)) : coreBlock, defaultTeam); + + 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 new file mode 100644 index 0000000000..9692f0dc54 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/generators/RandomGenerator.java @@ -0,0 +1,34 @@ +package io.anuke.mindustry.maps.generators; + +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; + +public abstract class RandomGenerator extends Generator{ + protected Block floor; + protected Block block; + + public RandomGenerator(int width, int height){ + super(width, height); + } + + @Override + public void generate(Tile[][] tiles){ + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + floor = Blocks.air; + block = Blocks.air; + generate(x, y); + tiles[x][y] = new Tile(x, y, floor.id, block.id); + } + } + + tiles[width/2][height/2].setBlock(Blocks.coreShard, Team.blue); + tiles[width/2][height/2 - 6].setBlock(Blocks.launchPad, Team.blue); + } + + /**Sets {@link #floor} and {@link #block} to the correct values as output. + * Before this method is called, both are set to {@link Blocks#air} as defaults.*/ + public abstract void generate(int x, int y); +} diff --git a/core/src/io/anuke/mindustry/maps/missions/ActionMission.java b/core/src/io/anuke/mindustry/maps/missions/ActionMission.java deleted file mode 100644 index 55710aa1ff..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/ActionMission.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import io.anuke.ucore.util.Bundles; - -import static io.anuke.mindustry.Vars.threads; - -/**A mission which simply runs a single action and is completed instantly.*/ -public class ActionMission extends Mission{ - protected Runnable runner; - - public ActionMission(Runnable runner){ - this.runner = runner; - } - - public ActionMission(){ - } - - @Override - public void onComplete(){ - threads.run(runner); - } - - @Override - public boolean isComplete(){ - return true; - } - - @Override - public String displayString(){ - return Bundles.get("text.loading"); - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/BattleMission.java b/core/src/io/anuke/mindustry/maps/missions/BattleMission.java deleted file mode 100644 index e1f5bc5614..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/BattleMission.java +++ /dev/null @@ -1,77 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.game.GameMode; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.maps.generation.FortressGenerator; -import io.anuke.mindustry.maps.generation.Generation; -import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.util.Bundles; - -import static io.anuke.mindustry.Vars.*; - -public class BattleMission extends MissionWithStartingCore{ - final int spacing = 30; - public static final int defaultXCorePos = 50; - public static final int defaultYCorePos = 50; - - /** Creates a battle mission with the player core being at (@defaultXCorePos, @defaultYCorePos) */ - public BattleMission(){ - this(defaultXCorePos, defaultYCorePos); - } - - /** - * Creates a wave survival with the player core being at a custom location. - * @param xCorePos The X coordinate of the custom core position. - * @param yCorePos The Y coordinate of the custom core position. - */ - public BattleMission(int xCorePos, int yCorePos){ - super(xCorePos, yCorePos); - } - - @Override - public String getIcon(){ - return "icon-mission-battle"; - } - - @Override - public GameMode getMode(){ - return GameMode.attack; - } - - @Override - public String displayString(){ - return Bundles.get("text.mission.battle"); - } - - @Override - public Array getSpawnPoints(Generation gen){ - return Array.with(new GridPoint2(50, 50), new GridPoint2(gen.width - 1 - spacing, gen.height - 1 - spacing)); - } - - @Override - public void generate(Generation gen){ - generateCoreAtFirstSpawnPoint(gen, defaultTeam); - - if(state.teams.get(defaultTeam).cores.size == 0){ - return; - } - - Tile core = state.teams.get(defaultTeam).cores.first(); - int enx = gen.width - 1 - spacing; - int eny = gen.height - 1 - spacing; - new FortressGenerator().generate(gen, Team.red, core.x, core.y, enx, eny); - } - - @Override - public boolean isComplete(){ - for(Team team : Vars.state.teams.enemiesOf(Vars.defaultTeam)){ - if(Vars.state.teams.isActive(team)){ - return false; - } - } - return true; - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/BlockLocMission.java b/core/src/io/anuke/mindustry/maps/missions/BlockLocMission.java deleted file mode 100644 index 00a596e81a..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/BlockLocMission.java +++ /dev/null @@ -1,72 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.world.Block; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Mathf; - -import static io.anuke.mindustry.Vars.players; -import static io.anuke.mindustry.Vars.tilesize; -import static io.anuke.mindustry.Vars.world; - -public class BlockLocMission extends Mission{ - private final Block block; - private final int x, y, rotation; - - public BlockLocMission(Block block, int x, int y, int rotation){ - this.block = block; - this.x = x; - this.y = y; - this.rotation = rotation; - } - - public BlockLocMission(Block block, int x, int y){ - this.block = block; - this.x = x; - this.y = y; - this.rotation = 0; - } - - @Override - public void drawOverlay(){ - Lines.stroke(2f); - - Draw.color(Palette.accentBack); - Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset() - 1f, block.size * tilesize/2f + 1f+ Mathf.absin(Timers.time(), 6f, 2f)); - - Draw.color(Palette.accent); - Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset(), block.size * tilesize/2f + 1f+ Mathf.absin(Timers.time(), 6f, 2f)); - - - if(block.rotate){ - Draw.colorl(0.4f); - Draw.rect("icon-arrow", x * tilesize + block.offset(), y * tilesize + block.offset() - 1f, rotation*90); - Draw.colorl(0.6f); - Draw.rect("icon-arrow", x * tilesize + block.offset(), y * tilesize + block.offset(), rotation*90); - } - - float rot = players[0].angleTo(x * tilesize + block.offset(), y * tilesize + block.offset()); - float len = 12f; - - Draw.color(Palette.accentBack); - Draw.rect("icon-arrow", players[0].x + Angles.trnsx(rot, len), players[0].y + Angles.trnsy(rot, len), rot); - Draw.color(Palette.accent); - Draw.rect("icon-arrow", players[0].x + Angles.trnsx(rot, len), players[0].y + Angles.trnsy(rot, len) + 1f, rot); - - Draw.reset(); - } - - @Override - public boolean isComplete(){ - return world.tile(x, y).block() == block && (!block.rotate || world.tile(x,y).getRotation() == rotation); - } - - @Override - public String displayString(){ - return Bundles.format("text.mission.block", block.formalName); - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/BlockMission.java b/core/src/io/anuke/mindustry/maps/missions/BlockMission.java deleted file mode 100644 index 4ddf80efe1..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/BlockMission.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import io.anuke.mindustry.type.Recipe; -import io.anuke.mindustry.world.Block; - -/**A mission in which the player must place a block somewhere.*/ -public class BlockMission extends ContentMission{ - - public BlockMission(Block block) { - super(Recipe.getByResult(block)); - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/CommandMission.java b/core/src/io/anuke/mindustry/maps/missions/CommandMission.java deleted file mode 100644 index a25f5e04f5..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/CommandMission.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.entities.units.BaseUnit; -import io.anuke.mindustry.entities.units.UnitCommand; -import io.anuke.ucore.util.Bundles; - -public class CommandMission extends Mission{ - private final UnitCommand command; - - public CommandMission(UnitCommand command){ - this.command = command; - } - - @Override - public boolean isComplete(){ - for(BaseUnit unit : Vars.unitGroups[Vars.defaultTeam.ordinal()].all()){ - if(unit.isCommanded() && unit.getCommand() == command){ - return true; - } - } - return false; - } - - @Override - public String displayString(){ - return Bundles.format("text.mission.command", command.localized()); - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/ConditionMission.java b/core/src/io/anuke/mindustry/maps/missions/ConditionMission.java deleted file mode 100644 index 68e141633b..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/ConditionMission.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import io.anuke.ucore.function.BooleanProvider; - -public class ConditionMission extends Mission{ - private final BooleanProvider complete; - private final String display; - - public ConditionMission(String display, BooleanProvider complete){ - this.complete = complete; - this.display = display; - } - - @Override - public boolean isComplete(){ - return complete.get(); - } - - @Override - public String displayString(){ - return display; - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/ContentMission.java b/core/src/io/anuke/mindustry/maps/missions/ContentMission.java deleted file mode 100644 index c4a85afd26..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/ContentMission.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.ucore.util.Bundles; - -public class ContentMission extends Mission { - private final UnlockableContent content; - private boolean done; - - public ContentMission(UnlockableContent content) { - this.content = content; - } - - @Override - public void onContentUsed(UnlockableContent content) { - if(content == this.content){ - done = true; - } - } - - @Override - public boolean isComplete() { - return done; - } - - @Override - public void reset() { - done = false; - } - - @Override - public String displayString() { - return Bundles.format("text.mission.create", content.localizedName()); - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/ItemMission.java b/core/src/io/anuke/mindustry/maps/missions/ItemMission.java deleted file mode 100644 index a65eb4bc31..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/ItemMission.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.util.Bundles; - -import static io.anuke.mindustry.Vars.state; - -/**A mission that is completed when the player obtains items in their core.*/ -public class ItemMission extends Mission{ - private final Item item; - private final int amount; - - public ItemMission(Item item, int amount){ - this.item = item; - this.amount = amount; - } - - @Override - public boolean isComplete(){ - for(Tile tile : state.teams.get(Vars.defaultTeam).cores){ - if(tile.entity.items.has(item, amount)){ - return true; - } - } - return false; - } - - @Override - public String displayString(){ - TileEntity core = Vars.players[0].getClosestCore(); - if(core == null) return "imminent doom"; - return Bundles.format("text.mission.resource", item.localizedName(), core.items.get(item), amount); - } - - @Override - public String menuDisplayString(){ - return Bundles.format("text.mission.resource.menu", item.localizedName(), amount); - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/LineBlockMission.java b/core/src/io/anuke/mindustry/maps/missions/LineBlockMission.java deleted file mode 100644 index 918788b55c..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/LineBlockMission.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import com.badlogic.gdx.math.Bresenham2; -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.world.Block; - -public class LineBlockMission extends Mission{ - private Array points = new Array<>(); - private int completeIndex; - - public LineBlockMission(Block block, int x1, int y1, int x2, int y2, int rotation){ - Array points = new Bresenham2().line(x1, y1, x2, y2); - for(GridPoint2 point : points){ - this.points.add(new BlockLocMission(block, point.x, point.y, rotation)); - } - } - - @Override - public boolean isComplete(){ - while(completeIndex < points.size && points.get(completeIndex).isComplete()){ - completeIndex ++; - } - return completeIndex >= points.size; - } - - @Override - public void drawOverlay(){ - if(completeIndex < points.size){ - points.get(completeIndex).drawOverlay(); - } - } - - @Override - public void reset(){ - completeIndex = 0; - } - - @Override - public String displayString(){ - if(completeIndex < points.size){ - return points.get(completeIndex).displayString(); - } - return points.first().displayString(); - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/MechMission.java b/core/src/io/anuke/mindustry/maps/missions/MechMission.java deleted file mode 100644 index f59710a698..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/MechMission.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.type.Mech; -import io.anuke.ucore.util.Bundles; - -public class MechMission extends Mission{ - private final Mech mech; - - public MechMission(Mech mech){ - this.mech = mech; - } - - @Override - public boolean isComplete(){ - for(Player player : Vars.playerGroup.all()){ - if(player.mech == mech){ - return true; - } - } - return false; - } - - @Override - public String displayString(){ - return Bundles.format("text.mission.mech", mech.localizedName()); - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/Mission.java b/core/src/io/anuke/mindustry/maps/missions/Mission.java deleted file mode 100644 index eba443be21..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/Mission.java +++ /dev/null @@ -1,101 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.game.GameMode; -import io.anuke.mindustry.game.SpawnGroup; -import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.mindustry.maps.Sector; -import io.anuke.mindustry.maps.generation.Generation; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Bundles; - -import static io.anuke.mindustry.Vars.*; - -public abstract class Mission{ - private String extraMessage; - private boolean showComplete = true; - - public abstract boolean isComplete(); - - /**Returns the string that is displayed in-game near the menu.*/ - public abstract String displayString(); - - /**Returns the info string displayed in the sector dialog (menu)*/ - public String menuDisplayString(){ - return displayString(); - } - - public String getIcon(){ - return "icon-mission-defense"; - } - - public GameMode getMode(){ - return GameMode.attack; - } - - /**Sets the message displayed on mission begin. Returns this mission for chaining.*/ - public Mission setMessage(String message){ - this.extraMessage = message; - return this; - } - - public Mission setShowComplete(boolean complete){ - this.showComplete = complete; - return this; - } - - /**Called when a specified piece of content is 'used' by a block.*/ - public void onContentUsed(UnlockableContent content){ - - } - - /**Draw mission overlay.*/ - public void drawOverlay(){ - - } - - public void update(){ - - } - - public void reset(){ - - } - - /**Shows the unique sector message.*/ - public void showMessage(){ - if(!headless && extraMessage != null){ - ui.hudfrag.showTextDialog(extraMessage); - } - } - - public boolean hasMessage(){ - return extraMessage != null; - } - - public void onBegin(){ - Timers.runTask(60f, this::showMessage); - } - - public void onComplete(){ - if(showComplete && !headless){ - threads.runGraphics(() -> ui.hudfrag.showToast("[LIGHT_GRAY]"+menuDisplayString() + ":\n" + Bundles.get("text.mission.complete"))); - } - } - - public void display(Table table){ - table.add(displayString()); - } - - public Array getWaves(Sector sector){ - return new Array<>(); - } - - public Array getSpawnPoints(Generation gen){ - return Array.with(); - } - - public void generate(Generation gen){} -} diff --git a/core/src/io/anuke/mindustry/maps/missions/MissionWithStartingCore.java b/core/src/io/anuke/mindustry/maps/missions/MissionWithStartingCore.java deleted file mode 100644 index a134891329..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/MissionWithStartingCore.java +++ /dev/null @@ -1,68 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.content.blocks.StorageBlocks; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.maps.generation.Generation; -import io.anuke.mindustry.world.Tile; - -import static io.anuke.mindustry.Vars.state; - -public abstract class MissionWithStartingCore extends Mission{ - /** Stores a custom starting location for the core, or null if the default calculation (map center) shall be used. */ - private final GridPoint2 customStartingPoint; - - /** Default constructor. Missions created this way will have a player starting core in the center of the map. */ - MissionWithStartingCore(){ - this.customStartingPoint = null; - } - - /** - * Creates a mission with a core on a non-default location. - * @param xCorePos The x coordinate of the custom core position. - * @param yCorePos The y coordinate of the custom core position. - */ - MissionWithStartingCore(int xCorePos, int yCorePos){ - this.customStartingPoint = new GridPoint2(xCorePos, yCorePos); - } - - /** - * Generates a player core based on generation parameters. - * @param gen The generation parameters which provide the map size. - * @param team The team to generate the core for. - */ - public void generateCoreAtFirstSpawnPoint(Generation gen, Team team){ - Array spawnPoints = getSpawnPoints(gen); - if(spawnPoints == null || spawnPoints.size == 0){ - throw new IllegalArgumentException("A MissionWithStartingCore subclass did not provide a spawn point in getSpawnPoints(). However, at least one point must always be provided."); - } - - Tile startingCoreTile = gen.tiles[spawnPoints.first().x][spawnPoints.first().y]; - startingCoreTile.setBlock(StorageBlocks.core); - startingCoreTile.setTeam(team); - state.teams.get(team).cores.add(startingCoreTile); - - //makes sure there's a flat area around core - for(int dx = -2; dx <= 2; dx++){ - for(int dy = -2; dy <= 2; dy++){ - gen.tiles[startingCoreTile.x + dx][startingCoreTile.y + dy].setElevation(startingCoreTile.getElevation()); - } - } - } - - /** - * Retrieves the spawn point in the center of the map or at a custom location which was provided through the constructor. - * @param gen The generation parameters which provide the map size. - * @return The center of the map or a custom location. - * @implNote Must return an array with at least one entry. - */ - @Override - public Array getSpawnPoints(Generation gen){ - if(this.customStartingPoint == null){ - return Array.with(new GridPoint2(gen.width / 2, gen.height / 2)); - }else{ - return Array.with(this.customStartingPoint); - } - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/Missions.java b/core/src/io/anuke/mindustry/maps/missions/Missions.java deleted file mode 100644 index bc0b139185..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/Missions.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Recipe; -import io.anuke.mindustry.world.Block; - -public class Missions{ - - /**Returns an array of missions to obtain the items needed to make this block. - * This array includes a mission to place this block.*/ - public static Array blockRecipe(Block block){ - Recipe recipe = Recipe.getByResult(block); - - Array out = new Array<>(); - for(ItemStack stack : recipe.requirements){ - out.add(new ItemMission(stack.item, stack.amount)); - } - out.add(new BlockMission(block)); - return out; - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/UnitMission.java b/core/src/io/anuke/mindustry/maps/missions/UnitMission.java deleted file mode 100644 index efe097a687..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/UnitMission.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.entities.units.BaseUnit; -import io.anuke.mindustry.entities.units.UnitType; -import io.anuke.ucore.util.Bundles; - -public class UnitMission extends Mission{ - private final UnitType type; - - public UnitMission(UnitType type){ - this.type = type; - } - - @Override - public boolean isComplete(){ - for(BaseUnit unit : Vars.unitGroups[Vars.defaultTeam.ordinal()].all()){ - if(unit.getType() == type){ - return true; - } - } - return false; - } - - @Override - public String displayString(){ - return Bundles.format("text.mission.unit", type.localizedName()); - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/VictoryMission.java b/core/src/io/anuke/mindustry/maps/missions/VictoryMission.java deleted file mode 100644 index 46b6153dff..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/VictoryMission.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import io.anuke.mindustry.game.GameMode; -import io.anuke.ucore.scene.ui.layout.Table; - -public class VictoryMission extends Mission{ - @Override - public boolean isComplete(){ - return false; - } - - @Override - public String displayString(){ - return "none"; - } - - @Override - public GameMode getMode(){ - return GameMode.victory; - } - - @Override - public void display(Table table){ - - } -} diff --git a/core/src/io/anuke/mindustry/maps/missions/WaveMission.java b/core/src/io/anuke/mindustry/maps/missions/WaveMission.java deleted file mode 100644 index e31120af00..0000000000 --- a/core/src/io/anuke/mindustry/maps/missions/WaveMission.java +++ /dev/null @@ -1,85 +0,0 @@ -package io.anuke.mindustry.maps.missions; - -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.game.GameMode; -import io.anuke.mindustry.game.SpawnGroup; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.game.Waves; -import io.anuke.mindustry.maps.Sector; -import io.anuke.mindustry.maps.generation.Generation; -import io.anuke.ucore.util.Bundles; - -import static io.anuke.mindustry.Vars.*; - -public class WaveMission extends MissionWithStartingCore{ - private final int target; - - /** - * Creates a wave survival mission with the player core being in the center of the map. - * @param target The number of waves to be survived. - */ - public WaveMission(int target){ - super(); - this.target = target; - } - - /** - * Creates a wave survival with the player core being at a custom location. - * @param target The number of waves to be survived. - * @param xCorePos The X coordinate of the custom core position. - * @param yCorePos The Y coordinate of the custom core position. - */ - public WaveMission(int target, int xCorePos, int yCorePos){ - super(xCorePos, yCorePos); - this.target = target; - } - - @Override - public Array getWaves(Sector sector){ - return Waves.getSpawns(); - } - - @Override - public void generate(Generation gen){ - generateCoreAtFirstSpawnPoint(gen, Team.blue); - } - - @Override - public void onBegin(){ - super.onBegin(); - - world.pathfinder.activateTeamPath(waveTeam); - } - - @Override - public GameMode getMode(){ - return GameMode.waves; - } - - @Override - public String displayString(){ - return state.wave > target ? - Bundles.format( - state.enemies() > 1 ? - "text.mission.wave.enemies" : - "text.mission.wave.enemy", target, target, state.enemies()) : - Bundles.format("text.mission.wave", state.wave, target, (int)(state.wavetime/60)); - } - - @Override - public String menuDisplayString(){ - return Bundles.format("text.mission.wave.menu", target); - } - - @Override - public void update(){ - if(state.wave > target){ - state.mode = GameMode.attack; - } - } - - @Override - public boolean isComplete(){ - return state.wave > target && state.enemies() == 0; - } -} diff --git a/core/src/io/anuke/mindustry/net/Administration.java b/core/src/io/anuke/mindustry/net/Administration.java index 1f7d2288af..52de0350f5 100644 --- a/core/src/io/anuke/mindustry/net/Administration.java +++ b/core/src/io/anuke/mindustry/net/Administration.java @@ -1,10 +1,10 @@ package io.anuke.mindustry.net; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.ObjectMap; -import com.badlogic.gdx.utils.ObjectSet; import io.anuke.annotations.Annotations.Serialize; -import io.anuke.ucore.core.Settings; +import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.collection.ObjectSet; import static io.anuke.mindustry.Vars.headless; @@ -15,7 +15,7 @@ public class Administration{ private Array bannedIPs = new Array<>(); public Administration(){ - Settings.defaultList( + Core.settings.defaults( "strict", true ); @@ -23,21 +23,21 @@ public class Administration{ } public void setStrict(boolean on){ - Settings.putBool("strict", on); - Settings.save(); + Core.settings.put("strict", on); + Core.settings.save(); } public boolean getStrict(){ - return Settings.getBool("strict"); + return Core.settings.getBool("strict"); } public boolean allowsCustomClients(){ - return Settings.getBool("allow-custom", !headless); + return Core.settings.getBool("allow-custom", !headless); } public void setCustomClients(boolean allowed){ - Settings.putBool("allow-custom", allowed); - Settings.save(); + Core.settings.put("allow-custom", allowed); + Core.settings.save(); } /**Call when a player joins to update their information here.*/ @@ -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.*/ @@ -256,15 +256,15 @@ public class Administration{ } public void save(){ - Settings.putObject("player-info", playerInfo); - Settings.putObject("banned-ips", bannedIPs); - Settings.save(); + Core.settings.putObject("player-info", playerInfo); + Core.settings.putObject("banned-ips", bannedIPs); + Core.settings.save(); } @SuppressWarnings("unchecked") private void load(){ - playerInfo = Settings.getObject("player-info", ObjectMap.class, ObjectMap::new); - bannedIPs = Settings.getObject("banned-ips", Array.class, Array::new); + playerInfo = Core.settings.getObject("player-info", ObjectMap.class, ObjectMap::new); + bannedIPs = Core.settings.getObject("banned-ips", Array.class, Array::new); } @Serialize diff --git a/core/src/io/anuke/mindustry/net/Host.java b/core/src/io/anuke/mindustry/net/Host.java index 261c60fc7e..77a281d8ec 100644 --- a/core/src/io/anuke/mindustry/net/Host.java +++ b/core/src/io/anuke/mindustry/net/Host.java @@ -1,7 +1,5 @@ package io.anuke.mindustry.net; -import io.anuke.mindustry.game.GameMode; - public class Host{ public final String name; public final String address; @@ -10,9 +8,8 @@ public class Host{ public final int players; public final int version; public final String versionType; - public final GameMode mode; - public Host(String name, String address, String mapname, int wave, int players, int version, String versionType, GameMode mode){ + public Host(String name, String address, String mapname, int wave, int players, int version, String versionType){ this.name = name; this.address = address; this.players = players; @@ -20,6 +17,5 @@ public class Host{ this.wave = wave; this.version = version; this.versionType = versionType; - this.mode = mode; } } diff --git a/core/src/io/anuke/mindustry/net/Interpolator.java b/core/src/io/anuke/mindustry/net/Interpolator.java index b184875d88..d4590ecec3 100644 --- a/core/src/io/anuke/mindustry/net/Interpolator.java +++ b/core/src/io/anuke/mindustry/net/Interpolator.java @@ -1,9 +1,8 @@ package io.anuke.mindustry.net; - -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.TimeUtils; -import io.anuke.ucore.util.Mathf; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.util.Time; public class Interpolator{ //used for movement @@ -16,10 +15,10 @@ public class Interpolator{ public Vector2 pos = new Vector2(); public float[] values = {}; - public void read(float cx, float cy, float x, float y, long sent, float... target1ds){ - if(lastUpdated != 0) updateSpacing = TimeUtils.timeSinceMillis(lastUpdated); + public void read(float cx, float cy, float x, float y, float... target1ds){ + if(lastUpdated != 0) updateSpacing = Time.timeSinceMillis(lastUpdated); - lastUpdated = TimeUtils.millis(); + lastUpdated = Time.millis(); targets = target1ds; last.set(cx, cy); @@ -46,10 +45,10 @@ public class Interpolator{ }*/ if(lastUpdated != 0 && updateSpacing != 0){ - float timeSinceUpdate = TimeUtils.timeSinceMillis(lastUpdated); + float timeSinceUpdate = Time.timeSinceMillis(lastUpdated); float alpha = Math.min(timeSinceUpdate / updateSpacing, 2f); - Mathf.lerp2(pos.set(last), target, alpha); + pos.set(last).lerpPast(target, alpha); if(values.length != targets.length){ values = new float[targets.length]; diff --git a/core/src/io/anuke/mindustry/net/Net.java b/core/src/io/anuke/mindustry/net/Net.java index 13548a2872..e1a337c6d5 100644 --- a/core/src/io/anuke/mindustry/net/Net.java +++ b/core/src/io/anuke/mindustry/net/Net.java @@ -1,27 +1,28 @@ package io.anuke.mindustry.net; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Net.HttpRequest; -import com.badlogic.gdx.Net.HttpResponse; -import com.badlogic.gdx.Net.HttpResponseListener; -import com.badlogic.gdx.net.HttpRequestBuilder; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.IntMap; -import com.badlogic.gdx.utils.ObjectMap; +import io.anuke.arc.Core; +import io.anuke.arc.Net.HttpRequest; +import io.anuke.arc.Net.HttpResponse; +import io.anuke.arc.Net.HttpResponseListener; +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.IntMap; +import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.function.BiConsumer; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.net.HttpRequestBuilder; +import io.anuke.arc.util.Log; +import io.anuke.arc.util.Time; +import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Packets.KickReason; import io.anuke.mindustry.net.Packets.StreamBegin; import io.anuke.mindustry.net.Packets.StreamChunk; import io.anuke.mindustry.net.Streamable.StreamBuilder; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.function.BiConsumer; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.Pooling; import java.io.IOException; +import java.nio.BufferOverflowException; +import java.nio.BufferUnderflowException; import static io.anuke.mindustry.Vars.*; @@ -59,21 +60,23 @@ public class Net{ String error = t.getMessage() == null ? "" : t.getMessage().toLowerCase(); String type = t.getClass().toString().toLowerCase(); - if(error.equals("mismatch")){ - error = Bundles.get("text.error.mismatch"); + if(e instanceof BufferUnderflowException || e instanceof BufferOverflowException){ + error = Core.bundle.get("error.io"); + }else if(error.equals("mismatch")){ + error = Core.bundle.get("error.mismatch"); }else if(error.contains("port out of range") || error.contains("invalid argument") || (error.contains("invalid") && error.contains("address"))){ - error = Bundles.get("text.error.invalidaddress"); + error = Core.bundle.get("error.invalidaddress"); }else if(error.contains("connection refused") || error.contains("route to host") || type.contains("unknownhost")){ - error = Bundles.get("text.error.unreachable"); + error = Core.bundle.get("error.unreachable"); }else if(type.contains("timeout")){ - error = Bundles.get("text.error.timedout"); + error = Core.bundle.get("error.timedout"); }else if(error.equals("alreadyconnected")){ - error = Bundles.get("text.error.alreadyconnected"); + error = Core.bundle.get("error.alreadyconnected"); }else if(!error.isEmpty()){ - error = Bundles.get("text.error.any"); + error = Core.bundle.get("error.any"); } - ui.showText("", Bundles.format("text.connectfail", error)); + ui.showText("", Core.bundle.format("connectfail", error)); ui.loadfrag.hide(); if(Net.client()){ @@ -126,7 +129,7 @@ public class Net{ active = true; server = true; - Timers.runTask(60f, Platform.instance::updateRPC); + Time.runTask(60f, Platform.instance::updateRPC); } /** @@ -262,12 +265,12 @@ public class Net{ if(clientLoaded || ((object instanceof Packet) && ((Packet) object).isImportant())){ if(clientListeners.get(object.getClass()) != null) clientListeners.get(object.getClass()).accept(object); - Pooling.free(object); + Pools.free(object); }else if(!((object instanceof Packet) && ((Packet) object).isUnimportant())){ packetQueue.add(object); Log.info("Queuing packet {0}", object); }else{ - Pooling.free(object); + Pools.free(object); } }else{ Log.err("Unhandled packet type: '{0}'!", object); @@ -282,7 +285,7 @@ public class Net{ if(serverListeners.get(object.getClass()) != null){ if(serverListeners.get(object.getClass()) != null) serverListeners.get(object.getClass()).accept(connection, object); - Pooling.free(object); + Pools.free(object); }else{ Log.err("Unhandled packet type: '{0}'!", object.getClass()); } @@ -347,7 +350,7 @@ public class Net{ HttpRequest req = new HttpRequestBuilder().newRequest() .method(method).url(url).content(body).build(); - Gdx.net.sendHttpRequest(req, new HttpResponseListener(){ + Core.net.sendHttpRequest(req, new HttpResponseListener(){ @Override public void handleHttpResponse(HttpResponse httpResponse){ listener.accept(httpResponse.getResultAsString()); 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 f8a9a5ddbe..04375e7a15 100644 --- a/core/src/io/anuke/mindustry/net/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -1,23 +1,19 @@ package io.anuke.mindustry.net; -import com.badlogic.gdx.utils.ObjectMap; -import com.badlogic.gdx.utils.ObjectMap.Entry; -import com.badlogic.gdx.utils.TimeUtils; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.game.GameMode; +import io.anuke.arc.Core; +import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.collection.ObjectMap.Entry; +import io.anuke.mindustry.entities.Entities; +import io.anuke.arc.util.Time; +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; import io.anuke.mindustry.game.Version; +import io.anuke.mindustry.gen.Serialization; +import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.maps.MapMeta; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.BlockPart; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.Entities; -import io.anuke.ucore.util.Bits; import java.io.*; import java.nio.ByteBuffer; @@ -31,10 +27,8 @@ public class NetworkIO{ try(DataOutputStream stream = new DataOutputStream(os)){ //--GENERAL STATE-- - stream.writeByte(state.mode.ordinal()); //gamemode + Serialization.writeRules(stream, state.rules); stream.writeUTF(world.getMap().name); //map name - stream.writeInt(world.getSector() == null ? invalidSector : world.getSector().pos()); //sector ID - stream.writeInt(world.getSector() == null ? 0 : world.getSector().completedMissions); //write tags ObjectMap tags = world.getMap().meta.tags; @@ -50,71 +44,8 @@ public class NetworkIO{ stream.writeInt(player.id); player.write(stream); - //--MAP DATA-- - - //map size - stream.writeShort(world.width()); - stream.writeShort(world.height()); - - for(int i = 0; i < world.width() * world.height(); i++){ - Tile tile = world.tile(i % world.width(), i / world.width()); - - stream.writeByte(tile.getFloorID()); - stream.writeByte(tile.getBlockID()); - stream.writeByte(tile.getElevation()); - - if(tile.block() instanceof BlockPart){ - stream.writeByte(tile.link); - }else if(tile.entity != null){ - stream.writeByte(Bits.packByte(tile.getTeamID(), tile.getRotation())); //team + rotation - stream.writeShort((short) tile.entity.health); //health - - if(tile.entity.items != null) tile.entity.items.write(stream); - if(tile.entity.power != null) tile.entity.power.write(stream); - if(tile.entity.liquids != null) tile.entity.liquids.write(stream); - if(tile.entity.cons != null) tile.entity.cons.write(stream); - - tile.entity.writeConfig(stream); - tile.entity.write(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 || nextTile.getElevation() != tile.getElevation()){ - break; - } - - consecutives++; - } - - stream.writeByte(consecutives); - i += consecutives; - } - } - - //write visibility, length-run encoded - for(int i = 0; i < world.width() * world.height(); i++){ - Tile tile = world.tile(i % world.width(), i / world.width());; - boolean discovered = tile.discovered(); - - int consecutives = 0; - - for(int j = i + 1; j < world.width() * world.height() && consecutives < 32767*2-1; j++){ - Tile nextTile = world.tile(j % world.width(), j / world.width());; - - if(nextTile.discovered() != discovered){ - break; - } - - consecutives++; - } - - stream.writeBoolean(discovered); - stream.writeShort(consecutives); - i += consecutives; - } + world.spawner.write(stream); + SaveIO.getSaveWriter().writeMap(stream); stream.write(Team.all.length); @@ -134,13 +65,6 @@ public class NetworkIO{ } } - //now write a snapshot. - player.con.viewX = world.width() * tilesize/2f; - player.con.viewY = world.height() * tilesize/2f; - player.con.viewWidth = world.width() * tilesize; - player.con.viewHeight = world.height() * tilesize; - netServer.writeSnapshot(player, stream); - }catch(IOException e){ throw new RuntimeException(e); } @@ -151,21 +75,11 @@ public class NetworkIO{ Player player = players[0]; try(DataInputStream stream = new DataInputStream(is)){ - Timers.clear(); + Time.clear(); //general state - byte mode = stream.readByte(); + state.rules = Serialization.readRules(stream); String map = stream.readUTF(); - int sector = stream.readInt(); - int missions = stream.readInt(); - - if(sector != invalidSector){ - world.sectors.createSector(Bits.getLeftShort(sector), Bits.getRightShort(sector)); - world.setSector(world.sectors.get(sector)); - world.getSector().completedMissions = missions; - }else{ - world.setSector(null); - } ObjectMap tags = new ObjectMap<>(); @@ -181,84 +95,20 @@ public class NetworkIO{ state.wave = wave; state.wavetime = wavetime; - state.mode = GameMode.values()[mode]; Entities.clear(); int id = stream.readInt(); player.resetNoAdd(); - player.read(stream, TimeUtils.millis()); + player.read(stream); player.resetID(id); player.add(); world.beginMapLoad(); //map - int width = stream.readShort(); - int height = stream.readShort(); - - Map currentMap = new Map(map, new MapMeta(0, new ObjectMap<>(), width, height, null), true, () -> null); - currentMap.meta.tags.clear(); - currentMap.meta.tags.putAll(tags); - world.setMap(currentMap); - - Tile[][] tiles = world.createTiles(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(); - byte elevation = stream.readByte(); - - Tile tile = new Tile(x, y, floorid, wallid); - tile.setElevation(elevation); - - if(wallid == Blocks.blockpart.id){ - tile.link = stream.readByte(); - }else if(tile.entity != null){ - byte tr = stream.readByte(); - short health = stream.readShort(); - - byte team = Bits.getLeftByte(tr); - byte rotation = Bits.getRightByte(tr); - - tile.setTeam(Team.all[team]); - tile.entity.health = health; - tile.setRotation(rotation); - - if(tile.entity.items != null) tile.entity.items.read(stream); - if(tile.entity.power != null) tile.entity.power.read(stream); - if(tile.entity.liquids != null) tile.entity.liquids.read(stream); - if(tile.entity.cons != null) tile.entity.cons.read(stream); - - tile.entity.readConfig(stream); - tile.entity.read(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); - newTile.setElevation(elevation); - tiles[newx][newy] = newTile; - } - - i += consecutives; - } - - tiles[x][y] = tile; - } - - for(int i = 0; i < width * height; i++){ - boolean discovered = stream.readBoolean(); - int consecutives = stream.readUnsignedShort(); - if(discovered){ - for(int j = i + 1; j < i + 1 + consecutives; j++){ - int newx = j % width, newy = j / width; - tiles[newx][newy].setVisibility((byte) 1); - } - } - i += consecutives; - } + world.spawner.read(stream); + SaveIO.getSaveWriter().readMap(stream); + world.setMap(new Map(map, 0, 0)); state.teams = new Teams(); @@ -281,15 +131,12 @@ public class NetworkIO{ } if(team == players[0].getTeam() && cores > 0){ - Core.camera.position.set(state.teams.get(team).cores.first().drawx(), state.teams.get(team).cores.first().drawy(), 0); + Core.camera.position.set(state.teams.get(team).cores.first().drawx(), state.teams.get(team).cores.first().drawy()); } } world.endMapLoad(); - //read raw snapshot - netClient.readSnapshot(stream); - }catch(IOException e){ throw new RuntimeException(e); } @@ -317,7 +164,6 @@ public class NetworkIO{ 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)state.mode.ordinal()); return buffer; } @@ -340,8 +186,7 @@ public class NetworkIO{ byte[] tb = new byte[tlength]; buffer.get(tb); String vertype = new String(tb, StandardCharsets.UTF_8); - GameMode mode = GameMode.values()[buffer.get()]; - return new Host(host, hostAddress, map, wave, players, version, vertype, mode); + return new Host(host, hostAddress, map, wave, players, version, vertype); } } diff --git a/core/src/io/anuke/mindustry/net/Packet.java b/core/src/io/anuke/mindustry/net/Packet.java index ef34666dbb..f5feb59c94 100644 --- a/core/src/io/anuke/mindustry/net/Packet.java +++ b/core/src/io/anuke/mindustry/net/Packet.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.net; -import com.badlogic.gdx.utils.Pool.Poolable; +import io.anuke.arc.util.pooling.Pool.Poolable; import java.nio.ByteBuffer; diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index 1d3ef834e7..381df947c5 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -1,9 +1,9 @@ package io.anuke.mindustry.net; -import com.badlogic.gdx.utils.Base64Coder; +import io.anuke.arc.Core; +import io.anuke.arc.util.serialization.Base64Coder; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.io.TypeIO; -import io.anuke.ucore.util.Bundles; import java.nio.ByteBuffer; @@ -14,7 +14,7 @@ public class Packets{ public enum KickReason{ kick, clientOutdated, serverOutdated, banned, gameover(true), recentKick, - nameInUse, idInUse, nameEmpty, customClient, sectorComplete, serverClose; + nameInUse, idInUse, nameEmpty, customClient, serverClose; public final boolean quiet; @@ -28,11 +28,11 @@ public class Packets{ @Override public String toString(){ - return Bundles.get("text.server.kicked." + name()); + return Core.bundle.get("server.kicked." + name()); } public String extraText(){ - return Bundles.getOrNull("text.server.kicked." + name() + ".text"); + return Core.bundle.getOrNull("server.kicked." + name() + ".text"); } } diff --git a/core/src/io/anuke/mindustry/net/Registrator.java b/core/src/io/anuke/mindustry/net/Registrator.java index 1fd12cca26..6430a686a9 100644 --- a/core/src/io/anuke/mindustry/net/Registrator.java +++ b/core/src/io/anuke/mindustry/net/Registrator.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.net; -import com.badlogic.gdx.utils.ObjectIntMap; +import io.anuke.arc.collection.ObjectIntMap; +import io.anuke.arc.function.Supplier; import io.anuke.mindustry.net.Packets.*; -import io.anuke.ucore.function.Supplier; public class Registrator{ private static ClassEntry[] classes = { 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/AmmoEntry.java b/core/src/io/anuke/mindustry/type/AmmoEntry.java deleted file mode 100644 index d92c7963e5..0000000000 --- a/core/src/io/anuke/mindustry/type/AmmoEntry.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.anuke.mindustry.type; - -/**Used to store ammo amounts in turrets.*/ -public class AmmoEntry{ - public AmmoType type; - public int amount; - - public AmmoEntry(AmmoType type, int amount){ - this.type = type; - this.amount = amount; - } -} diff --git a/core/src/io/anuke/mindustry/type/AmmoType.java b/core/src/io/anuke/mindustry/type/AmmoType.java deleted file mode 100644 index 2244a09a1d..0000000000 --- a/core/src/io/anuke/mindustry/type/AmmoType.java +++ /dev/null @@ -1,75 +0,0 @@ -package io.anuke.mindustry.type; - -import io.anuke.mindustry.content.fx.Fx; -import io.anuke.mindustry.entities.bullet.BulletType; -import io.anuke.mindustry.game.Content; -import io.anuke.ucore.core.Effects.Effect; - -public class AmmoType extends Content { - /**The item used. Always null if liquid isn't.*/ - public final Item item; - /**The liquid used. Always null if item isn't.*/ - public final Liquid liquid; - /**The resulting bullet. Never null.*/ - public final BulletType bullet; - /** - * For item ammo, this is amount given per ammo item. - * For liquid ammo, this is amount used per shot. - */ - public final float quantityMultiplier; - /**Reload speed multiplier.*/ - public float reloadMultiplier = 1f; - /**Bullet recoil strength.*/ - public float recoil = 0f; - /**Additional inaccuracy in degrees.*/ - public float inaccuracy; - /**Effect created when shooting.*/ - public Effect shootEffect = Fx.none; - /**Extra smoke effect created when shooting.*/ - public Effect smokeEffect = Fx.none; - /**Range. Use a value < 0 to calculate from bullet.*/ - public float range = -1f; - - /** - * Creates an AmmoType with no liquid or item. Used for power-based ammo. - */ - public AmmoType(BulletType result){ - this.item = null; - this.liquid = null; - this.bullet = result; - this.quantityMultiplier = 1f; - this.reloadMultiplier = 1f; - } - - /** - * Creates an AmmoType with an item. - */ - public AmmoType(Item item, BulletType result, float multiplier){ - this.item = item; - this.liquid = null; - this.bullet = result; - this.quantityMultiplier = multiplier; - } - - /** - * Creates an AmmoType with a liquid. - */ - public AmmoType(Liquid liquid, BulletType result, float multiplier){ - this.item = null; - this.liquid = liquid; - this.bullet = result; - this.quantityMultiplier = multiplier; - } - - /** - * Returns maximum distance the bullet this ammo type has can travel. - */ - public float getRange(){ - return range < 0 ? bullet.speed * bullet.lifetime : range; - } - - @Override - public ContentType getContentType(){ - return ContentType.ammo; - } -} diff --git a/core/src/io/anuke/mindustry/type/ContentType.java b/core/src/io/anuke/mindustry/type/ContentType.java index 80ae68252a..30189125ee 100644 --- a/core/src/io/anuke/mindustry/type/ContentType.java +++ b/core/src/io/anuke/mindustry/type/ContentType.java @@ -3,15 +3,13 @@ package io.anuke.mindustry.type; /**Do not rearrange, ever!*/ public enum ContentType { item, - recipe, block, mech, bullet, liquid, - weapon, status, unit, - ammo, weather, - effect + effect, + zone } diff --git a/core/src/io/anuke/mindustry/type/Item.java b/core/src/io/anuke/mindustry/type/Item.java index 62e91451ed..f655e65b6e 100644 --- a/core/src/io/anuke/mindustry/type/Item.java +++ b/core/src/io/anuke/mindustry/type/Item.java @@ -1,23 +1,22 @@ package io.anuke.mindustry.type; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.utils.Array; +import io.anuke.arc.Core; +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.graphics.Pal; import io.anuke.mindustry.ui.ContentDisplay; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.Strings; 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; @@ -27,12 +26,10 @@ 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*/ - public Color flameColor = Palette.darkFlame.cpy(); + /**the burning color of this item. TODO unused; implement*/ + public Color flameColor = Pal.darkFlame.cpy(); /** * base material cost of this item, used for calculating place times * 1 cost = 1 tick added to build time @@ -46,16 +43,24 @@ public class Item extends UnlockableContent implements Comparable{ public Item(String name, Color color){ this.name = name; this.color = color; - this.description = Bundles.getOrNull("item." + this.name + ".description"); + this.description = Core.bundle.getOrNull("item." + this.name + ".description"); - if(!Bundles.has("item." + this.name + ".name")){ + 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('-', '_'))); + Log.err("item." + this.name + ".name = " + Strings.capitalize(name.replace('-', '_'))); } } public void load(){ - this.region = Draw.region("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 @@ -70,12 +75,12 @@ public class Item extends UnlockableContent implements Comparable{ @Override public String localizedName(){ - return Bundles.get("item." + this.name + ".name"); + return Core.bundle.get("item." + this.name + ".name"); } @Override public TextureRegion getContentIcon(){ - return region; + return icon(Icon.large); } @Override @@ -98,11 +103,21 @@ public class Item extends UnlockableContent implements Comparable{ return ContentType.item; } - public static Array getAllOres(){ - Array arr = new Array<>(); - for(Item item : Vars.content.items()){ - if(item.genOre) arr.add(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; } - return arr; + } + + /**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 5714050602..5b77275b36 100644 --- a/core/src/io/anuke/mindustry/type/ItemStack.java +++ b/core/src/io/anuke/mindustry/type/ItemStack.java @@ -1,10 +1,10 @@ package io.anuke.mindustry.type; public class ItemStack{ - public io.anuke.mindustry.type.Item item; + public Item item; public int amount; - public ItemStack(io.anuke.mindustry.type.Item item, int amount){ + public ItemStack(Item item, int amount){ this.item = item; this.amount = amount; } @@ -12,4 +12,20 @@ public class ItemStack{ public boolean equals(ItemStack other){ return other != null && other.item == item && other.amount == amount; } + + public static ItemStack[] with(Object... items){ + ItemStack[] stacks = new ItemStack[items.length/2]; + for(int i = 0; i < items.length; i+= 2){ + stacks[i/2] = new ItemStack((Item)items[i], (Integer)items[i + 1]); + } + return stacks; + } + + @Override + public String toString(){ + return "ItemStack{" + + "item=" + item + + ", amount=" + amount + + '}'; + } } diff --git a/core/src/io/anuke/mindustry/type/ItemType.java b/core/src/io/anuke/mindustry/type/ItemType.java index fb676443bb..320e0d0fce 100644 --- a/core/src/io/anuke/mindustry/type/ItemType.java +++ b/core/src/io/anuke/mindustry/type/ItemType.java @@ -1,16 +1,8 @@ package io.anuke.mindustry.type; public enum ItemType{ - /** - * Not used for anything besides crafting inside blocks. - */ + /**Not used for anything besides crafting inside blocks.*/ resource, - /** - * Can be used for constructing blocks. Only materials are accepted into the core. - */ - material, - /** - * Only used as ammo for turrets. - */ - ammo + /**Can be used for constructing blocks. Only materials are accepted into the core.*/ + material } diff --git a/core/src/io/anuke/mindustry/type/Liquid.java b/core/src/io/anuke/mindustry/type/Liquid.java index 3dbb52fbe9..378a6f4779 100644 --- a/core/src/io/anuke/mindustry/type/Liquid.java +++ b/core/src/io/anuke/mindustry/type/Liquid.java @@ -1,13 +1,12 @@ package io.anuke.mindustry.type; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; +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.StatusEffects; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.ui.ContentDisplay; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Bundles; public class Liquid extends UnlockableContent{ public final Color color; @@ -30,13 +29,13 @@ public class Liquid extends UnlockableContent{ public StatusEffect effect = StatusEffects.none; /**Pump tier. Controls which pumps can use this liquid.*/ public int tier; - /**Displayed icon.*/ + /**Displayed icon. TODO fix it by removing autogen, draw icons manually*/ public TextureRegion iconRegion; public Liquid(String name, Color color){ this.name = name; this.color = new Color(color); - this.description = Bundles.getOrNull("liquid." + name + ".description"); + this.description = Core.bundle.getOrNull("liquid." + name + ".description"); } public boolean canExtinguish(){ @@ -45,7 +44,7 @@ public class Liquid extends UnlockableContent{ @Override public void load(){ - iconRegion = Draw.region("liquid-icon-" + name); + iconRegion = Core.atlas.find("liquid-" + name); } @Override @@ -55,7 +54,7 @@ public class Liquid extends UnlockableContent{ @Override public String localizedName(){ - return Bundles.get("liquid." + this.name + ".name"); + return Core.bundle.get("liquid." + this.name + ".name"); } @Override diff --git a/core/src/io/anuke/mindustry/type/Mech.java b/core/src/io/anuke/mindustry/type/Mech.java index 744bf11be1..bfe9842a62 100644 --- a/core/src/io/anuke/mindustry/type/Mech.java +++ b/core/src/io/anuke/mindustry/type/Mech.java @@ -1,15 +1,13 @@ package io.anuke.mindustry.type; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import io.anuke.mindustry.content.Weapons; -import io.anuke.mindustry.entities.Player; +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.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; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Bundles; public class Mech extends UnlockableContent{ public final String name; @@ -22,33 +20,31 @@ 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){ this.flying = flying; this.name = name; - this.description = Bundles.get("mech." + name + ".description"); + this.description = Core.bundle.get("mech." + name + ".description"); } public String localizedName(){ - return Bundles.get("mech." + name + ".name"); + return Core.bundle.get("mech." + name + ".name"); } public void updateAlt(Player player){} @@ -93,13 +89,14 @@ public class Mech extends UnlockableContent{ @Override public void load(){ + weapon.load(); if(!flying){ - legRegion = Draw.region(name + "-leg"); - baseRegion = Draw.region(name + "-base"); + legRegion = Core.atlas.find(name + "-leg"); + baseRegion = Core.atlas.find(name + "-base"); } - region = Draw.region(name); - iconRegion = Draw.region("mech-icon-" + name); + region = Core.atlas.find(name); + iconRegion = Core.atlas.find("mech-icon-" + name); } @Override diff --git a/core/src/io/anuke/mindustry/type/Recipe.java b/core/src/io/anuke/mindustry/type/Recipe.java deleted file mode 100644 index daa84726e7..0000000000 --- a/core/src/io/anuke/mindustry/type/Recipe.java +++ /dev/null @@ -1,192 +0,0 @@ -package io.anuke.mindustry.type; - -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.ObjectMap; -import com.badlogic.gdx.utils.OrderedMap; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.game.GameMode; -import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.mindustry.ui.ContentDisplay; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.ContentStatValue; -import io.anuke.mindustry.world.meta.StatValue; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.Strings; - -import java.util.Arrays; - -import static io.anuke.mindustry.Vars.*; - -public class Recipe extends UnlockableContent{ - private static ObjectMap recipeMap = new ObjectMap<>(); - private static Array returnArray = new Array<>(); - - public final Block result; - public final ItemStack[] requirements; - public final Category category; - public final float cost; - - public RecipeVisibility visibility = RecipeVisibility.all; - //the only gamemode in which the recipe shows up - public GameMode mode; - public boolean hidden; - public boolean alwaysUnlocked; - - private UnlockableContent[] dependencies; - private Block[] blockDependencies; - - public Recipe(Category category, Block result, ItemStack... requirements){ - this.result = result; - this.requirements = requirements; - this.category = category; - - Arrays.sort(requirements, (a, b) -> Integer.compare(a.item.id, b.item.id)); - - float timeToPlace = 0f; - for(ItemStack stack : requirements){ - timeToPlace += stack.amount * stack.item.cost; - } - - this.cost = timeToPlace; - - recipeMap.put(result, this); - } - - /**Returns all non-hidden recipes in a category.*/ - public static Array getByCategory(Category category){ - returnArray.clear(); - for(Recipe recipe : content.recipes()){ - if(recipe.category == category && recipe.visibility.shown() && (recipe.mode == state.mode || recipe.mode == null)){ - returnArray.add(recipe); - } - } - return returnArray; - } - - public static Recipe getByResult(Block block){ - return recipeMap.get(block); - } - - public Recipe setVisible(RecipeVisibility visibility){ - this.visibility = visibility; - return this; - } - - public Recipe setMode(GameMode mode){ - this.mode = mode; - return this; - } - - public Recipe setHidden(boolean hidden){ - this.hidden = hidden; - return this; - } - - public Recipe setAlwaysUnlocked(boolean unlocked){ - this.alwaysUnlocked = unlocked; - return this; - } - - @Override - public boolean alwaysUnlocked(){ - return alwaysUnlocked; - } - - @Override - public boolean isHidden(){ - return !visibility.shown() || hidden; - } - - @Override - public void displayInfo(Table table){ - ContentDisplay.displayRecipe(table, this); - } - - @Override - public String localizedName(){ - return result.formalName; - } - - @Override - public TextureRegion getContentIcon(){ - return result.getEditorIcon(); - } - - @Override - public void init(){ - if(!Bundles.has("block." + result.name + ".name")){ - Log.err("WARNING: Recipe block '{0}' does not have a formal name defined. Add the following to bundle.properties:", result.name); - Log.err("block.{0}.name={1}", result.name, Strings.capitalize(result.name.replace('-', '_'))); - }/*else if(result.fullDescription == null){ - Log.err("WARNING: Recipe block '{0}' does not have a description defined.", result.name); - }*/ - } - - @Override - public String getContentName(){ - return result.name; - } - - @Override - public ContentType getContentType(){ - return ContentType.recipe; - } - - @Override - public void onUnlock(){ - for(OrderedMap map : result.stats.toMap().values()){ - for(StatValue value : map.values()){ - if(value instanceof ContentStatValue){ - ContentStatValue stat = (ContentStatValue) value; - UnlockableContent[] content = stat.getValueContent(); - for(UnlockableContent c : content){ - control.unlocks.unlockContent(c); - } - } - } - } - } - - @Override - public UnlockableContent[] getDependencies(){ - if(blockDependencies != null && dependencies == null){ - dependencies = new UnlockableContent[blockDependencies.length]; - for(int i = 0; i < dependencies.length; i++){ - dependencies[i] = Recipe.getByResult(blockDependencies[i]); - } - return dependencies; - } - return dependencies; - } - - public Recipe setDependencies(UnlockableContent... dependencies){ - this.dependencies = dependencies; - return this; - } - - public Recipe setDependencies(Block... dependencies){ - this.blockDependencies = dependencies; - return this; - } - - public enum RecipeVisibility{ - mobileOnly(true, false), - desktopOnly(false, true), - all(true, true); - - public final boolean mobile, desktop; - - RecipeVisibility(boolean mobile, boolean desktop){ - this.mobile = mobile; - this.desktop = desktop; - } - - public boolean shown(){ - return (Vars.mobile && mobile) || (!Vars.mobile && desktop); - } - } -} diff --git a/core/src/io/anuke/mindustry/type/StatusEffect.java b/core/src/io/anuke/mindustry/type/StatusEffect.java index 1d8282354b..3852f0a38e 100644 --- a/core/src/io/anuke/mindustry/type/StatusEffect.java +++ b/core/src/io/anuke/mindustry/type/StatusEffect.java @@ -1,31 +1,79 @@ package io.anuke.mindustry.type; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.utils.ObjectSet; -import io.anuke.mindustry.entities.StatusController.StatusEntry; -import io.anuke.mindustry.entities.Unit; +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.ObjectMap; +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.units.Statuses.StatusEntry; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.Content; public class StatusEffect extends Content{ - /**Duration of this status effect in ticks at maximum power.*/ - public final float baseDuration; - public float damageMultiplier = 1f; //damage dealt public float armorMultiplier = 1f; //armor points public float speedMultiplier = 1f; //speed public Color color = Color.WHITE.cpy(); //tint color - /**Set of 'opposite' effects, which will decrease the duration of this effect when applied.*/ - protected ObjectSet opposites = new ObjectSet<>(); - /**The strength of time decrease when met with an opposite effect, as a fraction of the other's duration.*/ - protected float oppositeScale = 0.5f; + /**Transition handler map.*/ + private ObjectMap transitions = new ObjectMap<>(); + /**Transition initializer array. Since provided effects are only available after init(), this handles putting things + * in the transitions map.*/ + private Array transInit = new Array<>(); - public StatusEffect(float baseDuration){ - this.baseDuration = baseDuration; + /**Damage per frame.*/ + protected float damage; + /**Effect that happens randomly on top of the affected unit.*/ + protected Effect effect = Fx.none; + + @SuppressWarnings("unchecked") + @Override + public void init(){ + for(Object[] pair : transInit){ + Supplier sup = (Supplier) pair[0]; + TransitionHandler handler = (TransitionHandler) pair[1]; + transitions.put(sup.get(), handler); + } + transInit.clear(); } /**Runs every tick on the affected unit while time is greater than 0.*/ public void update(Unit unit, float time){ + if(damage > 0){ + unit.damagePeriodic(damage); + }else if(damage < 0){ //heal unit + unit.healBy(damage * Time.delta()); + } + + if(effect != Fx.none && Mathf.chance(Time.delta() * 0.15f)){ + Effects.effect(effect, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f)); + } + } + + protected void trans(Supplier effect, TransitionHandler handler){ + transInit.add(new Object[]{effect, handler}); + } + + @SuppressWarnings("unchecked") + protected void opposite(Supplier... effect){ + for(Supplier sup : effect){ + trans(sup, (unit, time, newTime, result) -> { + time -= newTime * 0.5f; + if(time > 0){ + result.set(this, time); + return; + } + result.set(sup.get(), newTime); + }); + } + } + + public boolean reactsWith(StatusEffect effect){ + return transitions.containsKey(effect); } /** @@ -36,32 +84,20 @@ public class StatusEffect extends Content{ * @param newTime The time that the new status effect will last */ public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result){ - if(opposites.contains(to)){ - time -= newTime * oppositeScale; - if(time > 0){ - return result.set(this, time); - } + if(transitions.containsKey(to)){ + transitions.get(to).handle(unit, time, newTime, result); + return result; } return result.set(to, newTime); } - /**Called when this effect transitions to a new status effect.*/ - public void onTransition(Unit unit, StatusEffect to){ - } - - public boolean isOpposite(StatusEffect other){ - return opposites.size > 0 && opposites.contains(other); - } - - public void setOpposites(StatusEffect... effects){ - for(StatusEffect e : effects){ - opposites.add(e); - } - } - @Override public ContentType getContentType(){ return ContentType.status; } + + public interface TransitionHandler{ + void handle(Unit unit, float time, float newTime, StatusEntry result); + } } diff --git a/core/src/io/anuke/mindustry/entities/units/UnitType.java b/core/src/io/anuke/mindustry/type/UnitType.java similarity index 64% rename from core/src/io/anuke/mindustry/entities/units/UnitType.java rename to core/src/io/anuke/mindustry/type/UnitType.java index c18928262b..2af1392bad 100644 --- a/core/src/io/anuke/mindustry/entities/units/UnitType.java +++ b/core/src/io/anuke/mindustry/type/UnitType.java @@ -1,23 +1,18 @@ -package io.anuke.mindustry.entities.units; +package io.anuke.mindustry.type; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.utils.ObjectSet; +import io.anuke.arc.Core; +import io.anuke.arc.collection.ObjectSet; +import io.anuke.arc.function.Supplier; +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; -import io.anuke.ucore.function.Supplier; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.Strings; public class UnitType extends UnlockableContent{ protected final Supplier constructor; @@ -28,34 +23,34 @@ public class UnitType extends UnlockableContent{ 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; this.constructor = mainConstructor; - this.description = Bundles.getOrNull("unit." + name + ".description"); + this.description = Core.bundle.getOrNull("unit." + name + ".description"); TypeTrait.registerType(type, mainConstructor); - if(!Bundles.has("unit." + this.name + ".name")){ + 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('-', '_'))); } @@ -68,7 +63,7 @@ public class UnitType extends UnlockableContent{ @Override public String localizedName(){ - return Bundles.get("unit." + name + ".name"); + return Core.bundle.get("unit." + name + ".name"); } @Override @@ -78,12 +73,13 @@ public class UnitType extends UnlockableContent{ @Override public void load(){ - iconRegion = Draw.region("unit-icon-" + name); - region = Draw.region(name); + weapon.load(); + iconRegion = Core.atlas.find("unit-icon-" + name, Core.atlas.find(name)); + region = Core.atlas.find(name); if(!isFlying){ - legRegion = Draw.region(name + "-leg"); - baseRegion = Draw.region(name + "-base"); + legRegion = Core.atlas.find(name + "-leg"); + baseRegion = Core.atlas.find(name + "-base"); } } diff --git a/core/src/io/anuke/mindustry/type/Weapon.java b/core/src/io/anuke/mindustry/type/Weapon.java index 1a4e9159cd..093eda0244 100644 --- a/core/src/io/anuke/mindustry/type/Weapon.java +++ b/core/src/io/anuke/mindustry/type/Weapon.java @@ -1,62 +1,72 @@ package io.anuke.mindustry.type; -import com.badlogic.gdx.graphics.g2d.TextureRegion; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; +import io.anuke.arc.Core; +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.arc.util.Tmp; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.fx.Fx; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.content.Fx; +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; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Translator; -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 AmmoType 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; - /**translator for vector calulations*/ - protected Translator tr = new Translator(); + 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))); - AmmoType 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.getVelocity().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 = Draw.region(name + "-equip"); - region = Draw.region(name); - } - - @Override - public ContentType getContentType(){ - return ContentType.weapon; - } - - public AmmoType 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.bullet, - 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 new file mode 100644 index 0000000000..265820d0de --- /dev/null +++ b/core/src/io/anuke/mindustry/type/Zone.java @@ -0,0 +1,81 @@ +package io.anuke.mindustry.type; + +import io.anuke.arc.Core; +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.game.Rules; +import io.anuke.mindustry.game.UnlockableContent; +import io.anuke.mindustry.maps.generators.Generator; +import io.anuke.mindustry.world.Block; + +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 = 50; + public int launchPeriod = 10; + + public Zone(String name, Generator generator){ + this.name = name; + this.generator = generator; + } + + /**Whether this zone has met its condition; if true, the player can leave.*/ + public boolean metCondition(){ + return state.wave >= conditionWave; + } + + public boolean canConfigure(){ + return data.getWaveScore(this) >= configureWave; + } + + @Override + public void init(){ + generator.init(); + } + + @Override + public boolean alwaysUnlocked(){ + return alwaysUnlocked; + } + + @Override + public boolean isHidden(){ + return true; + } + + //neither of these are implemented, as zones are not displayed in a normal fashion... yet + @Override + public void displayInfo(Table table){} + + @Override + public TextureRegion getContentIcon(){ return null; } + + @Override + public String getContentName(){ + return name; + } + + @Override + public String localizedName(){ + return Core.bundle.get("zone."+name+".name"); + } + + @Override + public ContentType getContentType(){ + return ContentType.zone; + } + +} diff --git a/core/src/io/anuke/mindustry/ui/Bar.java b/core/src/io/anuke/mindustry/ui/Bar.java new file mode 100644 index 0000000000..a29ce6d4cb --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/Bar.java @@ -0,0 +1,85 @@ +package io.anuke.mindustry.ui; + +import io.anuke.arc.Core; +import io.anuke.arc.function.FloatProvider; +import io.anuke.arc.function.Supplier; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.BitmapFont; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.GlyphLayout; +import io.anuke.arc.graphics.g2d.ScissorStack; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Rectangle; +import io.anuke.arc.scene.Element; +import io.anuke.arc.scene.style.Drawable; +import io.anuke.arc.util.pooling.Pools; + +public class Bar extends Element{ + private static Rectangle scissor = new Rectangle(); + + private FloatProvider fraction; + private String name = ""; + private float value, lastValue, blink; + private Color blinkColor = new Color(); + + public Bar(String name, Color color, FloatProvider fraction){ + this.fraction = fraction; + this.name = Core.bundle.get(name); + this.blinkColor.set(color); + lastValue = value = fraction.get(); + setColor(color); + } + + 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()); + }); + } + + public Bar blink(Color color){ + blinkColor.set(color); + return this; + } + + @Override + public void draw(){ + float computed = Mathf.clamp(fraction.get()); + if(!Mathf.isEqual(lastValue, computed)){ + blink = 1f; + lastValue = computed; + } + + blink = Mathf.lerpDelta(blink, 0f, 0.2f); + value = Mathf.lerpDelta(value, computed, 0.15f); + + Draw.colorl(0.1f); + Draw.drawable("bar", x, y, width, height); + Draw.color(color, blinkColor, blink); + + Drawable top = Core.scene.skin.getDrawable("bar-top"); + float topWidth = width * value; + + if(topWidth > Core.atlas.find("bar-top").getWidth()){ + top.draw(x, y, topWidth, height); + }else{ + if(ScissorStack.pushScissors(scissor.set(x, y, topWidth, height))){ + top.draw(x, y, Core.atlas.find("bar-top").getWidth(), height); + ScissorStack.popScissors(); + } + } + + Draw.color(); + + BitmapFont font = Core.scene.skin.getFont("default-font"); + GlyphLayout lay = Pools.obtain(GlyphLayout.class, GlyphLayout::new); + lay.setText(font, name); + + 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 66d3913500..0db23da2ba 100644 --- a/core/src/io/anuke/mindustry/ui/BorderImage.java +++ b/core/src/io/anuke/mindustry/ui/BorderImage.java @@ -1,13 +1,12 @@ package io.anuke.mindustry.ui; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.scene.ui.Image; -import io.anuke.ucore.scene.ui.layout.Unit; +import io.anuke.arc.graphics.Texture; +import io.anuke.arc.graphics.g2d.TextureRegion; +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; +import io.anuke.arc.scene.ui.layout.Unit; public class BorderImage extends Image{ private float thickness = 3f; @@ -31,13 +30,13 @@ public class BorderImage extends Image{ } @Override - public void draw(Batch batch, float alpha){ - super.draw(batch, alpha); + public void draw(){ + super.draw(); 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 25da82eaa8..7f9e969938 100644 --- a/core/src/io/anuke/mindustry/ui/ContentDisplay.java +++ b/core/src/io/anuke/mindustry/ui/ContentDisplay.java @@ -1,38 +1,36 @@ package io.anuke.mindustry.ui; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.utils.OrderedMap; -import io.anuke.mindustry.entities.units.UnitType; -import io.anuke.mindustry.graphics.Palette; +import io.anuke.arc.Core; +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.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; -import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Block.Icon; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.BlockStats; import io.anuke.mindustry.world.meta.StatCategory; import io.anuke.mindustry.world.meta.StatValue; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Strings; public class ContentDisplay{ - public static void displayRecipe(Table table, Recipe recipe){ - Block block = recipe.result; + public static void displayBlock(Table table, Block block){ table.table(title -> { int size = 8 * 6; - title.addImage(Draw.region("block-icon-" + block.name)).size(size); + title.addImage(block.icon(Icon.large)).size(size); title.add("[accent]" + block.formalName).padLeft(5); }); table.row(); - table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); + table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(8).padLeft(0).padRight(0).fillX(); table.row(); @@ -40,7 +38,7 @@ public class ContentDisplay{ table.add(block.fullDescription).padLeft(5).padRight(5).width(400f).wrap().fillX(); table.row(); - table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); + table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(8).padLeft(0).padRight(0).fillX(); table.row(); } @@ -51,7 +49,7 @@ public class ContentDisplay{ if(map.size == 0) continue; - table.add("$text.category." + cat.name()).color(Palette.accent).fillX(); + table.add("$category." + cat.name()).color(Pal.accent).fillX(); table.row(); for(BlockStat stat : map.keys()){ @@ -88,13 +86,11 @@ public class ContentDisplay{ table.left().defaults().fillX(); - table.add(Bundles.format("text.item.explosiveness", (int) (item.explosiveness * 100 * 2f))); + table.add(Core.bundle.format("item.explosiveness", (int) (item.explosiveness * 100))); table.row(); - table.add(Bundles.format("text.item.flammability", (int) (item.flammability * 100 * 2f))); + table.add(Core.bundle.format("item.flammability", (int) (item.flammability * 100))); table.row(); - table.add(Bundles.format("text.item.radioactivity", (int) (item.radioactivity * 100 * 2f))); - table.row(); - table.add(Bundles.format("text.item.fluxiness", (int) (item.fluxiness * 100 * 2f))); + table.add(Core.bundle.format("item.radioactivity", (int) (item.radioactivity * 100))); table.row(); } @@ -121,15 +117,15 @@ public class ContentDisplay{ table.left().defaults().fillX(); - table.add(Bundles.format("text.item.explosiveness", (int) (liquid.explosiveness * 100 * 2f))); + table.add(Core.bundle.format("item.explosiveness", (int) (liquid.explosiveness * 100))); table.row(); - table.add(Bundles.format("text.item.flammability", (int) (liquid.flammability * 100 * 2f))); + table.add(Core.bundle.format("item.flammability", (int) (liquid.flammability * 100))); table.row(); - table.add(Bundles.format("text.liquid.heatcapacity", (int) (liquid.heatCapacity * 100))); + table.add(Core.bundle.format("liquid.heatcapacity", (int) (liquid.heatCapacity * 100))); table.row(); - table.add(Bundles.format("text.liquid.temperature", (int) (liquid.temperature * 100))); + table.add(Core.bundle.format("liquid.temperature", (int) (liquid.temperature * 100))); table.row(); - table.add(Bundles.format("text.liquid.viscosity", (int) (liquid.viscosity * 100))); + table.add(Core.bundle.format("liquid.viscosity", (int) (liquid.viscosity * 100))); table.row(); } @@ -155,23 +151,23 @@ public class ContentDisplay{ table.left().defaults().fillX(); - if(Bundles.has("mech." + mech.name + ".weapon")){ - table.add(Bundles.format("text.mech.weapon", Bundles.get("mech." + mech.name + ".weapon"))); + if(Core.bundle.has("mech." + mech.name + ".weapon")){ + table.add(Core.bundle.format("mech.weapon", Core.bundle.get("mech." + mech.name + ".weapon"))); table.row(); } - if(Bundles.has("mech." + mech.name + ".ability")){ - table.add(Bundles.format("text.mech.ability", Bundles.get("mech." + mech.name + ".ability"))); + if(Core.bundle.has("mech." + mech.name + ".ability")){ + table.add(Core.bundle.format("mech.ability", Core.bundle.get("mech." + mech.name + ".ability"))); table.row(); } - table.add(Bundles.format("text.mech.armor", mech.armor)); + table.add(Core.bundle.format("mech.health", (int)mech.health)); table.row(); - table.add(Bundles.format("text.mech.itemcapacity", mech.itemCapacity)); + table.add(Core.bundle.format("mech.itemcapacity", mech.itemCapacity)); table.row(); if(mech.drillPower > 0){ - table.add(Bundles.format("text.mech.minespeed", (int) (mech.mineSpeed * 10))); + table.add(Core.bundle.format("mech.minespeed", (int) (mech.mineSpeed * 10))); table.row(); - table.add(Bundles.format("text.mech.minepower", mech.drillPower)); + table.add(Core.bundle.format("mech.minepower", mech.drillPower)); table.row(); } } @@ -198,9 +194,9 @@ public class ContentDisplay{ table.left().defaults().fillX(); - table.add(Bundles.format("text.unit.health", unit.health)); + table.add(Core.bundle.format("unit.health", unit.health)); table.row(); - table.add(Bundles.format("text.unit.speed", Strings.toFixed(unit.speed, 1))); + table.add(Core.bundle.format("unit.speed", Strings.toFixed(unit.speed, 1))); table.row(); table.row(); } diff --git a/core/src/io/anuke/mindustry/ui/GridImage.java b/core/src/io/anuke/mindustry/ui/GridImage.java index 01792f5fbb..fd164cc191 100644 --- a/core/src/io/anuke/mindustry/ui/GridImage.java +++ b/core/src/io/anuke/mindustry/ui/GridImage.java @@ -1,9 +1,7 @@ package io.anuke.mindustry.ui; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.scene.Element; +import io.anuke.arc.graphics.g2d.Fill; +import io.anuke.arc.scene.Element; public class GridImage extends Element{ private int imageWidth, imageHeight; @@ -13,9 +11,8 @@ public class GridImage extends Element{ this.imageHeight = h; } - public void draw(Batch batch, float alpha){ - TextureRegion blank = Draw.region("white"); - + @Override + public void draw(){ float xspace = (getWidth() / imageWidth); float yspace = (getHeight() / imageHeight); float s = 1f; @@ -26,11 +23,11 @@ public class GridImage extends Element{ int jumpy = (int) (Math.max(minspace, yspace) / yspace); for(int x = 0; x <= imageWidth; x += jumpx){ - batch.draw(blank, (int) (getX() + xspace * x - s), getY() - s, 2, getHeight() + (x == imageWidth ? 1 : 0)); + Fill.crect((int) (getX() + xspace * x - s), getY() - s, 2, getHeight() + (x == imageWidth ? 1 : 0)); } for(int y = 0; y <= imageHeight; y += jumpy){ - batch.draw(blank, getX() - s, (int) (getY() + y * yspace - s), getWidth(), 2); + Fill.crect(getX() - s, (int) (getY() + y * yspace - s), getWidth(), 2); } } diff --git a/core/src/io/anuke/mindustry/ui/ImageStack.java b/core/src/io/anuke/mindustry/ui/ImageStack.java deleted file mode 100644 index 2ca0063e48..0000000000 --- a/core/src/io/anuke/mindustry/ui/ImageStack.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.anuke.mindustry.ui; - -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import io.anuke.ucore.scene.ui.Image; -import io.anuke.ucore.scene.ui.layout.Stack; - -public class ImageStack extends Stack{ - - public ImageStack(TextureRegion... regions){ - for(TextureRegion region : regions){ - add(new Image(region)); - } - } -} diff --git a/core/src/io/anuke/mindustry/ui/IntFormat.java b/core/src/io/anuke/mindustry/ui/IntFormat.java index 6c4431a4b0..cdf1e529ad 100644 --- a/core/src/io/anuke/mindustry/ui/IntFormat.java +++ b/core/src/io/anuke/mindustry/ui/IntFormat.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.ui; -import io.anuke.ucore.util.Bundles; + +import io.anuke.arc.Core; /** * A low-garbage way to format bundle strings. @@ -17,7 +18,7 @@ public class IntFormat{ public CharSequence get(int value){ if(lastValue != value){ builder.setLength(0); - builder.append(Bundles.format(text, value)); + builder.append(Core.bundle.format(text, value)); } lastValue = value; return builder; diff --git a/core/src/io/anuke/mindustry/ui/ItemDisplay.java b/core/src/io/anuke/mindustry/ui/ItemDisplay.java index 4530d606f0..ff5b6153f3 100644 --- a/core/src/io/anuke/mindustry/ui/ItemDisplay.java +++ b/core/src/io/anuke/mindustry/ui/ItemDisplay.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.ui; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; -import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.arc.scene.ui.layout.Table; /**An item image with text.*/ public class ItemDisplay extends Table{ diff --git a/core/src/io/anuke/mindustry/ui/ItemImage.java b/core/src/io/anuke/mindustry/ui/ItemImage.java index 64007340af..1ccd3a6f02 100644 --- a/core/src/io/anuke/mindustry/ui/ItemImage.java +++ b/core/src/io/anuke/mindustry/ui/ItemImage.java @@ -1,11 +1,12 @@ package io.anuke.mindustry.ui; -import com.badlogic.gdx.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.mindustry.type.Item.Icon; import io.anuke.mindustry.type.ItemStack; -import io.anuke.ucore.function.Supplier; -import io.anuke.ucore.scene.ui.Image; -import io.anuke.ucore.scene.ui.layout.Stack; -import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.arc.function.Supplier; +import io.anuke.arc.scene.ui.Image; +import io.anuke.arc.scene.ui.layout.Stack; +import io.anuke.arc.scene.ui.layout.Table; public class ItemImage extends Stack{ @@ -18,7 +19,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..49a3b40ccf --- /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(2); + 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 891e44f7f8..8e538759a7 100644 --- a/core/src/io/anuke/mindustry/ui/Links.java +++ b/core/src/io/anuke/mindustry/ui/Links.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.ui; -import com.badlogic.gdx.graphics.Color; -import io.anuke.ucore.util.Bundles; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; public class Links{ private static LinkEntry[] links; @@ -33,7 +33,7 @@ public class Links{ public LinkEntry(String name, String link, Color color){ this.name = name; this.color = color; - this.description = Bundles.getNotNull("text.link." + name + ".description"); + this.description = Core.bundle.getNotNull("link." + name + ".description"); this.link = link; } } diff --git a/core/src/io/anuke/mindustry/ui/LiquidDisplay.java b/core/src/io/anuke/mindustry/ui/LiquidDisplay.java index f639dfe1c5..442707408e 100644 --- a/core/src/io/anuke/mindustry/ui/LiquidDisplay.java +++ b/core/src/io/anuke/mindustry/ui/LiquidDisplay.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.ui; import io.anuke.mindustry.type.Liquid; -import io.anuke.ucore.scene.ui.Image; -import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.arc.scene.ui.Image; +import io.anuke.arc.scene.ui.layout.Table; /**An ItemDisplay, but for liquids.*/ public class LiquidDisplay extends Table{ diff --git a/core/src/io/anuke/mindustry/ui/MenuButton.java b/core/src/io/anuke/mindustry/ui/MenuButton.java index a7e1062bfc..9d5f34430e 100644 --- a/core/src/io/anuke/mindustry/ui/MenuButton.java +++ b/core/src/io/anuke/mindustry/ui/MenuButton.java @@ -1,8 +1,8 @@ package io.anuke.mindustry.ui; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.utils.Align; -import io.anuke.ucore.scene.ui.TextButton; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.util.Align; +import io.anuke.arc.scene.ui.TextButton; public class MenuButton extends TextButton{ diff --git a/core/src/io/anuke/mindustry/ui/Minimap.java b/core/src/io/anuke/mindustry/ui/Minimap.java index ae87725d75..243e8039da 100644 --- a/core/src/io/anuke/mindustry/ui/Minimap.java +++ b/core/src/io/anuke/mindustry/ui/Minimap.java @@ -1,57 +1,28 @@ package io.anuke.mindustry.ui; -import com.badlogic.gdx.graphics.Texture.TextureFilter; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import io.anuke.mindustry.graphics.Shaders; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.scene.Element; -import io.anuke.ucore.scene.event.InputEvent; -import io.anuke.ucore.scene.event.InputListener; -import io.anuke.ucore.scene.ui.layout.Container; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.scene.Element; +import io.anuke.arc.scene.event.InputEvent; +import io.anuke.arc.scene.event.InputListener; +import io.anuke.arc.scene.ui.layout.Container; -import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.renderer; public class Minimap extends Container{ public Minimap(){ super(new Element(){ - TextureRegion r = new TextureRegion(); @Override public void draw(){ if(renderer.minimap.getRegion() == null) return; - Draw.crect(renderer.minimap.getRegion(), x, y, width, height); + Draw.rect(renderer.minimap.getRegion(), x + width/2f, y + height/2f, width, height); if(renderer.minimap.getTexture() != null){ renderer.minimap.drawEntities(x, y, width, height); } - - if(showFog){ - renderer.fog.getTexture().setFilter(TextureFilter.Nearest, TextureFilter.Nearest); - - r.setRegion(renderer.minimap.getRegion()); - float pad = renderer.fog.getPadding(); - - float px = r.getU() * world.width() + pad; - float py = r.getV() * world.height() + pad; - float px2 = r.getU2() * world.width() + pad; - float py2 = r.getV2() * world.height() + pad; - - r.setTexture(renderer.fog.getTexture()); - r.setU(px / (world.width() + pad*2f)); - r.setV(1f - py / (world.height() + pad*2f)); - r.setU2(px2 / (world.width() + pad*2f)); - r.setV2(1f - py2 / (world.height() + pad*2f)); - - Graphics.shader(Shaders.fog); - Draw.crect(r, x, y, width, height); - Graphics.shader(); - - renderer.fog.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear); - } } }); @@ -61,15 +32,16 @@ public class Minimap extends Container{ margin(5f); addListener(new InputListener(){ - public boolean scrolled(InputEvent event, float x, float y, int amount){ - renderer.minimap.zoomBy(amount); + @Override + public boolean scrolled(InputEvent event, float x, float y, float amountx, float amounty){ + renderer.minimap.zoomBy(amounty); return true; } }); update(() -> { - Element e = Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true); + Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true); if(e != null && e.isDescendantOf(this)){ Core.scene.setScrollFocus(this); }else if(Core.scene.getScrollFocus() == this){ diff --git a/core/src/io/anuke/mindustry/ui/MobileButton.java b/core/src/io/anuke/mindustry/ui/MobileButton.java index 68999a260c..4d64eafe5c 100644 --- a/core/src/io/anuke/mindustry/ui/MobileButton.java +++ b/core/src/io/anuke/mindustry/ui/MobileButton.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.ui; -import com.badlogic.gdx.utils.Align; -import io.anuke.ucore.scene.ui.ImageButton; +import io.anuke.arc.util.Align; +import io.anuke.arc.scene.ui.ImageButton; public class MobileButton extends ImageButton{ diff --git a/core/src/io/anuke/mindustry/ui/TreeLayout.java b/core/src/io/anuke/mindustry/ui/TreeLayout.java new file mode 100644 index 0000000000..d5f0db4e8e --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/TreeLayout.java @@ -0,0 +1,310 @@ + + +package io.anuke.mindustry.ui; + +import io.anuke.arc.collection.FloatArray; +import io.anuke.arc.math.geom.Rectangle; + +/** + * Algorithm taken from TreeLayout. + */ +public class TreeLayout{ + public TreeLocation rootLocation = TreeLocation.top; + public TreeAlignment alignment = TreeAlignment.awayFromRoot; + public float gapBetweenLevels = 10; + public float gapBetweenNodes = 10f; + + private final FloatArray sizeOfLevel = new FloatArray(); + private float boundsLeft = Float.MAX_VALUE; + private float boundsRight = Float.MIN_VALUE; + private float boundsTop = Float.MAX_VALUE; + private float boundsBottom = Float.MIN_VALUE; + + public void layout(TreeNode root){ + firstWalk(root, null); + calcSizeOfLevels(root, 0); + secondWalk(root, -root.prelim, 0, 0); + } + + private float getWidthOrHeightOfNode(TreeNode treeNode, boolean returnWidth){ + return returnWidth ? treeNode.width : treeNode.height; + } + + private float getNodeThickness(TreeNode treeNode){ + return getWidthOrHeightOfNode(treeNode, !isLevelChangeInYAxis()); + } + + private float getNodeSize(TreeNode treeNode){ + return getWidthOrHeightOfNode(treeNode, isLevelChangeInYAxis()); + } + + private boolean isLevelChangeInYAxis(){ + return rootLocation == TreeLocation.top || rootLocation == TreeLocation.bottom; + } + + private int getLevelChangeSign(){ + return rootLocation == TreeLocation.bottom || rootLocation == TreeLocation.right ? -1 : 1; + } + + private void updateBounds(TreeNode node, float centerX, float centerY){ + float width = node.width; + float height = node.height; + float left = centerX - width / 2; + float right = centerX + width / 2; + float top = centerY - height / 2; + float bottom = centerY + height / 2; + if(boundsLeft > left){ + boundsLeft = left; + } + if(boundsRight < right){ + boundsRight = right; + } + if(boundsTop > top){ + boundsTop = top; + } + if(boundsBottom < bottom){ + boundsBottom = bottom; + } + } + + public Rectangle getBounds(){ + return new Rectangle(boundsLeft, boundsBottom, boundsRight - boundsLeft, boundsTop - boundsBottom); + } + + private void calcSizeOfLevels(TreeNode node, int level){ + float oldSize; + if(sizeOfLevel.size <= level){ + sizeOfLevel.add(0); + oldSize = 0; + }else{ + oldSize = sizeOfLevel.get(level); + } + + float size = getNodeThickness(node); + if(oldSize < size){ + sizeOfLevel.set(level, size); + } + + if(!node.isLeaf()){ + for(TreeNode child : node.children){ + calcSizeOfLevels(child, level + 1); + } + } + } + + public int getLevelCount(){ + return sizeOfLevel.size; + } + + public float getGapBetweenNodes(TreeNode a, TreeNode b){ + return gapBetweenNodes; + } + + public float getSizeOfLevel(int level){ + if(!(level >= 0)) throw new IllegalArgumentException("level must be >= 0"); + if(!(level < getLevelCount())) throw new IllegalArgumentException("level must be < levelCount"); + + return sizeOfLevel.get(level); + } + + private TreeNode getAncestor(TreeNode node){ + return node.ancestor != null ? node.ancestor : node; + } + + private float getDistance(TreeNode v, TreeNode w){ + float sizeOfNodes = getNodeSize(v) + getNodeSize(w); + + return sizeOfNodes / 2 + getGapBetweenNodes(v, w); + } + + private TreeNode nextLeft(TreeNode v){ + return v.isLeaf() ? v.thread : v.children[0]; + } + + private TreeNode nextRight(TreeNode v){ + return v.isLeaf() ? v.thread : v.children[v.children.length - 1]; + } + + private int getNumber(TreeNode node, TreeNode parentNode){ + if(node.number == -1){ + int number = 1; + for(TreeNode child : parentNode.children){ + child.number = number++; + } + } + return node.number; + } + + private TreeNode ancestor(TreeNode vIMinus, TreeNode parentOfV, TreeNode defaultAncestor){ + TreeNode ancestor = getAncestor(vIMinus); + return ancestor.parent == parentOfV ? ancestor : defaultAncestor; + } + + private void moveSubtree(TreeNode wMinus, TreeNode wPlus, TreeNode parent, float shift){ + int subtrees = getNumber(wPlus, parent) - getNumber(wMinus, parent); + wPlus.change = wPlus.change - shift / subtrees; + wPlus.shift = wPlus.shift + shift; + wMinus.change = wMinus.change + shift / subtrees; + wPlus.prelim = wPlus.prelim + shift; + wPlus.mode = wPlus.mode + shift; + } + + private TreeNode apportion(TreeNode v, TreeNode defaultAncestor, + TreeNode leftSibling, TreeNode parentOfV){ + if(leftSibling == null){ + return defaultAncestor; + } + + TreeNode vOPlus = v; + TreeNode vIPlus = v; + TreeNode vIMinus = leftSibling; + + TreeNode vOMinus = parentOfV.children[0]; + + float sIPlus = (vIPlus).mode; + float sOPlus = (vOPlus).mode; + float sIMinus = (vIMinus).mode; + float sOMinus = (vOMinus).mode; + + TreeNode nextRightVIMinus = nextRight(vIMinus); + TreeNode nextLeftVIPlus = nextLeft(vIPlus); + + while(nextRightVIMinus != null && nextLeftVIPlus != null){ + vIMinus = nextRightVIMinus; + vIPlus = nextLeftVIPlus; + vOMinus = nextLeft(vOMinus); + vOPlus = nextRight(vOPlus); + vOPlus.ancestor = v; + float shift = (vIMinus.prelim + sIMinus) + - (vIPlus.prelim + sIPlus) + + getDistance(vIMinus, vIPlus); + + if(shift > 0){ + moveSubtree(ancestor(vIMinus, parentOfV, defaultAncestor), + v, parentOfV, shift); + sIPlus = sIPlus + shift; + sOPlus = sOPlus + shift; + } + sIMinus += vIMinus.mode; + sIPlus += vIPlus.mode; + sOMinus += vOMinus.mode; + sOPlus += vOPlus.mode; + + nextRightVIMinus = nextRight(vIMinus); + nextLeftVIPlus = nextLeft(vIPlus); + } + + if(nextRightVIMinus != null && nextRight(vOPlus) == null){ + vOPlus.thread = nextRightVIMinus; + vOPlus.mode += sIMinus - sOPlus; + } + + if(nextLeftVIPlus != null && nextLeft(vOMinus) == null){ + vOMinus.thread = nextLeftVIPlus; + vOMinus.mode += sIPlus - sOMinus; + defaultAncestor = v; + } + return defaultAncestor; + } + + private void executeShifts(TreeNode v){ + float shift = 0; + float change = 0; + + for(int i = v.children.length - 1; i >= 0; i --){ + TreeNode w = v.children[i]; + change = change + w.change; + w.prelim += shift; + w.mode += shift; + shift += w.shift + change; + } + } + + private void firstWalk(TreeNode v, TreeNode leftSibling){ + if(v.isLeaf()){ + if(leftSibling != null){ + v.prelim = leftSibling.prelim + getDistance(v, leftSibling); + } + + }else{ + TreeNode defaultAncestor = v.children[0]; + TreeNode previousChild = null; + for(TreeNode w : v.children){ + firstWalk(w, previousChild); + defaultAncestor = apportion(w, defaultAncestor, previousChild, + v); + previousChild = w; + } + executeShifts(v); + float midpoint = (v.children[0].prelim + v.children[v.children.length-1].prelim) / 2f; + TreeNode w = leftSibling; + if(w != null){ + v.prelim = w.prelim + getDistance(v, w); + v.mode = v.prelim - midpoint; + }else{ + v.prelim = midpoint; + } + } + } + + private void secondWalk(TreeNode v, float m, int level, float levelStart){ + float levelChangeSign = getLevelChangeSign(); + boolean levelChangeOnYAxis = isLevelChangeInYAxis(); + float levelSize = getSizeOfLevel(level); + + float x = v.prelim + m; + + float y; + if(alignment == TreeAlignment.center){ + y = levelStart + levelChangeSign * (levelSize / 2); + }else if(alignment == TreeAlignment.towardsRoot){ + y = levelStart + levelChangeSign * (getNodeThickness(v) / 2); + }else{ + y = levelStart + levelSize - levelChangeSign + * (getNodeThickness(v) / 2); + } + + if(!levelChangeOnYAxis){ + float t = x; + x = y; + y = t; + } + + v.x = x; + v.y = y; + updateBounds(v, x, y); + + if(!v.isLeaf()){ + float nextLevelStart = levelStart + + (levelSize + gapBetweenLevels) + * levelChangeSign; + for(TreeNode w : v.children){ + secondWalk(w, m + v.mode, level + 1, nextLevelStart); + } + } + } + + public enum TreeLocation{ + top, left, bottom, right + } + + public enum TreeAlignment{ + center, towardsRoot, awayFromRoot + } + + public static class TreeNode{ + public float width, height, x, y; + + //should be initialized by user + public T[] children; + public T parent; + + private float mode, prelim, change, shift; + private int number = -1; + private TreeNode thread, ancestor; + + boolean isLeaf(){ + return children == null || children.length == 0; + } + } +} \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java index 4cfa262779..af6ddffe1b 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java @@ -1,22 +1,21 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.ObjectSet; -import io.anuke.mindustry.graphics.Palette; +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.Pal; import io.anuke.mindustry.io.Contributors; import io.anuke.mindustry.io.Contributors.Contributor; import io.anuke.mindustry.ui.Links; import io.anuke.mindustry.ui.Links.LinkEntry; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.scene.ui.ScrollPane; -import io.anuke.ucore.scene.ui.layout.Cell; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.utils.UIUtils; -import io.anuke.ucore.util.OS; -import io.anuke.ucore.util.Strings; +import io.anuke.arc.util.Time; +import io.anuke.arc.scene.ui.ScrollPane; +import io.anuke.arc.scene.ui.layout.Cell; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.scene.utils.UIUtils; +import io.anuke.arc.util.OS; +import io.anuke.arc.util.Strings; import static io.anuke.mindustry.Vars.ios; import static io.anuke.mindustry.Vars.ui; @@ -26,7 +25,7 @@ public class AboutDialog extends FloatingDialog{ private static ObjectSet bannedItems = ObjectSet.with("google-play", "itch.io", "dev-builds", "trello"); public AboutDialog(){ - super("$text.about.button"); + super("$about.button"); Contributors.getContributors(out -> contributors = out, Throwable::printStackTrace); @@ -35,8 +34,8 @@ public class AboutDialog extends FloatingDialog{ } void setup(){ - content().clear(); - buttons().clear(); + cont.clear(); + buttons.clear(); float h = UIUtils.portrait() ? 90f : 80f; float w = UIUtils.portrait() ? 330f : 600f; @@ -49,7 +48,7 @@ public class AboutDialog extends FloatingDialog{ continue; } - Table table = new Table("underline-2"); + Table table = new Table("underline"); table.margin(0); table.table(img -> { img.addImage("white").height(h - 5).width(40f).color(link.color); @@ -69,29 +68,29 @@ public class AboutDialog extends FloatingDialog{ }).padLeft(8); table.addImageButton("icon-link", 14 * 3, () -> { - if(!Gdx.net.openURI(link.link)){ - ui.showError("$text.linkfail"); - Gdx.app.getClipboard().setContents(link.link); + if(!Core.net.openURI(link.link)){ + ui.showError("$linkfail"); + Core.app.getClipboard().setContents(link.link); } }).size(h - 5, h); in.add(table).size(w, h).padTop(5).row(); } - shown(() -> Timers.run(1f, () -> Core.scene.setScrollFocus(pane))); + shown(() -> Time.run(1f, () -> Core.scene.setScrollFocus(pane))); - content().add(pane).growX(); + cont.add(pane).growX(); addCloseButton(); - buttons().addButton("$text.credits", this::showCredits).size(200f, 64f); + buttons.addButton("$credits", this::showCredits).size(200f, 64f); if(!ios && !OS.isMac){ - buttons().addButton("$text.changelog.title", ui.changelog::show).size(200f, 64f); + buttons.addButton("$changelog.title", ui.changelog::show).size(200f, 64f); } if(UIUtils.portrait()){ - for(Cell cell : buttons().getCells()){ + for(Cell cell : buttons.getCells()){ cell.width(140f); } } @@ -99,16 +98,16 @@ public class AboutDialog extends FloatingDialog{ } public void showCredits(){ - FloatingDialog dialog = new FloatingDialog("$text.credits"); + FloatingDialog dialog = new FloatingDialog("$credits"); dialog.addCloseButton(); - dialog.content().add("$text.credits.text"); - dialog.content().row(); + dialog.cont.add("$credits.text"); + dialog.cont.row(); if(!contributors.isEmpty()){ - dialog.content().addImage("blank").color(Palette.accent).fillX().height(3f).pad(3f); - dialog.content().row(); - dialog.content().add("$text.contributors"); - dialog.content().row(); - dialog.content().pane(new Table(){{ + dialog.cont.addImage("blank").color(Pal.accent).fillX().height(3f).pad(3f); + dialog.cont.row(); + dialog.cont.add("$contributors"); + dialog.cont.row(); + dialog.cont.pane(new Table(){{ int i = 0; left(); for(Contributor c : contributors){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java index 31496a5e3a..70a1e5abb3 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java @@ -1,15 +1,15 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.mindustry.net.Administration.PlayerInfo; -import io.anuke.ucore.scene.ui.ScrollPane; -import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.arc.scene.ui.ScrollPane; +import io.anuke.arc.scene.ui.layout.Table; import static io.anuke.mindustry.Vars.*; public class AdminsDialog extends FloatingDialog{ public AdminsDialog(){ - super("$text.server.admins"); + super("$server.admins"); addCloseButton(); @@ -18,7 +18,7 @@ public class AdminsDialog extends FloatingDialog{ } private void setup(){ - content().clear(); + cont.clear(); float w = 400f, h = 80f; @@ -28,7 +28,7 @@ public class AdminsDialog extends FloatingDialog{ pane.setFadeScrollBars(false); if(netServer.admins.getAdmins().size == 0){ - table.add("$text.server.admins.none"); + table.add("$server.admins.none"); } for(PlayerInfo info : netServer.admins.getAdmins()){ @@ -38,7 +38,7 @@ public class AdminsDialog extends FloatingDialog{ res.labelWrap("[LIGHT_GRAY]" + info.lastName).width(w - h - 24f); res.add().growX(); res.addImageButton("icon-cancel", 14 * 3, () -> { - ui.showConfirm("$text.confirm", "$text.confirmunadmin", () -> { + ui.showConfirm("$confirm", "$confirmunadmin", () -> { netServer.admins.unAdminPlayer(info.id); playerGroup.forEach(player -> { if(player != null && player.uuid != null && player.uuid.equals(info.id)){ @@ -53,6 +53,6 @@ public class AdminsDialog extends FloatingDialog{ table.row(); } - content().add(pane); + cont.add(pane); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java index 1a3d8369d7..741ce3c983 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java @@ -1,15 +1,15 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.mindustry.net.Administration.PlayerInfo; -import io.anuke.ucore.scene.ui.ScrollPane; -import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.arc.scene.ui.ScrollPane; +import io.anuke.arc.scene.ui.layout.Table; import static io.anuke.mindustry.Vars.*; public class BansDialog extends FloatingDialog{ public BansDialog(){ - super("$text.server.bans"); + super("$server.bans"); addCloseButton(); @@ -19,7 +19,7 @@ public class BansDialog extends FloatingDialog{ } private void setup(){ - content().clear(); + cont.clear(); float w = 400f, h = 80f; @@ -29,7 +29,7 @@ public class BansDialog extends FloatingDialog{ pane.setFadeScrollBars(false); if(netServer.admins.getBanned().size == 0){ - table.add("$text.server.bans.none"); + table.add("$server.bans.none"); } for(PlayerInfo info : netServer.admins.getBanned()){ @@ -39,7 +39,7 @@ public class BansDialog extends FloatingDialog{ res.labelWrap("IP: [LIGHT_GRAY]" + info.lastIP + "\n[]Name: [LIGHT_GRAY]" + info.lastName).width(w - h - 24f); res.add().growX(); res.addImageButton("icon-cancel", 14 * 3, () -> { - ui.showConfirm("$text.confirm", "$text.confirmunban", () -> { + ui.showConfirm("$confirm", "$confirmunban", () -> { netServer.admins.unbanPlayerID(info.id); setup(); }); @@ -49,6 +49,6 @@ public class BansDialog extends FloatingDialog{ table.row(); } - content().add(pane); + cont.add(pane); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ChangelogDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ChangelogDialog.java index 9d2e094eb1..4087992daa 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ChangelogDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ChangelogDialog.java @@ -1,16 +1,15 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.utils.Array; +import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; +import io.anuke.arc.scene.ui.ScrollPane; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.util.Log; +import io.anuke.arc.util.OS; import io.anuke.mindustry.Vars; +import io.anuke.mindustry.game.Version; import io.anuke.mindustry.io.Changelogs; import io.anuke.mindustry.io.Changelogs.VersionInfo; -import io.anuke.mindustry.game.Version; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.scene.ui.ScrollPane; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.OS; import static io.anuke.mindustry.Vars.ios; @@ -19,19 +18,19 @@ public class ChangelogDialog extends FloatingDialog{ private Array versions; public ChangelogDialog(){ - super("$text.changelog.title"); + super("$changelog.title"); addCloseButton(); - content().add("$text.changelog.loading"); + cont.add("$changelog.loading"); if(!ios && !OS.isMac){ Changelogs.getChangelog(result -> { versions = result; - Gdx.app.postRunnable(this::setup); + Core.app.post(this::setup); }, t -> { Log.err(t); - Gdx.app.postRunnable(this::setup); + Core.app.post(this::setup); }); } } @@ -40,19 +39,19 @@ public class ChangelogDialog extends FloatingDialog{ Table table = new Table(); ScrollPane pane = new ScrollPane(table); - content().clear(); - content().add(pane).grow(); + cont.clear(); + cont.add(pane).grow(); if(versions == null){ - table.add("$text.changelog.error"); + table.add("$changelog.error"); if(Vars.android){ table.row(); - table.add("$text.changelog.error.android").padTop(8); + table.add("$changelog.error.android").padTop(8); } if(ios){ table.row(); - table.add("$text.changelog.error.ios").padTop(8); + table.add("$changelog.error.ios").padTop(8); } }else{ for(VersionInfo info : versions){ @@ -66,10 +65,10 @@ public class ChangelogDialog extends FloatingDialog{ in.add("[accent]" + info.name + "[LIGHT_GRAY] | " + info.date); if(info.build == Version.build){ in.row(); - in.add("$text.changelog.current"); + in.add("$changelog.current"); }else if(info == versions.first()){ in.row(); - in.add("$text.changelog.latest"); + in.add("$changelog.latest"); } in.row(); in.labelWrap("[lightgray]" + desc).width(vw - 20).padTop(12); @@ -77,10 +76,10 @@ public class ChangelogDialog extends FloatingDialog{ table.add(in).width(vw).pad(8).row(); } - int lastid = Settings.getInt("lastBuild"); + int lastid = Core.settings.getInt("lastBuild"); if(lastid != 0 && versions.peek().build > lastid){ - Settings.putInt("lastBuild", versions.peek().build); - Settings.save(); + Core.settings.put("lastBuild", versions.peek().build); + Core.settings.save(); show(); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ColorPickDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ColorPickDialog.java index a9c282b065..68ac658a9f 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ColorPickDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ColorPickDialog.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.graphics.Color; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.scene.ui.Dialog; -import io.anuke.ucore.scene.ui.ImageButton; -import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.input.KeyCode; +import io.anuke.arc.scene.ui.Dialog; +import io.anuke.arc.scene.ui.ImageButton; +import io.anuke.arc.scene.ui.layout.Table; import static io.anuke.mindustry.Vars.playerColors; import static io.anuke.mindustry.Vars.players; @@ -20,7 +20,7 @@ public class ColorPickDialog extends Dialog{ private void build(){ Table table = new Table(); - content().add(table); + cont.add(table); for(int i = 0; i < playerColors.length; i++){ Color color = playerColors[i]; @@ -38,7 +38,7 @@ public class ColorPickDialog extends Dialog{ } keyDown(key -> { - if(key == Keys.ESCAPE || key == Keys.BACK) + if(key == KeyCode.ESCAPE || key == KeyCode.BACK) hide(); }); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ContentInfoDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ContentInfoDialog.java index 50a2f4cf78..23f46045e8 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ContentInfoDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ContentInfoDialog.java @@ -1,19 +1,19 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.ucore.scene.ui.ScrollPane; -import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.arc.scene.ui.ScrollPane; +import io.anuke.arc.scene.ui.layout.Table; public class ContentInfoDialog extends FloatingDialog{ public ContentInfoDialog(){ - super("$text.info.title"); + super("$info.title"); addCloseButton(); } public void show(UnlockableContent content){ - content().clear(); + cont.clear(); Table table = new Table(); table.margin(10); @@ -21,7 +21,7 @@ public class ContentInfoDialog extends FloatingDialog{ content.displayInfo(table); ScrollPane pane = new ScrollPane(table); - content().add(pane); + cont.add(pane); show(); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java index c9c2901a6b..2a6db67316 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java @@ -1,29 +1,30 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.utils.Align; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.ucore.scene.ui.Image; -import io.anuke.ucore.scene.ui.KeybindDialog; +import io.anuke.arc.Core; +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.Pal; public class ControlsDialog extends KeybindDialog{ public ControlsDialog(){ - setDialog(); + setStyle(Core.scene.skin.get("dialog", WindowStyle.class)); setFillParent(true); - title().setAlignment(Align.center); - getTitleTable().row(); - getTitleTable().add(new Image("white")) - .growX().height(3f).pad(4f).get().setColor(Palette.accent); + title.setAlignment(Align.center); + titleTable.row(); + titleTable.add(new Image("white")) + .growX().height(3f).pad(4f).get().setColor(Pal.accent); } @Override public void addCloseButton(){ - buttons().addImageTextButton("$text.back", "icon-arrow-left", 30f, this::hide).size(230f, 64f); + buttons.addImageTextButton("$back", "icon-arrow-left", 30f, this::hide).size(230f, 64f); keyDown(key -> { - if(key == Keys.ESCAPE || key == Keys.BACK) + if(key == KeyCode.ESCAPE || key == KeyCode.BACK) hide(); }); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java index 1a5f218489..c068eae79d 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java @@ -1,29 +1,29 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.utils.Align; -import com.badlogic.gdx.utils.Scaling; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.scene.event.Touchable; +import io.anuke.arc.scene.ui.ButtonGroup; +import io.anuke.arc.scene.ui.ImageButton; +import io.anuke.arc.scene.ui.ScrollPane; +import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.util.Align; +import io.anuke.arc.util.Scaling; import io.anuke.mindustry.game.Difficulty; -import io.anuke.mindustry.game.GameMode; +import io.anuke.mindustry.game.RulePreset; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.ui.BorderImage; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.scene.event.Touchable; -import io.anuke.ucore.scene.ui.ButtonGroup; -import io.anuke.ucore.scene.ui.ImageButton; -import io.anuke.ucore.scene.ui.ScrollPane; -import io.anuke.ucore.scene.ui.TextButton; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.*; public class CustomGameDialog extends FloatingDialog{ + Difficulty difficulty = Difficulty.normal; + RulePreset lastPreset = RulePreset.survival; public CustomGameDialog(){ - super("$text.customgame"); + super("$customgame"); addCloseButton(); shown(this::setup); @@ -31,35 +31,36 @@ public class CustomGameDialog extends FloatingDialog{ } void setup(){ - content().clear(); + state.rules = lastPreset.get(); + cont.clear(); Table maps = new Table(); maps.marginRight(14); ScrollPane pane = new ScrollPane(maps); pane.setFadeScrollBars(false); - int maxwidth = (Gdx.graphics.getHeight() > Gdx.graphics.getHeight() ? 2 : 4); + int maxwidth = (Core.graphics.getHeight() > Core.graphics.getHeight() ? 2 : 4); Table selmode = new Table(); ButtonGroup group = new ButtonGroup<>(); - selmode.add("$text.level.mode").padRight(15f); + selmode.add("$level.mode").padRight(15f); int i = 0; Table modes = new Table(); modes.marginBottom(5); - for(GameMode mode : GameMode.values()){ - if(mode.hidden) continue; - - modes.addButton("$mode." + mode.name() + ".name", "toggle", () -> state.mode = mode) - .update(b -> b.setChecked(state.mode == mode)).group(group).size(140f, 54f); + for(RulePreset mode : RulePreset.values()){ + 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); selmode.addButton("?", this::displayGameModeHelp).width(50f).fillY().padLeft(18f); - content().add(selmode); - content().row(); + cont.add(selmode); + cont.row(); Difficulty[] ds = Difficulty.values(); @@ -68,24 +69,25 @@ public class CustomGameDialog extends FloatingDialog{ Table sdif = new Table(); sdif.add("$setting.difficulty.name").padRight(15f); - sdif.defaults().height(s + 4); sdif.addImageButton("icon-arrow-left", 10 * 3, () -> { - state.difficulty = (ds[Mathf.mod(state.difficulty.ordinal() - 1, ds.length)]); + difficulty = (ds[Mathf.mod(difficulty.ordinal() - 1, ds.length)]); + state.wavetime = difficulty.waveTime; }).width(s); sdif.addButton("", () -> {}) .update(t -> { - t.setText(state.difficulty.toString()); - t.setTouchable(Touchable.disabled); + t.setText(difficulty.toString()); + t.touchable(Touchable.disabled); }).width(180f); sdif.addImageButton("icon-arrow-right", 10 * 3, () -> { - state.difficulty = (ds[Mathf.mod(state.difficulty.ordinal() + 1, ds.length)]); + difficulty = (ds[Mathf.mod(difficulty.ordinal() + 1, ds.length)]); + state.wavetime = difficulty.waveTime; }).width(s); - content().add(sdif); - content().row(); + cont.add(sdif); + cont.row(); float images = 146f; @@ -104,7 +106,7 @@ public class CustomGameDialog extends FloatingDialog{ image.row(); image.add("[accent]" + map.getDisplayName()).pad(3f).growX().wrap().get().setAlignment(Align.center, Align.center); image.row(); - image.label((() -> Bundles.format("text.level.highscore", Settings.getInt("hiscore" + map.name, 0)))).pad(3f); + image.label((() -> Core.bundle.format("level.highscore", Core.settings.getInt("hiscore" + map.name, 0)))).pad(3f); BorderImage border = new BorderImage(map.texture, 3f); border.setScaling(Scaling.fit); @@ -112,7 +114,7 @@ public class CustomGameDialog extends FloatingDialog{ image.clicked(() -> { hide(); - control.playMap(map); + control.playMap(map, lastPreset.get()); }); maps.add(image); @@ -120,36 +122,28 @@ 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("$text.map.random"); - if(world.maps.all().size == 0){ - maps.add("$text.maps.none").pad(50); + maps.add("$maps.none").pad(50); } - content().add(pane).uniformX(); + cont.add(pane).uniformX(); } private void displayGameModeHelp(){ - FloatingDialog d = new FloatingDialog(Bundles.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); ScrollPane pane = new ScrollPane(table); pane.setFadeScrollBars(false); table.row(); - for(GameMode mode : GameMode.values()){ - if(mode.hidden) continue; + for(RulePreset mode : RulePreset.values()){ table.labelWrap("[accent]" + mode.toString() + ":[] [lightgray]" + mode.description()).width(400f); table.row(); } - d.content().add(pane); - d.buttons().addButton("$text.ok", d::hide).size(110, 50).pad(10f); + d.cont.add(pane); + d.buttons.addButton("$ok", d::hide).size(110, 50).pad(10f); d.show(); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/UnlocksDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java similarity index 58% rename from core/src/io/anuke/mindustry/ui/dialogs/UnlocksDialog.java rename to core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java index a1d58ea766..879a9340e1 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/UnlocksDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java @@ -1,25 +1,24 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.utils.Array; +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.graphics.Pal; import io.anuke.mindustry.type.ContentType; -import io.anuke.ucore.scene.event.HandCursorListener; -import io.anuke.ucore.scene.ui.Image; -import io.anuke.ucore.scene.ui.ScrollPane; -import io.anuke.ucore.scene.ui.Tooltip; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.utils.UIUtils; +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.content; -import static io.anuke.mindustry.Vars.control; +import static io.anuke.mindustry.Vars.*; -public class UnlocksDialog extends FloatingDialog{ +public class DatabaseDialog extends FloatingDialog{ - public UnlocksDialog(){ - super("$text.unlocks"); + public DatabaseDialog(){ + super("database"); shouldPause = true; addCloseButton(); @@ -28,42 +27,40 @@ public class UnlocksDialog extends FloatingDialog{ } void rebuild(){ - content().clear(); + cont.clear(); Table table = new Table(); table.margin(20); ScrollPane pane = new ScrollPane(table); - Array[] allContent = content.getContentMap(); + Array[] allContent = Vars.content.getContentMap(); 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 = control.unlocks.isUnlocked(unlock) ? new Image(unlock.getContentIcon()) : new Image("icon-locked"); + Image image = data.isUnlocked(unlock) ? new Image(unlock.getContentIcon()) : new Image("icon-tree-locked"); image.addListener(new HandCursorListener()); list.add(image).size(size).pad(3); - if(control.unlocks.isUnlocked(unlock)){ + if(data.isUnlocked(unlock)){ image.clicked(() -> Vars.ui.content.show(unlock)); image.addListener(new Tooltip<>(new Table("button"){{ add(unlock.localizedName()); @@ -78,6 +75,6 @@ public class UnlocksDialog extends FloatingDialog{ table.row(); } - content().add(pane); + cont.add(pane); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java new file mode 100644 index 0000000000..a3427894e8 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java @@ -0,0 +1,257 @@ +package io.anuke.mindustry.ui.dialogs; + +import io.anuke.arc.Core; +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.Zone; +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(""); + + ZoneNode root = new ZoneNode(Zones.groundZero, null); + + 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); + + shown(this::setup); + } + + public void setup(){ + cont.clear(); + titleTable.remove(); + margin(0f).marginBottom(8); + + cont.stack(control.saves.getZoneSlot() == null ? new View() : new Table(){{ + SaveSlot slot = control.saves.getZoneSlot(); + + TextButton[] b = {null}; + + TextButton button = addButton(Core.bundle.format("resume", slot.getZone().localizedName()), () -> { + if(b[0].childrenPressed()) return; + + 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; + + 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); + + }}, new ItemsDisplay()).grow(); + } + + boolean hidden(Zone zone){ + for(Zone other : zone.zoneRequirements){ + if(!data.isUnlocked(other)){ + return true; + } + } + 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.table(title -> { + button.addImage("icon-zone").padRight(3); + button.labelWrap(zone.localizedName()).width(140).growX(); + //}); + + //if(data.getWaveScore(zone) > 0){ + // button.add(Core.bundle.format("bestwave", data.getWaveScore(zone))); + //} + + /* + 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"); + + /*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(other) ? "icon-check-2" : "icon-cancel-2") + .color(data.isCompleted(other) ? 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(); + } + }*/ + } + } + + //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; + }); + } + + @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); + } + } + } +} diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java index e4571b2447..b21e875749 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java @@ -1,9 +1,9 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.ucore.scene.ui.Dialog; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.arc.scene.ui.Dialog; import static io.anuke.mindustry.Vars.discordURL; import static io.anuke.mindustry.Vars.ui; @@ -15,11 +15,11 @@ public class DiscordDialog extends Dialog{ float h = 70f; - content().margin(12f); + cont.margin(12f); Color color = Color.valueOf("7289da"); - content().table(t -> { + cont.table(t -> { t.background("button").margin(0); t.table(img -> { @@ -33,19 +33,19 @@ public class DiscordDialog extends Dialog{ i.addImage("icon-discord").size(14 * 3); }).size(h).left(); - t.add("$text.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); + buttons.defaults().size(170f, 50); - buttons().addButton("$text.back", this::hide); - buttons().addButton("$text.copylink", () -> { - Gdx.app.getClipboard().setContents(discordURL); + buttons.addButton("$back", this::hide); + buttons.addButton("$copylink", () -> { + Core.app.getClipboard().setContents(discordURL); }); - buttons().addButton("$text.openlink", () -> { - if(!Gdx.net.openURI(discordURL)){ - ui.showError("$text.linkfail"); - Gdx.app.getClipboard().setContents(discordURL); + buttons.addButton("$openlink", () -> { + if(!Core.net.openURI(discordURL)){ + ui.showError("$linkfail"); + Core.app.getClipboard().setContents(discordURL); } }); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java b/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java index b608f3527c..a6e42fa975 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java @@ -1,23 +1,22 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.graphics.g2d.GlyphLayout; -import com.badlogic.gdx.utils.Align; -import com.badlogic.gdx.utils.Array; +import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.function.Predicate; +import io.anuke.arc.graphics.g2d.GlyphLayout; +import io.anuke.arc.scene.event.Touchable; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.scene.ui.layout.Unit; +import io.anuke.arc.scene.utils.UIUtils; +import io.anuke.arc.util.Align; +import io.anuke.arc.util.OS; +import io.anuke.arc.util.Time; +import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.Platform; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.function.Predicate; -import io.anuke.ucore.scene.event.Touchable; -import io.anuke.ucore.scene.ui.*; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.scene.utils.UIUtils; -import io.anuke.ucore.util.OS; -import io.anuke.ucore.util.Pooling; import java.util.Arrays; @@ -27,8 +26,8 @@ public class FileChooser extends FloatingDialog{ public static Predicate jpegFilter = file -> file.extension().equalsIgnoreCase("png") || file.extension().equalsIgnoreCase("jpg") || file.extension().equalsIgnoreCase("jpeg"); public static Predicate defaultFilter = file -> true; private Table files; - private FileHandle homeDirectory = Gdx.files.absolute(OS.isMac ? OS.getProperty("user.home") + "/Downloads/" : - Gdx.files.getExternalStoragePath()); + private FileHandle homeDirectory = Core.files.absolute(OS.isMac ? OS.getProperty("user.home") + "/Downloads/" : + Core.files.getExternalStoragePath()); private FileHandle directory = homeDirectory; private ScrollPane pane; private TextField navigation, filefield; @@ -46,7 +45,7 @@ public class FileChooser extends FloatingDialog{ } private void setupWidgets(){ - content().margin(-10); + cont.margin(-10); Table content = new Table(); @@ -55,7 +54,7 @@ public class FileChooser extends FloatingDialog{ if(!open) Platform.instance.addDialog(filefield); filefield.setDisabled(open); - ok = new TextButton(open ? "$text.load" : "$text.save"); + ok = new TextButton(open ? "$load" : "$save"); ok.clicked(() -> { if(ok.isDisabled()) return; @@ -70,11 +69,11 @@ public class FileChooser extends FloatingDialog{ filefield.change(); - TextButton cancel = new TextButton("$text.cancel"); + TextButton cancel = new TextButton("$cancel"); cancel.clicked(this::hide); navigation = new TextField(""); - navigation.setTouchable(Touchable.disabled); + navigation.touchable(Touchable.disabled); files = new Table(); files.marginRight(10); @@ -82,7 +81,7 @@ public class FileChooser extends FloatingDialog{ pane = new ScrollPane(files){ public float getPrefHeight(){ - return Gdx.graphics.getHeight(); + return Core.graphics.getHeight(); } }; pane.setOverscroll(false, false); @@ -130,7 +129,7 @@ public class FileChooser extends FloatingDialog{ icontable.add(up); Table fieldcontent = new Table(); - fieldcontent.bottom().left().add(new Label("$text.filename")); + fieldcontent.bottom().left().add(new Label("$filename")); fieldcontent.add(filefield).height(40f).fillX().expandX().padLeft(10f); Table buttons = new Table(); @@ -142,7 +141,7 @@ public class FileChooser extends FloatingDialog{ content.add(icontable).expandX().fillX(); content.row(); - content.center().add(pane).width(UIUtils.portrait() ? Gdx.graphics.getWidth() / Unit.dp.scl(1) : Gdx.graphics.getWidth() / Unit.dp.scl(2)).colspan(3).grow(); + content.center().add(pane).width(UIUtils.portrait() ? Core.graphics.getWidth() / Unit.dp.scl(1) : Core.graphics.getWidth() / Unit.dp.scl(2)).colspan(3).grow(); content.row(); if(!open){ @@ -152,7 +151,7 @@ public class FileChooser extends FloatingDialog{ content.add(buttons).growX(); - content().add(content); + cont.add(content); } private void updateFileFieldStatus(){ @@ -179,9 +178,9 @@ public class FileChooser extends FloatingDialog{ //if is mac, don't display extra info since you can only ever go to downloads navigation.setText(OS.isMac ? directory.name() : directory.toString()); - GlyphLayout layout = Pooling.obtain(GlyphLayout.class, GlyphLayout::new); + GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new); - layout.setText(Core.font, navigation.getText()); + layout.setText(Core.scene.skin.getFont("default-font"), navigation.getText()); if(layout.width < navigation.getWidth()){ navigation.setCursorPosition(0); @@ -189,7 +188,7 @@ public class FileChooser extends FloatingDialog{ navigation.setCursorPosition(navigation.getText().length()); } - Pooling.free(layout); + Pools.free(layout); files.clearChildren(); files.top().left(); @@ -264,8 +263,8 @@ public class FileChooser extends FloatingDialog{ @Override public Dialog show(){ - Timers.runTask(2f, () -> { - content().clear(); + Time.runTask(2f, () -> { + cont.clear(); setupWidgets(); super.show(); Core.scene.setScrollFocus(pane); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java index 600c59c193..4ad7908bec 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java @@ -1,16 +1,15 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.utils.Align; +import io.anuke.arc.Core; +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.ucore.core.Core; -import io.anuke.ucore.core.Events; -import io.anuke.ucore.scene.ui.Dialog; -import io.anuke.ucore.scene.ui.ScrollPane; +import io.anuke.arc.Events; +import io.anuke.arc.scene.ui.Dialog; +import io.anuke.arc.scene.ui.ScrollPane; import static io.anuke.mindustry.Vars.state; @@ -21,9 +20,9 @@ public class FloatingDialog extends Dialog{ public FloatingDialog(String title){ super(title, "dialog"); setFillParent(true); - title().setAlignment(Align.center); - getTitleTable().row(); - getTitleTable().addImage("white", Palette.accent) + this.title.setAlignment(Align.center); + titleTable.row(); + titleTable.addImage("white", Pal.accent) .growX().height(3f).pad(4f); hidden(() -> { @@ -43,7 +42,7 @@ public class FloatingDialog extends Dialog{ boolean[] done = {false}; - shown(() -> Gdx.app.postRunnable(() -> + shown(() -> Core.app.post(() -> forEach(child -> { if(done[0]) return; @@ -64,11 +63,11 @@ public class FloatingDialog extends Dialog{ @Override public void addCloseButton(){ - buttons().addImageTextButton("$text.back", "icon-arrow-left", 30f, this::hide).size(230f, 64f); + buttons.addImageTextButton("$back", "icon-arrow-left", 30f, this::hide).size(230f, 64f); keyDown(key -> { - if(key == Keys.ESCAPE || key == Keys.BACK) { - Gdx.app.postRunnable(this::hide); + if(key == KeyCode.ESCAPE || key == KeyCode.BACK) { + Core.app.post(this::hide); } }); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/GameOverDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/GameOverDialog.java new file mode 100644 index 0000000000..a2fc45017c --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/dialogs/GameOverDialog.java @@ -0,0 +1,88 @@ +package io.anuke.mindustry.ui.dialogs; + +import io.anuke.arc.Core; +import io.anuke.mindustry.core.GameState.State; +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.*; + +public class GameOverDialog extends FloatingDialog{ + private Team winner; + + public GameOverDialog(){ + super("$gameover"); + setFillParent(false); + shown(this::rebuild); + } + + public void show(Team winner){ + this.winner = winner; + show(); + } + + void rebuild(){ + title.setText(state.launched ? "$launch.title" : "$gameover"); + buttons.clear(); + cont.clear(); + + buttons.margin(10); + + if(state.rules.pvp){ + cont.add(Core.bundle.format("gameover.pvp",winner.localized())).pad(6); + buttons.addButton("$menu", () -> { + hide(); + state.set(State.menu); + logic.reset(); + }).size(130f, 60f); + }else{ + if(control.isHighScore()){ + cont.add("$highscore").pad(6); + cont.row(); + } + + cont.table(t -> { + cont.left().defaults().left(); + cont.add(Core.bundle.format("stat.wave", state.stats.wavesLasted)); + cont.row(); + cont.add(Core.bundle.format("stat.enemiesDestroyed", state.stats.enemyUnitsDestroyed)); + cont.row(); + cont.add(Core.bundle.format("stat.built", state.stats.buildingsBuilt)); + cont.row(); + cont.add(Core.bundle.format("stat.destroyed", state.stats.buildingsDestroyed)); + cont.row(); + cont.add(Core.bundle.format("stat.deconstructed", state.stats.buildingsDeconstructed)); + cont.row(); + if(world.isZone() && !state.stats.itemsDelivered.isEmpty()){ + cont.add("$stat.delivered"); + cont.row(); + for(Item item : content.items()){ + if(state.stats.itemsDelivered.get(item, 0) > 0){ + cont.table(items -> { + items.add(" [LIGHT_GRAY]" + state.stats.itemsDelivered.get(item, 0)); + items.addImage(item.icon(Icon.medium)).size(8 *3).pad(4); + }).left(); + cont.row(); + } + } + } + }).pad(12); + + if(world.isZone()){ + buttons.addButton("$continue", () -> { + hide(); + state.set(State.menu); + logic.reset(); + ui.deploy.show(); + }).size(130f, 60f); + }else{ + buttons.addButton("$menu", () -> { + hide(); + state.set(State.menu); + logic.reset(); + }).size(130f, 60f); + } + } + } +} diff --git a/core/src/io/anuke/mindustry/ui/dialogs/GenViewDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/GenViewDialog.java deleted file mode 100644 index 64a8a21bec..0000000000 --- a/core/src/io/anuke/mindustry/ui/dialogs/GenViewDialog.java +++ /dev/null @@ -1,107 +0,0 @@ -package io.anuke.mindustry.ui.dialogs; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.Pixmap.Format; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.async.AsyncExecutor; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.maps.generation.WorldGenerator.GenResult; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.ColorMapper; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.scene.Element; -import io.anuke.ucore.scene.event.InputEvent; -import io.anuke.ucore.scene.event.InputListener; -import io.anuke.ucore.scene.utils.Cursors; -import io.anuke.ucore.util.GridMap; -import io.anuke.ucore.util.Mathf; - -import static io.anuke.mindustry.Vars.sectorSize; -import static io.anuke.mindustry.Vars.world; - -public class GenViewDialog extends FloatingDialog{ - Array ores = Array.with(Items.copper, Items.lead, Items.coal); - - public GenViewDialog(){ - super("generate view"); - - content().add(new GenView()).grow(); - } - - public class GenView extends Element{ - GridMap map = new GridMap<>(); - GridMap processing = new GridMap<>(); - float panX, panY; - float lastX, lastY; - int viewsize = 3; - AsyncExecutor async = new AsyncExecutor(Mathf.sqr(viewsize*2)); - - { - addListener(new InputListener(){ - @Override - public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){ - Cursors.setHand(); - lastX = x; - lastY = y; - return true; - } - - @Override - public void touchDragged(InputEvent event, float x, float y, int pointer){ - panX -= x - lastX; - panY -= y - lastY; - - lastX = x; - lastY = y; - } - - @Override - public void touchUp(InputEvent event, float x, float y, int pointer, int button){ - Cursors.restoreCursor(); - } - }); - } - - public void draw(){ - float padSectorSize = 200f; - int tx = (int)(panX / padSectorSize); - int ty = (int)(panY / padSectorSize); - - Draw.color(); - - for(int x = -viewsize; x <= viewsize; x++){ - for(int y = -viewsize; y <= viewsize; y++){ - int wx = tx + x, wy = ty + y; - if(map.get(wx, wy) == null){ - if(processing.get(wx, wy) == Boolean.TRUE){ - continue; - } - processing.put(wx, wy, true); - async.submit(() -> { - GenResult result = new GenResult(); - Pixmap pixmap = new Pixmap(sectorSize, sectorSize, Format.RGBA8888); - for(int i = 0; i < sectorSize; i++){ - for(int j = 0; j < sectorSize; j++){ - world.generator.generateTile(result, wx, wy, i, j, true, null, ores); - pixmap.drawPixel(i, sectorSize - 1 - j, ColorMapper.colorFor(result.floor, result.wall, Team.none, result.elevation, (byte)0)); - } - } - Gdx.app.postRunnable(() -> map.put(wx, wy, new Texture(pixmap))); - return pixmap; - }); - - continue; - } - - float drawX = x + width/2f+ wx * padSectorSize - tx * padSectorSize - panX % padSectorSize; - float drawY = y + height/2f + wy * padSectorSize - ty * padSectorSize - panY % padSectorSize; - - Draw.rect(map.get(wx, wy), drawX, drawY, padSectorSize, padSectorSize); - } - } - } - } -} diff --git a/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java index b896ec75fd..8771012793 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java @@ -1,14 +1,13 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.graphics.Color; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; +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 io.anuke.ucore.core.Settings; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.scene.ui.ImageButton; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Strings; import java.io.IOException; @@ -19,54 +18,54 @@ public class HostDialog extends FloatingDialog{ float w = 300; public HostDialog(){ - super("$text.hostserver"); + super("$hostserver"); Player player = players[0]; addCloseButton(); - content().table(t -> { - t.add("$text.name").padRight(10); - t.addField(Settings.getString("name"), text -> { + cont.table(t -> { + t.add("$name").padRight(10); + t.addField(Core.settings.getString("name"), text -> { player.name = text; - Settings.put("name", text); - Settings.save(); + Core.settings.put("name", text); + Core.settings.save(); ui.listfrag.rebuild(); }).grow().pad(8).get().setMaxLength(40); ImageButton button = t.addImageButton("white", "clear-full", 40, () -> { new ColorPickDialog().show(color -> { player.color.set(color); - Settings.putInt("color-0", Color.rgba8888(color)); - Settings.save(); + Core.settings.put("color-0", Color.rgba8888(color)); + Core.settings.save(); }); }).size(54f).get(); button.update(() -> button.getStyle().imageUpColor = player.color); }).width(w).height(70f).pad(4).colspan(3); - content().row(); + cont.row(); - content().add().width(65f); + cont.add().width(65f); - content().addButton("$text.host", () -> { - if(Settings.getString("name").trim().isEmpty()){ - ui.showInfo("$text.noname"); + cont.addButton("$host", () -> { + if(Core.settings.getString("name").trim().isEmpty()){ + ui.showInfo("$noname"); return; } - ui.loadfrag.show("$text.hosting"); - Timers.runTask(5f, () -> { + ui.loadfrag.show("$hosting"); + Time.runTask(5f, () -> { try{ Net.host(Vars.port); player.isAdmin = true; }catch(IOException e){ - ui.showError(Bundles.format("text.server.error", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("server.error", Strings.parseException(e, false))); } ui.loadfrag.hide(); hide(); }); }).width(w).height(70f); - content().addButton("?", () -> ui.showInfo("$text.host.info")).size(65f, 70f).padLeft(6f); + cont.addButton("?", () -> ui.showInfo("$host.info")).size(65f, 70f).padLeft(6f); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java index 853f758f57..91a263aa7c 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java @@ -1,24 +1,23 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.MathUtils; -import com.badlogic.gdx.utils.Array; import io.anuke.annotations.Annotations.Serialize; +import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.scene.style.Drawable; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.layout.Cell; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.scene.utils.UIUtils; +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; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.scene.style.Drawable; -import io.anuke.ucore.scene.ui.*; -import io.anuke.ucore.scene.ui.layout.Cell; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.utils.UIUtils; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Strings; import static io.anuke.mindustry.Vars.*; @@ -32,50 +31,50 @@ public class JoinDialog extends FloatingDialog{ int totalHosts; public JoinDialog(){ - super("$text.joingame"); + super("$joingame"); loadServers(); - buttons().add().width(60f); - buttons().add().growX(); + buttons.add().width(60f); + buttons.add().growX(); addCloseButton(); - buttons().add().growX(); - buttons().addButton("?", () -> ui.showInfo("$text.join.info")).size(60f, 64f); + buttons.add().growX(); + buttons.addButton("?", () -> ui.showInfo("$join.info")).size(60f, 64f); - add = new FloatingDialog("$text.joingame.title"); - add.content().add("$text.joingame.ip").padRight(5f).left(); + add = new FloatingDialog("$joingame.title"); + add.cont.add("$joingame.ip").padRight(5f).left(); - TextField field = add.content().addField(Settings.getString("ip"), text -> { - Settings.putString("ip", text); - Settings.save(); + TextField field = add.cont.addField(Core.settings.getString("ip"), text -> { + Core.settings.put("ip", text); + Core.settings.save(); }).size(320f, 54f).get(); Platform.instance.addDialog(field, 100); - add.content().row(); - add.buttons().defaults().size(140f, 60f).pad(4f); - add.buttons().addButton("$text.cancel", add::hide); - add.buttons().addButton("$text.ok", () -> { + add.cont.row(); + add.buttons.defaults().size(140f, 60f).pad(4f); + add.buttons.addButton("$cancel", add::hide); + add.buttons.addButton("$ok", () -> { if(renaming == null){ Server server = new Server(); - server.setIP(Settings.getString("ip")); + server.setIP(Core.settings.getString("ip")); servers.add(server); saveServers(); setupRemote(); refreshRemote(); }else{ - renaming.setIP(Settings.getString("ip")); + renaming.setIP(Core.settings.getString("ip")); saveServers(); setupRemote(); refreshRemote(); } add.hide(); - }).disabled(b -> Settings.getString("ip").isEmpty() || Net.active()); + }).disabled(b -> Core.settings.getString("ip").isEmpty() || Net.active()); add.shown(() -> { - add.getTitleLabel().setText(renaming != null ? "$text.server.edit" : "$text.server.add"); + add.title.setText(renaming != null ? "$server.edit" : "$server.add"); if(renaming != null){ field.setText(renaming.displayIP()); } @@ -120,7 +119,7 @@ public class JoinDialog extends FloatingDialog{ }).margin(3f).padTop(6f).top().right(); inner.addImageButton("icon-trash-16", "empty", 16 * 2, () -> { - ui.showConfirm("$text.confirm", "$text.server.delete", () -> { + ui.showConfirm("$confirm", "$server.delete", () -> { servers.removeValue(server, true); saveServers(); setupRemote(); @@ -145,23 +144,23 @@ public class JoinDialog extends FloatingDialog{ void refreshServer(Server server){ server.content.clear(); - server.content.label(() -> Bundles.get("text.server.refreshing") + Strings.animated(4, 11, ".")); + server.content.label(() -> Core.bundle.get("server.refreshing") + Strings.animated(Time.time(), 4, 11, ".")); Net.pingHost(server.ip, server.port, host -> { String versionString; if(host.version == -1){ - versionString = Bundles.format("text.server.version", Bundles.get("text.server.custombuild"), ""); + versionString = Core.bundle.format("server.version", Core.bundle.get("server.custombuild"), ""); }else if(host.version == 0){ - versionString = Bundles.get("text.server.outdated"); + versionString = Core.bundle.get("server.outdated"); }else if(host.version < Version.build && Version.build != -1){ - versionString = Bundles.get("text.server.outdated") + "\n" + - Bundles.format("text.server.version", host.version, ""); + versionString = Core.bundle.get("server.outdated") + "\n" + + Core.bundle.format("server.version", host.version, ""); }else if(host.version > Version.build && Version.build != -1){ - versionString = Bundles.get("text.server.outdated.client") + "\n" + - Bundles.format("text.server.version", host.version, ""); + versionString = Core.bundle.get("server.outdated.client") + "\n" + + Core.bundle.format("server.version", host.version, ""); }else{ - versionString = Bundles.format("text.server.version", host.version, host.versionType); + versionString = Core.bundle.format("server.version", host.version, host.versionType); } server.content.clear(); @@ -169,17 +168,17 @@ public class JoinDialog extends FloatingDialog{ server.content.table(t -> { t.add(versionString).left(); t.row(); - t.add("[lightgray]" + Bundles.format("text.server.hostname", host.name)).left(); + t.add("[lightgray]" + Core.bundle.format("server.hostname", host.name)).left(); t.row(); - t.add("[lightgray]" + (host.players != 1 ? Bundles.format("text.players", host.players) : - Bundles.format("text.players.single", host.players))).left(); + t.add("[lightgray]" + (host.players != 1 ? Core.bundle.format("players", host.players) : + Core.bundle.format("players.single", host.players))).left(); t.row(); - t.add("[lightgray]" + Bundles.format("text.save.map", host.mapname) + " / " + Bundles.format("text.save.wave", host.wave)).left(); + t.add("[lightgray]" + Core.bundle.format("save.map", host.mapname) + " / " + Core.bundle.format("save.wave", host.wave)).left(); }).expand().left().bottom().padLeft(12f).padBottom(8); }, e -> { server.content.clear(); - server.content.add("$text.host.invalid"); + server.content.add("$host.invalid"); }); } @@ -201,28 +200,28 @@ public class JoinDialog extends FloatingDialog{ setupRemote(); refreshRemote(); - content().clear(); - content().table(t -> { - t.add("$text.name").padRight(10); - t.addField(Settings.getString("name"), text -> { + cont.clear(); + cont.table(t -> { + t.add("$name").padRight(10); + t.addField(Core.settings.getString("name"), text -> { player.name = text; - Settings.put("name", text); - Settings.save(); + Core.settings.put("name", text); + Core.settings.save(); }).grow().pad(8).get().setMaxLength(maxNameLength); ImageButton button = t.addImageButton("white", "clear-full", 40, () -> { new ColorPickDialog().show(color -> { player.color.set(color); - Settings.putInt("color-0", Color.rgba8888(color)); - Settings.save(); + Core.settings.put("color-0", Color.rgba8888(color)); + Core.settings.save(); }); }).size(54f).get(); button.update(() -> button.getStyle().imageUpColor = player.color); }).width(w).height(70f).pad(4); - content().row(); - content().add(pane).width(w + 38).pad(0); - content().row(); - content().addCenteredImageTextButton("$text.server.add", "icon-add", 14 * 3, () -> { + cont.row(); + cont.add(pane).width(w + 38).pad(0); + cont.row(); + cont.addCenteredImageTextButton("$server.add", "icon-add", 14 * 3, () -> { renaming = null; add.show(); }).marginLeft(6).width(w).height(80f).update(button -> { @@ -233,9 +232,9 @@ public class JoinDialog extends FloatingDialog{ pad = 6; } - Cell cell = ((Table) pane.getParent()).getCell(button); + Cell cell = ((Table) pane.getParent()).getCell(button); - if(!MathUtils.isEqual(cell.getMinWidth(), pw)){ + if(!Mathf.isEqual(cell.getMinWidth(), pw)){ cell.width(pw); cell.padLeft(pad); pane.getParent().invalidateHierarchy(); @@ -248,7 +247,7 @@ public class JoinDialog extends FloatingDialog{ local.clear(); local.background((Drawable)null); - local.table("button", t -> t.label(() -> "[accent]" + Bundles.get("text.hosts.discovering") + Strings.animated(4, 10f, ".")).pad(10f)).growX(); + local.table("button", t -> t.label(() -> "[accent]" + Core.bundle.get("hosts.discovering") + Strings.animated(Time.time(), 4, 10f, ".")).pad(10f)).growX(); Net.discoverServers(this::addLocalHost, this::finishLocalHosts); } @@ -256,7 +255,7 @@ public class JoinDialog extends FloatingDialog{ if(totalHosts == 0){ local.clear(); local.background("button"); - local.add("$text.hosts.none").pad(10f); + local.add("$hosts.none").pad(10f); local.add().growX(); local.addImageButton("icon-loading", 16 * 2f, this::refreshLocal).pad(-12f).padLeft(0).size(70f); }else{ @@ -278,24 +277,24 @@ public class JoinDialog extends FloatingDialog{ .width(w).height(80f).pad(4f).get(); button.left(); button.row(); - button.add("[lightgray]" + (host.players != 1 ? Bundles.format("text.players", host.players) : - Bundles.format("text.players.single", host.players))).padBottom(5); + button.add("[lightgray]" + (host.players != 1 ? Core.bundle.format("players", host.players) : + Core.bundle.format("players.single", host.players))).padBottom(5); } void connect(String ip, int port){ - if(Settings.getString("name").trim().isEmpty()){ - ui.showInfo("$text.noname"); + if(Core.settings.getString("name").trim().isEmpty()){ + ui.showInfo("$noname"); return; } - ui.loadfrag.show("$text.connecting"); + ui.loadfrag.show("$connecting"); ui.loadfrag.setButton(() -> { ui.loadfrag.hide(); netClient.disconnectQuietly(); }); - Timers.runTask(2f, () -> { + Time.runTask(2f, () -> { Vars.netClient.beginConnecting(); Net.connect(ip, port, () -> { hide(); @@ -310,12 +309,12 @@ public class JoinDialog extends FloatingDialog{ @SuppressWarnings("unchecked") private void loadServers(){ - servers = Settings.getObject("server-list", Array.class, Array::new); + servers = Core.settings.getObject("server-list", Array.class, Array::new); } private void saveServers(){ - Settings.putObject("server-list", servers); - Settings.save(); + Core.settings.putObject("server-list", servers); + Core.settings.save(); } @Serialize diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java index a7a05f4433..53317eca9e 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.ui.dialogs; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.scene.ui.ButtonGroup; -import io.anuke.ucore.scene.ui.ScrollPane; -import io.anuke.ucore.scene.ui.TextButton; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Log; +import io.anuke.arc.Core; +import io.anuke.arc.scene.ui.ButtonGroup; +import io.anuke.arc.scene.ui.ScrollPane; +import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.util.Log; import java.util.Locale; @@ -16,7 +16,7 @@ public class LanguageDialog extends FloatingDialog{ private Locale lastLocale; public LanguageDialog(){ - super("$text.settings.language"); + super("$settings.language"); addCloseButton(); setup(); } @@ -33,19 +33,19 @@ public class LanguageDialog extends FloatingDialog{ TextButton button = new TextButton(loc.getDisplayName(loc), "toggle"); button.clicked(() -> { if(getLocale().equals(loc)) return; - Settings.putString("locale", loc.toString()); - Settings.save(); + Core.settings.put("locale", loc.toString()); + Core.settings.save(); Log.info("Setting locale: {0}", loc.toString()); - ui.showInfo("$text.language.restart"); + ui.showInfo("$language.restart"); }); langs.add(button).group(group).update(t -> t.setChecked(loc.equals(getLocale()))).size(400f, 50f).pad(2).row(); } - content().add(pane); + cont.add(pane); } public Locale getLocale(){ - String loc = Settings.getString("locale"); + String loc = Core.settings.getString("locale"); if(loc.equals("default")){ findClosestLocale(); @@ -67,7 +67,7 @@ public class LanguageDialog extends FloatingDialog{ //check exact locale for(Locale l : locales){ if(l.equals(Locale.getDefault())){ - Settings.putString("locale", l.toString()); + Core.settings.put("locale", l.toString()); return; } } @@ -75,11 +75,11 @@ public class LanguageDialog extends FloatingDialog{ //find by language for(Locale l : locales){ if(l.getLanguage().equals(Locale.getDefault().getLanguage())){ - Settings.putString("locale", l.toString()); + Core.settings.put("locale", l.toString()); return; } } - Settings.putString("locale", new Locale("en").toString()); + Core.settings.put("locale", new Locale("en").toString()); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java index d402ed9eeb..1bfccbc6df 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java @@ -1,21 +1,20 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.utils.Array; +import io.anuke.arc.Core; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.collection.Array; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.game.Saves.SaveSlot; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.scene.ui.ScrollPane; -import io.anuke.ucore.scene.ui.TextButton; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.Strings; +import io.anuke.arc.util.Time; +import io.anuke.arc.scene.ui.ScrollPane; +import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.util.Log; +import io.anuke.arc.util.Strings; +import io.anuke.mindustry.io.SaveIO.SaveException; import java.io.IOException; @@ -26,7 +25,7 @@ public class LoadDialog extends FloatingDialog{ Table slots; public LoadDialog(){ - this("$text.loadgame"); + this("$loadgame"); } public LoadDialog(String title){ @@ -35,14 +34,14 @@ public class LoadDialog extends FloatingDialog{ shown(() -> { setup(); - Timers.runTask(2f, () -> Core.scene.setScrollFocus(pane)); + Time.runTask(2f, () -> Core.scene.setScrollFocus(pane)); }); addCloseButton(); } protected void setup(){ - content().clear(); + cont.clear(); slots = new Table(); pane = new ScrollPane(slots); @@ -51,7 +50,7 @@ public class LoadDialog extends FloatingDialog{ slots.marginRight(24); - Timers.runTask(2f, () -> Core.scene.setScrollFocus(pane)); + Time.runTask(2f, () -> Core.scene.setScrollFocus(pane)); Array array = control.saves.getSaveSlots(); @@ -73,14 +72,14 @@ public class LoadDialog extends FloatingDialog{ }).checked(slot.isAutosave()).right(); t.addImageButton("icon-trash", "empty", 14 * 3, () -> { - ui.showConfirm("$text.confirm", "$text.save.delete.confirm", () -> { + ui.showConfirm("$confirm", "$save.delete.confirm", () -> { slot.delete(); setup(); }); }).size(14 * 3).right(); t.addImageButton("icon-pencil-small", "empty", 14 * 3, () -> { - ui.showTextInput("$text.save.rename", "$text.save.rename.text", slot.getName(), text -> { + ui.showTextInput("$save.rename", "$save.rename.text", slot.getName(), text -> { slot.setName(text); setup(); }); @@ -88,21 +87,21 @@ public class LoadDialog extends FloatingDialog{ t.addImageButton("icon-save", "empty", 14 * 3, () -> { if(!ios){ - Platform.instance.showFileChooser(Bundles.get("text.save.export"), "Mindustry Save", file -> { + Platform.instance.showFileChooser(Core.bundle.get("save.export"), "Mindustry Save", file -> { try{ slot.exportFile(file); setup(); }catch(IOException e){ - ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("save.export.fail", Strings.parseException(e, false))); } }, false, saveExtension); }else{ try{ - FileHandle file = Gdx.files.local("save-" + slot.getName() + "." + Vars.saveExtension); + FileHandle file = Core.files.local("save-" + slot.getName() + "." + Vars.saveExtension); slot.exportFile(file); Platform.instance.shareFile(file); }catch(Exception e){ - ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("save.export.fail", Strings.parseException(e, false))); } } }).size(14 * 3).right(); @@ -114,19 +113,15 @@ public class LoadDialog extends FloatingDialog{ button.defaults().padBottom(3); button.row(); - button.add(Bundles.format("text.save.map", color + (slot.getMap() == null ? "Unknown" : slot.getMap().meta.name()))); + button.add(Core.bundle.format("save.map", color + (slot.getMap() == null ? Core.bundle.get("unknown") : slot.getMap().meta.name()))); button.row(); - button.add(Bundles.get("text.level.mode") + " " + color + slot.getMode()); + button.add(Core.bundle.format("save.wave", color + slot.getWave())); button.row(); - button.add(Bundles.format("text.save.wave", color + slot.getWave())); + button.label(() -> Core.bundle.format("save.autosave", color + Core.bundle.get(slot.isAutosave() ? "on" : "off"))); button.row(); - button.add(Bundles.format("text.save.difficulty", color + slot.getDifficulty())); + button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime())); button.row(); - button.label(() -> Bundles.format("text.save.autosave", color + Bundles.get(slot.isAutosave() ? "text.on" : "text.off"))); - button.row(); - button.label(() -> Bundles.format("text.save.playtime", color + slot.getPlayTime())); - button.row(); - button.add(Bundles.format("text.save.date", color + slot.getDate())).colspan(2).padTop(5).right(); + button.add(Core.bundle.format("save.date", color + slot.getDate())).colspan(2).padTop(5).right(); button.row(); modifyButton(button, slot); @@ -134,7 +129,7 @@ public class LoadDialog extends FloatingDialog{ slots.row(); } - content().add(pane); + cont.add(pane); addSetup(); } @@ -146,7 +141,7 @@ public class LoadDialog extends FloatingDialog{ if(!valids){ slots.row(); - slots.addButton("$text.save.none", () -> { + slots.addButton("$save.none", () -> { }).disabled(true).fillX().margin(20f).minWidth(340f).height(80f).pad(4f); } @@ -154,18 +149,18 @@ public class LoadDialog extends FloatingDialog{ if(ios) return; - slots.addImageTextButton("$text.save.import", "icon-add", 14 * 3, () -> { - Platform.instance.showFileChooser(Bundles.get("text.save.import"), "Mindustry Save", file -> { + slots.addImageTextButton("$save.import", "icon-add", 14 * 3, () -> { + Platform.instance.showFileChooser(Core.bundle.get("save.import"), "Mindustry Save", file -> { if(SaveIO.isSaveValid(file)){ try{ control.saves.importSave(file); setup(); }catch(IOException e){ e.printStackTrace(); - ui.showError(Bundles.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"); } }, true, saveExtension); }).fillX().margin(10f).minWidth(300f).height(70f).pad(4f).padRight(-4); @@ -175,15 +170,15 @@ public class LoadDialog extends FloatingDialog{ hide(); ui.paused.hide(); - ui.loadLogic(() -> { + ui.loadAnd(() -> { try{ slot.load(); state.set(State.playing); - }catch(Exception e){ + }catch(SaveException e){ Log.err(e); state.set(State.menu); logic.reset(); - threads.runGraphics(() -> ui.showError("$text.save.corrupted")); + ui.showError("$save.corrupted"); } }); } @@ -193,7 +188,7 @@ public class LoadDialog extends FloatingDialog{ if(!button.childrenPressed()){ int build = slot.getBuild(); if(SaveIO.breakingVersions.contains(build)){ - ui.showInfo("$text.save.old"); + ui.showInfo("$save.old"); slot.delete(); }else{ runLoadSave(slot); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LocalPlayerDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LocalPlayerDialog.java index 7ef5786ee3..59f23e65ec 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LocalPlayerDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LocalPlayerDialog.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.utils.Scaling; -import io.anuke.mindustry.entities.Player; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.scene.ui.Image; -import io.anuke.ucore.scene.ui.layout.Stack; -import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.arc.Core; +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.type.Player; import static io.anuke.mindustry.Vars.control; import static io.anuke.mindustry.Vars.players; @@ -13,7 +13,7 @@ import static io.anuke.mindustry.Vars.players; public class LocalPlayerDialog extends FloatingDialog{ public LocalPlayerDialog(){ - super("$text.addplayers"); + super("$addplayers"); addCloseButton(); shown(this::rebuild); @@ -22,15 +22,15 @@ public class LocalPlayerDialog extends FloatingDialog{ private void rebuild(){ float size = 140f; - content().clear(); + cont.clear(); if(players.length > 1){ - content().addImageButton("icon-cancel", 14 * 2, () -> { + cont.addImageButton("icon-cancel", 14 * 2, () -> { control.removePlayer(); rebuild(); }).size(50f, size).pad(5).bottom(); }else{ - content().add().size(50f, size); + cont.add().size(50f, size); } for(Player player : players){ @@ -39,7 +39,7 @@ public class LocalPlayerDialog extends FloatingDialog{ stack.add(new Image("button")); - Image img = new Image(Draw.region("icon-chat")); + Image img = new Image(Core.atlas.find("icon-chat")); img.setScaling(Scaling.fill); stack.add(img); @@ -48,11 +48,11 @@ public class LocalPlayerDialog extends FloatingDialog{ table.row(); table.add(stack).size(size); - content().add(table).pad(5); + cont.add(table).pad(5); } if(players.length < 4){ - content().addImageButton("icon-add", 14 * 2, () -> { + cont.addImageButton("icon-add", 14 * 2, () -> { control.addPlayer(players.length); rebuild(); }).size(50f, size).pad(5).bottom(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java index bed08f9954..62cc23e37a 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java @@ -1,7 +1,16 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.utils.Scaling; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.scene.event.Touchable; +import io.anuke.arc.scene.ui.Image; +import io.anuke.arc.scene.ui.ScrollPane; +import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.scene.utils.UIUtils; +import io.anuke.arc.util.Log; +import io.anuke.arc.util.Scaling; +import io.anuke.arc.util.Strings; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.io.MapIO; @@ -9,15 +18,6 @@ import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.maps.MapMeta; import io.anuke.mindustry.maps.MapTileData; import io.anuke.mindustry.ui.BorderImage; -import io.anuke.ucore.scene.event.Touchable; -import io.anuke.ucore.scene.ui.Image; -import io.anuke.ucore.scene.ui.ScrollPane; -import io.anuke.ucore.scene.ui.TextButton; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.utils.UIUtils; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Log; -import io.anuke.ucore.util.Strings; import java.io.DataInputStream; @@ -27,11 +27,11 @@ public class MapsDialog extends FloatingDialog{ private FloatingDialog dialog; public MapsDialog(){ - super("$text.maps"); + super("$maps"); addCloseButton(); - buttons().addImageTextButton("$text.editor.importmap", "icon-add", 14 * 2, () -> { - Platform.instance.showFileChooser("$text.editor.importmap", "Map File", file -> { + buttons.addImageTextButton("$editor.importmap", "icon-add", 14 * 2, () -> { + Platform.instance.showFileChooser("$editor.importmap", "Map File", file -> { try{ DataInputStream stream = new DataInputStream(file.read()); MapMeta meta = MapIO.readMapMeta(stream); @@ -41,9 +41,9 @@ public class MapsDialog extends FloatingDialog{ String name = meta.tags.get("name", file.nameWithoutExtension()); if(world.maps.getByName(name) != null && !world.maps.getByName(name).custom){ - ui.showError(Bundles.format("text.editor.import.exists", name)); + ui.showError(Core.bundle.format("editor.import.exists", name)); }else if(world.maps.getByName(name) != null){ - ui.showConfirm("$text.confirm", "$text.editor.overwrite.confirm", () -> { + ui.showConfirm("$confirm", "$editor.overwrite.confirm", () -> { world.maps.saveMap(name, data, meta.tags); setup(); }); @@ -53,7 +53,7 @@ public class MapsDialog extends FloatingDialog{ } }catch(Exception e){ - ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false))); Log.err(e); } }, true, mapExtension); @@ -68,7 +68,7 @@ public class MapsDialog extends FloatingDialog{ } void setup(){ - content().clear(); + cont.clear(); Table maps = new Table(); maps.marginRight(24); @@ -95,24 +95,24 @@ public class MapsDialog extends FloatingDialog{ button.row(); button.stack(new Image(map.texture).setScaling(Scaling.fit), new BorderImage(map.texture).setScaling(Scaling.fit)).size(mapsize - 20f); button.row(); - button.add(map.custom ? "$text.custom" : "$text.builtin").color(Color.GRAY).padTop(3); + button.add(map.custom ? "$custom" : "$builtin").color(Color.GRAY).padTop(3); i++; } if(world.maps.all().size == 0){ - maps.add("$text.maps.none"); + maps.add("$maps.none"); } - content().add(pane).uniformX(); + cont.add(pane).uniformX(); } void showMapInfo(Map map){ - dialog = new FloatingDialog("$text.editor.mapinfo"); + dialog = new FloatingDialog("$editor.mapinfo"); dialog.addCloseButton(); float mapsize = UIUtils.portrait() ? 160f : 300f; - Table table = dialog.content(); + Table table = dialog.cont; table.stack(new Image(map.texture).setScaling(Scaling.fit), new BorderImage(map.texture).setScaling(Scaling.fit)).size(mapsize); @@ -127,38 +127,36 @@ public class MapsDialog extends FloatingDialog{ t.top(); t.defaults().padTop(10).left(); - t.add("$text.editor.name").padRight(10).color(Color.GRAY).padTop(0); + t.add("$editor.name").padRight(10).color(Color.GRAY).padTop(0); t.row(); t.add(map.meta.tags.get("name", map.name)).growX().wrap().padTop(2); t.row(); - t.add("$text.editor.author").padRight(10).color(Color.GRAY); + t.add("$editor.author").padRight(10).color(Color.GRAY); t.row(); t.add(map.meta.author()).growX().wrap().padTop(2); t.row(); - t.add("$text.editor.description").padRight(10).color(Color.GRAY).top(); + t.add("$editor.description").padRight(10).color(Color.GRAY).top(); t.row(); t.add(map.meta.description()).growX().wrap().padTop(2); t.row(); - t.add("$text.editor.oregen.info").padRight(10).color(Color.GRAY); - t.row(); - t.add(map.meta.hasOreGen() ? "$text.on" : "$text.off").padTop(2); + t.add("$editor.oregen.info").padRight(10).color(Color.GRAY); }).height(mapsize).width(mapsize); table.row(); - table.addImageTextButton("$text.editor.openin", "icon-load-map", 16 * 2, () -> { + table.addImageTextButton("$editor.openin", "icon-load-map", 16 * 2, () -> { try{ Vars.ui.editor.beginEditMap(map.stream.get()); dialog.hide(); hide(); }catch(Exception e){ e.printStackTrace(); - ui.showError("$text.error.mapnotfound"); + ui.showError("$error.mapnotfound"); } }).fillX().height(54f).marginLeft(10); - table.addImageTextButton("$text.delete", "icon-trash-16", 16 * 2, () -> { - ui.showConfirm("$text.confirm", Bundles.format("text.map.delete", map.name), () -> { + table.addImageTextButton("$delete", "icon-trash-16", 16 * 2, () -> { + ui.showConfirm("$confirm", Core.bundle.format("map.delete", map.name), () -> { world.maps.removeMap(map); dialog.hide(); setup(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MissionDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MissionDialog.java deleted file mode 100644 index d41b2b7480..0000000000 --- a/core/src/io/anuke/mindustry/ui/dialogs/MissionDialog.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.anuke.mindustry.ui.dialogs; - -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.maps.Sector; -import io.anuke.ucore.util.Bundles; - -public class MissionDialog extends FloatingDialog{ - - public MissionDialog(){ - super("$text.mission.complete"); - setFillParent(false); - } - - public void show(Sector sector){ - buttons().clear(); - content().clear(); - - buttons().addButton("$text.nextmission", () -> { - hide(); - Vars.ui.paused.runExitSave(); - Vars.ui.sectors.show(); - }).size(190f, 64f); - - buttons().addButton("$text.continue", this::hide).size(190f, 64f); - - content().add(Bundles.format("text.mission.complete.body", sector.x, sector.y)).pad(10); - show(); - } -} diff --git a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java index fc6b0ad57a..76cb78078f 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java @@ -1,74 +1,62 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.Input.Keys; +import io.anuke.arc.Core; +import io.anuke.arc.input.KeyCode; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.net.Net; -import io.anuke.ucore.scene.style.Drawable; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Bundles; import static io.anuke.mindustry.Vars.*; public class PausedDialog extends FloatingDialog{ private SaveDialog save = new SaveDialog(); private LoadDialog load = new LoadDialog(); - private Table missionTable; public PausedDialog(){ - super("$text.menu"); + super("$menu"); shouldPause = true; - setup(); shown(this::rebuild); keyDown(key -> { - if(key == Keys.ESCAPE || key == Keys.BACK) { + if(key == KeyCode.ESCAPE || key == KeyCode.BACK) { hide(); } }); } void rebuild(){ - missionTable.clear(); - missionTable.background((Drawable) null); - if(world.getSector() != null){ - missionTable.background("underline"); - missionTable.add(Bundles.format("text.sector", world.getSector().x + ", " + world.getSector().y)); - } - } + cont.clear(); - void setup(){ update(() -> { if(state.is(State.menu) && isShown()){ hide(); } }); - content().table(t -> missionTable = t).colspan(mobile ? 3 : 2); - content().row(); - if(!mobile){ float dw = 210f; - content().defaults().width(dw).height(50).pad(5f); + cont.defaults().width(dw).height(50).pad(5f); - content().addButton("$text.back", this::hide).colspan(2).width(dw*2 + 20f); + cont.addButton("$back", this::hide).colspan(2).width(dw*2 + 20f); - content().row(); - content().addButton("$text.unlocks", ui.unlocks::show); - content().addButton("$text.settings", ui.settings::show); + cont.row(); + cont.addButton("$techtree", ui.tech::show); + cont.addButton("$settings", ui.settings::show); - content().row(); - content().addButton("$text.savegame", save::show).disabled(s -> world.getSector() != null); - content().addButton("$text.loadgame", load::show).disabled(b -> Net.active()); + if(!world.isZone()){ + cont.row(); + cont.addButton("$savegame", save::show); + cont.addButton("$loadgame", load::show).disabled(b -> Net.active()); + } - content().row(); + cont.row(); - content().addButton("$text.hostserver", ui.host::show).disabled(b -> Net.active()).colspan(2).width(dw*2 + 20f); + cont.addButton("$hostserver", ui.host::show).disabled(b -> Net.active()).colspan(2).width(dw*2 + 20f); - content().row(); + cont.row(); - content().addButton("$text.quit", () -> { - ui.showConfirm("$text.confirm", "$text.quit.confirm", () -> { + cont.addButton("$quit", () -> { + ui.showConfirm("$confirm", "$quit.confirm", () -> { if(Net.client()) netClient.disconnectQuietly(); runExitSave(); hide(); @@ -76,21 +64,23 @@ public class PausedDialog extends FloatingDialog{ }).colspan(2).width(dw + 10f); }else{ - content().defaults().size(120f).pad(5); + cont.defaults().size(120f).pad(5); float isize = 14f * 4; - content().addRowImageTextButton("$text.back", "icon-play-2", isize, () -> { - hide(); - }); - content().addRowImageTextButton("$text.settings", "icon-tools", isize, ui.settings::show); - content().addRowImageTextButton("$text.save", "icon-save", isize, save::show).disabled(b -> world.getSector() != null); + cont.addRowImageTextButton("$back", "icon-play-2", isize, this::hide); + cont.addRowImageTextButton("$settings", "icon-tools", isize, ui.settings::show); - content().row(); + if(!world.isZone()){ + cont.addRowImageTextButton("$save", "icon-save", isize, save::show); - content().addRowImageTextButton("$text.load", "icon-load", isize, load::show).disabled(b -> Net.active()); - content().addRowImageTextButton("$text.hostserver.mobile", "icon-host", isize, ui.host::show).disabled(b -> Net.active()); - content().addRowImageTextButton("$text.quit", "icon-quit", isize, () -> { - ui.showConfirm("$text.confirm", "$text.quit.confirm", () -> { + cont.row(); + + cont.addRowImageTextButton("$load", "icon-load", isize, load::show).disabled(b -> Net.active()); + } + + cont.addRowImageTextButton("$hostserver.mobile", "icon-host", isize, ui.host::show).disabled(b -> Net.active()); + cont.addRowImageTextButton("$quit", "icon-quit", isize, () -> { + ui.showConfirm("$confirm", "$quit.confirm", () -> { if(Net.client()) netClient.disconnectQuietly(); runExitSave(); hide(); @@ -106,12 +96,12 @@ public class PausedDialog extends FloatingDialog{ return; } - ui.loadLogic("$text.saveload", () -> { + ui.loadAnd("$saveload", () -> { try{ control.saves.getCurrent().save(); }catch(Throwable e){ e.printStackTrace(); - threads.runGraphics(() -> ui.showError("[accent]" + Bundles.get("text.savefail"))); + ui.showError("[accent]" + Core.bundle.get("savefail")); } state.set(State.menu); }); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/RestartDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/RestartDialog.java deleted file mode 100644 index f61cc21a4d..0000000000 --- a/core/src/io/anuke/mindustry/ui/dialogs/RestartDialog.java +++ /dev/null @@ -1,64 +0,0 @@ -package io.anuke.mindustry.ui.dialogs; - -import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.maps.Sector; -import io.anuke.ucore.util.Bundles; - -import static io.anuke.mindustry.Vars.*; - -public class RestartDialog extends FloatingDialog{ - private Team winner; - - public RestartDialog(){ - super("$text.gameover"); - setFillParent(false); - shown(this::rebuild); - } - - public void show(Team winner){ - this.winner = winner; - show(); - } - - void rebuild(){ - buttons().clear(); - content().clear(); - - buttons().margin(10); - - if(state.mode.isPvp){ - content().add(Bundles.format("text.gameover.pvp",winner.localized())).pad(6); - buttons().addButton("$text.menu", () -> { - hide(); - state.set(State.menu); - logic.reset(); - }).size(130f, 60f); - }else if(world.getSector() == null){ - if(control.isHighScore()){ - content().add("$text.highscore").pad(6); - content().row(); - } - content().add(Bundles.format("text.wave.lasted", state.wave)).pad(12); - - buttons().addButton("$text.menu", () -> { - hide(); - state.set(State.menu); - logic.reset(); - }).size(130f, 60f); - }else{ - content().add("$text.sector.gameover"); - buttons().addButton("$text.menu", () -> { - hide(); - state.set(State.menu); - logic.reset(); - }).size(130f, 60f); - - buttons().addButton("$text.sector.retry", () -> { - Sector sector = world.getSector(); - ui.loadLogic(() -> world.sectors.playSector(sector)); - hide(); - }).size(130f, 60f); - } - } -} diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java index 92ffff5f7a..9baf019de2 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java @@ -1,17 +1,17 @@ package io.anuke.mindustry.ui.dialogs; +import io.anuke.arc.Core; +import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.util.Time; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.Saves.SaveSlot; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.scene.ui.TextButton; -import io.anuke.ucore.util.Bundles; import static io.anuke.mindustry.Vars.*; public class SaveDialog extends LoadDialog{ public SaveDialog(){ - super("$text.savegame"); + super("$savegame"); update(() -> { if(state.is(State.menu) && isShown()){ @@ -22,11 +22,11 @@ public class SaveDialog extends LoadDialog{ public void addSetup(){ slots.row(); - slots.addImageTextButton("$text.save.new", "icon-add",14 * 3, () -> - ui.showTextInput("$text.save", "$text.save.newslot", "", text -> { - ui.loadGraphics("$text.saving", () -> { + slots.addImageTextButton("$save.new", "icon-add",14 * 3, () -> + ui.showTextInput("$save", "$save.newslot", "", text -> { + ui.loadAnd("$saving", () -> { control.saves.addSave(text); - threads.runGraphics(() -> threads.run(() -> threads.runGraphics(this::setup))); + Core.app.post(() -> Core.app.post(this::setup)); }); }) ).fillX().margin(10f).minWidth(300f).height(70f).pad(4f).padRight(-4); @@ -37,15 +37,15 @@ public class SaveDialog extends LoadDialog{ button.clicked(() -> { if(button.childrenPressed()) return; - ui.showConfirm("$text.overwrite", "$text.save.overwrite", () -> save(slot)); + ui.showConfirm("$overwrite", "$save.overwrite", () -> save(slot)); }); } void save(SaveSlot slot){ - ui.loadfrag.show("$text.saveload"); + ui.loadfrag.show("$saveload"); - Timers.runTask(5f, () -> { + Time.runTask(5f, () -> { hide(); ui.loadfrag.hide(); try{ @@ -53,7 +53,7 @@ public class SaveDialog extends LoadDialog{ }catch(Throwable e){ e.printStackTrace(); - ui.showError("[accent]" + Bundles.get("text.savefail")); + ui.showError("[accent]" + Core.bundle.get("savefail")); } }); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SectorsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SectorsDialog.java deleted file mode 100644 index c38cfc31f6..0000000000 --- a/core/src/io/anuke/mindustry/ui/dialogs/SectorsDialog.java +++ /dev/null @@ -1,274 +0,0 @@ -package io.anuke.mindustry.ui.dialogs; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Align; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.maps.Sector; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.scene.Element; -import io.anuke.ucore.scene.Group; -import io.anuke.ucore.scene.event.InputEvent; -import io.anuke.ucore.scene.event.InputListener; -import io.anuke.ucore.scene.event.Touchable; -import io.anuke.ucore.scene.ui.layout.Cell; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.scene.utils.Cursors; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Geometry; -import io.anuke.ucore.util.Mathf; - -import static io.anuke.mindustry.Vars.world; - -public class SectorsDialog extends FloatingDialog{ - private static final float sectorSize = Unit.dp.scl(32*5); - private Sector selected; - private Table table; - private SectorView view; - - public SectorsDialog(){ - super(""); - - table = new Table(){ - @Override - public float getPrefWidth(){ - return sectorSize*2f; - } - }; - table.visible(() -> selected != null); - table.update(() -> { - if(selected != null){ - - int offsetX = (int)(view.panX / sectorSize); - int offsetY = (int)(view.panY / sectorSize); - float drawX = x + width/2f+ selected.x * (sectorSize-2) - offsetX * sectorSize - view.panX % sectorSize + sectorSize/2f; - float drawY = y + height/2f + selected.y * (sectorSize-2) - offsetY * sectorSize - view.panY % sectorSize + sectorSize/2f; - - table.setPosition(drawX, drawY - sectorSize/2f + 1, Align.top); - } - }); - - Group container = new Group(); - container.setTouchable(Touchable.childrenOnly); - container.addChild(table); - - margin(0); - getTitleTable().clear(); - clear(); - stack(content(), container, buttons()).grow(); - - shown(this::setup); - } - - void setup(){ - selected = null; - - table.clear(); - content().clear(); - buttons().clear(); - buttons().bottom().margin(15); - - addCloseButton(); - content().add(view = new SectorView()).grow(); - } - - void selectSector(Sector sector){ - selected = sector; - - table.clear(); - table.background("button").margin(5); - - table.defaults().pad(3); - table.add(Bundles.format("text.sector", sector.x + ", " + sector.y)); - table.row(); - - if(selected.completedMissions < selected.missions.size && !selected.complete){ - table.labelWrap(Bundles.format("text.mission", selected.getDominantMission().menuDisplayString())).growX(); - table.row(); - } - - if(selected.hasSave()){ - table.labelWrap(Bundles.format("text.sector.time", selected.getSave().getPlayTime())).growX(); - table.row(); - } - - table.table(t -> { - Cell cell = t.addImageTextButton(sector.hasSave() ? "$text.sector.resume" : "$text.sector.deploy", "icon-play", 10*3, () -> { - hide(); - Vars.ui.loadLogic(() -> world.sectors.playSector(selected)); - }).height(60f); - - if(selected.hasSave()){ - t.addImageTextButton("$text.sector.abandon", "icon-cancel", 16 * 2, () -> - Vars.ui.showConfirm("$text.confirm", "$text.sector.abandon.confirm", () -> { - world.sectors.abandonSector(selected); - // Simulate a sector selection so the buttons get updated. - selectSector(selected); - }) - ).width(sectorSize / Unit.dp.scl(1f)).height(60f); - cell.width(sectorSize / Unit.dp.scl(1f)); - }else{ - cell.width(sectorSize*2f / Unit.dp.scl(1f)); - } - }).pad(-5).growX().padTop(0); - - table.pack(); - table.act(Gdx.graphics.getDeltaTime()); - } - - public Sector getSelected(){ - return selected; - } - - class SectorView extends Element{ - float lastX, lastY; - boolean clicked = false; - float panX = sectorSize/2f, panY = sectorSize/2f; - - SectorView(){ - addListener(new InputListener(){ - @Override - public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){ - if(pointer != 0) return false; - //Cursors.setHand(); - lastX = x; - lastY = y; - return true; - } - - @Override - public void touchDragged(InputEvent event, float x, float y, int pointer){ - if(pointer != 0) return; - panX -= x - lastX; - panY -= y - lastY; - - lastX = x; - lastY = y; - } - - @Override - public void touchUp(InputEvent event, float x, float y, int pointer, int button){ - if(pointer != 0) return; - Cursors.restoreCursor(); - } - }); - - clicked(() -> clicked = true); - - this.focus(); - } - - private void focus(){ - Sector focusSector = null; - long newestTimestamp = 0; - for(Sector sector : world.sectors.getSectors()){ - if(sector.hasSave()){ - long timestamp = sector.getSave().getTimestamp(); - if(timestamp > newestTimestamp){ - focusSector = sector; - newestTimestamp = timestamp; - } - } - } - if(focusSector != null) { - panX = (focusSector.x + 0.5f) * sectorSize; - panY = (focusSector.y + 0.5f) * sectorSize; - } - } - - @Override - public void draw(){ - Draw.alpha(alpha); - - int shownSectorsX = (int)(width/sectorSize); - int shownSectorsY = (int)(height/sectorSize); - - int offsetX = (int)(panX / sectorSize); - int offsetY = (int)(panY / sectorSize); - - Vector2 mouse = Graphics.mouse(); - - for(int x = -shownSectorsX; x <= shownSectorsX; x++){ - for(int y = -shownSectorsY; y <= shownSectorsY; y++){ - int sectorX = offsetX + x; - int sectorY = offsetY + y; - - float drawX = x + width/2f+ sectorX * (sectorSize-2) - offsetX * sectorSize - panX % sectorSize + sectorSize/2f; - float drawY = y + height/2f + sectorY * (sectorSize-2) - offsetY * sectorSize - panY % sectorSize + sectorSize/2f; - - Sector sector = world.sectors.get(sectorX, sectorY); - - if(sector == null || sector.texture == null){ - Draw.reset(); - Draw.rect("empty-sector", drawX, drawY, sectorSize, sectorSize); - - int i = 0; - for(GridPoint2 point : Geometry.d4){ - Sector other = world.sectors.get(sectorX + point.x, sectorY + point.y); - if(other != null){ - Draw.rect("sector-edge", drawX, drawY, sectorSize, sectorSize, i*90); - } - - i ++; - } - continue; - } - - Draw.colorl(!sector.complete ? 0.3f : 1f); - Draw.rect(sector.texture, drawX, drawY, sectorSize, sectorSize); - - if(sector.missions.size == 0) continue; - - String region = sector.getDominantMission().getIcon(); - - if(sector.complete){ - region = "icon-mission-done"; - } - - Color iconColor = Color.WHITE; - Color backColor = Color.BLACK; - Color selectColor = Color.CLEAR; - - if(sector == selected){ - selectColor = Palette.accent; - }else if(Mathf.inRect(mouse.x, mouse.y, drawX - sectorSize / 2f, drawY - sectorSize / 2f, - drawX + sectorSize / 2f, drawY + sectorSize / 2f)){ - if(clicked){ - selectSector(sector); - } - selectColor = Color.WHITE; - }else if(sector.hasSave()){ - iconColor = Palette.command; - }else{ - iconColor = Color.GRAY; - } - - if(sector.complete){ - iconColor = backColor = Color.CLEAR; - } - - Draw.color(selectColor); - Draw.rect("sector-select", drawX, drawY, sectorSize, sectorSize); - - Draw.color(backColor); - Draw.alpha(0.75f * backColor.a); - Draw.rect("icon-mission-background", drawX, drawY, Unit.dp.scl(18f * 5), Unit.dp.scl(18f * 5)); - - float size = Unit.dp.scl(10f * 5); - - Draw.color(iconColor); - Draw.rect(region, drawX, drawY, size, size); - } - } - - Draw.reset(); - - clicked = false; - } - } -} diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index c088808401..810bdd2e20 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -1,30 +1,21 @@ package io.anuke.mindustry.ui.dialogs; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.utils.Align; +import io.anuke.arc.Core; +import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.input.KeyCode; +import io.anuke.arc.scene.Element; +import io.anuke.arc.scene.event.InputEvent; +import io.anuke.arc.scene.event.InputListener; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.SettingsDialog.SettingsTable.Setting; +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 io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.scene.Element; -import io.anuke.ucore.scene.event.InputEvent; -import io.anuke.ucore.scene.event.InputListener; -import io.anuke.ucore.scene.ui.Image; -import io.anuke.ucore.scene.ui.ScrollPane; -import io.anuke.ucore.scene.ui.SettingsDialog; -import io.anuke.ucore.scene.ui.SettingsDialog.SettingsTable.Setting; -import io.anuke.ucore.scene.ui.Slider; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Mathf; - -import java.util.HashMap; -import java.util.Map; import static io.anuke.mindustry.Vars.*; @@ -38,7 +29,7 @@ public class SettingsMenuDialog extends SettingsDialog{ private boolean wasPaused; public SettingsMenuDialog(){ - setStyle(Core.skin.get("dialog", WindowStyle.class)); + setStyle(Core.scene.skin.get("dialog", WindowStyle.class)); hidden(() -> { if(!state.is(State.menu)){ @@ -55,20 +46,20 @@ public class SettingsMenuDialog extends SettingsDialog{ }); setFillParent(true); - title().setAlignment(Align.center); - getTitleTable().row(); - getTitleTable().add(new Image("white")) - .growX().height(3f).pad(4f).get().setColor(Palette.accent); + title.setAlignment(Align.center); + titleTable.row(); + titleTable.add(new Image("white")) + .growX().height(3f).pad(4f).get().setColor(Pal.accent); - content().clearChildren(); - content().remove(); - buttons().remove(); + cont.clearChildren(); + cont.remove(); + buttons.remove(); menu = new Table(); Consumer s = table -> { table.row(); - table.addImageTextButton("$text.back", "icon-arrow-left", 10 * 3, this::back).size(240f, 60f).colspan(2).padTop(15f); + table.addImageTextButton("$back", "icon-arrow-left", 10 * 3, this::back).size(240f, 60f).colspan(2).padTop(15f); }; game = new SettingsTable(s); @@ -80,17 +71,17 @@ public class SettingsMenuDialog extends SettingsDialog{ prefs.margin(14f); menu.defaults().size(300f, 60f).pad(3f); - menu.addButton("$text.settings.game", () -> visible(0)); + menu.addButton("$settings.game", () -> visible(0)); menu.row(); - menu.addButton("$text.settings.graphics", () -> visible(1)); + menu.addButton("$settings.graphics", () -> visible(1)); menu.row(); - menu.addButton("$text.settings.sound", () -> visible(2)); + menu.addButton("$settings.sound", () -> visible(2)); if(!Vars.mobile){ menu.row(); - menu.addButton("$text.settings.controls", ui.controls::show); + menu.addButton("$settings.controls", ui.controls::show); } menu.row(); - menu.addButton("$text.settings.language", ui.language::show); + menu.addButton("$settings.language", ui.language::show); prefs.clearChildren(); prefs.add(menu); @@ -98,7 +89,7 @@ public class SettingsMenuDialog extends SettingsDialog{ ScrollPane pane = new ScrollPane(prefs); pane.addCaptureListener(new InputListener(){ @Override - public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){ + public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){ Element actor = pane.hit(x, y, true); if(actor instanceof Slider){ pane.setFlickScroll(false); @@ -109,7 +100,7 @@ public class SettingsMenuDialog extends SettingsDialog{ } @Override - public void touchUp(InputEvent event, float x, float y, int pointer, int button){ + public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){ pane.setFlickScroll(true); super.touchUp(event, x, y, pointer, button); } @@ -119,7 +110,7 @@ public class SettingsMenuDialog extends SettingsDialog{ row(); add(pane).grow().top(); row(); - add(buttons()).fillX(); + add(buttons).fillX(); hidden(this::back); @@ -127,14 +118,15 @@ public class SettingsMenuDialog extends SettingsDialog{ } void addSettings(){ - sound.volumePrefs(); + //TODO add when sound works again + //sound.volumePrefs(); game.screenshakePref(); game.checkPref("effects", true); if(mobile){ game.checkPref("autotarget", true); } - game.sliderPref("saveinterval", 120, 10, 5 * 120, i -> Bundles.format("setting.seconds", i)); + game.sliderPref("saveinterval", 60, 10, 5 * 120, i -> Core.bundle.format("setting.seconds", i)); if(!mobile){ game.checkPref("crashreport", true); @@ -143,45 +135,38 @@ public class SettingsMenuDialog extends SettingsDialog{ game.pref(new Setting(){ @Override public void add(SettingsTable table){ - table.addButton("$text.settings.cleardata", () -> { - FloatingDialog dialog = new FloatingDialog("$text.settings.cleardata"); + table.addButton("$settings.cleardata", () -> { + FloatingDialog dialog = new FloatingDialog("$settings.cleardata"); dialog.setFillParent(false); - dialog.content().defaults().size(230f, 60f).pad(3); + dialog.cont.defaults().size(230f, 60f).pad(3); dialog.addCloseButton(); - dialog.content().addButton("$text.settings.clearsectors", () -> { - ui.showConfirm("$text.confirm", "$text.settings.clear.confirm", () -> { - world.sectors.clear(); + dialog.cont.addButton("$settings.clearunlocks", () -> { + ui.showConfirm("$confirm", "$settings.clear.confirm", () -> { + data.reset(); dialog.hide(); }); }); - dialog.content().row(); - dialog.content().addButton("$text.settings.clearunlocks", () -> { - ui.showConfirm("$text.confirm", "$text.settings.clear.confirm", () -> { - control.unlocks.reset(); - dialog.hide(); - }); - }); - dialog.content().row(); - dialog.content().addButton("$text.settings.clearall", () -> { - ui.showConfirm("$text.confirm", "$text.settings.clearall.confirm", () -> { - Map map = new HashMap<>(); - for(String value : Settings.prefs().get().keySet()){ + dialog.cont.row(); + dialog.cont.addButton("$settings.clearall", () -> { + ui.showConfirm("$confirm", "$settings.clearall.confirm", () -> { + ObjectMap map = new ObjectMap<>(); + for(String value : Core.settings.keys()){ if(value.contains("usid") || value.contains("uuid")){ - map.put(value, Settings.prefs().getString(value)); + map.put(value, Core.settings.getString(value)); } } - Settings.prefs().clear(); - Settings.prefs().put(map); - Settings.save(); + Core.settings.clear(); + Core.settings.putAll(map); + Core.settings.save(); for(FileHandle file : dataDirectory.list()){ file.deleteDirectory(); } - Gdx.app.exit(); + Core.app.exit(); }); }); - dialog.content().row(); + dialog.cont.row(); dialog.show(); }).size(220f, 60f).pad(6).left(); table.add(); @@ -189,21 +174,21 @@ public class SettingsMenuDialog extends SettingsDialog{ } }); - graphics.sliderPref("fpscap", 125, 5, 125, 5, s -> (s > 120 ? Bundles.get("setting.fpscap.none") : Bundles.format("setting.fpscap.text", s))); + graphics.sliderPref("fpscap", 125, 5, 125, 5, s -> (s > 120 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s))); if(!mobile){ - graphics.checkPref("vsync", true, b -> Gdx.graphics.setVSync(b)); + graphics.checkPref("vsync", true, b -> Core.graphics.setVSync(b)); graphics.checkPref("fullscreen", false, b -> { if(b){ - Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode()); + Core.graphics.setFullscreenMode(Core.graphics.getDisplayMode()); }else{ - Gdx.graphics.setWindowedMode(600, 480); + Core.graphics.setWindowedMode(600, 480); } }); - Gdx.graphics.setVSync(Settings.getBool("vsync")); - if(Settings.getBool("fullscreen")){ - Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode()); + Core.graphics.setVSync(Core.settings.getBool("vsync")); + if(Core.settings.getBool("fullscreen")){ + Core.graphics.setFullscreenMode(Core.graphics.getDisplayMode()); } } @@ -220,16 +205,16 @@ public class SettingsMenuDialog extends SettingsDialog{ private void visible(int index){ prefs.clearChildren(); - Table table = Mathf.select(index, game, graphics, sound); + Table table = new Table[]{game, graphics, sound}[index]; prefs.add(table); } @Override public void addCloseButton(){ - buttons().addImageTextButton("$text.menu", "icon-arrow-left", 30f, this::hide).size(230f, 64f); + buttons.addImageTextButton("$menu", "icon-arrow-left", 30f, this::hide).size(230f, 64f); keyDown(key -> { - if(key == Keys.ESCAPE || key == Keys.BACK) + if(key == KeyCode.ESCAPE || key == KeyCode.BACK) hide(); }); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java new file mode 100644 index 0000000000..83274b4359 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java @@ -0,0 +1,251 @@ +package io.anuke.mindustry.ui.dialogs; + +import io.anuke.arc.Core; +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.math.Interpolation; +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.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.mindustry.content.TechTree; +import io.anuke.mindustry.content.TechTree.TechNode; +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.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 ItemsDisplay items; + + public TechTreeDialog(){ + super(""); + + TreeLayout layout = new TreeLayout(); + layout.gapBetweenLevels = Unit.dp.scl(60f); + layout.gapBetweenNodes = Unit.dp.scl(40f); + layout.layout(root); + + titleTable.remove(); + margin(0f).marginBottom(8); + cont.stack(new View(), items = new ItemsDisplay()).grow(); + + shown(() -> checkNodes(root)); + hidden(ui.deploy::setup); + addCloseButton(); + } + + @Override + protected void drawBackground(float x, float y){ + drawDefaultBackground(x, y); + } + + void checkNodes(TechTreeNode node){ + boolean locked = locked(node.node); + if(!locked) node.visible = true; + for(TechTreeNode l : node.children){ + l.visible = !locked; + checkNodes(l); + } + + items.rebuild(); + } + + 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); + } + } + + int m = maxIndex; + + Table table = new Table(); + table.actions(Actions.fadeOut(7f, 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); + }); + Core.scene.add(table); + } + + boolean locked(TechNode node){ + return node.block.locked(); + } + + class TechTreeNode extends TreeNode{ + final TechNode node; + boolean visible = true; + + TechTreeNode(TechNode node, TechTreeNode parent){ + this.node = node; + this.parent = parent; + this.width = this.height = nodeSize; + nodes.add(this); + if(node.children != null){ + children = new TechTreeNode[node.children.size]; + for(int i = 0; i < children.length; i++){ + children[i] = new TechTreeNode(node.children.get(i), this); + } + } + } + } + + class View extends Group{ + float panX = 0, panY = -200; + boolean moved = false; + ImageButton hoverNode; + Table infoTable = new Table(); + + { + infoTable.touchable(Touchable.enabled); + + for(TechTreeNode node : nodes){ + ImageButton button = new ImageButton(node.node.block.icon(Icon.medium), "node"); + button.clicked(() -> { + if(mobile){ + hoverNode = button; + rebuild(); + }else if(data.hasItems(node.node.requirements) && locked(node.node)){ + unlock(node.node); + } + }); + button.hovered(() -> { + if(!mobile && hoverNode != button && node.visible){ + hoverNode = button; + rebuild(); + } + }); + button.exited(() -> { + if(!mobile && hoverNode == button && !infoTable.hasMouse() && !hoverNode.hasMouse()){ + hoverNode = null; + rebuild(); + } + }); + button.touchable(() -> !node.visible ? Touchable.disabled : Touchable.enabled); + button.setUserObject(node.node); + button.tapped(() -> moved = false); + button.setSize(nodeSize); + button.update(() -> { + 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.node) ? Color.WHITE : Color.GRAY); + }); + addChild(button); + } + + 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)); + checkNodes(root); + hoverNode = null; + rebuild(); + } + + void rebuild(){ + ImageButton button = hoverNode; + + infoTable.remove(); + infoTable.clear(); + infoTable.update(null); + + if(button == null) return; + + TechNode node = (TechNode)button.getUserObject(); + + infoTable.exited(() -> { + if(hoverNode == button && !infoTable.hasMouse() && !hoverNode.hasMouse()){ + hoverNode = null; + rebuild(); + } + }); + + infoTable.background("content-background"); + infoTable.update(() -> infoTable.setPosition(button.getX() + button.getWidth(), button.getY() + button.getHeight(), Align.topLeft)); + + infoTable.margin(0).left().defaults().left(); + + infoTable.addImageButton("icon-info", "node", 14*2, () -> ui.content.show(node.block)).growY().width(50f); + + infoTable.add().grow(); + + infoTable.table(desc -> { + desc.left().defaults().left(); + desc.add(node.block.formalName); + desc.row(); + if(locked(node)){ + desc.table(t -> { + t.left(); + for(ItemStack req : node.requirements){ + t.table(list -> { + list.left(); + list.addImage(req.item.getContentIcon()).size(8 * 3).padRight(3); + list.add(req.item.localizedName()).color(Color.LIGHT_GRAY); + 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(); + } + }); + }else{ + desc.add("$completed"); + } + }).pad(9); + + if(mobile && locked(node)){ + infoTable.row(); + infoTable.addImageTextButton("$research", "icon-check", "node", 16*2, () -> unlock(node)) + .disabled(b -> !data.hasItems(node.requirements)).growX().height(44f).colspan(3); + } + + addChild(infoTable); + infoTable.pack(); + } + + @Override + public void draw(){ + float offsetX = panX + width/2f + x, offsetY = panY + height/2f + y; + + for(TechTreeNode node : nodes){ + for(TechTreeNode child : node.children){ + 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 7c58101b03..b588d4d7e4 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/TraceDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/TraceDialog.java @@ -3,13 +3,13 @@ package io.anuke.mindustry.ui.dialogs; public class TraceDialog extends FloatingDialog{ public TraceDialog(){ - super("$text.trace"); + super("$trace"); addCloseButton(); } /* public void show(Player player, SessionInfo info){ - content().clear(); + cont.clear(); Table table = new Table("clear"); table.margin(14); @@ -17,15 +17,15 @@ public class TraceDialog extends FloatingDialog{ /* table.defaults().left(); - table.add(Bundles.format("text.trace.playername", player.name)); + table.add(Core.bundle.format("trace.playername", player.name)); table.row(); - table.add(Bundles.format("text.trace.ip", info.ip)); + table.add(Core.bundle.format("trace.ip", info.ip)); table.row(); - table.add(Bundles.format("text.trace.id", info.uuid)); + table.add(Core.bundle.format("trace.id", info.uuid)); table.row(); - table.add(Bundles.format("text.trace.modclient", info.modclient)); + table.add(Core.bundle.format("trace.modclient", info.modclient)); table.row(); - table.add(Bundles.format("text.trace.android", info.android)); + table.add(Core.bundle.format("trace.android", info.android)); table.row(); table.add().pad(5); @@ -33,22 +33,22 @@ public class TraceDialog extends FloatingDialog{ //disabled until further notice /* - table.add(Bundles.format("text.trace.totalblocksbroken", info.totalBlocksBroken)); + table.add(Core.bundle.format("trace.totalblocksbroken", info.totalBlocksBroken)); table.row(); - table.add(Bundles.format("text.trace.structureblocksbroken", info.structureBlocksBroken)); + table.add(Core.bundle.format("trace.structureblocksbroken", info.structureBlocksBroken)); table.row(); - table.add(Bundles.format("text.trace.lastblockbroken", info.lastBlockBroken.formalName)); + table.add(Core.bundle.format("trace.lastblockbroken", info.lastBlockBroken.formalName)); table.row(); table.add().pad(5); table.row(); - table.add(Bundles.format("text.trace.totalblocksplaced", info.totalBlocksPlaced)); + table.add(Core.bundle.format("trace.totalblocksplaced", info.totalBlocksPlaced)); table.row(); - table.add(Bundles.format("text.trace.lastblockplaced", info.lastBlockPlaced.formalName)); + table.add(Core.bundle.format("trace.lastblockplaced", info.lastBlockPlaced.formalName)); table.row(); - content().add(table); + cont.add(table); show(); }*/ 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..a046bcd909 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java @@ -0,0 +1,142 @@ +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.mindustry.graphics.Pal; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.ItemStack; +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(); + } + + public void show(Zone zone){ + setup(zone); + show(); + } + + private void setup(Zone zone){ + cont.clear(); + + 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(data.isCompleted(other) ? "icon-check-2" : "icon-cancel-2") + .color(data.isCompleted(other) ? 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.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(); + + }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(data.getWaveScore(zone) > 0){ + cont.row(); + cont.add(Core.bundle.format("bestwave", data.getWaveScore(zone))); + } + } + }); + + 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.deployCost); + hide(); + world.playZone(zone); + } + }).size(300f, 70f).padTop(5).disabled(b -> zone.locked() ? !canUnlock(zone) : !data.hasItems(zone.deployCost)).get(); + + button.row(); + button.table(r -> { + ItemStack[] stacks = zone.unlocked() ? zone.deployCost : zone.itemRequirements; + for(ItemStack stack : stacks){ + r.addImage(stack.item.icon(Item.Icon.medium)).size(8*3).padRight(1); + r.add(stack.amount + "").color(Color.LIGHT_GRAY).padRight(5); + } + }); + } + + private boolean canUnlock(Zone zone){ + if(data.isUnlocked(zone)){ + return true; + } + + for(Zone other : zone.zoneRequirements){ + if(!data.isCompleted(other)){ + 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/BackgroundFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java index ab5cfec300..de0b8851cb 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java @@ -1,16 +1,13 @@ package io.anuke.mindustry.ui.fragments; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.g2d.TextureRegion; +import io.anuke.arc.Core; +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.scene.Group; +import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Shaders; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.scene.Group; -import io.anuke.ucore.scene.ui.layout.Unit; import static io.anuke.mindustry.Vars.state; @@ -18,24 +15,21 @@ public class BackgroundFragment extends Fragment{ @Override public void build(Group parent){ - Core.scene.table().addRect((a, b, w, h) -> { Draw.colorl(0.1f); Fill.crect(0, 0, w, h); - Draw.color(Palette.accent); - Graphics.shader(Shaders.menu); + Draw.shader(Shaders.menu); Fill.crect(0, 0, w, h); - Graphics.shader(); - Draw.color(); + Draw.shader(); - boolean portrait = Gdx.graphics.getWidth() < Gdx.graphics.getHeight(); - float logoscl = (int) Unit.dp.scl(7) * (portrait ? 5f / 7f : 1f); - TextureRegion logo = Core.skin.getRegion("logotext"); - float logow = logo.getRegionWidth() * logoscl; - float logoh = logo.getRegionHeight() * logoscl; + boolean portrait = Core.graphics.getWidth() < Core.graphics.getHeight(); + float logoscl = (int) Unit.dp.scl(1); + TextureRegion logo = Core.atlas.find("logotext"); + float logow = logo.getWidth() * logoscl; + float logoh = logo.getHeight() * logoscl; Draw.color(); - Core.batch.draw(logo, (int) (w / 2 - logow / 2), (int) (h - logoh + 15 - Unit.dp.scl(portrait ? 30f : 0)), logow, logoh); + Draw.rect(logo, (int) (w / 2), (int) (h - 10 - logoh - Unit.dp.scl(portrait ? 30f : 0)) + logoh/2, logow, logoh); }).visible(() -> state.is(State.menu)).grow(); } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java index b122811e16..6617701231 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java @@ -1,20 +1,18 @@ package io.anuke.mindustry.ui.fragments; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.math.Interpolation; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Align; -import io.anuke.mindustry.content.blocks.Blocks; +import io.anuke.arc.Core; +import io.anuke.arc.math.Interpolation; +import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.scene.Element; +import io.anuke.arc.scene.Group; +import io.anuke.arc.scene.actions.Actions; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.util.Align; +import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.scene.Element; -import io.anuke.ucore.scene.Group; -import io.anuke.ucore.scene.actions.Actions; -import io.anuke.ucore.scene.ui.layout.Table; import static io.anuke.mindustry.Vars.state; import static io.anuke.mindustry.Vars.tilesize; @@ -46,7 +44,7 @@ public class BlockConfigFragment extends Fragment{ configTile = tile; configBlock = tile.block(); - table.setVisible(true); + table.visible(true); table.clear(); tile.block().buildTable(tile, table); table.pack(); @@ -66,7 +64,7 @@ public class BlockConfigFragment extends Fragment{ } table.setOrigin(Align.center); - Vector2 pos = Graphics.screen(tile.drawx(), tile.drawy() - tile.block().size * tilesize / 2f - 1); + Vector2 pos = Core.input.mouseScreen(tile.drawx(), tile.drawy() - tile.block().size * tilesize / 2f - 1); table.setPosition(pos.x, pos.y, Align.top); if(configTile == null || configTile.block() == Blocks.air || configTile.block() != configBlock){ hideConfig(); @@ -75,7 +73,7 @@ public class BlockConfigFragment extends Fragment{ } public boolean hasConfigMouse(){ - Element e = Core.scene.hit(Gdx.input.getX(), Gdx.graphics.getHeight() - Gdx.input.getY(), true); + Element e = Core.scene.hit(Core.input.mouseX(), Core.graphics.getHeight() - Core.input.mouseY(), true); return e != null && (e == table || e.isDescendantOf(table)); } diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlockConsumeFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlockConsumeFragment.java deleted file mode 100644 index 78ec16761b..0000000000 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockConsumeFragment.java +++ /dev/null @@ -1,132 +0,0 @@ -package io.anuke.mindustry.ui.fragments; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Align; -import com.badlogic.gdx.utils.ObjectSet; -import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.consumers.Consume; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.scene.Element; -import io.anuke.ucore.scene.Group; -import io.anuke.ucore.scene.ui.layout.Table; - -import static io.anuke.mindustry.Vars.*; - -public class BlockConsumeFragment extends Fragment{ - private Table table; - private Tile lastTile; - private boolean visible; - - @Override - public void build(Group parent){ - table = new Table(); - table.visible(() -> !state.is(State.menu) && visible); - table.setTransform(true); - - parent.addChild(new Element(){{update(() -> { - if(!ui.hasMouse()){ - Tile tile = world.tileWorld(Graphics.mouseWorld().x, Graphics.mouseWorld().y); - if(tile == null) return; - tile = tile.target(); - - if(tile != lastTile){ - if(tile.getTeam() == players[0].getTeam() && tile.block().consumes.hasAny()){ - show(tile); - }else if(visible){ - hide(); - } - lastTile = tile; - } - } - });}}); - - parent.setTransform(true); - parent.addChild(table); - } - - public void show(Tile tile){ - ObjectSet consumers = new ObjectSet<>(); - TileEntity entity = tile.entity; - Block block = tile.block(); - - table.clearChildren(); - - rebuild(block, entity); - visible = true; - - table.update(() -> { - - if(tile.entity == null || state.is(State.menu)){ - hide(); - return; - } - - boolean rebuild = false; - - for(Consume c : block.consumes.array()){ - boolean valid = c.isOptional() || c.valid(block, entity); - - if(consumers.contains(c) == valid){ - if(valid){ - consumers.remove(c); - }else{ - consumers.add(c); - } - rebuild = true; - } - } - - if(rebuild){ - rebuild(block, entity); - } - - Vector2 v = Graphics.screen(tile.drawx() - tile.block().size * tilesize / 2f + 0.25f, tile.drawy() + tile.block().size * tilesize / 2f); - table.pack(); - table.setPosition(v.x, v.y, Align.topRight); - }); - - table.act(Gdx.graphics.getDeltaTime()); - } - - public void hide(){ - table.clear(); - table.update(() -> {}); - visible = false; - } - - private void rebuild(Block block, TileEntity entity){ - table.clearChildren(); - table.left(); - - int scale = mobile ? 4 : 3; - - for(Consume c : block.consumes.array()){ - if(!c.isOptional() && !c.valid(block, entity)){ - boolean[] hovered = {false}; - - table.table("inventory", c::buildTooltip).visible(() -> hovered[0]).height(scale * 10 + 6).padBottom(-4).right().update(t -> { - if(t.getChildren().size == 0) t.remove(); - }).get().act(0); - - Table result = table.table(out -> { - out.addImage(c.getIcon()).size(10 * scale).color(Color.DARK_GRAY).padRight(-10 * scale).padBottom(-scale * 2); - out.addImage(c.getIcon()).size(10 * scale).color(Palette.accent); - out.addImage("icon-missing").size(10 * scale).color(Palette.remove).padLeft(-10 * scale); - }).size(10 * scale).get(); - - result.hovered(() -> hovered[0] = true); - if(!mobile){ - result.exited(() -> hovered[0] = false); - } - - table.row(); - } - } - } -} diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java index e193b04ed2..171ac4c692 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java @@ -1,30 +1,32 @@ package io.anuke.mindustry.ui.fragments; -import com.badlogic.gdx.math.Interpolation; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Align; -import com.badlogic.gdx.utils.IntSet; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; +import io.anuke.arc.Core; +import io.anuke.arc.collection.IntSet; +import io.anuke.arc.function.BooleanProvider; +import io.anuke.arc.input.KeyCode; +import io.anuke.arc.math.Interpolation; +import io.anuke.arc.math.Mathf; +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.HandCursorListener; +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.ui.layout.Table; +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; -import io.anuke.ucore.core.Graphics; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.function.BooleanProvider; -import io.anuke.ucore.scene.Group; -import io.anuke.ucore.scene.actions.Actions; -import io.anuke.ucore.scene.event.HandCursorListener; -import io.anuke.ucore.scene.event.InputEvent; -import io.anuke.ucore.scene.event.InputListener; -import io.anuke.ucore.scene.event.Touchable; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Strings; import static io.anuke.mindustry.Vars.*; @@ -48,9 +50,9 @@ 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++){ - Timers.run(j * 3f, () -> Call.transferItemEffect(item, tile.drawx(), tile.drawy(), player)); + Time.run(j * 3f, () -> Call.transferItemEffect(item, tile.drawx(), tile.drawy(), player)); } } @@ -75,7 +77,7 @@ public class BlockInventoryFragment extends Fragment{ table.clear(); table.update(null); })); - table.setTouchable(Touchable.disabled); + table.touchable(Touchable.disabled); tile = null; } @@ -87,16 +89,16 @@ public class BlockInventoryFragment extends Fragment{ table.clearChildren(); table.background("inventory"); - table.setTouchable(Touchable.enabled); + table.touchable(Touchable.enabled); table.update(() -> { if(state.is(State.menu) || tile == null || tile.entity == null || !tile.block().isAccessible() || tile.entity.items.total() == 0){ hide(); }else{ if(holding && lastItem != null){ - holdTime += Timers.delta(); + 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; @@ -119,7 +121,7 @@ public class BlockInventoryFragment extends Fragment{ int row = 0; table.margin(6f); - table.defaults().size(mobile ? 16 * 3 : 16 * 2).space(6f); + table.defaults().size(8 * 5).space(6f); if(tile.block().hasItems){ @@ -129,12 +131,12 @@ public class BlockInventoryFragment extends Fragment{ container.add(i); - BooleanProvider canPick = () -> player.inventory.canAcceptItem(item); + BooleanProvider canPick = () -> player.acceptsItem(item); 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 ""; } @@ -144,9 +146,9 @@ public class BlockInventoryFragment extends Fragment{ image.addListener(new InputListener(){ @Override - public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){ + 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)); + int amount = Math.min(1, player.maxAccepted(item)); Call.requestItem(player, tile, item, amount); lastItem = item; holding = true; @@ -155,7 +157,7 @@ public class BlockInventoryFragment extends Fragment{ } @Override - public void touchUp(InputEvent event, float x, float y, int pointer, int button){ + public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){ holding = false; lastItem = null; } @@ -190,7 +192,7 @@ public class BlockInventoryFragment extends Fragment{ } private void updateTablePosition(){ - Vector2 v = Graphics.screen(tile.drawx() + tile.block().size * tilesize / 2f, tile.drawy() + tile.block().size * tilesize / 2f); + Vector2 v = Core.input.mouseScreen(tile.drawx() + tile.block().size * tilesize / 2f, tile.drawy() + tile.block().size * tilesize / 2f); table.pack(); table.setPosition(v.x, v.y, Align.topLeft); } diff --git a/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java b/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java index 3d96883b34..40083a7524 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java @@ -1,32 +1,32 @@ package io.anuke.mindustry.ui.fragments; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.GlyphLayout; -import com.badlogic.gdx.utils.Align; -import com.badlogic.gdx.utils.Array; +import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.BitmapFont; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.Fill; +import io.anuke.arc.graphics.g2d.GlyphLayout; +import io.anuke.arc.input.KeyCode; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.scene.Group; +import io.anuke.arc.scene.ui.Dialog; +import io.anuke.arc.scene.ui.Label; +import io.anuke.arc.scene.ui.Label.LabelStyle; +import io.anuke.arc.scene.ui.TextField; +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.Time; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.gen.Call; +import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.net.Net; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Inputs; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.scene.Group; -import io.anuke.ucore.scene.ui.Dialog; -import io.anuke.ucore.scene.ui.Label; -import io.anuke.ucore.scene.ui.Label.LabelStyle; -import io.anuke.ucore.scene.ui.TextField; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.util.Mathf; +import static io.anuke.arc.Core.input; +import static io.anuke.arc.Core.scene; import static io.anuke.mindustry.Vars.*; -import static io.anuke.ucore.core.Core.scene; -import static io.anuke.ucore.core.Core.skin; public class ChatFragment extends Table{ private final static int messagesShown = 10; @@ -55,7 +55,7 @@ public class ChatFragment extends Table{ super(); setFillParent(true); - font = Core.skin.getFont("default-font"); + font = scene.skin.getFont("default-font"); visible(() -> { if(!Net.active() && messages.size > 0){ @@ -71,21 +71,21 @@ public class ChatFragment extends Table{ update(() -> { - if(Net.active() && Inputs.keyTap("chat")){ + if(Net.active() && input.keyTap(Binding.chat)){ toggle(); } if(chatOpen){ - if(Inputs.keyTap("chat_history_prev") && historyPos < history.size - 1){ + if(input.keyTap(Binding.chat_history_prev) && historyPos < history.size - 1){ if(historyPos == 0) history.set(0, chatfield.getText()); historyPos++; updateChat(); } - if(Inputs.keyTap("chat_history_next") && historyPos > 0){ + if(input.keyTap(Binding.chat_history_next) && historyPos > 0){ historyPos--; updateChat(); } - scrollPos = (int) Mathf.clamp(scrollPos + Inputs.getAxis("chat_scroll"), 0, Math.max(0, messages.size - messagesShown)); + scrollPos = (int) Mathf.clamp(scrollPos + input.axis(Binding.chat_scroll), 0, Math.max(0, messages.size - messagesShown)); } }); @@ -108,10 +108,10 @@ public class ChatFragment extends Table{ fieldlabel.getStyle().font = font; fieldlabel.setStyle(fieldlabel.getStyle()); - chatfield = new TextField("", new TextField.TextFieldStyle(skin.get(TextField.TextFieldStyle.class))); + chatfield = new TextField("", new TextField.TextFieldStyle(scene.skin.get(TextField.TextFieldStyle.class))); chatfield.setTextFieldFilter((field, c) -> field.getText().length() < Vars.maxTextLength); chatfield.getStyle().background = null; - chatfield.getStyle().font = skin.getFont("default-font-chat"); + chatfield.getStyle().font = scene.skin.getFont("default-font-chat"); chatfield.getStyle().fontColor = Color.WHITE; chatfield.setStyle(chatfield.getStyle()); @@ -119,25 +119,27 @@ public class ChatFragment extends Table{ chatfield.tapped(() -> { Dialog dialog = new Dialog("", "dialog"); dialog.setFillParent(true); - dialog.content().top(); - dialog.content().defaults().height(65f); - TextField to = dialog.content().addField("", t-> {}).pad(15).width(250f).get(); + dialog.cont.top(); + dialog.cont.defaults().height(65f); + TextField to = dialog.cont.addField("", t-> {}).pad(15).width(250f).get(); to.setMaxLength(maxTextLength); - to.keyDown(Keys.ENTER, () -> dialog.content().find("okb").fireClick()); - dialog.content().addButton("$text.ok", () -> { + to.keyDown(KeyCode.ENTER, () -> { + dialog.cont.find("okb").fireClick(); + }); + dialog.cont.addButton("$ok", () -> { chatfield.clearText(); chatfield.appendText(to.getText()); chatfield.change(); dialog.hide(); - Gdx.input.setOnscreenKeyboardVisible(false); + Core.input.setOnscreenKeyboardVisible(false); toggle(); }).width(90f).name("okb"); dialog.show(); - Timers.runTask(1f, () -> { + Time.runTask(1f, () -> { to.setCursorPosition(to.getText().length()); Core.scene.setKeyboardFocus(to); - Gdx.input.setOnscreenKeyboardVisible(true); + Core.input.setOnscreenKeyboardVisible(true); }); }); } @@ -153,22 +155,22 @@ public class ChatFragment extends Table{ } @Override - public void draw(Batch batch, float alpha){ + public void draw(){ - batch.setColor(shadowColor); + Draw.color(shadowColor); if(chatOpen){ - batch.draw(skin.getRegion("white"), offsetx, chatfield.getY(), chatfield.getWidth() + 15f, chatfield.getHeight() - 1); + Fill.crect(offsetx, chatfield.getY(), chatfield.getWidth() + 15f, chatfield.getHeight() - 1); } - super.draw(batch, alpha); + super.draw(); float spacing = chatspace; - chatfield.setVisible(chatOpen); - fieldlabel.setVisible(chatOpen); + chatfield.visible(chatOpen); + fieldlabel.visible(chatOpen); - batch.setColor(shadowColor); + Draw.color(shadowColor); float theight = offsety + spacing + getMarginBottom(); for(int i = scrollPos; i < messages.size && i < messagesShown + scrollPos && (i < fadetime || chatOpen); i++){ @@ -182,19 +184,19 @@ public class ChatFragment extends Table{ if(!chatOpen && fadetime - i < 1f && fadetime - i >= 0f){ font.getCache().setAlphas(fadetime - i); - batch.setColor(0, 0, 0, shadowColor.a * (fadetime - i)); + Draw.color(0, 0, 0, shadowColor.a * (fadetime - i)); } - batch.draw(skin.getRegion("white"), offsetx, theight - layout.height - 2, textWidth + Unit.dp.scl(4f), layout.height + textspacing); - batch.setColor(shadowColor); + Fill.crect(offsetx, theight - layout.height - 2, textWidth + Unit.dp.scl(4f), layout.height + textspacing); + Draw.color(shadowColor); - font.getCache().draw(batch); + font.getCache().draw(); } - batch.setColor(Color.WHITE); + Draw.color(); if(fadetime > 0 && !chatOpen) - fadetime -= Timers.delta() / 180f; + fadetime -= Time.delta() / 180f; } private void sendMessage(){ diff --git a/core/src/io/anuke/mindustry/ui/fragments/Fragment.java b/core/src/io/anuke/mindustry/ui/fragments/Fragment.java index 080c2c4a05..f878d5465d 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/Fragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/Fragment.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.ui.fragments; -import io.anuke.ucore.scene.Group; +import io.anuke.arc.scene.Group; public abstract class Fragment{ public abstract void build(Group parent); diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index 9037574c38..0b1580d5b9 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -1,38 +1,36 @@ package io.anuke.mindustry.ui.fragments; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.Interpolation; -import com.badlogic.gdx.utils.Align; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Scaling; +import io.anuke.arc.Core; +import io.anuke.arc.Events; +import io.anuke.arc.collection.Array; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.math.Interpolation; +import io.anuke.arc.math.Mathf; +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.Touchable; +import io.anuke.arc.scene.ui.Image; +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.*; 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.type.Recipe; import io.anuke.mindustry.ui.IntFormat; -import io.anuke.mindustry.ui.Minimap; import io.anuke.mindustry.ui.dialogs.FloatingDialog; -import io.anuke.ucore.core.*; -import io.anuke.ucore.graphics.Hue; -import io.anuke.ucore.scene.Element; -import io.anuke.ucore.scene.Group; -import io.anuke.ucore.scene.actions.Actions; -import io.anuke.ucore.scene.event.Touchable; -import io.anuke.ucore.scene.ui.Image; -import io.anuke.ucore.scene.ui.ImageButton; -import io.anuke.ucore.scene.ui.Label; -import io.anuke.ucore.scene.ui.TextButton; -import io.anuke.ucore.scene.ui.layout.Stack; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Mathf; + +import java.lang.StringBuilder; import static io.anuke.mindustry.Vars.*; @@ -56,7 +54,6 @@ public class HudFragment extends Fragment{ //menu at top left parent.fill(cont -> { - cont.top().left().visible(() -> !state.is(State.menu)); if(mobile){ @@ -75,10 +72,10 @@ public class HudFragment extends Fragment{ } }).update(i -> { if(Net.active()){ - i.getStyle().imageUp = Core.skin.getDrawable("icon-players"); + i.getStyle().imageUp = Core.scene.skin.getDrawable("icon-players"); }else{ - i.setDisabled(Net.active()); - i.getStyle().imageUp = Core.skin.getDrawable(state.is(State.paused) ? "icon-play" : "icon-pause"); + i.setDisabled(false); + i.getStyle().imageUp = Core.scene.skin.getDrawable(state.is(State.paused) ? "icon-play" : "icon-pause"); } }).get(); @@ -90,26 +87,26 @@ public class HudFragment extends Fragment{ ui.chatfrag.toggle(); } }else{ - ui.unlocks.show(); + ui.database.show(); } }).update(i -> { if(Net.active() && mobile){ - i.getStyle().imageUp = Core.skin.getDrawable("icon-chat"); + i.getStyle().imageUp = Core.scene.skin.getDrawable("icon-chat"); }else{ - i.getStyle().imageUp = Core.skin.getDrawable("icon-unlocks"); + i.getStyle().imageUp = Core.scene.skin.getDrawable("icon-unlocks"); } }).get(); - select.addImage("blank").color(Palette.accent).width(6f).fillY(); + select.addImage("blank").color(Pal.accent).width(6f).fillY(); }); cont.row(); - cont.addImage("blank").height(6f).color(Palette.accent).fillX(); + cont.addImage("blank").height(6f).color(Pal.accent).fillX(); cont.row(); } cont.update(() -> { - if(!Inputs.keyDown("gridMode") && Inputs.keyTap("toggle_menus") && !ui.chatfrag.chatOpen()){ + if(!Core.input.keyDown(Binding.gridMode) && Core.input.keyTap(Binding.toggle_menus) && !ui.chatfrag.chatOpen()){ toggleMenus(); } }); @@ -131,15 +128,14 @@ public class HudFragment extends Fragment{ //fps display infolabel = cont.table(t -> { - IntFormat fps = new IntFormat("text.fps"); - IntFormat tps = new IntFormat("text.tps"); - IntFormat ping = new IntFormat("text.ping"); - t.label(() -> fps.get(Gdx.graphics.getFramesPerSecond())).padRight(10); + 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(() -> Settings.getBool("fps")).update(t -> t.setTranslation(0, (!waves.isVisible() ? wavetable.getHeight() : Math.min(wavetable.getTranslation().y, wavetable.getHeight())))).get(); + }).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){ @@ -148,18 +144,36 @@ public class HudFragment extends Fragment{ }); //minimap - parent.fill(t -> t.top().right().add(new Minimap()) - .visible(() -> !state.is(State.menu) && Settings.getBool("minimap"))); + //parent.fill(t -> t.top().right().add(new Minimap()).visible(() -> !state.is(State.menu) && Core.settings.getBool("minimap"))); - //paused table + //spawner warning parent.fill(t -> { - t.top().visible(() -> state.is(State.paused) && !Net.active()); - t.table("button", top -> top.add("$text.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 -> { t.visible(() -> netServer.isWaitingForPlayers() && !state.is(State.menu)); - t.table("button", c -> c.add("$text.waiting.players")); + t.table("button", c -> c.add("$waiting.players")); }); //'core is under attack' table @@ -193,21 +207,61 @@ public class HudFragment extends Fragment{ coreAttackOpacity = Mathf.lerpDelta(coreAttackOpacity, 0f, 0.1f); } - coreAttackTime -= Timers.delta(); + coreAttackTime -= Time.delta(); return coreAttackOpacity > 0; }); - t.table("button", top -> top.add("$text.coreattack").pad(2) - .update(label -> label.setColor(Hue.mix(Color.ORANGE, Color.SCARLET, Mathf.absin(Timers.time(), 2f, 1f))))); + t.table("button", top -> top.add("$coreattack").pad(2) + .update(label -> label.getColor().set(Color.ORANGE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 2f, 1f)))); + }); + + //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 - 70); + + button.update(() -> { + if(world.getZone() == null){ + button.setText(""); + return; + } + + button.setText(Core.bundle.get(state.enemies() > 0 ? "launch.unable" : "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 -> { t.bottom().visible(() -> !state.is(State.menu) && control.saves.isSaving()); - t.add("$text.saveload"); + t.add("$saveload"); }); - blockfrag.build(Core.scene.getRoot()); + blockfrag.build(Core.scene.root); } public void showToast(String text){ @@ -232,7 +286,9 @@ public class HudFragment extends Fragment{ } /** Show unlock notification for a new recipe. */ - public void showUnlock(Recipe recipe){ + public void showUnlock(UnlockableContent content){ + //some content may not have icons... yet + if(content.getContentIcon() == null) return; //if there's currently no unlock notification... if(lastUnlockTable == null){ @@ -249,18 +305,14 @@ public class HudFragment extends Fragment{ Table in = new Table(); //create texture stack for displaying - Stack stack = new Stack(); - for(TextureRegion region : recipe.result.getCompactIcon()){ - Image image = new Image(region); - image.setScaling(Scaling.fit); - stack.add(image); - } + Image image = new Image(content.getContentIcon()); + image.setScaling(Scaling.fit); - in.add(stack).size(48f).pad(2); + in.add(image).size(48f).pad(2); //add to table table.add(in).padRight(8); - table.add("$text.unlocked"); + table.add("$unlocked"); table.pack(); //create container table which will align and move @@ -292,11 +344,6 @@ public class HudFragment extends Fragment{ //get size of each element float size = 48f / Math.min(elements.size + 1, col); - //correct plurals if needed - if(esize == 1){ - ((Label) lastUnlockLayout.getParent().find(e -> e instanceof Label)).setText("$text.unlocked.plural"); - } - lastUnlockLayout.clearChildren(); lastUnlockLayout.defaults().size(size).pad(2); @@ -311,14 +358,10 @@ public class HudFragment extends Fragment{ //if there's space, add it if(esize < cap){ - Stack stack = new Stack(); - for(TextureRegion region : recipe.result.getCompactIcon()){ - Image image = new Image(region); - image.setScaling(Scaling.fit); - stack.add(image); - } + Image image = new Image(content.getContentIcon()); + image.setScaling(Scaling.fit); - lastUnlockLayout.add(stack); + lastUnlockLayout.add(image); }else{ //else, add a specific icon to denote no more space lastUnlockLayout.addImage("icon-add"); } @@ -328,12 +371,12 @@ public class HudFragment extends Fragment{ } public void showTextDialog(String str){ - new FloatingDialog("$text.mission.info"){{ + new FloatingDialog("$mission.info"){{ shouldPause = true; setFillParent(false); - getCell(content()).growX(); - content().margin(15).add(str).width(400f).wrap().get().setAlignment(Align.left, Align.left); - buttons().addButton("$text.continue", this::hide).size(140, 60).pad(4); + 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(); } @@ -345,7 +388,7 @@ public class HudFragment extends Fragment{ Interpolation in = Interpolation.pow3Out; if(flip != null){ - flip.getStyle().imageUp = Core.skin.getDrawable(shown ? "icon-arrow-down" : "icon-arrow-up"); + flip.getStyle().imageUp = Core.scene.skin.getDrawable(shown ? "icon-arrow-down" : "icon-arrow-up"); } if(shown){ @@ -363,33 +406,38 @@ public class HudFragment extends Fragment{ private void addWaveTable(TextButton table){ - IntFormat wavef = new IntFormat("text.wave"); - IntFormat enemyf = new IntFormat("text.wave.enemy"); - IntFormat enemiesf = new IntFormat("text.wave.enemies"); + IntFormat wavef = new IntFormat("wave"); + IntFormat enemyf = new IntFormat("wave.enemy"); + IntFormat enemiesf = new IntFormat("wave.enemies"); + IntFormat waitingf = new IntFormat("wave.waiting"); table.clearChildren(); - table.setTouchable(Touchable.enabled); + table.touchable(Touchable.enabled); - table.labelWrap(() -> - world.getSector() == null ? - (state.enemies() > 0 && state.mode.disableWaveTimer ? - wavef.get(state.wave) + "\n" + (state.enemies() == 1 ? - enemyf.get(state.enemies()) : - enemiesf.get(state.enemies())) : - wavef.get(state.wave) + "\n" + - (!state.mode.disableWaveTimer ? - Bundles.format("text.wave.waiting", (int)(state.wavetime/60)) : - Bundles.get("text.waiting"))) : - Bundles.format("text.mission.display", world.getSector().currentMission().displayString())).growX().pad(8f); + StringBuilder builder = new StringBuilder(); - table.clicked(() -> { - if(world.getSector() != null && world.getSector().currentMission().hasMessage()){ - world.getSector().currentMission().showMessage(); + table.labelWrap(() -> { + builder.setLength(0); + builder.append(wavef.get(state.wave)); + builder.append("\n"); + + if(state.enemies() > 0 && !state.rules.waveTimer){ + if(state.enemies() == 1){ + builder.append(enemyf.get(state.enemies())); + }else{ + builder.append(enemiesf.get(state.enemies())); + } + }else if(state.rules.waveTimer){ + builder.append(waitingf.get((int)(state.wavetime/60))); + }else{ + builder.append(Core.bundle.get("waiting")); } - }); - table.setDisabled(() -> !(world.getSector() != null && world.getSector().currentMission().hasMessage())); - table.visible(() -> !((world.getSector() == null && state.mode.disableWaves) || !state.mode.showMission || (world.getSector() != null && world.getSector().complete))); + return builder; + }).growX().pad(8f); + + table.setDisabled(true); + table.visible(() -> state.rules.waves); } private void addPlayButton(Table table){ @@ -400,11 +448,11 @@ public class HudFragment extends Fragment{ state.wavetime = 0f; } }).growY().fillX().right().width(40f).update(l -> { - boolean vis = state.mode.disableWaveTimer && ((Net.server() || players[0].isAdmin) || !Net.active()); + boolean vis = !state.rules.waveTimer && ((Net.server() || players[0].isAdmin) || !Net.active()); boolean paused = state.is(State.paused) || !vis; - l.getStyle().imageUp = Core.skin.getDrawable(vis ? "icon-play" : "clear"); - l.setTouchable(!paused ? Touchable.enabled : Touchable.disabled); - }).visible(() -> state.mode.disableWaveTimer && ((Net.server() || players[0].isAdmin) || !Net.active()) && unitGroups[Team.red.ordinal()].size() == 0); + 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); } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java b/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java index 3ea3df3685..2b178a2125 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.ui.fragments; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.ucore.scene.Group; -import io.anuke.ucore.scene.event.Touchable; -import io.anuke.ucore.scene.ui.Label; -import io.anuke.ucore.scene.ui.TextButton; -import io.anuke.ucore.scene.ui.layout.Table; +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; +import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.scene.ui.layout.Table; public class LoadingFragment extends Fragment{ private Table table; @@ -14,40 +14,40 @@ public class LoadingFragment extends Fragment{ @Override public void build(Group parent){ parent.fill("loadDim", t -> { - t.setVisible(false); - t.setTouchable(Touchable.enabled); + t.visible(false); + 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("$text.loading").name("namelabel").pad(10f); + 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("$text.cancel", () -> {}).pad(20).size(250f, 70f).visible(false).get(); + button = t.addButton("$cancel", () -> {}).pad(20).size(250f, 70f).visible(false).get(); table = t; }); } public void setButton(Runnable listener){ - button.setVisible(true); - button.getListeners().removeIndex(button.getListeners().size - 1); + button.visible(true); + button.getListeners().remove(button.getListeners().size - 1); button.clicked(listener); } public void show(){ - show("$text.loading"); + show("$loading"); } public void show(String text){ table.