Compare commits
6 Commits
v144.1
...
new-liquid
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c89d7d273 | ||
|
|
3ea742b06d | ||
|
|
9bedadac79 | ||
|
|
5ccadcf38f | ||
|
|
a32462971b | ||
|
|
3faf8ca07f |
@@ -15,6 +15,7 @@ manifold=36
|
||||
mega=5
|
||||
mindustry.entities.comp.BuildingComp=6
|
||||
mindustry.entities.comp.BulletComp=7
|
||||
mindustry.entities.comp.ConduitGraphUpdaterComp=48
|
||||
mindustry.entities.comp.DecalComp=8
|
||||
mindustry.entities.comp.EffectStateComp=9
|
||||
mindustry.entities.comp.FireComp=10
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{fields:[]}
|
||||
|
Before Width: | Height: | Size: 784 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 464 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 230 B |
|
Before Width: | Height: | Size: 221 B |
|
Before Width: | Height: | Size: 220 B |
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
core/assets-raw/sprites/blocks/turrets/salvo-heat.png
Normal file
|
After Width: | Height: | Size: 517 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 501 B |
|
Before Width: | Height: | Size: 383 B |
|
Before Width: | Height: | Size: 203 B |
|
Before Width: | Height: | Size: 864 B |
BIN
core/assets-raw/sprites/blocks/turrets/scatter.png
Normal file
|
After Width: | Height: | Size: 853 B |
|
Before Width: | Height: | Size: 499 B |
|
Before Width: | Height: | Size: 779 B |
|
Before Width: | Height: | Size: 547 B |
|
Before Width: | Height: | Size: 329 B After Width: | Height: | Size: 304 B |
|
Before Width: | Height: | Size: 324 B After Width: | Height: | Size: 304 B |
|
Before Width: | Height: | Size: 308 B After Width: | Height: | Size: 285 B |
|
Before Width: | Height: | Size: 322 B After Width: | Height: | Size: 291 B |
@@ -1789,7 +1789,7 @@ hint.launch = Once enough resources are collected, you can [accent]Launch[] by s
|
||||
hint.launch.mobile = Once enough resources are collected, you can [accent]Launch[] by selecting nearby sectors from the \uE827 [accent]Map[] in the \uE88C [accent]Menu[].
|
||||
hint.schematicSelect = Hold [accent][[F][] and drag to select blocks to copy and paste.\n\n[accent][[Middle Click][] to copy a single block type.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
|
||||
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
||||
hint.conveyorPathfind.mobile = Enable \uE844 [accent]diagonal mode[] and drag conveyors to automatically generate a path.
|
||||
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
||||
|
||||
@@ -1757,7 +1757,6 @@ hint.launch = Калі рэсурсы сабраны, вы можаце [accent]
|
||||
hint.launch.mobile = Калі рэсурсы сабраны, вы можаце [accentЗапусціць[] выбіраючы сектара якія знаходзяцца побач на \ue827 [accent]Карце[] ў \ue88c [accent]Меню[].
|
||||
hint.schematicSelect = Утрымайце [accent][[F][] і працягніце каб выбраць блокі для капіявання і ўстаўкі.\n\n[accent][[Сярэдні Пстрык][] каб скапіяваць толькі адзін тып блоку.
|
||||
hint.rebuildSelect = Утрымайце [accent][[B][] і працягніце каб выбраць блокі для разбудавання.\nГэта перабудуе іх аўтаматычна.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Утрымайце [accent][[Левы Ctrl][] калі правозіце канвееры каб аутаматычна згенераваць шлях.
|
||||
hint.conveyorPathfind.mobile = Уключыце \ue844 [accent]дыяганальны рэжым[] і утрымлівайце і размяшчайце канвееры па аўтаматычна згенераванаму шляху.
|
||||
hint.boost = Утрымайце [accent][[Левы Shift][] каб ляцець праз перашкоды з вашай выбранай адзінкай.\n\nТолькі некаторыя наземныя адзінкі могуць узлятаць.
|
||||
|
||||
@@ -1769,7 +1769,6 @@ hint.launch = След като съберете достатъчно ресур
|
||||
hint.launch.mobile = След като съберете достатъчно ресурси, можете да [accent]Изстреляте[] ядро като изберете близък сектор от \ue827 [accent]Глобуса[] в \ue88c [accent]Менюто[].
|
||||
hint.schematicSelect = Задръжте [accent][[F][] и плъзнете за да изберете/копирате група от блокчета.\n\n[accent][[Среден клик][] за да копирате едно блокче.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Задръжте [accent][[L-Ctrl][] докато поставяте пътека от конвейери за да генерирате пътека автоматично.
|
||||
hint.conveyorPathfind.mobile = Позволете \ue844 [accent]Диагонално Поставяне[] за автоматично намиране на пътека при поставяне на конвейери.
|
||||
hint.boost = Задръжте [accent][[L-Shift][] за да прелетите над препятствия с тази единица.\n\nСамо някои наземни единици имат двигатели за летене.
|
||||
|
||||
@@ -1779,7 +1779,6 @@ hint.launch = Un cop s’han recollit prou recursos, podeu iniciar un llançamen
|
||||
hint.launch.mobile = Un cop s’han recollit prou recursos, podeu iniciar un llançament seleccionant un sector proper del \ue827 [accent]Mapa[] del \ue88c [accent]Menú[].
|
||||
hint.schematicSelect = Manteniu premuda la tecla [accent]F[] i arrossegueu per a seleccionar els blocs que vulgueu copiar i enganxar.\n\nFeu clic amb el [accent]botó del mig[] del ratolí per a copiar només un tipus de bloc.
|
||||
hint.rebuildSelect = Manteniu premuda la tecla [accent][[B][] i arrossegueu per a seleccionar els plànols dels blocs destruïts.\nAixí, es podran reconstruir automàticament.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Manteniu premuda la tecla [accent]ControlEsquerra[] i arrossegueu les cintes per a generar un camí automàticament.
|
||||
hint.conveyorPathfind.mobile = Activeu el \ue844 [accent]mode diagonal[] i arrossegueu les cintes per a generar un camí automàticament.
|
||||
hint.boost = Manteniu premuda la tecla [accent]ControlEsquerra[] per a sobrevolar els obstacles amb la unitat actual.\n\nNomés algunes unitats terrestres tenen elevadors per a poder-ho fer.
|
||||
|
||||
@@ -1773,7 +1773,6 @@ hint.launch = Jakmile je nasbíráno dostatek zdrojových materiálů, můžeš
|
||||
hint.launch.mobile = Jakmile je nasbíráno dostatek zdrojových materiálů, můžeš se [accent]vyslat[] do přilehlých sektorů z \ue827 [accent]mapy[] v the \ue88c [accent]nabídce[].
|
||||
hint.schematicSelect = Podrž [accent][[F][] a potáhni pro výběr bloků, které chceš zkopírovat.\n\nKlikni na [accent][[prostřední tlačítko][] myši pro zkopírování jednoho typu bloku.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Podrž [accent][[levý Ctrl][], když táhneš dopravníky, pro automatické vygenerování cesty.
|
||||
hint.conveyorPathfind.mobile = Povol \ue844 [accent]úhlopříčný režim[] a potáhni dopravníky pro automatické generování cesty.
|
||||
hint.boost = Podrž [accent][[levý Shift][], abys přeletěl přes překážky se svou současnou jednotkou.\n\nPouze některé jednotky však mají takový posilovač.
|
||||
|
||||
@@ -1758,7 +1758,6 @@ hint.launch = Once enough resources are collected, you can [accent]Launch[] by s
|
||||
hint.launch.mobile = Once enough resources are collected, you can [accent]Launch[] by selecting nearby sectors from the \ue827 [accent]Map[] in the \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Hold [accent][[F][] and drag to select blocks to copy and paste.\n\n[accent][[Middle Click][] to copy a single block type.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
||||
hint.conveyorPathfind.mobile = Enable \ue844 [accent]diagonal mode[] and drag conveyors to automatically generate a path.
|
||||
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
||||
|
||||
@@ -1789,7 +1789,6 @@ hint.launch = Sobald du genug Ressourcen gesammelt hast, kannst du [accent]Start
|
||||
hint.launch.mobile = Sobald du genug Ressourcen gesammelt hast, kannst du [accent]Starten[], indem du andere Sektoren auf der \ue827 [accent]Karte[] im \ue88c [accent]Menü[] auswählst.
|
||||
hint.schematicSelect = Halte [accent][[F][] gedrückt und bewege deine Maus, um Blöcke zu kopieren.\n\nMit [accent][[Mittelklick][] kannst du einen einzelnen Block kopieren.
|
||||
hint.rebuildSelect = Halte [accent][[B][] gedrückt und bewege deine Maus, um Überreste zerstörter Blöcke auszuwählen.\nDiese werden dann automatisch wiederaufgebaut.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
|
||||
hint.conveyorPathfind = Halte [accent][[L-STRG][] während du Förderbänder baust, um automatisch einen Weg zu finden.
|
||||
hint.conveyorPathfind.mobile = Aktiviere den \ue844 [accent]Diagonal-Modus[] unten rechts und platziere Förderbänder, um automatisch einen Weg zu generieren.
|
||||
|
||||
@@ -1785,7 +1785,6 @@ hint.launch = Cuando tengas sufientes recursos, puedes [accent]Lanzar el núcleo
|
||||
hint.launch.mobile = Cuando tengas sufientes recursos, puedes [accent]Lanzar el núcleo[] escogiendo como objetivo sectores cercanos en el [accent]Mapa[], disponible desde el [accent]Menú de pausa[].
|
||||
hint.schematicSelect = Mantén [accent][[F][] y arrastra para crear una selección de bloques que puedes copiar y pegar.\n\nUsa [accent][[Clic central][] para seleccionar un tipo de bloque.
|
||||
hint.rebuildSelect = Mantén [accent][[B][] y arrastra para seleccionar planos de bloques destruidos.\nEsto los reconstruirá automáticamente.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Mantener [accent][[L-Ctrl][] mientras arrastras cintas transportadoras generará automáticamente una ruta.
|
||||
hint.conveyorPathfind.mobile = Activa el [accent]modo diagonal[] y arrastra cintas transportadoras para generar una ruta inteligente.
|
||||
hint.boost = Mantén [accent][[L-Shift][] para sobrevolar obstáculos con tu unidad actual.\n\nSólo algunas unidades terrestres disponen de propulsores que les otorgan esta habilidad.
|
||||
|
||||
@@ -1758,7 +1758,6 @@ hint.launch = Once enough resources are collected, you can [accent]Launch[] by s
|
||||
hint.launch.mobile = Once enough resources are collected, you can [accent]Launch[] by selecting nearby sectors from the \ue827 [accent]Map[] in the \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Hold [accent][[F][] and drag to select blocks to copy and paste.\n\n[accent][[Middle Click][] to copy a single block type.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
||||
hint.conveyorPathfind.mobile = Enable \ue844 [accent]diagonal mode[] and drag conveyors to automatically generate a path.
|
||||
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
||||
|
||||
@@ -1760,7 +1760,6 @@ hint.launch = Once enough resources are collected, you can [accent]Launch[] by s
|
||||
hint.launch.mobile = Once enough resources are collected, you can [accent]Launch[] by selecting nearby sectors from the \ue827 [accent]Map[] in the \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Hold [accent][[F][] and drag to select blocks to copy and paste.\n\n[accent][[Middle Click][] to copy a single block type.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
||||
hint.conveyorPathfind.mobile = Enable \ue844 [accent]diagonal mode[] and drag conveyors to automatically generate a path.
|
||||
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
||||
|
||||
@@ -1760,7 +1760,6 @@ hint.launch = Kun olet kerännyt riittävästi resursseja, voit [accent]Laukaist
|
||||
hint.launch.mobile = Kun olet kerännyt riittävästi resursseja, voit [accent]Laukaista[] valitsemalla läheisen sektorin \ue827[accent]Kartasta[], joka löytyy \ue88c[accent]Valikosta[].
|
||||
hint.schematicSelect = Pidä näppäintä [accent][[F][] pohjassa ja vedä valitaksesi palikoita kopioitavaksi ja liitettäväksi.\n\n[accent] Paina [[Hiiren keskinäppäin][] kopioidaksesi yksittäisen palikan.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Pidä näppäintä [accent][[Vasen ctrl][] pohjassa, kun vedät liukuhihnoja luodaksesi polun automaattisesti.
|
||||
hint.conveyorPathfind.mobile = Salli \ue844[accent]Viisto tila[] ja vedä liukuhihnoja luodaksesi polun automaattisesti.
|
||||
hint.boost = Pidä [accent][[Vasen shift][] pohjassa lentääksesi esteiden yli yksikölläsi.\n\nVain harvoilla maajoukoilla on tehostin.
|
||||
|
||||
@@ -1757,7 +1757,6 @@ hint.launch = Kapag sapat na ang mga mapagkukunan, maaari mong [accent]Ilunsad[]
|
||||
hint.launch.mobile = Kapag sapat na ang mga mapagkukunan, maaari mong [accent]Ilunsad[] sa pamamagitan ng pagpili sa mga kalapit na sektor mula sa \ue827 [accent]Map[] sa \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Pindutin ang [accent][[F][] at i-drag upang pumili ng mga bloke na kokopyahin at ipe-paste.\n\n[accent][[Middle Click][] upang kopyahin ang isang uri ng block.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
||||
hint.conveyorPathfind.mobile = Pindutin ang [accent][[L-Ctrl][] habang dina-drag ang mga conveyor para awtomatikong bumuo ng landas.
|
||||
hint.boost = Pindutin ang [accent][[L-Shift][] para lumipad sa mga obstacle kasama ang iyong kasalukuyang unit.\n\nIlang ground unit lang ang may mga booster
|
||||
|
||||
@@ -150,16 +150,16 @@ mod.incompatiblemod = [red]Incompatible
|
||||
mod.blacklisted = [red]Non supporté
|
||||
mod.unmetdependencies = [red]Dépendances manquantes
|
||||
mod.erroredcontent = [scarlet]Erreurs dans le contenu !
|
||||
mod.circulardependencies = [red]Dépendances circulaires
|
||||
mod.incompletedependencies = [red]Dépendances incomplètes
|
||||
mod.circulardependencies = [red]Circular Dependencies
|
||||
mod.incompletedependencies = [red]Incomplete Dependencies
|
||||
|
||||
mod.requiresversion.details = Requiert la version: [accent]{0}[]\nVotre jeu n'est pas à jour. Ce mod a besoin d'une version récente du jeu (la beta ou l'alpha) pour fonctionner.
|
||||
mod.outdatedv7.details = Ce mod est incompatible avec la version la plus récente du jeu. L'auteur doit le mettre à jour et ajouter [accent]minGameVersion: 136[] dans le fichier [accent]mod.json[].
|
||||
mod.blacklisted.details = Ce mod à été mis sur liste noire, car il cause des plantages ou d'autres problèmes avec la version actuelle du jeu. Ne l'utilisez pas.
|
||||
mod.blacklisted.details = Ce mod à été manuellement mis sur liste noire car il cause des crashs ou d'autres problèmes avec la version actuelle du jeu. Ne l'utilisez pas.
|
||||
mod.missingdependencies.details = Ce mod à des dépendances manquantes: {0}
|
||||
mod.erroredcontent.details = Ce mod cause des erreurs lors du chargement. Demandez à l'auteur de les régler.
|
||||
mod.circulardependencies.details = Ce mod à des dépendances qui dépendent les unes des autres.
|
||||
mod.incompletedependencies.details = Ce mod ne peut pas être chargé en raison de dépendances invalides ou manquantes: {0}.
|
||||
mod.erroredcontent.details = Ce mod cause des erreurs lors du chargement. Demandez à l'autheur de les régler.
|
||||
mod.circulardependencies.details = This mod has dependencies that depends on each other.
|
||||
mod.incompletedependencies.details = This mod is unable to be loaded due to invalid or missing dependencies: {0}.
|
||||
|
||||
mod.requiresversion = Requiert la version: [red]{0}
|
||||
|
||||
@@ -296,7 +296,7 @@ server.invalidport = Numéro de port invalide !
|
||||
server.error = [scarlet]Erreur lors de l'hébergement du serveur.
|
||||
save.new = Nouvelle sauvegarde
|
||||
save.overwrite = Êtes-vous sûr de vouloir\nécraser cette sauvegarde ?
|
||||
save.nocampaign = Les fichiers de sauvegarde de la campagne ne peuvent pas être importés individuellement.
|
||||
save.nocampaign = Individual save files from the campaign cannot be imported.
|
||||
overwrite = Écraser
|
||||
save.none = Aucune sauvegarde trouvée !
|
||||
savefail = Échec de la sauvegarde !
|
||||
@@ -339,7 +339,7 @@ command.repair = Réparer
|
||||
command.rebuild = Reconstruire
|
||||
command.assist = Assister
|
||||
command.move = Bouger
|
||||
command.boost = Booster
|
||||
command.boost = Boost
|
||||
openlink = Ouvrir le lien
|
||||
copylink = Copier le lien
|
||||
back = Retour
|
||||
@@ -365,8 +365,8 @@ pausebuilding = [accent][[{0}][] pour mettre la construction en pause
|
||||
resumebuilding = [scarlet][[{0}][] pour reprendre la construction
|
||||
enablebuilding = [scarlet][[{0}][] pour activer la construction
|
||||
showui = Interface cachée.\nPressez [accent][[{0}][] pour montrer l'interface.
|
||||
commandmode.name = [accent]Mode « Commande »
|
||||
commandmode.nounits = [aucune unité]
|
||||
commandmode.name = [accent]Command Mode
|
||||
commandmode.nounits = [no units]
|
||||
wave = [accent]Vague {0}
|
||||
wave.cap = [accent]Vague {0}/{1}
|
||||
wave.waiting = [lightgray]Vague dans {0}
|
||||
@@ -451,7 +451,7 @@ waves.max = unités maximum
|
||||
waves.guardian = Gardien
|
||||
waves.preview = Prévisualiser
|
||||
waves.edit = Modifier...
|
||||
waves.random = Aléatoire
|
||||
waves.random = Random
|
||||
waves.copy = Copier dans le presse-papiers
|
||||
waves.load = Coller depuis le presse-papiers
|
||||
waves.invalid = Vagues invalides dans le presse-papiers.
|
||||
@@ -462,8 +462,8 @@ waves.sort.reverse = Tri inversé
|
||||
waves.sort.begin = Vague
|
||||
waves.sort.health = Santé
|
||||
waves.sort.type = Type
|
||||
waves.search = Rechercher des vagues...
|
||||
waves.filter.unit = Filtre d'Unité
|
||||
waves.search = Search waves...
|
||||
waves.filter.unit = Unit Filter
|
||||
waves.units.hide = Masquer tout
|
||||
waves.units.show = Afficher tout
|
||||
|
||||
@@ -488,7 +488,7 @@ editor.errornot = Ceci n'est pas un fichier de carte.
|
||||
editor.errorheader = Ce fichier de carte est invalide ou corrompu.
|
||||
editor.errorname = La carte n'a pas de nom. Essayez-vous de charger une sauvegarde ?
|
||||
editor.update = Mettre à jour
|
||||
editor.randomize = Générer
|
||||
editor.randomize = Randomiser
|
||||
editor.moveup = Monter
|
||||
editor.movedown = Descendre
|
||||
editor.copy = Copier
|
||||
@@ -902,7 +902,7 @@ stat.repairspeed = Vitesse de réparation
|
||||
stat.weapons = Armes
|
||||
stat.bullet = Balles
|
||||
stat.moduletier = Tier
|
||||
stat.unittype = Type d'Unité
|
||||
stat.unittype = Unit Type
|
||||
stat.speedincrease = Accélération
|
||||
stat.range = Portée
|
||||
stat.drilltier = Blocs forables
|
||||
@@ -914,7 +914,7 @@ stat.armor = Armure
|
||||
stat.buildtime = Durée de construction
|
||||
stat.maxconsecutive = Max Consécutif
|
||||
stat.buildcost = Coût de construction
|
||||
stat.inaccuracy = Imprécision
|
||||
stat.inaccuracy = Précision
|
||||
stat.shots = Tirs
|
||||
stat.reload = Cadence de tir
|
||||
stat.ammo = Munitions
|
||||
@@ -996,9 +996,9 @@ bullet.splashdamage = [stat]{0}[lightgray] dégâts de zone ~[stat] {1}[lightgra
|
||||
bullet.incendiary = [stat]incendiaire
|
||||
bullet.homing = [stat]autoguidé
|
||||
bullet.armorpierce = [stat]perceur d'armure
|
||||
bullet.suppression = [stat]{0} sec[lightgray] suppression de soins ~ [stat]{1}[lightgray] blocs
|
||||
bullet.interval = [stat]{0}/sec[lightgray] Balle secondaire:
|
||||
bullet.frags = [stat]{0}[lightgray]x Balle à fragmentation:
|
||||
bullet.suppression = [stat]{0} sec[lightgray] repair suppression ~ [stat]{1}[lightgray] tiles
|
||||
bullet.interval = [stat]{0}/sec[lightgray] interval bullets:
|
||||
bullet.frags = [stat]{0}[lightgray]x Balle à fragmentation :
|
||||
bullet.lightning = [stat]{0}[lightgray]x foudre ~ [stat]{1}[lightgray] dégâts
|
||||
bullet.buildingdamage = [stat]{0}%[lightgray] des dégâts aux bâtiments
|
||||
bullet.knockback = [stat]{0}[lightgray] recul
|
||||
@@ -1007,13 +1007,13 @@ bullet.infinitepierce = [stat]perçant
|
||||
bullet.healpercent = [stat]{0}[lightgray]% soins
|
||||
bullet.healamount = [stat]{0}[lightgray] réparation directe
|
||||
bullet.multiplier = [stat]{0}[lightgray]x multiplicateur de munitions
|
||||
bullet.reload = [stat]{0}[lightgray]% vitesse de tir
|
||||
bullet.range = [stat]{0}[lightgray] blocs de portée
|
||||
bullet.reload = [stat]{0}[lightgray]x vitesse de tir
|
||||
bullet.range = [stat]{0}[lightgray] tuiles de portée
|
||||
|
||||
unit.blocks = blocs
|
||||
unit.blockssquared = blocs²
|
||||
unit.powersecond = unités d'énergie/seconde
|
||||
unit.tilessecond = blocs/seconde
|
||||
unit.tilessecond = tuiles/seconde
|
||||
unit.liquidsecond = unités de liquide/seconde
|
||||
unit.itemssecond = objets/seconde
|
||||
unit.liquidunits = unités de liquide
|
||||
@@ -1111,8 +1111,8 @@ setting.bridgeopacity.name = Opacité des ponts
|
||||
setting.playerchat.name = Montrer les bulles de discussion des joueurs
|
||||
setting.showweather.name = Montrer les Effets météo
|
||||
setting.hidedisplays.name = Cacher les Écrans
|
||||
steam.friendsonly = Amis seulement
|
||||
steam.friendsonly.tooltip = Indique si seuls les amis Steam peuvent rejoindre votre partie.\nSi vous décochez cette case, votre partie deviendra publique et tout le monde pourra la rejoindre.
|
||||
steam.friendsonly = Friends Only
|
||||
steam.friendsonly.tooltip = Whether only Steam friends will be able to join your game.\nUnchecking this box will make your game public - anyone can join.
|
||||
public.beta = Notez que les versions bêta du jeu ne peuvent pas créer de salons publics.
|
||||
uiscale.reset = L'échelle de l'interface a été modifiée.\nAppuyez sur "OK" pour confirmer.\n[scarlet]Rétablissement des anciens paramètres et fermeture du jeu dans [accent] {0}[] secondes...
|
||||
uiscale.cancel = Annuler & Quitter
|
||||
@@ -1227,7 +1227,7 @@ rules.unitbuildspeedmultiplier = Multiplicateur de Vitesse de Construction des U
|
||||
rules.unitcostmultiplier = Multiplicateur du coût de fabrication des Unités
|
||||
rules.unithealthmultiplier = Multiplicateur de Santé des Unités
|
||||
rules.unitdamagemultiplier = Multiplicateur de Dégât des Unités
|
||||
rules.unitcrashdamagemultiplier = Multiplicateur de Dégât de chute des Unités
|
||||
rules.unitcrashdamagemultiplier = Unit Crash Damage Multiplier
|
||||
rules.solarmultiplier = Multiplicateur de l'Efficacité des Panneaux Solaires
|
||||
rules.unitcapvariable = Les Noyaux contribuent à la limite d'Unités actives
|
||||
rules.unitcap = Limite d'Unités actives de Base
|
||||
@@ -1239,8 +1239,8 @@ rules.buildcostmultiplier = Multiplicateur du prix de construction
|
||||
rules.buildspeedmultiplier = Multiplicateur du temps de construction
|
||||
rules.deconstructrefundmultiplier = Multiplicateur du remboursement lors de la déconstruction
|
||||
rules.waitForWaveToEnd = Les Vagues attendent la mort des ennemis
|
||||
rules.wavelimit = La Partie termine après la Vague
|
||||
rules.dropzoneradius = Rayon d'Apparition des ennemis :[lightgray] (blocs)
|
||||
rules.wavelimit = Map Ends After Wave
|
||||
rules.dropzoneradius = Rayon d'Apparition des ennemis :[lightgray] (tuiles)
|
||||
rules.unitammo = Les Unités nécessitent des munitions
|
||||
rules.enemyteam = Équipe ennemie
|
||||
rules.playerteam = Équipe du joueur
|
||||
@@ -1587,9 +1587,9 @@ block.silicon-crucible.name = Grande Fonderie de Silicium
|
||||
block.overdrive-dome.name = Dôme Accélérant
|
||||
block.interplanetary-accelerator.name = Accélérateur Interplanétaire
|
||||
block.constructor.name = Constructeur
|
||||
block.constructor.description = Fabrique des structures d'une taille maximale de 2x2 (blocs).
|
||||
block.constructor.description = Fabrique des structures d'une taille maximale de 2x2 (tuiles).
|
||||
block.large-constructor.name = Grand Constructeur
|
||||
block.large-constructor.description = Fabrique des structures d'une taille maximale de 4x4 (blocs).
|
||||
block.large-constructor.description = Fabrique des structures d'une taille maximale de 4x4 (tuiles).
|
||||
block.deconstructor.name = Déconstructeur
|
||||
block.deconstructor.description = Déconstruit les structures et les unités. Retourne 100% du coût de construction.
|
||||
block.payload-loader.name = Chargeur de charge utile
|
||||
@@ -1789,7 +1789,6 @@ hint.launch = Une fois que vous avez collecté assez de ressources, vous pouvez
|
||||
hint.launch.mobile = Une fois que vous avez collecté assez de ressources, vous pouvez [accent]Lancer[] votre Noyau en sélectionnant un secteur depuis la \ue827 [accent]Carte[] dans le \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Retenez [accent][[F][] pour sélectionner des blocs dans une zone afin de les copier et les coller.\n\n[accent][[Clic du milieu][] pour copier un seul type de bloc.
|
||||
hint.rebuildSelect = Retenz [accent][[B][] et faites glissez pour selectionner les plans des blocs détruits.\nCela va automatiquement les reconstruire.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
|
||||
hint.conveyorPathfind = Retenez [accent][[Ctrl-gauche][] pendant que vous placez des convoyeurs, afin de générer un chemin automatiquement.
|
||||
hint.conveyorPathfind.mobile = Activez le mode \ue844 [accent]Diagonale[] et déplacez des convoyeurs, afin de générer un chemin automatiquement.
|
||||
@@ -2240,7 +2239,7 @@ lst.flushmessage = Affiche un message sur l'écran depuis la mémoire tampon de
|
||||
lst.cutscene = Manipule la caméra du joueur.
|
||||
lst.setflag = Définit un drapeau global qui peut être lu par tous les processeurs.
|
||||
lst.getflag = Vérifie si un drapeau global est présent.
|
||||
lst.setprop = Change une propriété d'une unité ou d'un bâtiment.
|
||||
lst.setprop = Sets a property of a unit or building.
|
||||
|
||||
logic.nounitbuild = [red]Les unités contrôlées par des processeurs ne peuvent pas construire ici.
|
||||
|
||||
@@ -2255,7 +2254,7 @@ laccess.controller = Le contrôleur de l'Unité.\nSi l'Unité est contrôlée pa
|
||||
laccess.dead = Retourne si l'Unité/Bâtiment est morte/détruit ou plus valide.
|
||||
laccess.controlled = Retourne:\n[accent]@ctrlProcessor[] si le contrôleur de l'Unité est un processeur\n[accent]@ctrlPlayer[] si l'Unité/Bâtiment est contrôlé par un joueur\n[accent]@ctrlFormation[] si l'Unité est en formation\nSinon, retourne 0.
|
||||
laccess.progress = Progression de l'action, 0 à 1.\nRenvoie la progression de la production, du rechargement de la tourelle ou de la construction.
|
||||
laccess.speed = La vitesse maximale d'une unité, en blocs/sec.
|
||||
laccess.speed = La vitesse maximale d'une unité, en tuiles/sec.
|
||||
|
||||
lcategory.unknown = Inconnu
|
||||
lcategory.unknown.description = Instructions sans catégorie.
|
||||
|
||||
@@ -1768,7 +1768,6 @@ hint.launch = Ha elegendő nyersanyagot gyűjtöttél, [accent]Kilőhetsz[] egy
|
||||
hint.launch.mobile = Ha elegendő nyersanyagot gyűjtöttél, [accent]Kilőhetsz[] egy közeli szektorba. Ezt a \ue88c [accent]Menü[]ből elérhető \ue827 [accent]Térkép[]en teheted meg.
|
||||
hint.schematicSelect = Az [accent][[F][] nyomva tartásával kijelölhetsz és másolhastz épületeket.\n\nKattints a [accent][[görgővel][], hogy egy épületet lemásolj.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Tartsd nyomva a [accent][[L-Ctrl][] billentyűt futószalagok lerakása közben, hogy a játék útvnalat generáljon.
|
||||
hint.conveyorPathfind.mobile = Enegdélyezd az \ue844 [accent]átlós mód[]ot és tagyél le egyszerre több futószalagot, hogy a játék útvonalat generáljon.
|
||||
hint.boost = Tartsd nyomva a [accent][[L-Shift][] billentyűt, hogy átrepülj az akadályok felett.\n\nErre nem minden földi egység képes.
|
||||
|
||||
@@ -1785,7 +1785,6 @@ hint.launch = Ketika sumber daya sudah mencukupi, kamu bisa [accent]Meluncurkan[
|
||||
hint.launch.mobile = Ketika sumber daya sudah mencukupi, kamu bisa [accent]Meluncurkan[] dengan memilih sektor terdekat dari \ue827 [accent]Map[] di \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Tahan [accent][[F][] dan tarik ke bangunan untuk menyalin bangunan.\n\n[accent][[Klik tengah][] untuk menyalin blok setipe.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Tahan [accent][[L-Ctrl][] ketika menarik pengantar untuk membuat jalur secara otomatis.
|
||||
hint.conveyorPathfind.mobile = Aktifkan \ue844 [accent]diagonal mode[] dan tarik pengantar untuk membuat jalur secara otomatis.
|
||||
hint.boost = Tahan [accent][[L-Shift][] untuk terbang dengan unit sekarang.\n\nHanya beberapa unit darat yang memiliki pendorong.
|
||||
|
||||
@@ -1770,7 +1770,6 @@ hint.launch = Una volta che sono state raccolte abbastanza risorse, puoi[accent]
|
||||
hint.launch.mobile = Una volta che sono state raccolte abbastanza risorse, puoi[accent]Lanciare[] selezionando settori vicini dalla \ue827 [accent]Mappa[] nel \ue88c [accent]menu[].
|
||||
hint.schematicSelect = Tieni premuto [accent][[F][] e trascina per selezionare blocchi da copiare ed incollare.\n\n[accent][[Middle Click][] per copiare un singolo tipo di blocco.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Tieni premuto [accent][[L-Ctrl][] mentre trascini nastri per generare automaticamente un percorso.
|
||||
hint.conveyorPathfind.mobile = Attiva la \ue844 [accent]modalità diagonale[] e trascina nastri per generare automaticamente un percorso.
|
||||
hint.boost = Tieni premuto [accent][[L-Shift][] per volare sopra gli ostacoli con la tua unità attuale.\n\nSolo poche unità terrestri possono farlo.
|
||||
|
||||
@@ -1773,7 +1773,6 @@ hint.launch = 十分な資源を確保できたら、右下の\ue827 [accent]マ
|
||||
hint.launch.mobile = 十分な資源を確保できたら、\ue88c [accent]メニュー[]の\ue827 [accent]マップ[]から、近くのセクターを選択して[accent]発射[]できます。
|
||||
hint.schematicSelect = [accent][[F][]を押しながらドラッグして、コピー&ペーストするブロックを選択します。\n\n[accent][[ミドルクリック][]により、1つのブロックタイプをコピーします。
|
||||
hint.rebuildSelect = [accent][[B][] を押したままドラッグして、破壊されたブロック計画を選択します。\nこれにより、それらが自動的に再建築されます。
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = [accent][[左-Ctrl][]を押しながらコンベアーをドラッグすると、経路が自動生成されます。
|
||||
hint.conveyorPathfind.mobile = \ue844 [accent]対角線モード[]を有効にし、コンベアーをドラッグすると経路が自動生成します。
|
||||
hint.boost = [accent][[左シフト][]を押したままにすると、操作中のユニットは障害物を飛び越えます。\n\n少数の地上ユニットのみがこのブースターを搭載しています。
|
||||
|
||||
@@ -1772,7 +1772,6 @@ hint.launch = 충분한 자원을 모았으면, 오른쪽 아래의 \ue827 [acce
|
||||
hint.launch.mobile = 충분한 자원을 모았으면, 오른쪽 아래의 \ue88c [accent]메뉴[]에 있는 \ue827 [accent]지도[]에서 주변 지역을 선택해서 [accent]출격[]할 수 있습니다.
|
||||
hint.schematicSelect = [accent][[F][]를 누른 채로 끌어서 복사하고 붙여넣을 블록을 선택하십시오. \n\n [accent][[마우스 휠][]을 누르면 한 개의 블록만 복사할 수 있습니다.
|
||||
hint.rebuildSelect = [accent][[B][]를 누르고 끌어서 파괴된 블록 흔적을 선택하세요.\n선택된 블록은 자동으로 복구됩니다.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = [accent][[왼쪽 Ctrl][]을 누른 채로 컨베이어를 대각선으로 끌면 길을 자동으로 만들어줍니다.
|
||||
hint.conveyorPathfind.mobile = \ue844 [accent]대각 모드[]를 활성화하고 컨베이어를 대각선으로 끌면 길을 자동으로 찾아줍니다.
|
||||
hint.boost = [accent][[왼쪽 Shift][]를 눌러 탑승한 기체로 장애물을 넘을 수 있습니다. \n\n 일부 지상 기체만 이륙할 수 있습니다.
|
||||
|
||||
@@ -1758,7 +1758,6 @@ hint.launch = Once enough resources are collected, you can [accent]Launch[] by s
|
||||
hint.launch.mobile = Once enough resources are collected, you can [accent]Launch[] by selecting nearby sectors from the \ue827 [accent]Map[] in the \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Hold [accent][[F][] and drag to select blocks to copy and paste.\n\n[accent][[Middle Click][] to copy a single block type.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
||||
hint.conveyorPathfind.mobile = Enable \ue844 [accent]diagonal mode[] and drag conveyors to automatically generate a path.
|
||||
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
||||
|
||||
@@ -1771,7 +1771,6 @@ hint.launch = Once enough resources are collected, you can [accent]Launch[] by s
|
||||
hint.launch.mobile = Once enough resources are collected, you can [accent]Launch[] by selecting nearby sectors from the \ue827 [accent]Map[] in the \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Hold [accent][[F][] and drag to select blocks to copy and paste.\n\n[accent][[Middle Click][] to copy a single block type.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
||||
hint.conveyorPathfind.mobile = Enable \ue844 [accent]diagonal mode[] and drag conveyors to automatically generate a path.
|
||||
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
||||
|
||||
@@ -1758,7 +1758,6 @@ hint.launch = Once enough resources are collected, you can [accent]Launch[] by s
|
||||
hint.launch.mobile = Once enough resources are collected, you can [accent]Launch[] by selecting nearby sectors from the \ue827 [accent]Map[] in the \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Hold [accent][[F][] and drag to select blocks to copy and paste.\n\n[accent][[Middle Click][] to copy a single block type.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
||||
hint.conveyorPathfind.mobile = Enable \ue844 [accent]diagonal mode[] and drag conveyors to automatically generate a path.
|
||||
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
||||
|
||||
@@ -1779,7 +1779,6 @@ hint.launch = Gdy zebrałeś wystarczająco materiałów możesz [accent]Wystrze
|
||||
hint.launch.mobile = Gdy zebrałeś wystarczająco materiałów możesz [accent]Wystrzelić[] do pobliskich sektorów klikając w \ue827 [accent]Mapę[] w \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Przytrzymaj [accent][[F][] by kopiować i wkleić bloki.\n\n[accent][[Środkowy przycisk myszy][] kopiuje pojedynczy blok.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Przeciągij i przytrzymaj [accent][[Lewy CTRL][] w trakcie budowania przenośników aby wygenerować ścieżkę.
|
||||
hint.conveyorPathfind.mobile = Włącz \ue844 [accent]tryb ukośny[] i przeciągnij w trakcie budowania przenośników aby wygenerować ścieżkę.
|
||||
hint.boost = Przytrzymaj [accent][[Lewy Shift][] by przelecieć ponad przeszkody.\n\nTylko część jednostek lądowych może to zrobić.
|
||||
|
||||
@@ -1780,7 +1780,6 @@ hint.launch = Quando recursos suficientes forem coletados, você pode [accent]La
|
||||
hint.launch.mobile = Quando recursos suficientes forem coletados, você pode [accent]Lançar[] selecionando setores próximos a partir do \ue827 [accent]Mapa[] no \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Segure [accent][[F][] e arraste para selecionar blocos para copiar e colar.\n\n[accent][[Middle Click][] para copiar um bloco só.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Segure [accent][[L-Ctrl][] enquanto arrasta as esteiras para gerar automaticamente um caminho.
|
||||
hint.conveyorPathfind.mobile = Ative o \ue844 [accent]modo diagonal[] e arraste as esteiras para gerar automaticamente um caminho.
|
||||
hint.boost = Segure [accent][[L-Shift][] para voar sobre obstáculos com a sua unidade.\n\nApenas algumas unidades terrestres tem propulsores.
|
||||
|
||||
@@ -1758,7 +1758,6 @@ hint.launch = Once enough resources are collected, you can [accent]Launch[] by s
|
||||
hint.launch.mobile = Once enough resources are collected, you can [accent]Launch[] by selecting nearby sectors from the \ue827 [accent]Map[] in the \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Hold [accent][[F][] and drag to select blocks to copy and paste.\n\n[accent][[Middle Click][] to copy a single block type.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
||||
hint.conveyorPathfind.mobile = Enable \ue844 [accent]diagonal mode[] and drag conveyors to automatically generate a path.
|
||||
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
||||
|
||||
@@ -1773,7 +1773,6 @@ hint.launch = Odată ce s-au strâns suficiente resurse, poți [accent]Lansa[] c
|
||||
hint.launch.mobile = Odată ce s-au strâns suficiente resurse, poți [accent]Lansa[] către o altă zonă selectând sectoarele învecinate folosind \ue827 [accent]Harta[] din \ue88c [accent]Meniu[].
|
||||
hint.schematicSelect = Ține apăsat [accent][[F][] și trage pt a selecta blocuri pt copiere.\n\n[accent][[Click pe rotiță][] pt a copia un singur tip de bloc.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Ține apăsat [accent][[Ctrl][] în timp ce plasezi benzi pt a genera automat o cale între 2 puncte.
|
||||
hint.conveyorPathfind.mobile = Activează \ue844 [accent]modul diagonal[] și plasează benzi pt a genera automat o cale între 2 puncte.
|
||||
hint.boost = Ține apăsat [accent][[Shift][] pt a zbura peste obstacole cu unitatea ta.\n\nDoar câteva unități de artilerie au propulsoare.
|
||||
|
||||
@@ -1773,7 +1773,6 @@ hint.launch = Как только будет собрано достаточно
|
||||
hint.launch.mobile = Как только будет собрано достаточно ресурсов, вы сможете осуществить [accent]Запуск[], выбрав близлежащие секторы на \ue827 [accent]Карте[] в \ue88c [accent]Меню[].
|
||||
hint.schematicSelect = Зажмите [accent][[F][] и переместите, чтобы выбрать блоки для копирования и вставки.\n\nЩелкните [accent][[колёсиком][] по блоку для копирования.
|
||||
hint.rebuildSelect = Удерживайте [accent][[B][] и перетаскивайте, чтобы выбрать уничтоженные блоки.\nОни будут перестроены автоматически.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Удерживайте [accent][[Л-Ctrl][] при размещении конвейеров для автоматической прокладки пути.
|
||||
hint.conveyorPathfind.mobile = Включите \ue844 [accent]диагональный режим[] и перетащите конвейеры для автоматической прокладки пути.
|
||||
hint.boost = Удерживайте [accent][[Л-Shift][], чтобы пролететь над препятствиями при помощи вашей единицы.\n\nТолько некоторые наземные единицы могут взлетать.
|
||||
|
||||
@@ -1776,7 +1776,6 @@ hint.launch = Jednom kada je dovoljno resursa skupljeno, možeš [accent]Lansira
|
||||
hint.launch.mobile = Jednom kada je dovoljno resursa skupljeno, možeš [accent]Lansirati[] tako što bi izabrao obljižnji sektor iz \ue827 [accent]Mape[] u \ue88c [accent]Meniju[].
|
||||
hint.schematicSelect = Drži [accent][[F][] i vuci da bi izabrao blokove da kopiraš i postaviš.\n\n[accent][[Srednji Klick][] Da iskopiraš samo jedan tip blokova.
|
||||
hint.rebuildSelect = Drži [accent][[B][] i vuci da bi izabrao planove izabranih blokova.\nOvo će automatski ponovo da ih sagradi.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Drži [accent][[L-Ctrl][] dok vučeš trake da automatski stvoriš put.
|
||||
hint.conveyorPathfind.mobile = Osposobi \ue844 [accent]dijagonalni mod[] dok vučeš trake da automatski stvoriš put.
|
||||
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
||||
|
||||
@@ -1758,7 +1758,6 @@ hint.launch = Once enough resources are collected, you can [accent]Launch[] by s
|
||||
hint.launch.mobile = Once enough resources are collected, you can [accent]Launch[] by selecting nearby sectors from the \ue827 [accent]Map[] in the \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Hold [accent][[F][] and drag to select blocks to copy and paste.\n\n[accent][[Middle Click][] to copy a single block type.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
||||
hint.conveyorPathfind.mobile = Enable \ue844 [accent]diagonal mode[] and drag conveyors to automatically generate a path.
|
||||
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
||||
|
||||
@@ -1781,7 +1781,6 @@ hint.launch = เมื่อเก็บทรัพยากรเยอะพ
|
||||
hint.launch.mobile = เมื่อเก็บทรัพยากรเยอะพอ คุณสามารถ[accent]ส่งแกนกลาง[]โดยการเลือกเซ็กเตอร์จาก \ue827 [accent]แผนที่[] ใน \ue88c [accent]เมนู[]
|
||||
hint.schematicSelect = กด [accent][[F][] แล้วลากเพื่อเลือกบล็อกที่จะคัดลอกและวาง\n\n[accent][[คลิ๊กกลาง][] เพื่อคัดลอกบล็อกชนิดเดียว
|
||||
hint.rebuildSelect = กด [accent][[B][] แล้วลากเพื่อเลือกแปลนบล็อกที่ถูกทำลาย\nแปลนบล็อกที่เลือกจะถูกสร้างใหม้โดยอัตโนมัติ
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = กด [accent][[L-Ctrl][] ในขณะที่กำลังลากสายพานเพื่อสร้างเส้นทางแบบอัตโนมัติ
|
||||
hint.conveyorPathfind.mobile = เปิดใช้งาน \ue844 [accent]โหมดแนวทแยง[] แล้วลากสายพานเพื่อสร้างเส้นทางแบบอัตโนมัติ
|
||||
hint.boost = กด [accent][[L-Shift][] เพื่อบูสต์ข้ามสิ่งกีดขวางด้วยยูนิตของคุณ\n\nยูนิตพื้นดินบางประเภทเท่านั้นที่บินได้
|
||||
|
||||
@@ -1758,7 +1758,6 @@ hint.launch = Once enough resources are collected, you can [accent]Launch[] by s
|
||||
hint.launch.mobile = Once enough resources are collected, you can [accent]Launch[] by selecting nearby sectors from the \ue827 [accent]Map[] in the \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Hold [accent][[F][] and drag to select blocks to copy and paste.\n\n[accent][[Middle Click][] to copy a single block type.
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Hold [accent][[L-Ctrl][] while dragging conveyors to automatically generate a path.
|
||||
hint.conveyorPathfind.mobile = Enable \ue844 [accent]diagonal mode[] and drag conveyors to automatically generate a path.
|
||||
hint.boost = Hold [accent][[L-Shift][] to fly over obstacles with your current unit.\n\nOnly a few ground units have boosters.
|
||||
|
||||
@@ -1774,7 +1774,6 @@ hint.launch = Yeterince kaynak topladıktan sonra, üssünüzü başka bir sekt
|
||||
hint.launch.mobile = Yeterince kaynak topladıktan sonra, üssünüzü başka bir sektöre [accent]fırlatmak[] için sağ alttaki \ue88c [accent]menüden[] \ue827 [accent]harita[] tuşuna basın.
|
||||
hint.schematicSelect = İstediğiniz blokları kopyalayıp yapıştırmak için [accent][[F][] tuşunu basılı tutun ve farenizi sürükleyin.\n\n[accent][[Orta Tuş'a (Fare Tekerleği'ne)][] basarak tek bir blok seçebilirsiniz.
|
||||
hint.rebuildSelect = [accent][[B][] ye basılı tutarak, yok edilmiş blokları seç.\nBu binaları yeniden inşaa etmeni sağlar.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Konveyörler ile yol yaparken bir noktadan diğer noktaya otomatik yol oluşturmak için [accent][[Sol CTRL][] tuşunu basılı tutun.
|
||||
hint.conveyorPathfind.mobile = Konveyörler ile yol yaparken bir noktadan diğer noktaya otomatik yol oluşturmak için \ue844 [accent]Çapraz Mod'u[] etkinleştirin.
|
||||
hint.boost = Bazı yer birimleri duvarların, taretlerin, diğer birimlerin üstünden uçma özelliği vardır. [accent][[Sol Shift][] tuşunu basılı tutarak bazı yer üniteleri ile uçabilirsiniz.
|
||||
|
||||
@@ -1787,7 +1787,6 @@ hint.launch = Як тільки буде зібрано достатньо ре
|
||||
hint.launch.mobile = Як тільки буде зібрано достатньо ресурсів, ви зможете зробити [accent]Запуск[] за допомогою вибору найближчих секторів з \ue827 [accent]мапи[] у \ue88c [accent]меню[].
|
||||
hint.schematicSelect = Утримуйте [accent][[F][] і тягніть, щоби вибрати блоки для їхнього подальшого копіювання і вставлення.\n\nНатисніть [accent][[СКМ][], щоби скопіювати певний тип блоку.
|
||||
hint.rebuildSelect = Утримуючи [accent][[B][], протягніть, щоби вибрати зруйновані проєкти блоків.\nЦе призведе до їхнього автоматичного відновлення.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
|
||||
hint.conveyorPathfind = Утримуйте [accent][[лівий Ctrl][], коли тягнете конвеєри, щоб автоматично прокласти шлях.
|
||||
hint.conveyorPathfind.mobile = Увімкніть \ue844 [accent]діагональний режим[] і тягніть конвеєри, щоб автоматично прокласти шлях.
|
||||
|
||||
@@ -1775,7 +1775,6 @@ hint.launch = Sau khi thu thập đủ tài nguyên, bạn có thể [accent]Ph
|
||||
hint.launch.mobile = Sau khi thu thập đủ tài nguyên, bạn có thể [accent]Phóng[] bằng cách chọn các khu vực lân cận từ \ue827 [accent]Bản đồ[] trong \ue88c [accent]Menu[].
|
||||
hint.schematicSelect = Giữ [accent][[F][] và kéo để chọn các khối để sao chép và dán.\n\n[accent][[Middle Click][] để sao chép một khối.
|
||||
hint.rebuildSelect = Giữ [accent][[B][] và kéo để chọn các khối bị hỏng.\nChúng sẽ được tự động được xây lại.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = Giữ [accent][[L-Ctrl][] trong khi kéo băng chuyền để tự động tạo đường dẫn.
|
||||
hint.conveyorPathfind.mobile = Mở \ue844 [accent]chế độ đường chéo[] và kéo băng chuyền để tự động tạo đường dẫn.
|
||||
hint.boost = Giữ [accent][[L-Shift][] bay qua các chướng ngại vật với quân lính hiện tại của bạn.\n\nChỉ một số quân lính mặt đất có thể bay được.
|
||||
|
||||
@@ -1788,7 +1788,6 @@ hint.launch = 一旦收集了足够的资源,您就可以通过右下角的\ue
|
||||
hint.launch.mobile = 一旦收集到足够的资源,您就可以通过\ue88c[accent]菜单[]中的\ue827[accent]地图[]选择附近的区块[accent]发射[]核心。
|
||||
hint.schematicSelect = 按住[accent][[F][]键用鼠标框选建筑以复制粘贴。 \n\n[accent][鼠标中键][]复制单个建筑。
|
||||
hint.rebuildSelect = 按住[accent][[B][]用鼠标框选被摧毁的建筑以自动重建。
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
|
||||
hint.conveyorPathfind = 按住[accent][[L-Ctrl][]键并拖动传送带,使其自动寻路。
|
||||
hint.conveyorPathfind.mobile = 启用\ue844[accent]传送带自动寻路[]后,拖动传送带可使其自动寻路。
|
||||
|
||||
@@ -1784,7 +1784,6 @@ hint.launch = 一旦蒐集到足夠的資源,你可以透過右下角的 \ue82
|
||||
hint.launch.mobile = 一旦蒐集到足夠的資源,你可以透過選單中的 \ue827 [accent]地圖[]來選取你要[accent]發射[]的區域。
|
||||
hint.schematicSelect = 按住[accent][[F][]並拖曳可以選取方塊並貼上。\n\n按下[accent][[滑鼠中鍵][]可以複製單一方塊。
|
||||
hint.rebuildSelect = Hold [accent][[B][] and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.rebuildSelect.mobile = Select the \ue874 copy button, then tap the \ue80f rebuild button and drag to select destroyed block plans.\nThis will rebuild them automatically.
|
||||
hint.conveyorPathfind = 在建造輸送帶時按下[accent][[L-Ctrl][]可以自動產生路徑。
|
||||
hint.conveyorPathfind.mobile = 啟用 \ue844 [accent]對角線模式[]可以在建造輸送帶時自動產生路徑。
|
||||
hint.boost = 按住[accent][[L-Shift][]可以帶著你的機甲一起飛越障礙物\n\n只有少數陸行機甲有推進器。
|
||||
|
||||
@@ -154,5 +154,3 @@ zenonet
|
||||
AyuKo-o
|
||||
JojoFR1
|
||||
Xasmedy
|
||||
xStaBUx
|
||||
WayZer
|
||||
|
||||
@@ -3055,7 +3055,7 @@ public class Blocks{
|
||||
progress = PartProgress.recoil;
|
||||
recoilIndex = f;
|
||||
under = true;
|
||||
moveY = -1.5f;
|
||||
moves.add(new PartMove(PartProgress.recoil, 0f, -1.5f, 0f));
|
||||
}});
|
||||
}
|
||||
}};
|
||||
@@ -3122,15 +3122,6 @@ public class Blocks{
|
||||
}};
|
||||
}}
|
||||
);
|
||||
|
||||
drawer = new DrawTurret(){{
|
||||
parts.add(new RegionPart("-mid"){{
|
||||
progress = PartProgress.recoil;
|
||||
under = true;
|
||||
moveY = -1f;
|
||||
}});
|
||||
}};
|
||||
|
||||
reload = 18f;
|
||||
range = 220f;
|
||||
size = 2;
|
||||
@@ -3139,7 +3130,7 @@ public class Blocks{
|
||||
shoot.shotDelay = 5f;
|
||||
shoot.shots = 2;
|
||||
|
||||
recoil = 1f;
|
||||
recoil = 2f;
|
||||
rotateSpeed = 15f;
|
||||
inaccuracy = 17f;
|
||||
shootCone = 35f;
|
||||
@@ -3488,21 +3479,12 @@ public class Blocks{
|
||||
}}
|
||||
);
|
||||
|
||||
drawer = new DrawTurret(){{
|
||||
parts.add(new RegionPart("-barrel"){{
|
||||
progress = PartProgress.recoil.delay(0.5f); //Since recoil is 1-0, cut from the start instead of the end.
|
||||
under = true;
|
||||
turretHeatLayer = Layer.turret - 0.0001f;
|
||||
moveY = -1.5f;
|
||||
}});
|
||||
}};
|
||||
|
||||
size = 2;
|
||||
range = 190f;
|
||||
reload = 31f;
|
||||
consumeAmmoOnce = false;
|
||||
ammoEjectBack = 3f;
|
||||
recoil = 2f;
|
||||
recoil = 3f;
|
||||
shake = 1f;
|
||||
shoot.shots = 4;
|
||||
shoot.shotDelay = 3f;
|
||||
@@ -3794,8 +3776,7 @@ public class Blocks{
|
||||
explodeRange = 20f;
|
||||
}}
|
||||
);
|
||||
shootY = 10f;
|
||||
|
||||
shootY = 8.75f;
|
||||
shoot = new ShootBarrel(){{
|
||||
barrels = new float[]{
|
||||
0f, 1f, 0f,
|
||||
@@ -3803,25 +3784,10 @@ public class Blocks{
|
||||
-3f, 0f, 0f,
|
||||
};
|
||||
}};
|
||||
|
||||
recoils = 3;
|
||||
drawer = new DrawTurret(){{
|
||||
for(int i = 3; i > 0; i--){
|
||||
int f = i;
|
||||
parts.add(new RegionPart("-barrel-" + i){{
|
||||
progress = PartProgress.recoil;
|
||||
recoilIndex = f - 1;
|
||||
under = true;
|
||||
moveY = -2f;
|
||||
}});
|
||||
}
|
||||
}};
|
||||
|
||||
reload = 8f;
|
||||
range = 200f;
|
||||
size = 3;
|
||||
recoil = 1.5f;
|
||||
recoilTime = 10;
|
||||
recoil = 3f;
|
||||
rotateSpeed = 10f;
|
||||
inaccuracy = 10f;
|
||||
shootCone = 30f;
|
||||
|
||||
@@ -72,8 +72,6 @@ public class Renderer implements ApplicationListener{
|
||||
landPTimer,
|
||||
//intensity for screen shake
|
||||
shakeIntensity,
|
||||
//reduction rate of screen shake
|
||||
shakeReduction,
|
||||
//current duration of screen shake
|
||||
shakeTime;
|
||||
//for landTime > 0: if true, core is currently *launching*, otherwise landing.
|
||||
@@ -85,15 +83,14 @@ public class Renderer implements ApplicationListener{
|
||||
Shaders.init();
|
||||
|
||||
Events.on(ResetEvent.class, e -> {
|
||||
shakeTime = shakeIntensity = shakeReduction = 0f;
|
||||
shakeTime = shakeIntensity = 0f;
|
||||
camShakeOffset.setZero();
|
||||
});
|
||||
}
|
||||
|
||||
public void shake(float intensity, float duration){
|
||||
shakeIntensity = Math.max(shakeIntensity, Mathf.clamp(intensity, 0, 100));
|
||||
shakeIntensity = Math.max(shakeIntensity, intensity);
|
||||
shakeTime = Math.max(shakeTime, duration);
|
||||
shakeReduction = shakeIntensity / shakeTime;
|
||||
}
|
||||
|
||||
public void addEnvRenderer(int mask, Runnable render){
|
||||
@@ -213,7 +210,7 @@ public class Renderer implements ApplicationListener{
|
||||
float intensity = shakeIntensity * (settings.getInt("screenshake", 4) / 4f) * 0.75f;
|
||||
camShakeOffset.setToRandomDirection().scl(Mathf.random(intensity));
|
||||
camera.position.add(camShakeOffset);
|
||||
shakeIntensity -= shakeReduction * Time.delta;
|
||||
shakeIntensity -= 0.25f * Time.delta;
|
||||
shakeTime -= Time.delta;
|
||||
shakeIntensity = Mathf.clamp(shakeIntensity, 0f, 100f);
|
||||
}else{
|
||||
|
||||
@@ -51,7 +51,7 @@ public class UI implements ApplicationListener, Loadable{
|
||||
public AboutDialog about;
|
||||
public GameOverDialog restart;
|
||||
public CustomGameDialog custom;
|
||||
public EditorMapsDialog maps;
|
||||
public MapsDialog maps;
|
||||
public LoadDialog load;
|
||||
public DiscordDialog discord;
|
||||
public JoinDialog join;
|
||||
@@ -85,14 +85,6 @@ public class UI implements ApplicationListener, Loadable{
|
||||
Fonts.loadFonts();
|
||||
}
|
||||
|
||||
public static void loadColors(){
|
||||
Colors.put("accent", Pal.accent);
|
||||
Colors.put("unlaunched", Color.valueOf("8982ed"));
|
||||
Colors.put("highlight", Pal.accent.cpy().lerp(Color.white, 0.3f));
|
||||
Colors.put("stat", Pal.stat);
|
||||
Colors.put("negstat", Pal.negativeStat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAsync(){
|
||||
|
||||
@@ -100,8 +92,6 @@ public class UI implements ApplicationListener, Loadable{
|
||||
|
||||
@Override
|
||||
public void loadSync(){
|
||||
loadColors();
|
||||
|
||||
Fonts.outline.getData().markupEnabled = true;
|
||||
Fonts.def.getData().markupEnabled = true;
|
||||
Fonts.def.setOwnsTexture(false);
|
||||
@@ -135,6 +125,12 @@ public class UI implements ApplicationListener, Loadable{
|
||||
|
||||
ClickListener.clicked = () -> Sounds.press.play();
|
||||
|
||||
Colors.put("accent", Pal.accent);
|
||||
Colors.put("unlaunched", Color.valueOf("8982ed"));
|
||||
Colors.put("highlight", Pal.accent.cpy().lerp(Color.white, 0.3f));
|
||||
Colors.put("stat", Pal.stat);
|
||||
Colors.put("negstat", Pal.negativeStat);
|
||||
|
||||
drillCursor = Core.graphics.newCursor("drill", Fonts.cursorScale());
|
||||
unloadCursor = Core.graphics.newCursor("unload", Fonts.cursorScale());
|
||||
targetCursor = Core.graphics.newCursor("target", Fonts.cursorScale());
|
||||
@@ -199,7 +195,7 @@ public class UI implements ApplicationListener, Loadable{
|
||||
bans = new BansDialog();
|
||||
admins = new AdminsDialog();
|
||||
traces = new TraceDialog();
|
||||
maps = new EditorMapsDialog();
|
||||
maps = new MapsDialog();
|
||||
content = new ContentInfoDialog();
|
||||
planet = new PlanetDialog();
|
||||
research = new ResearchDialog();
|
||||
|
||||
@@ -53,9 +53,7 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{
|
||||
while(it.hasNext()){
|
||||
BuildPlan plan = it.next();
|
||||
Tile tile = world.tile(plan.x, plan.y);
|
||||
if(tile == null || (plan.breaking && tile.block() == Blocks.air) || (!plan.breaking && ((tile.build != null && tile.build.rotation == plan.rotation) || !plan.block.rotate) &&
|
||||
(tile.block() == plan.block || (plan.block != null && (plan.block.isOverlay() && plan.block == tile.overlay() || (plan.block.isFloor() && plan.block == tile.floor())))))){
|
||||
|
||||
if(tile == null || (plan.breaking && tile.block() == Blocks.air) || (!plan.breaking && ((tile.build != null && tile.build.rotation == plan.rotation) || !plan.block.rotate) && tile.block() == plan.block)){
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
|
||||
private transient boolean sleeping;
|
||||
private transient float sleepTime;
|
||||
private transient boolean initialized;
|
||||
private transient boolean initialized, wasAdded;
|
||||
|
||||
/** Sets this tile entity data to this and adds it if necessary. */
|
||||
public Building init(Tile tile, Team team, boolean shouldAdd, int rotation){
|
||||
@@ -174,6 +174,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
//endregion
|
||||
//region io
|
||||
|
||||
/** certain blocks merge liquid graphs, so it is necessary to provide a fake one at write-time */
|
||||
public LiquidModule writeLiquids(){
|
||||
return liquids;
|
||||
}
|
||||
|
||||
public final void writeBase(Writes write){
|
||||
boolean writeVisibility = state.rules.fog && visibleFlags != 0;
|
||||
|
||||
@@ -186,7 +191,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
write.b(moduleBitmask());
|
||||
if(items != null) items.write(write);
|
||||
if(power != null) power.write(write);
|
||||
if(liquids != null) liquids.write(write);
|
||||
if(liquids != null) writeLiquids().write(write);
|
||||
|
||||
//efficiency is written as two bytes to save space
|
||||
write.b((byte)(Mathf.clamp(efficiency) * 255f));
|
||||
@@ -820,6 +825,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
|
||||
if(!net.client() && state.isCampaign() && team == state.rules.defaultTeam) liquid.unlock();
|
||||
|
||||
float selfCapacity = liquidCapacity();
|
||||
|
||||
for(int i = 0; i < proximity.size; i++){
|
||||
incrementDump(proximity.size);
|
||||
|
||||
@@ -829,10 +836,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
other = other.getLiquidDestination(self(), liquid);
|
||||
|
||||
if(other != null && other.team == team && other.block.hasLiquids && canDumpLiquid(other, liquid) && other.liquids != null){
|
||||
float ofract = other.liquids.get(liquid) / other.block.liquidCapacity;
|
||||
float fract = liquids.get(liquid) / block.liquidCapacity;
|
||||
float ofract = other.liquids.get(liquid) / other.liquidCapacity();
|
||||
float fract = liquids.get(liquid) / selfCapacity;
|
||||
|
||||
if(ofract < fract) transferLiquid(other, (fract - ofract) * block.liquidCapacity / scaling, liquid);
|
||||
if(ofract < fract) transferLiquid(other, (fract - ofract) * selfCapacity / scaling, liquid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -842,7 +849,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
}
|
||||
|
||||
public void transferLiquid(Building next, float amount, Liquid liquid){
|
||||
float flow = Math.min(next.block.liquidCapacity - next.liquids.get(liquid), amount);
|
||||
float flow = Math.min(next.liquidCapacity() - next.liquids.get(liquid), amount);
|
||||
|
||||
if(next.acceptLiquid(self(), liquid)){
|
||||
next.handleLiquid(self(), liquid, flow);
|
||||
@@ -869,19 +876,20 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
if(next == null) return 0;
|
||||
|
||||
next = next.getLiquidDestination(self(), liquid);
|
||||
float selfCapacity = liquidCapacity(), nextCapacity = next.liquidCapacity();
|
||||
|
||||
if(next.team == team && next.block.hasLiquids && liquids.get(liquid) > 0f){
|
||||
float ofract = next.liquids.get(liquid) / next.block.liquidCapacity;
|
||||
float fract = liquids.get(liquid) / block.liquidCapacity * block.liquidPressure;
|
||||
float flow = Math.min(Mathf.clamp((fract - ofract)) * (block.liquidCapacity), liquids.get(liquid));
|
||||
flow = Math.min(flow, next.block.liquidCapacity - next.liquids.get(liquid));
|
||||
float ofract = next.liquids.get(liquid) / nextCapacity;
|
||||
float fract = liquids.get(liquid) / selfCapacity * block.liquidPressure;
|
||||
float flow = Math.min(Mathf.clamp((fract - ofract)) * selfCapacity, liquids.get(liquid));
|
||||
flow = Math.min(flow, nextCapacity - next.liquids.get(liquid));
|
||||
|
||||
if(flow > 0f && ofract <= fract && next.acceptLiquid(self(), liquid)){
|
||||
next.handleLiquid(self(), liquid, flow);
|
||||
liquids.remove(liquid, flow);
|
||||
return flow;
|
||||
//handle reactions between different liquid types ▼
|
||||
}else if(!next.block.consumesLiquid(liquid) && next.liquids.currentAmount() / next.block.liquidCapacity > 0.1f && fract > 0.1f){
|
||||
}else if(!next.block.consumesLiquid(liquid) && next.liquids.currentAmount() / nextCapacity > 0.1f && fract > 0.1f){
|
||||
//TODO !IMPORTANT! uses current(), which is 1) wrong for multi-liquid blocks and 2) causes unwanted reactions, e.g. hydrogen + slag in pump
|
||||
//TODO these are incorrect effect positions
|
||||
float fx = (x + next.x) / 2f, fy = (y + next.y) / 2f;
|
||||
@@ -907,6 +915,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Override to set a custom liquid capacity, e.g. for blocks with shared inventories. */
|
||||
public float liquidCapacity(){
|
||||
return block.liquidCapacity;
|
||||
}
|
||||
|
||||
public Building getLiquidDestination(Building from, Liquid liquid){
|
||||
return self();
|
||||
}
|
||||
@@ -1074,6 +1087,9 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
noSleep();
|
||||
}
|
||||
|
||||
/** Like onProximityAdded, but only called once. Essentially does what onProximityAdded was supposed to. */
|
||||
public void onAdded(){}
|
||||
|
||||
public void updatePowerGraph(){
|
||||
for(Building other : getPowerConnections(tempBuilds)){
|
||||
if(other.power != null){
|
||||
@@ -1679,6 +1695,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
other.onProximityUpdate();
|
||||
}
|
||||
proximity.clear();
|
||||
wasAdded = false;
|
||||
}
|
||||
|
||||
public void rotated(int prevRotation, int newRotation){
|
||||
|
||||
}
|
||||
|
||||
public void updateProximity(){
|
||||
@@ -1701,6 +1722,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
proximity.add(tile);
|
||||
}
|
||||
|
||||
if(!wasAdded){
|
||||
onAdded();
|
||||
wasAdded = true;
|
||||
}
|
||||
onProximityAdded();
|
||||
onProximityUpdate();
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package mindustry.entities.comp;
|
||||
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.blocks.liquid.Conduit.*;
|
||||
|
||||
@EntityDef(value = ConduitGraphUpdaterc.class, serialize = false, genio = false)
|
||||
@Component
|
||||
abstract class ConduitGraphUpdaterComp implements Entityc{
|
||||
public transient ConduitGraph graph;
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
graph.update();
|
||||
}
|
||||
}
|
||||
@@ -323,7 +323,13 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
|
||||
}
|
||||
|
||||
void sendMessage(String text){
|
||||
sendMessage(text, null, null);
|
||||
if(isLocal()){
|
||||
if(ui != null){
|
||||
ui.chatfrag.addMessage(text);
|
||||
}
|
||||
}else{
|
||||
Call.sendMessage(con, text, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
void sendMessage(String text, Player from){
|
||||
@@ -340,14 +346,6 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
|
||||
}
|
||||
}
|
||||
|
||||
void sendUnformatted(String unformatted){
|
||||
sendUnformatted(null, unformatted);
|
||||
}
|
||||
|
||||
void sendUnformatted(Player from, String unformatted){
|
||||
sendMessage(netServer.chatFormatter.format(from, unformatted), from, unformatted);
|
||||
}
|
||||
|
||||
PlayerInfo getInfo(){
|
||||
if(isLocal()){
|
||||
throw new IllegalArgumentException("Local players cannot be traced and do not have info.");
|
||||
|
||||
@@ -78,8 +78,8 @@ public class RegionPart extends DrawPart{
|
||||
mx += move.x * p;
|
||||
my += move.y * p;
|
||||
mr += move.rot * p;
|
||||
gx += move.gx * p;
|
||||
gy += move.gy * p;
|
||||
gx += move.gx;
|
||||
gy += move.gy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ public class RegionPart extends DrawPart{
|
||||
//can be null
|
||||
var region = drawRegion ? regions[Math.min(i, regions.length - 1)] : null;
|
||||
float sign = (i == 0 ? 1 : -1) * params.sideMultiplier;
|
||||
Tmp.v1.set((x + mx) * sign, y + my).rotateRadExact((params.rotation - 90) * Mathf.degRad);
|
||||
Tmp.v1.set((x + mx) * sign * Draw.xscl, (y + my) * Draw.yscl).rotateRadExact((params.rotation - 90) * Mathf.degRad);
|
||||
|
||||
float
|
||||
rx = params.x + Tmp.v1.x,
|
||||
|
||||
@@ -257,13 +257,13 @@ public class EventType{
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when a specific building has its configuration changed. */
|
||||
/** Called when the player configures a specific building. */
|
||||
public static class ConfigEvent{
|
||||
public final Building tile;
|
||||
public final @Nullable Player player;
|
||||
public final Player player;
|
||||
public final Object value;
|
||||
|
||||
public ConfigEvent(Building tile, @Nullable Player player, Object value){
|
||||
public ConfigEvent(Building tile, Player player, Object value){
|
||||
this.tile = tile;
|
||||
this.player = player;
|
||||
this.value = value;
|
||||
@@ -473,18 +473,6 @@ public class EventType{
|
||||
}
|
||||
}
|
||||
|
||||
public static class BuildRotateEvent{
|
||||
public final Building build;
|
||||
public final @Nullable Unit unit;
|
||||
public final int previous;
|
||||
|
||||
public BuildRotateEvent(Building build, @Nullable Unit unit, int previous){
|
||||
this.build = build;
|
||||
this.unit = unit;
|
||||
this.previous = previous;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player or drone begins building something.
|
||||
* This does not necessarily happen when a new ConstructBlock is created.
|
||||
|
||||
@@ -138,7 +138,7 @@ public class SpawnGroup implements JsonSerializable, Cloneable{
|
||||
shieldScaling = data.getFloat("shieldScaling", 0);
|
||||
unitAmount = data.getInt("amount", 1);
|
||||
spawn = data.getInt("spawn", -1);
|
||||
if(data.has("payloads")) payloads = Seq.with(json.readValue(String[].class, data.get("payloads"))).map(content::unit).removeAll(t -> t == null);
|
||||
if(data.has("payloads")) payloads = Seq.with(json.readValue(String[].class, data.get("payloads"))).map(s -> content.unit(s));
|
||||
if(data.has("items")) items = json.readValue(ItemStack.class, data.get("items"));
|
||||
|
||||
|
||||
|
||||
@@ -12,15 +12,20 @@ import arc.scene.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.Teams.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.input.Placement.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static arc.Core.*;
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.input.PlaceMode.*;
|
||||
@@ -114,7 +119,19 @@ public class DesktopInput extends InputHandler{
|
||||
if(Core.input.keyDown(Binding.schematic_select)){
|
||||
drawSelection(schemX, schemY, cursorX, cursorY, Vars.maxSchematicSize);
|
||||
}else if(Core.input.keyDown(Binding.rebuild_select)){
|
||||
drawRebuildSelection(schemX, schemY, cursorX, cursorY);
|
||||
//TODO color?
|
||||
drawSelection(schemX, schemY, cursorX, cursorY, 0, Pal.sapBulletBack, Pal.sapBullet);
|
||||
|
||||
NormalizeDrawResult result = Placement.normalizeDrawArea(Blocks.air, schemX, schemY, cursorX, cursorY, false, 0, 1f);
|
||||
|
||||
Tmp.r1.set(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
|
||||
|
||||
for(BlockPlan plan : player.team().data().plans){
|
||||
Block block = content.block(plan.block);
|
||||
if(block.bounds(plan.x, plan.y, Tmp.r2).overlaps(Tmp.r1)){
|
||||
drawSelected(plan.x, plan.y, content.block(plan.block), Pal.sapBullet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,8 +529,20 @@ public class DesktopInput extends InputHandler{
|
||||
schemX = -1;
|
||||
schemY = -1;
|
||||
}else if(input.keyRelease(Binding.rebuild_select)){
|
||||
//TODO rebuild!!!
|
||||
|
||||
NormalizeResult result = Placement.normalizeArea(schemX, schemY, rawCursorX, rawCursorY, rotation, false, 999999999);
|
||||
Tmp.r1.set(result.x * tilesize, result.y * tilesize, (result.x2 - result.x) * tilesize, (result.y2 - result.y) * tilesize);
|
||||
|
||||
Iterator<BlockPlan> broken = player.team().data().plans.iterator();
|
||||
while(broken.hasNext()){
|
||||
BlockPlan plan = broken.next();
|
||||
Block block = content.block(plan.block);
|
||||
if(block.bounds(plan.x, plan.y, Tmp.r2).overlaps(Tmp.r1)){
|
||||
player.unit().addBuild(new BuildPlan(plan.x, plan.y, plan.rotation, content.block(plan.block), plan.config));
|
||||
}
|
||||
}
|
||||
|
||||
rebuildArea(schemX, schemY, rawCursorX, rawCursorY);
|
||||
schemX = -1;
|
||||
schemY = -1;
|
||||
}
|
||||
|
||||
@@ -464,12 +464,12 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
}
|
||||
|
||||
if(player != null) build.lastAccessed = player.name;
|
||||
int previous = build.rotation;
|
||||
build.rotation = Mathf.mod(build.rotation + Mathf.sign(direction), 4);
|
||||
int newRotation = Mathf.mod(build.rotation + Mathf.sign(direction), 4), prev = build.rotation;
|
||||
build.rotation = newRotation;
|
||||
build.updateProximity();
|
||||
build.rotated(prev, newRotation);
|
||||
build.noSleep();
|
||||
Fx.rotateBlock.at(build.x, build.y, build.block.size);
|
||||
Events.fire(new BuildRotateEvent(build, player.unit(), previous));
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.both, forward = true)
|
||||
@@ -1166,21 +1166,6 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
Lines.rect(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
|
||||
}
|
||||
|
||||
protected void drawRebuildSelection(int x, int y, int x2, int y2){
|
||||
drawSelection(x, y, x2, y2, 0, Pal.sapBulletBack, Pal.sapBullet);
|
||||
|
||||
NormalizeDrawResult result = Placement.normalizeDrawArea(Blocks.air, x, y, x2, y2, false, 0, 1f);
|
||||
|
||||
Tmp.r1.set(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
|
||||
|
||||
for(BlockPlan plan : player.team().data().plans){
|
||||
Block block = content.block(plan.block);
|
||||
if(block.bounds(plan.x, plan.y, Tmp.r2).overlaps(Tmp.r1)){
|
||||
drawSelected(plan.x, plan.y, content.block(plan.block), Pal.sapBullet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawBreakSelection(int x1, int y1, int x2, int y2){
|
||||
drawBreakSelection(x1, y1, x2, y2, maxLength);
|
||||
}
|
||||
@@ -1668,20 +1653,6 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
}
|
||||
}
|
||||
|
||||
public void rebuildArea(int x, int y, int x2, int y2){
|
||||
NormalizeResult result = Placement.normalizeArea(x, y, x2, y2, rotation, false, 999999999);
|
||||
Tmp.r1.set(result.x * tilesize, result.y * tilesize, (result.x2 - result.x) * tilesize, (result.y2 - result.y) * tilesize);
|
||||
|
||||
Iterator<BlockPlan> broken = player.team().data().plans.iterator();
|
||||
while(broken.hasNext()){
|
||||
BlockPlan plan = broken.next();
|
||||
Block block = content.block(plan.block);
|
||||
if(block.bounds(plan.x, plan.y, Tmp.r2).overlaps(Tmp.r1)){
|
||||
player.unit().addBuild(new BuildPlan(plan.x, plan.y, plan.rotation, content.block(plan.block), plan.config));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void tryBreakBlock(int x, int y){
|
||||
if(validBreak(x, y)){
|
||||
breakBlock(x, y);
|
||||
|
||||
@@ -55,7 +55,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
/** Whether the player is currently shifting all placed tiles. */
|
||||
public boolean selecting;
|
||||
/** Whether the player is currently in line-place mode. */
|
||||
public boolean lineMode, schematicMode, rebuildMode;
|
||||
public boolean lineMode, schematicMode;
|
||||
/** Current place mode. */
|
||||
public PlaceMode mode = none;
|
||||
/** Whether no recipe was available when switching to break mode. */
|
||||
@@ -208,8 +208,6 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
if(schematicMode){
|
||||
block = null;
|
||||
mode = none;
|
||||
}else{
|
||||
rebuildMode = false;
|
||||
}
|
||||
}
|
||||
}).update(i -> {
|
||||
@@ -221,45 +219,37 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
});
|
||||
|
||||
//confirm button
|
||||
table.button(Icon.ok, Styles.clearNoneTogglei, () -> {
|
||||
if(schematicMode){
|
||||
rebuildMode = !rebuildMode;
|
||||
}else{
|
||||
for(BuildPlan plan : selectPlans){
|
||||
Tile tile = plan.tile();
|
||||
table.button(Icon.ok, Styles.clearNonei, () -> {
|
||||
for(BuildPlan plan : selectPlans){
|
||||
Tile tile = plan.tile();
|
||||
|
||||
//actually place/break all selected blocks
|
||||
if(tile != null){
|
||||
if(!plan.breaking){
|
||||
if(validPlace(plan.x, plan.y, plan.block, plan.rotation)){
|
||||
BuildPlan other = getPlan(plan.x, plan.y, plan.block.size, null);
|
||||
BuildPlan copy = plan.copy();
|
||||
//actually place/break all selected blocks
|
||||
if(tile != null){
|
||||
if(!plan.breaking){
|
||||
if(validPlace(plan.x, plan.y, plan.block, plan.rotation)){
|
||||
BuildPlan other = getPlan(plan.x, plan.y, plan.block.size, null);
|
||||
BuildPlan copy = plan.copy();
|
||||
|
||||
if(other == null){
|
||||
player.unit().addBuild(copy);
|
||||
}else if(!other.breaking && other.x == plan.x && other.y == plan.y && other.block.size == plan.block.size){
|
||||
player.unit().plans().remove(other);
|
||||
player.unit().addBuild(copy);
|
||||
}
|
||||
if(other == null){
|
||||
player.unit().addBuild(copy);
|
||||
}else if(!other.breaking && other.x == plan.x && other.y == plan.y && other.block.size == plan.block.size){
|
||||
player.unit().plans().remove(other);
|
||||
player.unit().addBuild(copy);
|
||||
}
|
||||
|
||||
rotation = plan.rotation;
|
||||
}else{
|
||||
tryBreakBlock(tile.x, tile.y);
|
||||
}
|
||||
|
||||
rotation = plan.rotation;
|
||||
}else{
|
||||
tryBreakBlock(tile.x, tile.y);
|
||||
}
|
||||
}
|
||||
|
||||
//move all current plans to removal array so they fade out
|
||||
removals.addAll(selectPlans.select(r -> !r.breaking));
|
||||
selectPlans.clear();
|
||||
selecting = false;
|
||||
}
|
||||
}).visible(() -> !selectPlans.isEmpty() || schematicMode || rebuildMode).update(i -> {
|
||||
i.getStyle().imageUp = schematicMode || rebuildMode ? Icon.wrench : Icon.ok;
|
||||
i.setChecked(rebuildMode);
|
||||
|
||||
}).name("confirmplace");
|
||||
//move all current plans to removal array so they fade out
|
||||
removals.addAll(selectPlans.select(r -> !r.breaking));
|
||||
selectPlans.clear();
|
||||
selecting = false;
|
||||
}).visible(() -> !selectPlans.isEmpty()).name("confirmplace");
|
||||
}
|
||||
|
||||
boolean showCancel(){
|
||||
@@ -376,10 +366,9 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
|
||||
@Override
|
||||
public void drawTop(){
|
||||
//draw schematic selection
|
||||
if(mode == schematicSelect){
|
||||
drawSelection(lineStartX, lineStartY, lastLineX, lastLineY, Vars.maxSchematicSize);
|
||||
}else if(mode == rebuildSelect){
|
||||
drawRebuildSelection(lineStartX, lineStartY, lastLineX, lastLineY);
|
||||
}
|
||||
|
||||
drawCommanded();
|
||||
@@ -454,11 +443,6 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
//endregion
|
||||
//region input events, overrides
|
||||
|
||||
@Override
|
||||
public boolean isRebuildSelecting(){
|
||||
return rebuildMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int schemOriginX(){
|
||||
Tmp.v1.setZero();
|
||||
@@ -512,8 +496,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
//call tap events
|
||||
if(pointer == 0 && !selecting){
|
||||
if(schematicMode && block == null){
|
||||
mode = rebuildMode ? rebuildSelect : schematicSelect;
|
||||
|
||||
mode = schematicSelect;
|
||||
//engage schematic selection mode
|
||||
int tileX = tileX(screenX);
|
||||
int tileY = tileY(screenY);
|
||||
@@ -563,9 +546,6 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
}
|
||||
schematicMode = false;
|
||||
mode = none;
|
||||
}else if(mode == rebuildSelect){
|
||||
rebuildArea(lineStartX, lineStartY, lastLineX, lastLineY);
|
||||
mode = none;
|
||||
}else{
|
||||
Tile tile = tileAt(screenX, screenY);
|
||||
|
||||
@@ -800,15 +780,11 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
}
|
||||
|
||||
//stop select when not in schematic mode
|
||||
if(!schematicMode && (mode == schematicSelect || mode == rebuildSelect)){
|
||||
if(!schematicMode && mode == schematicSelect){
|
||||
mode = none;
|
||||
}
|
||||
|
||||
if(!rebuildMode && mode == rebuildSelect){
|
||||
mode = none;
|
||||
}
|
||||
|
||||
if(mode == schematicSelect || mode == rebuildSelect){
|
||||
if(mode == schematicSelect){
|
||||
lastLineX = rawTileX();
|
||||
lastLineY = rawTileY();
|
||||
autoPan();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package mindustry.maps.generators;
|
||||
|
||||
import arc.math.geom.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.io.*;
|
||||
@@ -17,13 +16,7 @@ public class FileMapGenerator implements WorldGenerator{
|
||||
public final SectorPreset preset;
|
||||
|
||||
public FileMapGenerator(String mapName, SectorPreset preset){
|
||||
//try to look for the prefixed map first, then the mod-specific one
|
||||
this.map = maps != null ? maps.loadInternalMap(
|
||||
preset.minfo.mod == null || Vars.tree.get("maps/" + mapName + "." + mapExtension).exists() ?
|
||||
mapName :
|
||||
mapName.substring(1 + preset.minfo.mod.name.length())
|
||||
) : null;
|
||||
|
||||
this.map = maps != null ? maps.loadInternalMap(mapName) : null;
|
||||
this.preset = preset;
|
||||
}
|
||||
|
||||
|
||||
@@ -575,7 +575,7 @@ public class ContentParser{
|
||||
|
||||
if(!value.has("sector") || !value.get("sector").isNumber()) throw new RuntimeException("SectorPresets must have a sector number.");
|
||||
|
||||
SectorPreset out = new SectorPreset(mod + "-" + name, currentMod);
|
||||
SectorPreset out = new SectorPreset(mod + "-" + name);
|
||||
|
||||
currentContent = out;
|
||||
read(() -> {
|
||||
|
||||
@@ -51,7 +51,7 @@ public class ArcNetProvider implements NetProvider{
|
||||
packetSpamLimit = Config.packetSpamLimit.num();
|
||||
});
|
||||
|
||||
client = new Client(8192, 16384, new PacketSerializer());
|
||||
client = new Client(8192, 8192, new PacketSerializer());
|
||||
client.setDiscoveryPacket(packetSupplier);
|
||||
client.addListener(new NetListener(){
|
||||
@Override
|
||||
|
||||
@@ -5,7 +5,6 @@ import mindustry.ctype.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.maps.generators.*;
|
||||
import mindustry.mod.Mods.*;
|
||||
|
||||
public class SectorPreset extends UnlockableContent{
|
||||
public FileMapGenerator generator;
|
||||
@@ -36,16 +35,10 @@ public class SectorPreset extends UnlockableContent{
|
||||
initialize(planet, sector);
|
||||
}
|
||||
|
||||
/** Internal use only! */
|
||||
public SectorPreset(String name, LoadedMod mod){
|
||||
super(name);
|
||||
this.minfo.mod = mod;
|
||||
this.generator = new FileMapGenerator(name, this);
|
||||
}
|
||||
|
||||
/** Internal use only! */
|
||||
public SectorPreset(String name){
|
||||
this(name, null);
|
||||
super(name);
|
||||
this.generator = new FileMapGenerator(name, this);
|
||||
}
|
||||
|
||||
public void initialize(Planet planet, int sector){
|
||||
|
||||
@@ -42,14 +42,6 @@ public class BaseDialog extends Dialog{
|
||||
this(title, Core.scene.getStyle(DialogStyle.class));
|
||||
}
|
||||
|
||||
/** Places the buttons as an overlay on top of the content. Used when the content can be scrolled through.*/
|
||||
protected void makeButtonOverlay(){
|
||||
clearChildren();
|
||||
add(titleTable).growX().row();
|
||||
stack(cont, buttons).grow();
|
||||
buttons.bottom();
|
||||
}
|
||||
|
||||
protected void onResize(Runnable run){
|
||||
Events.on(ResizeEvent.class, event -> {
|
||||
if(isShown() && Core.scene.getDialog() == this){
|
||||
@@ -63,15 +55,11 @@ public class BaseDialog extends Dialog{
|
||||
closeOnBack();
|
||||
}
|
||||
|
||||
public void addCloseButton(float width){
|
||||
buttons.defaults().size(width, 64f);
|
||||
buttons.button("@back", Icon.left, this::hide).size(width, 64f);
|
||||
@Override
|
||||
public void addCloseButton(){
|
||||
buttons.defaults().size(210f, 64f);
|
||||
buttons.button("@back", Icon.left, this::hide).size(210f, 64f);
|
||||
|
||||
addCloseListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCloseButton(){
|
||||
addCloseButton(210f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,98 @@
|
||||
package mindustry.ui.dialogs;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.ImageButton.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.maps.*;
|
||||
import mindustry.ui.*;
|
||||
|
||||
public class CustomGameDialog extends MapListDialog{
|
||||
public class CustomGameDialog extends BaseDialog{
|
||||
private MapPlayDialog dialog = new MapPlayDialog();
|
||||
|
||||
public CustomGameDialog(){
|
||||
super("@customgame", false);
|
||||
super("@customgame");
|
||||
addCloseButton();
|
||||
shown(this::setup);
|
||||
onResize(this::setup);
|
||||
}
|
||||
|
||||
@Override
|
||||
void showMap(Map map){
|
||||
dialog.show(map);
|
||||
void setup(){
|
||||
clearChildren();
|
||||
add(titleTable).growX().row();
|
||||
stack(cont, buttons).grow();
|
||||
buttons.bottom();
|
||||
cont.clear();
|
||||
|
||||
Table maps = new Table();
|
||||
maps.marginBottom(55f).marginRight(-20f);
|
||||
ScrollPane pane = new ScrollPane(maps);
|
||||
pane.setFadeScrollBars(false);
|
||||
|
||||
int maxwidth = Math.max((int)(Core.graphics.getWidth() / Scl.scl(210)), 1);
|
||||
float images = 146f;
|
||||
|
||||
ImageButtonStyle style = new ImageButtonStyle(){{
|
||||
up = Styles.grayPanel;
|
||||
down = Styles.flatOver;
|
||||
over = Styles.flatOver;
|
||||
disabled = Styles.none;
|
||||
}};
|
||||
|
||||
int i = 0;
|
||||
maps.defaults().width(170).fillY().top().pad(4f);
|
||||
for(Map map : Vars.maps.all()){
|
||||
|
||||
if(i % maxwidth == 0){
|
||||
maps.row();
|
||||
}
|
||||
|
||||
ImageButton image = new ImageButton(new TextureRegion(map.safeTexture()), style);
|
||||
image.margin(5);
|
||||
image.top();
|
||||
|
||||
Image img = image.getImage();
|
||||
img.remove();
|
||||
|
||||
image.row();
|
||||
image.table(t -> {
|
||||
t.left();
|
||||
for(Gamemode mode : Gamemode.all){
|
||||
TextureRegionDrawable icon = Vars.ui.getIcon("mode" + Strings.capitalize(mode.name()) + "Small");
|
||||
if(mode.valid(map) && Core.atlas.isFound(icon.getRegion())){
|
||||
t.image(icon).size(16f).pad(4f);
|
||||
}
|
||||
}
|
||||
}).left();
|
||||
image.row();
|
||||
image.add(map.name()).pad(1f).growX().wrap().left().get().setEllipsis(true);
|
||||
image.row();
|
||||
image.image(Tex.whiteui, Pal.gray).growX().pad(3).height(4f);
|
||||
image.row();
|
||||
image.add(img).size(images);
|
||||
|
||||
BorderImage border = new BorderImage(map.safeTexture(), 3f);
|
||||
border.setScaling(Scaling.fit);
|
||||
image.replaceImage(border);
|
||||
|
||||
image.clicked(() -> dialog.show(map));
|
||||
|
||||
maps.add(image);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if(Vars.maps.all().size == 0){
|
||||
maps.add("@maps.none").pad(50);
|
||||
}
|
||||
|
||||
cont.add(pane).grow();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
package mindustry.ui.dialogs;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.io.*;
|
||||
import mindustry.maps.*;
|
||||
import mindustry.ui.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class EditorMapsDialog extends MapListDialog{
|
||||
|
||||
public EditorMapsDialog(){
|
||||
super("@maps", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
void buildButtons(){
|
||||
buttons.button("@editor.newmap", Icon.add, () -> {
|
||||
ui.showTextInput("@editor.newmap", "@editor.mapname", "", text -> {
|
||||
Runnable show = () -> ui.loadAnd(() -> {
|
||||
hide();
|
||||
ui.editor.show();
|
||||
editor.tags.put("name", text);
|
||||
Events.fire(new MapMakeEvent());
|
||||
});
|
||||
|
||||
if(maps.byName(text) != null){
|
||||
ui.showErrorMessage("@editor.exists");
|
||||
}else{
|
||||
show.run();
|
||||
}
|
||||
});
|
||||
}).size(210f, 64f);
|
||||
|
||||
buttons.button("@editor.importmap", Icon.upload, () -> {
|
||||
platform.showFileChooser(true, mapExtension, file -> {
|
||||
ui.loadAnd(() -> {
|
||||
maps.tryCatchMapError(() -> {
|
||||
if(MapIO.isImage(file)){
|
||||
ui.showErrorMessage("@editor.errorimage");
|
||||
return;
|
||||
}
|
||||
|
||||
Map map = MapIO.createMap(file, true);
|
||||
|
||||
//when you attempt to import a save, it will have no name, so generate one
|
||||
String name = map.tags.get("name", () -> {
|
||||
String result = "unknown";
|
||||
int number = 0;
|
||||
while(maps.byName(result + number++) != null) ;
|
||||
return result + number;
|
||||
});
|
||||
|
||||
//this will never actually get called, but it remains just in case
|
||||
if(name == null){
|
||||
ui.showErrorMessage("@editor.errorname");
|
||||
return;
|
||||
}
|
||||
|
||||
Map conflict = maps.all().find(m -> m.name().equals(name));
|
||||
|
||||
if(conflict != null && !conflict.custom){
|
||||
ui.showInfo(Core.bundle.format("editor.import.exists", name));
|
||||
}else if(conflict != null){
|
||||
ui.showConfirm("@confirm", Core.bundle.format("editor.overwrite.confirm", map.name()), () -> {
|
||||
maps.tryCatchMapError(() -> {
|
||||
maps.removeMap(conflict);
|
||||
maps.importMap(map.file);
|
||||
setup();
|
||||
});
|
||||
});
|
||||
}else{
|
||||
maps.importMap(map.file);
|
||||
setup();
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
}).size(210f, 64f);
|
||||
}
|
||||
|
||||
@Override
|
||||
void showMap(Map map){
|
||||
BaseDialog dialog = activeDialog = new BaseDialog("@editor.mapinfo");
|
||||
dialog.addCloseButton();
|
||||
|
||||
float mapsize = Core.graphics.isPortrait() ? 160f : 300f;
|
||||
Table table = dialog.cont;
|
||||
|
||||
table.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize);
|
||||
|
||||
table.table(Styles.black, desc -> {
|
||||
desc.top();
|
||||
Table t = new Table();
|
||||
t.margin(6);
|
||||
|
||||
ScrollPane pane = new ScrollPane(t);
|
||||
desc.add(pane).grow();
|
||||
|
||||
t.top();
|
||||
t.defaults().padTop(10).left();
|
||||
|
||||
t.add("@editor.mapname").padRight(10).color(Color.gray).padTop(0);
|
||||
t.row();
|
||||
t.add(map.name()).growX().wrap().padTop(2);
|
||||
t.row();
|
||||
t.add("@editor.author").padRight(10).color(Color.gray);
|
||||
t.row();
|
||||
t.add(!map.custom && map.tags.get("author", "").isEmpty() ? "Anuke" : map.author()).growX().wrap().padTop(2);
|
||||
t.row();
|
||||
|
||||
if(!map.tags.get("description", "").isEmpty()){
|
||||
t.add("@editor.description").padRight(10).color(Color.gray).top();
|
||||
t.row();
|
||||
t.add(map.description()).growX().wrap().padTop(2);
|
||||
}
|
||||
}).height(mapsize).width(mapsize);
|
||||
|
||||
table.row();
|
||||
|
||||
table.button("@editor.openin", Icon.export, () -> {
|
||||
try{
|
||||
Vars.ui.editor.beginEditMap(map.file);
|
||||
dialog.hide();
|
||||
hide();
|
||||
}catch(Exception e){
|
||||
Log.err(e);
|
||||
ui.showErrorMessage("@error.mapnotfound");
|
||||
}
|
||||
}).fillX().height(54f).marginLeft(10);
|
||||
|
||||
table.button(map.workshop && steam ? "@view.workshop" : "@delete", map.workshop && steam ? Icon.link : Icon.trash, () -> {
|
||||
if(map.workshop && steam){
|
||||
platform.viewListing(map);
|
||||
}else{
|
||||
ui.showConfirm("@confirm", Core.bundle.format("map.delete", map.name()), () -> {
|
||||
maps.removeMap(map);
|
||||
dialog.hide();
|
||||
setup();
|
||||
});
|
||||
}
|
||||
}).fillX().height(54f).marginLeft(10).disabled(!map.workshop && !map.custom);
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,8 +45,6 @@ public class JoinDialog extends BaseDialog{
|
||||
public JoinDialog(){
|
||||
super("@joingame");
|
||||
|
||||
makeButtonOverlay();
|
||||
|
||||
style = new TextButtonStyle(){{
|
||||
over = Styles.flatOver;
|
||||
font = Fonts.def;
|
||||
@@ -58,21 +56,13 @@ public class JoinDialog extends BaseDialog{
|
||||
|
||||
loadServers();
|
||||
|
||||
//mobile players don't get information >:(
|
||||
boolean infoButton = !steam && !mobile;
|
||||
|
||||
if(infoButton) buttons.add().width(60f);
|
||||
if(!steam) buttons.add().width(60f);
|
||||
buttons.add().growX().width(-1);
|
||||
|
||||
addCloseButton(mobile ? 190f : 210f);
|
||||
|
||||
buttons.button("@server.add", Icon.add, () -> {
|
||||
renaming = null;
|
||||
add.show();
|
||||
});
|
||||
addCloseButton();
|
||||
|
||||
buttons.add().growX().width(-1);
|
||||
if(infoButton) buttons.button("?", () -> ui.showInfo("@join.info")).size(60f, 64f);
|
||||
if(!steam) buttons.button("?", () -> ui.showInfo("@join.info")).size(60f, 64f);
|
||||
|
||||
add = new BaseDialog("@joingame.title");
|
||||
add.cont.add("@joingame.ip").padRight(5f).left();
|
||||
@@ -324,8 +314,6 @@ public class JoinDialog extends BaseDialog{
|
||||
float w = targetWidth();
|
||||
|
||||
hosts.clear();
|
||||
//since the buttons are an overlay, make room for that
|
||||
hosts.marginBottom(70f);
|
||||
|
||||
section(steam ? "@servers.local.steam" : "@servers.local", local, false);
|
||||
section("@servers.remote", remote, false);
|
||||
@@ -356,6 +344,25 @@ public class JoinDialog extends BaseDialog{
|
||||
cont.row();
|
||||
cont.add(pane).width((w + 5) * columns() + 33).pad(0);
|
||||
cont.row();
|
||||
cont.buttonCenter("@server.add", Icon.add, () -> {
|
||||
renaming = null;
|
||||
add.show();
|
||||
}).marginLeft(10).width(w).height(80f).update(button -> {
|
||||
float pw = w;
|
||||
float pad = 0f;
|
||||
if(pane.getChildren().first().getPrefHeight() > pane.getHeight()){
|
||||
pw = w + 30;
|
||||
pad = 6;
|
||||
}
|
||||
|
||||
var cell = ((Table)pane.parent).getCell(button);
|
||||
|
||||
if(!Mathf.equal(cell.minWidth(), pw)){
|
||||
cell.width(pw);
|
||||
cell.padLeft(pad);
|
||||
pane.parent.invalidateHierarchy();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void section(String label, Table servers, boolean eye){
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
package mindustry.ui.dialogs;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.maps.*;
|
||||
import mindustry.ui.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public abstract class MapListDialog extends BaseDialog{
|
||||
BaseDialog activeDialog;
|
||||
|
||||
private String searchString;
|
||||
private Seq<Gamemode> modes = new Seq<>();
|
||||
private Table mapTable = new Table();
|
||||
private TextField searchField;
|
||||
|
||||
private boolean
|
||||
showBuiltIn = Core.settings.getBool("editorshowbuiltinmaps", true),
|
||||
showCustom = Core.settings.getBool("editorshowcustommaps", true),
|
||||
searchAuthor = Core.settings.getBool("editorsearchauthor", false),
|
||||
searchDescription = Core.settings.getBool("editorsearchdescription", false),
|
||||
displayType;
|
||||
|
||||
public MapListDialog(String title, boolean displayType){
|
||||
super(title);
|
||||
|
||||
this.displayType = displayType;
|
||||
|
||||
buttons.remove();
|
||||
|
||||
addCloseListener();
|
||||
|
||||
shown(this::setup);
|
||||
onResize(() -> {
|
||||
if(activeDialog != null){
|
||||
activeDialog.hide();
|
||||
}
|
||||
setup();
|
||||
});
|
||||
}
|
||||
|
||||
void buildButtons(){}
|
||||
|
||||
abstract void showMap(Map map);
|
||||
|
||||
void setup(){
|
||||
makeButtonOverlay();
|
||||
|
||||
buttons.clearChildren();
|
||||
|
||||
searchString = null;
|
||||
|
||||
if(Core.graphics.isPortrait() && displayType){
|
||||
buttons.button("@back", Icon.left, this::hide).size(210f * 2f, 64f).colspan(2);
|
||||
buttons.row();
|
||||
}else{
|
||||
buttons.button("@back", Icon.left, this::hide).size(210f, 64f);
|
||||
}
|
||||
|
||||
buildButtons();
|
||||
|
||||
cont.clear();
|
||||
|
||||
rebuildMaps();
|
||||
|
||||
ScrollPane pane = new ScrollPane(mapTable);
|
||||
pane.setFadeScrollBars(false);
|
||||
pane.setScrollingDisabledX(true);
|
||||
|
||||
Table search = new Table();
|
||||
search.image(Icon.zoom);
|
||||
searchField = search.field("", t -> {
|
||||
searchString = t.length() > 0 ? t.toLowerCase() : null;
|
||||
rebuildMaps();
|
||||
}).maxTextLength(50).growX().get();
|
||||
searchField.setMessageText("@editor.search");
|
||||
search.button(Icon.filter, Styles.emptyi, this::showMapFilters).tooltip("@editor.filters");
|
||||
|
||||
cont.add(search).growX();
|
||||
cont.row();
|
||||
cont.add(pane).padLeft(36f).uniformX().growY();
|
||||
}
|
||||
|
||||
void rebuildMaps(){
|
||||
mapTable.clear();
|
||||
|
||||
mapTable.marginRight(18f);
|
||||
|
||||
int maxwidth = Math.max((int)(Core.graphics.getWidth() / Scl.scl(230)), 1);
|
||||
float mapsize = 200f;
|
||||
boolean noMapsShown = true;
|
||||
|
||||
int i = 0;
|
||||
|
||||
Seq<Map> mapList = showCustom ?
|
||||
showBuiltIn ? maps.all() : maps.customMaps() :
|
||||
showBuiltIn ? maps.defaultMaps() : null;
|
||||
|
||||
if(mapList != null){
|
||||
for(Map map : mapList){
|
||||
|
||||
boolean invalid = false;
|
||||
for(Gamemode mode : modes){
|
||||
invalid |= !mode.valid(map);
|
||||
}
|
||||
if(invalid || (searchString != null
|
||||
&& !Strings.stripColors(map.name()).toLowerCase().contains(searchString)
|
||||
&& (!searchAuthor || !Strings.stripColors(map.author()).toLowerCase().contains(searchString))
|
||||
&& (!searchDescription || !Strings.stripColors(map.description()).toLowerCase().contains(searchString)))){
|
||||
continue;
|
||||
}
|
||||
|
||||
noMapsShown = false;
|
||||
|
||||
if(i % maxwidth == 0){
|
||||
mapTable.row();
|
||||
}
|
||||
|
||||
TextButton button = mapTable.button("", Styles.grayt, () -> showMap(map)).width(mapsize).bottom().growY().pad(8).get();
|
||||
button.clearChildren();
|
||||
button.margin(9);
|
||||
button.bottom();
|
||||
|
||||
//TODO hide in editor?
|
||||
button.table(t -> {
|
||||
t.left();
|
||||
for(Gamemode mode : Gamemode.all){
|
||||
TextureRegionDrawable icon = Vars.ui.getIcon("mode" + Strings.capitalize(mode.name()) + "Small");
|
||||
if(mode.valid(map) && Core.atlas.isFound(icon.getRegion())){
|
||||
t.image(icon).size(16f).pad(4f);
|
||||
}
|
||||
}
|
||||
}).left().row();
|
||||
|
||||
button.add(map.name()).width(mapsize - 18f).center().get().setEllipsis(true);
|
||||
button.row();
|
||||
button.image().growX().pad(4).color(Pal.gray);
|
||||
button.row();
|
||||
button.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize - 20f);
|
||||
|
||||
if(displayType){
|
||||
button.row();
|
||||
button.add(map.custom ? "@custom" : map.workshop ? "@workshop" : map.mod != null ? "[lightgray]" + map.mod.meta.displayName() : "@builtin").color(Color.gray).padTop(3);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if(noMapsShown){
|
||||
mapTable.add("@maps.none");
|
||||
}
|
||||
}
|
||||
|
||||
void showMapFilters(){
|
||||
activeDialog = new BaseDialog("@editor.filters");
|
||||
activeDialog.addCloseButton();
|
||||
activeDialog.cont.table(menu -> {
|
||||
menu.add("@editor.filters.mode").width(150f).left();
|
||||
menu.table(t -> {
|
||||
for(Gamemode mode : Gamemode.all){
|
||||
TextureRegionDrawable icon = Vars.ui.getIcon("mode" + Strings.capitalize(mode.name()));
|
||||
if(Core.atlas.isFound(icon.getRegion())){
|
||||
t.button(icon, Styles.emptyTogglei, () -> {
|
||||
if(modes.contains(mode)){
|
||||
modes.remove(mode);
|
||||
}else{
|
||||
modes.add(mode);
|
||||
}
|
||||
rebuildMaps();
|
||||
}).size(60f).checked(modes.contains(mode)).tooltip("@mode." + mode.name() + ".name");
|
||||
}
|
||||
}
|
||||
}).padBottom(10f);
|
||||
menu.row();
|
||||
|
||||
menu.add("@editor.filters.type").width(150f).left();
|
||||
menu.table(Tex.button, t -> {
|
||||
t.button("@custom", Styles.flatTogglet, () -> {
|
||||
showCustom = !showCustom;
|
||||
Core.settings.put("editorshowcustommaps", showCustom);
|
||||
rebuildMaps();
|
||||
}).size(150f, 60f).checked(showCustom);
|
||||
t.button("@builtin", Styles.flatTogglet, () -> {
|
||||
showBuiltIn = !showBuiltIn;
|
||||
Core.settings.put("editorshowbuiltinmaps", showBuiltIn);
|
||||
rebuildMaps();
|
||||
}).size(150f, 60f).checked(showBuiltIn);
|
||||
}).padBottom(10f);
|
||||
menu.row();
|
||||
|
||||
menu.add("@editor.filters.search").width(150f).left();
|
||||
menu.table(Tex.button, t -> {
|
||||
t.button("@editor.filters.author", Styles.flatTogglet, () -> {
|
||||
searchAuthor = !searchAuthor;
|
||||
Core.settings.put("editorsearchauthor", searchAuthor);
|
||||
rebuildMaps();
|
||||
}).size(150f, 60f).checked(searchAuthor);
|
||||
t.button("@editor.filters.description", Styles.flatTogglet, () -> {
|
||||
searchDescription = !searchDescription;
|
||||
Core.settings.put("editorsearchdescription", searchDescription);
|
||||
rebuildMaps();
|
||||
}).size(150f, 60f).checked(searchDescription);
|
||||
});
|
||||
});
|
||||
|
||||
activeDialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog show(){
|
||||
super.show();
|
||||
|
||||
if(Core.app.isDesktop() && searchField != null){
|
||||
Core.scene.setKeyboardFocus(searchField);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
332
core/src/mindustry/ui/dialogs/MapsDialog.java
Normal file
@@ -0,0 +1,332 @@
|
||||
package mindustry.ui.dialogs;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.io.*;
|
||||
import mindustry.maps.*;
|
||||
import mindustry.ui.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class MapsDialog extends BaseDialog{
|
||||
private BaseDialog dialog;
|
||||
private String searchString;
|
||||
private Seq<Gamemode> modes = new Seq<>();
|
||||
private Table mapTable = new Table();
|
||||
private TextField searchField;
|
||||
|
||||
private boolean showBuiltIn = Core.settings.getBool("editorshowbuiltinmaps", true);
|
||||
private boolean showCustom = Core.settings.getBool("editorshowcustommaps", true);
|
||||
private boolean searchAuthor = Core.settings.getBool("editorsearchauthor", false);
|
||||
private boolean searchDescription = Core.settings.getBool("editorsearchdescription", false);
|
||||
|
||||
public MapsDialog(){
|
||||
super("@maps");
|
||||
|
||||
buttons.remove();
|
||||
|
||||
addCloseListener();
|
||||
|
||||
shown(this::setup);
|
||||
onResize(() -> {
|
||||
if(dialog != null){
|
||||
dialog.hide();
|
||||
}
|
||||
setup();
|
||||
});
|
||||
}
|
||||
|
||||
void setup(){
|
||||
buttons.clearChildren();
|
||||
|
||||
searchString = null;
|
||||
|
||||
if(Core.graphics.isPortrait()){
|
||||
buttons.button("@back", Icon.left, this::hide).size(210f * 2f, 64f).colspan(2);
|
||||
buttons.row();
|
||||
}else{
|
||||
buttons.button("@back", Icon.left, this::hide).size(210f, 64f);
|
||||
}
|
||||
|
||||
buttons.button("@editor.newmap", Icon.add, () -> {
|
||||
ui.showTextInput("@editor.newmap", "@editor.mapname", "", text -> {
|
||||
Runnable show = () -> ui.loadAnd(() -> {
|
||||
hide();
|
||||
ui.editor.show();
|
||||
editor.tags.put("name", text);
|
||||
Events.fire(new MapMakeEvent());
|
||||
});
|
||||
|
||||
if(maps.byName(text) != null){
|
||||
ui.showErrorMessage("@editor.exists");
|
||||
}else{
|
||||
show.run();
|
||||
}
|
||||
});
|
||||
}).size(210f, 64f);
|
||||
|
||||
buttons.button("@editor.importmap", Icon.upload, () -> {
|
||||
platform.showFileChooser(true, mapExtension, file -> {
|
||||
ui.loadAnd(() -> {
|
||||
maps.tryCatchMapError(() -> {
|
||||
if(MapIO.isImage(file)){
|
||||
ui.showErrorMessage("@editor.errorimage");
|
||||
return;
|
||||
}
|
||||
|
||||
Map map = MapIO.createMap(file, true);
|
||||
|
||||
//when you attempt to import a save, it will have no name, so generate one
|
||||
String name = map.tags.get("name", () -> {
|
||||
String result = "unknown";
|
||||
int number = 0;
|
||||
while(maps.byName(result + number++) != null) ;
|
||||
return result + number;
|
||||
});
|
||||
|
||||
//this will never actually get called, but it remains just in case
|
||||
if(name == null){
|
||||
ui.showErrorMessage("@editor.errorname");
|
||||
return;
|
||||
}
|
||||
|
||||
Map conflict = maps.all().find(m -> m.name().equals(name));
|
||||
|
||||
if(conflict != null && !conflict.custom){
|
||||
ui.showInfo(Core.bundle.format("editor.import.exists", name));
|
||||
}else if(conflict != null){
|
||||
ui.showConfirm("@confirm", Core.bundle.format("editor.overwrite.confirm", map.name()), () -> {
|
||||
maps.tryCatchMapError(() -> {
|
||||
maps.removeMap(conflict);
|
||||
maps.importMap(map.file);
|
||||
setup();
|
||||
});
|
||||
});
|
||||
}else{
|
||||
maps.importMap(map.file);
|
||||
setup();
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
}).size(210f, 64f);
|
||||
|
||||
cont.clear();
|
||||
|
||||
rebuildMaps();
|
||||
|
||||
ScrollPane pane = new ScrollPane(mapTable);
|
||||
pane.setFadeScrollBars(false);
|
||||
|
||||
Table search = new Table();
|
||||
search.image(Icon.zoom);
|
||||
searchField = search.field("", t -> {
|
||||
searchString = t.length() > 0 ? t.toLowerCase() : null;
|
||||
rebuildMaps();
|
||||
}).maxTextLength(50).growX().get();
|
||||
searchField.setMessageText("@editor.search");
|
||||
search.button(Icon.filter, Styles.emptyi, this::showMapFilters).tooltip("@editor.filters");
|
||||
|
||||
cont.add(search).growX();
|
||||
cont.row();
|
||||
cont.add(pane).uniformX().growY();
|
||||
cont.row();
|
||||
cont.add(buttons).growX();
|
||||
}
|
||||
|
||||
void rebuildMaps(){
|
||||
mapTable.clear();
|
||||
|
||||
mapTable.marginRight(24);
|
||||
|
||||
int maxwidth = Math.max((int)(Core.graphics.getWidth() / Scl.scl(230)), 1);
|
||||
float mapsize = 200f;
|
||||
boolean noMapsShown = true;
|
||||
|
||||
int i = 0;
|
||||
|
||||
Seq<Map> mapList = showCustom ?
|
||||
showBuiltIn ? maps.all() : maps.customMaps() :
|
||||
showBuiltIn ? maps.defaultMaps() : null;
|
||||
|
||||
if(mapList != null){
|
||||
for(Map map : mapList){
|
||||
|
||||
boolean invalid = false;
|
||||
for(Gamemode mode : modes){
|
||||
invalid |= !mode.valid(map);
|
||||
}
|
||||
if(invalid || (searchString != null
|
||||
&& !Strings.stripColors(map.name()).toLowerCase().contains(searchString)
|
||||
&& (!searchAuthor || !Strings.stripColors(map.author()).toLowerCase().contains(searchString))
|
||||
&& (!searchDescription || !Strings.stripColors(map.description()).toLowerCase().contains(searchString)))){
|
||||
continue;
|
||||
}
|
||||
|
||||
noMapsShown = false;
|
||||
|
||||
if(i % maxwidth == 0){
|
||||
mapTable.row();
|
||||
}
|
||||
|
||||
TextButton button = mapTable.button("", Styles.grayt, () -> showMapInfo(map)).width(mapsize).pad(8).get();
|
||||
button.clearChildren();
|
||||
button.margin(9);
|
||||
button.add(map.name()).width(mapsize - 18f).center().get().setEllipsis(true);
|
||||
button.row();
|
||||
button.image().growX().pad(4).color(Pal.gray);
|
||||
button.row();
|
||||
button.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize - 20f);
|
||||
button.row();
|
||||
button.add(map.custom ? "@custom" : map.workshop ? "@workshop" : map.mod != null ? "[lightgray]" + map.mod.meta.displayName() : "@builtin").color(Color.gray).padTop(3);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if(noMapsShown){
|
||||
mapTable.add("@maps.none");
|
||||
}
|
||||
}
|
||||
|
||||
void showMapFilters(){
|
||||
dialog = new BaseDialog("@editor.filters");
|
||||
dialog.addCloseButton();
|
||||
dialog.cont.table(menu -> {
|
||||
menu.add("@editor.filters.mode").width(150f).left();
|
||||
menu.table(t -> {
|
||||
for(Gamemode mode : Gamemode.all){
|
||||
TextureRegionDrawable icon = Vars.ui.getIcon("mode" + Strings.capitalize(mode.name()));
|
||||
if(Core.atlas.isFound(icon.getRegion())){
|
||||
t.button(icon, Styles.emptyTogglei, () -> {
|
||||
if(modes.contains(mode)){
|
||||
modes.remove(mode);
|
||||
}else{
|
||||
modes.add(mode);
|
||||
}
|
||||
rebuildMaps();
|
||||
}).size(60f).checked(modes.contains(mode)).tooltip("@mode." + mode.name() + ".name");
|
||||
}
|
||||
}
|
||||
}).padBottom(10f);
|
||||
menu.row();
|
||||
|
||||
menu.add("@editor.filters.type").width(150f).left();
|
||||
menu.table(Tex.button, t -> {
|
||||
t.button("@custom", Styles.flatTogglet, () -> {
|
||||
showCustom = !showCustom;
|
||||
Core.settings.put("editorshowcustommaps", showCustom);
|
||||
rebuildMaps();
|
||||
}).size(150f, 60f).checked(showCustom);
|
||||
t.button("@builtin", Styles.flatTogglet, () -> {
|
||||
showBuiltIn = !showBuiltIn;
|
||||
Core.settings.put("editorshowbuiltinmaps", showBuiltIn);
|
||||
rebuildMaps();
|
||||
}).size(150f, 60f).checked(showBuiltIn);
|
||||
}).padBottom(10f);
|
||||
menu.row();
|
||||
|
||||
menu.add("@editor.filters.search").width(150f).left();
|
||||
menu.table(Tex.button, t -> {
|
||||
t.button("@editor.filters.author", Styles.flatTogglet, () -> {
|
||||
searchAuthor = !searchAuthor;
|
||||
Core.settings.put("editorsearchauthor", searchAuthor);
|
||||
rebuildMaps();
|
||||
}).size(150f, 60f).checked(searchAuthor);
|
||||
t.button("@editor.filters.description", Styles.flatTogglet, () -> {
|
||||
searchDescription = !searchDescription;
|
||||
Core.settings.put("editorsearchdescription", searchDescription);
|
||||
rebuildMaps();
|
||||
}).size(150f, 60f).checked(searchDescription);
|
||||
});
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
void showMapInfo(Map map){
|
||||
dialog = new BaseDialog("@editor.mapinfo");
|
||||
dialog.addCloseButton();
|
||||
|
||||
float mapsize = Core.graphics.isPortrait() ? 160f : 300f;
|
||||
Table table = dialog.cont;
|
||||
|
||||
table.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize);
|
||||
|
||||
table.table(Styles.black, desc -> {
|
||||
desc.top();
|
||||
Table t = new Table();
|
||||
t.margin(6);
|
||||
|
||||
ScrollPane pane = new ScrollPane(t);
|
||||
desc.add(pane).grow();
|
||||
|
||||
t.top();
|
||||
t.defaults().padTop(10).left();
|
||||
|
||||
t.add("@editor.mapname").padRight(10).color(Color.gray).padTop(0);
|
||||
t.row();
|
||||
t.add(map.name()).growX().wrap().padTop(2);
|
||||
t.row();
|
||||
t.add("@editor.author").padRight(10).color(Color.gray);
|
||||
t.row();
|
||||
t.add(!map.custom && map.tags.get("author", "").isEmpty() ? "Anuke" : map.author()).growX().wrap().padTop(2);
|
||||
t.row();
|
||||
|
||||
if(!map.tags.get("description", "").isEmpty()){
|
||||
t.add("@editor.description").padRight(10).color(Color.gray).top();
|
||||
t.row();
|
||||
t.add(map.description()).growX().wrap().padTop(2);
|
||||
}
|
||||
}).height(mapsize).width(mapsize);
|
||||
|
||||
table.row();
|
||||
|
||||
table.button("@editor.openin", Icon.export, () -> {
|
||||
try{
|
||||
Vars.ui.editor.beginEditMap(map.file);
|
||||
dialog.hide();
|
||||
hide();
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
ui.showErrorMessage("@error.mapnotfound");
|
||||
}
|
||||
}).fillX().height(54f).marginLeft(10);
|
||||
|
||||
table.button(map.workshop && steam ? "@view.workshop" : "@delete", map.workshop && steam ? Icon.link : Icon.trash, () -> {
|
||||
if(map.workshop && steam){
|
||||
platform.viewListing(map);
|
||||
}else{
|
||||
ui.showConfirm("@confirm", Core.bundle.format("map.delete", map.name()), () -> {
|
||||
maps.removeMap(map);
|
||||
dialog.hide();
|
||||
setup();
|
||||
});
|
||||
}
|
||||
}).fillX().height(54f).marginLeft(10).disabled(!map.workshop && !map.custom);
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog show(){
|
||||
super.show();
|
||||
|
||||
if(Core.app.isDesktop() && searchField != null){
|
||||
Core.scene.setKeyboardFocus(searchField);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -184,7 +184,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
b.add(planet.localizedName).color(Pal.accent).style(Styles.outlineLabel);
|
||||
b.row();
|
||||
b.image(new TextureRegionDrawable(tex)).grow().scaling(Scaling.fit);
|
||||
}, Styles.togglet, () -> selected[0] = planet).size(mobile ? 220f : 320f).group(group);
|
||||
}, Styles.togglet, () -> selected[0] = planet).size(Core.app.isMobile() ? 220f : 320f).group(group);
|
||||
i ++;
|
||||
}
|
||||
|
||||
@@ -606,42 +606,29 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
t.label(() -> mode == select ? "@sectors.select" : "").style(Styles.outlineLabel).color(Pal.accent);
|
||||
}),
|
||||
buttons,
|
||||
|
||||
// planet selection
|
||||
//planet selection
|
||||
new Table(t -> {
|
||||
t.top().left();
|
||||
ScrollPane pane = new ScrollPane(null, Styles.smallPane);
|
||||
t.add(pane).colspan(2).row();
|
||||
Table starsTable = new Table(Styles.black);
|
||||
pane.setWidget(starsTable);
|
||||
pane.setScrollingDisabled(true, false);
|
||||
|
||||
int starCount = 0;
|
||||
for(Planet star : content.planets()){
|
||||
if(star.solarSystem != star || !content.planets().contains(p -> p.solarSystem == star && selectable(p))) continue;
|
||||
|
||||
starCount++;
|
||||
if(starCount > 1) starsTable.add(star.localizedName).padLeft(10f).padBottom(10f).padTop(10f).left().width(190f).row();
|
||||
Table planetTable = new Table();
|
||||
planetTable.margin(4f); //less padding
|
||||
starsTable.add(planetTable).left().row();
|
||||
for(Planet planet : content.planets()){
|
||||
if(planet.solarSystem == star && selectable(planet)){
|
||||
Button planetButton = planetTable.button(planet.localizedName, Icon.icons.get(planet.icon + "Small", Icon.icons.get(planet.icon, Icon.commandRallySmall)), Styles.flatTogglet, () -> {
|
||||
selected = null;
|
||||
launchSector = null;
|
||||
if(state.planet != planet){
|
||||
newPresets.clear();
|
||||
state.planet = planet;
|
||||
rebuildExpand();
|
||||
}
|
||||
settings.put("lastplanet", planet.name);
|
||||
}).width(200).height(40).update(bb -> bb.setChecked(state.planet == planet)).with(w -> w.marginLeft(10f)).get();
|
||||
planetButton.getChildren().get(1).setColor(planet.iconColor);
|
||||
planetButton.setColor(planet.iconColor);
|
||||
planetTable.background(Tex.pane).row();
|
||||
if(content.planets().count(this::selectable) > 1){
|
||||
t.table(Tex.pane, pt -> {
|
||||
pt.margin(4f);
|
||||
for(int i = 0; i < content.planets().size; i++){
|
||||
Planet planet = content.planets().get(i);
|
||||
if(selectable(planet)){
|
||||
pt.button(planet.localizedName, Icon.icons.get(planet.icon + "Small", Icon.icons.get(planet.icon, Icon.commandRallySmall)), Styles.flatTogglet, () -> {
|
||||
selected = null;
|
||||
launchSector = null;
|
||||
if(state.planet != planet){
|
||||
newPresets.clear();
|
||||
state.planet = planet;
|
||||
rebuildExpand();
|
||||
}
|
||||
settings.put("lastplanet", planet.name);
|
||||
}).width(190).height(40).growX().update(bb -> bb.setChecked(state.planet == planet)).with(w -> w.marginLeft(10f)).get().getChildren().get(1).setColor(planet.iconColor);
|
||||
pt.row();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ public class HintsFragment{
|
||||
payloadDrop(() -> !player.unit().dead && player.unit() instanceof Payloadc p && p.payloads().any(), () -> player.unit() instanceof Payloadc p && p.payloads().isEmpty()),
|
||||
waveFire(() -> Groups.fire.size() > 0 && Blocks.wave.unlockedNow(), () -> indexer.getFlagged(state.rules.defaultTeam, BlockFlag.extinguisher).size > 0),
|
||||
generator(() -> control.input.block == Blocks.combustionGenerator, () -> ui.hints.placedBlocks.contains(Blocks.combustionGenerator)),
|
||||
rebuildSelect(() -> state.rules.defaultTeam.data().plans.size >= 10, () -> control.input.isRebuildSelecting()),
|
||||
rebuildSelect(visibleDesktop, () -> state.rules.defaultTeam.data().plans.size >= 10, () -> Core.input.keyDown(Binding.rebuild_select)),
|
||||
guardian(() -> state.boss() != null && isSerpulo() && state.boss().armor >= 4, () -> state.boss() == null),
|
||||
factoryControl(() -> !(state.isCampaign() && state.rules.sector.preset == SectorPresets.onset) &&
|
||||
state.rules.defaultTeam.data().getBuildings(Blocks.tankFabricator).size + state.rules.defaultTeam.data().getBuildings(Blocks.groundFactory).size > 0, () -> ui.hints.events.contains("factorycontrol")),
|
||||
|
||||
@@ -558,7 +558,7 @@ public class Block extends UnlockableContent implements Senseable{
|
||||
addBar("liquid-" + liq.name, entity -> !liq.unlockedNow() ? null : new Bar(
|
||||
() -> liq.localizedName,
|
||||
liq::barColor,
|
||||
() -> entity.liquids.get(liq) / liquidCapacity
|
||||
() -> entity.liquids.get(liq) / entity.liquidCapacity()
|
||||
));
|
||||
}
|
||||
|
||||
@@ -567,7 +567,7 @@ public class Block extends UnlockableContent implements Senseable{
|
||||
addBar("liquid", entity -> new Bar(
|
||||
() -> current.get((T)entity) == null || entity.liquids.get(current.get((T)entity)) <= 0.001f ? Core.bundle.get("bar.liquid") : current.get((T)entity).localizedName,
|
||||
() -> current.get((T)entity) == null ? Color.clear : current.get((T)entity).barColor(),
|
||||
() -> current.get((T)entity) == null ? 0f : entity.liquids.get(current.get((T)entity)) / liquidCapacity)
|
||||
() -> current.get((T)entity) == null ? 0f : entity.liquids.get(current.get((T)entity)) / entity.liquidCapacity())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,12 +77,10 @@ public class Build{
|
||||
//auto-rotate the block to the correct orientation and bail out
|
||||
if(tile.team() == team && tile.block == result && tile.build != null && tile.block.quickRotate){
|
||||
if(unit != null && unit.getControllerName() != null) tile.build.lastAccessed = unit.getControllerName();
|
||||
int previous = tile.build.rotation;
|
||||
tile.build.rotation = Mathf.mod(rotation, 4);
|
||||
tile.build.updateProximity();
|
||||
tile.build.noSleep();
|
||||
Fx.rotateBlock.at(tile.build.x, tile.build.y, tile.build.block.size);
|
||||
Events.fire(new BuildRotateEvent(tile.build, unit, previous));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -171,10 +169,6 @@ public class Build{
|
||||
return false;
|
||||
}
|
||||
|
||||
if((type.isFloor() && tile.floor() == type) || (type.isOverlay() && tile.overlay() == type)){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!type.canPlaceOn(tile, team, rotation)){
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -303,9 +303,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{
|
||||
public void setFloorUnder(Floor floor){
|
||||
Block overlay = this.overlay;
|
||||
setFloor(floor);
|
||||
if(this.overlay != overlay){
|
||||
setOverlay(overlay);
|
||||
}
|
||||
setOverlay(overlay);
|
||||
}
|
||||
|
||||
/** Sets the block to air. */
|
||||
|
||||
@@ -20,7 +20,6 @@ import mindustry.graphics.*;
|
||||
import mindustry.logic.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.environment.*;
|
||||
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||
import mindustry.world.modules.*;
|
||||
|
||||
@@ -73,15 +72,7 @@ public class ConstructBlock extends Block{
|
||||
float healthf = tile.build == null ? 1f : tile.build.healthf();
|
||||
Seq<Building> prev = tile.build instanceof ConstructBuild co ? co.prevBuild : null;
|
||||
|
||||
if(block instanceof OverlayFloor overlay){
|
||||
tile.setOverlay(overlay);
|
||||
tile.setBlock(Blocks.air);
|
||||
}else if(block instanceof Floor floor){
|
||||
tile.setFloorUnder(floor);
|
||||
tile.setBlock(Blocks.air);
|
||||
}else{
|
||||
tile.setBlock(block, team, rotation);
|
||||
}
|
||||
tile.setBlock(block, team, rotation);
|
||||
|
||||
if(tile.build != null){
|
||||
tile.build.health = block.health * healthf;
|
||||
|
||||
@@ -468,10 +468,10 @@ public class Turret extends ReloadTurret{
|
||||
target = Units.bestEnemy(team, x, y, range, e -> !e.dead() && !e.isGrounded() && unitFilter.get(e), unitSort);
|
||||
}else{
|
||||
target = Units.bestTarget(team, x, y, range, e -> !e.dead() && unitFilter.get(e) && (e.isGrounded() || targetAir) && (!e.isGrounded() || targetGround), b -> targetGround && buildingFilter.get(b), unitSort);
|
||||
}
|
||||
|
||||
if(target == null && canHeal()){
|
||||
target = Units.findAllyTile(team, x, y, range, b -> b.damaged() && b != this);
|
||||
if(target == null && canHeal()){
|
||||
target = Units.findAllyTile(team, x, y, range, b -> b.damaged() && b != this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
@@ -15,17 +16,22 @@ import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.input.*;
|
||||
import mindustry.logic.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.distribution.*;
|
||||
import mindustry.world.modules.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.type.Liquid.*;
|
||||
|
||||
public class Conduit extends LiquidBlock implements Autotiler{
|
||||
static final boolean debugGraphs = false;
|
||||
static final float mergeThreshold = 0.2f;
|
||||
static final float rotatePad = 6, hpad = rotatePad / 2f / 4f;
|
||||
static final float[][] rotateOffsets = {{hpad, hpad}, {-hpad, hpad}, {-hpad, -hpad}, {hpad, -hpad}};
|
||||
static final LiquidModule tempLiquids = new LiquidModule();
|
||||
|
||||
public final int timerFlow = timers++;
|
||||
|
||||
@@ -51,6 +57,10 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
noUpdateDisabled = true;
|
||||
canOverdrive = false;
|
||||
priority = TargetPriority.transport;
|
||||
|
||||
//conduits don't need to update
|
||||
update = false;
|
||||
destructible = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -148,10 +158,78 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
}
|
||||
|
||||
public class ConduitBuild extends LiquidBuild implements ChainedBuilding{
|
||||
public @Nullable ConduitGraph graph;
|
||||
|
||||
public float smoothLiquid;
|
||||
public int blendbits, xscl = 1, yscl = 1, blending;
|
||||
public boolean capped, backCapped = false;
|
||||
|
||||
protected void addGraphs(){
|
||||
//connect self to every nearby graph
|
||||
getConnections(other -> {
|
||||
if(other.graph != null){
|
||||
other.graph.merge(this);
|
||||
}
|
||||
});
|
||||
|
||||
//nothing to connect to
|
||||
if(graph == null){
|
||||
new ConduitGraph().merge(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected void removeGraphs(){
|
||||
//graph is getting recalculated, no longer valid
|
||||
if(graph != null){
|
||||
graph.checkRemove();
|
||||
graph.remove(this);
|
||||
graph = null; //TODO ?????
|
||||
}
|
||||
|
||||
getConnections(other -> new ConduitGraph().reflow(this, other));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void control(LAccess type, double p1, double p2, double p3, double p4){
|
||||
if(type == LAccess.enabled){
|
||||
boolean shouldEnable = !Mathf.zero((float)p1);
|
||||
if(enabled != shouldEnable){
|
||||
|
||||
if(graph != null){
|
||||
//keep track of how many conduits are disabled, so the graph can stop working
|
||||
if(shouldEnable){
|
||||
graph.disabledConduits --;
|
||||
}else{
|
||||
graph.disabledConduits ++;
|
||||
}
|
||||
}
|
||||
|
||||
enabled = shouldEnable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded(){
|
||||
addGraphs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityRemoved(){
|
||||
super.onProximityRemoved();
|
||||
|
||||
removeGraphs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotated(int prevRot, int newRot){
|
||||
//essentially simulates the conduit being removed and re-placed - hacky, but it works
|
||||
rotation = prevRot;
|
||||
removeGraphs();
|
||||
rotation = newRot;
|
||||
addGraphs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
int r = this.rotation;
|
||||
@@ -173,6 +251,21 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
|
||||
if(capped && capRegion.found()) Draw.rect(capRegion, x, y, rotdeg());
|
||||
if(backCapped && capRegion.found()) Draw.rect(capRegion, x, y, rotdeg() + 180);
|
||||
|
||||
if(debugGraphs){
|
||||
//simple visualization that assigns random color to each graph
|
||||
Mathf.rand.setSeed(graph == null ? -1 : graph.id);
|
||||
Draw.color(Tmp.c1.rand());
|
||||
|
||||
Drawf.selected(tileX(), tileY(), block, Tmp.c1);
|
||||
Draw.color(Pal.accent);
|
||||
|
||||
if(this == graph.head){
|
||||
Fill.poly(x, y, 3, 2f, rotdeg());
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawAt(float x, float y, int bits, int rotation, SliceMode slice){
|
||||
@@ -196,7 +289,7 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
//the drawing state machine sure was a great design choice with no downsides or hidden behavior!!!
|
||||
float xscl = Draw.xscl, yscl = Draw.yscl;
|
||||
Draw.scl(1f, 1f);
|
||||
Drawf.liquid(sliced(liquidr, slice), x + ox, y + oy, smoothLiquid, liquids.current().color.write(Tmp.c1).a(1f));
|
||||
Drawf.liquid(sliced(liquidr, slice), x + ox, y + oy, graph == null ? smoothLiquid : graph.smoothLiquid, liquids.current().color.write(Tmp.c1).a(1f));
|
||||
Draw.scl(xscl, yscl);
|
||||
|
||||
Draw.rect(sliced(topRegions[bits], slice), x, y, angle);
|
||||
@@ -225,15 +318,15 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
smoothLiquid = Mathf.lerpDelta(smoothLiquid, liquids.currentAmount() / liquidCapacity, 0.05f);
|
||||
public LiquidModule writeLiquids(){
|
||||
//"saved" liquids are based on a fraction, essentially splitting apart and re-joining
|
||||
tempLiquids.set(liquids, graph == null ? 1f : block.liquidCapacity / graph.totalCapacity);
|
||||
return tempLiquids;
|
||||
}
|
||||
|
||||
if(liquids.currentAmount() > 0.0001f && timer(timerFlow, 1)){
|
||||
moveLiquidForward(leaks, liquids.current());
|
||||
noSleep();
|
||||
}else{
|
||||
sleep();
|
||||
}
|
||||
@Override
|
||||
public float liquidCapacity(){
|
||||
return graph == null ? block.liquidCapacity : graph.totalCapacity;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -245,5 +338,195 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeAll(Writes write){
|
||||
super.writeAll(write);
|
||||
}
|
||||
|
||||
/** Calls callback with every conduit that transfers fluids to this one. */
|
||||
public void getConnections(Cons<ConduitBuild> cons){
|
||||
for(var other : proximity){
|
||||
if(canMerge(other)){
|
||||
cons.get((ConduitBuild)other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canMerge(Building other){
|
||||
return
|
||||
other instanceof ConduitBuild conduit && other.team == team &&
|
||||
(front() == conduit || other.front() == this) &&
|
||||
(other.liquids.current() == liquids.current() || other.liquids.currentAmount() <= mergeThreshold || liquids.currentAmount() <= mergeThreshold);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TODO:
|
||||
- [X] liquids shared as one inventory
|
||||
- [X] liquids merged when placing
|
||||
- [X] liquids split when breaking
|
||||
- [X] liquids saved
|
||||
- [X] liquids accept input
|
||||
- [X] liquids transfer forward
|
||||
- [X] liquids leak
|
||||
- [X] liquids display properly (including flow rate)
|
||||
- [X] liquids merge different types correctly
|
||||
- [X] conduits can (or can't) be disabled
|
||||
*/
|
||||
public static class ConduitGraph{
|
||||
private static final IntSet closedSet = new IntSet(), headSet = new IntSet();
|
||||
private static final Queue<ConduitBuild> queue = new Queue<>();
|
||||
|
||||
static int lastId = 0;
|
||||
|
||||
public final int id = lastId ++;
|
||||
public float smoothLiquid;
|
||||
|
||||
/** if any are disabled, does not update */
|
||||
private int disabledConduits;
|
||||
private Seq<ConduitBuild> conduits = new Seq<>();
|
||||
private final @Nullable ConduitGraphUpdater entity;
|
||||
private LiquidModule liquids = new LiquidModule();
|
||||
private float totalCapacity;
|
||||
|
||||
public @Nullable ConduitBuild head;
|
||||
|
||||
public ConduitGraph(){
|
||||
entity = ConduitGraphUpdater.create();
|
||||
entity.graph = this;
|
||||
}
|
||||
|
||||
public void update(){
|
||||
smoothLiquid = Mathf.lerpDelta(smoothLiquid, liquids.currentAmount() / totalCapacity, 0.05f);
|
||||
|
||||
if(disabledConduits > 0) return;
|
||||
|
||||
if(head != null){
|
||||
|
||||
//move forward as the head
|
||||
if(liquids.currentAmount() > 0.0001f && head.timer(((Conduit)head.block).timerFlow, 1)){
|
||||
head.moveLiquidForward(((Conduit)head.block).leaks, liquids.current());
|
||||
}
|
||||
|
||||
//merge with front if one of the conduits becomes empty
|
||||
if(head.front() instanceof ConduitBuild build && build.graph != this && head.canMerge(build)){
|
||||
merge(build);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void checkAdd(){
|
||||
if(entity != null) entity.add();
|
||||
}
|
||||
|
||||
public void checkRemove(){
|
||||
if(entity != null) entity.remove();
|
||||
}
|
||||
|
||||
public void remove(ConduitBuild build){
|
||||
float fraction = build.block.liquidCapacity / totalCapacity;
|
||||
//remove fraction of liquids based on what part this conduit constituted
|
||||
//e.g. 70% of capacity was made up by this conduit = multiply liquids by 0.3 (remove 70%)
|
||||
liquids.mul(1f - fraction);
|
||||
|
||||
totalCapacity -= build.block.liquidCapacity;
|
||||
}
|
||||
|
||||
public void reflow(@Nullable ConduitBuild ignore, ConduitBuild conduit){
|
||||
closedSet.clear();
|
||||
queue.clear();
|
||||
|
||||
//ignore the starting point and don't add it, as it is being removed
|
||||
if(ignore != null) closedSet.add(ignore.id);
|
||||
|
||||
closedSet.add(conduit.id);
|
||||
queue.add(conduit);
|
||||
|
||||
|
||||
while(queue.size > 0){
|
||||
var parent = queue.removeFirst();
|
||||
assign(parent, ignore);
|
||||
|
||||
parent.getConnections(child -> {
|
||||
if(closedSet.add(child.id)){
|
||||
queue.addLast(child);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
closedSet.clear();
|
||||
queue.clear();
|
||||
}
|
||||
|
||||
public void merge(ConduitBuild other){
|
||||
if(other.graph == this) return;
|
||||
|
||||
if(other.graph != null){
|
||||
|
||||
//merge graphs - TODO - flip if it is larger, like power graphs?
|
||||
for(var cond : other.graph.conduits){
|
||||
assign(cond);
|
||||
}
|
||||
}else{
|
||||
assign(other);
|
||||
}
|
||||
}
|
||||
|
||||
protected void assign(ConduitBuild build){
|
||||
assign(build, null);
|
||||
}
|
||||
|
||||
protected void assign(ConduitBuild build, @Nullable Building ignore){
|
||||
if(build.graph != this){
|
||||
|
||||
//merge graph liquids - TODO - how does this react to different types
|
||||
if(build.graph != null){
|
||||
build.graph.checkRemove();
|
||||
|
||||
//add liquids based on what fraction it made up
|
||||
liquids.add(build.liquids, build.block.liquidCapacity / build.graph.totalCapacity);
|
||||
}else{
|
||||
//simple direct liquid merge
|
||||
liquids.add(build.liquids);
|
||||
}
|
||||
|
||||
totalCapacity += build.block.liquidCapacity;
|
||||
build.graph = this;
|
||||
build.liquids = liquids;
|
||||
conduits.add(build);
|
||||
checkAdd();
|
||||
|
||||
//re-validate head
|
||||
if(head == null){
|
||||
head = build;
|
||||
}
|
||||
|
||||
//find the best head block
|
||||
headSet.clear();
|
||||
headSet.add(head.id);
|
||||
|
||||
while(true){
|
||||
var next = head.front();
|
||||
|
||||
if(next instanceof ConduitBuild cond && cond.team == head.team && next != ignore && cond.graph == this){
|
||||
if(!headSet.add(next.id)){
|
||||
//there's a loop, which means a head does not exist
|
||||
head = null;
|
||||
break;
|
||||
}else{
|
||||
head = cond;
|
||||
}
|
||||
}else{
|
||||
//found the end
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//snap smoothLiquid so it doesn't start at 0
|
||||
smoothLiquid = liquids.currentAmount() / totalCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public class DrawLiquidRegion extends DrawBlock{
|
||||
public void draw(Building build){
|
||||
Liquid drawn = drawLiquid != null ? drawLiquid : build.liquids.current();
|
||||
Drawf.liquid(liquid, build.x, build.y,
|
||||
build.liquids.get(drawn) / build.block.liquidCapacity * alpha,
|
||||
build.liquids.get(drawn) / build.liquidCapacity() * alpha,
|
||||
drawn.color
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,16 +9,14 @@ import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class DrawPistons extends DrawBlock{
|
||||
public float sinMag = 4f, sinScl = 6f, sinOffset = 50f, sideOffset = 0f, lenOffset = -1f, horiOffset = 0f, angleOffset = 0f;
|
||||
public float sinMag = 4f, sinScl = 6f, sinOffset = 50f, sideOffset = 0f, lenOffset = -1f, angleOffset = 0f;
|
||||
public int sides = 4;
|
||||
public String suffix = "-piston";
|
||||
public TextureRegion region1, region2, regiont, iconRegion;
|
||||
public TextureRegion region1, region2, regiont;
|
||||
|
||||
@Override
|
||||
public void drawPlan(Block block, BuildPlan plan, Eachable<BuildPlan> list){
|
||||
if(iconRegion.found()){
|
||||
Draw.rect(iconRegion, plan.drawx(), plan.drawy());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -34,8 +32,7 @@ public class DrawPistons extends DrawBlock{
|
||||
Draw.yscl = -1f;
|
||||
}
|
||||
|
||||
Tmp.v1.trns(angle, len, -horiOffset);
|
||||
Draw.rect(reg, build.x + Tmp.v1.x, build.y + Tmp.v1.y, angle);
|
||||
Draw.rect(reg, build.x + Angles.trnsx(angle, len), build.y + Angles.trnsy(angle, len), angle);
|
||||
|
||||
Draw.yscl = 1f;
|
||||
}
|
||||
@@ -48,11 +45,5 @@ public class DrawPistons extends DrawBlock{
|
||||
region1 = Core.atlas.find(block.name + suffix + "0", block.name + suffix);
|
||||
region2 = Core.atlas.find(block.name + suffix + "1", block.name + suffix);
|
||||
regiont = Core.atlas.find(block.name + suffix + "-t");
|
||||
iconRegion = Core.atlas.find(block.name + suffix + "-icon");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion[] icons(Block block){
|
||||
return new TextureRegion[]{iconRegion};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,12 @@ public class LiquidModule extends BlockModule{
|
||||
}
|
||||
}
|
||||
|
||||
public void mul(float amount){
|
||||
for(int i = 0; i < liquids.length; i ++){
|
||||
liquids[i] *= amount;
|
||||
}
|
||||
}
|
||||
|
||||
public void stopFlow(){
|
||||
flow = null;
|
||||
}
|
||||
@@ -107,6 +113,27 @@ public class LiquidModule extends BlockModule{
|
||||
Arrays.fill(liquids, 0);
|
||||
}
|
||||
|
||||
public void add(LiquidModule other){
|
||||
add(other, 1f);
|
||||
}
|
||||
|
||||
public void add(LiquidModule other, float mul){
|
||||
for(int i = 0; i < liquids.length; i ++){
|
||||
liquids[i] += other.liquids[i] * mul;
|
||||
|
||||
if(liquids[i] > liquids[current.id]){
|
||||
current = content.liquid(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void set(LiquidModule other, float mul){
|
||||
current = other.current;
|
||||
for(int i = 0; i < liquids.length; i ++){
|
||||
liquids[i] = other.liquids[i] * mul;
|
||||
}
|
||||
}
|
||||
|
||||
public void add(Liquid liquid, float amount){
|
||||
liquids[liquid.id] += amount;
|
||||
current = liquid;
|
||||
@@ -180,6 +207,20 @@ public class LiquidModule extends BlockModule{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
var res = new StringBuilder();
|
||||
res.append("LiquidModule{ current=").append(current).append(", ");
|
||||
for(int i = 0; i < liquids.length; i++){
|
||||
if(liquids[i] > 0){
|
||||
res.append(content.liquid(i).name).append(":").append(liquids[i]).append(", ");
|
||||
}
|
||||
}
|
||||
res.setLength(res.length() - 2);
|
||||
res.append("}");
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
public interface LiquidConsumer{
|
||||
void accept(Liquid liquid, float amount);
|
||||
}
|
||||
|
||||
@@ -25,4 +25,4 @@ org.gradle.caching=true
|
||||
#used for slow jitpack builds; TODO see if this actually works
|
||||
org.gradle.internal.http.socketTimeout=100000
|
||||
org.gradle.internal.http.connectionTimeout=100000
|
||||
archash=55585b5c6e
|
||||
archash=eb3b8bdd10
|
||||
|
||||
@@ -45,7 +45,6 @@ public class ServerLauncher implements ApplicationListener{
|
||||
|
||||
Vars.loadSettings();
|
||||
Vars.init();
|
||||
UI.loadColors();
|
||||
content.createBaseContent();
|
||||
mods.loadScripts();
|
||||
content.createModContent();
|
||||
|
||||