Removed shadow/world padding

This commit is contained in:
Anuken
2018-11-12 13:17:43 -05:00
83 changed files with 1375 additions and 1454 deletions
+2
View File
@@ -1,5 +1,6 @@
##Packr, build stuff ##Packr, build stuff
logs/
/core/assets/mindustry-saves/ /core/assets/mindustry-saves/
/core/assets/mindustry-maps/ /core/assets/mindustry-maps/
/core/assets/bundles/output/ /core/assets/bundles/output/
@@ -25,6 +26,7 @@
/core/assets/version.properties /core/assets/version.properties
/core/assets/locales /core/assets/locales
/ios/src/io/anuke/mindustry/gen/ /ios/src/io/anuke/mindustry/gen/
/core/src/io/anuke/mindustry/gen/
*.gif *.gif
version.properties version.properties
@@ -42,12 +42,13 @@ public class TextFieldDialogListener extends ClickListener{
AndroidTextFieldDialog dialog = new AndroidTextFieldDialog(); AndroidTextFieldDialog dialog = new AndroidTextFieldDialog();
dialog.setTextPromptListener(text -> { dialog.setTextPromptListener(text ->
field.clearText(); Gdx.app.postRunnable(() -> {
field.appendText(text); field.clearText();
field.fire(new ChangeListener.ChangeEvent()); field.appendText(text);
Gdx.graphics.requestRendering(); field.fire(new ChangeListener.ChangeEvent());
}); Gdx.graphics.requestRendering();
}));
if(type == 0){ if(type == 0){
dialog.setInputType(InputType.TYPE_CLASS_TEXT); dialog.setInputType(InputType.TYPE_CLASS_TEXT);
+3 -2
View File
@@ -25,7 +25,7 @@ allprojects {
appName = 'Mindustry' appName = 'Mindustry'
gdxVersion = '1.9.8' gdxVersion = '1.9.8'
roboVMVersion = '2.3.0' roboVMVersion = '2.3.0'
uCoreVersion = 'eb1503dfb786f5f727bdb4b6a302718490444335' uCoreVersion = '8919cb7b6881d040fb720149779fcf58c1927893'
getVersionString = { getVersionString = {
String buildVersion = getBuildVersion() String buildVersion = getBuildVersion()
@@ -120,7 +120,7 @@ project(":ios") {
} }
} }
build.dependsOn(copyGen) //build.dependsOn(copyGen)
dependencies { dependencies {
compile project(":core") compile project(":core")
@@ -131,6 +131,7 @@ project(":ios") {
compile "com.badlogicgames.gdx:gdx-backend-robovm:$gdxVersion" compile "com.badlogicgames.gdx:gdx-backend-robovm:$gdxVersion"
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-ios" compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-ios"
compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-ios" compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-ios"
compileOnly project(":annotations")
} }
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 B

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 B

After

Width:  |  Height:  |  Size: 167 B

+2 -1
View File
@@ -263,7 +263,7 @@ text.mapeditor = Map Editor
text.donate = Donate text.donate = Donate
text.connectfail = [crimson]Failed to connect to server\:\n\n[accent]{0} text.connectfail = [crimson]Failed to connect to server\:\n\n[accent]{0}
text.error.unreachable = Server unreachable. text.error.unreachable = Server unreachable.\nIs the address spelled correctly?
text.error.invalidaddress = Invalid address. 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.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.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry!
@@ -372,6 +372,7 @@ setting.musicvol.name = Music Volume
setting.mutemusic.name = Mute Music setting.mutemusic.name = Mute Music
setting.sfxvol.name = SFX Volume setting.sfxvol.name = SFX Volume
setting.mutesound.name = Mute Sound setting.mutesound.name = Mute Sound
setting.crashreport.name = Send Anonymous Crash Reports
text.keybind.title = Rebind Keys text.keybind.title = Rebind Keys
category.general.name = General category.general.name = General
category.view.name = View category.view.name = View
File diff suppressed because it is too large Load Diff
+192 -191
View File
@@ -7,13 +7,13 @@ text.link.dev-builds.description = Versiones de desarrollo inestable
text.link.trello.description = Tablero de Trello oficial para las características planificadas 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.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.google-play.description = Ficha en la Google Play Store
text.link.wiki.description = wiki oficial de Mindustry text.link.wiki.description = Wiki oficial de Mindustry
text.linkfail = ¡Error al abrir el enlace!\nLa URL ha sido copiada a su portapapeles. text.linkfail = ¡Error al abrir el enlace!\nLa URL ha sido copiada a su portapapeles.
text.editor.web = ¡La versión web no es compatible con el editor!\nDescargue el juego para usarlo. text.editor.web = ¡La versión web no es compatible con el editor!\nDescarga el juego para usarlo.
text.web.unsupported = ¡La versión web no soporta esta característica! Descarga el juego para poder usarla. text.web.unsupported = ¡La versión web no soporta esta característica! Descarga el juego para poder usarla.
text.gameover = Tu núcleo ha sido destruido. text.gameover = Tu núcleo ha sido destruido.
text.gameover.pvp = El equipo[accent] {0}[] ha ganado! text.gameover.pvp = ¡El equipo[accent] {0}[] ha ganado!
text.sector.gameover = Este sector ha sido perdido. ¿Re-instaurar? text.sector.gameover = Este sector ha sido perdido. ¿Re-desplegar?
text.sector.retry = Reintentar text.sector.retry = Reintentar
text.highscore = [accent]¡Nueva mejor puntuación! text.highscore = [accent]¡Nueva mejor puntuación!
text.wave.lasted = Duraste hasta la ronda [accent]{0}[]. text.wave.lasted = Duraste hasta la ronda [accent]{0}[].
@@ -22,35 +22,35 @@ text.level.delete.title = Confirmar Eliminación
text.map.delete = ¿Estás seguro que quieres borrar el mapa "[accent]{0}[]"? text.map.delete = ¿Estás seguro que quieres borrar el mapa "[accent]{0}[]"?
text.level.select = Selección de nivel text.level.select = Selección de nivel
text.level.mode = Modo de juego: 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 barra espaciadora[]. 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.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.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.title = Guía de Deconstrucción de Bloques
text.deconstruction = Acaba de seleccionar el [accent]modo de deconstrucción de bloques[].\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.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 devuelta en la próxima sesión text.showagain = No mostrar otra vez en la próxima sesión
text.coreattack = < ¡El núcleo está bajo ataque! > text.coreattack = < ¡El núcleo está bajo ataque! >
text.unlocks = Desbloqueos text.unlocks = Desbloqueos
text.savegame = Guardar Partida text.savegame = Guardar Partida
text.loadgame = Cargar Partida text.loadgame = Cargar Partida
text.joingame = Unirse a la Partida text.joingame = Unirse a la Partida
text.addplayers = Agregar/Remover Jugadores text.addplayers = Agregar/Quitar Jugadores
text.customgame = Partida personalizada text.customgame = Partida personalizada
text.sectors = Sectores text.sectors = Sectores
text.sector = Sector: [LIGHT_GRAY]{0} text.sector = Sector: [LIGHT_GRAY]{0}
text.sector.time = Tiempo: [LIGHT_GRAY]{0} text.sector.time = Tiempo: [LIGHT_GRAY]{0}
text.sector.deploy = Desplegar text.sector.deploy = Desplegar
text.sector.abandon = Abandonar text.sector.abandon = Abandonar
text.sector.abandon.confirm = ¿Definitivamente quieres abandonar todo el progreso hecho en este sector?\n¡Esto no se puede deshacer! text.sector.abandon.confirm = ¿Realmente quieres abandonar todo el progreso hecho en este sector?\n¡Esto no se puede deshacer!
text.sector.resume = Resumir text.sector.resume = Continuar
text.sector.locked = [scarlet][[Incompleto] text.sector.locked = [scarlet][[Incompleto]
text.sector.unexplored = [accent][[Inexplorado] text.sector.unexplored = [accent][[No explorado]
text.missions = Missions:[LIGHT_GRAY] {0} text.missions = Misiones:[LIGHT_GRAY] {0}
text.mission = Misión:[LIGHT_GRAY] {0} text.mission = Misión:[LIGHT_GRAY] {0}
text.mission.main = Misión Principal:[LIGHT_GRAY] {0} text.mission.main = Misión Principal:[LIGHT_GRAY] {0}
text.mission.info = Información de la Misión text.mission.info = Información de la Misión
text.mission.complete = ¡Misión completada! text.mission.complete = ¡Misión completada!
text.mission.complete.body = El Sector {0},{1} ha sido conquistado. text.mission.complete.body = El Sector {0},{1} ha sido conquistado.
text.mission.wave = Sobrevive [accent]{0}[] hordas. 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.enemies = Sobrevive[accent] {0}/{1} []hordas\n{2} Enemigas
text.mission.wave.enemy = 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.wave.menu = Sobrevive[accent] {0} []hordas
@@ -58,11 +58,11 @@ text.mission.battle = Destruye la base enemiga.
text.mission.resource.menu = Obtener {0} x{1} text.mission.resource.menu = Obtener {0} x{1}
text.mission.resource = Obtén {0} x{1} text.mission.resource = Obtén {0} x{1}
text.mission.block = Crear {0} text.mission.block = Crear {0}
text.mission.unit = Crear {0} Unit text.mission.unit = Crear {0}
text.mission.command = Enviar Comando {0} A Las Unidades text.mission.command = Envía Comando {0} a las unidades
text.mission.linknode = Conecta nodo de energía text.mission.linknode = Conecta nodo de energía
text.mission.display = [accent]Misión:\n[LIGHT_GRAY]{0} text.mission.display = [accent]Misión:\n[LIGHT_GRAY]{0}
text.mission.mech = Cambiar a mech[accent] {0}[] text.mission.mech = Cambiar a mecanoide[accent] {0}[]
text.mission.create = Crear[accent] {0}[] text.mission.create = Crear[accent] {0}[]
text.none = <no hay> text.none = <no hay>
text.close = Cerrar text.close = Cerrar
@@ -82,24 +82,24 @@ text.server.closing = [accent]Cerrando servidor...
text.server.kicked.kick = ¡Has sido expulsado del servidor! text.server.kicked.kick = ¡Has sido expulsado del servidor!
text.server.kicked.serverClose = El servidor ha cerrado. text.server.kicked.serverClose = El servidor ha cerrado.
text.server.kicked.sectorComplete = Sector completado. text.server.kicked.sectorComplete = Sector completado.
text.server.kicked.sectorComplete.text = Tu misión ha sido completada.\nEl servidor ahora continuara con el próximo sector. 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.clientOutdated = ¡Cliente desactualizado! ¡Actualiza tu juego!
text.server.kicked.serverOutdated = ¡Servidor desactualizado! ¡Pídele al anfitrión que lo actualice! 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.banned = Has sido baneado del servidor.
text.server.kicked.recentKick = Has sido expulsado recientemente.\nEspera para poder conectarte de nuevo. text.server.kicked.recentKick = Has sido expulsado recientemente.\nEspera para poder conectarte de nuevo.
text.server.kicked.nameInUse = Ya hay alguien con ese nombre\nen el servidor. 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.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.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.server.kicked.customClient = Este servidor no soporta versiones personalizadas. Descarga una versión oficial.
text.host.info = El botón [accent]hostear[] 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.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 servidor[] 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.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 = Hostear Servidor
text.hostserver.mobile = Hostear\nJuego text.hostserver.mobile = Hostear\nJuego
text.host = Hostear text.host = Hostear
text.hosting = [accent]Abriendo servidor... text.hosting = [accent]Abriendo servidor...
text.hosts.refresh = Actualizar text.hosts.refresh = Actualizar
text.hosts.discovering = Descubrir partidas LAN text.hosts.discovering = Descubrir partidas LAN
text.server.refreshing = Actualizando servidor text.server.refreshing = Actualizando servidor...
text.hosts.none = [lightgray]¡No se han encontrado partidas LAN! text.hosts.none = [lightgray]¡No se han encontrado partidas LAN!
text.host.invalid = [scarlet]No se ha podido conectar al anfitrión text.host.invalid = [scarlet]No se ha podido conectar al anfitrión
text.trace = Rastrear Jugador text.trace = Rastrear Jugador
@@ -108,29 +108,29 @@ text.trace.ip = IP: [accent]{0}
text.trace.id = ID Única: [accent]{0} text.trace.id = ID Única: [accent]{0}
text.trace.android = Cliente de Android: [accent]{0} text.trace.android = Cliente de Android: [accent]{0}
text.trace.modclient = Cliente Personalizado: [accent]{0} text.trace.modclient = Cliente Personalizado: [accent]{0}
text.trace.totalblocksbroken = Total de bloques removidos: [accent]{0} text.trace.totalblocksbroken = Total de bloques quitados: [accent]{0}
text.trace.structureblocksbroken = Bloques de estructura removidos: [accent]{0} text.trace.structureblocksbroken = Bloques de estructura quitados: [accent]{0}
text.trace.lastblockbroken = Último bloque removido: [accent]{0} text.trace.lastblockbroken = Último bloque quitado: [accent]{0}
text.trace.totalblocksplaced = Total de bloques colocados: [accent]{0} text.trace.totalblocksplaced = Total de bloques colocados: [accent]{0}
text.trace.lastblockplaced = Último bloque colocado: [accent]{0} text.trace.lastblockplaced = Último bloque colocado: [accent]{0}
text.invalidid = ¡ID de cliente invalida! Envía un informe del error. text.invalidid = ¡ID de cliente inválida! Envía un informe del error.
text.server.bans = Bans text.server.bans = Baneos
text.server.bans.none = ¡Ningún usuario ha sido baneado! text.server.bans.none = ¡Ningún usuario ha sido baneado!
text.server.admins = Admins text.server.admins = Administradores
text.server.admins.none = ¡Ningún admin ha sido encontrado! text.server.admins.none = ¡Ningún administrador ha sido encontrado!
text.server.add = Agregar Servidor text.server.add = Agregar Servidor
text.server.delete = ¿Estás seguro que quieres borrar este servidor? text.server.delete = ¿Estás seguro de querer borrar este servidor?
text.server.hostname = Anfitrión: {0} text.server.hostname = Anfitrión: {0}
text.server.edit = Editar Servidor text.server.edit = Editar Servidor
text.server.outdated = [crimson]¡Servidor desactualizado![] text.server.outdated = [crimson]¡Servidor desactualizado![]
text.server.outdated.client = [crimson]¡Cliente desactualizado![] text.server.outdated.client = [crimson]¡Cliente desactualizado![]
text.server.version = [lightgray]Versión: {0} text.server.version = [lightgray]Versión: {0}
text.server.custombuild = [yellow]Versión personalizada text.server.custombuild = [yellow]Versión personalizada
text.confirmban = ¿Estás seguro que quieres banear este jugador? text.confirmban = ¿Estás seguro de querer banear este jugador?
text.confirmkick = ¿Estás seguro que quieres expulsar este jugador? text.confirmkick = ¿Estás seguro de querer expulsar este jugador?
text.confirmunban = ¿Estás seguro que quieres desbanear este jugador? text.confirmunban = ¿Estás seguro de querer desbanear este jugador?
text.confirmadmin = ¿Estás seguro que quieres hacer admin a este jugador? text.confirmadmin = ¿Estás seguro de querer hacer administrador a este jugador?
text.confirmunadmin = ¿Estás seguro que quieres quitar los permisos de admin 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.title = Unirse a la partida
text.joingame.ip = IP: text.joingame.ip = IP:
text.disconnect = Desconectado. text.disconnect = Desconectado.
@@ -138,29 +138,29 @@ text.disconnect.data = ¡Se ha fallado la carga de datos del mundo!
text.connecting = [accent]Conectando... text.connecting = [accent]Conectando...
text.connecting.data = [accent]Cargando datos del mundo... text.connecting.data = [accent]Cargando datos del mundo...
text.server.port = Puerto: text.server.port = Puerto:
text.server.addressinuse = ¡La dirección está en uso! text.server.addressinuse = ¡La dirección ya está en uso!
text.server.invalidport = ¡El número de puerto es invalido! text.server.invalidport = ¡El número de puerto es invalido!
text.server.error = [crimson]Error hosteando el servidor: [accent]{0} text.server.error = [crimson]Error hosteando el servidor: error [accent]{0}
text.save.old = Este punto de guardado es para una versión más antigua de este juego, y ya no puede ser usada.\n\n[LIGHT_GRAY]Guardados con retrocompatibilidad sen completamente implementados en la versión 4.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.new = Nuevo Punto de Guardado
text.save.overwrite = ¿Estás seguro que quieres sobrescribir\neste punto de guardado? text.save.overwrite = ¿Estás seguro de querer sobrescribir\neste punto de guardado?
text.overwrite = Sobrescribir text.overwrite = Sobrescribir
text.save.none = ¡No se ha encontrado ningún punto de guardado! text.save.none = ¡No se ha encontrado ningún punto de guardado!
text.saveload = [accent]Guardando... text.saveload = [accent]Guardando...
text.savefail = ¡No se ha podido guardar la partida! text.savefail = ¡No se ha podido guardar la partida!
text.save.delete.confirm = ¿Estás seguro que quieres borrar este punto de guardado? text.save.delete.confirm = ¿Estás seguro de querer borrar este punto de guardado?
text.save.delete = Borrar text.save.delete = Borrar
text.save.export = Exportar Punto de Guardado text.save.export = Exportar Punto de Guardado
text.save.import.invalid = [accent]¡Este punto de guardado es invalido! text.save.import.invalid = [accent]¡Este punto de guardado es inválido!
text.save.import.fail = [crimson]Se ha fallado la importación del punto de guardado: [accent]{0} text.save.import.fail = [crimson]La importación del punto de guardado ha fallado: error [accent]{0}
text.save.export.fail = [crimson]Se ha fallado la exportación del punto de guardado: [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.import = Importar Punto de Guardado
text.save.newslot = Nombre del Punto de Guardado: text.save.newslot = Nombre del Punto de Guardado:
text.save.rename = Renombrar text.save.rename = Renombrar
text.save.rename.text = Nuevo nombre: text.save.rename.text = Nuevo nombre:
text.selectslot = Selecciona un Punto de Guardado. text.selectslot = Selecciona un Punto de Guardado.
text.slot = [accent]Casilla {0} text.slot = [accent]Casilla {0}
text.save.corrupted = [accent]¡El punto de guardado está corrupto o es invalido!\nSi acabas de actualizar el juego, esto debe ser probablemente un cambio en el formato de guardado y [scarlet]no[] un error. 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.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 = <vacío> text.empty = <vacío>
text.on = Encendido text.on = Encendido
@@ -169,7 +169,7 @@ text.save.autosave = Autoguardado: {0}
text.save.map = Mapa: {0} text.save.map = Mapa: {0}
text.save.wave = Horda {0} text.save.wave = Horda {0}
text.save.difficulty = Dificultad: {0} text.save.difficulty = Dificultad: {0}
text.save.date = Ultima vez guardado: {0} text.save.date = Última vez guardado: {0}
text.save.playtime = Tiempo de juego: {0} text.save.playtime = Tiempo de juego: {0}
text.confirm = Confirmar text.confirm = Confirmar
text.delete = Borrar text.delete = Borrar
@@ -182,9 +182,9 @@ text.back = Atras
text.quit.confirm = ¿Estás seguro de querer salir de la partida? text.quit.confirm = ¿Estás seguro de querer salir de la partida?
text.changelog.title = Registro de Parches text.changelog.title = Registro de Parches
text.changelog.loading = Consiguiendo el registro de parches... text.changelog.loading = Consiguiendo el registro de parches...
text.changelog.error.android = [accent]¡Nota que el registro de parches a veces no funciona en Android 4.4 o inferior!\nEsto es por un error de Android interno. 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 es actualmente soportado por iOS. text.changelog.error.ios = [accent]El registro de parches no es actualmente soportado para iOS.
text.changelog.error = [scarlet]¡Error consiguiendo el registro de parches!\nChequeá tu conexión a Internet. 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.current = [yellow][[Versión actual]
text.changelog.latest = [accent][[Última version] text.changelog.latest = [accent][[Última version]
text.loading = [accent]Cargando... text.loading = [accent]Cargando...
@@ -192,7 +192,7 @@ text.saving = [accent]Guardando...
text.wave = [accent]Horda {0} text.wave = [accent]Horda {0}
text.wave.waiting = Horda en {0} text.wave.waiting = Horda en {0}
text.waiting = Esperando... text.waiting = Esperando...
text.waiting.players = Esperando por jugafores... text.waiting.players = Esperando jugadores...
text.wave.enemies = [LIGHT_GRAY]{0} Enemigos Restantes text.wave.enemies = [LIGHT_GRAY]{0} Enemigos Restantes
text.wave.enemy = [LIGHT_GRAY]{0} Enemigo Restante text.wave.enemy = [LIGHT_GRAY]{0} Enemigo Restante
text.loadimage = Cargar Imagen text.loadimage = Cargar Imagen
@@ -200,11 +200,11 @@ text.saveimage = Guardar Imagen
text.unknown = Desconocido text.unknown = Desconocido
text.custom = Personalizado text.custom = Personalizado
text.builtin = Incorporado text.builtin = Incorporado
text.map.delete.confirm = ¿Estás seguro que quieres borrar este mapa? ¡Recuerda que está acción no puede ser descartada! 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.random = [accent]Mapa Aleatorio
text.map.nospawn = ¡Este mapa no tiene ningún núcleo en el cual pueda meter al jugador! Agrega un núcleo [ROYAL]azul[] al mapa con el editor. 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 [SCARLET] red[] núcleos a este mapa en 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: corrupto o archivo invalido. text.map.invalid = Error cargando el mapa: archivo corrupto o inválido.
text.editor.brush = Pincel text.editor.brush = Pincel
text.editor.slope = \\ text.editor.slope = \\
text.editor.openin = Abrir en el Editor text.editor.openin = Abrir en el Editor
@@ -216,15 +216,15 @@ text.editor.description = Descripción:
text.editor.name = Nombre: text.editor.name = Nombre:
text.editor.teams = Equipos text.editor.teams = Equipos
text.editor.elevation = Elevación text.editor.elevation = Elevación
text.editor.errorimageload = Error cargando el archivo:\n[accent]{0} text.editor.errorimageload = Error cargando el archivo:\n[accent] {0}
text.editor.errorimagesave = Error guardando el archivo:\n[accent]{0} text.editor.errorimagesave = Error guardando el archivo:\n[accent] {0}
text.editor.generate = Generar text.editor.generate = Generar
text.editor.resize = Cambiar Tamaño text.editor.resize = Cambiar Tamaño
text.editor.loadmap = Cargar Mapa text.editor.loadmap = Cargar Mapa
text.editor.savemap = Guardar Mapa text.editor.savemap = Guardar Mapa
text.editor.saved = ¡Guardado! 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.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 menu '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.exists = [scarlet]¡No se ha podido importar:[] un mapa incorporado con el nombre '{0}' ya existe!
text.editor.import = Importar... text.editor.import = Importar...
text.editor.importmap = Importar Mapa text.editor.importmap = Importar Mapa
@@ -240,14 +240,14 @@ text.editor.exportimage = Exportar Imagen del Terreno
text.editor.exportimage.description = Exportar archivo de imagen del mapa text.editor.exportimage.description = Exportar archivo de imagen del mapa
text.editor.loadimage = Importar Terreno text.editor.loadimage = Importar Terreno
text.editor.saveimage = Exportar Terreno text.editor.saveimage = Exportar Terreno
text.editor.unsaved = [scarlet]¡Tienes cambios sin guardar![]\n¿Estás seguro que quieres salir? 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.resizemap = Cambiar Tamaño del Mapa
text.editor.mapname = Nombre del Mapa: text.editor.mapname = Nombre del Mapa:
text.editor.overwrite = [accent]¡Advertencia!\nEsto sobrescribe un mapa ya existente. 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 que quieres sobrescribirlo? 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.editor.selectmap = Selecciona un mapa para cargar:
text.width = Ancho: text.width = Ancho:
text.height = Altura: text.height = Alto:
text.menu = Menu text.menu = Menu
text.play = Jugar text.play = Jugar
text.load = Cargar text.load = Cargar
@@ -264,7 +264,7 @@ text.donate = Donar
text.connectfail = [crimson]Ha fallado la conexión con el servidor: [accent]{0} text.connectfail = [crimson]Ha fallado la conexión con el servidor: [accent]{0}
text.error.unreachable = Servidor inaccesible. text.error.unreachable = Servidor inaccesible.
text.error.invalidaddress = Dirección inválida. text.error.invalidaddress = Dirección inválida.
text.error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! 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.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.alreadyconnected = Ya estás conectado.
text.error.mapnotfound = ¡Archivo de mapa no encontrado! text.error.mapnotfound = ¡Archivo de mapa no encontrado!
@@ -277,17 +277,17 @@ text.settings.game = Juego
text.settings.sound = Sonido text.settings.sound = Sonido
text.settings.graphics = Gráficos text.settings.graphics = Gráficos
text.settings.cleardata = Limpiar Datos del Juego... text.settings.cleardata = Limpiar Datos del Juego...
text.settings.clear.confirm = ¿Estas seguro de querer limpiar estos datos?\nEsta accion no puede deshacerse! 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 saves, mapas, desbloqueos y keybinds.\nUna vez presiones 'ok' el juego va a borrrar todos tus datos y a salir del juego automáticamente. 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 = Limpiar Sectores text.settings.clearsectors = Limpiar Sectores
text.settings.clearunlocks = Limpiar Desbloqueos text.settings.clearunlocks = Limpiar Desbloqueos
text.settings.clearall = Limpiar Todo text.settings.clearall = Limpiar Todo
text.paused = Pausado text.paused = Pausado
text.yes = Si text.yes =
text.no = No text.no = No
text.info.title = [accent]Información text.info.title = [accent]Información
text.error.title = [crimson]Un error ha ocurrido text.error.title = [crimson]Un error ha ocurrido.
text.error.crashtitle = Un error ha ocurrido text.error.crashtitle = Un error ha ocurrido.
text.blocks.blockinfo = Información del Bloque text.blocks.blockinfo = Información del Bloque
text.blocks.powercapacity = Capacidad de Energía text.blocks.powercapacity = Capacidad de Energía
text.blocks.powershot = Energía/Disparo text.blocks.powershot = Energía/Disparo
@@ -311,7 +311,7 @@ text.blocks.inputliquidaux = Líquido Auxiliar
text.blocks.inputitem = Objeto de Entrada text.blocks.inputitem = Objeto de Entrada
text.blocks.inputitems = Objetos de Entrada text.blocks.inputitems = Objetos de Entrada
text.blocks.outputitem = Objeto de Salida text.blocks.outputitem = Objeto de Salida
text.blocks.drilltier = Taladrable text.blocks.drilltier = Taladrables
text.blocks.drillspeed = Velocidad de Base del Taladro text.blocks.drillspeed = Velocidad de Base del Taladro
text.blocks.liquidoutput = Líquido de Salida text.blocks.liquidoutput = Líquido de Salida
text.blocks.liquidoutputspeed = Velocidad de Salida del Líquido text.blocks.liquidoutputspeed = Velocidad de Salida del Líquido
@@ -326,7 +326,7 @@ text.blocks.inaccuracy = Imprecisión
text.blocks.shots = Disparos text.blocks.shots = Disparos
text.blocks.reload = Recarga text.blocks.reload = Recarga
text.blocks.inputfuel = Combustible text.blocks.inputfuel = Combustible
text.blocks.fuelburntime = Tiempo de Quema del Combustible text.blocks.fuelburntime = Tiempo de Quemado del Combustible
text.blocks.inputcapacity = Capacidad de entrada text.blocks.inputcapacity = Capacidad de entrada
text.blocks.outputcapacity = Capacidad de salida text.blocks.outputcapacity = Capacidad de salida
text.unit.blocks = bloques text.unit.blocks = bloques
@@ -346,7 +346,7 @@ text.category.items = Objetos
text.category.crafting = Fabricación text.category.crafting = Fabricación
text.category.shooting = Disparo text.category.shooting = Disparo
setting.autotarget.name = Auto apuntado setting.autotarget.name = Auto apuntado
setting.fpscap.name = Max FPS setting.fpscap.name = Máx FPS
setting.fpscap.none = Nada setting.fpscap.none = Nada
setting.fpscap.text = {0} FPS setting.fpscap.text = {0} FPS
setting.difficulty.training = entrenamiento setting.difficulty.training = entrenamiento
@@ -361,28 +361,28 @@ setting.sensitivity.name = Sensibilidad del Control
setting.saveinterval.name = Intervalo del Auto-guardado setting.saveinterval.name = Intervalo del Auto-guardado
setting.seconds = {0} Segundos setting.seconds = {0} Segundos
setting.fullscreen.name = Pantalla Completa setting.fullscreen.name = Pantalla Completa
setting.multithread.name = Multihilo setting.multithread.name = Multiproceso
setting.fps.name = Mostrar FPS setting.fps.name = Mostrar FPS
setting.vsync.name = VSync setting.vsync.name = VSync
setting.lasers.name = Mostrar Energía de los Lasers setting.lasers.name = Mostrar Energía de los Láseres
setting.minimap.name = Mostrar Minimapa setting.minimap.name = Mostrar Minimapa
setting.musicvol.name = Volumen de la Musica setting.musicvol.name = Volumen de la Música
setting.mutemusic.name = Mutear Musica setting.mutemusic.name = Silenciar Musica
setting.sfxvol.name = Volumen de los efectos de sonido setting.sfxvol.name = Volumen de los efectos de sonido
setting.mutesound.name = Mutear Sonido setting.mutesound.name = Silenciar Sonido
text.keybind.title = Reasignar Teclas text.keybind.title = Reasignar Teclas
category.general.name = General category.general.name = General
category.view.name = Visión category.view.name = Visión
category.multiplayer.name = Multijugador category.multiplayer.name = Multijugador
command.attack = Atacar command.attack = Atacar
command.retreat = Retirada command.retreat = Retirarse
command.patrol = Patrullar command.patrol = Patrullar
keybind.press = Presiona una tecla... keybind.press = Presiona una tecla...
keybind.press.axis = Pulsa un eje o botón... keybind.press.axis = Pulsa un eje o botón...
keybind.move_x.name = Mover x keybind.move_x.name = Mover x
keybind.move_y.name = Mover y keybind.move_y.name = Mover y
keybind.select.name = Seleccionar keybind.select.name = Seleccionar
keybind.break.name = Remover keybind.break.name = Romper
keybind.deselect.name = Deseleccionar keybind.deselect.name = Deseleccionar
keybind.shoot.name = Disparar keybind.shoot.name = Disparar
keybind.zoom_hold.name = Mantener Zoom keybind.zoom_hold.name = Mantener Zoom
@@ -402,9 +402,9 @@ keybind.drop_unit.name = drop unit
keybind.zoom_minimap.name = Zoom minimapa keybind.zoom_minimap.name = Zoom minimapa
mode.text.help.title = Descripción de modos mode.text.help.title = Descripción de modos
mode.waves.name = hordas mode.waves.name = hordas
mode.waves.description = el modo normal. con recursos limitados y entrada de hordas automática. mode.waves.description = El modo normal. con recursos limitados y entrada de hordas automática.
mode.sandbox.name = sandbox mode.sandbox.name = sandbox
mode.sandbox.description = recursos ilimitados y no hay temporizador para las hordas. mode.sandbox.description = Recursos ilimitados y sin temporizador para las hordas.
mode.custom.warning = Ten en cuenta que los bloques no pueden usarse en partidas personalizadas hasta que se desbloqueen en sectores.\n\n[LIGHT_GRAY]Si no desbloqueaste ningún bloque, ningno aparecerá. mode.custom.warning = Ten en cuenta que los bloques no pueden usarse en partidas personalizadas hasta que se desbloqueen en sectores.\n\n[LIGHT_GRAY]Si no desbloqueaste ningún bloque, ningno aparecerá.
mode.custom.warning.read = Solo para asegurar que lo has leído:\n[scarlet]¡LOS DESBLOQUEOS EN PARTIDAS PERSONALIZADAS NO ESTÁN DISPONIBLES EN LOS SECTORES U OTROS MODOS DE JUEGO!\n\n[LIGHT_GRAY](Ojalá esto no fuera necesario, pero parece que lo es) mode.custom.warning.read = Solo para asegurar que lo has leído:\n[scarlet]¡LOS DESBLOQUEOS EN PARTIDAS PERSONALIZADAS NO ESTÁN DISPONIBLES EN LOS SECTORES U OTROS MODOS DE JUEGO!\n\n[LIGHT_GRAY](Ojalá esto no fuera necesario, pero parece que lo es)
mode.freebuild.name = construcción libre mode.freebuild.name = construcción libre
@@ -451,33 +451,33 @@ liquid.lava.name = Lava
liquid.oil.name = Petróleo liquid.oil.name = Petróleo
liquid.cryofluid.name = Criogénico liquid.cryofluid.name = Criogénico
mech.alpha-mech.name = Alpha mech.alpha-mech.name = Alpha
mech.alpha-mech.weapon = Heavy Repeater mech.alpha-mech.weapon = Repetidor Pesado
mech.alpha-mech.ability = Drone Swarm 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.description = El mecanoide estándar. Tiene velocidad y daño decentes, puede crear hasta 3 drones para poder ofensivo incremenado.
mech.delta-mech.name = Delta mech.delta-mech.name = Delta
mech.delta-mech.weapon = Arc Generator mech.delta-mech.weapon = Generador de arco
mech.delta-mech.ability = Discharge mech.delta-mech.ability = Descarga
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.description = Un mecanoide rápido y ligeramente armado para ataques de ataque y retirada. Hace poco daño a estructuras, pero puede eliminar rápidamente a grandes grupos de unidades con sus armas de arco eléctrico.
mech.tau-mech.name = Tau mech.tau-mech.name = Tau
mech.tau-mech.weapon = Restruct Laser mech.tau-mech.weapon = Láser de reestructuración
mech.tau-mech.ability = Repair Burst 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.description = El mecanoide de soporte. Repara bloques aliados disparándolos. Puede extinguir el fuego y reparar aliados en un rango con su habilidad de reparación.
mech.omega-mech.name = Omega mech.omega-mech.name = Omega
mech.omega-mech.weapon = Swarm Missiles mech.omega-mech.weapon = Swarm Missiles
mech.omega-mech.ability = Armored Configuration 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.omega-mech.description = Un mecanoide grande y bien armado, hecho para asaltos en primera línea. Su habilidad de armadura puede bloquear hasta el 90% del daño que recibe.
mech.dart-ship.name = Dart mech.dart-ship.name = Dardo
mech.dart-ship.weapon = Repeater mech.dart-ship.weapon = Repetidor
mech.dart-ship.description = La nave normal. Bastante ligera y rápida, pero tiene poca capacidad ofensiva y baja velocidad minado. mech.dart-ship.description = La nave normal. Bastante ligera y rápida, pero tiene poca capacidad ofensiva y baja velocidad minado.
mech.javelin-ship.name = Jabalina mech.javelin-ship.name = Jabalina
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.description = Una nave de ataque y retirada. Aunque inicialmente lento, puede acelerar a altas velocidades y volar sobre puestos enemigos, causando gran daño con su habilidad de rayos y misiles.
mech.javelin-ship.weapon = Burst Missiles mech.javelin-ship.weapon = Burst Missiles
mech.javelin-ship.ability = Discharge Booster mech.javelin-ship.ability = Discharge Booster
mech.trident-ship.name = Tridente mech.trident-ship.name = Tridente
mech.trident-ship.description = A heavy bomber. Reasonably well armored. mech.trident-ship.description = Un bombardero pesado. Razonablemente bien equipado.
mech.trident-ship.weapon = Bomb Bay mech.trident-ship.weapon = Bomb Bay
mech.glaive-ship.name = Glaive 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.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 mech.glaive-ship.weapon = Flame Repeater
text.item.explosiveness = [LIGHT_GRAY]Explosividad: {0} text.item.explosiveness = [LIGHT_GRAY]Explosividad: {0}
text.item.flammability = [LIGHT_GRAY]Inflamabilidad: {0} text.item.flammability = [LIGHT_GRAY]Inflamabilidad: {0}
@@ -557,14 +557,14 @@ block.pneumatic-drill.name = Taladro neumático
block.laser-drill.name = Taladro Laser block.laser-drill.name = Taladro Laser
block.water-extractor.name = Extractor de Agua block.water-extractor.name = Extractor de Agua
block.cultivator.name = Cultivador block.cultivator.name = Cultivador
block.alpha-mech-pad.name = Alpha Mech Pad block.alpha-mech-pad.name = Pad de mecanoide Alpha
block.dart-ship-pad.name = Dart Ship Pad block.dart-ship-pad.name = Pad de nave de dardos
block.delta-mech-pad.name = Delta Mech Pad block.delta-mech-pad.name = Pad de mecanoide Delta
block.javelin-ship-pad.name = Javelin Ship Pad block.javelin-ship-pad.name = Pad de nave Jabalina
block.trident-ship-pad.name = Trident Ship Pad block.trident-ship-pad.name = Pad de nave Tridente
block.glaive-ship-pad.name = Glaive Ship Pad block.glaive-ship-pad.name = Glaive Ship Pad
block.omega-mech-pad.name = Omega Mech Pad block.omega-mech-pad.name = Pad de mecanoide Omega
block.tau-mech-pad.name = Tau Mech Pad block.tau-mech-pad.name = Pad de mecanoide Tau
block.conduit.name = Conducto block.conduit.name = Conducto
block.mechanical-pump.name = Bomba Mecánica block.mechanical-pump.name = Bomba Mecánica
block.itemsource.name = Objeto Fuente block.itemsource.name = Objeto Fuente
@@ -587,12 +587,12 @@ block.solidifer.name = Solidificador
block.solar-panel.name = Panel Solar block.solar-panel.name = Panel Solar
block.solar-panel-large.name = Panel Solar Grande block.solar-panel-large.name = Panel Solar Grande
block.oil-extractor.name = Extractor de Petróleo block.oil-extractor.name = Extractor de Petróleo
block.spirit-factory.name = Spirit Drone Factory block.spirit-factory.name = Fábrica de Drones Espíritu
block.phantom-factory.name = Phantom Drone Factory block.phantom-factory.name = Fábrica de Drones Fantasmales
block.wraith-factory.name = Wraith Fighter Factory block.wraith-factory.name = Wraith Fighter Factory
block.ghoul-factory.name = Ghoul Bomber Factory block.ghoul-factory.name = Ghoul Bomber Factory
block.dagger-factory.name = Dagger Mech Factory block.dagger-factory.name = Fábrica de Dagas
block.titan-factory.name = Titan Mech Factory block.titan-factory.name = Fábrica de Titanes
block.fortress-factory.name = Fortress Mech Factory block.fortress-factory.name = Fortress Mech Factory
block.revenant-factory.name = Revenant Fighter Factory block.revenant-factory.name = Revenant Fighter Factory
block.repair-point.name = Punto de Reparación block.repair-point.name = Punto de Reparación
@@ -610,7 +610,7 @@ block.blast-drill.name = Taladro Gigante
block.thermal-pump.name = Bomba Térmica block.thermal-pump.name = Bomba Térmica
block.thermal-generator.name = Generador Térmico block.thermal-generator.name = Generador Térmico
block.alloy-smelter.name = Alloy Smtler block.alloy-smelter.name = Alloy Smtler
block.mend-projector.name = Mend Projector block.mend-projector.name = Proyector de reparación
block.surge-wall.name = Surge Wall block.surge-wall.name = Surge Wall
block.surge-wall-large.name = Large Surge Wall block.surge-wall-large.name = Large Surge Wall
block.cyclone.name = Ciclón block.cyclone.name = Ciclón
@@ -622,30 +622,30 @@ block.arc.name = Arc
block.rtg-generator.name = Generador RTG block.rtg-generator.name = Generador RTG
block.spectre.name = Spectre block.spectre.name = Spectre
block.meltdown.name = Meltdown block.meltdown.name = Meltdown
block.container.name = Container block.container.name = Contenedor
team.blue.name = azul team.blue.name = azul
team.red.name = rojo team.red.name = rojo
team.orange.name = naranja team.orange.name = naranja
team.none.name = gris team.none.name = gris
team.green.name = verde team.green.name = verde
team.purple.name = púrpura team.purple.name = púrpura
unit.alpha-drone.name = Alpha Drone unit.alpha-drone.name = Dron Alpha
unit.spirit.name = Spirit Drone unit.spirit.name = Dron Espíritu
unit.spirit.description = El dron del comienzo. Aparece en el núcleo por defecto. Mina automáticamente minerales, recoge objetos y repara bloques. unit.spirit.description = El dron del comienzo. Aparece en el núcleo por defecto. Mina automáticamente minerales, recoge objetos y repara bloques.
unit.phantom.name = Phantom Drone 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.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.name = Daga
unit.dagger.description = Una unidad de terreno. Útil con enjambres. unit.dagger.description = Una unidad de terreno. Útil con enjambres.
unit.titan.name = Titán unit.titan.name = Titán
unit.titan.description = Una unidad blindada de terreno, avanzada. Ataca blancos de aire y de terreno. unit.titan.description = Una unidad blindada de terreno, avanzada. Ataca blancos de aire y de terreno.
unit.ghoul.name = Ghoul Bomber unit.ghoul.name = Ghoul Bomber
unit.ghoul.description = A heavy carpet bomber. Uses blast compound or pyratite as ammo. unit.ghoul.description = Una unidad bombardera pesada. Usa compuesto explosivo o pirotita como munición.
unit.wraith.name = Wraith Fighter unit.wraith.name = Wraith Fighter
unit.wraith.description = A fast, hit-and-run interceptor unit. unit.wraith.description = Una unidad interceptora rápida.
unit.fortress.name = Fortress unit.fortress.name = Fortress
unit.fortress.description = A heavy artillery ground unit. unit.fortress.description = Una unidad terrestre pesada de artillería.
unit.revenant.name = Revenant unit.revenant.name = Revenant
unit.revenant.description = A heavy laser platform. unit.revenant.description = Una plataforma láser pesada.
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.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.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. tutorial.conveyor = Los [accent]Conveyors[] se usan para transportar objetos al núcleo.\nConstruye una línea de transportadores del taladro al núcleo.
@@ -667,53 +667,53 @@ tutorial.daggerfactory = Construye una[accent] dagger mech factory[].\n\nEsto se
tutorial.router = Las fábricas necesitan recursos para funcionar.\nCrea un enrutador para separar recursos del transportador. tutorial.router = Las fábricas necesitan recursos para funcionar.\nCrea un enrutador para separar recursos del transportador.
tutorial.dagger = Conecta nodos de energía a la fábrica.\nUna vez las necesidades se cumplan, una unidad será creada.\n\nCrea taladros, generadores y transportadores según necesites. tutorial.dagger = Conecta nodos de energía a la fábrica.\nUna vez las necesidades se cumplan, una unidad será creada.\n\nCrea taladros, generadores y transportadores según necesites.
tutorial.battle = El[LIGHT_GRAY] enemy[] ha revelado su núcleo.\nDestrúyelo con tu nave y tus unidades de combate. tutorial.battle = El[LIGHT_GRAY] enemy[] ha revelado su núcleo.\nDestrúyelo con tu nave y tus unidades de combate.
block.copper-wall.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves. block.copper-wall.description = Un bloque defensivo barato.\nÚtil para defneder e núcleo y las torres en las primeras hordas.
block.copper-wall-large.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves.\nSpans multiple tiles. block.copper-wall-large.description = Un bloque defensivo barato.\nÚtil para defneder e núcleo y las torres en las primeras hordas.\nOcupa múltiples casillas.
block.dense-alloy-wall.description = A standard defensive block.\nAdequate protection from enemies. block.dense-alloy-wall.description = Un bloque de defensa estándar.\nProtección adecuada contra enemigos.
block.dense-alloy-wall-large.description = A standard defensive block.\nAdequate protection from enemies.\nSpans multiple tiles. block.dense-alloy-wall-large.description = Un bloque de defensa estándar.\nProtección adecuada contra enemigos.\nOcupa múltiples casillas.
block.thorium-wall.description = A strong defensive block.\nGood protection from enemies. block.thorium-wall.description = Un bloque defensivo fuerte.\nBuena protección contra enemigos.
block.thorium-wall-large.description = A strong defensive block.\nGood protection from enemies.\nSpans multiple tiles. block.thorium-wall-large.description = Un bloque defensivo fuerte.\nBuena protección contra enemigos.\nOcupa múltiples casillas.
block.phase-wall.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful. block.phase-wall.description = No es tan fuerte como un muro de torio pero rebota balas al enemigo si no son demasiado fuertes.
block.phase-wall-large.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful.\nSpans multiple tiles. block.phase-wall-large.description = No es tan fuerte como un muro de torio pero rebota balas al enemigo si no son demasiado fuertes.\nOcupa múltiples casillas.
block.surge-wall.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker. block.surge-wall.description = El bloque defensivo más fuerte.\nTiene una pequeña probabilidad de disparar rayos al atacante.
block.surge-wall-large.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker.\nSpans multiple tiles. block.surge-wall-large.description = El bloque defensivo más fuerte.\nTiene una pequeña probabilidad de disparar rayos al atacante.\nOcupa múltiplies casillas.
block.door.description = A small door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through. block.door.description = Una puerta pequeña que puede ser abierta y cerrada tocándola.\nSi está abirta, los enemigos pueden moverse y disparar a través de ella.\nOcupa múltiples casillas.
block.door-large.description = A large door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through.\nSpans multiple tiles. block.door-large.description = Una puerta grande que puede ser abierta y cerrada tocándola.\nSi está abirta, los enemigos pueden moverse y disparar a través de ella.\nOcupa múltiples casillas.
block.mend-projector.description = Periodically heals buildings in its vicinity. block.mend-projector.description = Regenera edificios cercanos periódcamente.
block.overdrive-projector.description = Increases the speed of nearby buildings like drills and conveyors. block.overdrive-projector.description = Aumenta la velocidad de edificios cercanos como taladros y transportadores.
block.force-projector.description = Creates a hexagonal force field around itself, protecting buildings and units inside from damage through bullets. block.force-projector.description = Crea un área de fuerza hexagonal alrededor de él, protegiendo edificios y unidades dentro de él del daño de las balas.
block.shock-mine.description = Damages enemies stepping on the mine. Nearly invisible to the enemy. block.shock-mine.description = Daña enemigos que pisan a mina. Casi invisible al enemigo.
block.duo.description = A small, cheap turret. block.duo.description = Una torre pequeña y barata.
block.arc.description = A small turret which shoots electricity in a random arc towards the enemy. block.arc.description = Una torre pequeña que disapra electricidad en un arco aleatorio al enemigo.
block.hail.description = A small artillery turret. block.hail.description = Una torre de artillería pequeña.
block.lancer.description = A medium-sized turret which shoots charged electricity beams. block.lancer.description = Una torre de tamaño mediano que dispara rayos cargados eléctricamente.
block.wave.description = A medium-sized rapid-fire turret which shoots liquid bubbles. block.wave.description = Una torre de tamaño mediano que dispara burbujas de líquido.
block.salvo.description = A medium-sized turret which fires shots in salvos. block.salvo.description = Una torre de tramaño mediano que dispara balas en salvos.
block.swarmer.description = A medium-sized turret which shoots burst missiles. block.swarmer.description = Una torre de tamaño mediano que dispara misiles en grupo.
block.ripple.description = A large artillery turret which fires several shots simultaneously. block.ripple.description = Una torre de artillería grande que dispara varios disparos simultáneamente.
block.cyclone.description = A large rapid fire turret. block.cyclone.description = Una torre de disparo rápido grande.
block.fuse.description = A large turret which shoots powerful short-range beams. block.fuse.description = Una torre grande que dispara rayos poderosos de corto alcance.
block.spectre.description = A large turret which shoots two powerful bullets at once. block.spectre.description = Una torre grande que dispara dos balas poderosas de una vez.
block.meltdown.description = A large turret which shoots powerful long-range beams. block.meltdown.description = Una torre grande que dispara rayos poderosos de largo alcance.
block.conveyor.description = Basic item transport block. Moved items forward and automatically deposits them into turrets or crafters. Rotatable. block.conveyor.description = Bloque de transporte básico. Mueve objetos hacia adelante y los deposita automáticamente en torres o fábricas. Rotable.
block.titanium-conveyor.description = Advanced item transport block. Moves items faster than standard conveyors. block.titanium-conveyor.description = Bloque de transporte avanzado. Mueve objetos más rápido que los transportadores estándar.
block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles. block.phase-conveyor.description = Bloque de transporte avanzado. Usa energía para transportar objetos a otro transportador de fase conectado por varias casillas.
block.junction.description = Acts as a bridge for two crossing conveyor belts. Useful in situations with two different conveyors carrying different materials to different locations. block.junction.description = Actúa como puente para dos transportadores que se cruzan. Útil en situaciones con dos diferentes transportadores transportando diferentes materiales a diferentes lugares.
block.mass-driver.description = Ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. block.mass-driver.description = El mejor bloque de transorte. Recoge varios objetos y los dispara a otro conductor de masa en un largo rango.
block.smelter.description = Burns coal for smelting copper and lead into dense alloy. block.smelter.description = Quema carbón para fundir cobre y plomo, produciendo así aleación densa.
block.arc-smelter.description = Smelts copper and lead into dense alloy by using an external power source. block.arc-smelter.description = Funde cobre y plomo en aleación densa usando una fuented de energía externa.
block.silicon-smelter.description = Reduces sand with highly pure coke in order to produce silicon. block.silicon-smelter.description = Reduces sand with highly pure coke in order to produce silicon.
block.plastanium-compressor.description = Produces plastanium from oil and titanium. block.plastanium-compressor.description = Produce plastanio con aceite y titanio.
block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand.
block.alloy-smelter.description = Produces surge alloy from titanium, lead, silicon and copper. block.alloy-smelter.description = Produce "surge alloy" con titanio, plomo, silicona y cobre.
block.pulverizer.description = Crushes stone into sand. Useful when there is a lack of natural sand. block.pulverizer.description = Despedaza la piedra en arena. Útil cuando no hay arena natural.
block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. block.pyratite-mixer.description = Mezcla carbón, plomo y arena en pirotita altamente inflamable.
block.blast-mixer.description = Uses oil for transforming pyratite into the less flammable but more explosive blast compound. block.blast-mixer.description = Usa aceite para transformar pirotita en un objeto menos inflamable pero más explosivo: compuesto explosivo.
block.cryofluidmixer.description = Combines water and titanium into cryofluid which is much more efficient for cooling. block.cryofluidmixer.description = Combina agua y titanio en líquido criogénico que es mucho más eficiente para enfriar.
block.solidifer.description = Cools lava to stone at a fast pace. block.solidifer.description = Enfría la lava a piedra a una gran velocidad.
block.melter.description = Heats up stone to very high temperatures to obtain lava. block.melter.description = Calienta piedra a temperaturas muy altas para obtener lava.
block.incinerator.description = Gets rid of any excess item or liquid. block.incinerator.description = Se deshace de cualquier líquido u objeto excesivo.
block.biomattercompressor.description = Compresses biomatter in order to retrieve oil. block.biomattercompressor.description = Comprime biomateria para extraer aceite.
block.separator.description = Expone piedra a la presión del agua para obtener diversos minerales contenidos en la piedra. block.separator.description = Expone piedra a la presión del agua para obtener diversos minerales contenidos en la piedra.
block.centrifuge.description = Más eficiente que un separador, pero es más caro de construir y requiere energía. block.centrifuge.description = Más eficiente que un separador, pero es más caro de construir y requiere energía.
block.power-node.description = Transmite energía a nodos conectados, conecta hasta cuatro fuentes de energía, edificios que usan energía o nodos. El nodo obtendrá o transmitirá energía de cualquier bloque adyacente. block.power-node.description = Transmite energía a nodos conectados, conecta hasta cuatro fuentes de energía, edificios que usan energía o nodos. El nodo obtendrá o transmitirá energía de cualquier bloque adyacente.
@@ -733,47 +733,48 @@ block.vault.description = Almacena una gran cantidad de objetos. Úsalo para cre
block.mechanical-drill.description = Un taladro barato. Cuando es colocado en casillas apropiadas, extrae objetos lentamente de forma indefinida. block.mechanical-drill.description = Un taladro barato. Cuando es colocado en casillas apropiadas, extrae objetos lentamente de forma indefinida.
block.pneumatic-drill.description = Un taladro mejorado que es más rápido y puede obtener minerales más duros usando la presión. block.pneumatic-drill.description = Un taladro mejorado que es más rápido y puede obtener minerales más duros usando la presión.
block.laser-drill.description = Permite obtener minerales incluso más rápido con la tecnología láser, pero requiere energía. Además, se puede obtener torio radioactivo con este taladro. block.laser-drill.description = Permite obtener minerales incluso más rápido con la tecnología láser, pero requiere energía. Además, se puede obtener torio radioactivo con este taladro.
block.blast-drill.description = The ultimate drill. Requires large amounts of power. block.blast-drill.description = El mejor taladro. Requiere grandes cantidades de energía.
block.water-extractor.description = Extrae agua de la tierra. Úsalo cuando no haya lagos cercanos. block.water-extractor.description = Extrae agua de la tierra. Úsalo cuando no haya lagos cercanos.
block.cultivator.description = Cultiva la tierra para obtener biomateria. block.cultivator.description = Cultiva la tierra para obtener biomateria.
block.oil-extractor.description = Usa grandes cantidades de energía para extraer aceite de la arena. Úsalo cuando no hay fuentes directas de aceite cerca. block.oil-extractor.description = Usa grandes cantidades de energía para extraer aceite de la arena. Úsalo cuando no hay fuentes directas de aceite cerca.
block.dart-ship-pad.description = Leave your current vessel and change into a basic fighter aircraft.\nUse the pad by double tapping while standing on it. block.dart-ship-pad.description = Deja tu nave actual y transfórmate en una unidad aérea básica.\nUsa el pad tocándolo dos veces mientras estás en él.
block.trident-ship-pad.description = Leave your current vessel and change into a reasonably well armored heavy bomber.\nUse the pad by double tapping while standing on it. block.trident-ship-pad.description = Deja tu nave actual y transfórmate en una unidad aérea bombardera pesada.\nUsa el pad tocándolo dos veces mientras estás en él.
block.javelin-ship-pad.description = Leave your current vessel and change into a strong and fast interceptor with lightning weapons.\nUse the pad by double tapping while standing on it. block.javelin-ship-pad.description = Deja tu nave actual y transfórmate en una unidad aérea fuerte y rápida interceptora con arma eléctrica.\nUsa el pad tocándolo dos veces mientras estás en él.
block.glaive-ship-pad.description = Leave your current vessel and change into a large, well-armored gunship.\nUse the pad by double tapping while standing on it. block.glaive-ship-pad.description = Deja tu nave actual y transfórmate en una unidad aérea grande y bien armada nave pistolera.\nUsa el pad tocándolo dos veces mientras estás en él.
block.tau-mech-pad.description = Leave your current vessel and change into a support mech which can heal friendly buildings and units.\nUse the pad by double tapping while standing on it. block.tau-mech-pad.description = Deja tu nave actual y transfórmate en un mecanoide de soporte que puede reparar construcciones y tropas aliadas.\nUsa el pad tocándolo dos veces mientras estás en él.
block.delta-mech-pad.description = Leave your current vessel and change into a fast, lightly-armored mech made for hit-and-run attacks.\nUse the pad by double tapping while standing on it. block.delta-mech-pad.description = Leave your current vessel and change into a fast, lightly-armored mech made for hit-and-run attacks.\nUse the pad by double tapping while standing on it.
block.omega-mech-pad.description = Leave your current vessel and change into a bulky and well-armored mech, made for front-line assaults.\nUse the pad by double tapping while standing on it. Deja tu nave actual y transfórmate en un mecanoide rápido, con armas ligeras hecho para ataques de ataque y retirada.\nUsa el pad tocándolo dos veces mientras estás en él.
block.omega-mech-pad.description = Deja tu nave actual y transfórmate en un mecanoide pesado y bien armado, hecho para asaltos en primera línea.\nUsa el pad tocándolo dos veces mientras estás en él.
block.spirit-factory.description = Produce drones ligeros que obtienen minerales y reparan bloques. block.spirit-factory.description = Produce drones ligeros que obtienen minerales y reparan bloques.
block.phantom-factory.description = Produces advanced drone units which are significantly more effective than a spirit drone. block.phantom-factory.description = Produce drones avanzados que son significativamente más eficientes que un dron espíritu.
block.wraith-factory.description = Produces fast, hit-and-run interceptor units. block.wraith-factory.description = Produce unidades aéreas rápidas e interceptoras.
block.ghoul-factory.description = Produces heavy carpet bombers. block.ghoul-factory.description = Produce unidadess bombarderas pesadas.
block.dagger-factory.description = Produce unidades terrestres básicas. block.dagger-factory.description = Produce unidades terrestres básicas.
block.titan-factory.description = Produces advanced, armored ground units. block.titan-factory.description = Produce unidades terrestres avanzadas.
block.fortress-factory.description = Produces heavy artillery ground units. block.fortress-factory.description = Produce unidades terrestres de artillería pesada.
block.revenant-factory.description = Produces heavy laser ground units. block.revenant-factory.description = Produce unidades terrestres láser pesadas.
block.repair-point.description = Repara la unidad dañada más cercana a su alrededor. block.repair-point.description = Repara la unidad dañada más cercana a su alrededor.
block.command-center.description = Allows changing friendly AI behavior. Currently, attack, retreat and patrol commands are supported. block.command-center.description = Permite cambiar el comportamiento de la IA aliada. Actualmente, atacar, retirarse y patrullar son los comandos soportados.
block.conduit.description = Basic liquid transport block. Works like a conveyor, but with liquids. Best used with extractors, pumps or other conduits. block.conduit.description = Bloque de transporte de líquidos básico. Funciona como un transportador, pero con líquidos. Usado con bombas, extractores u otros conductos.
block.pulse-conduit.description = Advanced liquid transport block. Transports liquids faster and stores more than standard conduits. block.pulse-conduit.description = Bloque de transporte de líquidos avanzado. Transporta líquidos más rápidamente y almacena más que los conductos estándar.
block.phase-conduit.description = Advanced liquid transport block. Uses power to teleport liquids to a connected phase conduit over several tiles. block.phase-conduit.description = Bloque de transporte de líquidos avanzado. Usa energía para transportar líquidos a otro conducto de fase conectado por varias casillas.
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-router.description = Acepta líquidos de una dirección y los deja en hasta 3 direcciones equitativamente. También puede amacenar cierta capacidad de líquido. Útil para dividir los líquidos de una fuente a varios objetivos.
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-tank.description = Almacena una gran cantidad de líquidos. Úsalo para crear almacenes cuando no hay una demanda constante de materiales o para asegurarse de enfriar bloques vitales.
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.liquid-junction.description = Actúa como un puente para dos condusctos que se cruzan. Útil en situaciones en las que hay dos conductos con líquidos diferentes a diferentes lugares.
block.bridge-conduit.description = Advanced liquid transport block. Allows transporting liquids over up to 3 tiles of any terrain or building. block.bridge-conduit.description = Bloque avanzado de transporte de líquidos. Permite transportar líquidos por encima hasta 3 casillas de cualquier terreno o construcción.
block.mechanical-pump.description = A cheap pump with slow output, but no power consumption. block.mechanical-pump.description = Una bomba barata con extracción lenta, pero sin uso de energía.
block.rotary-pump.description = An advanced pump which doubles up speed by using power. block.rotary-pump.description = Una bomba avanzada que duplica la velocidad usando energía.
block.thermal-pump.description = The ultimate pump. Three times as fast as a mechanical pump and the only pump which is able to retrieve lava. block.thermal-pump.description = La mejor bomba. Tres veces más rápido que la bomba mecánica, y la única bomba que puede extraer 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.router.description = Acepta objetos de una dirección y deja objetos equitativamente en hasta 3 direcciones diferentes. Útil para dividir los materiales de una fuente de recursos a múltiples objetivos.
block.distributor.description = An advanced router which splits items to up to 7 other directions equally. block.distributor.description = Un enrutador avanzado que distribuye objetos equitativamente en hasta otras 7 direcciones.
block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building. 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 = When given enough power, rebuilds your ship into the[accent] Alpha[] mech. block.alpha-mech-pad.description = Cuando se le da suficiente energía, reconstruye tu nave en el mecanoide[accent] Alpha[].
block.itemsource.description = Infinitely outputs items. Sandbox only. block.itemsource.description = Da objetos infinitos. Solo en sandbox.
block.liquidsource.description = Infinitely outputs liquids. Sandbox only. block.liquidsource.description = Da líquido infinito. Solo en sandbox.
block.itemvoid.description = Destroys any items which go into it without using power. Sandbox only. block.itemvoid.description = Destruye cuanquier objeto que va a él sin necesitar energía. Solo en sandbox.
block.powerinfinite.description = Infinitely outputs power. Sandbox only. block.powerinfinite.description = Da energía infinita. Solo en sandbox.
block.powervoid.description = Voids all power inputted into it. Sandbox only. block.powervoid.description = Elimina toda la energía que se le da. Solo en sandbox.
liquid.water.description = Commonly used for cooling machines and waste processing. liquid.water.description = Usado comúnmente para enfriar máquinas y para procesar residuos.
liquid.lava.description = Can be transformed into[LIGHT_GRAY] stone[], used for generating power or used as ammo for certain turrets. 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 = Can be burnt, exploded or used as a coolant. liquid.oil.description = Puede ser quemado, explotado o como un enfriador.
liquid.cryofluid.description = The most efficient liquid for cooling things down. liquid.cryofluid.description = El líquido más eficiente pra enfriar las cosas.
+1 -1
View File
@@ -50,7 +50,7 @@ text.mission.main = Main Mission:[LIGHT_GRAY] {0}
text.mission.info = Mission Info text.mission.info = Mission Info
text.mission.complete = Mission complete! text.mission.complete = Mission complete!
text.mission.complete.body = Sector {0},{1} has been conquered. text.mission.complete.body = Sector {0},{1} has been conquered.
text.mission.wave = Survive [accent]{0}[] waves. 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.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies
text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy
text.mission.wave.menu = Survive[accent] {0} []waves text.mission.wave.menu = Survive[accent] {0} []waves
@@ -50,7 +50,7 @@ text.mission.main = Main Mission:[LIGHT_GRAY] {0}
text.mission.info = Mission Info text.mission.info = Mission Info
text.mission.complete = Missione completata! text.mission.complete = Missione completata!
text.mission.complete.body = Il settore {0},{1} è stato conquistato. text.mission.complete.body = Il settore {0},{1} è stato conquistato.
text.mission.wave = Sopravvivi a [accent]{0}[] onda/e. 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.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies
text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy
text.mission.wave.menu = Survive[accent] {0} []waves text.mission.wave.menu = Survive[accent] {0} []waves
+130 -128
View File
@@ -13,22 +13,22 @@ text.editor.web = HTML5 버전은 에디터 기능을 지원하지 않습니다!
text.web.unsupported = HTML5 버전은 이 기능을 지원하지 않습니다! 게임을 다운로드 한 뒤에 사용 해 주세요. text.web.unsupported = HTML5 버전은 이 기능을 지원하지 않습니다! 게임을 다운로드 한 뒤에 사용 해 주세요.
text.gameover = 코어가 터졌습니다. 게임 오버! text.gameover = 코어가 터졌습니다. 게임 오버!
text.gameover.pvp = [accent]{0}[] 팀이 승리했습니다! text.gameover.pvp = [accent]{0}[] 팀이 승리했습니다!
text.sector.gameover = 이 구역을 공략하는데 실패했습니다. 다시 배치하시겠습니까? text.sector.gameover = 이 구역을 공략하는데 실패했습니다. 포기 하시겠습니까?
text.sector.retry = 다시할꺼임 text.sector.retry = 아니오
text.highscore = [YELLOW]최고점수 달성! text.highscore = [YELLOW]최고점수 달성!
text.wave.lasted = [accent]{0}[] 까지 버티셨습니다. text.wave.lasted = [accent]{0}[] 까지 버티셨습니다.
text.level.highscore = 최고 점수 : [accent]{0} text.level.highscore = 최고 점수 : [accent]{0}
text.level.delete.title = 삭제 확인 text.level.delete.title = 삭제 확인
text.map.delete = 정말로 "[accent]{0}[]" 맵을 삭제하시겠습니까? text.map.delete = 정말로 "[orange]{0}[]" 맵을 삭제하시겠습니까?
text.level.select = 맵 선택 text.level.select = 맵 선택
text.level.mode = 게임모드 : text.level.mode = 게임모드 :
text.construction.desktop = PC 에서의 조작 방법이 변경되었습니다.\n블록 선택을 해제하거나 건설을 중지하려면 [accent]스페이스 바[]를 누르세요. text.construction.desktop = PC 에서의 조작 방법이 변경되었습니다.\n블록 선택을 해제하거나 건설을 중지하려면 [accent]스페이스 바[]를 누르세요.
text.construction.title = 블록 배치 안내서 text.construction.title = 블록 배치 안내서
text.construction = [accent]블록 배치 모드[]를 선택하셨습니다.\n\n블록을 설치하고 싶으면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 배치 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요. \n- [accent]블록을 넓게 배치[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록을 한줄로 배치[]하고 싶다면 배치하고 싶은 시작 영역을 한번 탭 하고 길게 누르면서 드래그 하면 됩니다. \n- [accent]블록 배치 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. text.construction = [accent]블록 배치 모드[]를 선택하셨습니다.\n\n블록을 설치하고 싶으면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 배치 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요. \n- [accent]블록을 넓게 배치[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록을 한줄로 배치[]하고 싶다면 배치하고 싶은 시작 영역을 한번 탭 하고 길게 누르면서 드래그 하면 됩니다. \n- [accent]블록 배치 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다.
text.deconstruction.title = 블록 삭제 안내서 text.deconstruction.title = 블록 삭제 안내서
text.deconstruction = [accent]블록 삭제 모드[]를 선택하셨습니다\n\n블록을 삭제하고 싶다면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 파괴 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요\n- [accent]블록을 넓은 범위로 삭제[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록 삭제 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. text.deconstruction = [accent]블록 삭제 모드[]를 선택하셨습니다\n\n블록을 삭제하고 싶다면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 파괴 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요\n- [accent]블록을 넓은 범위로 삭제[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록 삭제 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다.
text.showagain = 다음 세션에서 이 메세지를 표시하지 않습니다 text.showagain = 다음 세션에서 이 메세지를 표시하지 않습니다
text.coreattack = < 코어가 공격받고 있습니다 ! > text.coreattack = < 코어가 공격받고 있습니다! >
text.unlocks = 아이템들 text.unlocks = 아이템들
text.savegame = 게임 저장 text.savegame = 게임 저장
text.loadgame = 게임 불러오기 text.loadgame = 게임 불러오기
@@ -50,20 +50,20 @@ text.mission.main = 주요 목표 : [LIGHT_GRAY]{0}
text.mission.info = 미션 정보 text.mission.info = 미션 정보
text.mission.complete = 미션 성공! text.mission.complete = 미션 성공!
text.mission.complete.body = 구역 {0},{1} 클리어. text.mission.complete.body = 구역 {0},{1} 클리어.
text.mission.wave = [accent]{0}[]단계가 될때까지 생존하세요. text.mission.wave = [accent]{0}/{1}[] 단계동안 생존하세요.남은 시간 {2}\n
text.mission.wave.enemies = [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.enemy = [accent] {0}/{1} []단계 생존하세요.\n{2}마리 남음
text.mission.wave.menu = [accent]{0}[] 단계 text.mission.wave.menu = [accent]{0}[] 단계
text.mission.battle = 본부를 파괴하세요. text.mission.battle = 코어를 파괴하세요.
text.mission.resource.menu = {0} {1}개 수집 text.mission.resource.menu = {0} {1}개 수집
text.mission.resource = {0} 자원을 수집하세요 :\n[accent]{1}/{2}[] text.mission.resource = {0} 자원을 수집하세요 :\n[accent]{1}/{2}[]
text.mission.block = 이것을 만드세요 :\n{0} text.mission.block = {0} 를 만드세요
text.mission.unit = 유닛을 만드세요 :\n{0} text.mission.unit = {0} 유닛을 만드세요
text.mission.command = 유닛에게 명령을 보내세요 :\n{0} text.mission.command = 유닛에게 {0} 명령을 보내세요
text.mission.linknode = 전력 노드를 연결하세요. text.mission.linknode = 전력 노드를 연결하세요.
text.mission.display = [accent]미션 : \n[LIGHT_GRAY]{0} text.mission.display = [accent]미션 :\n[LIGHT_GRAY]{0}
text.mission.mech = 이 기체로 바꾸세요 :\n[accent]{0} text.mission.mech = [accent]{0}[] 기체로 바꾸세요
text.mission.create = 이 자원을 만드세요 :\n[accent]{0} text.mission.create = [accent]{0}[] 자원을 만드세요
text.none = <없음> text.none = <없음>
text.close = 닫기 text.close = 닫기
text.quit = 나가기 text.quit = 나가기
@@ -91,12 +91,12 @@ text.server.kicked.nameInUse = 이 닉네임이 이미 서버에서 사용중입
text.server.kicked.nameEmpty = 닉네임에는 반드시 영어 또는 숫자가 있어야 합니다. text.server.kicked.nameEmpty = 닉네임에는 반드시 영어 또는 숫자가 있어야 합니다.
text.server.kicked.idInUse = 이미 서버에 접속중입니다! 다중 계정은 허용되지 않습니다. text.server.kicked.idInUse = 이미 서버에 접속중입니다! 다중 계정은 허용되지 않습니다.
text.server.kicked.customClient = 이 서버는 직접 빌드한 버전을 지원하지 않습니다. 공식 버전을 사용하세요. text.server.kicked.customClient = 이 서버는 직접 빌드한 버전을 지원하지 않습니다. 공식 버전을 사용하세요.
text.host.info = [accent]호스트[] 버튼은 현재 네트워크의 [scarlet]6567[] 과 [scarlet]6568[] 포트를 사용합니다.\n[LIGHY_GRAY]같은 Wi-Fi 또는 로컬 네트워크[] 에서 서버 목록을 볼 수 있습니다.\n\n만약 플레이어들이 이 IP를 통해 어디에서나 연결할 수 있게 하고 싶다면, 공유기 설정에서 [accent]포트 포워딩[]을 해야 합니다.\n\n[LIGHT_GRAY]참고 : LAN 게임 연결에 문제가 있는 사람이 있다면, 방화벽 설정에서 Mindustry 가 로컬 네트워크에 액세스하도록 허용했는지 확인 해 주세요. 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.join.info = 여기서 [accent]서버 IP[]를 입력하여 다른 서버에 접속할 수 있습니다.\n또는 [accent]로컬 네트워크(LAN)[] 서버를 검색하여 접속할 수 있습니다.\nLAN 및 WAN 멀티 플레이어 모두 지원됩니다.\n\n[LIGHT_GRAY]참고:여기에서는 자동으로 글로벌 서버를 추가하지 않습니다. IP로 다른 사람의 서버에 접속할려면 서버장에게 IP를 요청해야 합니다.
text.hostserver = 서버 열기 text.hostserver = 서버 열기
text.hostserver.mobile = 게임\n호스트 text.hostserver.mobile = 서버\n열기
text.host = 호스트 text.host = 서버 열기
text.hosting = [accent]서버 여는중.. text.hosting = [accent]서버 여는중...
text.hosts.refresh = 새로고침 text.hosts.refresh = 새로고침
text.hosts.discovering = LAN 게임 찾기 text.hosts.discovering = LAN 게임 찾기
text.server.refreshing = 서버 목록 새로고치는중... text.server.refreshing = 서버 목록 새로고치는중...
@@ -129,7 +129,7 @@ text.server.custombuild = [yellow]커스텀 서버
text.confirmban = 이 플레이어를 차단하시겠습니까? text.confirmban = 이 플레이어를 차단하시겠습니까?
text.confirmkick = 정말로 이 플레이어를 추방시키겠습니까? text.confirmkick = 정말로 이 플레이어를 추방시키겠습니까?
text.confirmunban = 이 플레이어를 차단해제 하시겠습니까? text.confirmunban = 이 플레이어를 차단해제 하시겠습니까?
text.confirmadmin = 이 플레이어를 자로 만들겠습니까? text.confirmadmin = 이 플레이어를 관리자로 만들겠습니까?
text.confirmunadmin = 이 플레이어를 일반 유저로 만들겠습니까? text.confirmunadmin = 이 플레이어를 일반 유저로 만들겠습니까?
text.joingame.title = 게임 참가 text.joingame.title = 게임 참가
text.joingame.ip = IP : text.joingame.ip = IP :
@@ -140,7 +140,7 @@ text.connecting.data = [accent]맵 데이터 다운로드중...
text.server.port = 포트 : text.server.port = 포트 :
text.server.addressinuse = 이 주소는 이미 사용중입니다! text.server.addressinuse = 이 주소는 이미 사용중입니다!
text.server.invalidport = 포트 번호가 잘못되었습니다. text.server.invalidport = 포트 번호가 잘못되었습니다.
text.server.error = [crimson]{0}[accent]서버를 여는데 오류가 발생했습니다.[] text.server.error = [crimson]{0}[orange]서버를 여는데 오류가 발생했습니다.[]
text.save.old = 이 저장파일은 이전 버전의 게임용이며, 지금은 사용할 수 없습니다. \n\n[LIGHT_GRAY]4.0 정식때 이전 게임버전에서 만든 저장파일과 호환됩니다. text.save.old = 이 저장파일은 이전 버전의 게임용이며, 지금은 사용할 수 없습니다. \n\n[LIGHT_GRAY]4.0 정식때 이전 게임버전에서 만든 저장파일과 호환됩니다.
text.save.new = 새로 저장 text.save.new = 새로 저장
text.save.overwrite = 이 저장 슬롯을 덮어씌우겠습니까? text.save.overwrite = 이 저장 슬롯을 덮어씌우겠습니까?
@@ -151,17 +151,17 @@ text.savefail = 게임을 저장하지 못했습니다!
text.save.delete.confirm = 이 저장파일을 삭제 하시겠습니까? text.save.delete.confirm = 이 저장파일을 삭제 하시겠습니까?
text.save.delete = 삭제 text.save.delete = 삭제
text.save.export = 저장파일 내보내기 text.save.export = 저장파일 내보내기
text.save.import.invalid = [accent]파일이 잘못되었습니다! text.save.import.invalid = [orange]파일이 잘못되었습니다!
text.save.import.fail = [crimson]저장파일을 불러오지 못함 : [accent]{0} text.save.import.fail = [crimson]저장파일을 불러오지 못함 : [orange]{0}
text.save.export.fail = [crimson]저장파일을 내보내지 못함 : [accent]{0} text.save.export.fail = [crimson]저장파일을 내보내지 못함 : [orange]{0}
text.save.import = 저장파일 불러오기 text.save.import = 저장파일 불러오기
text.save.newslot = 저장 파일이름 : text.save.newslot = 저장 파일이름 :
text.save.rename = 이름 변경 text.save.rename = 이름 변경
text.save.rename.text = 새 이름 : text.save.rename.text = 새 이름 :
text.selectslot = 저장슬롯을 선택하십시오. text.selectslot = 저장슬롯을 선택하십시오.
text.slot = [accent]{0}번째 슬롯 text.slot = [accent]{0}번째 슬롯
text.save.corrupted = [accent]세이브 파일이 손상되었거나 잘못된 파일입니다! 만약 게임을 업데이트 했다면 이것은 아마 저장 형식 변경일 것이고, 이것은 버그가 [scarlet]아닙니다[]. text.save.corrupted = [orange]세이브 파일이 손상되었거나 잘못된 파일입니다! 만약 게임을 업데이트 했다면 이것은 아마 저장 형식 변경일 것이고, 이것은 버그가 [scarlet]아닙니다[].
text.sector.corrupted = [accent]저장 파일에서 구역을 발견했으나 불러오지 못했습니다.\n새로 생성되었습니다. text.sector.corrupted = [orange]저장 파일에서 구역을 발견했으나 불러오지 못했습니다.\n새로 생성되었습니다.
text.empty = <비어있음> text.empty = <비어있음>
text.on = 켜기 text.on = 켜기
text.off = 끄기 text.off = 끄기
@@ -182,14 +182,14 @@ text.back = 뒤로가기
text.quit.confirm = 정말로 종료하시겠습니까? text.quit.confirm = 정말로 종료하시겠습니까?
text.changelog.title = 변경사항 text.changelog.title = 변경사항
text.changelog.loading = 변경사항 가져오는중... text.changelog.loading = 변경사항 가져오는중...
text.changelog.error.android = [accent]게임 변경사항은 가끔 Android 4.4 이하에서 작동하지 않습니다.이것은 내부 Android 버그 때문입니다. text.changelog.error.android = [orange]게임 변경사항은 가끔 Android 4.4 이하에서 작동하지 않습니다. 이것은 내부 Android 버그 때문입니다.
text.changelog.error.ios = [accent]현재 iOS에서는 변경 사항을 지원하지 않습니다. text.changelog.error.ios = [orange]현재 iOS에서는 변경 사항을 지원하지 않습니다.
text.changelog.error = [scarlet]게임 변경사항을 가져오는 중 오류가 발생했습니다![]\n인터넷 연결을 확인하십시오. text.changelog.error = [scarlet]게임 변경사항을 가져오는 중 오류가 발생했습니다![]\n인터넷 연결을 확인하십시오.
text.changelog.current = [accent][[현재 버전] text.changelog.current = [orange][[현재 버전]
text.changelog.latest = [accent][[최신 버전] text.changelog.latest = [orange][[최신 버전]
text.loading = [accent]불러오는중... text.loading = [accent]불러오는중...
text.saving = [accent]저장중... text.saving = [accent]저장중...
text.wave = [accent]{0}단계 text.wave = [orange]{0}단계
text.wave.waiting = 다음 단계 시작까지 {0}초 text.wave.waiting = 다음 단계 시작까지 {0}초
text.waiting = [LIGHT_GRAY]대기중... text.waiting = [LIGHT_GRAY]대기중...
text.waiting.players = 다른 플레이어를 기다리는 중.. text.waiting.players = 다른 플레이어를 기다리는 중..
@@ -216,14 +216,14 @@ text.editor.description = 설명 :
text.editor.name = 이름 : text.editor.name = 이름 :
text.editor.teams = text.editor.teams =
text.editor.elevation = 지형 높이 text.editor.elevation = 지형 높이
text.editor.errorimageload = [accent]{0}[] 파일을 불러오는데 오류가 발생했습니다. text.editor.errorimageload = [orange]{0}[] 파일을 불러오는데 오류가 발생했습니다.
text.editor.errorimagesave = [accent]{0}[] 파일 저장중 오류가 발생했습니다. text.editor.errorimagesave = [orange]{0}[] 파일 저장중 오류가 발생했습니다.
text.editor.generate = 생성 text.editor.generate = 생성
text.editor.resize = 맵 크기조정 text.editor.resize = 맵 크기조정
text.editor.loadmap = 맵 불러오기 text.editor.loadmap = 맵 불러오기
text.editor.savemap = 맵 저장 text.editor.savemap = 맵 저장
text.editor.saved = 저장됨! text.editor.saved = 저장됨!
text.editor.save.noname = 지도에 이름이 없습니다! '맵 정보' 메뉴에서 설정하세요. text.editor.save.noname = 지도에 이름이 없습니다! 메뉴 -> '맵 정보' 에서 설정하세요.
text.editor.save.overwrite = 이 맵의 이름은 기존에 있던 맵을 덮어씁니다! '맵 정보' 메뉴에서 다른 이름을 선택하세요. text.editor.save.overwrite = 이 맵의 이름은 기존에 있던 맵을 덮어씁니다! '맵 정보' 메뉴에서 다른 이름을 선택하세요.
text.editor.import.exists = [scarlet]맵을 불러올 수 없음 : [] 기존에 있던 '{0}' 맵이 이미 존재합니다! text.editor.import.exists = [scarlet]맵을 불러올 수 없음 : [] 기존에 있던 '{0}' 맵이 이미 존재합니다!
text.editor.import = 가져오기 text.editor.import = 가져오기
@@ -261,7 +261,7 @@ text.tutorial = 게임 방법
text.editor = 편집기 text.editor = 편집기
text.mapeditor = 맵 편집기 text.mapeditor = 맵 편집기
text.donate = 기부 text.donate = 기부
text.connectfail = [crimson]{0}[accent] 서버에 연결하지 못했습니다.[] text.connectfail = [crimson]{0}[orange] 서버에 연결하지 못했습니다.[]
text.error.unreachable = 서버에 연결하지 못했습니다. text.error.unreachable = 서버에 연결하지 못했습니다.
text.error.invalidaddress = 잘못된 주소입니다. text.error.invalidaddress = 잘못된 주소입니다.
text.error.timedout = 시간 초과!\n서버에 포트 포워딩이 설정되어 있고 주소가 올바른지 확인하십시오. text.error.timedout = 시간 초과!\n서버에 포트 포워딩이 설정되어 있고 주소가 올바른지 확인하십시오.
@@ -285,50 +285,50 @@ text.settings.clearall = 모두 초기화
text.paused = 일시 정지 text.paused = 일시 정지
text.yes = text.yes =
text.no = 아니오 text.no = 아니오
text.info.title = 정보 text.info.title = [accent]정보
text.error.title = [crimson]오류가 발생했습니다. text.error.title = [crimson]오류가 발생했습니다.
text.error.crashtitle = 오류가 발생했습니다. text.error.crashtitle = 오류가 발생했습니다.
text.blocks.blockinfo = 블록 정보 text.blocks.blockinfo = 블록 정보
text.blocks.powercapacity = 최대 전력 용량 text.blocks.powercapacity = 최대 전력 용량
text.blocks.powershot = 1발당 전력 소모량 text.blocks.powershot = 1발당 전력 소모량
text.blocks.targetsair = 공중공격 가능 text.blocks.targetsair = 공중공격 가능
text.blocks.itemspeed = 유닛 이동 속도 text.blocks.itemspeed = 유닛 이동 속도
text.blocks.shootrange = 사거리 text.blocks.shootrange = 사거리
text.blocks.size = 블록 크기 text.blocks.size = 블록 크기
text.blocks.liquidcapacity = 최대 액체 용량 text.blocks.liquidcapacity = 최대 액체 용량
text.blocks.maxitemssecond = 최대 아이템 보관량 text.blocks.maxitemssecond = 최대 아이템 보관량
text.blocks.powerrange = 전력 범위 text.blocks.powerrange = 전력 범위
text.blocks.poweruse = 전력 사용 text.blocks.poweruse = 전력 사용
text.blocks.powerdamage = 전력/데미지 text.blocks.powerdamage = 전력/데미지
text.blocks.inputitemcapacity = 입력 아이템 용량 text.blocks.inputitemcapacity = 입력 아이템 용량
text.blocks.outputitemcapacity = 출력 아이템 용량 text.blocks.outputitemcapacity = 출력 아이템 용량
text.blocks.itemcapacity = 저장 용량 text.blocks.itemcapacity = 저장 용량
text.blocks.basepowergeneration = 기지 전력 생성기 text.blocks.basepowergeneration = 기지 전력 생성기
text.blocks.powertransferspeed = 전력 전송량 text.blocks.powertransferspeed = 전력 전송량
text.blocks.craftspeed = 생산 속도 text.blocks.craftspeed = 생산 속도
text.blocks.inputliquid = 사용되는 액체 text.blocks.inputliquid = 사용되는 액체
text.blocks.inputliquidaux = 보조 액체 text.blocks.inputliquidaux = 보조 액체
text.blocks.inputitem = 사용되는 아이템 text.blocks.inputitem = 사용되는 아이템
text.blocks.inputitems = 사용되는 아이템들 text.blocks.inputitems = 사용되는 아이템들
text.blocks.outputitem = 출력 아이템 text.blocks.outputitem = 출력 아이템
text.blocks.drilltier = 드릴 text.blocks.drilltier = 드릴
text.blocks.drillspeed = 기본 드릴 속도 text.blocks.drillspeed = 기본 드릴 속도
text.blocks.liquidoutput = 액체 출력 text.blocks.liquidoutput = 액체 출력
text.blocks.liquidoutputspeed = 액체 출력속도 text.blocks.liquidoutputspeed = 액체 출력속도
text.blocks.liquiduse = 액체 사용량 text.blocks.liquiduse = 액체 사용량
text.blocks.coolant = 냉각제 text.blocks.coolant = 냉각제
text.blocks.coolantuse = 냉각수 사용 text.blocks.coolantuse = 냉각수 사용
text.blocks.inputliquidfuel = 연료 액 text.blocks.inputliquidfuel = 연료 액
text.blocks.liquidfueluse = 액체 연료 사용 text.blocks.liquidfueluse = 액체 연료 사용
text.blocks.explosive = 게 터지면 펑 터지면 주변 블록에게 피해를 입힙니다! text.blocks.explosive = 블록이 터지면 주변 블록과 같이 자폭을 합니다!!
text.blocks.health = 체력 text.blocks.health = 체력
text.blocks.inaccuracy = 오차각 text.blocks.inaccuracy = 오차각
text.blocks.shots = 발포 횟수 text.blocks.shots = 발포 횟수
text.blocks.reload = 재장전 text.blocks.reload = 재장전
text.blocks.inputfuel = 연료 text.blocks.inputfuel = 연료
text.blocks.fuelburntime = 연료 연소 시간 text.blocks.fuelburntime = 연료 연소 시간
text.blocks.inputcapacity = 입력 용량 text.blocks.inputcapacity = 입력 용량
text.blocks.outputcapacity = 출력 용량 text.blocks.outputcapacity = 출력 용량
text.unit.blocks = 블록 text.unit.blocks = 블록
text.unit.powersecond = 전력/초 text.unit.powersecond = 전력/초
text.unit.liquidsecond = 액체/초 text.unit.liquidsecond = 액체/초
@@ -370,6 +370,7 @@ setting.musicvol.name = 음악 크기
setting.mutemusic.name = 음소거 setting.mutemusic.name = 음소거
setting.sfxvol.name = 효과음 크기 setting.sfxvol.name = 효과음 크기
setting.mutesound.name = 소리 끄기 setting.mutesound.name = 소리 끄기
setting.crashreport.name = 오류 보고서 보내기
text.keybind.title = 키 바인딩 text.keybind.title = 키 바인딩
category.general.name = 일반 category.general.name = 일반
category.view.name = 보기 category.view.name = 보기
@@ -417,11 +418,11 @@ content.unit.name = 유닛
content.recipe.name = 블록 content.recipe.name = 블록
content.mech.name = 기체 content.mech.name = 기체
item.stone.name = item.stone.name =
item.stone.description = 주로 용암을 사용하여 얻을 수 있니다. item.stone.description = 주로 용암을 사용하여 얻을 수 있는 자원입니다.
item.copper.name = 구리 item.copper.name = 구리
item.copper.description = 모든 유형의 블록에서 광범위하게 사용되는 자원입니다. item.copper.description = 모든 유형의 블록에서 광범위하게 사용되는 자원입니다.
item.lead.name = item.lead.name =
item.lead.description = 쉽게 구할 수 있는 자원.\n전자 및 액체 수송 블록에서 광범위하게 사용되는 자원입니다. item.lead.description = 쉽게 구할 수 있으며, 전자 및 액체 수송 블록에서 광범위하게 사용되는 자원입니다.
item.coal.name = 석탄 item.coal.name = 석탄
item.coal.description = 쉽게 구할 수 있으며, 주로 제련소 등에서 연료로 사용됩니다. item.coal.description = 쉽게 구할 수 있으며, 주로 제련소 등에서 연료로 사용됩니다.
item.dense-alloy.name = 합금 item.dense-alloy.name = 합금
@@ -439,9 +440,9 @@ item.phase-fabric.description = 최첨단 전자 제품과 자기수리 기술
item.surge-alloy.name = 설금 item.surge-alloy.name = 설금
item.surge-alloy.description = 주로 건물의 재료로 사용되는 자원입니다 item.surge-alloy.description = 주로 건물의 재료로 사용되는 자원입니다
item.biomatter.name = 바이오메터 item.biomatter.name = 바이오메터
item.biomatter.description = 이것은 유기농 덤불입니다!\n석유로 전환하거나 연료로 사용됩니다. item.biomatter.description = 이것은 유기농 덤불입니다!\n압축기에 넣어 석유로 바꿀 수 있습니다.
item.sand.name = 모래 item.sand.name = 모래
item.sand.description = 합금이나 플스 등에서 제련시 광범위하게 사용되는 일반적인 재료입니다. item.sand.description = 합금이나 플스 등에서 제련시 광범위하게 사용되는 일반적인 재료입니다.
item.blast-compound.name = 화합물 item.blast-compound.name = 화합물
item.blast-compound.description = 포탑 및 건설의 재료로 사용되는 휘발성 화합물.\n연료로도 사용할 수 있지만, 별로 추천하지는 않습니다. item.blast-compound.description = 포탑 및 건설의 재료로 사용되는 휘발성 화합물.\n연료로도 사용할 수 있지만, 별로 추천하지는 않습니다.
item.pyratite.name = 피라테 item.pyratite.name = 피라테
@@ -482,7 +483,7 @@ mech.glaive-ship.weapon = 방화총
text.item.explosiveness = [LIGHT_GRAY]폭발력 : {0} text.item.explosiveness = [LIGHT_GRAY]폭발력 : {0}
text.item.flammability = [LIGHT_GRAY]인화성 : {0} text.item.flammability = [LIGHT_GRAY]인화성 : {0}
text.item.radioactivity = [LIGHT_GRAY]방사능 : {0} text.item.radioactivity = [LIGHT_GRAY]방사능 : {0}
text.item.fluxiness = [LIGHT_GRAY]플스 파워 : {0} text.item.fluxiness = [LIGHT_GRAY]플스 파워 : {0}
text.unit.health = [LIGHT_GRAY]체력 : {0} text.unit.health = [LIGHT_GRAY]체력 : {0}
text.unit.speed = [LIGHT_GRAY]속도 : {0} text.unit.speed = [LIGHT_GRAY]속도 : {0}
text.mech.weapon = [LIGHT_GRAY]무기 : {0} text.mech.weapon = [LIGHT_GRAY]무기 : {0}
@@ -496,7 +497,7 @@ text.liquid.viscosity = [LIGHT_GRAY]점도 : {0}
text.liquid.temperature = [LIGHT_GRAY]온도 : {0} text.liquid.temperature = [LIGHT_GRAY]온도 : {0}
block.spawn.name = 적 스폰지점 block.spawn.name = 적 스폰지점
block.core.name = 코어 block.core.name = 코어
block.metalfloor.name = 메탈 바닥 block.metalfloor.name = 철판
block.deepwater.name = 깊은물 block.deepwater.name = 깊은물
block.water.name = block.water.name =
block.lava.name = 용암 block.lava.name = 용암
@@ -517,7 +518,7 @@ block.copper-wall-large.name = 큰 구리벽
block.dense-alloy-wall.name = 합금 벽 block.dense-alloy-wall.name = 합금 벽
block.dense-alloy-wall-large.name = 큰 합금 벽 block.dense-alloy-wall-large.name = 큰 합금 벽
block.phase-wall.name = 메타벽 block.phase-wall.name = 메타벽
block.phase-wall-large.name = 메타벽 block.phase-wall-large.name = 메타벽
block.thorium-wall.name = 토륨벽 block.thorium-wall.name = 토륨벽
block.thorium-wall-large.name = 대형 토륨벽 block.thorium-wall-large.name = 대형 토륨벽
block.door.name = block.door.name =
@@ -534,7 +535,7 @@ block.distributor.name = 대형 분배기
block.sorter.name = 필터 block.sorter.name = 필터
block.sorter.description = 아이템을 넣어서 필터에 설정된 아이템일 경우 바로 앞으로 통과하며, 그렇지 않을 경우 옆으로 통과합니다. block.sorter.description = 아이템을 넣어서 필터에 설정된 아이템일 경우 바로 앞으로 통과하며, 그렇지 않을 경우 옆으로 통과합니다.
block.overflow-gate.name = 오버플로 게이트 block.overflow-gate.name = 오버플로 게이트
block.overflow-gate.description = 정면 경로가 차단된 경우 왼쪽과 오른쪽으로 출력하는 복합 분배기입니다. block.overflow-gate.description = 정면으로 가는 자원이 막히면 옆으로 출력하고, 그렇지 않으면 계속 정면으로 출력합니다.
block.smelter.name = 제련소 block.smelter.name = 제련소
block.arc-smelter.name = 대형 제련소 block.arc-smelter.name = 대형 제련소
block.silicon-smelter.name = 실리콘 제련소 block.silicon-smelter.name = 실리콘 제련소
@@ -623,7 +624,6 @@ block.rtg-generator.name = 토륨 발전소
block.spectre.name = 스펙터 block.spectre.name = 스펙터
block.meltdown.name = 멜트다운 block.meltdown.name = 멜트다운
block.container.name = 컨테이너 block.container.name = 컨테이너
block.core.description = 게임에서 가장 중요한 건물.\n파괴되면 게임이 끝납니다.
team.blue.name = 블루팀 team.blue.name = 블루팀
team.red.name = 레드팀 team.red.name = 레드팀
team.orange.name = 오렌지팀 team.orange.name = 오렌지팀
@@ -637,6 +637,7 @@ unit.phantom.name = 팬텀 드론
unit.phantom.description = 첨단 드론 유닛. 광석을 자동으로 채광하며, 아이템을 수집하고 블록을 수리합니다. 일반 드론보다 훨씬 효과적입니다. unit.phantom.description = 첨단 드론 유닛. 광석을 자동으로 채광하며, 아이템을 수집하고 블록을 수리합니다. 일반 드론보다 훨씬 효과적입니다.
unit.dagger.name = 귀여운 디거 unit.dagger.name = 귀여운 디거
unit.dagger.description = 밈의 대상으로 지정되어 이름이 바뀐 기본 지상 유닛입니다. unit.dagger.description = 밈의 대상으로 지정되어 이름이 바뀐 기본 지상 유닛입니다.
## unit.dagger.description = 기본 지상 유닛입니다. 스웜과 같이 쓰면 유용합니다.
unit.titan.name = 타이탄 unit.titan.name = 타이탄
unit.titan.description = 고급 지상 유닛입니다. 합금을 탄약으로 사용하며 지상과 공중 둘다 공격할 수 있습니다. unit.titan.description = 고급 지상 유닛입니다. 합금을 탄약으로 사용하며 지상과 공중 둘다 공격할 수 있습니다.
unit.ghoul.name = 구울 폭격기 unit.ghoul.name = 구울 폭격기
@@ -668,6 +669,7 @@ tutorial.daggerfactory = 이[accent] 귀여운 디거 기체 공장[]은\n\n공
tutorial.router = 공장을 작동시키기 위해 자원이 필요합니다.\n컨베이어에 운반되고 있는 자원을 분할할 분배기를 만드세요. tutorial.router = 공장을 작동시키기 위해 자원이 필요합니다.\n컨베이어에 운반되고 있는 자원을 분할할 분배기를 만드세요.
tutorial.dagger = 전력 노드를 공장에 연결하세요.\n일단 요구 사항이 충족되면 기체 생산을 시작합니다.\n\n필요에 따라 드릴 및 발전기, 컨베이어를 더 많이 만들 수 있습니다. tutorial.dagger = 전력 노드를 공장에 연결하세요.\n일단 요구 사항이 충족되면 기체 생산을 시작합니다.\n\n필요에 따라 드릴 및 발전기, 컨베이어를 더 많이 만들 수 있습니다.
tutorial.battle = [LIGHT_GRAY]적[]의 코어가 드러났습니다.\n당신의 부대와 귀여운 디거를 사용하여 파괴하세요. tutorial.battle = [LIGHT_GRAY]적[]의 코어가 드러났습니다.\n당신의 부대와 귀여운 디거를 사용하여 파괴하세요.
block.core.description = 게임에서 가장 중요한 건물.\n파괴되면 게임이 끝납니다.
block.copper-wall.description = 구리로 만든 벽. block.copper-wall.description = 구리로 만든 벽.
block.copper-wall-large.description = 구리로 만든 큰 벽. block.copper-wall-large.description = 구리로 만든 큰 벽.
block.dense-alloy-wall.description = 합금으로 만든 벽. 구리벽보다 체력이 높습니다. block.dense-alloy-wall.description = 합금으로 만든 벽. 구리벽보다 체력이 높습니다.
@@ -680,17 +682,17 @@ block.surge-wall.description = 데미지를 입으면 번개를 일으켜 대상
block.surge-wall-large.description = 설금을 재료로 한 큰 벽.\n데미지를 입으면 번개를 일으켜 대상에게 피해를 입힙니다. block.surge-wall-large.description = 설금을 재료로 한 큰 벽.\n데미지를 입으면 번개를 일으켜 대상에게 피해를 입힙니다.
block.door.description = 유닛이 지나갈 수 있도록 만든 문. 클릭하면 열고 닫습니다. block.door.description = 유닛이 지나갈 수 있도록 만든 문. 클릭하면 열고 닫습니다.
block.door-large.description = 유닛이 자나갈 수 있도록 만든 큰 문. 클릭하면 열고 닫습니다. block.door-large.description = 유닛이 자나갈 수 있도록 만든 큰 문. 클릭하면 열고 닫습니다.
block.mend-projector.description = 주위 건물을 치료하는 건물. block.mend-projector.description = 주위 건물을 치료하는 건물입니다.
block.overdrive-projector.description = 범위 내 모든 행동의 속도를 높여주는 보조형 방어 건물. block.overdrive-projector.description = 범위 내 모든 행동의 속도를 높여주는 보조형 방어 건물입니다.
block.force-projector.description = 보호막을 생성하는 건물.\n기본적으로 전기만 있으면 작동하지만, 메타를 넣어 보호막의 범위를 크게 확장시킬 수 있습니다. block.force-projector.description = 보호막을 생성하는 건물.\n기본적으로 전기만 있으면 작동하지만, 메타를 넣어 보호막의 범위를 크게 확장시킬 수 있습니다.
block.shock-mine.description = 적이 이 블록을 지나가면 전격 공격을 하는 함정형 방어 건물. block.shock-mine.description = 적이 이 블록을 지나가면 전격 공격을 하는 함정형 방어 건물입니다.
block.duo.description = 범용성을 가진 터렛.\n지상 및 공중공격을 하며, 초중반에 유용합니다. block.duo.description = 범용성을 가진 터렛.\n지상 및 공중공격을 하며, 초중반에 유용합니다.
block.arc.description = 목표 방향으로 전격 공격을 하는 포탑입니다. block.arc.description = 목표 방향으로 전격 공격을 하는 포탑입니다.
block.hail.description = 장거리 지상 공격을 하는 터렛입니다.\n적이 오기 전에 쓸어버릴 수 있습니다. block.hail.description = 장거리 지상 공격을 하는 터렛입니다.\n적이 오기 전에 쓸어버릴 수 있습니다.
block.lancer.description = 중거리 레이져 포탑입니다.\n적을 관통하기 때문에 뭉쳐있는 적들에게 매우 효과적입니다. block.lancer.description = 중거리 레이져 포탑입니다.\n적을 관통하기 때문에 뭉쳐있는 적들에게 매우 효과적입니다.
block.wave.description = 적이 있는 자리에 액체를 뿌립니다.\n이 포탑을 활용하여 액체를 뿌린 곳에 불을 붙이거나 적을 느리게 할 수 있습니다. block.wave.description = 적이 있는 자리에 액체를 뿌립니다.\n이 포탑을 활용하여 액체를 뿌린 곳에 불을 붙이거나 적을 느리게 할 수 있습니다.
block.salvo.description = 명중률이 높고, 3발씩 끊어 발사하는 포탑입니다. block.salvo.description = 명중률이 높고, 3발씩 끊어 발사하는 포탑입니다.
block.swarmer.description = 4발씩 끊어 발사하고, 유도 미사일을 가진 포탑입니다. block.swarmer.description = 4발씩 끊어서 유도체를 발사하는 포탑입니다
block.ripple.description = 4개의 탄약으로 나눠 발사하여 명중률이 낮지만, 사거리가 매우 긴 포탑입니다. block.ripple.description = 4개의 탄약으로 나눠 발사하여 명중률이 낮지만, 사거리가 매우 긴 포탑입니다.
block.cyclone.description = 낮은 명중률과 높은 RPM 을 가진 포탑입니다.\n탄약이 남아있는 한 멈추지 않고 계속 연사합니다. block.cyclone.description = 낮은 명중률과 높은 RPM 을 가진 포탑입니다.\n탄약이 남아있는 한 멈추지 않고 계속 연사합니다.
block.fuse.description = 단거리에서 범위형 레이저를 발사하는 포탑입니다. block.fuse.description = 단거리에서 범위형 레이저를 발사하는 포탑입니다.
@@ -701,21 +703,21 @@ block.titanium-conveyor.description = 빠른 속도로 자원을 수송할 수
block.phase-conveyor.description = 자원을 순간이동 시켜 주는 컨베이어 입니다. block.phase-conveyor.description = 자원을 순간이동 시켜 주는 컨베이어 입니다.
block.junction.description = 컨베이어를 교차시켜 자원을 수송할 때 사용할 수 있는 블록입니다. block.junction.description = 컨베이어를 교차시켜 자원을 수송할 때 사용할 수 있는 블록입니다.
block.mass-driver.description = 자원을 받아서 다른 물질 이동기로 전달할 수 있는 블록입니다.\n엄청난 사거리를 가지고 있으며, 주로 컨베이어가 접근할 수 없는 곳에 유용하게 사용됩니다. block.mass-driver.description = 자원을 받아서 다른 물질 이동기로 전달할 수 있는 블록입니다.\n엄청난 사거리를 가지고 있으며, 주로 컨베이어가 접근할 수 없는 곳에 유용하게 사용됩니다.
block.smelter.description = 합금을 제작할 수 있는 건물. block.smelter.description = 합금을 제작할 수 있는 건물입니다.
block.arc-smelter.description = 합금을 제작할 수 있는 건물이지만, 이 건물은 석탄이 필요 없고 좀더 빠른 속도로 합금을 생산해낼 수 있습니다. block.arc-smelter.description = 합금을 제작할 수 있는 건물이지만, 이 건물은 석탄이 필요 없고 좀더 빠른 속도로 합금을 생산해낼 수 있습니다.
block.silicon-smelter.description = 실리콘을 제작할 수 있는 건물. block.silicon-smelter.description = 실리콘을 제작할 수 있는 건물입니다.
block.plastanium-compressor.description = 플라스터늄을 제조할 수 있는 건물. block.plastanium-compressor.description = 플라스터늄을 제조할 수 있는 건물입니다.
block.phase-weaver.description = 메타를 제작할 수 있는 건물. block.phase-weaver.description = 메타를 제작할 수 있는 건물입니다.
block.alloy-smelter.description = 설금을 제작할 수 있는 건물. block.alloy-smelter.description = 설금을 제작할 수 있는 건물입니다.
block.pulverizer.description = 돌을 갈아서 모래로 만들 수 있는 건물. block.pulverizer.description = 돌을 갈아서 모래로 만들 수 있는 건물입니다.
block.pyratite-mixer.description = 피라테를 제조할 수 있는 건물. block.pyratite-mixer.description = 피라테를 제조할 수 있는 건물입니다.
block.blast-mixer.description = 화합물을 제조할 수 있는 건물. block.blast-mixer.description = 화합물을 제조할 수 있는 건물입니다.
block.cryofluidmixer.description = 냉각수를 제작할 수 있는 건물. block.cryofluidmixer.description = 냉각수를 제작할 수 있는 건물입니다.
block.solidifer.description = 용암을 돌로 만들 수 있는 건물. block.solidifer.description = 용암을 돌로 만들 수 있는 건물입니다.
block.melter.description = 돌로 용암을 만들 수 있는 건물. block.melter.description = 돌로 용암을 만들 수 있는 건물입니다.
block.incinerator.description = 불필요한 아이템을 소각시켜 줄 수 있는 건물. block.incinerator.description = 불필요한 아이템을 소각시켜 줄 수 있는 건물입니다.
block.biomattercompressor.description = 잔디밭에서 바이오메터를 추출할 수 있는 건물. block.biomattercompressor.description = 잔디밭에서 바이오메터를 추출할 수 있는 건물입니다.
block.separator.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물. block.separator.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물입니다.
block.centrifuge.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물이지만, 이 건물은 좀 더 다양한 자원을 얻을 수 있게 해 줍니다. block.centrifuge.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물이지만, 이 건물은 좀 더 다양한 자원을 얻을 수 있게 해 줍니다.
block.power-node.description = 생성된 전기를 다른 건물로 전달하기 위한 전력 노드입니다. block.power-node.description = 생성된 전기를 다른 건물로 전달하기 위한 전력 노드입니다.
block.power-node-large.description = 생성된 전기를 다른 건물로 전달하기 위한 건물이며, 일반 노드보다 더 많은 전력을 이동시킬 수 있습니다. block.power-node-large.description = 생성된 전기를 다른 건물로 전달하기 위한 건물이며, 일반 노드보다 더 많은 전력을 이동시킬 수 있습니다.
@@ -729,31 +731,31 @@ block.solar-panel-large.description = 태양열을 받아 자기 스스로 전
block.thorium-reactor.description = 토륨을 원료로 하는 토륨 원자로 입니다.\n많은 전력을 생산하지만 엄청난 열을 발생시키기 때문에, 많은 량의 물 또는 냉각수가 있어야 터지지 않고 작동합니다. block.thorium-reactor.description = 토륨을 원료로 하는 토륨 원자로 입니다.\n많은 전력을 생산하지만 엄청난 열을 발생시키기 때문에, 많은 량의 물 또는 냉각수가 있어야 터지지 않고 작동합니다.
block.rtg-generator.description = 냉각은 필요 없지만 토륨 원자로보다 적은량의 전력을 생산하는 방사선 동위원소 열전자 발전기. block.rtg-generator.description = 냉각은 필요 없지만 토륨 원자로보다 적은량의 전력을 생산하는 방사선 동위원소 열전자 발전기.
block.unloader.description = 해당 창고 및 코어에서 자원을 빼내는데 사용됩니다. block.unloader.description = 해당 창고 및 코어에서 자원을 빼내는데 사용됩니다.
block.container.description = 자원을 운반하기 위한 수송 블록입니다. block.container.description = 아이템을 임시로 저장할 수 있는 소형 창고입니다.
block.vault.description = 아이템을 임시로 저장할 수 있는 대형 창고 block.vault.description = 아이템을 임시로 저장할 수 있는 대형 창고입니다.
block.mechanical-drill.description = 구리로 제작할 수 있는 기본 드릴입니다. block.mechanical-drill.description = 구리로 제작할 수 있는 기본 드릴입니다.
block.pneumatic-drill.description = 돌, 티타늄을 채광할 수 있는 고급 드릴입니다. block.pneumatic-drill.description = 돌, 티타늄을 채광할 수 있는 고급 드릴입니다.
block.laser-drill.description = 토륨을 채광할 수 있는 최고급 드릴입니다.\n전력과 물을 공급하여 빠른 속도로 채광할 수 있습니다. block.laser-drill.description = 토륨을 채광할 수 있는 최고급 드릴입니다.\n전력과 물을 공급하여 빠른 속도로 채광할 수 있습니다.
block.blast-drill.description = 최상위 드릴입니다. 엄청난 양의 전력과 물을 소모하는 대신, 매우 빠른 속도로 채광합니다. block.blast-drill.description = 최상위 드릴입니다. 엄청난 양의 전력과 물을 소모하는 대신, 매우 빠른 속도로 채광합니다.
block.water-extractor.description = 바닥에서 물을 추출하여 건물에 공급할 수 있는 건물. block.water-extractor.description = 바닥에서 물을 추출하여 건물에 공급할 수 있는 건물입니다.
block.cultivator.description = 잔디에서 바이오메터를 추출할 수 있는 건물. block.cultivator.description = 잔디에서 바이오메터를 추출할 수 있는 건물입니다.
block.oil-extractor.description = 기름을 추출 해 주는 건물. block.oil-extractor.description = 기름(타르)을 추출 해 주는 건물입니다.
block.dart-ship-pad.description = 다트 비행선으로 바꿀 수 있는 패드. block.dart-ship-pad.description = 다트 비행선으로 바꿀 수 있는 패드입니다.
block.trident-ship-pad.description = 삼지창 비행선으로 바꿀 수 있는 패드. block.trident-ship-pad.description = 삼지창 비행선으로 바꿀 수 있는 패드입니다.
block.javelin-ship-pad.description = 자비린 비행선으로 바꿀 수 있는 패드. block.javelin-ship-pad.description = 자비린 비행선으로 바꿀 수 있는 패드입니다.
block.glaive-ship-pad.description = 글레브 비행선으로 바꿀 수 있는 패드. block.glaive-ship-pad.description = 글레브 비행선으로 바꿀 수 있는 패드입니다.
block.tau-mech-pad.description = 타우 기체로 바꿀 수 있는 패드 block.tau-mech-pad.description = 타우 기체로 바꿀 수 있는 패드
block.delta-mech-pad.description = 델타 기체로 바꿀 수 있는 패드. block.delta-mech-pad.description = 델타 기체로 바꿀 수 있는 패드입니다.
block.omega-mech-pad.description = 오메가 기체로 바꿀 수 있는 패드 block.omega-mech-pad.description = 오메가 기체로 바꿀 수 있는 패드
block.spirit-factory.description = 스피릿 유닛을 생산하는 공장. block.spirit-factory.description = 스피릿 유닛을 생산하는 공장입니다.
block.phantom-factory.description = 유닛 팬텀을 생산하는 공장. block.phantom-factory.description = 유닛 팬텀을 생산하는 공장입니다.
block.wraith-factory.description = 유닛 유령 전투기를 소환하는 공장. block.wraith-factory.description = 유닛 유령 전투기를 소환하는 공장입니다.
block.ghoul-factory.description = 구울 유닛을 생산하는 공장. block.ghoul-factory.description = 구울 유닛을 생산하는 공장입니다.
block.dagger-factory.description = 귀여운 디거를 생산하는 공장. block.dagger-factory.description = 귀여운 디거를 생산하는 공장입니다.
block.titan-factory.description = 타이탄 유닛을 생산할 수 있는 공장. block.titan-factory.description = 타이탄 유닛을 생산할 수 있는 공장입니다.
block.fortress-factory.description = 포트리스를 생산하는 공장. block.fortress-factory.description = 포트리스를 생산하는 공장입니다.
block.revenant-factory.description = 레비던트 유닛을 생산할 수 있는 공장. block.revenant-factory.description = 레비던트 유닛을 생산할 수 있는 공장입니다.
block.repair-point.description = 근처 유닛들을 수리하는 건물. block.repair-point.description = 근처 유닛들을 수리하는 건물입니다.
block.command-center.description = 생산된 유닛들을 제어할 수 있는 건물.\n첫번째 버튼은 적 기지로 공격하며, 두번째는 대기 상태, 세번째는 기지 근처를 돌며 정찰합니다. block.command-center.description = 생산된 유닛들을 제어할 수 있는 건물.\n첫번째 버튼은 적 기지로 공격하며, 두번째는 대기 상태, 세번째는 기지 근처를 돌며 정찰합니다.
block.conduit.description = 일반 파이프. 액체가 지나갈 수 있도록 해 줍니다. block.conduit.description = 일반 파이프. 액체가 지나갈 수 있도록 해 줍니다.
block.pulse-conduit.description = 티타늄으로 만들어 졌으며, 일반 파이프보다 액체 수용량이 높습니다. block.pulse-conduit.description = 티타늄으로 만들어 졌으며, 일반 파이프보다 액체 수용량이 높습니다.
@@ -768,13 +770,13 @@ block.thermal-pump.description = 용암 위에서 사용할 수 있는 펌프입
block.router.description = 한 방향에서 아이템을 받은 후 최대 3개의 다른 방향으로 동일하게 출력합니다.\n재료를 한곳에서 여러 대상으로 분할하여 운반하는데 유용합니다. block.router.description = 한 방향에서 아이템을 받은 후 최대 3개의 다른 방향으로 동일하게 출력합니다.\n재료를 한곳에서 여러 대상으로 분할하여 운반하는데 유용합니다.
block.distributor.description = 아이템을 최대 7개의 다른 방향으로 똑같이 분할하는 고급 분배기. block.distributor.description = 아이템을 최대 7개의 다른 방향으로 똑같이 분할하는 고급 분배기.
block.bridge-conveyor.description = 고급 자원 수송 블록.\n지형이나 건물을 넘어 최대 3개 타일을 건너뛰고 자원을 운송할 수 있습니다. block.bridge-conveyor.description = 고급 자원 수송 블록.\n지형이나 건물을 넘어 최대 3개 타일을 건너뛰고 자원을 운송할 수 있습니다.
block.alpha-mech-pad.description = 알파 기체로 바꿀 수 있는 패드. block.alpha-mech-pad.description = 알파 기체로 바꿀 수 있는 패드입니다.
block.itemsource.description = 자원을 선택하면 그 자원이 무한하게 튀어나오는 블록입니다. block.itemsource.description = 자원을 선택하면 그 자원이 무한하게 생성되는 블록입니다.
block.liquidsource.description = 무한한 액체를 출력해냅니다. block.liquidsource.description = 무한한 액체를 출력해냅니다.
block.itemvoid.description = 아이템을 시공으로 빠트려 사라지게 만듭니다. block.itemvoid.description = 아이템을 시공으로 빠트려 사라지게 만듭니다.
block.powerinfinite.description = 무한한 전력을 출력해냅니다. block.powerinfinite.description = 무한한 전력을 공급해주는 블록입니다.
block.powervoid.description = 무한한 아이템을 출력해냅니다. block.powervoid.description = 설정된 아이템을 계속해서 출력하는 블록입니다.
liquid.water.description = 유닛이 이 위를 지나가면 이동속도가 느려지고, 깊은 물에 빠지면 죽습니다. liquid.water.description = 지상 유닛이 이 위를 지나가면 이동속도가 느려지고, 깊은 물에 빠지면 죽습니다.
liquid.lava.description = 유닛이 이 위를 지나가면 이동속도가 매우 느려지고, 지속적으로 데미지를 입습니다. liquid.lava.description = 지상 유닛이 이 위를 지나가면 이동속도가 매우 느려지고, 지속적으로 데미지를 입습니다.
liquid.oil.description = 일부 조합 블록에서 사용되는 자원입니다. liquid.oil.description = 일부 조합 블록에서 사용되는 자원입니다.
liquid.cryofluid.description = 포탑 및 토륨 원자로에서 사용되는 자원입니다. 누출시 폭발 및 방화의 위험성이 있습니다. liquid.cryofluid.description = 포탑 및 토륨 원자로에서 사용되는 자원입니다. 누출시 폭발 및 방화의 위험성이 있습니다.
+1 -1
View File
@@ -50,7 +50,7 @@ text.mission.main = Main Mission:[LIGHT_GRAY] {0}
text.mission.info = Mission Info text.mission.info = Mission Info
text.mission.complete = Mission complete! text.mission.complete = Mission complete!
text.mission.complete.body = Sector {0},{1} has been conquered. text.mission.complete.body = Sector {0},{1} has been conquered.
text.mission.wave = Survive [accent]{0}[] waves. 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.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies
text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy
text.mission.wave.menu = Survive[accent] {0} []waves text.mission.wave.menu = Survive[accent] {0} []waves
+1 -1
View File
@@ -50,7 +50,7 @@ text.mission.main = Main Mission:[LIGHT_GRAY] {0}
text.mission.info = Mission Info text.mission.info = Mission Info
text.mission.complete = Mission complete! text.mission.complete = Mission complete!
text.mission.complete.body = Sector {0},{1} has been conquered. text.mission.complete.body = Sector {0},{1} has been conquered.
text.mission.wave = Sobrevive [accent]{0}[] Onda. text.mission.wave = Sobrevive [accent]{0}/{1}[] Onda\nOnda em {2}
text.mission.wave.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies 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.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy
text.mission.wave.menu = Survive[accent] {0} []waves text.mission.wave.menu = Survive[accent] {0} []waves
+2 -2
View File
@@ -50,7 +50,7 @@ text.mission.main = Главная мисия:[LIGHT_GRAY] {0}
text.mission.info = Информация о миссии text.mission.info = Информация о миссии
text.mission.complete = Миссия выполнена! text.mission.complete = Миссия выполнена!
text.mission.complete.body = Сектор {0},{1} был завоёван. text.mission.complete.body = Сектор {0},{1} был завоёван.
text.mission.wave = Пережить следующее количество волн: [accent]{0}[]. text.mission.wave = Пережить следующее количество волн: [accent]{0}/{1}[]\nВолна в {2}
text.mission.wave.enemies = Осталось волн:[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.enemy = Осталось волн:[accent] {0}/{1}[]\n{2} враг
text.mission.wave.menu = Пережить[accent] {0} []волн text.mission.wave.menu = Пережить[accent] {0} []волн
@@ -407,7 +407,7 @@ mode.sandbox.name = Песочница
mode.sandbox.description = Бесконечные ресурсы и нет таймера для волн, но можно самим вызвать волну. mode.sandbox.description = Бесконечные ресурсы и нет таймера для волн, но можно самим вызвать волну.
mode.custom.warning = [scarlet]РАЗБЛОКИРОВАННОЕ В ПОЛЬЗОВАТЕЛЬСКИХ ИГРАХ ИЛИ НА СЕРВЕРАХ НЕ СОХРАНЯЕТСЯ[]\n\nИграйте в секторах для разблокировки чего-либо mode.custom.warning = [scarlet]РАЗБЛОКИРОВАННОЕ В ПОЛЬЗОВАТЕЛЬСКИХ ИГРАХ ИЛИ НА СЕРВЕРАХ НЕ СОХРАНЯЕТСЯ[]\n\nИграйте в секторах для разблокировки чего-либо
mode.custom.warning.read = Внимательно прочитайте это!:\n[scarlet]РАЗБЛОКИРОВАННОЕ В ПОЛЬЗОВАТЕЛЬСКИХ ИГРАХ ИЛИ ДРУГИХ РЕЖИМАХ ИГРЫ НЕ РАСПРОСТРАНЯЕТСЯ НА СЕКТОРА ИЛИ ДРУГИЕ РЕЖИМЫ ИГРЫ!\n\n[LIGHT_GRAY](Я бы хотел, чтобы это не было необходимо, но, по-видимому, это так) mode.custom.warning.read = Внимательно прочитайте это!:\n[scarlet]РАЗБЛОКИРОВАННОЕ В ПОЛЬЗОВАТЕЛЬСКИХ ИГРАХ ИЛИ ДРУГИХ РЕЖИМАХ ИГРЫ НЕ РАСПРОСТРАНЯЕТСЯ НА СЕКТОРА ИЛИ ДРУГИЕ РЕЖИМЫ ИГРЫ!\n\n[LIGHT_GRAY](Я бы хотел, чтобы это не было необходимо, но, по-видимому, это так)
mode.freebuild.name = Cвободная\nстройка mode.freebuild.name = Свободная\nстройка
mode.freebuild.description = ограниченные ресурсы и нет таймера для волн. mode.freebuild.description = ограниченные ресурсы и нет таймера для волн.
mode.pvp.name = Противо-\nстояние mode.pvp.name = Противо-\nстояние
mode.pvp.description = боритесь против других игроков. mode.pvp.description = боритесь против других игроков.
+1 -1
View File
@@ -50,7 +50,7 @@ text.mission.main = Main Mission:[LIGHT_GRAY] {0}
text.mission.info = Mission Info text.mission.info = Mission Info
text.mission.complete = Gorev tamamlandi! text.mission.complete = Gorev tamamlandi!
text.mission.complete.body = Sektor {0},{1} ele gecirildi text.mission.complete.body = Sektor {0},{1} ele gecirildi
text.mission.wave = [accent]{0}[] Dalga hayatta kal 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.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies
text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy
text.mission.wave.menu = Survive[accent] {0} []waves text.mission.wave.menu = Survive[accent] {0} []waves
+1 -1
View File
@@ -50,7 +50,7 @@ text.mission.main = Main Mission:[LIGHT_GRAY] {0}
text.mission.info = Mission Info text.mission.info = Mission Info
text.mission.complete = Mission complete! text.mission.complete = Mission complete!
text.mission.complete.body = Sector {0},{1} has been conquered. text.mission.complete.body = Sector {0},{1} has been conquered.
text.mission.wave = Survive [accent]{0}[] waves. 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.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies
text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy
text.mission.wave.menu = Survive[accent] {0} []waves text.mission.wave.menu = Survive[accent] {0} []waves
+1 -1
View File
@@ -50,7 +50,7 @@ text.mission.main = Головна місія:[LIGHT_GRAY] {0}
text.mission.info = Інформація про місії text.mission.info = Інформація про місії
text.mission.complete = Місія завершена! text.mission.complete = Місія завершена!
text.mission.complete.body = Сектор {0},{1} був завойований. text.mission.complete.body = Сектор {0},{1} був завойований.
text.mission.wave = Пережити наступну кількість хвиль:[accent]{0}[] . text.mission.wave = Пережити наступну кількість хвиль:[accent]{0}/{1}[]\nХвиля в {2}
text.mission.wave.enemies = Пережити [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.enemy = Пережити[accent] {0}/{1} []хвиль\n{2} Ворог
text.mission.wave.menu = Пережити[accent] {0} []хвиль text.mission.wave.menu = Пережити[accent] {0} []хвиль
+1 -1
View File
@@ -50,7 +50,7 @@ text.mission.main = Main Mission:[LIGHT_GRAY] {0}
text.mission.info = Mission Info text.mission.info = Mission Info
text.mission.complete = 任务完成! text.mission.complete = 任务完成!
text.mission.complete.body = 区域 {0},攻占了 {1} 个 text.mission.complete.body = 区域 {0},攻占了 {1} 个
text.mission.wave = 存活了 [accent]{0}[] 波。 text.mission.wave = 存活了 [accent]{0}/{1}[] 波。\nWave in {2}
text.mission.wave.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies 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.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy
text.mission.wave.menu = Survive[accent] {0} []waves text.mission.wave.menu = Survive[accent] {0} []waves
+1 -1
View File
@@ -50,7 +50,7 @@ text.mission.main = Main Mission:[LIGHT_GRAY] {0}
text.mission.info = Mission Info text.mission.info = Mission Info
text.mission.complete = Mission complete! text.mission.complete = Mission complete!
text.mission.complete.body = Sector {0},{1} has been conquered. text.mission.complete.body = Sector {0},{1} has been conquered.
text.mission.wave = Survive [accent]{0}[] waves. 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.enemies = Survive[accent] {0}/{1} []waves\n{2} Enemies
text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy text.mission.wave.enemy = Survive[accent] {0}/{1} []waves\n{2} Enemy
text.mission.wave.menu = Survive[accent] {0} []waves text.mission.wave.menu = Survive[accent] {0} []waves
Binary file not shown.
+6 -30
View File
@@ -6,17 +6,15 @@ precision highp int;
#define MAX_HITS 64 #define MAX_HITS 64
#define HIT_RADIUS 12.0 #define HIT_RADIUS 12.0
#define ALPHA 0.18 #define ALPHA 0.18
#define thickness 1.0
#define step 2.0
uniform sampler2D u_texture; uniform sampler2D u_texture;
uniform vec4 u_color;
uniform vec2 u_texsize; uniform vec2 u_texsize;
uniform float u_time; uniform float u_time;
uniform float u_scaling; uniform float u_scaling;
uniform float u_dp; uniform float u_dp;
uniform vec2 u_offset; uniform vec2 u_offset;
uniform int u_hitamount;
uniform vec3 u_hits[MAX_HITS];
varying vec4 v_color; varying vec4 v_color;
varying vec2 v_texCoord; varying vec2 v_texCoord;
@@ -28,29 +26,19 @@ float round(float f){
void main() { void main() {
vec2 T = v_texCoord.xy; vec2 T = v_texCoord.xy;
vec2 coords = (T * u_texsize) + u_offset; vec2 coords = (T * u_texsize) + u_offset;
T += vec2(sin(coords.y / 3.0 + u_time / 20.0) / 240.0, sin(coords.x / 3.0 + u_time / 20.0) / 240.0) * u_scaling; T += vec2(sin(coords.y / 3.0 + u_time / 20.0) / 240.0, sin(coords.x / 3.0 + u_time / 20.0) / 240.0) * u_scaling;
float si = sin(u_time / 20.0) / 8.0; float si = sin(u_time / 20.0) / 8.0;
vec4 color = texture2D(u_texture, T); vec4 color = texture2D(u_texture, T);
vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y); vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y);
bool any = false; if(texture2D(u_texture, T).a < 0.1 &&
(texture2D(u_texture, T + vec2(0, step) * v).a > 0.1 || texture2D(u_texture, T + vec2(0, -step) * v).a > 0.1 ||
texture2D(u_texture, T + vec2(step, 0) * v).a > 0.1 || texture2D(u_texture, T + vec2(-step, 0) * v).a > 0.1)){
float thickness = 1.0; gl_FragColor = mix(v_color, vec4(1.0), si);
float step = 2.0;
if(texture2D(u_texture, T).a < 0.1 &&
(texture2D(u_texture, T + vec2(0, step) * v).a > 0.1 || texture2D(u_texture, T + vec2(0, -step) * v).a > 0.1 ||
texture2D(u_texture, T + vec2(step, 0) * v).a > 0.1 || texture2D(u_texture, T + vec2(-step, 0) * v).a > 0.1))
any = true;
if(any){
gl_FragColor = mix(u_color, vec4(1.0), si);
}else{ }else{
if(color.a > 0.1){ if(color.a > 0.1){
@@ -59,18 +47,6 @@ void main() {
} }
color.a = ALPHA; color.a = ALPHA;
for(int i = 0; i < MAX_HITS; i ++){
if(i >= u_hitamount) break;
vec3 hit = u_hits[i];
float rad = hit.z * HIT_RADIUS;
float fin = 1.0 - hit.z;
if(abs(distance(vec2(hit.x, hit.y), coords - u_texsize/2.0) - rad) < 1.0){
color = mix(color, mix(u_color, vec4(1.0), si), (1.0 * fin));
color.a = ALPHA + 0.82 *fin;
}
}
} }
gl_FragColor = color; gl_FragColor = color;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

-23
View File
@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module>
<source path="io/anuke/mindustry"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.Tile"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.Content"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.type.ItemStack"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.maps.Maps"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.Map"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.SpawnGroup"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.core.GameState"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.io.SaveFileVersion"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.ucore.entities.impl.EffectEntity"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.effect"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.bullet.Bullet"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.Team"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.maps.missions.Mission"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.type.Item"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.meta.BlockBar"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.maps.generation.WorldGenerator"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.StatusController"/>
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.maps.Sector"/>
<extend-configuration-property name="gdx.reflect.include" value="com.badlogic.gdx.utils.Predicate"/>
</module>
+2
View File
@@ -94,6 +94,7 @@ public class Vars{
public static float controllerMin = 0.25f; public static float controllerMin = 0.25f;
public static float baseControllerSpeed = 11f; public static float baseControllerSpeed = 11f;
public static boolean snapCamera = true; public static boolean snapCamera = true;
public static ContentLoader content; public static ContentLoader content;
public static GameState state; public static GameState state;
public static ThreadHandler threads; public static ThreadHandler threads;
@@ -162,6 +163,7 @@ public class Vars{
}); });
} }
state = new GameState();
threads = new ThreadHandler(); threads = new ThreadHandler();
mobile = Gdx.app.getType() == ApplicationType.Android || Gdx.app.getType() == ApplicationType.iOS || testMobile; mobile = Gdx.app.getType() == ApplicationType.Android || Gdx.app.getType() == ApplicationType.iOS || testMobile;
@@ -71,6 +71,7 @@ public class BlockIndexer{
flagMap[i][j] = new ObjectSet<>(); flagMap[i][j] = new ObjectSet<>();
} }
} }
typeMap.clear(); typeMap.clear();
ores = null; ores = null;
@@ -246,7 +247,7 @@ public class BlockIndexer{
for(int x = quadrantX * structQuadrantSize; x < world.width() && x < (quadrantX + 1) * structQuadrantSize; x++){ 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++){ for(int y = quadrantY * structQuadrantSize; y < world.height() && y < (quadrantY + 1) * structQuadrantSize; y++){
Tile result = world.tile(x, y); Tile result = world.tile(x, y);
if(result.block().drops == null || !scanOres.contains(result.block().drops.item)) continue; if( result == null || result.block().drops == null || !scanOres.contains(result.block().drops.item)) continue;
itemSet.add(result.block().drops.item); itemSet.add(result.block().drops.item);
} }
+13 -8
View File
@@ -37,7 +37,7 @@ public class Mechs implements ContentList{
alpha = new Mech("alpha-mech", false){ alpha = new Mech("alpha-mech", false){
int maxDrones = 3; int maxDrones = 3;
float buildTime = 200f; float buildTime = 20f;
{ {
drillPower = 1; drillPower = 1;
@@ -53,14 +53,19 @@ public class Mechs implements ContentList{
@Override @Override
public void updateAlt(Player player){ public void updateAlt(Player player){
if(getDrones(player) < maxDrones && !TutorialSector.supressDrone() && player.timer.get(Player.timerAbility, buildTime)){ if(player.isShooting && getDrones(player) < maxDrones && !TutorialSector.supressDrone()){
if(!Net.client()) { player.timer.get(Player.timerAbility, buildTime);
AlphaDrone drone = (AlphaDrone) UnitTypes.alphaDrone.create(player.getTeam());
drone.leader = player; if(player.timer.getTime(Player.timerAbility) > buildTime/2f){
drone.set(player.x, player.y); if(!Net.client()){
drone.add(); AlphaDrone drone = (AlphaDrone) UnitTypes.alphaDrone.create(player.getTeam());
drone.leader = player;
drone.set(player.x, player.y);
drone.add();
Effects.effect(UnitFx.unitLand, player);
}
} }
Effects.effect(UnitFx.unitLand, player);
} }
} }
@@ -139,7 +139,7 @@ public class Blocks extends BlockList implements ContentList{
}}; }};
ice = new Floor("ice"){{ ice = new Floor("ice"){{
dragMultiplier = 0.3f; dragMultiplier = 0.2f;
speedMultiplier = 0.4f; speedMultiplier = 0.4f;
minimapColor = Color.valueOf("b8eef8"); minimapColor = Color.valueOf("b8eef8");
hasOres = true; hasOres = true;
@@ -30,7 +30,7 @@ public class LiquidBlocks extends BlockList implements ContentList{
thermalPump = new Pump("thermal-pump"){{ thermalPump = new Pump("thermal-pump"){{
shadow = "shadow-rounded-2"; shadow = "shadow-rounded-2";
pumpAmount = 0.3f; pumpAmount = 0.275f;
consumes.power(0.03f); consumes.power(0.03f);
liquidCapacity = 40f; liquidCapacity = 40f;
hasPower = true; hasPower = true;
@@ -20,9 +20,9 @@ public class PowerBlocks extends BlockList implements ContentList{
}}; }};
thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{ thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{
maxLiquidGenerate = 0.5f; maxLiquidGenerate = 4f;
powerCapacity = 40f; powerCapacity = 40f;
powerPerLiquid = 1f; powerPerLiquid = 0.1f;
generateEffect = BlockFx.redgeneratespark; generateEffect = BlockFx.redgeneratespark;
size = 2; size = 2;
}}; }};
@@ -179,12 +179,6 @@ public class Control extends Module{
}); });
Events.on(WorldLoadEvent.class, event -> threads.runGraphics(() -> Events.fire(new WorldLoadGraphicsEvent()))); Events.on(WorldLoadEvent.class, event -> threads.runGraphics(() -> Events.fire(new WorldLoadGraphicsEvent())));
Events.on(TileChangeEvent.class, event -> {
if(event.tile.getTeam() == players[0].getTeam() && Recipe.getByResult(event.tile.block()) != null){
unlocks.handleContentUsed(Recipe.getByResult(event.tile.block()));
}
});
} }
public void addPlayer(int index){ public void addPlayer(int index){
@@ -278,7 +272,7 @@ public class Control extends Module{
outer: outer:
for(int i = 0; i < content.recipes().size; i ++){ for(int i = 0; i < content.recipes().size; i ++){
Recipe recipe = content.recipes().get(i); Recipe recipe = content.recipes().get(i);
if(!recipe.hidden && recipe.requirements != null){ if(!recipe.isHidden() && recipe.requirements != null){
for(ItemStack stack : recipe.requirements){ for(ItemStack stack : recipe.requirements){
if(!entity.items.has(stack.item, Math.min((int) (stack.amount * unlockResourceScaling), 2000))) continue outer; if(!entity.items.has(stack.item, Math.min((int) (stack.amount * unlockResourceScaling), 2000))) continue outer;
} }
+29 -13
View File
@@ -10,9 +10,11 @@ import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.Teams; import io.anuke.mindustry.game.Teams;
import io.anuke.mindustry.game.UnlockableContent;
import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.Recipe;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Events; import io.anuke.ucore.core.Events;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
@@ -35,13 +37,31 @@ public class Logic extends Module{
public boolean doUpdate = true; public boolean doUpdate = true;
public Logic(){ public Logic(){
state = new GameState(); Events.on(TileChangeEvent.class, event -> {
if(event.tile.getTeam() == defaultTeam && Recipe.getByResult(event.tile.block()) != null){
handleContent(Recipe.getByResult(event.tile.block()));
}
});
} }
@Override @Override
public void init(){ public void init(){
EntityQuery.init(); EntityQuery.init();
EntityQuery.collisions().setCollider(tilesize, world::solid); EntityQuery.collisions().setCollider(tilesize, (x, y) -> {
Tile tile = world.tile(x, y);
return tile != null && tile.solid();
});
}
/**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);
}
} }
public void play(){ public void play(){
@@ -142,7 +162,8 @@ public class Logic extends Module{
world.sectors.completeSector(world.getSector().x, world.getSector().y); world.sectors.completeSector(world.getSector().x, world.getSector().y);
world.sectors.save(); world.sectors.save();
if(!headless){
if(!headless && !Net.client()){
ui.missions.show(world.getSector()); ui.missions.show(world.getSector());
} }
@@ -151,7 +172,6 @@ public class Logic extends Module{
@Override @Override
public void update(){ public void update(){
if(threads.isEnabled() && !threads.isOnThread()) return;
if(Vars.control != null){ if(Vars.control != null){
control.runUpdateLogic(); control.runUpdateLogic();
@@ -159,15 +179,10 @@ public class Logic extends Module{
if(!state.is(State.menu)){ if(!state.is(State.menu)){
if(!Net.client() && !world.isInvalidMap()){
updateSectors();
checkGameOver();
}
if(!state.isPaused()){ if(!state.isPaused()){
Timers.update(); Timers.update();
if(!state.mode.disableWaveTimer && !state.mode.disableWaves){ if(!state.mode.disableWaveTimer && !state.mode.disableWaves && !state.gameOver){
state.wavetime -= Timers.delta(); state.wavetime -= Timers.delta();
} }
@@ -216,10 +231,11 @@ public class Logic extends Module{
world.pathfinder.update(); world.pathfinder.update();
} }
}
if(threads.isEnabled()){ if(!Net.client() && !world.isInvalidMap()){
netServer.update(); updateSectors();
checkGameOver();
}
} }
} }
} }
+15 -14
View File
@@ -165,14 +165,17 @@ public class NetClient extends Module{
public static void onKick(KickReason reason){ public static void onKick(KickReason reason){
netClient.disconnectQuietly(); netClient.disconnectQuietly();
state.set(State.menu); state.set(State.menu);
if(!reason.quiet){
if(reason.extraText() != null){ threads.runGraphics(() -> {
ui.showText(reason.toString(), reason.extraText()); if(!reason.quiet){
}else{ if(reason.extraText() != null){
ui.showText("$text.disconnect", reason.toString()); ui.showText(reason.toString(), reason.extraText());
}else{
ui.showText("$text.disconnect", reason.toString());
}
} }
} ui.loadfrag.hide();
ui.loadfrag.hide(); });
} }
@Remote(variants = Variant.both) @Remote(variants = Variant.both)
@@ -396,11 +399,11 @@ public class NetClient extends Module{
quiet = true; quiet = true;
} }
public synchronized void addRemovedEntity(int id){ public void addRemovedEntity(int id){
removed.add(id); removed.add(id);
} }
public synchronized boolean isEntityUsed(int id){ public boolean isEntityUsed(int id){
return removed.contains(id); return removed.contains(id);
} }
@@ -411,11 +414,9 @@ public class NetClient extends Module{
BuildRequest[] requests; BuildRequest[] requests;
synchronized(player.getPlaceQueue()){ requests = new BuildRequest[player.getPlaceQueue().size];
requests = new BuildRequest[player.getPlaceQueue().size]; for(int i = 0; i < requests.length; i++){
for(int i = 0; i < requests.length; i++){ requests[i] = player.getPlaceQueue().get(i);
requests[i] = player.getPlaceQueue().get(i);
}
} }
Call.onClientShapshot(lastSent++, TimeUtils.millis(), player.x, player.y, Call.onClientShapshot(lastSent++, TimeUtils.millis(), player.x, player.y,
@@ -416,7 +416,6 @@ public class NetServer extends Module{
} }
public void update(){ public void update(){
if(threads.isEnabled() && !threads.isOnThread()) return;
if(!headless && !closing && Net.server() && state.is(State.menu)){ if(!headless && !closing && Net.server() && state.is(State.menu)){
closing = true; closing = true;
@@ -248,11 +248,12 @@ public class Renderer extends RendererModule{
overlays.drawBottom(); overlays.drawBottom();
drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests); drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests);
Shaders.shield.color.set(Palette.accent);
Graphics.beginShaders(Shaders.shield); Graphics.beginShaders(Shaders.shield);
EntityDraw.draw(shieldGroup); EntityDraw.draw(shieldGroup);
EntityDraw.drawWith(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawOver()); EntityDraw.drawWith(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawOver());
Draw.color(Palette.accent);
Graphics.endShaders(); Graphics.endShaders();
Draw.color();
overlays.drawTop(); overlays.drawTop();
@@ -1,80 +1,35 @@
package io.anuke.mindustry.core; package io.anuke.mindustry.core;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.Queue;
import com.badlogic.gdx.utils.TimeUtils; import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Settings;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.Threads;
import io.anuke.ucore.util.Threads.ThreadInfoProvider; import io.anuke.ucore.util.Threads.ThreadInfoProvider;
import static io.anuke.mindustry.Vars.control;
import static io.anuke.mindustry.Vars.logic;
public class ThreadHandler implements ThreadInfoProvider{ public class ThreadHandler implements ThreadInfoProvider{
private final Queue<Runnable> toRun = new Queue<>();
private Thread thread, graphicsThread;
private final Object updateLock = new Object();
private float delta = 1f;
private float smoothDelta = 1f;
private long frame = 0, lastDeltaUpdate;
private float framesSinceUpdate;
private boolean enabled;
private boolean rendered = true;
private long lastFrameTime; private long lastFrameTime;
public ThreadHandler(){ public ThreadHandler(){
Threads.setThreadInfoProvider(this);
graphicsThread = Thread.currentThread();
Timers.setDeltaProvider(() -> { Timers.setDeltaProvider(() -> {
float result = isOnThread() ? delta : Gdx.graphics.getDeltaTime() * 60f; float result = Gdx.graphics.getDeltaTime() * 60f;
return Math.min(Float.isNaN(result) ? 1f : result, 15f); return Math.min(Float.isNaN(result) || Float.isInfinite(result) ? 1f : result, 15f);
}); });
} }
public void run(Runnable r){ public void run(Runnable r){
if(enabled){ r.run();
synchronized(toRun){
toRun.addLast(r);
}
}else{
r.run();
}
} }
public void runGraphics(Runnable r){ public void runGraphics(Runnable r){
if(enabled){ r.run();
Gdx.app.postRunnable(r);
}else{
r.run();
}
} }
public void runDelay(Runnable r){ public void runDelay(Runnable r){
if(enabled){ Gdx.app.postRunnable(r);
synchronized(toRun){
toRun.addLast(r);
}
}else{
Gdx.app.postRunnable(r);
}
}
public int getTPS(){
if(smoothDelta == 0f){
return 60;
}
return (int) (60 / smoothDelta);
} }
public long getFrameID(){ public long getFrameID(){
return enabled ? frame : Gdx.graphics.getFrameId(); return Gdx.graphics.getFrameId();
}
public float getFramesSinceUpdate(){
return framesSinceUpdate;
} }
public void handleBeginRender(){ public void handleBeginRender(){
@@ -95,119 +50,16 @@ public class ThreadHandler implements ThreadInfoProvider{
} }
} }
} }
if(!enabled) return;
framesSinceUpdate += Timers.delta();
synchronized(updateLock){
rendered = true;
updateLock.notify();
}
}
public boolean isEnabled(){
return enabled;
}
public void setEnabled(boolean enabled){
if(enabled){
logic.doUpdate = false;
Timers.runTask(2f, () -> {
if(thread != null){
thread.interrupt();
thread = null;
}
thread = new Thread(this::runLogic);
thread.setDaemon(true);
thread.setName("Update Thread");
thread.start();
Log.info("Starting logic thread.");
this.enabled = true;
});
}else{
this.enabled = false;
if(thread != null){
thread.interrupt();
thread = null;
}
Timers.runTask(2f, () -> {
logic.doUpdate = true;
});
}
}
public boolean doInterpolate(){
return enabled && Gdx.graphics.getFramesPerSecond() - getTPS() > 20 && getTPS() < 30;
}
public boolean isOnThread(){
return Thread.currentThread() == thread;
} }
@Override @Override
public boolean isOnLogicThread() { public boolean isOnLogicThread() {
return !enabled || Thread.currentThread() == thread; return true;
} }
@Override @Override
public boolean isOnGraphicsThread() { public boolean isOnGraphicsThread() {
return !enabled || Thread.currentThread() == graphicsThread; return true;
} }
private void runLogic(){
try{
while(true){
long time = TimeUtils.nanoTime();
while(true){
Runnable r;
synchronized(toRun){
if(toRun.size > 0){
r = toRun.removeFirst();
}else{
break;
}
}
r.run();
}
logic.doUpdate = true;
logic.update();
logic.doUpdate = false;
long elapsed = TimeUtils.nanosToMillis(TimeUtils.timeSinceNanos(time));
long target = (long) ((1000) / 60f);
if(elapsed < target){
Thread.sleep(target - elapsed);
}
synchronized(updateLock){
while(!rendered){
updateLock.wait();
}
rendered = false;
}
long actuallyElapsed = TimeUtils.nanosToMillis(TimeUtils.timeSinceNanos(time));
delta = Math.max(actuallyElapsed, target) / 1000f * 60f;
if(TimeUtils.timeSinceMillis(lastDeltaUpdate) > 1000){
lastDeltaUpdate = TimeUtils.millis();
smoothDelta = delta;
}
frame++;
framesSinceUpdate = 0;
}
}catch(InterruptedException ex){
Log.info("Stopping logic thread.");
}catch(Throwable ex){
control.setError(ex);
}
}
} }
+8 -1
View File
@@ -28,6 +28,7 @@ import io.anuke.ucore.scene.ui.TextField.TextFieldFilter;
import io.anuke.ucore.scene.ui.TooltipManager; import io.anuke.ucore.scene.ui.TooltipManager;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.scene.ui.layout.Unit; import io.anuke.ucore.scene.ui.layout.Unit;
import io.anuke.ucore.util.Threads;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
import static io.anuke.ucore.scene.actions.Actions.*; import static io.anuke.ucore.scene.actions.Actions.*;
@@ -154,6 +155,7 @@ public class UI extends SceneModule{
load = new LoadDialog(); load = new LoadDialog();
levels = new CustomGameDialog(); levels = new CustomGameDialog();
language = new LanguageDialog(); language = new LanguageDialog();
unlocks = new UnlocksDialog();
settings = new SettingsMenuDialog(); settings = new SettingsMenuDialog();
host = new HostDialog(); host = new HostDialog();
paused = new PausedDialog(); paused = new PausedDialog();
@@ -164,7 +166,6 @@ public class UI extends SceneModule{
traces = new TraceDialog(); traces = new TraceDialog();
maps = new MapsDialog(); maps = new MapsDialog();
localplayers = new LocalPlayerDialog(); localplayers = new LocalPlayerDialog();
unlocks = new UnlocksDialog();
content = new ContentInfoDialog(); content = new ContentInfoDialog();
sectors = new SectorsDialog(); sectors = new SectorsDialog();
missions = new MissionDialog(); missions = new MissionDialog();
@@ -239,6 +240,8 @@ public class UI extends SceneModule{
} }
public void showInfoFade(String info){ public void showInfoFade(String info){
Threads.assertGraphics();
Table table = new Table(); Table table = new Table();
table.setFillParent(true); table.setFillParent(true);
table.actions(Actions.fadeOut(7f, Interpolation.fade), Actions.removeActor()); table.actions(Actions.fadeOut(7f, Interpolation.fade), Actions.removeActor());
@@ -247,6 +250,8 @@ public class UI extends SceneModule{
} }
public void showInfo(String info){ public void showInfo(String info){
Threads.assertGraphics();
new Dialog("$text.info.title", "dialog"){{ new Dialog("$text.info.title", "dialog"){{
getCell(content()).growX(); getCell(content()).growX();
content().margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center); content().margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center);
@@ -255,6 +260,8 @@ public class UI extends SceneModule{
} }
public void showInfo(String info, Runnable clicked){ public void showInfo(String info, Runnable clicked){
Threads.assertGraphics();
new Dialog("$text.info.title", "dialog"){{ new Dialog("$text.info.title", "dialog"){{
getCell(content()).growX(); getCell(content()).growX();
content().margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center); content().margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center);
@@ -70,7 +70,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
public TargetTrait moveTarget; public TargetTrait moveTarget;
private float walktime; private float walktime;
private Queue<BuildRequest> placeQueue = new ThreadQueue<>(); private Queue<BuildRequest> placeQueue = new Queue<>();
private Tile mining; private Tile mining;
private CarriableTrait carrying; private CarriableTrait carrying;
private Trail trail = new Trail(12); private Trail trail = new Trail(12);
@@ -323,7 +323,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
} }
if(floor.isLiquid){ if(floor.isLiquid){
Draw.tint(Color.WHITE, floor.liquidColor, Mathf.clamp(drownTime)); Draw.tint(Color.WHITE, floor.liquidColor, drownTime);
}else{ }else{
Draw.tint(Color.WHITE); Draw.tint(Color.WHITE);
} }
@@ -421,55 +421,53 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
/**Draw all current build requests. Does not draw the beam effect, only the positions.*/ /**Draw all current build requests. Does not draw the beam effect, only the positions.*/
public void drawBuildRequests(){ public void drawBuildRequests(){
synchronized(getPlaceQueue()){ for(BuildRequest request : getPlaceQueue()){
for(BuildRequest request : getPlaceQueue()){ if(getCurrentRequest() == request) continue;
if(getCurrentRequest() == request) continue;
if(request.breaking){ if(request.breaking){
Block block = world.tile(request.x, request.y).target().block(); Block block = world.tile(request.x, request.y).target().block();
//draw removal request //draw removal request
Lines.stroke(2f); Lines.stroke(2f);
Draw.color(Palette.removeBack); Draw.color(Palette.removeBack);
float rad = Mathf.absin(Timers.time(), 7f, 1f) + block.size * tilesize / 2f - 1; float rad = Mathf.absin(Timers.time(), 7f, 1f) + block.size * tilesize / 2f - 1;
Lines.square( Lines.square(
request.x * tilesize + block.offset(), request.x * tilesize + block.offset(),
request.y * tilesize + block.offset() - 1, request.y * tilesize + block.offset() - 1,
rad); rad);
Draw.color(Palette.remove); Draw.color(Palette.remove);
Lines.square( Lines.square(
request.x * tilesize + block.offset(), request.x * tilesize + block.offset(),
request.y * tilesize + block.offset(), request.y * tilesize + block.offset(),
rad); rad);
}else{ }else{
//draw place request //draw place request
Lines.stroke(2f); Lines.stroke(2f);
Draw.color(Palette.accentBack); Draw.color(Palette.accentBack);
float rad = Mathf.absin(Timers.time(), 7f, 1f) - 2f + request.recipe.result.size * tilesize / 2f; float rad = Mathf.absin(Timers.time(), 7f, 1f) - 2f + request.recipe.result.size * tilesize / 2f;
Lines.square( Lines.square(
request.x * tilesize + request.recipe.result.offset(), request.x * tilesize + request.recipe.result.offset(),
request.y * tilesize + request.recipe.result.offset() - 1, request.y * tilesize + request.recipe.result.offset() - 1,
rad); rad);
Draw.color(Palette.accent); Draw.color(Palette.accent);
Lines.square( Lines.square(
request.x * tilesize + request.recipe.result.offset(), request.x * tilesize + request.recipe.result.offset(),
request.y * tilesize + request.recipe.result.offset(), request.y * tilesize + request.recipe.result.offset(),
rad); rad);
}
} }
Draw.reset();
} }
Draw.reset();
} }
//endregion //endregion
@@ -512,14 +510,14 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
achievedFlight = true; achievedFlight = true;
} }
if(boostHeat <= liftoffBoost + 0.05f && achievedFlight){ if(boostHeat <= liftoffBoost + 0.05f && achievedFlight && !mech.flying){
if(tile != null){ if(tile != null){
if(mech.shake > 1f){ if(mech.shake > 1f){
Effects.shake(mech.shake, mech.shake, this); Effects.shake(mech.shake, mech.shake, this);
} }
Effects.effect(UnitFx.unitLand, tile.floor().minimapColor, x, y, tile.floor().isLiquid ? 1f : 0.5f); Effects.effect(UnitFx.unitLand, tile.floor().minimapColor, x, y, tile.floor().isLiquid ? 1f : 0.5f);
} }
if(!mech.flying) mech.onLand(this); mech.onLand(this);
achievedFlight = false; achievedFlight = false;
} }
@@ -259,27 +259,25 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
@Override @Override
public void update(){ public void update(){
synchronized(Tile.tileSetLock){ //TODO better smoke effect, this one is awful
//TODO better smoke effect, this one is awful if(health != 0 && health < tile.block().health && !(tile.block() instanceof Wall) &&
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 * Timers.delta() * (1f - health / tile.block().health))){
Effects.effect(Fx.smoke, x + Mathf.range(4), y + Mathf.range(4)); Effects.effect(Fx.smoke, x + Mathf.range(4), y + Mathf.range(4));
} }
timeScaleDuration -= Timers.delta(); timeScaleDuration -= Timers.delta();
if(timeScaleDuration <= 0f || !tile.block().canOverdrive){ if(timeScaleDuration <= 0f || !tile.block().canOverdrive){
timeScale = 1f; timeScale = 1f;
} }
if(health <= 0){ if(health <= 0){
onDeath(); onDeath();
} }
Block previous = tile.block(); Block previous = tile.block();
tile.block().update(tile); tile.block().update(tile);
if(tile.block() == previous && cons != null){ if(tile.block() == previous && cons != null){
cons.update(this); cons.update(this);
}
} }
} }
@@ -278,7 +278,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
drownTime = Mathf.clamp(drownTime); drownTime = Mathf.clamp(drownTime);
if(drownTime >= 0.999f){ if(drownTime >= 0.999f && !Net.client()){
damage(health + 1); damage(health + 1);
} }
@@ -88,14 +88,13 @@ public interface BuilderTrait extends Entity{
} }
default void readBuilding(DataInput input, boolean applyChanges) throws IOException{ default void readBuilding(DataInput input, boolean applyChanges) throws IOException{
synchronized(getPlaceQueue()){ if(applyChanges) getPlaceQueue().clear();
if(applyChanges) getPlaceQueue().clear();
byte type = input.readByte(); byte type = input.readByte();
if(type != -1){ if(type != -1){
int position = input.readInt(); int position = input.readInt();
float progress = input.readFloat(); float progress = input.readFloat();
BuildRequest request; BuildRequest request;
if(type == 1){ //remove if(type == 1){ //remove
request = new BuildRequest(Pos.x(position), Pos.y(position)); request = new BuildRequest(Pos.x(position), Pos.y(position));
@@ -105,13 +104,12 @@ public interface BuilderTrait extends Entity{
request = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.recipe(recipe)); request = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.recipe(recipe));
} }
request.progress = progress; request.progress = progress;
if(applyChanges){ if(applyChanges){
getPlaceQueue().addLast(request); getPlaceQueue().addLast(request);
}else if(isBuilding()){ }else if(isBuilding()){
getCurrentRequest().progress = progress; getCurrentRequest().progress = progress;
}
} }
} }
} }
@@ -126,13 +124,11 @@ public interface BuilderTrait extends Entity{
* Otherwise, a new place request is added to the queue. * Otherwise, a new place request is added to the queue.
*/ */
default void replaceBuilding(int x, int y, int rotation, Recipe recipe){ default void replaceBuilding(int x, int y, int rotation, Recipe recipe){
synchronized(getPlaceQueue()){ for(BuildRequest request : getPlaceQueue()){
for(BuildRequest request : getPlaceQueue()){ if(request.x == x && request.y == y){
if(request.x == x && request.y == y){ clearBuilding();
clearBuilding(); addBuildRequest(request);
addBuildRequest(request); return;
return;
}
} }
} }
@@ -146,18 +142,16 @@ public interface BuilderTrait extends Entity{
/**Add another build requests to the tail of the queue, if it doesn't exist there yet.*/ /**Add another build requests to the tail of the queue, if it doesn't exist there yet.*/
default void addBuildRequest(BuildRequest place){ default void addBuildRequest(BuildRequest place){
synchronized(getPlaceQueue()){ for(BuildRequest request : getPlaceQueue()){
for(BuildRequest request : getPlaceQueue()){ if(request.x == place.x && request.y == place.y){
if(request.x == place.x && request.y == place.y){ return;
return;
}
} }
Tile tile = world.tile(place.x, place.y);
if(tile != null && tile.entity instanceof BuildEntity){
place.progress = tile.<BuildEntity>entity().progress;
}
getPlaceQueue().addLast(place);
} }
Tile tile = world.tile(place.x, place.y);
if(tile != null && tile.entity instanceof BuildEntity){
place.progress = tile.<BuildEntity>entity().progress;
}
getPlaceQueue().addLast(place);
} }
/** /**
@@ -165,9 +159,7 @@ public interface BuilderTrait extends Entity{
* May return null. * May return null.
*/ */
default BuildRequest getCurrentRequest(){ default BuildRequest getCurrentRequest(){
synchronized(getPlaceQueue()){ return getPlaceQueue().size == 0 ? null : getPlaceQueue().first();
return getPlaceQueue().size == 0 ? null : getPlaceQueue().first();
}
} }
/** /**
@@ -279,18 +271,15 @@ public interface BuilderTrait extends Entity{
/**Draw placement effects for an entity. This includes mining*/ /**Draw placement effects for an entity. This includes mining*/
default void drawBuilding(Unit unit){ default void drawBuilding(Unit unit){
BuildRequest request; BuildRequest request;
if(!isBuilding()){
synchronized(getPlaceQueue()){ if(getMineTile() != null){
if(!isBuilding()){ drawMining(unit);
if(getMineTile() != null){
drawMining(unit);
}
return;
} }
return;
request = getCurrentRequest();
} }
request = getCurrentRequest();
Tile tile = world.tile(request.x, request.y); Tile tile = world.tile(request.x, request.y);
if(unit.distanceTo(tile) > placeDistance){ if(unit.distanceTo(tile) > placeDistance){
@@ -28,10 +28,7 @@ import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.*;
import io.anuke.ucore.util.Geometry;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Timer;
import java.io.DataInput; import java.io.DataInput;
import java.io.DataOutput; import java.io.DataOutput;
@@ -316,8 +313,8 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
if(target != null) behavior(); if(target != null) behavior();
if(!isWave && !isFlying()){ if(!isWave && !isFlying()){
x = Mathf.clamp(x, 0, world.width() * tilesize); x = Mathf.clamp(x, tilesize/2f, world.width() * tilesize - tilesize/2f);
y = Mathf.clamp(y, 0, world.height() * tilesize); y = Mathf.clamp(y, tilesize/2f, world.height() * tilesize - tilesize/2f);
} }
} }
@@ -1,15 +1,21 @@
package io.anuke.mindustry.entities.units.types; package io.anuke.mindustry.entities.units.types;
import com.badlogic.gdx.math.Vector2; 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.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.Predict;
import io.anuke.mindustry.entities.Unit;
import io.anuke.mindustry.entities.traits.TargetTrait; 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.FlyingUnit;
import io.anuke.mindustry.entities.units.UnitCommand; import io.anuke.mindustry.entities.units.UnitCommand;
import io.anuke.mindustry.entities.units.UnitState; import io.anuke.mindustry.entities.units.UnitState;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.type.AmmoType; import io.anuke.mindustry.type.AmmoType;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
import java.io.DataInput; import java.io.DataInput;
@@ -22,7 +28,8 @@ import static io.anuke.mindustry.Vars.players;
public class AlphaDrone extends FlyingUnit { public class AlphaDrone extends FlyingUnit {
static final float followDistance = 80f; static final float followDistance = 80f;
public Unit leader; public Player leader;
public final UnitState attack = new UnitState() { public final UnitState attack = new UnitState() {
@Override @Override
public void update() { public void update() {
@@ -32,15 +39,18 @@ public class AlphaDrone extends FlyingUnit {
} }
TargetTrait last = target; TargetTrait last = target;
target = leader; target = leader;
if(last == null){ if(last == null){
circle(50f); circle(leader.isShooting ? 60f : 0f);
} }
target = last; target = last;
if(distanceTo(leader) < followDistance){ if(distanceTo(leader) < followDistance){
targetClosest(); targetClosest();
}else{ }else{
target = null; target = null;
} }
if(target != null){ if(target != null){
attack(50f); attack(50f);
@@ -51,9 +61,20 @@ public class AlphaDrone extends FlyingUnit {
getWeapon().update(AlphaDrone.this, to.x, to.y); getWeapon().update(AlphaDrone.this, to.x, to.y);
} }
} }
if(!leader.isShooting && distanceTo(leader) < 8f){
Call.onAlphaDroneFade(AlphaDrone.this);
}
} }
}; };
@Remote(called = Loc.server)
public static void onAlphaDroneFade(BaseUnit drone){
if(drone == null) return;
drone.remove();
Effects.effect(UnitFx.pickup, drone);
}
@Override @Override
public void onCommand(UnitCommand command){ public void onCommand(UnitCommand command){
//nuh //nuh
@@ -40,12 +40,11 @@ import static io.anuke.mindustry.Vars.unitGroups;
import static io.anuke.mindustry.Vars.world; import static io.anuke.mindustry.Vars.world;
public class Drone extends FlyingUnit implements BuilderTrait{ public class Drone extends FlyingUnit implements BuilderTrait{
protected static float discoverRange = 120f;
protected static int timerRepairEffect = timerIndex++; protected static int timerRepairEffect = timerIndex++;
protected Item targetItem; protected Item targetItem;
protected Tile mineTile; protected Tile mineTile;
protected Queue<BuildRequest> placeQueue = new ThreadQueue<>(); protected Queue<BuildRequest> placeQueue = new Queue<>();
protected boolean isBreaking; protected boolean isBreaking;
public final UnitState public final UnitState
@@ -250,14 +249,12 @@ public class Drone extends FlyingUnit implements BuilderTrait{
for(BaseUnit unit : group.all()){ for(BaseUnit unit : group.all()){
if(unit instanceof Drone){ if(unit instanceof Drone){
Drone drone = (Drone)unit; Drone drone = (Drone)unit;
synchronized(drone.getPlaceQueue()){ if(drone.isBuilding()){
if(drone.isBuilding()){ //stop building if opposite building begins.
//stop building if opposite building begins. BuildRequest req = drone.getCurrentRequest();
BuildRequest req = drone.getCurrentRequest(); if(req.breaking != event.breaking && req.x == event.tile.x && req.y == event.tile.y){
if(req.breaking != event.breaking && req.x == event.tile.x && req.y == event.tile.y){ drone.clearBuilding();
drone.clearBuilding(); drone.setState(drone.repair);
drone.setState(drone.repair);
}
} }
} }
@@ -319,6 +316,10 @@ public class Drone extends FlyingUnit implements BuilderTrait{
TileEntity entity = (TileEntity) target; TileEntity entity = (TileEntity) target;
entity.health += type.healSpeed * Timers.delta(); entity.health += type.healSpeed * Timers.delta();
entity.health = Mathf.clamp(entity.health, 0, entity.tile.block().health); entity.health = Mathf.clamp(entity.health, 0, entity.tile.block().health);
if(timer.get(timerRepairEffect, 30)){
Effects.effect(BlockFx.healBlockFull, Palette.heal, entity.x, entity.y, entity.tile.block().size);
}
} }
updateBuilding(this); updateBuilding(this);
@@ -19,14 +19,6 @@ public class Unlocks{
Settings.setSerializer(ContentType.class, (stream, t) -> stream.writeInt(t.ordinal()), stream -> ContentType.values()[stream.readInt()]); Settings.setSerializer(ContentType.class, (stream, t) -> stream.writeInt(t.ordinal()), stream -> ContentType.values()[stream.readInt()]);
} }
/**Handles the event of content being used by either the player or some block.*/
public void handleContentUsed(UnlockableContent content){
if(world.getSector() != null){
world.getSector().currentMission().onContentUsed(content);
}
unlockContent(content);
}
/** Returns whether or not this piece of content is unlocked yet.*/ /** Returns whether or not this piece of content is unlocked yet.*/
public boolean isUnlocked(UnlockableContent content){ public boolean isUnlocked(UnlockableContent content){
return rootSet().isUnlocked(content) || currentSet().isUnlocked(content); return rootSet().isUnlocked(content) || currentSet().isUnlocked(content);
@@ -106,32 +106,29 @@ public class BlockRenderer{
for(int x = minx; x <= maxx; x++){ for(int x = minx; x <= maxx; x++){
for(int y = miny; y <= maxy; y++){ for(int y = miny; y <= maxy; y++){
boolean expanded = (Math.abs(x - avgx) > rangex || Math.abs(y - avgy) > rangey); boolean expanded = (Math.abs(x - avgx) > rangex || Math.abs(y - avgy) > rangey);
Tile tile = world.rawTile(x, y);
synchronized(Tile.tileSetLock){ if(tile != null){
Tile tile = world.rawTile(x, y); Block block = tile.block();
Team team = tile.getTeam();
if(tile != null){ if(!expanded && block != Blocks.air && world.isAccessible(x, y)){
Block block = tile.block(); tile.block().drawShadow(tile);
Team team = tile.getTeam(); }
if(!expanded && block != Blocks.air && world.isAccessible(x, y)){ if(block != Blocks.air){
tile.block().drawShadow(tile); if(!expanded){
addRequest(tile, Layer.block);
teamChecks.add(team.ordinal());
} }
if(block != Blocks.air){ if(block.expanded || !expanded){
if(!expanded){ if(block.layer != null && block.isLayer(tile)){
addRequest(tile, Layer.block); addRequest(tile, block.layer);
teamChecks.add(team.ordinal());
} }
if(block.expanded || !expanded){ if(block.layer2 != null && block.isLayer2(tile)){
if(block.layer != null && block.isLayer(tile)){ addRequest(tile, block.layer2);
addRequest(tile, block.layer);
}
if(block.layer2 != null && block.isLayer2(tile)){
addRequest(tile, block.layer2);
}
} }
} }
} }
@@ -171,16 +168,14 @@ public class BlockRenderer{
layerBegins(req.layer); layerBegins(req.layer);
} }
synchronized(Tile.tileSetLock){ Block block = req.tile.block();
Block block = req.tile.block();
if(req.layer == Layer.block){ if(req.layer == Layer.block){
block.draw(req.tile); block.draw(req.tile);
}else if(req.layer == block.layer){ }else if(req.layer == block.layer){
block.drawLayer(req.tile); block.drawLayer(req.tile);
}else if(req.layer == block.layer2){ }else if(req.layer == block.layer2){
block.drawLayer2(req.tile); block.drawLayer2(req.tile);
}
} }
lastLayer = req.layer; lastLayer = req.layer;
@@ -199,17 +194,16 @@ public class BlockRenderer{
BlockRequest req = requests.get(index); BlockRequest req = requests.get(index);
if(req.tile.getTeam() != team) continue; if(req.tile.getTeam() != team) continue;
synchronized(Tile.tileSetLock){ Block block = req.tile.block();
Block block = req.tile.block();
if(req.layer == Layer.block){ if(req.layer == Layer.block){
block.draw(req.tile); block.draw(req.tile);
}else if(req.layer == block.layer){ }else if(req.layer == block.layer){
block.drawLayer(req.tile); block.drawLayer(req.tile);
}else if(req.layer == block.layer2){ }else if(req.layer == block.layer2){
block.drawLayer2(req.tile); block.drawLayer2(req.tile);
}
} }
} }
} }
@@ -74,20 +74,18 @@ public class MinimapRenderer implements Disposable{
dx = Mathf.clamp(dx, sz, world.width() - sz); dx = Mathf.clamp(dx, sz, world.width() - sz);
dy = Mathf.clamp(dy, sz, world.height() - sz); dy = Mathf.clamp(dy, sz, world.height() - sz);
synchronized(units){ rect.set((dx - sz) * tilesize, (dy - sz) * tilesize, sz * 2 * tilesize, sz * 2 * tilesize);
rect.set((dx - sz) * tilesize, (dy - sz) * tilesize, sz * 2 * tilesize, sz * 2 * tilesize); Graphics.beginClip(x, y, w, h);
Graphics.beginClip(x, y, w, h);
for(Unit unit : units){ for(Unit unit : units){
float rx = (unit.x - rect.x) / rect.width * w, ry = (unit.y - rect.y) / rect.width * h; float rx = (unit.x - rect.x) / rect.width * w, ry = (unit.y - rect.y) / rect.width * h;
Draw.color(unit.getTeam().color); Draw.color(unit.getTeam().color);
Draw.rect("white", x + rx, y + ry, w / (sz * 2), h / (sz * 2)); Draw.rect("white", x + rx, y + ry, w / (sz * 2), h / (sz * 2));
}
Draw.color();
Graphics.endClip();
} }
Draw.color();
Graphics.endClip();
} }
public TextureRegion getRegion(){ public TextureRegion getRegion(){
@@ -128,11 +126,9 @@ public class MinimapRenderer implements Disposable{
dx = Mathf.clamp(dx, sz, world.width() - sz); dx = Mathf.clamp(dx, sz, world.width() - sz);
dy = Mathf.clamp(dy, sz, world.height() - sz); dy = Mathf.clamp(dy, sz, world.height() - sz);
synchronized(units){ rect.set((dx - sz) * tilesize, (dy - sz) * tilesize, sz * 2 * tilesize, sz * 2 * tilesize);
rect.set((dx - sz) * tilesize, (dy - sz) * tilesize, sz * 2 * tilesize, sz * 2 * tilesize); units.clear();
units.clear(); Units.getNearby(rect, units::add);
Units.getNearby(rect, units::add);
}
} }
private int colorFor(Tile tile){ private int colorFor(Tile tile){
@@ -53,10 +53,7 @@ public class OverlayRenderer{
//draw config selected block //draw config selected block
if(input.frag.config.isShown()){ if(input.frag.config.isShown()){
Tile tile = input.frag.config.getSelectedTile(); Tile tile = input.frag.config.getSelectedTile();
tile.block().drawConfigure(tile);
synchronized(Tile.tileSetLock){
tile.block().drawConfigure(tile);
}
} }
input.drawTop(); input.drawTop();
@@ -113,53 +110,52 @@ public class OverlayRenderer{
Draw.reset(); Draw.reset();
} }
synchronized(Tile.tileSetLock){ Block block = target.block();
Block block = target.block(); TileEntity entity = target.entity;
TileEntity entity = target.entity;
if(entity != null){ if(entity != null){
int[] values = {0, 0}; int[] values = {0, 0};
boolean[] doDraw = {false}; boolean[] doDraw = {false};
Runnable drawbars = () -> { Runnable drawbars = () -> {
for(BlockBar bar : block.bars.list()){ for(BlockBar bar : block.bars.list()){
float offset = Mathf.sign(bar.top) * (block.size / 2f * tilesize + 2f + (bar.top ? values[0] : values[1])); float offset = Mathf.sign(bar.top) * (block.size / 2f * tilesize + 2f + (bar.top ? values[0] : values[1]));
float value = bar.value.get(target); float value = bar.value.get(target);
if(MathUtils.isEqual(value, -1f)) continue; if(MathUtils.isEqual(value, -1f)) continue;
if(doDraw[0]){ if(doDraw[0]){
drawBar(bar.type.color, target.drawx(), target.drawy() + offset, value); drawBar(bar.type.color, target.drawx(), target.drawy() + offset, value);
}
if(bar.top)
values[0]++;
else
values[1]++;
} }
};
drawbars.run(); if(bar.top)
values[0]++;
if(values[0] > 0){ else
drawEncloser(target.drawx(), target.drawy() + block.size * tilesize / 2f + 2f, values[0]); values[1]++;
} }
};
if(values[1] > 0){ drawbars.run();
drawEncloser(target.drawx(), target.drawy() - block.size * tilesize / 2f - 2f - values[1], values[1]);
}
doDraw[0] = true; if(values[0] > 0){
values[0] = 0; drawEncloser(target.drawx(), target.drawy() + block.size * tilesize / 2f + 2f, values[0]);
values[1] = 1;
drawbars.run();
} }
if(values[1] > 0){
drawEncloser(target.drawx(), target.drawy() - block.size * tilesize / 2f - 2f - values[1], values[1]);
}
target.block().drawSelect(target); doDraw[0] = true;
values[0] = 0;
values[1] = 1;
drawbars.run();
} }
target.block().drawSelect(target);
} }
} }
@@ -3,7 +3,6 @@ package io.anuke.mindustry.graphics;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.FloatArray;
import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
@@ -168,9 +167,7 @@ public class Shaders{
} }
public static class Shield extends Shader{ public static class Shield extends Shader{
public static final int MAX_HITS = 3 * 64; //public Color color = new Color();
public Color color = new Color();
public FloatArray hits = new FloatArray();
public Shield(){ public Shield(){
super("shield", "default"); super("shield", "default");
@@ -179,12 +176,9 @@ public class Shaders{
@Override @Override
public void apply(){ public void apply(){
float scaling = Core.cameraScale / 4f / Core.camera.zoom; float scaling = Core.cameraScale / 4f / Core.camera.zoom;
if(hits.size > 0){
shader.setUniform3fv("u_hits[0]", hits.items, 0, Math.min(hits.size, MAX_HITS));
shader.setUniformi("u_hitamount", Math.min(hits.size, MAX_HITS) / 3);
}
shader.setUniformf("u_dp", Unit.dp.scl(1f)); shader.setUniformf("u_dp", Unit.dp.scl(1f));
shader.setUniformf("u_color", color); //shader.setUniformf("u_color", color);
shader.setUniformf("u_time", Timers.time() / Unit.dp.scl(1f)); shader.setUniformf("u_time", Timers.time() / Unit.dp.scl(1f));
shader.setUniformf("u_scaling", scaling); shader.setUniformf("u_scaling", scaling);
shader.setUniformf("u_offset", shader.setUniformf("u_offset",
@@ -22,7 +22,7 @@ public class Trail{
this.length = length; this.length = length;
} }
public synchronized void update(float curx, float cury){ public void update(float curx, float cury){
if(Vector2.dst(curx, cury, lastX, lastY) >= maxJump){ if(Vector2.dst(curx, cury, lastX, lastY) >= maxJump){
points.clear(); points.clear();
} }
@@ -39,11 +39,11 @@ public class Trail{
lastY = cury; lastY = cury;
} }
public synchronized void clear(){ public void clear(){
points.clear(); points.clear();
} }
public synchronized void draw(Color color, float stroke){ public void draw(Color color, float stroke){
Draw.color(color); Draw.color(color);
for(int i = 0; i < points.size - 2; i += 2){ for(int i = 0; i < points.size - 2; i += 2){
@@ -430,7 +430,7 @@ public class MobileInput extends InputHandler implements GestureListener{
@Override @Override
public boolean touchDown(int screenX, int screenY, int pointer, int button){ public boolean touchDown(int screenX, int screenY, int pointer, int button){
if(state.is(State.menu)) return false; if(state.is(State.menu) || player.isDead()) return false;
//get tile on cursor //get tile on cursor
Tile cursor = tileAt(screenX, screenY); Tile cursor = tileAt(screenX, screenY);
@@ -519,7 +519,7 @@ public class MobileInput extends InputHandler implements GestureListener{
@Override @Override
public boolean longPress(float x, float y){ public boolean longPress(float x, float y){
if(state.is(State.menu) || mode == none) return false; if(state.is(State.menu) || mode == none || player.isDead()) return false;
//get tile on cursor //get tile on cursor
Tile cursor = tileAt(x, y); Tile cursor = tileAt(x, y);
@@ -535,7 +535,7 @@ public class MobileInput extends InputHandler implements GestureListener{
if(mode == breaking){ if(mode == breaking){
Effects.effect(Fx.tapBlock, cursor.worldx(), cursor.worldy(), 1f); Effects.effect(Fx.tapBlock, cursor.worldx(), cursor.worldy(), 1f);
}else{ }else if(recipe != null){
Effects.effect(Fx.tapBlock, cursor.worldx() + recipe.result.offset(), cursor.worldy() + recipe.result.offset(), recipe.result.size); Effects.effect(Fx.tapBlock, cursor.worldx() + recipe.result.offset(), cursor.worldy() + recipe.result.offset(), recipe.result.size);
} }
@@ -595,7 +595,7 @@ public class MobileInput extends InputHandler implements GestureListener{
@Override @Override
public void update(){ public void update(){
if(state.is(State.menu)){ if(state.is(State.menu) || player.isDead()){
selection.clear(); selection.clear();
removals.clear(); removals.clear();
mode = none; mode = none;
+3 -11
View File
@@ -47,23 +47,15 @@ public class MapIO{
data.position(0, 0); data.position(0, 0);
TileDataMarker marker = data.newDataMarker(); TileDataMarker marker = data.newDataMarker();
Color color = new Color();
for(int y = 0; y < data.height(); y++){ for(int y = 0; y < data.height(); y++){
for(int x = 0; x < data.width(); x++){ for(int x = 0; x < data.width(); x++){
data.read(marker); data.read(marker);
byte elev = y >= data.height() - 1 ? 0 : data.read(x, y + 1, DataPosition.elevation);
Block floor = content.block(marker.floor); Block floor = content.block(marker.floor);
Block wall = content.block(marker.wall); Block wall = content.block(marker.wall);
int wallc = ColorMapper.getBlockColor(wall); int color = ColorMapper.colorFor(floor, wall, Team.all[marker.team], marker.elevation + 1, elev > marker.elevation ? (byte)(1 << 6) : (byte)0);
if(wallc == 0 && (wall.update || wall.solid || wall.breakable)) wallc = Team.all[marker.team].intColor; pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, color);
wallc = wallc == 0 ? ColorMapper.getBlockColor(floor) : wallc;
if(marker.elevation > 0){
float scaling = 1f + marker.elevation / 8f;
color.set(wallc);
color.mul(scaling, scaling, scaling, 1f);
wallc = Color.rgba8888(color);
}
pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, wallc);
} }
} }
@@ -2,6 +2,7 @@ package io.anuke.mindustry.maps;
import com.badlogic.gdx.utils.IntIntMap; import com.badlogic.gdx.utils.IntIntMap;
import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.ucore.util.Bundles;
public class MapMeta{ public class MapMeta{
public final int version; public final int version;
@@ -18,15 +19,19 @@ public class MapMeta{
} }
public String author(){ public String author(){
return tags.get("author", "unknown"); return tag("author");
} }
public String description(){ public String description(){
return tags.get("description", "unknown"); return tag("description");
} }
public String name(){ public String name(){
return tags.get("name", "unknown"); return tag("name");
}
public String tag(String name){
return tags.containsKey(name) && !tags.get(name).trim().isEmpty() ? tags.get(name): Bundles.get("text.unknown");
} }
public boolean hasOreGen(){ public boolean hasOreGen(){
@@ -23,10 +23,10 @@ public class SectorPresets{
public SectorPresets(){ public SectorPresets(){
//base tutorial mission (disabled) //base tutorial mission
/*add(new SectorPreset(0, 0, add(new SectorPreset(0, 0,
TutorialSector.getMissions(), TutorialSector.getMissions(),
Array.with(Items.copper, Items.coal, Items.lead)));*/ Array.with(Items.copper, Items.coal, Items.lead)));
//command center mission //command center mission
add(new SectorPreset(0, 1, add(new SectorPreset(0, 1,
@@ -56,7 +56,8 @@ public class SectorPresets{
Missions.blockRecipe(ProductionBlocks.waterExtractor), Missions.blockRecipe(ProductionBlocks.waterExtractor),
new ContentMission(Items.biomatter), new ContentMission(Items.biomatter),
Missions.blockRecipe(CraftingBlocks.biomatterCompressor), Missions.blockRecipe(CraftingBlocks.biomatterCompressor),
new ContentMission(Liquids.oil) new ContentMission(Liquids.oil),
new BattleMission()
), ),
Array.with(Items.copper, Items.lead, Items.coal, Items.titanium))); Array.with(Items.copper, Items.lead, Items.coal, Items.titanium)));
} }
@@ -69,6 +70,8 @@ public class SectorPresets{
return presets.get(x, y); return presets.get(x, y);
} }
public GridMap<SectorPreset> getPresets() { return presets; }
private void add(SectorPreset preset){ private void add(SectorPreset preset){
presets.put(preset.x, preset.y, preset); presets.put(preset.x, preset.y, preset);
orePresets.put(preset.x, preset.y, preset.ores); orePresets.put(preset.x, preset.y, preset.ores);
@@ -41,7 +41,7 @@ public class Sectors{
private final AsyncExecutor executor = new AsyncExecutor(6); private final AsyncExecutor executor = new AsyncExecutor(6);
public void playSector(Sector sector){ public void playSector(Sector sector){
if(sector.hasSave() && SaveIO.breakingVersions.contains(sector.getSave().getBuild())){ if(!headless && sector.hasSave() && SaveIO.breakingVersions.contains(sector.getSave().getBuild())){
sector.getSave().delete(); sector.getSave().delete();
ui.showInfo("$text.save.old"); ui.showInfo("$text.save.old");
} }
@@ -88,8 +88,6 @@ public class Sectors{
public Difficulty getDifficulty(Sector sector){ public Difficulty getDifficulty(Sector sector){
if(sector.difficulty == 0){ if(sector.difficulty == 0){
//yes, this means hard tutorial difficulty
//(((have fun)))
return Difficulty.hard; return Difficulty.hard;
}else if(sector.difficulty < 4){ }else if(sector.difficulty < 4){
return Difficulty.normal; return Difficulty.normal;
@@ -158,7 +156,7 @@ public class Sectors{
} }
grid.clear(); grid.clear();
Array<Sector> out = Settings.getObject("sectors", Array.class, Array::new); Array<Sector> out = Settings.getObject("sector-data-2", Array.class, Array::new);
for(Sector sector : out){ for(Sector sector : out){
@@ -187,7 +185,7 @@ public class Sectors{
} }
} }
Settings.putObject("sectors", out); Settings.putObject("sector-data-2", out);
Settings.save(); Settings.save();
} }
@@ -229,7 +227,7 @@ public class Sectors{
private void generate(Sector sector){ private void generate(Sector sector){
//50% chance to get a wave mission //50% chance to get a wave mission
if(Mathf.randomSeed(sector.getSeed() + 6) < 0.5){ if(Mathf.randomSeed(sector.getSeed() + 7) < 0.5){
//recipe mission (maybe) //recipe mission (maybe)
addRecipeMission(sector, 3); addRecipeMission(sector, 3);
sector.missions.add(new WaveMission(sector.difficulty*5 + Mathf.randomSeed(sector.getSeed(), 1, 4)*5)); sector.missions.add(new WaveMission(sector.difficulty*5 + Mathf.randomSeed(sector.getSeed(), 1, 4)*5));
@@ -2,12 +2,15 @@ package io.anuke.mindustry.maps;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.content.Items; import io.anuke.mindustry.content.Items;
import io.anuke.mindustry.content.UnitTypes; import io.anuke.mindustry.content.blocks.CraftingBlocks;
import io.anuke.mindustry.content.blocks.*; import io.anuke.mindustry.content.blocks.ProductionBlocks;
import io.anuke.mindustry.maps.generation.Generation; import io.anuke.mindustry.content.blocks.StorageBlocks;
import io.anuke.mindustry.maps.missions.*; 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 io.anuke.mindustry.world.Block;
import io.anuke.ucore.util.Bundles;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@@ -16,7 +19,7 @@ public class TutorialSector{
private static int droneIndex; private static int droneIndex;
public static Array<Mission> getMissions(){ public static Array<Mission> getMissions(){
/*
Array<Mission> missions = Array.with( Array<Mission> missions = Array.with(
new ItemMission(Items.copper, 60).setMessage("$tutorial.begin"), new ItemMission(Items.copper, 60).setMessage("$tutorial.begin"),
@@ -30,7 +33,8 @@ public class TutorialSector{
//TODO fill turret with items mission //TODO fill turret with items mission
//new BlockMission(ProductionBlocks.mechanicalDrill).setMessage("$tutorial.drillturret"), //new BlockMission(ProductionBlocks.mechanicalDrill).setMessage("$tutorial.drillturret"),
new WaveMission(2).setMessage("$tutorial.waves"), // 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.lead, 150).setMessage("$tutorial.lead"),
new ItemMission(Items.copper, 250).setMessage("$tutorial.morecopper"), new ItemMission(Items.copper, 250).setMessage("$tutorial.morecopper"),
@@ -82,9 +86,21 @@ public class TutorialSector{
droneIndex = i; droneIndex = i;
break; break;
} }
} }*/
return missions; 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(){ public static boolean supressDrone(){
@@ -57,6 +57,7 @@ public class FortressGenerator{
void gen(){ void gen(){
gen.setBlock(enemyX, enemyY, StorageBlocks.core, team); 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 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); float dscl2 = Mathf.clamp(0.5f + gen.sector.difficulty / 20f + gen.random.range(0.1f), 0f, 1.5f);
@@ -312,7 +312,7 @@ public class WorldGenerator{
+ sim3.octaveNoise2D(detailed ? 12 : 9, 0.6, 1f / 1100f, x - 120, y); + sim3.octaveNoise2D(detailed ? 12 : 9, 0.6, 1f / 1100f, x - 120, y);
double lake = sim2.octaveNoise2D(1, 1, 1f / 110f, x, y); double lake = sim2.octaveNoise2D(1, 1, 1f / 110f, x, y);
elevation -= lake/3f; elevation -= Math.pow(lake + 0.15, 5);
int lerpDst = 20; int lerpDst = 20;
lerpDst *= lerpDst; lerpDst *= lerpDst;
@@ -330,9 +330,9 @@ public class WorldGenerator{
} }
} }
if(elevation < 0.7 || lake > 0.96){ if(elevation < 0.7){
floor = Blocks.deepwater; floor = Blocks.deepwater;
}else if(elevation < 0.79 || lake > 0.948){ }else if(elevation < 0.79){
floor = Blocks.water; floor = Blocks.water;
}else if(elevation < 0.85){ }else if(elevation < 0.85){
floor = Blocks.sand; floor = Blocks.sand;
@@ -12,8 +12,24 @@ import io.anuke.ucore.util.Bundles;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
public class BattleMission extends Mission{ public class BattleMission extends MissionWithStartingCore{
final int spacing = 30; 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 @Override
public String getIcon(){ public String getIcon(){
@@ -37,7 +53,7 @@ public class BattleMission extends Mission{
@Override @Override
public void generate(Generation gen){ public void generate(Generation gen){
generateCoreAt(gen, 50, 50, defaultTeam); generateCoreAtFirstSpawnPoint(gen, defaultTeam);
if(state.teams.get(defaultTeam).cores.size == 0){ if(state.teams.get(defaultTeam).cores.size == 0){
return; return;
@@ -1,15 +0,0 @@
package io.anuke.mindustry.maps.missions;
import io.anuke.mindustry.Vars;
/**A mission that just displays some text.*/
public class MessageMission extends ActionMission{
public MessageMission(String text){
super(() -> {
if(!Vars.headless){
Vars.ui.showInfo(text);
}
});
}
}
@@ -100,10 +100,4 @@ public abstract class Mission{
} }
public void generate(Generation gen){} public void generate(Generation gen){}
public void generateCoreAt(Generation gen, int coreX, int coreY, Team team){
gen.tiles[coreX][coreY].setBlock(StorageBlocks.core);
gen.tiles[coreX][coreY].setTeam(team);
state.teams.get(team).cores.add(gen.tiles[coreX][coreY]);
}
} }
@@ -0,0 +1,61 @@
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<GridPoint2> 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);
}
/**
* 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<GridPoint2> getSpawnPoints(Generation gen){
if(this.customStartingPoint == null){
return Array.with(new GridPoint2(gen.width / 2, gen.height / 2));
}else{
return Array.with(this.customStartingPoint);
}
}
}
@@ -1,6 +1,5 @@
package io.anuke.mindustry.maps.missions; package io.anuke.mindustry.maps.missions;
import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.GameMode;
@@ -9,16 +8,31 @@ import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.Waves; import io.anuke.mindustry.game.Waves;
import io.anuke.mindustry.maps.Sector; import io.anuke.mindustry.maps.Sector;
import io.anuke.mindustry.maps.generation.Generation; import io.anuke.mindustry.maps.generation.Generation;
import io.anuke.mindustry.net.Net;
import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Bundles;
import static io.anuke.mindustry.Vars.state; import static io.anuke.mindustry.Vars.*;
import static io.anuke.mindustry.Vars.waveTeam;
import static io.anuke.mindustry.Vars.world;
public class WaveMission extends Mission{ public class WaveMission extends MissionWithStartingCore{
private final int target; 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){ 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; this.target = target;
} }
@@ -29,8 +43,7 @@ public class WaveMission extends Mission{
@Override @Override
public void generate(Generation gen){ public void generate(Generation gen){
int coreX = gen.width/2, coreY = gen.height/2; generateCoreAtFirstSpawnPoint(gen, Team.blue);
generateCoreAt(gen, coreX, coreY, Team.blue);
} }
@Override @Override
@@ -49,7 +62,7 @@ public class WaveMission extends Mission{
public String displayString(){ public String displayString(){
return state.wave > target ? return state.wave > target ?
Bundles.format( Bundles.format(
Vars.unitGroups[Vars.waveTeam.ordinal()].size() > 1 ? Vars.unitGroups[Vars.waveTeam.ordinal()].size() > 1 && !Net.client() ?
"text.mission.wave.enemies" : "text.mission.wave.enemies" :
"text.mission.wave.enemy", target, target, Vars.unitGroups[Vars.waveTeam.ordinal()].size()) : "text.mission.wave.enemy", target, target, Vars.unitGroups[Vars.waveTeam.ordinal()].size()) :
Bundles.format("text.mission.wave", state.wave, target, (int)(state.wavetime/60)); Bundles.format("text.mission.wave", state.wave, target, (int)(state.wavetime/60));
@@ -71,9 +84,4 @@ public class WaveMission extends Mission{
public boolean isComplete(){ public boolean isComplete(){
return state.wave > target && Vars.unitGroups[Vars.waveTeam.ordinal()].size() == 0; return state.wave > target && Vars.unitGroups[Vars.waveTeam.ordinal()].size() == 0;
} }
@Override
public Array<GridPoint2> getSpawnPoints(Generation gen){
return Array.with(new GridPoint2(gen.width/2, gen.height/2));
}
} }
+1 -1
View File
@@ -59,7 +59,7 @@ public class Net{
} }
String error = t.getMessage() == null ? "" : t.getMessage().toLowerCase(); String error = t.getMessage() == null ? "" : t.getMessage().toLowerCase();
String type = error.getClass().toString().toLowerCase(); String type = t.getClass().toString().toLowerCase();
if(error.equals("mismatch")){ if(error.equals("mismatch")){
error = Bundles.get("text.error.mismatch"); error = Bundles.get("text.error.mismatch");
+13 -15
View File
@@ -1,21 +1,17 @@
package io.anuke.mindustry.ui; package io.anuke.mindustry.ui;
import com.badlogic.gdx.graphics.Texture.TextureFilter; import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion;
import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.graphics.Shaders;
import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.scene.Element; import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.event.InputEvent; import io.anuke.ucore.scene.event.InputEvent;
import io.anuke.ucore.scene.event.InputListener; import io.anuke.ucore.scene.event.InputListener;
import io.anuke.ucore.scene.style.TextureRegionDrawable;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
import static io.anuke.mindustry.Vars.renderer; import static io.anuke.mindustry.Vars.*;
import static io.anuke.mindustry.Vars.showFog;
import static io.anuke.mindustry.Vars.world;
public class Minimap extends Table{ public class Minimap extends Table{
@@ -25,14 +21,15 @@ public class Minimap extends Table{
margin(5); margin(5);
marginBottom(10); marginBottom(10);
Image image = new Image(new TextureRegionDrawable(new TextureRegion())){ TextureRegion r = new TextureRegion();
Element elem = new Element(){
@Override @Override
public void draw(Batch batch, float parentAlpha){ public void draw(){
if(renderer.minimap.getRegion() == null) return; if(renderer.minimap.getRegion() == null) return;
TextureRegionDrawable draw = (TextureRegionDrawable) getDrawable(); Draw.crect(renderer.minimap.getRegion(), x, y, width, height);
draw.getRegion().setRegion(renderer.minimap.getRegion());
super.draw(batch, parentAlpha);
if(renderer.minimap.getTexture() != null){ if(renderer.minimap.getTexture() != null){
renderer.minimap.drawEntities(x, y, width, height); renderer.minimap.drawEntities(x, y, width, height);
} }
@@ -40,7 +37,7 @@ public class Minimap extends Table{
if(showFog){ if(showFog){
renderer.fog.getTexture().setFilter(TextureFilter.Nearest, TextureFilter.Nearest); renderer.fog.getTexture().setFilter(TextureFilter.Nearest, TextureFilter.Nearest);
TextureRegion r = draw.getRegion(); r.setRegion(renderer.minimap.getRegion());
float pad = renderer.fog.getPadding(); float pad = renderer.fog.getPadding();
float px = r.getU() * world.width() + pad; float px = r.getU() * world.width() + pad;
@@ -55,7 +52,7 @@ public class Minimap extends Table{
r.setV2(1f - py2 / (world.height() + pad*2f)); r.setV2(1f - py2 / (world.height() + pad*2f));
Graphics.shader(Shaders.fog); Graphics.shader(Shaders.fog);
super.draw(batch, parentAlpha); Draw.crect(r, x, y, width, height);
Graphics.shader(); Graphics.shader();
renderer.fog.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear); renderer.fog.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
@@ -70,7 +67,7 @@ public class Minimap extends Table{
} }
}); });
image.update(() -> { elem.update(() -> {
Element e = Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true); Element e = Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true);
if(e != null && e.isDescendantOf(this)){ if(e != null && e.isDescendantOf(this)){
@@ -79,6 +76,7 @@ public class Minimap extends Table{
Core.scene.setScrollFocus(null); Core.scene.setScrollFocus(null);
} }
}); });
add(image).size(140f, 140f);
add(elem).size(140f, 140f);
} }
} }
@@ -57,6 +57,9 @@ public class PausedDialog extends FloatingDialog{
hide(); hide();
}); });
content().row();
content().addButton("$text.unlocks", ui.unlocks::show);
content().row(); content().row();
content().addButton("$text.settings", ui.settings::show); content().addButton("$text.settings", ui.settings::show);
@@ -60,7 +60,7 @@ public class SectorsDialog extends FloatingDialog{
margin(0); margin(0);
getTitleTable().clear(); getTitleTable().clear();
clear(); clear();
stack(content(), buttons(), container).grow(); stack(content(), container, buttons()).grow();
shown(this::setup); shown(this::setup);
} }
@@ -128,7 +128,7 @@ public class SectorsDialog extends FloatingDialog{
class SectorView extends Element{ class SectorView extends Element{
float lastX, lastY; float lastX, lastY;
boolean clicked = false; boolean clicked = false;
float panX = 0, panY = -sectorSize/2f; float panX = sectorSize/2f, panY = sectorSize/2f;
SectorView(){ SectorView(){
addListener(new InputListener(){ addListener(new InputListener(){
@@ -130,13 +130,16 @@ public class SettingsMenuDialog extends SettingsDialog{
sound.volumePrefs(); sound.volumePrefs();
game.screenshakePref(); game.screenshakePref();
//game.checkPref("smoothcam", true);
game.checkPref("effects", true); game.checkPref("effects", true);
if(mobile){ if(mobile){
game.checkPref("autotarget", true); game.checkPref("autotarget", true);
} }
//game.sliderPref("sensitivity", 100, 10, 300, i -> i + "%"); game.sliderPref("saveinterval", 120, 10, 5 * 120, i -> Bundles.format("setting.seconds", i));
game.sliderPref("saveinterval", 60, 10, 5 * 120, i -> Bundles.format("setting.seconds", i));
if(!mobile){
game.checkPref("crashreport", true);
}
game.pref(new Setting(){ game.pref(new Setting(){
@Override @Override
public void add(SettingsTable table){ public void add(SettingsTable table){
@@ -187,12 +190,6 @@ 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 ? Bundles.get("setting.fpscap.none") : Bundles.format("setting.fpscap.text", s)));
graphics.checkPref("multithread", mobile, threads::setEnabled);
if(Settings.getBool("multithread")){
threads.setEnabled(true);
}
if(!mobile){ if(!mobile){
graphics.checkPref("vsync", true, b -> Gdx.graphics.setVSync(b)); graphics.checkPref("vsync", true, b -> Gdx.graphics.setVSync(b));
@@ -107,7 +107,7 @@ public class HudFragment extends Fragment{
Stack stack = new Stack(); Stack stack = new Stack();
TextButton waves = new TextButton(""); TextButton waves = new TextButton("");
Table btable = new Table().margin(14); Table btable = new Table().margin(0);
stack.add(waves); stack.add(waves);
stack.add(btable); stack.add(btable);
@@ -126,7 +126,6 @@ public class HudFragment extends Fragment{
IntFormat tps = new IntFormat("text.tps"); IntFormat tps = new IntFormat("text.tps");
IntFormat ping = new IntFormat("text.ping"); IntFormat ping = new IntFormat("text.ping");
t.label(() -> fps.get(Gdx.graphics.getFramesPerSecond())).padRight(10); t.label(() -> fps.get(Gdx.graphics.getFramesPerSecond())).padRight(10);
t.label(() -> tps.get(threads.getTPS())).visible(() -> threads.isEnabled());
t.row(); t.row();
if(Net.hasClient()){ if(Net.hasClient()){
t.label(() -> ping.get(Net.getPing())).visible(Net::client).colspan(2); t.label(() -> ping.get(Net.getPing())).visible(Net::client).colspan(2);
@@ -375,7 +374,7 @@ public class HudFragment extends Fragment{
(!state.mode.disableWaveTimer ? (!state.mode.disableWaveTimer ?
Bundles.format("text.wave.waiting", (int)(state.wavetime/60)) : Bundles.format("text.wave.waiting", (int)(state.wavetime/60)) :
Bundles.get("text.waiting"))) : Bundles.get("text.waiting"))) :
Bundles.format("text.mission.display", world.getSector().currentMission().displayString())).growX(); Bundles.format("text.mission.display", world.getSector().currentMission().displayString())).growX().pad(8f);
table.clicked(() -> { table.clicked(() -> {
if(world.getSector() != null && world.getSector().currentMission().hasMessage()){ if(world.getSector() != null && world.getSector().currentMission().hasMessage()){
+1 -1
View File
@@ -230,7 +230,7 @@ public class Block extends BaseBlock {
/**Call when some content is produced. This unlocks the content if it is applicable.*/ /**Call when some content is produced. This unlocks the content if it is applicable.*/
public void useContent(Tile tile, UnlockableContent content){ public void useContent(Tile tile, UnlockableContent content){
if(!headless && tile.getTeam() == players[0].getTeam()){ if(!headless && tile.getTeam() == players[0].getTeam()){
control.unlocks.handleContentUsed(content); logic.handleContent(content);
} }
} }
@@ -14,11 +14,7 @@ public class ColorMapper implements ContentList{
private static ObjectIntMap<Block> colorMap = new ObjectIntMap<>(); private static ObjectIntMap<Block> colorMap = new ObjectIntMap<>();
private static ThreadLocal<Color> tmpColors = new ThreadLocal<>(); private static ThreadLocal<Color> tmpColors = new ThreadLocal<>();
public static Block getByColor(int color){ private static int getBlockColor(Block block){
return blockMap.get(color);
}
public static int getBlockColor(Block block){
return colorMap.get(block, 0); return colorMap.get(block, 0);
} }
+54 -65
View File
@@ -22,7 +22,6 @@ import static io.anuke.mindustry.Vars.*;
public class Tile implements PosTrait, TargetTrait{ public class Tile implements PosTrait, TargetTrait{
public static final Object tileSetLock = new Object();
/** /**
* The coordinates of the core tile this is linked to, in the form of two bytes packed into one. * The coordinates of the core tile this is linked to, in the form of two bytes packed into one.
* This is relative to the block it is linked to; negate coords to find the link. * This is relative to the block it is linked to; negate coords to find the link.
@@ -130,8 +129,9 @@ public class Tile implements PosTrait, TargetTrait{
return wall; return wall;
} }
@Override
public Team getTeam(){ public Team getTeam(){
return Team.all[team]; return Team.all[target().team];
} }
public void setTeam(Team team){ public void setTeam(Team team){
@@ -143,33 +143,27 @@ public class Tile implements PosTrait, TargetTrait{
} }
public void setBlock(Block type, int rotation){ public void setBlock(Block type, int rotation){
synchronized(tileSetLock){ preChanged();
preChanged(); if(rotation < 0) rotation = (-rotation + 2);
if(rotation < 0) rotation = (-rotation + 2); this.wall = type;
this.wall = type; this.link = 0;
this.link = 0; setRotation((byte) (rotation % 4));
setRotation((byte) (rotation % 4)); changed();
changed();
}
} }
public void setBlock(Block type, Team team){ public void setBlock(Block type, Team team){
synchronized(tileSetLock){ preChanged();
preChanged(); this.wall = type;
this.wall = type; this.team = (byte)team.ordinal();
this.team = (byte)team.ordinal(); this.link = 0;
this.link = 0; changed();
changed();
}
} }
public void setBlock(Block type){ public void setBlock(Block type){
synchronized(tileSetLock){ preChanged();
preChanged(); this.wall = type;
this.wall = type; this.link = 0;
this.link = 0; changed();
changed();
}
} }
public void setFloor(Floor type){ public void setFloor(Floor type){
@@ -266,7 +260,7 @@ public class Tile implements PosTrait, TargetTrait{
* Returns the list of all tiles linked to this multiblock, or an empty array if it's not a multiblock. * Returns the list of all tiles linked to this multiblock, or an empty array if it's not a multiblock.
* This array contains all linked tiles, including this tile itself. * This array contains all linked tiles, including this tile itself.
*/ */
public synchronized Array<Tile> getLinkedTiles(Array<Tile> tmpArray){ public Array<Tile> getLinkedTiles(Array<Tile> tmpArray){
Block block = block(); Block block = block();
tmpArray.clear(); tmpArray.clear();
if(block.isMultiblock()){ if(block.isMultiblock()){
@@ -288,7 +282,7 @@ public class Tile implements PosTrait, TargetTrait{
* Returns the list of all tiles linked to this multiblock if it were this block, or an empty array if it's not a multiblock. * Returns the list of all tiles linked to this multiblock if it were this block, or an empty array if it's not a multiblock.
* This array contains all linked tiles, including this tile itself. * This array contains all linked tiles, including this tile itself.
*/ */
public synchronized Array<Tile> getLinkedTilesAs(Block block, Array<Tile> tmpArray){ public Array<Tile> getLinkedTilesAs(Block block, Array<Tile> tmpArray){
tmpArray.clear(); tmpArray.clear();
if(block.isMultiblock()){ if(block.isMultiblock()){
int offsetx = -(block.size - 1) / 2; int offsetx = -(block.size - 1) / 2;
@@ -390,52 +384,47 @@ public class Tile implements PosTrait, TargetTrait{
} }
private void preChanged(){ private void preChanged(){
synchronized(tileSetLock){ block().removed(this);
block().removed(this); if(entity != null){
if(entity != null){ entity.removeFromProximity();
entity.removeFromProximity();
}
team = 0;
} }
team = 0;
} }
private void changed(){ private void changed(){
if(entity != null){
synchronized(tileSetLock){ entity.remove();
if(entity != null){ entity = null;
entity.remove();
entity = null;
}
Block block = block();
if(block.hasEntity()){
entity = block.newEntity().init(this, block.update);
entity.cons = new ConsumeModule();
if(block.hasItems) entity.items = new ItemModule();
if(block.hasLiquids) entity.liquids = new LiquidModule();
if(block.hasPower){
entity.power = new PowerModule();
entity.power.graph.add(this);
}
if(!world.isGenerating()){
entity.updateProximity();
}
}else if(!(block instanceof BlockPart) && !world.isGenerating()){
//since the entity won't update proximity for us, update proximity for all nearby tiles manually
for(GridPoint2 p : Geometry.d4){
Tile tile = world.tile(x + p.x, y + p.y);
if(tile != null){
tile = tile.target();
tile.block().onProximityUpdate(tile);
}
}
}
updateOcclusion();
} }
Block block = block();
if(block.hasEntity()){
entity = block.newEntity().init(this, block.update);
entity.cons = new ConsumeModule();
if(block.hasItems) entity.items = new ItemModule();
if(block.hasLiquids) entity.liquids = new LiquidModule();
if(block.hasPower){
entity.power = new PowerModule();
entity.power.graph.add(this);
}
if(!world.isGenerating()){
entity.updateProximity();
}
}else if(!(block instanceof BlockPart) && !world.isGenerating()){
//since the entity won't update proximity for us, update proximity for all nearby tiles manually
for(GridPoint2 p : Geometry.d4){
Tile tile = world.tile(x + p.x, y + p.y);
if(tile != null){
tile = tile.target();
tile.block().onProximityUpdate(tile);
}
}
}
updateOcclusion();
world.notifyChanged(this); world.notifyChanged(this);
} }
@@ -5,6 +5,7 @@ import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.type.Liquid;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter;
import io.anuke.mindustry.world.meta.BlockStat;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
@@ -15,9 +16,7 @@ import static io.anuke.mindustry.Vars.tilesize;
public abstract class ItemLiquidGenerator extends ItemGenerator{ public abstract class ItemLiquidGenerator extends ItemGenerator{
protected float minLiquidEfficiency = 0.2f; protected float minLiquidEfficiency = 0.2f;
protected float powerPerLiquid = 0.13f; protected float powerPerLiquid = 0.13f;
/** /**Maximum liquid used per frame.*/
* Maximum liquid used per frame.
*/
protected float maxLiquidGenerate = 0.4f; protected float maxLiquidGenerate = 0.4f;
public ItemLiquidGenerator(String name){ public ItemLiquidGenerator(String name){
@@ -28,6 +27,12 @@ public abstract class ItemLiquidGenerator extends ItemGenerator{
consumes.add(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, 0.001f, true)).update(false).optional(true); consumes.add(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, 0.001f, true)).update(false).optional(true);
} }
@Override
public void init(){
super.init();
stats.remove(BlockStat.liquidFuelUse);
}
@Override @Override
public void update(Tile tile){ public void update(Tile tile){
ItemGeneratorEntity entity = tile.entity(); ItemGeneratorEntity entity = tile.entity();
@@ -13,19 +13,21 @@ import io.anuke.ucore.util.Mathf;
public abstract class LiquidGenerator extends PowerGenerator{ public abstract class LiquidGenerator extends PowerGenerator{
protected float minEfficiency = 0.2f; protected float minEfficiency = 0.2f;
protected float powerPerLiquid = 0.13f; protected float powerPerLiquid;
/** /**Maximum liquid used per frame.*/
* Maximum liquid used per frame. protected float maxLiquidGenerate;
*/
protected float maxLiquidGenerate = 0.4f;
protected Effect generateEffect = BlockFx.generatespark; protected Effect generateEffect = BlockFx.generatespark;
public LiquidGenerator(String name){ public LiquidGenerator(String name){
super(name); super(name);
liquidCapacity = 30f; liquidCapacity = 30f;
hasLiquids = true; hasLiquids = true;
}
consumes.add(new ConsumeLiquidFilter(liquid -> getEfficiency(liquid) >= minEfficiency, 0.001f)).update(false); @Override
public void setStats(){
consumes.add(new ConsumeLiquidFilter(liquid -> getEfficiency(liquid) >= minEfficiency, maxLiquidGenerate)).update(false);
super.setStats();
} }
@Override @Override
@@ -14,7 +14,7 @@ public class LiquidHeatGenerator extends LiquidGenerator{
public void setStats(){ public void setStats(){
super.setStats(); super.setStats();
stats.add(BlockStat.basePowerGeneration, maxLiquidGenerate * powerPerLiquid * 60f * 0.4f, StatUnit.powerSecond); stats.add(BlockStat.basePowerGeneration, maxLiquidGenerate * powerPerLiquid * 60f, StatUnit.powerSecond);
} }
@Override @Override
@@ -5,6 +5,7 @@ import com.badlogic.gdx.utils.IntSet;
import com.badlogic.gdx.utils.ObjectSet; import com.badlogic.gdx.utils.ObjectSet;
import com.badlogic.gdx.utils.Queue; import com.badlogic.gdx.utils.Queue;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Timers;
import static io.anuke.mindustry.Vars.threads; import static io.anuke.mindustry.Vars.threads;
@@ -37,63 +38,38 @@ public class PowerGraph{
lastFrameUpdated = threads.getFrameID(); lastFrameUpdated = threads.getFrameID();
boolean charge = false;
float totalInput = 0f; float totalInput = 0f;
float bufferInput = 0f;
for(Tile producer : producers){ for(Tile producer : producers){
if (producer.block().consumesPower) { totalInput += producer.entity.power.amount;
bufferInput += producer.entity.power.amount;
} else {
totalInput += producer.entity.power.amount;
}
} }
float maxOutput = 0f;
float bufferOutput = 0f;
for(Tile consumer : consumers){
if (consumer.block().outputsPower) {
bufferOutput += consumer.block().powerCapacity - consumer.entity.power.amount;
} else {
maxOutput += consumer.block().powerCapacity - consumer.entity.power.amount;
}
}
if (maxOutput < totalInput) {
charge = true;
}
if (totalInput + bufferInput <= 0.0001f || maxOutput + bufferOutput <= 0.0001f) {
return;
}
float bufferUsed = 0;
if (charge) {
bufferUsed = Math.min((totalInput - maxOutput) / bufferOutput, 1f);
} else {
bufferUsed = Math.min((maxOutput - totalInput) / bufferInput, 1f);
}
float inputUsed = charge ? Math.min((maxOutput + bufferOutput) / totalInput, 1f) : 1f;
for(Tile producer : producers){ for(Tile producer : producers){
if (producer.block().consumesPower) { float accumulator = producer.entity.power.amount;
if (!charge) {
producer.entity.power.amount -= producer.entity.power.amount * bufferUsed; if(accumulator <= 0.0001f) continue;
}
float toEach = accumulator / consumers.size;
float outputs = 0f;
for(Tile tile : consumers){
outputs += Math.min(tile.block().powerCapacity - tile.entity.power.amount, toEach) / toEach;
}
float finalEach = toEach / outputs * Timers.delta();
float buffer = 0f;
if(Float.isNaN(finalEach) || Float.isInfinite(finalEach)){
continue; continue;
} }
producer.entity.power.amount -= producer.entity.power.amount * inputUsed;
}
float outputSatisfied = charge ? 1f : Math.min((totalInput + bufferInput) / maxOutput, 1f); for(Tile tile : consumers){
for(Tile consumer : consumers){ float used = Math.min(tile.block().powerCapacity - tile.entity.power.amount, finalEach) * accumulator / totalInput;
if (consumer.block().outputsPower) { buffer += used;
if (charge) { tile.entity.power.amount += used;
consumer.entity.power.amount += (consumer.block().powerCapacity - consumer.entity.power.amount) * bufferUsed;
}
continue;
} }
consumer.entity.power.amount += (consumer.block().powerCapacity - consumer.entity.power.amount) * outputSatisfied;
producer.entity.power.amount -= buffer;
} }
} }
@@ -127,7 +127,7 @@ public class MechPad extends Block{
if(checkValidTap(tile, player)){ if(checkValidTap(tile, player)){
Call.onMechFactoryTap(player, tile); Call.onMechFactoryTap(player, tile);
}else if(player.isLocal && mobile){ }else if(player.isLocal && mobile && !player.isDead()){
player.moveTarget = tile.entity; player.moveTarget = tile.entity;
} }
} }
@@ -23,6 +23,16 @@ public class CrashHandler{
public static void handle(Throwable e){ public static void handle(Throwable e){
e.printStackTrace(); e.printStackTrace();
try{
//check crash report setting
if(!Settings.getBool("crashreport")){
return;
}
}catch(Throwable ignored){
//don't send since we don't know if the user has the setting set
return;
}
if(!OS.isMac){ if(!OS.isMac){
try{ try{
javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName()); javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
+2
View File
@@ -34,6 +34,8 @@
<true/> <true/>
<key>UIRequiresFullScreen</key> <key>UIRequiresFullScreen</key>
<true/> <true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>NSPhotoLibraryAddUsageDescription</key> <key>NSPhotoLibraryAddUsageDescription</key>
<string>Mindustry</string> <string>Mindustry</string>
<key>UIDeviceFamily</key> <key>UIDeviceFamily</key>
+1 -1
View File
@@ -2,5 +2,5 @@ app.version=4.0
app.id=io.anuke.mindustry app.id=io.anuke.mindustry
app.mainclass=io.anuke.mindustry.IOSLauncher app.mainclass=io.anuke.mindustry.IOSLauncher
app.executable=IOSLauncher app.executable=IOSLauncher
app.build=23 app.build=27
app.name=Mindustry app.name=Mindustry
+1
View File
@@ -18,6 +18,7 @@
</resource> </resource>
</resources> </resources>
<forceLinkClasses> <forceLinkClasses>
<pattern>net.jpountz.lz4.**</pattern>
<pattern>io.anuke.ucore.scene.**</pattern> <pattern>io.anuke.ucore.scene.**</pattern>
<pattern>io.anuke.mindustry.gen.Call</pattern> <pattern>io.anuke.mindustry.gen.Call</pattern>
<pattern>io.anuke.mindustry.net.**</pattern> <pattern>io.anuke.mindustry.net.**</pattern>
+2 -7
View File
@@ -30,7 +30,6 @@ import java.util.concurrent.CopyOnWriteArraySet;
import static io.anuke.mindustry.Vars.threads; import static io.anuke.mindustry.Vars.threads;
public class KryoServer implements ServerProvider { public class KryoServer implements ServerProvider {
final boolean tcpOnly = System.getProperty("java.version") == null;
final Server server; final Server server;
final CopyOnWriteArrayList<KryoConnection> connections = new CopyOnWriteArrayList<>(); final CopyOnWriteArrayList<KryoConnection> connections = new CopyOnWriteArrayList<>();
final CopyOnWriteArraySet<Integer> missing = new CopyOnWriteArraySet<>(); final CopyOnWriteArraySet<Integer> missing = new CopyOnWriteArraySet<>();
@@ -150,11 +149,7 @@ public class KryoServer implements ServerProvider {
lastconnection = 0; lastconnection = 0;
connections.clear(); connections.clear();
missing.clear(); missing.clear();
if(tcpOnly){ server.bind(port, port);
server.bind(port);
}else{
server.bind(port, port);
}
serverThread = new Thread(() -> { serverThread = new Thread(() -> {
try{ try{
@@ -172,7 +167,7 @@ public class KryoServer implements ServerProvider {
connections.clear(); connections.clear();
lastconnection = 0; lastconnection = 0;
async(server::close); async(server::stop);
} }
@Override @Override
@@ -68,7 +68,7 @@ public class ServerControl extends Module{
); );
Log.setLogger(new LogHandler(){ Log.setLogger(new LogHandler(){
DateTimeFormatter dateTime = DateTimeFormatter.ofPattern("MM-dd-yyyy | HH:mm:ss"); DateTimeFormatter dateTime = DateTimeFormatter.ofPattern("MM-dd-yyyy | HH:mm:ss");
@Override @Override
public void info(String text, Object... args){ public void info(String text, Object... args){
+54
View File
@@ -0,0 +1,54 @@
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.ContentLoader;
import io.anuke.mindustry.maps.SectorPresets;
import io.anuke.mindustry.maps.generation.Generation;
import io.anuke.mindustry.maps.missions.Mission;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/** This class is responsible for testing predefined sectors. */
public class SectorTests{
private SectorPresets presets;
private Generation fakeGen;
@BeforeAll
static void initializeDependencies(){
Vars.content = new ContentLoader();
Vars.content.load();
}
@BeforeEach
void initTest(){
this.presets = new SectorPresets();
// Fake away the Generation dependency
this.fakeGen = new Generation(null, null, 250, 250, null);
}
/** Returns true if at least one mission provides a spawn point. */
private boolean spawnPointIsDefined(Array<Mission> missions){
for(Mission mission : missions){
if(mission.getSpawnPoints(this.fakeGen).size > 0){
return true;
}
}
// No spawn point provided
return false;
}
/**
* Makes sure that every predefined sector has a position for the player core defined.
* This is achieved by adding at least one mission which defines a spawn point.
*/
@Test
void test_sectorHasACore(){
for(SectorPresets.SectorPreset preset : this.presets.getPresets().values()){
assertTrue(spawnPointIsDefined(preset.missions), "Sector at (" + preset.x + "|" + preset.y + ") contains no missions which define a spawn point. Add a battle or wave mission.");
}
}
}