From b873adf5fc0505d669b6292736b72842311e430c Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 23 Jul 2021 10:25:12 -0400 Subject: [PATCH 001/130] docs --- core/src/mindustry/type/StatusEffect.java | 4 ++-- gradle.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/type/StatusEffect.java b/core/src/mindustry/type/StatusEffect.java index fe9a7f487f..4ae91a9d61 100644 --- a/core/src/mindustry/type/StatusEffect.java +++ b/core/src/mindustry/type/StatusEffect.java @@ -43,13 +43,13 @@ public class StatusEffect extends UnlockableContent{ public Color color = Color.white.cpy(); /** Effect that happens randomly on top of the affected unit. */ public Effect effect = Fx.none; + /** Affinity & opposite values for stat displaysdo. */ + public ObjectSet affinities = new ObjectSet<>(), opposites = new ObjectSet<>(); /** Transition handler map. */ protected ObjectMap transitions = new ObjectMap<>(); /** Called on init. */ protected Runnable initblock = () -> {}; - public ObjectSet affinities = new ObjectSet<>(), opposites = new ObjectSet<>(); - public StatusEffect(String name){ super(name); } diff --git a/gradle.properties b/gradle.properties index a5a0e68fcb..ba90b53b7a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,4 +10,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=a81197126a9190337ab9065734b5134d5f08ac05 +archash=47822d851954fd2707d51731042056450f07ca8c From 120aa7c12a0112a576613059113514f53d706c5a Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 23 Jul 2021 17:56:13 -0400 Subject: [PATCH 002/130] Cleanup --- core/src/mindustry/content/StatusEffects.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/mindustry/content/StatusEffects.java b/core/src/mindustry/content/StatusEffects.java index fb75fcabd3..793c5e3e42 100644 --- a/core/src/mindustry/content/StatusEffects.java +++ b/core/src/mindustry/content/StatusEffects.java @@ -69,12 +69,12 @@ public class StatusEffects implements ContentList{ transitionDamage = 14; init(() -> { - affinity(shocked, ((unit, result, time) -> { + affinity(shocked, (unit, result, time) -> { unit.damagePierce(transitionDamage); if(unit.team == state.rules.waveTeam){ Events.fire(Trigger.shock); } - })); + }); opposite(burning, melting); }); }}; @@ -96,11 +96,11 @@ public class StatusEffects implements ContentList{ init(() -> { opposite(wet, freezing); - affinity(tarred, ((unit, result, time) -> { + affinity(tarred, (unit, result, time) -> { unit.damagePierce(8f); Fx.burning.at(unit.x + Mathf.range(unit.bounds() / 2f), unit.y + Mathf.range(unit.bounds() / 2f)); result.set(melting, Math.min(time + result.time, 200f)); - })); + }); }); }}; @@ -133,8 +133,8 @@ public class StatusEffects implements ContentList{ effect = Fx.oily; init(() -> { - affinity(melting, ((unit, result, time) -> result.set(melting, result.time + time))); - affinity(burning, ((unit, result, time) -> result.set(burning, result.time + time))); + affinity(melting, (unit, result, time) -> result.set(melting, result.time + time)); + affinity(burning, (unit, result, time) -> result.set(burning, result.time + time)); }); }}; From 17e68f7a930d6045e3489b464bbf8eb46d98a1c0 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 23 Jul 2021 19:39:52 -0400 Subject: [PATCH 003/130] Fixed additive reconstructor center sprite --- .../blocks/units/additive-reconstructor.png | Bin 1314 -> 1375 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/core/assets-raw/sprites/blocks/units/additive-reconstructor.png b/core/assets-raw/sprites/blocks/units/additive-reconstructor.png index 7534cc4f1563308e712b10ee7a538e9b698a25e7..40ea654c1d46a3633843e050f222fae9b719c020 100644 GIT binary patch delta 1344 zcmZ3)b)Rd3K|QOar;B4q#hkZu_vZ;a3LH}x(|@2eNq4D7q7-{n)+C{>J*~S1R&`7g zx~M4iWR|#xWB1BT$2^aTN|SV1HTwm)Hh-(kPtQ*)&rd%;FP?SZ>3jFS-~D%gx8)C` zzrQRj?3gmowHsfmyxx6T=jD?{=JW3#`1H-sN(G8UIN$ zT*wvPrDf-El%e5|+8q9LzmFDbM>@{`{JrhPP5UQC3tw{j{oIoD==Zw$-Ln`O-p+Pd zdpLN;1(kj8x64@YGGv@@5!pLKFaG|s&i4;$>X;cAZdfE%R&Td!Kegij_3A&r5A$F9 z>05Al^ZEQF8@YwQ0vx;>7`5v;6(7A<+Gy&!m~mbAiXXR+%y_W2=}q^Je{0udtXgO2 zq3WVdqRnxzk(o!9?zLzJPW#;`zcww;Vs{p>IASKjRLdjIOV5W}>Ls>RFC zORqnv%eh1-q1)cVuIXdN6PxSm`w~kR-`;U#kqq}w>Fb8!^Kvx4vmMap>}5;1t5ZLn z^9m1B&V2*dgg(wYUo;*`2hA?{@a*kx_xqgb>*K0~4Q!SAe(YvgYQ>asO@Ei5oQ(Y2 zxjz{8TzaQ`tKsGH^O~P7dIrr9NIhWJo!?=qc!NQ--noas5_vEm}6W*82wEd|-5NY5Z2hds)m*-|uUbyqQ-Y5Mmzk z(D7Z{D$bV&*^*wwOfWoXDz0*uBe}Y0$@b$3#g2AOY)O;ehx{~i2{iZK>X@-s&_-yQ zL8H=!7EZ&^vMV7je!>=qo|!0a+xw>VjmSQ)+6 zT9G1L)|;hYw3;_S_}1}vhhA4T7+8r(N0<_ zsFZT@k@Pj~q=irBOnJ;PEBMcidC40Xg^U-8B&yE)BO%&!bI{T8|#?({WkeMh12XVqQ#M_w&`&3MSA)H#0t z@3|(%u`Qpsu058wqA{tdYky-BQ>8-MhnWi=UH>@q!Ru|+_l1w$=MP|x3AoR{Vo@(f z^gFWo=;;SNU;Me{-4Q-L#;im2Z8LH|1cpwSCGelmsYH6id9@`Kj4GbWd-~OU^z<(% zh{;Gf&(O(#@A1$=ZMygyf2rC0c1t-@qg!Xol^0#KDR2|lnZtc_!2^q=eLaCI>T7@c><`P9XZs~ppXzEn&-2mAKBEuPM(uH z>%FmKj^nbb!?~UBy;r~dwep}(0`HL`N74Hnmd9=5g{lpr?@UVRm=TibU7>kbkJD9B o;Im5k)s`e4kHFrNi!Jqc=AB!7;hDWD0|Nttr>mdKI;Vst0A;y?ssI20 delta 1282 zcmcc5wTNqiK|RYIPZ!6KiaBrR?k~FRAaKlFF7AM9+MAgonm&&mynTb5CT=efcbd9z zNy-Zesbi-46Pm<=FCW^W=-PGWhH;`=zW`V9w3=OaZ|}8!sghkU8gc67m)c$SyQXeo zkAD^~?|$5U!tBoqFG5BV(uOI^-Ztb_C`|xQ@L+VJwpQ{!vVV)7hFFw z{*z|7kSn}P%g*5>L&Gy)3wixHk34-k1miz_FE!jypK*%izUZ7!Sx1j7@4GJ|%FOV} zyzzGXa)X2Fc3-1~EqEDLoNp1?JVQ_Z{xi<4g**2!GBCWcORTNlez*N}%8%)H{{4N} zo>4D<>C>CPwLZ&*L*)4~xDDzPbQN9x)T(S-{z2-2RY%u;?;g$+@f7(ZU-MI&*Y7@- zu$7_J-NQR!J45w`g;593&X0ewO`GAzkEADe%<3&l{+UVND_$)bdhhCaQ-(DcKdJf8 zukP2(V5~f;V?TevE@g)Obr+jIy!f%A z{1NksC~Ma(jGz7I2VYq{d5MAIsRq05{0>va8w{fR6^^wiFo*onTB!D7Zb90WhBGS| zX9hAGEoMt`<2}K%Q^r>M-r-K=0NeFzt?nMH-+HFjC~ks(`2yXBsOJCQ9?sm5^_ySp zF~frS+X|!(a5k*qWS#PZ?MzD-zR{o$Dqo(V4VZvEI&c=^aH(}GgV zIZmN}ngaHoJKpWfJz>^@N8uA+r5SDS{t<*ohuuKd!e z62X(#x9zzcz8V58+H{0@gUW0( z&3g}?)J@v#_gPbT6Kl#T^_b~DLL&D)Ue0FhSfYGQB<5pp!KJ^&N%zle(^HXDQVYLf xwr5J-_LeY7fnwG2t1Z_gCM=SExrp;WgAMO$$@`3@Vhjun44$rjF6*2UngBEpU>*Pf From b88364ab48c71b5ade799f9ccffb9cb0822adc1f Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 24 Jul 2021 08:36:20 -0400 Subject: [PATCH 004/130] Fixed #5638 --- core/src/mindustry/world/blocks/campaign/LaunchPad.java | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/mindustry/world/blocks/campaign/LaunchPad.java b/core/src/mindustry/world/blocks/campaign/LaunchPad.java index c36b5a7a91..f16753a8bd 100644 --- a/core/src/mindustry/world/blocks/campaign/LaunchPad.java +++ b/core/src/mindustry/world/blocks/campaign/LaunchPad.java @@ -156,7 +156,7 @@ public class LaunchPad extends Block{ Sector dest = state.rules.sector == null ? null : state.rules.sector.info.getRealDestination(); return Core.bundle.format("launch.destination", - dest == null ? Core.bundle.get("sectors.nonelaunch") : + dest == null || !dest.hasBase() ? Core.bundle.get("sectors.nonelaunch") : "[accent]" + dest.name()); }).pad(4).wrap().width(200f).left(); } diff --git a/gradle.properties b/gradle.properties index ba90b53b7a..097aaec115 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,4 +10,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=47822d851954fd2707d51731042056450f07ca8c +archash=c066b6a3db27ce21fa4d07c28c0d70b86a87cd55 From 7897d2858ca09727fa507c444472938eb3595736 Mon Sep 17 00:00:00 2001 From: SoMall-dumpling <57857764+SoMall-dumpling@users.noreply.github.com> Date: Sat, 24 Jul 2021 20:40:23 +0800 Subject: [PATCH 005/130] Update bundle_zh_CN.properties (#5530) * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties * Create bundle_zh_CN.properties * Create bundle_zh_CN.properties * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties * Update bundle_zh_CN.properties Updates the latest Navy Support Units description. * Update bundle_zh_CN.properties Perfectly matches. --- core/assets/bundles/bundle_zh_CN.properties | 404 ++++++++++++-------- 1 file changed, 249 insertions(+), 155 deletions(-) diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties index e94bf8c026..8577a9b6a0 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -41,10 +41,13 @@ be.ignore = 忽略 be.noupdates = 未发现更新。 be.check = 检测更新 -mod.featured.dialog.title = 模组浏览器 (尚未完成) +mods.browser = 模组浏览器 mods.browser.selected = 已选模组 -mods.browser.add=安装 -mods.github.open=查看 +mods.browser.add = 安装 +mods.browser.reinstall = 重装 +mods.github.open = 查看 +mods.browser.sortdate = 按时间排序 +mods.browser.sortstars = 按星标排序 schematic = 蓝图 schematic.add = 保存蓝图… @@ -64,6 +67,14 @@ schematic.delete.confirm = 确认删除蓝图? schematic.rename = 重命名蓝图 schematic.info = {0}x{1},{2} 个方块 schematic.disabled = [scarlet]蓝图已禁用![]\n您不能在此[accent]地图[]或[accent]服务器[]上使用蓝图. +schematic.tags = 标签: +schematic.edittags = 编辑标签 +schematic.addtag = 增加新标签 +schematic.texttag = 文字标签 +schematic.icontag = 图标标签 +schematic.renametag = 重命名标签 +schematic.tagdelconfirm = 确定要完全删除这个标签吗? +schematic.tagexists = 这个标签已经存在了。 stats = 统计资料 stat.wave = 防守波数:[accent]{0} @@ -90,6 +101,7 @@ customgame = 自定义游戏 newgame = 新游戏 none = <无> none.found = [lightgray]<未找到> +none.inmap = [lightgray]<无法在地图中找到> minimap = 小地图 position = 位置 close = 关闭 @@ -110,26 +122,29 @@ committingchanges = 正在提交更改 done = 已完成 feature.unsupported = 您的设备不支持此功能。 -mods.alphainfo = 请注意,测试版本中的模组[scarlet]很容易存在缺陷[]。\n在 Mindustry 的 GitHub 或 Discord 上报告你发现的问题。 +mods.initfailed = [red]⚠[] 前一次的mindustry启动失败,这可能是由存在异常的模组导致的。\n\n为了防止循环崩溃,[red]所有模组都被禁用了。[]\n\n如果想关闭这个功能,可以在[accent]设置->游戏->游戏启动崩溃时不禁用模组[]里关闭. mods = 模组 mods.none = [lightgray]没有找到模组! mods.guide = 模组制作教程 mods.report = 报告 Bug mods.openfolder = 打开模组文件夹 +mods.viewcontent = 查看内容 mods.reload = 重载 mods.reloadexit = 游戏将退出以重载模组。 +mod.installed = [[已装载] mod.display = [gray]模组:[orange] {0} mod.enabled = [lightgray]已启用 mod.disabled = [scarlet]已禁用 +mod.multiplayer.compatible = [gray]多人游戏兼容性 mod.disable = 禁用 mod.content = 内容: -mod.delete.error = 无法删除模组。可能文件被占用。 -mod.requiresversion = [scarlet]所需的游戏版本:[accent]{0} +mod.delete.error = 无法删除模组。文件可能正在使用中。 +mod.requiresversion = [scarlet]所需的最低游戏版本:[accent]{0} mod.outdated = [scarlet]该模组可能不能在6.0上正确地运行(缺失 minGameVersion: 105) mod.missingdependencies = [scarlet]缺少前置模组:{0} mod.erroredcontent = [scarlet]内容错误 mod.errors = 读取内容时发生错误. -mod.noerrorplay = [scarlet]你的模组发生了错误.[] 禁用相关模组或修复错误后才能进入游戏. +mod.noerrorplay = [scarlet]您的模组发生了错误.[] 禁用相关模组或修复错误后才能进入游戏. mod.nowdisabled = [scarlet]“{0}”模组缺少依赖条件:[accent] {1}\n[lightgray]需要先下载上述模组。\n此模组现在将自动禁用。 mod.enable = 启用 mod.requiresrestart = 需要重启使模组生效。 @@ -165,19 +180,19 @@ researched = [lightgray]{0}己研究。 research.progress = {0}% 完成度 players = {0} 位玩家在线 players.single = {0} 位玩家在线 -players.search = 研究 +players.search = 搜索 players.notfound = [gray]没有找到玩家。 server.closing = [accent]服务器关闭… -server.kicked.kick = 你被踢出了服务器。 -server.kicked.whitelist = 你不在服务器白名单中。 +server.kicked.kick = 您被踢出了服务器。 +server.kicked.whitelist = 您不在服务器白名单中。 server.kicked.serverClose = 服务器已关闭。 server.kicked.vote = 您被投票踢出了服务器。 -server.kicked.clientOutdated = 客户端过旧,请更新你的游戏。 +server.kicked.clientOutdated = 客户端过旧,请更新您的游戏。 server.kicked.serverOutdated = 服务器过旧,请联系服务器管理员升级服务器。 server.kicked.banned = 您在这个服务器上被封禁了。 -server.kicked.typeMismatch = 此服务器与你的不稳定测试版不兼容。 +server.kicked.typeMismatch = 此服务器与您的不稳定测试版不兼容。 server.kicked.playerLimit = 服务器已满,请等待一个空位。 -server.kicked.recentKick = 你刚刚被踢出服务器。\n请稍后重新连接! +server.kicked.recentKick = 您刚刚被踢出服务器。\n请稍后重新连接! server.kicked.nameInUse = 您的名字与服务器中的一个人重复了。 server.kicked.nameEmpty = 无效的名字! server.kicked.idInUse = 您已经连接了这个服务器!不允许在一台设备上用两个客户端连接。 @@ -214,6 +229,8 @@ trace.ip = IP 地址:[accent]{0} trace.id = 唯一的 ID:[accent]{0} trace.mobile = 移动客户端:[accent]{0} trace.modclient = 自定义客户端:[accent]{0} +trace.times.joined = 进入服务器次数: [accent]{0} +trace.times.kicked = 踢出服务器次数: [accent]{0} invalidid = 无效的客户端 ID!提交一个错误报告。 server.bans = 黑名单 server.bans.none = 没有被封禁的玩家! @@ -287,6 +304,7 @@ cancel = 取消 openlink = 打开链接 copylink = 复制链接 back = 返回 +max = 最大值 crash.export = 导出崩溃日志 crash.none = 找不到崩溃日志。 crash.exported = 崩溃日志已导出。 @@ -297,7 +315,6 @@ data.exported = 数据已导出。 data.invalid = 非有效游戏数据。 data.import.confirm = 导入外部游戏数据将覆盖本地[scarlet]全部[]的游戏数据。\n[accent]此操作无法撤销![]\n\n数据导入后将自动退出游戏。 quit.confirm = 确定退出? -quit.confirm.tutorial = 确定要跳过教程?\n您可以通过[accent]设置->游戏->重玩教程[]来重玩教程。 loading = [accent]加载中… reloading = [accent]重载模组中… saving = [accent]保存中… @@ -306,6 +323,7 @@ cancelbuilding = [accent][[{0}][]来清除规划 selectschematic = [accent][[{0}][]来选择复制 pausebuilding = [accent][[{0}][]来暂停建造 resumebuilding = [scarlet][[{0}][]来恢复建造 +enablebuilding = [scarlet][[{0}][]来启用建造 showui = UI已隐藏\n按[accent][[{0}][]显示UI wave = [accent]第{0}波 wave.cap = [accent]波次 {0}/{1} @@ -324,7 +342,7 @@ saveimage = 保存图片 unknown = 未知 custom = 自定义 builtin = 内置的 -map.delete.confirm = 您确定你想要删除这张地图吗?这个操作无法撤销! +map.delete.confirm = 您确定想要删除这张地图吗?这个操作无法撤销! map.random = [accent]随机地图 map.nospawn = 这个地图没有核心!请在编辑器中添加一个[royal]己方[]的核心。 map.nospawn.pvp = 这个地图没有敌人的核心!请在编辑器中添加一个[royal]敌人[]的核心。 @@ -332,7 +350,7 @@ map.nospawn.attack = 这个地图没有敌人的核心!请在编辑中向地 map.invalid = 地图载入错误:地图文件可能已经损坏。 workshop.update = 更新地图 workshop.error = 获取创意工坊详细信息时出错:{0} -map.publish.confirm = 确定上传此地图?\n\n[lightgray]确定你同意 Steam 创意工坊的最终用户许可协议,否则你的地图将不会被展示! +map.publish.confirm = 确定上传此地图?\n\n[lightgray]确定您同意 Steam 创意工坊的最终用户许可协议,否则您的地图将不会被展示! workshop.menu = 选择此项目的目的。 workshop.info = 项目信息 changelog = 更新日志(可选): @@ -345,8 +363,8 @@ steam.error = 初始化 Steam 服务失败。\n错误:{0} editor.brush = 笔刷 editor.openin = 在编辑器中打开 -editor.oregen = 矿石的生成 -editor.oregen.info = 矿石的生成: +editor.oregen = 矿物的生成 +editor.oregen.info = 矿物的生成: editor.mapinfo = 地图信息 editor.author = 作者: editor.description = 描述: @@ -361,7 +379,6 @@ editor.center = 居中 workshop = 创意工坊 waves.title = 波数 waves.remove = 移除 -waves.never = < 无限 > waves.every = 每 waves.waves = 波 waves.perspawn = 每次生成 @@ -436,30 +453,32 @@ toolmode.orthogonal = 正交线 toolmode.orthogonal.description = 只绘制正交线。 toolmode.square = 方形 toolmode.square.description = 方形刷子 -toolmode.eraseores = 清除矿石 -toolmode.eraseores.description = 只清除矿石。 -toolmode.fillteams = 填充团队 -toolmode.fillteams.description = 填充团队而不是方块。 -toolmode.drawteams = 绘制团队 -toolmode.drawteams.description = 绘制团队而不是方块。 +toolmode.eraseores = 清除矿物 +toolmode.eraseores.description = 只清除矿物。 +toolmode.fillteams = 填充队伍 +toolmode.fillteams.description = 填充队伍而不是方块。 +toolmode.drawteams = 绘制队伍 +toolmode.drawteams.description = 绘制队伍而不是方块。 filters.empty = [lightgray]没有过滤条件!用下方的按钮添加。 + filter.distort = 扭曲程度 filter.noise = 波动程度 filter.enemyspawn = 敌人生成点选择 filter.spawnpath = 敌人生成途径 filter.corespawn = 核心降落点选择 filter.median = 平均数 -filter.oremedian = 矿石平均数 +filter.oremedian = 矿物平均数 filter.blend = 混合程度 -filter.defaultores = 默认矿石 -filter.ore = 矿石 +filter.defaultores = 默认矿物 +filter.ore = 矿物 filter.rivernoise = 河流波动程度 filter.mirror = 镜像 filter.clear = 清理 filter.option.ignore = 忽略 filter.scatter = 分散程度 filter.terrain = 地形 + filter.option.scale = 规模大小 filter.option.chance = 几率大小 filter.option.mag = 巨大程度 @@ -468,13 +487,15 @@ filter.option.circle-scale = 圆规模 filter.option.octaves = 递增 filter.option.falloff = 递减 filter.option.angle = 角度大小 +filter.option.rotate = 旋转 filter.option.amount = 数量 filter.option.block = 方块 filter.option.floor = 地面 filter.option.flooronto = 地面目标 filter.option.target = 目标 +filter.option.replacement = 替换 filter.option.wall = 墙 -filter.option.ore = 矿石 +filter.option.ore = 矿物 filter.option.floor2 = 二重地面 filter.option.threshold2 = 二重阈值 filter.option.radius = 半径大小 @@ -487,8 +508,9 @@ play = 开始游戏 campaign = 战役模式 load = 载入游戏 save = 保存 -fps = 帧数:{0} +fps = FPS:{0} ping = 延迟:{0}毫秒 +tps = TPS: {0} memory = 内存: {0}mb memory2 = 内存:\n {0}mb +\n {1}mb language.restart = 为了使语言设置生效请重启游戏。 @@ -521,7 +543,7 @@ launch.from = 发射地: [accent]{0} launch.destination = 目的地: {0} configure.invalid = 数量必须是0到{0}之间的数字。 add = 添加… -boss.health = Boss 生命值 +guardian = 守卫者 connectfail = [crimson]服务器连接失败:[accent]{0} error.unreachable = 无法访问服务器。\n确定输对地址了吗? @@ -537,15 +559,16 @@ error.bloom = 未能初始化特效。\n您的设备可能不支持。 weather.rain.name = 降雨 weather.snow.name = 降雪 weather.sandstorm.name = 沙尘暴 -weather.sporestorm.name = 孢子雾 +weather.sporestorm.name = 孢子风暴 weather.fog.name = 雾 sectors.unexplored = [lightgray]未探索 sectors.resources = 资源: sectors.production = 产出: sectors.export = 输出: +sectors.import = 输入: sectors.time = 时间: -sectors.threat = 威胁 +sectors.threat = 威胁: sectors.wave = 进攻波: sectors.stored = 贮存: sectors.resume = 继续 @@ -554,7 +577,7 @@ sectors.select = 选择 sectors.nonelaunch = [lightgray]无 (太阳) sectors.rename = 重命名区块 sectors.enemybase = [scarlet]敌人基地 -sectors.vulnerable = [scarlet]脆弱的 +sectors.vulnerable = [scarlet]易受攻击 sectors.underattack = [scarlet]遭到攻击![accent]{0}% 损毁度 sectors.survives = [accent]存活{0}波 sectors.go = 进入 @@ -565,12 +588,13 @@ sector.attacked = 区块[accent]{0}[white]受到攻击! sector.lost = 区块[accent]{0}[white]已丢失! #note: the missing space in the line below is intentional sector.captured = 区块[accent]{0}[white]已占领! +sector.changeicon = 更改图标 threat.low = 低度 threat.medium = 中度 threat.high = 高度 threat.extreme = 极高 -threat.eradication = 扫荡 +threat.eradication = 毁灭 planets = 行星 @@ -605,12 +629,26 @@ sector.tarFields.description = 产油区边缘,位于山脉和沙漠之间。 sector.desolateRift.description = 非常危险的区域。这儿的资源丰富但空间很小。敌人十分危险。尽快离开,不要被敌人的攻击间隔太长所愚弄。 sector.nuclearComplex.description = 以前生产和加工钍的设施已变成废墟。\n[lightgray]研究钍及其多种用途。\n\n敌人在这里大量存在,不断消灭入侵者。 sector.fungalPass.description = 介于高山和低矮孢子丛生的土地之间的过渡地带。这里有一个小型的敌方侦察基地。\n侦察它。\n使用尖刀和爬行者单位来摧毁两个核心。 -sector.biomassFacility.description = 孢子的发源地。这里有最初研究和生产孢子的设施。\n研究这里的科技,培养孢子来制造燃料和聚合物。\n\n[lightgray]设施损毁后,孢子散播了出去,原生生态系统无法抵挡这种外来物种。 +sector.biomassFacility.description = 孢子的发源地。这里有最初研究和生产孢子的设施。\n研究这里的科技,培养孢子来制造燃料和混合物。\n\n[lightgray]设施损毁后,孢子散播了出去,原生生态系统无法抵挡这种外来物种。 sector.windsweptIslands.description = 海岸线之外坐落着这一串群岛。据记载这里曾有生产[accent]塑钢[]的建筑。\n\n抵御敌人的海军,在岛上建立基地,研究这些工厂。 sector.extractionOutpost.description = 一座遥远的前哨,敌人为了向其他区域发射资源而建立。\n\n跨区域运输技术是征服这个星球不可或缺的技术。摧毁敌人基地,研究发射台。 sector.impact0078.description = 这里有最初进入这个星系的星际运输船的遗迹。\n\n回收可以利用的资源,研究科技。 sector.planetaryTerminal.description = 最终目标。\n\n这座滨海基地有一个可以将核心发射到其他行星的建筑,防卫森严。\n\n制造海军单位,尽快消灭敌人,研究发射建筑。 +status.burning.name = 燃烧 +status.freezing.name = 冰冻 +status.wet.name = 潮湿 +status.muddy.name = 泥泞 +status.melting.name = 熔化 +status.sapped.name = 削弱 +status.electrified.name = 麻痹 +status.spore-slowed.name = 孢子减速 +status.tarred.name = 油浸 +status.overclock.name = 超频 +status.shocked.name = 电击 +status.blasted.name = 爆炸 +status.unmoving.name = 静止 + settings.language = 语言 settings.data = 游戏数据 settings.reset = 恢复默认设置 @@ -632,6 +670,7 @@ settings.clearcampaignsaves.confirm = 您确定要清除战役进度? paused = [accent]< 暂停 > clear = 清除 banned = [scarlet]已禁止 +unsupported.environment = [scarlet]不支持的环境 yes = 是 no = 否 info.title = [accent]详情 @@ -641,12 +680,14 @@ unit.nobuild = [scarlet]单位未能建造 lastaccessed = [lightgray]上次操作: {0} block.unknown = [lightgray]??? +stat.showinmap = <加载地图以展示> stat.description = 介绍 stat.input = 输入 stat.output = 输出 stat.booster = 增强物品/液体 stat.tiles = 所需地型 stat.affinities = 相关 +stat.opposites = 对立 stat.powercapacity = 能量容量 stat.powershot = 能量/发射 stat.damage = 伤害 @@ -669,6 +710,7 @@ stat.memorycapacity = 内存容量 stat.basepowergeneration = 基础能源输出 stat.productiontime = 生产时间 stat.repairtime = 建筑完全修复时间 +stat.repairspeed = 修复速度 stat.weapons = 武器 stat.bullet = 子弹 stat.speedincrease = 提速 @@ -678,6 +720,7 @@ stat.drillspeed = 基础钻探速度 stat.boosteffect = 增强效果 stat.maxunits = 最大单位数量 stat.health = 生命值 +stat.armor = 护甲 stat.buildtime = 建造时间 stat.maxconsecutive = 最大连续 stat.buildcost = 建造花费 @@ -693,6 +736,7 @@ stat.lightningchance = 激发闪电几率 stat.lightningdamage = 激发闪电伤害 stat.flammability = 燃烧性 stat.radioactivity = 放射性 +stat.charge = 放电性 stat.heatcapacity = 热容量 stat.viscosity = 粘度 stat.temperature = 温度 @@ -703,9 +747,16 @@ stat.minetier = 采矿等级 stat.payloadcapacity = 载货容量 stat.commandlimit = 指挥上限 stat.abilities = 能力 -stat.canboost = 可助推 -stat.flying = 可飞行 +stat.canboost = 是否能助推 +stat.flying = 是否能飞行 stat.ammouse = 弹药消耗 +stat.damagemultiplier = 伤害倍率 +stat.healthmultiplier = 生命倍率 +stat.speedmultiplier = 移速倍率 +stat.reloadmultiplier = 射速倍率 +stat.buildspeedmultiplier = 建造速度倍率 +stat.reactive = 反应性 +stat.healing = 治疗 ability.forcefield = 力墙场 ability.repairfield = 修复场 @@ -713,6 +764,7 @@ ability.statusfield = 状态场 ability.unitspawn = {0} 单位工厂 ability.shieldregenfield = 护盾再生场 ability.movelightning = 闪电助推器 +ability.energyfield = 能量场: [accent]{0}[] 伤害 ~ [accent]{1}[] 格 / [accent]{2}[] 目标数 bar.drilltierreq = 需要更高级的钻头 bar.noresources = 缺失资源 @@ -720,11 +772,12 @@ bar.corereq = 缺失核心基座 bar.drillspeed = 挖掘速度:{0}/秒 bar.pumpspeed = 泵压速度:{0}/秒 bar.efficiency = 效率:{0}% +bar.boost = 超速:{0}% bar.powerbalance = 能量:{0}/秒 bar.powerstored = 储能:{0}/{1} bar.poweramount = 能量:{0} bar.poweroutput = 能量输出:{0} -bar.powerlines = 链接: {0}/{1} +bar.powerlines = 链接:{0}/{1} bar.items = 物品:{0} bar.capacity = 容量:{0} bar.unitcap = {0} {1}/{2} @@ -734,29 +787,28 @@ bar.power = 电力 bar.progress = 制造进度 bar.input = 输入 bar.output = 输出 +bar.strength = [stat]{0}[lightgray]x 效率 units.processorcontrol = [lightgray]由处理器控制 bullet.damage = [stat]{0}[lightgray] 伤害 bullet.splashdamage = [stat]{0}[lightgray] 范围伤害 ~[stat] {1}[lightgray] 格 bullet.incendiary = [stat] 燃烧 -bullet.sapping = [stat] 削弱 bullet.homing = [stat] 追踪 -bullet.shock = [stat] 电击 bullet.frag = [stat] 分裂 +bullet.lightning = [stat]{0}[lightgray]x 电弧 ~ [stat]{1}[lightgray] 伤害 bullet.buildingdamage = [stat]{0}%[lightgray] 对建筑伤害 bullet.knockback = [stat]{0}[lightgray] 击退 bullet.pierce = [stat]{0}[lightgray]x 穿透 -bullet.infinitepierce = [stat] 穿透 +bullet.infinitepierce = [stat] 贯穿 bullet.healpercent = [stat]{0}[lightgray]% 修复 -bullet.freezing = [stat] 冰冻 -bullet.tarred = [stat] 减速 bullet.multiplier = [stat]{0}[lightgray]x 装弹数量 bullet.reload = [stat]{0}[lightgray]x 装弹速度 unit.blocks = 方块 unit.blockssquared = 方块² unit.powersecond = 能量/秒 +unit.tilessecond = 格/秒 unit.liquidsecond = 液体/秒 unit.itemssecond = 物品/秒 unit.liquidunits = 液体 @@ -791,18 +843,20 @@ setting.logichints.name = 逻辑代码提示 setting.flow.name = 显示资源传送速度[scarlet] setting.backgroundpause.name = 在背景中暂停 setting.buildautopause.name = 自动暂停建造 -setting.animatedwater.name = 流动的水 -setting.animatedshields.name = 动态画面 -setting.antialias.name = 抗锯齿 -setting.playerindicators.name = 玩家指示灯 -setting.indicators.name = 队友指示器 +setting.doubletapmine.name = 双击以采矿 +setting.modcrashdisable.name = 游戏启动崩溃时不禁用模组 +setting.animatedwater.name = 动态液体 +setting.animatedshields.name = 动态力场 +setting.playerindicators.name = 玩家指示器 +setting.indicators.name = 敌军指示器 setting.autotarget.name = 自动射击 setting.keyboard.name = 鼠标+键盘操控 setting.touchscreen.name = 触屏操控 setting.fpscap.name = 最大FPS setting.fpscap.none = 无 setting.fpscap.text = {0} FPS -setting.uiscale.name = UI缩放比例[lightgray](需要重新启动)[] +setting.uiscale.name = UI缩放比例 +setting.uiscale.description = 需要重新启动以应用更改。 setting.swapdiagonal.name = 总是斜线建造 setting.difficulty.training = 训练 setting.difficulty.easy = 简单 @@ -820,7 +874,8 @@ setting.saveinterval.name = 自动保存间隔 setting.seconds = {0} 秒 setting.milliseconds = {0} 毫秒 setting.fullscreen.name = 全屏 -setting.borderlesswindow.name = 无边界窗口[lightgray](可能需要重启) +setting.borderlesswindow.name = 无边界窗口 +setting.borderlesswindow.description = 可能需要重新启动以应用更改。 setting.fps.name = 显示 FPS 和网络延迟 setting.smoothcamera.name = 镜头平滑 setting.vsync.name = 垂直同步 @@ -910,6 +965,7 @@ keybind.pause_building.name = 暂停/继续建造 keybind.minimap.name = 小地图 keybind.planet_map.name = 行星地图 keybind.research.name = 研究 +keybind.block_info.name = 方块信息 keybind.chat.name = 聊天 keybind.player_list.name = 玩家列表 keybind.console.name = 控制台 @@ -936,21 +992,27 @@ mode.custom = 自定义模式 rules.infiniteresources = 无限资源 rules.reactorexplosions = 反应堆爆炸 -rules.schematic = 启用蓝图 +rules.coreincinerates = 核心自动焚烧溢出物资 +rules.schematic = 允许使用蓝图 rules.wavetimer = 波次计时器 rules.waves = 波次 rules.attack = 攻击模式 rules.buildai = AI建造 +rules.cleanupdeadteams = 清理被打败的队伍的建筑(PvP模式) +rules.corecapture = 摧毁核心时占领该核心 +rules.polygoncoreprotection = 多边形核心保护区域 rules.enemyCheat = 敌人(红队)无限资源 rules.blockhealthmultiplier = 建筑生命倍数 rules.blockdamagemultiplier = 建筑伤害倍数 rules.unitbuildspeedmultiplier = 单位生产速度倍数 rules.unithealthmultiplier = 单位生命倍数 rules.unitdamagemultiplier = 单位伤害倍数 -rules.enemycorebuildradius = 敌对核心非建设区半径:[lightgray](格) +rules.unitcapvariable = 每个核心提供的单位上限 +rules.unitcap = 基础单位上限 +rules.enemycorebuildradius = 敌方核心禁造区半径:[lightgray](格) rules.wavespacing = 波次间隔时间:[lightgray](秒) -rules.buildcostmultiplier = 建设花费倍数 -rules.buildspeedmultiplier = 建设时间倍数 +rules.buildcostmultiplier = 建材倍率 +rules.buildspeedmultiplier = 建造速率 rules.deconstructrefundmultiplier = 拆除返还倍数 rules.waitForWaveToEnd = 等待敌人时间 rules.dropzoneradius = 敌人出生点禁区大小:[lightgray](格) @@ -962,7 +1024,7 @@ rules.title.unit = 单位 rules.title.experimental = 实验性 rules.title.environment = 环境性 rules.lighting = 光照 -rules.enemyLights = 单位光照 +rules.enemyLights = 敌方光照 rules.fire = 火焰 rules.explosions = 建筑/单位爆炸伤害 rules.ambientlight = 环境光 @@ -973,8 +1035,9 @@ rules.weather.duration = 时长: content.item.name = 物品 content.liquid.name = 液体 -content.unit.name = 部队 -content.block.name = 块 +content.unit.name = 单位 +content.block.name = 建筑 +content.status.name = 状态效果 content.sector.name = 区域 item.copper.name = 铜 @@ -985,14 +1048,15 @@ item.titanium.name = 钛 item.thorium.name = 钍 item.silicon.name = 硅 item.plastanium.name = 塑钢 -item.phase-fabric.name = 相位物 +item.phase-fabric.name = 相织物 item.surge-alloy.name = 巨浪合金 item.spore-pod.name = 孢子荚 item.sand.name = 沙 item.blast-compound.name = 爆炸混合物 -item.pyratite.name = 硫 +item.pyratite.name = 火石 item.metaglass.name = 钢化玻璃 item.scrap.name = 废料 + liquid.water.name = 水 liquid.slag.name = 矿渣 liquid.oil.name = 石油 @@ -1024,6 +1088,11 @@ unit.minke.name = 飞鲨 unit.bryde.name = 戟鲸 unit.sei.name = 蛟龙 unit.omura.name = 海神 +unit.retusa.name = 潜螺 +unit.oxynoe.name = 电鳗 +unit.cyerce.name = 江豚 +unit.aegires.name = 神盾 +unit.navanax.name = 龙王 unit.alpha.name = 阿尔法 unit.beta.name = 贝塔 unit.gamma.name = 伽马 @@ -1072,7 +1141,7 @@ block.core-nucleus.name = 终代核心 block.deepwater.name = 深水 block.water.name = 水 block.tainted-water.name = 污水 -block.darksand-tainted-water.name = 暗沙 污水 +block.darksand-tainted-water.name = 黑沙 污水 block.tar.name = 石油 block.stone.name = 石头 block.sand.name = 沙子 @@ -1081,11 +1150,12 @@ block.ice.name = 冰 block.snow.name = 雪 block.craters.name = 陨石坑 block.sand-water.name = 沙 水 -block.darksand-water.name = 暗沙 水 +block.darksand-water.name = 黑沙 水 block.char.name = 焦土 -block.dacite.name = 英安岩 -block.dacite-wall.name = 英安岩墙 -block.dacite-boulder.name = 英安巨岩 +block.dacite.name = 安山岩 +block.rhyolite.name = 流纹岩 +block.dacite-wall.name = 安山岩墙 +block.dacite-boulder.name = 安山巨岩 block.ice-snow.name = 冰雪地 block.stone-wall.name = 石墙 block.ice-wall.name = 冰墙 @@ -1101,7 +1171,8 @@ block.spore-cluster.name = 孢子簇 block.metal-floor.name = 金属地板1 block.metal-floor-2.name = 金属地板2 block.metal-floor-3.name = 金属地板3 -block.metal-floor-5.name = 金属地板4 +block.metal-floor-4.name = 金属地板4 +block.metal-floor-5.name = 金属地板5 block.metal-floor-damaged.name = 损坏的金属地板 block.dark-panel-1.name = 暗面板1 block.dark-panel-2.name = 暗面板2 @@ -1111,16 +1182,16 @@ block.dark-panel-5.name = 暗面板5 block.dark-panel-6.name = 暗面板6 block.dark-metal.name = 暗金属 block.basalt.name = 玄武岩 -block.hotrock.name = 热石头 -block.magmarock.name = 岩浆石头 +block.hotrock.name = 灼热岩石 +block.magmarock.name = 熔融岩石 block.copper-wall.name = 铜墙 block.copper-wall-large.name = 大型铜墙 block.titanium-wall.name = 钛墙 block.titanium-wall-large.name = 大型钛墙 block.plastanium-wall.name = 塑钢墙 block.plastanium-wall-large.name = 大型塑钢墙 -block.phase-wall.name = 相位物墙 -block.phase-wall-large.name = 大型相位物墙 +block.phase-wall.name = 相织物墙 +block.phase-wall-large.name = 大型相织物墙 block.thorium-wall.name = 钍墙 block.thorium-wall-large.name = 大型钍墙 block.door.name = 门 @@ -1144,7 +1215,7 @@ block.illuminator.name = 照明器 block.overflow-gate.name = 溢流门 block.underflow-gate.name = 反向溢流门 block.silicon-smelter.name = 硅冶炼厂 -block.phase-weaver.name = 相位物编织器 +block.phase-weaver.name = 相织物编织器 block.pulverizer.name = 粉碎机 block.cryofluid-mixer.name = 冷冻液混合器 block.melter.name = 熔炉 @@ -1182,10 +1253,10 @@ block.tsunami.name = 海啸 block.swarmer.name = 蜂群 block.salvo.name = 齐射炮 block.ripple.name = 浪涌 -block.phase-conveyor.name = 相位物传送带桥 +block.phase-conveyor.name = 相织物传送带桥 block.bridge-conveyor.name = 传送带桥 block.plastanium-compressor.name = 塑钢压缩机 -block.pyratite-mixer.name = 硫化物混合器 +block.pyratite-mixer.name = 火石混合器 block.blast-mixer.name = 爆炸物混合器 block.solar-panel.name = 太阳能板 block.solar-panel-large.name = 大型太阳能板 @@ -1193,7 +1264,7 @@ block.oil-extractor.name = 石油钻井 block.repair-point.name = 维修点 block.pulse-conduit.name = 脉冲导管 block.plated-conduit.name = 电镀导管 -block.phase-conduit.name = 相位物导管桥 +block.phase-conduit.name = 相织物导管桥 block.liquid-router.name = 液体路由器 block.liquid-tank.name = 储液罐 block.liquid-junction.name = 液体交叉器 @@ -1233,14 +1304,20 @@ block.exponential-reconstructor.name = 多幂级单位重构工厂 block.tetrative-reconstructor.name = 无量级单位重构工厂 block.payload-conveyor.name = 载荷传送带 block.payload-router.name = 载荷路由器 +block.duct.name = 物品导管 +block.duct-router.name = 物品导管路由器 +block.duct-bridge.name = 物品导管桥 +block.payload-propulsion-tower.name = 载荷驱动台 +block.payload-void.name = 载荷黑洞 +block.payload-source.name =载荷源 block.disassembler.name = 解离机 block.silicon-crucible.name = 热能坩埚 block.overdrive-dome.name = 超速穹顶投射器 +block.interplanetary-accelerator.name = 行星际加速器 #experimental, may be removed block.block-forge.name = 方块熔炉 block.block-loader.name = 方块装载机 block.block-unloader.name = 方块卸载机 -block.interplanetary-accelerator.name = 行星际加速器 block.switch.name = 开关 block.micro-processor.name = 微型处理器 @@ -1254,50 +1331,50 @@ block.memory-bank.name = 内存库 team.blue.name = 蓝 team.crux.name = 红 team.sharded.name = 黄 -team.orange.name = 橙 team.derelict.name = 灰 team.green.name = 绿 team.purple.name = 紫 hint.skip = 跳过 -hint.desktopMove = 使用[accent][[WASD][]来移动. -hint.zoom = 滚动[accent]鼠标滚轮[]放大或缩小. -hint.mine = 移动到\uf8c4 铜矿附近并[accent]点按[]进行手动开采. -hint.desktopShoot = [accent][[鼠标左键][]射击. +hint.desktopMove = 使用[accent][[WASD][]来移动。 +hint.zoom = 滚动[accent]鼠标滚轮[]放大或缩小。 +hint.mine = 移动到\uf8c4 铜矿附近并[accent]点按[]进行手动开采。 +hint.desktopShoot = [accent][[鼠标左键][]射击。 hint.depositItems = 要转移物品,请将其从飞船上拖到核心。 -hint.respawn = 要于核心中重生,请按[accent][[V][]. -hint.respawn.mobile = 您已切换控制单元/结构. 如果要重生飞船,请[accent]点击左上方的图标(您的单元/结构图标).[] -hint.desktopPause = 按[accent][[Space][]暂停和取消暂停游戏. -hint.placeDrill = 选择右下角菜单中的\ue85e [accent]钻头[]分类,然后选择一个\uf870 [accent]钻头[]然后单击铜矿将其放置. -hint.placeDrill.mobile = 选择右下角菜单中的\ue85e [accent]钻头[]分类,然后选择一个\uf870 [accent]钻头[],然后点击铜矿将其放置.\n\n点击右下角\ue800 [accent]复选标记[]以确认. -hint.placeConveyor = 传送带将物品从钻头移到其他方块中。从\ue814 [accent]布局[]分类选择\uf896 [accent]传送带[].\n\n单击并拖动以放置多个传送带.\n[accent]滚动[]以旋转. -hint.placeConveyor.mobile = 传送带将物品从钻头移到其他块中。从\ue814 [accent]布局[]分类选择\uf896 [accent]传送带[].\n\n长按一秒钟,然后拖动以放置多个传送带. -hint.placeTurret = 放置\uf861 [accent]炮塔[]以抵御敌人,保卫你的核心.\n\n炮塔需要弹药-\uf838 铜.\n使用传送带和钻头为它们供弹。 -hint.breaking = [accent]右击[]并拖动以拆除方块. -hint.breaking.mobile = 点击在右下角的\ue817 [accent]锤子[]点击以拆除方块.\n\n按住手指一秒钟,然后拖动并选择. -hint.research = 点击\ue875 [accent]科技树[]按钮研究新技术. -hint.research.mobile = 点击在\ue88c [accent]菜单[]中的\ue875 [accent]科技树[]按钮以研究新技术. +hint.respawn = 要于核心中重生,请按[accent][[V][]。 +hint.respawn.mobile = 您已切换控制单元/建筑。如果要重生为飞船,请[accent]点击左上方的图标(您的单元/结构图标)。[] +hint.desktopPause = 按[accent][[Space][]暂停和取消暂停游戏。 +hint.placeDrill = 选择右下角菜单中的\ue85e [accent]钻头[]分类,然后选择一个\uf870 [accent]钻头[]然后单击铜矿将其放置。 +hint.placeDrill.mobile = 选择右下角菜单中的\ue85e [accent]钻头[]分类,然后选择一个\uf870 [accent]钻头[],然后点击铜矿将其放置。\n\n点击右下角\ue800 [accent]复选标记[]以确认。 +hint.placeConveyor = 传送带将物品从钻头移到其他方块中。从\ue814 [accent]布局[]分类选择\uf896 [accent]传送带[]。\n\n单击并拖动以放置多个传送带。\n[accent]滚动[]以旋转。 +hint.placeConveyor.mobile = 传送带将物品从钻头移到其他块中。从\ue814 [accent]布局[]分类选择\uf896 [accent]传送带[]。\n\n长按一秒钟,然后拖动以放置多个传送带。 +hint.placeTurret = 放置\uf861 [accent]炮塔[]以抵御敌人,保卫你的核心。\n\n炮塔需要弹药-\uf838 铜。\n使用传送带和钻头为它们供弹。 +hint.breaking = [accent]右击[]并拖动以拆除方块。 +hint.breaking.mobile = 点击在右下角的\ue817 [accent]锤子[]点击以拆除方块。\n\n按住手指一秒钟,然后拖动并选择。 +hint.blockInfo = 在 [accent]建造菜单[]中选择一个建筑,然后点击右边的 [accent][[?][]按钮以查看这个方块的信息。 +hint.research = 点击\ue875 [accent]科技树[]按钮研究新技术。 +hint.research.mobile = 点击在\ue88c [accent]菜单[]中的\ue875 [accent]科技树[]按钮以研究新技术。 hint.unitControl = 按住[accent][[L-ctrl][]并[accent]点击[]友军单位或炮塔来进行控制。 hint.unitControl.mobile = [accent][双击][]友军单位或炮塔来进行控制。 -hint.launch = 一旦收集到足够的资源,您就可以通过从右下角的\ue827 [accent]地图[]选择附近的区域[accent]发射[]核心. -hint.launch.mobile = 一旦收集到足够的资源,您就可以通过在\ue88c [accent]菜单[]的\ue827 [accent]地图[]选择附近的区域[accent]发射[]核心. -hint.schematicSelect = 按住[accent][[F][]并拖动以选择要复制和粘贴的块.\n\n[accent][鼠标中键][]复制单个块类型. -hint.conveyorPathfind = 按住[accent][[L-Ctrl][]拖动传送带并使其自动寻路. -hint.conveyorPathfind.mobile = 启用\ue844 [accent]传送带自动寻路[]并拖动,传送带会自动生成路径. -hint.boost = 按住[accent][[L-Shift][]用当前单位飞越障碍物.\n\n但只有少数地面单位有助推器. -hint.command = 按住[accent][[G][]指挥附近的单位编队. -hint.command.mobile = [accent][[双击][]您的部队指挥附近的部队编队. -hint.payloadPickup = 按[accent][[[]捡起小方块或单位. -hint.payloadPickup.mobile = [accent]长按一个小方块或一个单位来捡起来. -hint.payloadDrop = 按[accent]][]放下有效载荷. -hint.payloadDrop.mobile = [accent]点住[]一个空的位置将有效载荷丢到那里. -hint.waveFire = [accent]波浪[]炮塔加水弹药会自动扑灭附近的火. -hint.generator = \uf879 [accent]燃烧发电机[]燃烧煤炭并将电力传输到相邻方块.\n\n用\uf87f [accent]能量节点[]可以扩展电力传输范围. -hint.guardian = [accent]Boss[]单位装甲厚重.[accent]铜[]和[accent]铅[]这类较弱的子弹对其[scarlet]作用不佳[].\n\n使用高级别炮塔或使用\uf835 [accent]石墨[]作为\uf861 双管炮及\uf859 齐射炮的弹药来消灭Boss. +hint.launch = 一旦收集到足够的资源,您就可以通过从右下角的\ue827 [accent]地图[]选择附近的区域[accent]发射[]核心。 +hint.launch.mobile = 一旦收集到足够的资源,您就可以通过在\ue88c [accent]菜单[]的\ue827 [accent]地图[]选择附近的区域[accent]发射[]核心。 +hint.schematicSelect = 按住[accent][[F][]并拖动以选择要复制和粘贴的块。\n\n[accent][鼠标中键][]复制单个块类型。 +hint.conveyorPathfind = 按住[accent][[L-Ctrl][]拖动传送带并使其自动寻路。 +hint.conveyorPathfind.mobile = 启用\ue844 [accent]传送带自动寻路[]并拖动,传送带会自动生成路径。 +hint.boost = 按住[accent][[L-Shift][]用当前单位飞越障碍物。\n\n但只有少数地面单位有助推器。 +hint.command = 按住[accent][[G][]指挥附近的单位编队。 +hint.command.mobile = [accent][[双击][]您的部队指挥附近的部队编队。 +hint.payloadPickup = 按[accent][[[]捡起方块或单位。 +hint.payloadPickup.mobile = [accent]长按一个方块或一个单位来捡起来。 +hint.payloadDrop = 按[accent]][]放下捡起的方块或单位。 +hint.payloadDrop.mobile = [accent]点住[]一个空的位置将捡起的方块或单位丢到那里。 +hint.waveFire = [accent]波浪[]炮塔加水弹药会自动扑灭附近的火。 +hint.generator = \uf879 [accent]燃烧发电机[]燃烧煤炭并将电力传输到相邻方块。\n\n用\uf87f [accent]能量节点[]可以扩展电力传输范围。 +hint.guardian = [accent]Boss[]单位装甲厚重。[accent]铜[]和[accent]铅[]这类较弱的子弹对其[scarlet]作用不佳[]。\n\n使用高级别炮塔或使用\uf835 [accent]石墨[]作为\uf861 双管炮及\uf859 齐射炮的弹药来消灭Boss。 hint.coreUpgrade = 核心可以通过[accent]在上面覆盖高等级核心[]进行升级。\n\n在[accent]初代核心[]上放置一个[accent]次代核心[]。确保周围没有障碍物。 hint.presetLaunch = 灰色的[accent]降落地区[],如[accent]冰冻森林[],可以从任何区域发射,不需要占领附近的区块。\n\n[accent]数字编号的区域[],如这个,是[accent]可选的[]。 hint.coreIncinerate = 核心存满一种物品后,再进入的同种物品会被[accent]摧毁[]。 -hint.coopCampaign = 游玩[accent]合作战役[]时,当前地图生产的资源也会被送入[accent]你本地的区域[]。\n\n新科技也会同步解锁。 +hint.coopCampaign = 游玩[accent]合作战役[]时,当前地图生产的资源也会被送入[accent]您本地的区域[]。\n\n新科技也会同步解锁。 item.copper.description = 用于所有类型的建筑和弹药。 item.copper.details = 铜。在塞普罗上的异常丰富的金属。不经加固,结构会较脆弱。 @@ -1327,7 +1404,7 @@ liquid.oil.description = 用于先进材料生产和燃烧弹药。 liquid.cryofluid.description = 用作反应堆、炮塔和工厂的冷却剂。 block.resupply-point.description = 为附近的部队提供铜弹药。与需要电池供电的设备不兼容。 -block.armored-conveyor.description = 向前方移动物品。不接受边上的输入。 +block.armored-conveyor.description = 将物品向前输送。不接受两侧的非传送带输入。 block.illuminator.description = 释放光源。 block.message.description = 保存一条文字信息。用于队友之间进行交流。 block.graphite-press.description = 将煤炭压缩为石墨。 @@ -1335,11 +1412,11 @@ block.multi-press.description = 将煤炭压缩为石墨。需要水进行冷却 block.silicon-smelter.description = 将沙和煤炭精炼为硅。 block.kiln.description = 将沙和铅熔炼为钢化玻璃。 block.plastanium-compressor.description = 用石油和钛生产塑钢。 -block.phase-weaver.description = 从钍和沙合成相位物。 +block.phase-weaver.description = 用钍和沙合成相织物。 block.alloy-smelter.description = 将钛、铅、硅和铜熔合成巨浪合金。 block.cryofluid-mixer.description = 将水和细钛粉混合制成冷冻液。 -block.blast-mixer.description = 从硫化物和孢子荚中产生爆炸化合物。 -block.pyratite-mixer.description = 把煤、铅和沙子混和为硫化物。 +block.blast-mixer.description = 把火石和孢子荚混合为爆炸混合物。 +block.pyratite-mixer.description = 把煤、铅和沙子混合为火石。 block.melter.description = 将废料熔化成矿渣。 block.separator.description = 将矿渣分离成矿物成分。 block.spore-press.description = 将孢子荚压缩成石油。 @@ -1362,18 +1439,18 @@ block.thorium-wall.description = 保护己方结构,挡下敌方炮弹。 block.thorium-wall-large.description = 保护己方结构,挡下敌方炮弹。 block.phase-wall.description = 保护己方结构,挡下敌方炮弹。在受攻击时反射大多数子弹。 block.phase-wall-large.description = 保护己方结构,挡下敌方炮弹。在受攻击时反射大多数子弹。 -block.surge-wall.description = 保护己方结构,挡下敌方炮弹。受攻击时定期释放电弧。 -block.surge-wall-large.description = 保护己方结构,挡下敌方炮弹。受攻击时定期释放电弧。 +block.surge-wall.description = 保护己方结构,挡下敌方炮弹。受攻击时有几率释放电弧。 +block.surge-wall-large.description = 保护己方结构,挡下敌方炮弹。受攻击时有几率释放电弧。 block.door.description = 可以开关的墙。 block.door-large.description = 可以开关的墙。 block.mender.description = 定期修复附近的区块。\n可使用硅来提高范围和效率。 -block.mend-projector.description = 修复其附近的区块。\n可使用相位物来提高射程和效率。 -block.overdrive-projector.description = 提高附近建筑物的速度。\n可使用相位物来提高射程和效率。 -block.force-projector.description = 在自身周围创建一个六角形力场,使里面的建筑物和单位免受伤害。\n持续承受高伤害会导致过热,可以使用冷却液降温。相位物可用于增加护盾大小。 +block.mend-projector.description = 修复其附近的区块。\n可使用相织物来提高范围和效率。 +block.overdrive-projector.description = 提高附近建筑物的速度。\n可使用相织物来提高范围和效率。 +block.force-projector.description = 在自身周围创建一个六角形力场,使里面的建筑物和单位免受伤害。\n持续承受高伤害会导致过热,可以使用冷却液降温。相织物可用于增加护盾大小和盾容。 block.shock-mine.description = 对踩到它的敌人释放电弧进行攻击。 block.conveyor.description = 将物品向前输送。 block.titanium-conveyor.description = 将物品向前输送。快于初级传送带。 -block.plastanium-conveyor.description = 打包物品进行运输。\n在后方输入物品,在前方三个方向输出物品。需要多个装载和卸载点才能达到峰值载量。 +block.plastanium-conveyor.description = 打包物品进行运输。\n在后方输入物品,在前方三个方向输出物品。需要多个装载和卸载点才能达到最大运载量。 block.junction.description = 两条交叉传送带的桥梁。 block.bridge-conveyor.description = 跨越任意地形或建筑物运输物品。 block.phase-conveyor.description = 跨越任意地形或建筑物即时运输物品。比传送带桥范围更大,但需要电力。 @@ -1384,7 +1461,7 @@ block.router.details = 这是个好东西,也可以带来麻烦。不建议在 block.distributor.description = 将物品平均分配到其他7个方向。 block.overflow-gate.description = 当前方被阻塞时才会向左和右输出,用于处理多余的物品。 block.underflow-gate.description = 与溢流门相反。 当左右均堵塞时才向前方运输。 -block.mass-driver.description = 长距离物品传输结构,收集若干物品后将其射到远处的另一个质量驱动器。 +block.mass-driver.description = 长距离物品传输建筑,收集若干物品后将其射到远处的另一个质量驱动器。 block.mechanical-pump.description = 泵送液体,不需要能量。 block.rotary-pump.description = 泵送液体,需要能量。 block.thermal-pump.description = 泵送液体。 @@ -1405,7 +1482,7 @@ block.battery-large.description = 储存电网多余电力,并在电网供电 block.combustion-generator.description = 燃烧煤等可燃材料发电。 block.thermal-generator.description = 放置在炽热的地形上能够发电。 block.steam-generator.description = 通过燃烧易燃材料并将水转化为蒸汽来发电。 -block.differential-generator.description = 利用低温流体与燃烧的硫之间的温差产生大量能量。 +block.differential-generator.description = 利用低温流体与燃烧的火石之间的温差产生大量能量。 block.rtg-generator.description = 利用放射物的衰变产生的热量以缓慢的速度产生能量。 block.solar-panel.description = 提供少量太阳能。 block.solar-panel-large.description = 提供少量太阳能。比标准太阳能电池板更高效。 @@ -1431,7 +1508,7 @@ block.unloader.description = 从周围方块卸载指定物品。 block.launch-pad.description = 将货物发射至指定区块。 block.duo.description = 交替向敌人发射子弹。 block.scatter.description = 向敌机发射铅、废料或钢化玻璃高射炮弹。 -block.scorch.description = 焚烧任何靠近它的地面敌人。近距离高效 +block.scorch.description = 焚烧任何靠近它的地面敌人。近距离高效。 block.hail.description = 向远距离地面敌人发射小型炮弹。 block.wave.description = 向敌人射出液体流。使用水作弹药时能够自动灭火。 block.lancer.description = 充能并向地面单位发射强力的的波束。 @@ -1448,11 +1525,11 @@ block.repair-point.description = 持续修复其附近受损最严重的单位 block.segment.description = 摧毁袭来的除激光以外的子弹或导弹。 block.parallax.description = 通过牵引光束牵引空中目标,并在这个过程中对其造成伤害。 block.tsunami.description = 向敌人射出强力的液体流。使用水作弹药时能够自动灭火。 -block.silicon-crucible.description = 从沙子和煤中提炼硅,用硫化物作为附加热源。在炙热地型上更高效。 +block.silicon-crucible.description = 从沙子和煤中提炼硅,用火石作为附加热源。在炙热地型上更高效。 block.disassembler.description = 以低效率将矿渣分离成微量的外来矿物成分。能产生钍。 -block.overdrive-dome.description = 提高附近建筑物的速度。需要相位物和硅来工作。 -block.payload-conveyor.description = 移动大型有效载荷,例如从工厂生产的单位。 -block.payload-router.description = 将输入的有效载荷向3个方向输出。 +block.overdrive-dome.description = 提高附近建筑物的速度。需要相织物和硅来工作。 +block.payload-conveyor.description = 移动大型载荷,例如从工厂生产的单位。 +block.payload-router.description = 将输入的载荷向3个方向输出。 block.command-center.description = 使用多个不同的命令控制单位。 block.ground-factory.description = 产生陆军单位。输出的单位可以直接使用,也可以移入重构厂进行升级。 block.air-factory.description = 产生空军单位。输出的单位可以直接使用,也可以移入重构厂进行升级。 @@ -1469,41 +1546,48 @@ block.memory-cell.description = 存储处理器的信息。 block.memory-bank.description = 存储处理器的信息。内存量更大。 block.logic-display.description = 显示处理器中的任意图形。 block.large-logic-display.description = 显示处理器中的任意图形。 -block.interplanetary-accelerator.description = 一个巨大的电磁轨道加速器。加速核心逃逸速度以进行星际部署。 +block.interplanetary-accelerator.description = 一个巨大的电磁轨道加速器。加速核心至逃逸速度以进行星际部署。 +block.repair-turret.description = 持续修复其范围内最近的受损单位。可使用液体冷却以提高修复效率。 +block.payload-propulsion-tower.description = 长距离载荷运输建筑。向与其相链接的其它载荷驱动台发射载荷。 -unit.dagger.description = 攻击附近所有敌人。发射标准子弹。 -unit.mace.description = 攻击附近所有敌人。发射火焰。 -unit.fortress.description = 攻击地面敌人。发射远程火炮。 -unit.scepter.description = 攻击附近所有敌人。发射充能弹。 -unit.reign.description = 攻击附近所有敌人。发射穿透性子弹。 -unit.nova.description = 发射激光弹来攻击敌人并修复盟军建筑。能够飞行。 -unit.pulsar.description = 发射电弧来攻击敌人并修复盟军建筑。能够飞行。 -unit.quasar.description = 发射穿透性激光束来攻击敌人并修复盟军建筑。能够飞行。拥有护盾。 -unit.vela.description = 发射巨大的持续激光束攻击敌人,引起火灾并修复盟军建筑。能够飞行。 -unit.corvus.description = 发射巨大的激光爆破束,摧毁敌人并修复盟军建筑。可以跨越大多数地形。 +unit.dagger.description = 向附近所有敌人发射标准子弹。 +unit.mace.description = 向附近所有敌人喷射火焰。 +unit.fortress.description = 向附近所有地面敌人发射远程火炮。 +unit.scepter.description = 向附近所有敌人发射一串电荷弹。 +unit.reign.description = 向附近所有敌人发射巨型穿甲弹。 +unit.nova.description = 发射激光弹攻击敌人并修复友方建筑。能够飞行。 +unit.pulsar.description = 发射数条电弧攻击敌人并修复友方建筑。能够飞行。 +unit.quasar.description = 发射穿透性激光束攻击敌人并修复友方建筑。能够飞行。拥有护盾。 +unit.vela.description = 发射巨型持续激光束攻击敌人,点燃敌人并修复友方建筑。能够飞行。 +unit.corvus.description = 发射巨型爆破激光束攻击敌人并修复友方建筑。可以跨越大多数地形。 unit.crawler.description = 冲向敌人并自毁,造成大爆炸。 -unit.atrax.description = 向地面目标发射削弱性的矿渣球体。可以跨越大多数地形。 +unit.atrax.description = 向地面敌人发射削弱性矿渣球。可以跨越大多数地形。 unit.spiroct.description = 向敌人发射激光束,并在此过程中自我修复。可以跨越大多数地形。 -unit.arkyid.description = 向敌人发射大量激光束,并在此过程中自我修复。可以跨越大多数地形。 -unit.toxopid.description = 向敌人发射大型电能集束炮弹和穿透激光。可以跨越大多数地形。 -unit.flare.description = 攻击地面敌人。发射标准子弹。 -unit.horizon.description = 攻击地面敌人。投下炸弹。 -unit.zenith.description = 攻击附近所有敌人。发射导弹群。 -unit.antumbra.description = 攻击附近所有敌人。发射密集的子弹。 -unit.eclipse.description = 攻击附近所有敌人。发射穿透性激光和分裂弹。 +unit.arkyid.description = 向敌人发射大型激光束,并在此过程中自我修复。可以跨越大多数地形。 +unit.toxopid.description = 向敌人发射大型电能集束炮弹和穿透性激光。可以跨越大多数地形。 +unit.flare.description = 向附近所有地面敌人发射标准子弹。 +unit.horizon.description = 向地面敌人投下炸弹簇。 +unit.zenith.description = 向附近所有敌人发射导弹群。 +unit.antumbra.description = 向附近所有敌人发射弹幕。 +unit.eclipse.description = 向附近所有敌人发射两道穿透性激光和一连串子弹。 unit.mono.description = 自动开采铜和铅,并将其放入核心中。 -unit.poly.description = 自动重建受损结构,协助其他单位建造。 +unit.poly.description = 自动重建被摧毁的建筑并协助其他单位建造。 unit.mega.description = 自动修复受损结构。能够携带方块和小型地面部队。 -unit.quad.description = 向地面目标投掷大型炸弹,修复盟军建筑并摧毁敌人。能够携带中型地面部队。 -unit.oct.description = 用它的再生护盾保护附近的盟友。能够携带大多数地面部队。 -unit.risso.description = 攻击附近所有敌人。发射一连串的导弹和子弹。 -unit.minke.description = 攻击附近所有敌人。发射炮弹和标准子弹。 -unit.bryde.description = 攻击附近所有敌人。发射发射远程炮弹和导弹。 -unit.sei.description = 攻击附近所有敌人。发射一连串的导弹和穿甲弹。 -unit.omura.description = 攻击附近所有敌人。发射远程穿透轨道炮。可构造星耀单元。 -unit.alpha.description = 保护初代核心。可构建结构。 -unit.beta.description = 保护次代核心。可构建结构。 -unit.gamma.description = 保护终代核心。可构建结构。 +unit.quad.description = 向地面敌人投掷大型炸弹,修复友方建筑并攻击敌人。能够携带中型地面部队。 +unit.oct.description = 用它的再生护盾保护附近的友方单位。能够携带大多数地面部队。 +unit.risso.description = 向附近所有敌人发射一连串的导弹和子弹。 +unit.minke.description = 向附近所有敌人发射炮弹和标准子弹。 +unit.bryde.description = 向附近所有敌人发射远程炮弹和导弹。 +unit.sei.description = 向附近所有敌人发射一连串的导弹和穿甲弹。 +unit.omura.description = 向附近所有敌人发射远程穿透轨道炮。构造星辉单位。 +unit.alpha.description = 保护初代核心。可建造建筑。 +unit.beta.description = 保护次代核心。可建造建筑。 +unit.gamma.description = 保护终代核心。可建造建筑。 +unit.retusa.description = 在附近放置水雷并修复友方建筑。 +unit.oxynoe.description = 向附近所有敌人喷射火焰并修复友方建筑。使用点防御摧毁附近的敌方射弹。 +unit.cyerce.description = 向附近所有敌人发射跟踪集束导弹并修复友方建筑。 +unit.aegires.description = 电击一切在它能量场范围内的敌方单位和建筑并修复所有友方单位和建筑。 +unit.navanax.description = 发射电磁脉冲爆弹,破坏敌方电网并修复友方建筑。使用四门自动激光炮塔融化附近所有敌人。 lst.read = 从连接的内存读取数字 lst.write = 写入数字到连接的内存 @@ -1518,6 +1602,8 @@ lst.sensor = 从建筑或单位取得数据 lst.set = 设置变量 lst.operation = 操作一两个变量 lst.end = 跳至指令栈顶\n(第一条语句) +lst.wait = 等待指定的秒数。 +lst.lookup = 通过ID寻找特定的物品/液体/单位/块的类型。\n查找每个类型的总数量可以使用:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] lst.jump = 有条件地跳到另一语句 lst.unitbind = 绑定下一个某型号单位\n并存到[accent]@unit[] lst.unitcontrol = 控制绑定的单位 @@ -1537,6 +1623,7 @@ laccess.controller = 单位控制者\n如果是处理器,返回处理器\n如 laccess.dead = 单位或建筑是不是死了或无效了 laccess.controlled = 若单位控制者是处理器,返回[accent]@ctrlProcessor[]\n若单位/建筑由玩家控制,返回[accent]@ctrlPlayer[]\n若单位在编队中,返回[accent]@ctrlFormation[]\n其他的,返回0 laccess.commanded = [red]已弃用,将被移除![]\n应该使用[accent]controlled[] +laccess.progress = 动作进度, 范围0~1。\n返回方块生产、炮塔装填或建造的进度。 graphicstype.clear = 用指定颜色填满显示屏 graphicstype.color = 设置后续画图操作的颜色 @@ -1568,9 +1655,16 @@ lenum.min = 取小的那个数 lenum.max = 取大的那个数 lenum.angle = 方位角° lenum.len = 原点到该点距离 + lenum.sin = 正弦°(对边:斜边) lenum.cos = 余弦°(邻边:斜边) lenum.tan = 正切°(对边:邻边) + +lenum.asin = 反正弦 +lenum.acos = 反余弦 +lenum.atan = 反正切 + +#not a typo, look up 'range notation' lenum.rand = [0, 值) 范围内随机数 lenum.log = 自然对数(ln) lenum.log10 = 10底对数 From 9160ee546ceb3684bfc61e47eb914c7ec1a1a51b Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 24 Jul 2021 08:44:43 -0400 Subject: [PATCH 006/130] Allow derelict block pickup / Fixed derelict blocks being targeted --- core/src/mindustry/ai/BlockIndexer.java | 2 +- core/src/mindustry/input/InputHandler.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/ai/BlockIndexer.java b/core/src/mindustry/ai/BlockIndexer.java index aae2ca6467..a01e6e1b39 100644 --- a/core/src/mindustry/ai/BlockIndexer.java +++ b/core/src/mindustry/ai/BlockIndexer.java @@ -306,7 +306,7 @@ public class BlockIndexer{ for(int i = 0; i < activeTeams.size; i++){ Team enemy = activeTeams.items[i]; - if(enemy == team || (team == Team.derelict && !state.rules.coreCapture)) continue; + if(enemy == team || (enemy == Team.derelict && !state.rules.coreCapture)) continue; Building candidate = indexer.findTile(enemy, x, y, range, pred, true); if(candidate == null) continue; diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index bc385af592..1f0486a223 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -230,7 +230,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ Unit unit = player.unit(); - if(build != null && build.team == unit.team + if(build != null && state.teams.canInteract(unit.team, build.team) && unit.within(build, tilesize * build.block.size * 1.2f + tilesize * 5f)){ //pick up block's payload @@ -510,7 +510,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ }else{ Building build = world.buildWorld(pay.x(), pay.y()); - if(build != null && build.team == unit.team){ + if(build != null && state.teams.canInteract(unit.team, build.team)){ Call.requestBuildPayload(player, build); } } From adbfcdf16ad672fd7e12344d9f0887ee1789c78a Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 24 Jul 2021 09:14:38 -0400 Subject: [PATCH 007/130] Reverted vault/container health buff due to "damaged" appearance in saves --- core/src/mindustry/content/Blocks.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 8b84a190c7..a43108db74 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1388,14 +1388,14 @@ public class Blocks implements ContentList{ requirements(Category.effect, with(Items.titanium, 250, Items.thorium, 125)); size = 3; itemCapacity = 1000; - health = size * size * 60; + health = size * size * 55; }}; container = new StorageBlock("container"){{ requirements(Category.effect, with(Items.titanium, 100)); size = 2; itemCapacity = 300; - health = size * size * 60; + health = size * size * 55; }}; unloader = new Unloader("unloader"){{ From 9c5d75c439d22b8a4cf60936d2fb00370fa0a72f Mon Sep 17 00:00:00 2001 From: buthed010203 Date: Sat, 24 Jul 2021 10:41:01 -0400 Subject: [PATCH 008/130] Typo Fix (#5639) do --- core/src/mindustry/type/StatusEffect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/type/StatusEffect.java b/core/src/mindustry/type/StatusEffect.java index 4ae91a9d61..ae17118d7b 100644 --- a/core/src/mindustry/type/StatusEffect.java +++ b/core/src/mindustry/type/StatusEffect.java @@ -43,7 +43,7 @@ public class StatusEffect extends UnlockableContent{ public Color color = Color.white.cpy(); /** Effect that happens randomly on top of the affected unit. */ public Effect effect = Fx.none; - /** Affinity & opposite values for stat displaysdo. */ + /** Affinity & opposite values for stat displays. */ public ObjectSet affinities = new ObjectSet<>(), opposites = new ObjectSet<>(); /** Transition handler map. */ protected ObjectMap transitions = new ObjectMap<>(); From 0ee137fe05d27dd6c5ca10634a08eb65f63b73e7 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 24 Jul 2021 12:48:25 -0400 Subject: [PATCH 009/130] Added hint & tooltip for derelict structures --- core/assets/bundles/bundle.properties | 2 ++ core/src/mindustry/content/Blocks.java | 2 +- core/src/mindustry/entities/comp/BuildingComp.java | 4 +++- core/src/mindustry/ui/fragments/HintsFragment.java | 8 ++++++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 80d41b2dac..6104dac106 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1352,6 +1352,7 @@ hint.placeTurret = Place \uf861 [accent]Turrets[] to defend your base from enemi hint.breaking = [accent]Right-click[] and drag to break blocks. hint.breaking.mobile = Activate the \ue817 [accent]hammer[] in the bottom right and tap to break blocks.\n\nHold down your finger for a second and drag to break in a selection. hint.blockInfo = View information of a block by selecting it in the [accent]build menu[], then selecting the [accent][[?][] button at the right. +hint.derelict = [accent]Derelict[] structures are broken remnants of old bases that no longer function.\n\nThese structures can be [accent]deconstructed[] for resources. hint.research = Use the \ue875 [accent]Research[] button to research new technology. hint.research.mobile = Use the \ue875 [accent]Research[] button in the \ue88c [accent]Menu[] to research new technology. hint.unitControl = Hold [accent][[L-ctrl][] and [accent]click[] to control friendly units or turrets. @@ -1403,6 +1404,7 @@ liquid.slag.description = Refined in separators into constituent metals, or spra liquid.oil.description = Used in advanced material production and as incendiary ammunition. liquid.cryofluid.description = Used as coolant in reactors, turrets and factories. +block.derelict = [lightgray] Derelict block.resupply-point.description = Resupplies nearby units with copper ammunition. Not compatible with units that require battery power. block.armored-conveyor.description = Moves items forward. Does not accept inputs from the sides. block.illuminator.description = Emits light. diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index a43108db74..e2069e22b1 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -2032,7 +2032,7 @@ public class Blocks implements ContentList{ size = 5; reloadTime = 140f; chargeTime = 100f; - range = 500f; + range = 600f; maxPayloadSize = 3.5f; consumes.power(6f); }}; diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index b98b8bf470..47de632e6b 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -1071,7 +1071,9 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } public String getDisplayName(){ - return block.localizedName; + return team == Team.derelict ? + block.localizedName + "\n" + Core.bundle.get("block.derelict"): + block.localizedName; } public TextureRegion getDisplayIcon(){ diff --git a/core/src/mindustry/ui/fragments/HintsFragment.java b/core/src/mindustry/ui/fragments/HintsFragment.java index f4f677e720..b548a5536c 100644 --- a/core/src/mindustry/ui/fragments/HintsFragment.java +++ b/core/src/mindustry/ui/fragments/HintsFragment.java @@ -12,6 +12,7 @@ import arc.struct.*; import arc.util.*; import mindustry.*; import mindustry.content.*; +import mindustry.game.*; import mindustry.game.EventType.*; import mindustry.gen.*; import mindustry.input.*; @@ -54,6 +55,12 @@ public class HintsFragment extends Fragment{ hints.remove(hint); }else if(hint != null){ display(hint); + }else{ + //moused over a derelict structure + var build = world.buildWorld(Core.input.mouseWorldX(), Core.input.mouseWorldY()); + if(build != null && build.team == Team.derelict){ + events.add("derelictmouse"); + } } } }); @@ -157,6 +164,7 @@ public class HintsFragment extends Fragment{ conveyorPathfind(() -> control.input.block == Blocks.titaniumConveyor, () -> Core.input.keyRelease(Binding.diagonal_placement) || (mobile && Core.settings.getBool("swapdiagonal"))), boost(visibleDesktop, () -> !player.dead() && player.unit().type.canBoost, () -> Core.input.keyDown(Binding.boost)), blockInfo(() -> true, () -> ui.content.isShown()), + derelict(() -> ui.hints.events.contains("derelictmouse"), () -> false), command(() -> state.rules.defaultTeam.data().units.size > 3 && !net.active(), () -> player.unit().isCommanding()), payloadPickup(() -> !player.unit().dead && player.unit() instanceof Payloadc p && p.payloads().isEmpty(), () -> player.unit() instanceof Payloadc p && p.payloads().any()), payloadDrop(() -> !player.unit().dead && player.unit() instanceof Payloadc p && p.payloads().any(), () -> player.unit() instanceof Payloadc p && p.payloads().isEmpty()), From 7ec5aa28b39cffa620315b42c22e81d87807c7be Mon Sep 17 00:00:00 2001 From: MEEP of Faith <54301439+MEEPofFaith@users.noreply.github.com> Date: Sat, 24 Jul 2021 17:10:41 -0700 Subject: [PATCH 010/130] Include time in status effect draw (#5640) --- core/src/mindustry/entities/comp/StatusComp.java | 2 +- core/src/mindustry/type/StatusEffect.java | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/entities/comp/StatusComp.java b/core/src/mindustry/entities/comp/StatusComp.java index 70d1e38dcb..3c72200829 100644 --- a/core/src/mindustry/entities/comp/StatusComp.java +++ b/core/src/mindustry/entities/comp/StatusComp.java @@ -154,7 +154,7 @@ abstract class StatusComp implements Posc, Flyingc{ public void draw(){ for(StatusEntry e : statuses){ - e.effect.draw(self()); + e.effect.draw(self(), e.time); } } diff --git a/core/src/mindustry/type/StatusEffect.java b/core/src/mindustry/type/StatusEffect.java index ae17118d7b..20d5b1809e 100644 --- a/core/src/mindustry/type/StatusEffect.java +++ b/core/src/mindustry/type/StatusEffect.java @@ -152,6 +152,10 @@ public class StatusEffect extends UnlockableContent{ }); } + public void draw(Unit unit, float time){ + draw(unit); //Backwards compatibility + } + public void draw(Unit unit){ } From f77c32cbb2460c62ff363fe80587de59208bed10 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 24 Jul 2021 21:10:39 -0400 Subject: [PATCH 011/130] New flying unit targeting system --- core/src/mindustry/ai/types/FlyingAI.java | 24 ++++++++++++------- core/src/mindustry/content/UnitTypes.java | 10 ++++---- .../entities/units/AIController.java | 7 ++++-- core/src/mindustry/game/Team.java | 5 ++++ core/src/mindustry/type/UnitType.java | 5 +++- 5 files changed, 36 insertions(+), 15 deletions(-) diff --git a/core/src/mindustry/ai/types/FlyingAI.java b/core/src/mindustry/ai/types/FlyingAI.java index b3e35a21d1..0f2cb8c5e8 100644 --- a/core/src/mindustry/ai/types/FlyingAI.java +++ b/core/src/mindustry/ai/types/FlyingAI.java @@ -33,16 +33,24 @@ public class FlyingAI extends AIController{ @Override protected Teamc findTarget(float x, float y, float range, boolean air, boolean ground){ - Teamc result = target(x, y, range, air, ground); - if(result != null) return result; + var result = findMainTarget(x, y, range, air, ground); - if(ground) result = targetFlag(x, y, BlockFlag.generator, true); - if(result != null) return result; + //if the main target is in range, use it, otherwise target whatever is closest + return checkTarget(result, x, y, range) ? target(x, y, range, air, ground) : result; + } - if(ground) result = targetFlag(x, y, BlockFlag.core, true); - if(result != null) return result; - - return null; + @Override + protected Teamc findMainTarget(float x, float y, float range, boolean air, boolean ground){ + for(var flag : unit.team.isAI() ? unit.type.targetFlags : unit.type.playerTargetFlags){ + if(flag == null){ + Teamc result = target(x, y, range, air, ground); + if(result != null) return result; + }else if(ground){ + Teamc result = targetFlag(x, y, flag, true); + if(result != null) return result; + } + } + return targetFlag(x, y, BlockFlag.core, true); } protected void attack(float circleLength){ diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 8749c7f4e9..b218b1c483 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -928,6 +928,7 @@ public class UnitTypes implements ContentList{ engineOffset = 5.5f; range = 140f; targetAir = false; + targetFlags = new BlockFlag[]{BlockFlag.generator, null}; commandLimit = 4; circleTarget = true; hitSize = 7; @@ -961,7 +962,7 @@ public class UnitTypes implements ContentList{ range = 140f; faceTarget = false; armor = 3f; - targetFlag = BlockFlag.factory; + targetFlags = new BlockFlag[]{BlockFlag.factory, null}; commandLimit = 5; circleTarget = true; @@ -999,6 +1000,7 @@ public class UnitTypes implements ContentList{ lowAltitude = true; armor = 5f; + targetFlags = new BlockFlag[]{BlockFlag.launchPad, BlockFlag.storage, BlockFlag.battery, null}; engineOffset = 12f; engineSize = 3f; @@ -1045,7 +1047,7 @@ public class UnitTypes implements ContentList{ engineOffset = 21; engineSize = 5.3f; hitSize = 46f; - targetFlag = BlockFlag.battery; + targetFlags = new BlockFlag[]{BlockFlag.generator, BlockFlag.core, null}; BulletType missiles = new MissileBulletType(2.7f, 14){{ width = 8f; @@ -1120,7 +1122,7 @@ public class UnitTypes implements ContentList{ hitSize = 58f; destructibleWreck = false; armor = 13f; - targetFlag = BlockFlag.reactor; + targetFlags = new BlockFlag[]{BlockFlag.reactor, BlockFlag.core, null}; BulletType fragBullet = new FlakBulletType(4f, 5){{ shootEffect = Fx.shootBig; @@ -1333,7 +1335,7 @@ public class UnitTypes implements ContentList{ buildBeamOffset = 23; range = 140f; targetAir = false; - targetFlag = BlockFlag.battery; + targetFlags = new BlockFlag[]{BlockFlag.battery, BlockFlag.factory, null}; ammoType = AmmoTypes.powerHigh; diff --git a/core/src/mindustry/entities/units/AIController.java b/core/src/mindustry/entities/units/AIController.java index e4d2bfaf2b..c1764052da 100644 --- a/core/src/mindustry/entities/units/AIController.java +++ b/core/src/mindustry/entities/units/AIController.java @@ -79,7 +79,6 @@ public class AIController implements UnitController{ return Units.invalidateTarget(target, unit.team, unit.x, unit.y); } - protected void pathfind(int pathTarget){ int costType = unit.pathType(); @@ -97,7 +96,7 @@ public class AIController implements UnitController{ boolean ret = retarget(); if(ret){ - target = findTarget(unit.x, unit.y, unit.range(), unit.type.targetAir, unit.type.targetGround); + target = findMainTarget(unit.x, unit.y, unit.range(), unit.type.targetAir, unit.type.targetGround); } if(invalid(target)){ @@ -167,6 +166,10 @@ public class AIController implements UnitController{ return timer.get(timerTarget, target == null ? 40 : 90); } + protected Teamc findMainTarget(float x, float y, float range, boolean air, boolean ground){ + return findTarget(x, y, range, air, ground); + } + protected Teamc findTarget(float x, float y, float range, boolean air, boolean ground){ return target(x, y, range, air, ground); } diff --git a/core/src/mindustry/game/Team.java b/core/src/mindustry/game/Team.java index e8141d6063..c7c70cda01 100644 --- a/core/src/mindustry/game/Team.java +++ b/core/src/mindustry/game/Team.java @@ -96,6 +96,11 @@ public class Team implements Comparable{ return state.teams.isActive(this); } + /** @return whether this team is solely comprised of AI, with no players. */ + public boolean isAI(){ + return state.rules.waves && this == state.rules.waveTeam; + } + public boolean isEnemy(Team other){ return this != other; } diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index da238f0584..b3f15477b0 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -73,7 +73,10 @@ public class UnitType extends UnlockableContent{ public Effect fallThrusterEffect = Fx.fallSmoke; public Effect deathExplosionEffect = Fx.dynamicExplosion; public Seq abilities = new Seq<>(); - public BlockFlag targetFlag = BlockFlag.generator; + /** Flags to target based on priority. Null indicates that the closest target should be found. The closest enemy core is used as a fallback. */ + public BlockFlag[] targetFlags = {null}; + /** targetFlags, as an override for "non-AI" teams. By default, units of this type will rush the core. */ + public BlockFlag[] playerTargetFlags = {BlockFlag.core, null}; public Color outlineColor = Pal.darkerMetal; public int outlineRadius = 3; From 2fec2156f64dc98b55cf91368427d6e89f964953 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 24 Jul 2021 23:14:28 -0400 Subject: [PATCH 012/130] Fixed #5642 --- core/src/mindustry/world/blocks/payloads/PayloadSource.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/mindustry/world/blocks/payloads/PayloadSource.java b/core/src/mindustry/world/blocks/payloads/PayloadSource.java index f64377ede2..e290463224 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadSource.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadSource.java @@ -30,6 +30,7 @@ public class PayloadSource extends PayloadBlock{ configurable = true; //make sure to display large units. clipSize = 120; + noUpdateDisabled = true; config(Block.class, (PayloadSourceBuild build, Block block) -> { if(canProduce(block) && build.block != block){ From b6ed5fbd6fd63ade5c3f27c0e1e317f0aaa1fbf9 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 25 Jul 2021 08:41:06 -0400 Subject: [PATCH 013/130] Disable keyboard option on iOS --- .../mindustry/ui/dialogs/SettingsMenuDialog.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java index e291ace87d..64333796cf 100644 --- a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -292,13 +292,15 @@ public class SettingsMenuDialog extends Dialog{ if(mobile){ game.checkPref("autotarget", true); - game.checkPref("keyboard", false, val -> { - control.setInput(val ? new DesktopInput() : new MobileInput()); - input.setUseKeyboard(val); - }); - if(Core.settings.getBool("keyboard")){ - control.setInput(new DesktopInput()); - input.setUseKeyboard(true); + if(!ios){ + game.checkPref("keyboard", false, val -> { + control.setInput(val ? new DesktopInput() : new MobileInput()); + input.setUseKeyboard(val); + }); + if(Core.settings.getBool("keyboard")){ + control.setInput(new DesktopInput()); + input.setUseKeyboard(true); + } } } //the issue with touchscreen support on desktop is that: From b66cc8d8d7dbecbebc1662766648d8fda00d2aba Mon Sep 17 00:00:00 2001 From: EnderquakeYT <59123442+EnderquakeYT@users.noreply.github.com> Date: Sun, 25 Jul 2021 15:08:16 +0200 Subject: [PATCH 014/130] Fixed stuff and added translation (#5440) Fixed wave.enemy and added a translation for stat.charge --- core/assets/bundles/bundle_cs.properties | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties index f727c74fc6..aad326105f 100644 --- a/core/assets/bundles/bundle_cs.properties +++ b/core/assets/bundles/bundle_cs.properties @@ -307,7 +307,7 @@ waiting.players = Čekání na hráče... wave.enemies = [lightgray]{0} zbývajících nepřátel wave.enemycores = [accent]{0}[lightgray] nepřátelská jádra wave.enemycore = [accent]{0}[lightgray] nepřátelské jádro -wave.enemy = [lightgray]{0} zbývající nepřátel +wave.enemy = [lightgray]{0} zbývající nepřítel wave.guardianwarn = Počet vln do příchodu strážce: [accent]{0}[]. wave.guardianwarn.one = [accent]Strážce přijde již příští vlnu![] loadimage = Nahrát obrázek @@ -323,16 +323,16 @@ map.nospawn.attack = Tato mapa nemá nepřátelská jádra, která by mohla být map.invalid = Chyba v načítání mapy: poškozený nebo neplatný soubor mapy. workshop.update = Aktualizovat položku workshop.error = Chyba při načítání podrobností z Workshopu na Steamu: {0} -map.publish.confirm = Jsi si jistý, že chceš vystavit tuto mapu?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami Workshopu na Steamu (EULA), jinak se Tvoje mapa nezobrazí.[] +map.publish.confirm = Jsi si jistý, že chceš publikovat tuto mapu?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami Workshopu na Steamu (EULA), jinak se Tvoje mapa nezobrazí.[] workshop.menu = Vyber si, co bys chtěl dělat s touto položkou. workshop.info = Informace o položce changelog = Seznam změn (volitelně): eula = Smluvní podmínky platformy Steam missing = Tato položka byla smazána nebo přesunuta.\n[lightgray]Položka bude automaticky odebrána ze seznamu Workshopu na Steamu. publishing = [accent]Publikuji... -publish.confirm = Opravdu chceš toto vystavit?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami Workshopu na Steamu (EULA), jinak se Tvoje položky nezobrazí.[] -publish.error = Chyba při vystavování položky: {0} -steam.error = Nepodařilo se inicializovat služby platformy Steam.Chyba: {0} +publish.confirm = Opravdu chceš toto publikovat?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami Workshopu na Steamu (EULA), jinak se Tvoje položky nezobrazí.[] +publish.error = Chyba při publikování položky: {0} +steam.error = Nepodařilo se inicializovat služby platformy Steam. Chyba: {0} editor.brush = Štětec editor.openin = Otevřít v editoru @@ -341,12 +341,12 @@ editor.oregen.info = Generování rud: editor.mapinfo = Informace o mapě editor.author = Autor: editor.description = Popis: -editor.nodescription = Než může být mapa publikována, musí mít popisek dlouhý nejméně 4 znaky. +editor.nodescription = Než může být mapa publikována, musí mít popis dlouhý nejméně 4 znaky. editor.waves = Vln: editor.rules = Pravidla: editor.generation = Generace: editor.ingame = Upravit ve hře -editor.publish.workshop = Vystavit ve Workshopu na Steamu +editor.publish.workshop = Publikovat do Workshopu na Steamu editor.newmap = Nová mapa editor.center = Vycentrovat workshop = Workshop na Steamu @@ -684,6 +684,7 @@ stat.lightningchance = Pravděpodobnost blesku stat.lightningdamage = Poškození bleskem stat.flammability = Hořlavost stat.radioactivity = Radioaktivita +stat.charge = Nabití stat.heatcapacity = Tepelná kapacita stat.viscosity = Vazkost stat.temperature = Teplota From c14532ecae6c30fa4821bdd7e317bf0b623dd162 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 25 Jul 2021 12:04:17 -0400 Subject: [PATCH 015/130] Fixed #5645 --- core/assets/bundles/bundle.properties | 1 + core/src/mindustry/content/Fx.java | 2 +- core/src/mindustry/game/Schematics.java | 5 +++++ core/src/mindustry/io/SaveVersion.java | 2 +- core/src/mindustry/type/UnitType.java | 2 ++ core/src/mindustry/ui/dialogs/JoinDialog.java | 2 +- core/src/mindustry/ui/fragments/MenuFragment.java | 2 -- 7 files changed, 11 insertions(+), 5 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 6104dac106..303aae648f 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -215,6 +215,7 @@ hosts.none = [lightgray]No local games found! host.invalid = [scarlet]Can't connect to host. servers.local = Local Servers +servers.local.steam = Open Games & Local Servers servers.remote = Remote Servers servers.global = Community Servers diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index 2eb71b595b..509167dd6b 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -1628,7 +1628,7 @@ public class Fx{ coalSmeltsmoke = new Effect(40f, e -> { randLenVectors(e.id, 0.2f + e.fin(), 4, 6.3f, (x, y, fin, out) -> { color(Color.darkGray, Pal.coalBlack, e.finpowdown()); - Fill.circle(e.x + x, e.y + y, out * 2f + 0.25f); + Fill.circle(e.x + x, e.y + y, out * 2f + 0.35f); }); }), diff --git a/core/src/mindustry/game/Schematics.java b/core/src/mindustry/game/Schematics.java index f21381802c..d1eefe211f 100644 --- a/core/src/mindustry/game/Schematics.java +++ b/core/src/mindustry/game/Schematics.java @@ -432,6 +432,11 @@ public class Schematics implements Loadable{ if(seq.contains(t -> !t.block().alwaysReplace && !t.synthetic())){ return; } + for(var t : seq){ + if(t.block() != Blocks.air){ + t.remove(); + } + } } tile.setBlock(st.block, team, st.rotation); diff --git a/core/src/mindustry/io/SaveVersion.java b/core/src/mindustry/io/SaveVersion.java index 90fd35a59d..904591f268 100644 --- a/core/src/mindustry/io/SaveVersion.java +++ b/core/src/mindustry/io/SaveVersion.java @@ -363,7 +363,7 @@ public abstract class SaveVersion extends SaveFileReader{ int amount = stream.readInt(); for(int j = 0; j < amount; j++){ readChunk(stream, true, in -> { - byte typeid = in.readByte(); + int typeid = in.readUnsignedByte(); if(mapping[typeid] == null){ in.skipBytes(lastRegionLength - 1); return; diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index b3f15477b0..7d8291e4d2 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -41,7 +41,9 @@ public class UnitType extends UnlockableContent{ /** If true, the unit is always at elevation 1. */ public boolean flying; + /** Creates a new instance of this unit class. */ public Prov constructor; + /** The default AI controller to assign on creation. */ public Prov defaultController = () -> !flying ? new GroundAI() : new FlyingAI(); /** Environmental flags that are *all* required for this unit to function. 0 = any environment */ diff --git a/core/src/mindustry/ui/dialogs/JoinDialog.java b/core/src/mindustry/ui/dialogs/JoinDialog.java index 40ec81d077..89ac9464a6 100644 --- a/core/src/mindustry/ui/dialogs/JoinDialog.java +++ b/core/src/mindustry/ui/dialogs/JoinDialog.java @@ -271,7 +271,7 @@ public class JoinDialog extends BaseDialog{ hosts.clear(); - section("@servers.local", local, false); + section(steam ? "@servers.local.steam" : "@servers.local", local, false); section("@servers.remote", remote, false); section("@servers.global", global, true); diff --git a/core/src/mindustry/ui/fragments/MenuFragment.java b/core/src/mindustry/ui/fragments/MenuFragment.java index da51d18ede..ca3001f5b5 100644 --- a/core/src/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/mindustry/ui/fragments/MenuFragment.java @@ -120,7 +120,6 @@ public class MenuFragment extends Fragment{ table.add(tools); table.add(mods); - //if(platform.canDonate()) table.add(donate); if(!ios) table.add(exit); }).colspan(4); }else{ @@ -139,7 +138,6 @@ public class MenuFragment extends Fragment{ table.defaults().set(container.defaults()); table.add(mods); - //if(platform.canDonate()) table.add(donate); if(!ios) table.add(exit); }).colspan(2); } From 9cd19c047021c3cea289f5d3408396648aa426d1 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 25 Jul 2021 14:35:56 -0400 Subject: [PATCH 016/130] Fixed generator time not saving / 128 compat break --- core/src/mindustry/core/NetClient.java | 5 ++--- .../src/mindustry/world/blocks/power/PowerGenerator.java | 9 +++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java index da52f23269..6d01275325 100644 --- a/core/src/mindustry/core/NetClient.java +++ b/core/src/mindustry/core/NetClient.java @@ -1,6 +1,7 @@ package mindustry.core; import arc.*; +import arc.audio.*; import arc.func.*; import arc.graphics.*; import arc.math.*; @@ -159,8 +160,6 @@ public class NetClient implements ApplicationListener{ clientPacketReliable(type, contents); } - //TODO enable in build 129 - /* @Remote(variants = Variant.both, unreliable = true) public static void sound(Sound sound, float volume, float pitch, float pan){ if(sound == null) return; @@ -173,7 +172,7 @@ public class NetClient implements ApplicationListener{ if(sound == null) return; sound.at(x, y, pitch, volume); - }*/ + } @Remote(variants = Variant.both, unreliable = true) public static void effect(Effect effect, float x, float y, float rotation, Color color){ diff --git a/core/src/mindustry/world/blocks/power/PowerGenerator.java b/core/src/mindustry/world/blocks/power/PowerGenerator.java index 5a2bd12f0d..fe86c5fd15 100644 --- a/core/src/mindustry/world/blocks/power/PowerGenerator.java +++ b/core/src/mindustry/world/blocks/power/PowerGenerator.java @@ -61,16 +61,25 @@ public class PowerGenerator extends PowerDistributor{ return powerProduction * productionEfficiency; } + @Override + public byte version(){ + return 1; + } + @Override public void write(Writes write){ super.write(write); write.f(productionEfficiency); + write.f(generateTime); } @Override public void read(Reads read, byte revision){ super.read(read, revision); productionEfficiency = read.f(); + if(revision >= 1){ + generateTime = read.f(); + } } } } From 7a1f33273167e7b688d39652a3c5068b17c09a4c Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 25 Jul 2021 17:15:39 -0400 Subject: [PATCH 017/130] Ammo system redesign --- core/src/mindustry/content/Blocks.java | 11 --- core/src/mindustry/content/UnitTypes.java | 28 +++++-- core/src/mindustry/entities/Units.java | 21 +++++ .../entities/comp/AmmoDistributeComp.java | 28 ------- core/src/mindustry/mod/ClassMap.java | 2 - core/src/mindustry/mod/ContentParser.java | 23 +++++- core/src/mindustry/net/Net.java | 2 +- core/src/mindustry/type/AmmoType.java | 1 + core/src/mindustry/type/AmmoTypes.java | 52 ++++++++----- core/src/mindustry/type/UnitType.java | 3 - core/src/mindustry/world/Block.java | 4 +- .../world/blocks/campaign/LaunchPad.java | 8 -- .../world/blocks/storage/CoreBlock.java | 13 ---- .../world/blocks/storage/StorageBlock.java | 1 + .../world/blocks/units/ResupplyPoint.java | 77 ------------------- core/src/mindustry/world/meta/BlockFlag.java | 4 +- 16 files changed, 107 insertions(+), 171 deletions(-) delete mode 100644 core/src/mindustry/entities/comp/AmmoDistributeComp.java delete mode 100644 core/src/mindustry/world/blocks/units/ResupplyPoint.java diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index e2069e22b1..3340e06757 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -2003,17 +2003,6 @@ public class Blocks implements ContentList{ acceptCoolant = true; }}; - resupplyPoint = new ResupplyPoint("resupply-point"){{ - requirements(Category.units, BuildVisibility.ammoOnly, with(Items.lead, 20, Items.copper, 15, Items.silicon, 15)); - - size = 2; - range = 80f; - itemCapacity = 20; - ammoAmount = 5; - - consumes.item(Items.copper, 1); - }}; - //endregion //region payloads diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index b218b1c483..cfc3434ac4 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -52,8 +52,8 @@ public class UnitTypes implements ContentList{ //air + payload, legacy public static @EntityDef(value = {Unitc.class, Payloadc.class}, legacy = true) UnitType quad; - //air + payload + ammo distribution - public static @EntityDef({Unitc.class, Payloadc.class, AmmoDistributec.class}) UnitType oct; + //air + payload + legacy (different branch) + public static @EntityDef(value = {Unitc.class, Payloadc.class}, legacy = true) UnitType oct; //air, legacy public static @EntityDef(value = {Unitc.class}, legacy = true) UnitType alpha, beta, gamma; @@ -89,6 +89,7 @@ public class UnitTypes implements ContentList{ hitSize = 10f; health = 540; armor = 4f; + ammoType = AmmoTypes.coal; immunities.add(StatusEffects.burning); @@ -123,6 +124,7 @@ public class UnitTypes implements ContentList{ health = 900; armor = 9f; mechFrontSway = 0.55f; + ammoType = AmmoTypes.graphite; weapons.add(new Weapon("artillery"){{ top = false; @@ -156,6 +158,7 @@ public class UnitTypes implements ContentList{ armor = 10f; canDrown = false; mechFrontSway = 1f; + ammoType = AmmoTypes.thorium; mechStepParticles = true; mechStepShake = 0.15f; @@ -220,6 +223,7 @@ public class UnitTypes implements ContentList{ canDrown = false; mechFrontSway = 1.9f; mechSideSway = 0.6f; + ammoType = AmmoTypes.thorium; weapons.add( new Weapon("reign-weapon"){{ @@ -558,6 +562,7 @@ public class UnitTypes implements ContentList{ health = 200; mechSideSway = 0.25f; range = 40f; + ammoType = AmmoTypes.coal; weapons.add(new Weapon(){{ reload = 24f; @@ -595,6 +600,7 @@ public class UnitTypes implements ContentList{ legMoveSpace = 1.4f; hovering = true; armor = 3f; + ammoType = AmmoTypes.coal; allowLegStep = true; visualElevation = 0.2f; @@ -965,6 +971,7 @@ public class UnitTypes implements ContentList{ targetFlags = new BlockFlag[]{BlockFlag.factory, null}; commandLimit = 5; circleTarget = true; + ammoType = AmmoTypes.graphite; weapons.add(new Weapon(){{ minShootVelocity = 0.75f; @@ -1003,6 +1010,7 @@ public class UnitTypes implements ContentList{ targetFlags = new BlockFlag[]{BlockFlag.launchPad, BlockFlag.storage, BlockFlag.battery, null}; engineOffset = 12f; engineSize = 3f; + ammoType = AmmoTypes.graphite; weapons.add(new Weapon("zenith-missiles"){{ reload = 40f; @@ -1048,6 +1056,7 @@ public class UnitTypes implements ContentList{ engineSize = 5.3f; hitSize = 46f; targetFlags = new BlockFlag[]{BlockFlag.generator, BlockFlag.core, null}; + ammoType = AmmoTypes.thorium; BulletType missiles = new MissileBulletType(2.7f, 14){{ width = 8f; @@ -1123,6 +1132,7 @@ public class UnitTypes implements ContentList{ destructibleWreck = false; armor = 13f; targetFlags = new BlockFlag[]{BlockFlag.reactor, BlockFlag.core, null}; + ammoType = AmmoTypes.thorium; BulletType fragBullet = new FlakBulletType(4f, 5){{ shootEffect = Fx.shootBig; @@ -1407,9 +1417,7 @@ public class UnitTypes implements ContentList{ commandLimit = 6; lowAltitude = true; buildBeamOffset = 43; - - ammoCapacity = 1300; - ammoResupplyAmount = 20; + ammoCapacity = 1; abilities.add(new ForceFieldAbility(140f, 4f, 7000f, 60f * 8), new RepairFieldAbility(130f, 60f * 2, 140f)); }}; @@ -1477,6 +1485,7 @@ public class UnitTypes implements ContentList{ accel = 0.3f; rotateSpeed = 2.6f; rotateShooting = false; + ammoType = AmmoTypes.graphite; trailLength = 20; trailX = 5.5f; @@ -1520,6 +1529,7 @@ public class UnitTypes implements ContentList{ hitSize = 20f; armor = 7f; rotateShooting = false; + ammoType = AmmoTypes.graphite; trailLength = 22; trailX = 7f; @@ -1583,6 +1593,7 @@ public class UnitTypes implements ContentList{ inaccuracy = 5f; velocityRnd = 0.1f; shootSound = Sounds.missile; + ammoType = AmmoTypes.thorium; ejectEffect = Fx.none; bullet = new MissileBulletType(2.7f, 12){{ @@ -1616,6 +1627,7 @@ public class UnitTypes implements ContentList{ accel = 0.2f; rotateSpeed = 1.3f; rotateShooting = false; + ammoType = AmmoTypes.thorium; trailLength = 50; trailX = 18f; @@ -1701,6 +1713,7 @@ public class UnitTypes implements ContentList{ accel = 0.19f; rotateSpeed = 0.9f; rotateShooting = false; + ammoType = AmmoTypes.powerHigh; float spawnTime = 60f * 15f; @@ -1758,6 +1771,7 @@ public class UnitTypes implements ContentList{ trailScl = 1.3f; rotateShooting = false; range = 100f; + ammoType = AmmoTypes.power; armor = 3f; @@ -1835,6 +1849,7 @@ public class UnitTypes implements ContentList{ trailX = 5.5f; trailY = -4f; trailScl = 1.9f; + ammoType = AmmoTypes.coal; buildSpeed = 2f; @@ -1903,6 +1918,7 @@ public class UnitTypes implements ContentList{ hitSize = 20f; armor = 6f; rotateShooting = false; + ammoType = AmmoTypes.graphite; trailLength = 23; trailX = 9f; @@ -2038,6 +2054,7 @@ public class UnitTypes implements ContentList{ accel = 0.2f; rotateSpeed = 1.4f; rotateShooting = false; + ammoType = AmmoTypes.powerHigh; //clip size is massive due to energy field clipSize = 250f; @@ -2081,6 +2098,7 @@ public class UnitTypes implements ContentList{ accel = 0.2f; rotateSpeed = 1.1f; rotateShooting = false; + ammoType = AmmoTypes.powerHigh; trailLength = 70; trailX = 23f; diff --git a/core/src/mindustry/entities/Units.java b/core/src/mindustry/entities/Units.java index 6fa7889d8e..52e6ad749c 100644 --- a/core/src/mindustry/entities/Units.java +++ b/core/src/mindustry/entities/Units.java @@ -22,6 +22,7 @@ public class Units{ private static float cdist; private static boolean boolResult; private static int intResult; + private static Building buildResult; @Remote(called = Loc.server) public static void unitCapDeath(Unit unit){ @@ -157,6 +158,26 @@ public class Units{ return indexer.findEnemyTile(team, x, y, range, pred); } + /** @return the closest building of the provided team that matches the predicate. */ + public static @Nullable Building closestBuilding(Team team, float wx, float wy, float range, Boolf pred){ + buildResult = null; + cdist = 0f; + + var buildings = team.data().buildings; + if(buildings == null) return null; + buildings.intersect(wx - range, wy - range, range*2f, range*2f, b -> { + if(pred.get(b)){ + float dst = b.dst(wx, wy) - b.hitSize()/2f; + if(dst <= range && (buildResult == null || dst <= cdist)){ + cdist = dst; + buildResult = b; + } + } + }); + + return buildResult; + } + /** Iterates through all buildings in a range. */ public static void nearbyBuildings(float x, float y, float range, Cons cons){ indexer.allBuildings(x, y, range, cons); diff --git a/core/src/mindustry/entities/comp/AmmoDistributeComp.java b/core/src/mindustry/entities/comp/AmmoDistributeComp.java deleted file mode 100644 index 96e10a9ce0..0000000000 --- a/core/src/mindustry/entities/comp/AmmoDistributeComp.java +++ /dev/null @@ -1,28 +0,0 @@ -package mindustry.entities.comp; - -import arc.util.*; -import mindustry.annotations.Annotations.*; -import mindustry.game.*; -import mindustry.gen.*; -import mindustry.type.*; -import mindustry.world.blocks.units.*; - -@Component -abstract class AmmoDistributeComp implements Unitc{ - @Import float x, y; - @Import UnitType type; - @Import Team team; - @Import float ammo; - - private transient float ammoCooldown; - - @Override - public void update(){ - if(ammoCooldown > 0f) ammoCooldown -= Time.delta; - - if(ammo > 0 && ammoCooldown <= 0f && ResupplyPoint.resupply(team, x, y, type.ammoResupplyRange, Math.min(type.ammoResupplyAmount, ammo), type.ammoType.color, u -> u != self())){ - ammo -= Math.min(type.ammoResupplyAmount, ammo); - ammoCooldown = 5f; - } - } -} diff --git a/core/src/mindustry/mod/ClassMap.java b/core/src/mindustry/mod/ClassMap.java index 787dc27489..99c62e1d15 100644 --- a/core/src/mindustry/mod/ClassMap.java +++ b/core/src/mindustry/mod/ClassMap.java @@ -325,8 +325,6 @@ public class ClassMap{ classes.put("ReconstructorBuild", mindustry.world.blocks.units.Reconstructor.ReconstructorBuild.class); classes.put("RepairPoint", mindustry.world.blocks.units.RepairPoint.class); classes.put("RepairPointBuild", mindustry.world.blocks.units.RepairPoint.RepairPointBuild.class); - classes.put("ResupplyPoint", mindustry.world.blocks.units.ResupplyPoint.class); - classes.put("ResupplyPointBuild", mindustry.world.blocks.units.ResupplyPoint.ResupplyPointBuild.class); classes.put("UnitBlock", mindustry.world.blocks.units.UnitBlock.class); classes.put("UnitBuild", mindustry.world.blocks.units.UnitBlock.UnitBuild.class); classes.put("UnitFactory", mindustry.world.blocks.units.UnitFactory.class); diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java index 9c8c7f3b3a..262249efa9 100644 --- a/core/src/mindustry/mod/ContentParser.java +++ b/core/src/mindustry/mod/ContentParser.java @@ -29,6 +29,7 @@ import mindustry.gen.*; import mindustry.graphics.*; import mindustry.mod.Mods.*; import mindustry.type.*; +import mindustry.type.AmmoTypes.*; import mindustry.type.weather.*; import mindustry.world.*; import mindustry.world.blocks.units.*; @@ -95,6 +96,16 @@ public class ContentParser{ readFields(result, data); return result; }); + put(AmmoType.class, (type, data) -> { + if(data.isString()){ + return field(AmmoTypes.class, data); + } + var bc = resolve(data.getString("type", ""), ItemAmmoType.class); + data.remove("type"); + AmmoType result = make(bc); + readFields(result, data); + return result; + }); put(DrawBlock.class, (type, data) -> { if(data.isString()){ //try to instantiate @@ -346,6 +357,16 @@ public class ContentParser{ if(!value.has("sector") || !value.get("sector").isNumber()) throw new RuntimeException("SectorPresets must have a sector number."); return new SectorPreset(name, locate(ContentType.planet, value.getString("planet", "serpulo")), value.getInt("sector")); + }, + ContentType.ammo, (TypeParser)(mod, name, value) -> { + if(value.isString()){ + return (AmmoType)field(AmmoTypes.class, value.asString()); + } + + AmmoType item = make(resolve(value.getString("type", null), ItemAmmoType.class)); + currentContent = item; + read(() -> readFields(item, value)); + return item; } ); @@ -746,7 +767,7 @@ public class ContentParser{ /** Tries to resolve a class from the class type map. */ Class resolve(String base, Class def){ //no base class specified - if(base.isEmpty() && def != null) return def; + if((base == null || base.isEmpty()) && def != null) return def; //return mapped class if found in the global map var out = ClassMap.classes.get(!base.isEmpty() && Character.isLowerCase(base.charAt(0)) ? Strings.capitalize(base) : base); diff --git a/core/src/mindustry/net/Net.java b/core/src/mindustry/net/Net.java index fe2c4cc12e..0dc711ea3d 100644 --- a/core/src/mindustry/net/Net.java +++ b/core/src/mindustry/net/Net.java @@ -96,7 +96,7 @@ public class Net{ String type = t.getClass().toString().toLowerCase(); boolean isError = false; - if(e instanceof BufferUnderflowException || e instanceof BufferOverflowException){ + if(e instanceof BufferUnderflowException || e instanceof BufferOverflowException || e.getCause() instanceof EOFException){ error = Core.bundle.get("error.io"); }else if(error.equals("mismatch") || e instanceof LZ4Exception || (e instanceof IndexOutOfBoundsException && e.getStackTrace()[0].getClassName().contains("java.nio"))){ error = Core.bundle.get("error.mismatch"); diff --git a/core/src/mindustry/type/AmmoType.java b/core/src/mindustry/type/AmmoType.java index afe0a9818a..45fd8e06bc 100644 --- a/core/src/mindustry/type/AmmoType.java +++ b/core/src/mindustry/type/AmmoType.java @@ -10,6 +10,7 @@ public class AmmoType extends Content{ public String icon = Iconc.itemCopper + ""; public Color color = Pal.ammo; public Color barColor = Pal.ammo; + public float range = 85f; public AmmoType(char icon, Color color){ this.icon = icon + ""; diff --git a/core/src/mindustry/type/AmmoTypes.java b/core/src/mindustry/type/AmmoTypes.java index 761bcbc8d0..491167ab1e 100644 --- a/core/src/mindustry/type/AmmoTypes.java +++ b/core/src/mindustry/type/AmmoTypes.java @@ -1,12 +1,10 @@ package mindustry.type; -import mindustry.*; import mindustry.content.*; import mindustry.ctype.*; +import mindustry.entities.*; import mindustry.gen.*; import mindustry.graphics.*; -import mindustry.world.*; -import mindustry.world.meta.*; public class AmmoTypes implements ContentList{ public static AmmoType @@ -14,6 +12,8 @@ public class AmmoTypes implements ContentList{ power, powerHigh, copper, + graphite, + coal, thorium; @Override @@ -22,6 +22,8 @@ public class AmmoTypes implements ContentList{ power = new PowerAmmoType(1000); powerHigh = new PowerAmmoType(2000); copper = new ItemAmmoType(Items.copper); + graphite = new ItemAmmoType(Items.graphite); + coal = new ItemAmmoType(Items.coal); thorium = new ItemAmmoType(Items.thorium); } @@ -40,31 +42,29 @@ public class AmmoTypes implements ContentList{ @Override public void resupply(Unit unit){ - float range = unit.hitSize + 60f; - Tile closest = Vars.indexer.findClosestFlag(unit.x, unit.y, unit.team, BlockFlag.battery); + float range = unit.hitSize + this.range; - if(closest != null && closest.build != null && unit.within(closest.build, range) && closest.build.power != null){ - var build = closest.build; + Building build = Units.closestBuilding(unit.team, unit.x, unit.y, range, u -> u.block.hasPower && u.block.consumes.getPower().buffered); - if(build.block.consumes.hasPower() && build.block.consumes.getPower().buffered){ - float amount = closest.build.power.status * build.block.consumes.getPower().capacity; - float powerPerAmmo = totalPower / unit.type.ammoCapacity; - float ammoRequired = unit.type.ammoCapacity - unit.ammo; - float powerRequired = ammoRequired * powerPerAmmo; - float powerTaken = Math.min(amount, powerRequired); + if(build != null){ + float amount = build.power.status * build.block.consumes.getPower().capacity; + float powerPerAmmo = totalPower / unit.type.ammoCapacity; + float ammoRequired = unit.type.ammoCapacity - unit.ammo; + float powerRequired = ammoRequired * powerPerAmmo; + float powerTaken = Math.min(amount, powerRequired); - if(powerTaken > 1){ - closest.build.power.status -= powerTaken / build.block.consumes.getPower().capacity; - unit.ammo += powerTaken / powerPerAmmo; + if(powerTaken > 1){ + build.power.status -= powerTaken / build.block.consumes.getPower().capacity; + unit.ammo += powerTaken / powerPerAmmo; - Fx.itemTransfer.at(build.x, build.y, Math.max(powerTaken / 100f, 1f), Pal.power, unit); - } + Fx.itemTransfer.at(build.x, build.y, Math.max(powerTaken / 100f, 1f), Pal.power, unit); } } } } public static class ItemAmmoType extends AmmoType{ + public int ammoPerItem = 15; public Item item; public ItemAmmoType(Item item){ @@ -75,6 +75,22 @@ public class AmmoTypes implements ContentList{ public ItemAmmoType(){ } + @Override + public void resupply(Unit unit){ + //do not resupply when it would waste resources + if(unit.type.ammoCapacity - unit.ammo < ammoPerItem) return; + + float range = unit.hitSize + this.range; + + Building build = Units.closestBuilding(unit.team, unit.x, unit.y, range, u -> u.block.allowResupply && u.items.has(item)); + + if(build != null){ + Fx.itemTransfer.at(build.x, build.y, ammoPerItem / 2f, item.color, unit); + unit.ammo = Math.min(unit.ammo + ammoPerItem, unit.type.ammoCapacity); + build.items.remove(item, 1); + } + } + @Override public void load(){ if(item != null){ diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 7d8291e4d2..de2f9f3215 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -89,9 +89,6 @@ public class UnitType extends UnlockableContent{ public float legSplashDamage = 0f, legSplashRange = 5; public boolean flipBackLegs = true; - public int ammoResupplyAmount = 10; - public float ammoResupplyRange = 100f; - public float mechSideSway = 0.54f, mechFrontSway = 0.1f; public float mechStride = -1f; public float mechStepShake = -1f; diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index d7a52caf4b..94732f338a 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -70,8 +70,10 @@ public class Block extends UnlockableContent{ public boolean update; /** whether this block has health and can be destroyed */ public boolean destructible; - /** whether unloaders work on this block*/ + /** whether unloaders work on this block */ public boolean unloadable = true; + /** whether units can resupply by taking items from this block */ + public boolean allowResupply = false; /** whether this is solid */ public boolean solid; /** whether this block CAN be solid. */ diff --git a/core/src/mindustry/world/blocks/campaign/LaunchPad.java b/core/src/mindustry/world/blocks/campaign/LaunchPad.java index f16753a8bd..8f10c7b5b9 100644 --- a/core/src/mindustry/world/blocks/campaign/LaunchPad.java +++ b/core/src/mindustry/world/blocks/campaign/LaunchPad.java @@ -22,7 +22,6 @@ import mindustry.logic.*; import mindustry.type.*; import mindustry.ui.*; import mindustry.world.*; -import mindustry.world.consumers.*; import mindustry.world.meta.*; import static mindustry.Vars.*; @@ -42,7 +41,6 @@ public class LaunchPad extends Block{ solid = true; update = true; configurable = true; - drawDisabled = false; flags = EnumSet.of(BlockFlag.launchPad); } @@ -73,12 +71,6 @@ public class LaunchPad extends Block{ return !state.isCampaign() || net.client() ? SystemCursor.arrow : super.getCursor(); } - //cannot be disabled - @Override - public float efficiency(){ - return power != null && (block.consumes.has(ConsumeType.power) && !block.consumes.getPower().buffered) ? power.status : 1f; - } - @Override public boolean shouldConsume(){ return true; diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 7cc16ad306..8aa18cf014 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -20,7 +20,6 @@ import mindustry.logic.*; import mindustry.type.*; import mindustry.ui.*; import mindustry.world.*; -import mindustry.world.blocks.units.*; import mindustry.world.meta.*; import mindustry.world.modules.*; @@ -32,13 +31,7 @@ public class CoreBlock extends StorageBlock{ public UnitType unitType = UnitTypes.alpha; - public final int timerResupply = timers++; - - public int ammoAmount = 5; - public float resupplyRate = 10f; - public float resupplyRange = 60f; public float captureInvicibility = 60f * 15f; - public Item resupplyItem = Items.copper; public CoreBlock(String name){ super(name); @@ -240,13 +233,7 @@ public class CoreBlock extends StorageBlock{ @Override public void updateTile(){ - iframes -= Time.delta; - - //resupply nearby units - if(items.has(resupplyItem) && timer(timerResupply, resupplyRate) && ResupplyPoint.resupply(this, resupplyRange, ammoAmount, resupplyItem.color)){ - items.remove(resupplyItem, 1); - } } @Override diff --git a/core/src/mindustry/world/blocks/storage/StorageBlock.java b/core/src/mindustry/world/blocks/storage/StorageBlock.java index be74e98402..f0f5e6af05 100644 --- a/core/src/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/mindustry/world/blocks/storage/StorageBlock.java @@ -22,6 +22,7 @@ public class StorageBlock extends Block{ destructible = true; group = BlockGroup.transportation; flags = EnumSet.of(BlockFlag.storage); + allowResupply = true; } @Override diff --git a/core/src/mindustry/world/blocks/units/ResupplyPoint.java b/core/src/mindustry/world/blocks/units/ResupplyPoint.java deleted file mode 100644 index aa765127a9..0000000000 --- a/core/src/mindustry/world/blocks/units/ResupplyPoint.java +++ /dev/null @@ -1,77 +0,0 @@ -package mindustry.world.blocks.units; - -import arc.func.*; -import arc.graphics.*; -import arc.struct.*; -import mindustry.content.*; -import mindustry.entities.*; -import mindustry.game.*; -import mindustry.gen.*; -import mindustry.graphics.*; -import mindustry.type.AmmoTypes.*; -import mindustry.world.*; -import mindustry.world.meta.*; - -import static mindustry.Vars.*; - -public class ResupplyPoint extends Block{ - public final int timerResupply = timers++; - - public int ammoAmount = 10; - public float resupplyRate = 5f; - public float range = 60f; - public Color ammoColor = Items.copper.color; - - public ResupplyPoint(String name){ - super(name); - solid = update = true; - hasItems = true; - flags = EnumSet.of(BlockFlag.resupply); - } - - @Override - public boolean outputsItems(){ - return false; - } - - @Override - public void drawPlace(int x, int y, int rotation, boolean valid){ - Drawf.dashCircle(x * tilesize + offset, y * tilesize + offset, range, Pal.placing); - } - - public class ResupplyPointBuild extends Building{ - - @Override - public void drawSelect(){ - Drawf.dashCircle(x, y, range, team.color); - } - - @Override - public void updateTile(){ - if(consValid() && timer(timerResupply, resupplyRate / timeScale) && resupply(this, range, ammoAmount, ammoColor)){ - consume(); - } - } - } - - /** Tries to resupply nearby units. - * @return whether resupplying was successful. If unit ammo is disabled, always returns false. */ - public static boolean resupply(Building tile, float range, float ammoAmount, Color ammoColor){ - return resupply(tile.team, tile.x, tile.y, range, ammoAmount, ammoColor, u -> true); - } - - /** Tries to resupply nearby units. - * @return whether resupplying was successful. If unit ammo is disabled, always returns false. */ - public static boolean resupply(Team team, float x, float y, float range, float ammoAmount, Color ammoColor, Boolf valid){ - if(!state.rules.unitAmmo) return false; - - Unit unit = Units.closest(team, x, y, range, u -> u.type.ammoType instanceof ItemAmmoType && u.ammo <= u.type.ammoCapacity - ammoAmount && valid.get(u)); - if(unit != null){ - Fx.itemTransfer.at(x, y, ammoAmount / 2f, ammoColor, unit); - unit.ammo = Math.min(unit.ammo + ammoAmount, unit.type.ammoCapacity); - return true; - } - - return false; - } -} diff --git a/core/src/mindustry/world/meta/BlockFlag.java b/core/src/mindustry/world/meta/BlockFlag.java index c68e396278..c6f7ebbdd1 100644 --- a/core/src/mindustry/world/meta/BlockFlag.java +++ b/core/src/mindustry/world/meta/BlockFlag.java @@ -18,8 +18,6 @@ public enum BlockFlag{ rally, /** Block that stored power for resupply. */ battery, - /** Block used for resupply. */ - resupply, /** Any reactor block. */ reactor, /** This flag is unused, and will be removed. */ @@ -33,5 +31,5 @@ public enum BlockFlag{ public final static BlockFlag[] all = values(); /** Values for logic only. Filters out some internal flags. */ - public final static BlockFlag[] allLogic = {core, storage, generator, turret, factory, repair, rally, battery, resupply, reactor}; + public final static BlockFlag[] allLogic = {core, storage, generator, turret, factory, repair, rally, battery, reactor}; } From f8c7739d5a58b295e5b7d13bfe9b28e9e3fd84fa Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 25 Jul 2021 17:17:07 -0400 Subject: [PATCH 018/130] Removed unitModifier flag --- core/src/mindustry/world/meta/BlockFlag.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/src/mindustry/world/meta/BlockFlag.java b/core/src/mindustry/world/meta/BlockFlag.java index c6f7ebbdd1..985b66c181 100644 --- a/core/src/mindustry/world/meta/BlockFlag.java +++ b/core/src/mindustry/world/meta/BlockFlag.java @@ -20,9 +20,6 @@ public enum BlockFlag{ battery, /** Any reactor block. */ reactor, - /** This flag is unused, and will be removed. */ - @Deprecated - unitModifier, /** Blocks that extinguishes fires. */ extinguisher, /** Just a launch pad. */ From 1734d02291c5c9b26d3749cd1e8bc9469de60389 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 25 Jul 2021 19:21:13 -0400 Subject: [PATCH 019/130] Bridge code cleanup --- core/src/mindustry/content/Blocks.java | 12 +++- core/src/mindustry/mod/Mods.java | 2 +- .../distribution/BufferedItemBridge.java | 9 +-- .../distribution/ExtendingItemBridge.java | 61 +--------------- .../world/blocks/distribution/ItemBridge.java | 72 ++++++++++++------- .../world/blocks/liquid/LiquidBridge.java | 42 +++-------- .../blocks/liquid/LiquidExtendingBridge.java | 52 ++------------ 7 files changed, 77 insertions(+), 173 deletions(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 3340e06757..151d134752 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -964,15 +964,20 @@ public class Blocks implements ContentList{ itemBridge = new BufferedItemBridge("bridge-conveyor"){{ requirements(Category.distribution, with(Items.lead, 6, Items.copper, 6)); + fadeIn = moveArrows = false; range = 4; speed = 74f; + arrowSpacing = 6f; bufferCapacity = 14; }}; phaseConveyor = new ItemBridge("phase-conveyor"){{ requirements(Category.distribution, with(Items.phaseFabric, 5, Items.silicon, 7, Items.lead, 10, Items.graphite, 10)); range = 12; + arrowPeriod = 0.9f; + arrowTimeScl = 2.75f; hasPower = true; + pulse = true; consumes.power(0.30f); }}; @@ -1095,8 +1100,10 @@ public class Blocks implements ContentList{ requirements(Category.liquid, with(Items.graphite, 2, Items.metaglass, 2)); }}; - bridgeConduit = new LiquidExtendingBridge("bridge-conduit"){{ + bridgeConduit = new LiquidBridge("bridge-conduit"){{ requirements(Category.liquid, with(Items.graphite, 4, Items.metaglass, 8)); + fadeIn = moveArrows = false; + arrowSpacing = 6f; range = 4; hasPower = false; }}; @@ -1104,8 +1111,11 @@ public class Blocks implements ContentList{ phaseConduit = new LiquidBridge("phase-conduit"){{ requirements(Category.liquid, with(Items.phaseFabric, 5, Items.silicon, 7, Items.metaglass, 20, Items.titanium, 10)); range = 12; + arrowPeriod = 0.9f; + arrowTimeScl = 2.75f; hasPower = true; canOverdrive = false; + pulse = true; consumes.power(0.30f); }}; diff --git a/core/src/mindustry/mod/Mods.java b/core/src/mindustry/mod/Mods.java index 693ac2222a..cde7f8450f 100644 --- a/core/src/mindustry/mod/Mods.java +++ b/core/src/mindustry/mod/Mods.java @@ -626,7 +626,7 @@ public class Mods implements Loadable{ try{ //this binds the content but does not load it entirely Content loaded = parser.parse(l.mod, l.file.nameWithoutExtension(), l.file.readString("UTF-8"), l.file, l.type); - Log.debug("[@] Loaded '@'.", l.mod.meta.name, (loaded instanceof UnlockableContent ? ((UnlockableContent)loaded).localizedName : loaded)); + Log.debug("[@] Loaded '@'.", l.mod.meta.name, (loaded instanceof UnlockableContent u ? u.localizedName : loaded)); }catch(Throwable e){ if(current != content.getLastAdded() && content.getLastAdded() != null){ parser.markError(content.getLastAdded(), l.mod, l.file, e); diff --git a/core/src/mindustry/world/blocks/distribution/BufferedItemBridge.java b/core/src/mindustry/world/blocks/distribution/BufferedItemBridge.java index a87fb0348a..6fe8e90722 100644 --- a/core/src/mindustry/world/blocks/distribution/BufferedItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/BufferedItemBridge.java @@ -1,12 +1,11 @@ package mindustry.world.blocks.distribution; -import arc.math.*; import arc.util.io.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; -public class BufferedItemBridge extends ExtendingItemBridge{ +public class BufferedItemBridge extends ItemBridge{ public final int timerAccept = timers++; public float speed = 40f; @@ -19,7 +18,7 @@ public class BufferedItemBridge extends ExtendingItemBridge{ canOverdrive = true; } - public class BufferedItemBridgeBuild extends ExtendingItemBridgeBuild{ + public class BufferedItemBridgeBuild extends ItemBridgeBuild{ ItemBuffer buffer = new ItemBuffer(bufferCapacity); @Override @@ -30,11 +29,9 @@ public class BufferedItemBridge extends ExtendingItemBridge{ Item item = buffer.poll(speed / timeScale); if(timer(timerAccept, 4 / timeScale) && item != null && other.acceptItem(this, item)){ - cycleSpeed = Mathf.lerpDelta(cycleSpeed, 4f, 0.05f); + moved = true; other.handleItem(this, item); buffer.remove(); - }else{ - cycleSpeed = Mathf.lerpDelta(cycleSpeed, 0f, 0.008f); } } diff --git a/core/src/mindustry/world/blocks/distribution/ExtendingItemBridge.java b/core/src/mindustry/world/blocks/distribution/ExtendingItemBridge.java index 98b48e043a..7e2e5eac55 100644 --- a/core/src/mindustry/world/blocks/distribution/ExtendingItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/ExtendingItemBridge.java @@ -1,70 +1,15 @@ package mindustry.world.blocks.distribution; -import arc.graphics.g2d.*; -import arc.math.*; -import arc.math.geom.*; -import mindustry.core.*; -import mindustry.graphics.*; -import mindustry.world.*; - -import static mindustry.Vars.*; - +/** @deprecated use ItemBridge instead. */ +@Deprecated public class ExtendingItemBridge extends ItemBridge{ public ExtendingItemBridge(String name){ super(name); - hasItems = true; } + @Deprecated public class ExtendingItemBridgeBuild extends ItemBridgeBuild{ - @Override - public void draw(){ - Draw.rect(region, x, y); - Draw.z(Layer.power); - - Tile other = world.tile(link); - if(!linkValid(tile, other)) return; - - int i = tile.absoluteRelativeTo(other.x, other.y); - - float ex = other.worldx() - x - Geometry.d4(i).x * tilesize / 2f, - ey = other.worldy() - y - Geometry.d4(i).y * tilesize / 2f; - - float uptime = state.isEditor() ? 1f : this.uptime; - - ex *= uptime; - ey *= uptime; - - if(Mathf.zero(Renderer.bridgeOpacity)) return; - Draw.alpha(Renderer.bridgeOpacity); - - Lines.stroke(8f); - Lines.line(bridgeRegion, - x + Geometry.d4(i).x * tilesize / 2f, - y + Geometry.d4(i).y * tilesize / 2f, - x + ex, - y + ey, false); - - Draw.rect(endRegion, x, y, i * 90 + 90); - Draw.rect(endRegion, - x + ex + Geometry.d4(i).x * tilesize / 2f, - y + ey + Geometry.d4(i).y * tilesize / 2f, i * 90 + 270); - - int dist = Math.max(Math.abs(other.x - tile.x), Math.abs(other.y - tile.y)); - - int arrows = (dist) * tilesize / 6 - 1; - - Draw.color(); - - for(int a = 0; a < arrows; a++){ - Draw.alpha(Mathf.absin(a / (float)arrows - time / 100f, 0.1f, 1f) * uptime * Renderer.bridgeOpacity); - Draw.rect(arrowRegion, - x + Geometry.d4(i).x * (tilesize / 2f + a * 6f + 2) * uptime, - y + Geometry.d4(i).y * (tilesize / 2f + a * 6f + 2) * uptime, - i * 90f); - } - Draw.reset(); - } } } diff --git a/core/src/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/mindustry/world/blocks/distribution/ItemBridge.java index 53f69b5aef..8f5233f535 100644 --- a/core/src/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/ItemBridge.java @@ -23,12 +23,20 @@ import static mindustry.Vars.*; public class ItemBridge extends Block{ private static BuildPlan otherReq; + public final int timerCheckMoved = timers ++; + public int range; public float transportTime = 2f; public @Load("@-end") TextureRegion endRegion; public @Load("@-bridge") TextureRegion bridgeRegion; public @Load("@-arrow") TextureRegion arrowRegion; + public boolean fadeIn = true; + public boolean moveArrows = true; + public boolean pulse = false; + public float arrowSpacing = 4f, arrowOffset = 2f, arrowPeriod = 0.4f; + public float arrowTimeScl = 6.2f; + //for autolink public @Nullable ItemBridgeBuild lastBuild; @@ -171,10 +179,9 @@ public class ItemBridge extends Block{ public int link = -1; //TODO awful public IntSet incoming = new IntSet(); - public float uptime; + public float warmup; public float time; - public float time2; - public float cycleSpeed = 1f; + public boolean wasMoved, moved; public float transportCounter; @Override @@ -283,24 +290,23 @@ public class ItemBridge extends Block{ @Override public void updateTile(){ - time += cycleSpeed * delta(); - time2 += (cycleSpeed - 1f) * delta(); + if(timer(timerCheckMoved, 30f)){ + wasMoved = moved; + moved = false; + } + + time += wasMoved ? delta() : 0f; checkIncoming(); Tile other = world.tile(link); if(!linkValid(tile, other)){ doDump(); - uptime = 0f; + warmup = 0f; }else{ ((ItemBridgeBuild)other.build).incoming.add(tile.pos()); - if(consValid() && Mathf.zero(1f - efficiency())){ - uptime = Mathf.lerpDelta(uptime, 1f, 0.04f); - }else{ - uptime = Mathf.lerpDelta(uptime, 0f, 0.02f); - } - + warmup = Mathf.approachDelta(warmup, efficiency(), 1f / 30f); updateTransport(other.build); } } @@ -311,21 +317,18 @@ public class ItemBridge extends Block{ } public void updateTransport(Building other){ - boolean any = false; transportCounter += edelta(); while(transportCounter >= transportTime){ Item item = items.take(); if(item != null && other.acceptItem(this, item)){ other.handleItem(this, item); - any = true; + moved = true; }else if(item != null){ items.add(item, 1); items.undoFlow(item); } transportCounter -= transportTime; } - - cycleSpeed = Mathf.lerpDelta(cycleSpeed, any ? 4f : 1f, any ? 0.05f : 0.01f); } @Override @@ -341,8 +344,11 @@ public class ItemBridge extends Block{ int i = relativeTo(other.x, other.y); - Draw.color(Color.white, Color.black, Mathf.absin(Time.time, 6f, 0.07f)); - Draw.alpha(Math.max(uptime, 0.25f) * Renderer.bridgeOpacity); + if(pulse){ + Draw.color(Color.white, Color.black, Mathf.absin(Time.time, 6f, 0.07f)); + } + + Draw.alpha((fadeIn ? Math.max(warmup, 0.25f) : 1f) * Renderer.bridgeOpacity); Draw.rect(endRegion, x, y, i * 90 + 90); Draw.rect(endRegion, other.drawx(), other.drawy(), i * 90 + 270); @@ -357,19 +363,20 @@ public class ItemBridge extends Block{ other.worldx() - Tmp.v1.x, other.worldy() - Tmp.v1.y, false); - int dist = Math.max(Math.abs(other.x - tile.x), Math.abs(other.y - tile.y)); - - float time = time2 / 1.7f; - int arrows = (dist) * tilesize / 4 - 2; + int dist = Math.max(Math.abs(other.x - tile.x), Math.abs(other.y - tile.y)) - 1; Draw.color(); + int arrows = (int)(dist * tilesize / arrowSpacing), dx = Geometry.d4x(i), dy = Geometry.d4y(i); + for(int a = 0; a < arrows; a++){ - Draw.alpha(Mathf.absin(a / (float)arrows - time / 100f, 0.1f, 1f) * uptime * Renderer.bridgeOpacity); + Draw.alpha(Mathf.absin(a - time / arrowTimeScl, arrowPeriod, 1f) * warmup * Renderer.bridgeOpacity); Draw.rect(arrowRegion, - x + Geometry.d4(i).x * (tilesize / 2f + a * 4f + time % 4f), - y + Geometry.d4(i).y * (tilesize / 2f + a * 4f + time % 4f), i * 90f); + x + dx * (tilesize / 2f + a * arrowSpacing + arrowOffset), + y + dy * (tilesize / 2f + a * arrowSpacing + arrowOffset), + i * 90f); } + Draw.reset(); } @@ -460,11 +467,16 @@ public class ItemBridge extends Block{ return Point2.unpack(link).sub(tile.x, tile.y); } + @Override + public byte version(){ + return 1; //TODO write cycleSpeed, 1 + } + @Override public void write(Writes write){ super.write(write); write.i(link); - write.f(uptime); + write.f(warmup); write.b(incoming.size); IntSetIterator it = incoming.iterator(); @@ -472,17 +484,23 @@ public class ItemBridge extends Block{ while(it.hasNext){ write.i(it.next()); } + + write.bool(wasMoved || moved); } @Override public void read(Reads read, byte revision){ super.read(read, revision); link = read.i(); - uptime = read.f(); + warmup = read.f(); byte links = read.b(); for(int i = 0; i < links; i++){ incoming.add(read.i()); } + + if(revision >= 1){ + wasMoved = moved = read.bool(); + } } } } diff --git a/core/src/mindustry/world/blocks/liquid/LiquidBridge.java b/core/src/mindustry/world/blocks/liquid/LiquidBridge.java index 83b2fe3e1e..4214a1cee9 100644 --- a/core/src/mindustry/world/blocks/liquid/LiquidBridge.java +++ b/core/src/mindustry/world/blocks/liquid/LiquidBridge.java @@ -1,13 +1,10 @@ package mindustry.world.blocks.liquid; -import arc.math.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.blocks.distribution.*; import mindustry.world.meta.*; -import static mindustry.Vars.*; - public class LiquidBridge extends ItemBridge{ public LiquidBridge(String name){ @@ -20,40 +17,19 @@ public class LiquidBridge extends ItemBridge{ } public class LiquidBridgeBuild extends ItemBridgeBuild{ + @Override - public void updateTile(){ - time += cycleSpeed * delta(); - time2 += (cycleSpeed - 1f) * delta(); - - checkIncoming(); - - Building other = world.build(link); - if(other == null || !linkValid(tile, other.tile())){ - dumpLiquid(liquids.current(), 1f); - }else{ - ((ItemBridgeBuild)other).incoming.add(tile.pos()); - - if(consValid()){ - float alpha = 0.04f; - if(hasPower){ - alpha *= efficiency(); // Exceed boot time unless power is at max. - } - uptime = Mathf.lerpDelta(uptime, 1f, alpha); - }else{ - uptime = Mathf.lerpDelta(uptime, 0f, 0.02f); - } - - if(uptime >= 0.5f){ - - if(moveLiquid(other, liquids.current()) > 0.1f){ - cycleSpeed = Mathf.lerpDelta(cycleSpeed, 4f, 0.05f); - }else{ - cycleSpeed = Mathf.lerpDelta(cycleSpeed, 1f, 0.01f); - } - } + public void updateTransport(Building other){ + if(warmup >= 0.5f){ + moved |= moveLiquid(other, liquids.current()) > 0.05f; } } + @Override + public void doDump(){ + dumpLiquid(liquids.current(), 1f); + } + @Override public boolean acceptItem(Building source, Item item){ return false; diff --git a/core/src/mindustry/world/blocks/liquid/LiquidExtendingBridge.java b/core/src/mindustry/world/blocks/liquid/LiquidExtendingBridge.java index 552c348891..37dcc69b7d 100644 --- a/core/src/mindustry/world/blocks/liquid/LiquidExtendingBridge.java +++ b/core/src/mindustry/world/blocks/liquid/LiquidExtendingBridge.java @@ -1,56 +1,14 @@ package mindustry.world.blocks.liquid; -import arc.math.*; -import mindustry.gen.*; -import mindustry.type.*; -import mindustry.world.blocks.distribution.*; -import mindustry.world.meta.*; - -import static mindustry.Vars.*; - -public class LiquidExtendingBridge extends ExtendingItemBridge{ +/** @deprecated use LiquidBridge instead. */ +@Deprecated +public class LiquidExtendingBridge extends LiquidBridge{ public LiquidExtendingBridge(String name){ super(name); - hasItems = false; - hasLiquids = true; - outputsLiquid = true; - group = BlockGroup.liquids; } - public class LiquidExtendingBridgeBuild extends ExtendingItemBridgeBuild{ - @Override - public void updateTile(){ - time += cycleSpeed * delta(); - time2 += (cycleSpeed - 1f) * delta(); - - checkIncoming(); - - Building other = world.build(link); - if(other == null || !linkValid(tile, other.tile())){ - dumpLiquid(liquids.current(), 1f); - }else{ - ((ItemBridgeBuild)other).incoming.add(tile.pos()); - - if(consValid()){ - uptime = Mathf.lerpDelta(uptime, 1f, 0.04f); - }else{ - uptime = Mathf.lerpDelta(uptime, 0f, 0.02f); - } - - if(uptime >= 0.5f){ - if(moveLiquid(other, liquids.current()) > 0.1f){ - cycleSpeed = Mathf.lerpDelta(cycleSpeed, 4f, 0.05f); - }else{ - cycleSpeed = Mathf.lerpDelta(cycleSpeed, 0f, 0.01f); - } - } - } - } - - @Override - public boolean acceptItem(Building source, Item item){ - return false; - } + @Deprecated + public class LiquidExtendingBridgeBuild extends LiquidBridgeBuild{ } } From d1fb436d6d2be94890bd3739adb12bb786360e1c Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 25 Jul 2021 19:55:07 -0400 Subject: [PATCH 020/130] Further bridge cleanup --- .../world/blocks/distribution/ItemBridge.java | 64 ++++++++----------- .../world/blocks/liquid/LiquidBridge.java | 8 +-- gradle.properties | 2 +- 3 files changed, 27 insertions(+), 47 deletions(-) diff --git a/core/src/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/mindustry/world/blocks/distribution/ItemBridge.java index 8f5233f535..f8f3af4ab9 100644 --- a/core/src/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/ItemBridge.java @@ -5,7 +5,6 @@ import arc.graphics.g2d.*; import arc.math.*; import arc.math.geom.*; import arc.struct.*; -import arc.struct.IntSet.*; import arc.util.*; import arc.util.io.*; import mindustry.annotations.Annotations.*; @@ -177,8 +176,7 @@ public class ItemBridge extends Block{ public class ItemBridgeBuild extends Building{ public int link = -1; - //TODO awful - public IntSet incoming = new IntSet(); + public IntSeq incoming = new IntSeq(false, 4); public float warmup; public float time; public boolean wasMoved, moved; @@ -278,13 +276,15 @@ public class ItemBridge extends Block{ } public void checkIncoming(){ - IntSetIterator it = incoming.iterator(); - while(it.hasNext){ - int i = it.next(); + int idx = 0; + while(idx < incoming.size){ + int i = incoming.items[idx]; Tile other = world.tile(i); if(!linkValid(tile, other, false) || ((ItemBridgeBuild)other.build).link != tile.pos()){ - it.remove(); + incoming.removeIndex(idx); + idx --; } + idx ++; } } @@ -304,7 +304,11 @@ public class ItemBridge extends Block{ doDump(); warmup = 0f; }else{ - ((ItemBridgeBuild)other.build).incoming.add(tile.pos()); + var inc = ((ItemBridgeBuild)other.build).incoming; + int pos = tile.pos(); + if(!inc.contains(pos)){ + inc.add(pos); + } warmup = Mathf.approachDelta(warmup, efficiency(), 1f / 30f); updateTransport(other.build); @@ -382,22 +386,7 @@ public class ItemBridge extends Block{ @Override public boolean acceptItem(Building source, Item item){ - if(team != source.team) return false; - - Tile other = world.tile(link); - - if(items.total() >= itemCapacity) return false; - - if(linked(source)) return true; - - if(linkValid(tile, other)){ - int rel = relativeTo(other); - int rel2 = relativeTo(Edges.getFacingEdge(source, this)); - - return rel != rel2; - } - - return false; + return hasItems && team == source.team && items.total() < itemCapacity && checkAccept(source, world.tile(link)); } @Override @@ -407,16 +396,17 @@ public class ItemBridge extends Block{ @Override public boolean acceptLiquid(Building source, Liquid liquid){ - if(team != source.team || !hasLiquids) return false; - - Tile other = world.tile(link); - - if(!(liquids.current() == liquid || liquids.get(liquids.current()) < 0.2f)) return false; + return + hasLiquids && team == source.team && + (liquids.current() == liquid || liquids.get(liquids.current()) < 0.2f) && + checkAccept(source, world.tile(link)); + } + protected boolean checkAccept(Building source, Tile other){ if(linked(source)) return true; if(linkValid(tile, other)){ - int rel = relativeTo(other.x, other.y); + int rel = relativeTo(other); int rel2 = relativeTo(Edges.getFacingEdge(source, this)); return rel != rel2; @@ -440,10 +430,8 @@ public class ItemBridge extends Block{ Tile edge = Edges.getFacingEdge(to.tile, tile); int i = relativeTo(edge.x, edge.y); - IntSetIterator it = incoming.iterator(); - - while(it.hasNext){ - int v = it.next(); + for(int j = 0; j < incoming.size; j++){ + int v = incoming.items[j]; if(relativeTo(Point2.x(v), Point2.y(v)) == i){ return false; } @@ -469,7 +457,7 @@ public class ItemBridge extends Block{ @Override public byte version(){ - return 1; //TODO write cycleSpeed, 1 + return 1; } @Override @@ -479,10 +467,8 @@ public class ItemBridge extends Block{ write.f(warmup); write.b(incoming.size); - IntSetIterator it = incoming.iterator(); - - while(it.hasNext){ - write.i(it.next()); + for(int i = 0; i < incoming.size; i++){ + write.i(incoming.items[i]); } write.bool(wasMoved || moved); diff --git a/core/src/mindustry/world/blocks/liquid/LiquidBridge.java b/core/src/mindustry/world/blocks/liquid/LiquidBridge.java index 4214a1cee9..c58a60c36c 100644 --- a/core/src/mindustry/world/blocks/liquid/LiquidBridge.java +++ b/core/src/mindustry/world/blocks/liquid/LiquidBridge.java @@ -1,7 +1,6 @@ package mindustry.world.blocks.liquid; import mindustry.gen.*; -import mindustry.type.*; import mindustry.world.blocks.distribution.*; import mindustry.world.meta.*; @@ -20,7 +19,7 @@ public class LiquidBridge extends ItemBridge{ @Override public void updateTransport(Building other){ - if(warmup >= 0.5f){ + if(warmup >= 0.25f){ moved |= moveLiquid(other, liquids.current()) > 0.05f; } } @@ -29,10 +28,5 @@ public class LiquidBridge extends ItemBridge{ public void doDump(){ dumpLiquid(liquids.current(), 1f); } - - @Override - public boolean acceptItem(Building source, Item item){ - return false; - } } } diff --git a/gradle.properties b/gradle.properties index 097aaec115..6df565d95f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,4 +10,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=c066b6a3db27ce21fa4d07c28c0d70b86a87cd55 +archash=d7b814ff69853e3bc8fa0703d3b2829cbff65e9e From f3b6f0a29b91732f6983368cfdef4efeca4e7ce8 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 25 Jul 2021 20:17:18 -0400 Subject: [PATCH 021/130] Fixed #5647 --- core/src/mindustry/type/AmmoTypes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/type/AmmoTypes.java b/core/src/mindustry/type/AmmoTypes.java index 491167ab1e..fb50fcaa17 100644 --- a/core/src/mindustry/type/AmmoTypes.java +++ b/core/src/mindustry/type/AmmoTypes.java @@ -44,7 +44,7 @@ public class AmmoTypes implements ContentList{ public void resupply(Unit unit){ float range = unit.hitSize + this.range; - Building build = Units.closestBuilding(unit.team, unit.x, unit.y, range, u -> u.block.hasPower && u.block.consumes.getPower().buffered); + Building build = Units.closestBuilding(unit.team, unit.x, unit.y, range, u -> u.block.consumes.hasPower() && u.block.consumes.getPower().buffered); if(build != null){ float amount = build.power.status * build.block.consumes.getPower().capacity; From aab79a90fb675176665ed4eec637dbd2fc6fcfbb Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 25 Jul 2021 20:55:59 -0400 Subject: [PATCH 022/130] Fixed #5648 --- core/src/mindustry/content/UnitTypes.java | 1 + .../entities/abilities/EnergyFieldAbility.java | 10 ++++++++-- core/src/mindustry/type/UnitType.java | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index cfc3434ac4..19498a5086 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -2055,6 +2055,7 @@ public class UnitTypes implements ContentList{ rotateSpeed = 1.4f; rotateShooting = false; ammoType = AmmoTypes.powerHigh; + ammoCapacity = 40; //clip size is massive due to energy field clipSize = 250f; diff --git a/core/src/mindustry/entities/abilities/EnergyFieldAbility.java b/core/src/mindustry/entities/abilities/EnergyFieldAbility.java index 8681e37843..5e5acce3bc 100644 --- a/core/src/mindustry/entities/abilities/EnergyFieldAbility.java +++ b/core/src/mindustry/entities/abilities/EnergyFieldAbility.java @@ -14,6 +14,8 @@ import mindustry.gen.*; import mindustry.graphics.*; import mindustry.type.*; +import static mindustry.Vars.*; + public class EnergyFieldAbility extends Ability{ private static final Seq all = new Seq<>(); @@ -31,6 +33,7 @@ public class EnergyFieldAbility extends Ability{ public float effectRadius = 5f, sectorRad = 0.14f, rotateSpeed = 0.5f; public int sectors = 5; public Color color = Pal.heal; + public boolean useAmmo = true; protected float timer, curStroke; protected boolean anyNearby = false; @@ -88,8 +91,7 @@ public class EnergyFieldAbility extends Ability{ curStroke = Mathf.lerpDelta(curStroke, anyNearby ? 1 : 0, 0.09f); - if((timer += Time.delta) >= reload){ - + if((timer += Time.delta) >= reload && (!useAmmo || unit.ammo > 0 || !state.rules.unitAmmo)){ Tmp.v1.trns(unit.rotation - 90, x, y).add(unit.x, unit.y); float rx = Tmp.v1.x, ry = Tmp.v1.y; anyNearby = false; @@ -143,6 +145,10 @@ public class EnergyFieldAbility extends Ability{ if(anyNearby){ shootSound.at(unit); + + if(useAmmo && state.rules.unitAmmo){ + unit.ammo --; + } } timer = 0f; diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index de2f9f3215..cd095d0acc 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -384,9 +384,9 @@ public class UnitType extends UnlockableContent{ //dynamically create ammo capacity based on firing rate if(ammoCapacity < 0){ - float shotsPerSecond = weapons.sumf(w -> 60f / w.reload); + float shotsPerSecond = weapons.sumf(w -> w.useAmmo ? 60f / w.reload : 0f); //duration of continuous fire without reload - float targetSeconds = 30; + float targetSeconds = 35; ammoCapacity = Math.max(1, (int)(shotsPerSecond * targetSeconds)); } From c19a7e8452618043d7adf02680f7da095ca04d6b Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 26 Jul 2021 19:29:14 -0400 Subject: [PATCH 023/130] New core landing animation --- .../storage/core-foundation-thruster1.png | Bin 0 -> 874 bytes .../storage/core-foundation-thruster2.png | Bin 0 -> 871 bytes .../blocks/storage/core-nucleus-thruster1.png | Bin 0 -> 1251 bytes .../blocks/storage/core-nucleus-thruster2.png | Bin 0 -> 1264 bytes .../blocks/storage/core-shard-thruster1.png | Bin 0 -> 528 bytes .../blocks/storage/core-shard-thruster2.png | Bin 0 -> 512 bytes core/assets-raw/sprites/effects/landheat.png | Bin 0 -> 24599 bytes core/assets/icons/icons.properties | 1 + core/assets/logicids.dat | Bin 2669 -> 2653 bytes core/assets/sprites/clouds.png | Bin 9675 -> 116329 bytes core/src/mindustry/Vars.java | 4 + core/src/mindustry/content/Blocks.java | 2 + core/src/mindustry/content/Fx.java | 12 +- core/src/mindustry/content/Planets.java | 2 + core/src/mindustry/content/UnitTypes.java | 8 +- core/src/mindustry/core/Control.java | 14 +- core/src/mindustry/core/Renderer.java | 158 ++++++++++++++---- core/src/mindustry/core/World.java | 1 + .../entities/units/AIController.java | 2 + core/src/mindustry/game/Rules.java | 2 + core/src/mindustry/type/Planet.java | 2 + .../world/blocks/storage/CoreBlock.java | 34 ++++ gradle.properties | 2 +- 23 files changed, 201 insertions(+), 43 deletions(-) create mode 100644 core/assets-raw/sprites/blocks/storage/core-foundation-thruster1.png create mode 100644 core/assets-raw/sprites/blocks/storage/core-foundation-thruster2.png create mode 100644 core/assets-raw/sprites/blocks/storage/core-nucleus-thruster1.png create mode 100644 core/assets-raw/sprites/blocks/storage/core-nucleus-thruster2.png create mode 100644 core/assets-raw/sprites/blocks/storage/core-shard-thruster1.png create mode 100644 core/assets-raw/sprites/blocks/storage/core-shard-thruster2.png create mode 100644 core/assets-raw/sprites/effects/landheat.png diff --git a/core/assets-raw/sprites/blocks/storage/core-foundation-thruster1.png b/core/assets-raw/sprites/blocks/storage/core-foundation-thruster1.png new file mode 100644 index 0000000000000000000000000000000000000000..f40a7eb905e8a2a5116776c8fcf0c0e1b37c9ed7 GIT binary patch literal 874 zcmeAS@N?(olHy`uVBq!ia0y~yU^v0Rz>vkk#=yYvvq!F)fq{XsILO_JVcj{ImkbQd zDxNNmAr*7p-nI3Uc9dv%s2|AZ=;-M9Gj%5z-h zdLpX+Ui|wrzbdsZ+?vL{U#h=6-HeF=3@ohgPpf0TaP@xucKKSl`ucL~U!QdaR$Vaf zJ9fikUw@_1oI@8Zl$7M=ZEKz{oyfAVAogc<`{ z3=Q98cQ3wZE>tWaR=&!jO@O2OmGtqnV%rxt0+<#``7-1xo)L6!aaeJrjv@a4eC@uD z4*AV{jeMR2Fci04G-wLg66`YJqp|+coAY;k?|ky;m67ec^tiC}?bR>8>_{%;Q50BJ zpfkzxQHKDBwn4azAk#vj_GgO4#{?Axv^Io*_yyh|4%fC48NqW)f)~8mb6oRrhe1=o z#NgwCiUJ;-EstViVz>2)ypv?W7rlg~SqJRenix5*|3rJo1{r=cJ8UkUu-AhhS-OH5t^_J4hs++q%E6izC z6MF5K-~>{Kq($MO4M+OI$ocoyn7*vCJHm13)y;40d>h{K%Ou>EpE1(`s`Om*hK@J? z6wdeGKL5K}=PU=*B?26)Q*XrOmK+7Pl s&q%G0LzzSLrS&8q%b)DvB+YQ{M7@**!<9>KY&k#zp00i_>zopr0QT5v>i_@% literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/blocks/storage/core-foundation-thruster2.png b/core/assets-raw/sprites/blocks/storage/core-foundation-thruster2.png new file mode 100644 index 0000000000000000000000000000000000000000..21bb44abc9d9424e0302bde0796f6a17b59fbac8 GIT binary patch literal 871 zcmeAS@N?(olHy`uVBq!ia0y~yU^v0Rz>vkk#=yYvvq!F)fq{XsILO_JVcj{ImkbQd zik>cxAr*7p-rbukZ79+3P~WjFV4+j1mT%$`kBM57CFBk&v&>YP+AY$yJmBe}R_^?V zA>tCJI(OAiTK;^c&Wqz(f0`D(P*!FDgND_gHNQ(YtgHK9S@r(&5Bd9fZvSh!TeQCP zE;clqbUt|=kGF)ByUUTccmFbh;>r zB>M0yzx62NOYaexmN(P7k~tbDgxz|di)nrK>&vsK$?IM#x(S4x-)3LXmRtXT=k~t? zXCM|fIy99EY;}T2@EuKG<_C79{$j9W#v{1@<|4Aul1(Ed4w~wW5&)u8<(u2imqgRKE zf{1Rp3e&<0OJzZh&=aDa4lC}>naI(iwP)`hwfFP2g&G6)co&*H>o~H1)`Y7|voG&H zW+<-A;c9Je8Q@%sW+)3a zPKdql5wx#v|IAlQm6Vb;nX?7&{vul7b^F@V+V$@J0vxTgwI(SRx^T2`_4KA>$Otkm v6mnLUwB9esarK4t$tjcT!ReXdLDwHvAwTiYYj>6{28npO`njxgN@xNAuFGb? literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster1.png b/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster1.png new file mode 100644 index 0000000000000000000000000000000000000000..112429f26aa3a7d7aa5dc1f77080d66435370df5 GIT binary patch literal 1251 zcmeAS@N?(olHy`uVBq!ia0y~yVEDkmz_5gaje&t-rPtzO1_lPk;vjb?hIQv;UNSJS z%=L6}45^s&_O4;yZ3~Hpi}u|zN=L<_m&^+030mT@Rh_e_#nNfQjqKGGh~@FmT6&*a6*Vg@lMI?Ibvjxe=to>Za!xnq6pwcY&RyO00>`)}V0 zS4QWY?s6m7InwW!s3b9dess0NJk@v4!PB}LFb?M~I2e^Zz-q-*C^ZU>Dry6s1>6s`B4%phcw`<}^5J6L%{ z-$=fH5_N>BtvBj#LTPV9VggfJBc}wLT0-2O#m~RwDJFCjDvKG+>6O^n@X*Qgh=2cb zTfJ0K#=~bk1i2;FNvI|*!!@+A6#Z3FRIX5>f z3|Kp{{A~5~ZQ+6jA}juGwJi0?%3tzunn0si(CoVHJD$hxzPMdbBCW5_yuIP!A&-x4 z91`<-#qwJk6qSzkm^&Sq&}07eMTIg8k84#2h`V+=h!a`WW$tufLsULUeb`IGdmN01 z&*p{{J<8oGbll~DKd%HXO`}V1wTkHMoP7+HS>)zwiiU}vKdG8TqYI_xRR9Z1% z#j3Bu(M)Y#YdTp|1d)OVC9If*4MHwe*{ugZGJj;`N zt&*65PDPcC?!If@N3I=d($?E9^R_ZmR@vaplQ-fu+UM?A9@?o4il&ok_q``h^ZRhV zGvYu&n9%zax$MfSpkl6!h-Da)Dea_xI_;wS57vCCRLGCXO@!lV6FVq=4% zbG{(Agwa=#jSUMO^aZ(Rh_6oxe&1oIBxc}Z_2~WmdL6m)5>Q$d1f^UF-6U{An9a|_ z9n>Fj@9y4Mn{{6bPo1u3m_C2vEae=QHm0rakFFT5eA&v>=CoBQ?(;oRqLa?)t$4jF zlBun??@yxlfq;WSN2<^Biy4F%_3t?Pqz;r?Kpu2l`mQq@IW<9oDsyD#R`W}*7j0(jo+sz;+8@5|?u9p#1SQHY zylU5FJnZMC9B2K@jYFbrs&t{>9znAoZ5=B<+kBaRo`3x`yX>>Jg?XTuPmflb_sF+4 zOzY7ku(LEeE9COMnc8N~>F5VL{OYWZ{ytD*)DSJ?|Hy<|elS@7l)vD#VAT)7{c0c? MPgg&ebxsLQ08l|1*8l(j literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster2.png b/core/assets-raw/sprites/blocks/storage/core-nucleus-thruster2.png new file mode 100644 index 0000000000000000000000000000000000000000..83897e87d7ceaf22902a774e935e54252ee92140 GIT binary patch literal 1264 zcmeAS@N?(olHy`uVBq!ia0y~yVEDkmz_5gaje&t-rPtzO1_lPk;vjb?hIQv;UNSJS ztnzem45^s&_O4;yZ3~Hpi}t(SBN8?q71P{yO0!2Z$Y<(g7Ry62i5t~Drz*J`Ece*z z+9k5n^->R8U(!V-*Fcp&aj6HUxt~pslAGAWfCg4o7k=S%Sbwj+=Fh$_cV=H-u6OI@ zBb5c_D=XA(U21-CI^l`6TI&`8U&<*Gv=6cR6yqoIg@tjj3(!lVjE= zJ0lKkXuecYyp!$Ov#a~q^m@NvU0pvp z>(Bn1*06Aq=Dj&fi?#_Egc!+JM!SG)ewqFGo*=h`nOE%RdHNUju`?cKi++5T^Uozd zUZysut#0>B*T>$9b3G8S;M?_QR}5F~o!A!b#1iF^TXF5ttn#;R_uUd^SX$kaVQMp0 zJ}Rx4P+=CeN06zlL&EqT2cxsmy(xwk3PkXV&1n%~l}aMiW)98L+XjcQ^OTtT6H_yAInBRBz`ufJ|kV&Msmyu!yeUHIee za(>s}M!qaOGq3qXWr%KUNIZD=Z|29HaZ20N#9|8eJ~~z(mXfA=Kah`9Kl(k}xGid~GbCYM+!hn%e&EiY?2pg>%*qM0esMu?yXQK^ zgou^LJ6L%ntGXi&Ojx2qVE<14Y#`SJVo=0(O$ub dT9!1-{llQhcXaylfd5t?8BbR~mvv4FO#pffBhLT; literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/blocks/storage/core-shard-thruster1.png b/core/assets-raw/sprites/blocks/storage/core-shard-thruster1.png new file mode 100644 index 0000000000000000000000000000000000000000..7d6fd6160409611ee98a04bd5dfeae6a161f152e GIT binary patch literal 528 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 N44$rjF6*2UngGy}_45D# literal 0 HcmV?d00001 diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties index 069518fd38..51373139a6 100755 --- a/core/assets/icons/icons.properties +++ b/core/assets/icons/icons.properties @@ -352,3 +352,4 @@ 63354=payload-launch-pad|block-payload-launch-pad-ui 63353=silicon-arc-furnace|block-silicon-arc-furnace-ui 63352=metal-floor-4|block-metal-floor-4-ui +63351=invincible|status-invincible-ui diff --git a/core/assets/logicids.dat b/core/assets/logicids.dat index c34c5571b73c1e01591eadc39c3385019462c1f2..07a91ab4879c47b594200e990a51263bffd8707d 100644 GIT binary patch delta 16 XcmaDWa#w_jVa7(LFKnCH*wdK-G{gmD delta 31 ncmcaB@>Yb2Vdh4rFKm2#MXAN51qC^kx&`@}d7HnmWikT*yK)QH diff --git a/core/assets/sprites/clouds.png b/core/assets/sprites/clouds.png index 93a8684689803c7b35871e52903f40b554721e8f..adcf7a97db7ab0058d8d65eb6b9c61216c892b9f 100644 GIT binary patch literal 116329 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 GGywqMp({uL delta 9657 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 { + color(e.color, e.fout(0.1f)); + rand.setSeed(e.id); + Tmp.v1.trns(e.rotation, e.finpow() * 90f * rand.random(0.2f, 1f)); + Fill.circle(e.x + Tmp.v1.x, e.y + Tmp.v1.y, 8f * rand.random(0.6f, 1f) * e.fout(0.2f)); + }).layer(Layer.block + 1f), + unitShieldBreak = new Effect(35, e -> { if(!(e.data instanceof Unitc)) return; @@ -1955,8 +1962,5 @@ public class Fx{ } Lines.endLine(); - }).followParent(false), - - coreLand = new Effect(120f, e -> { - }); + }).followParent(false); } diff --git a/core/src/mindustry/content/Planets.java b/core/src/mindustry/content/Planets.java index 7134a6ef28..6e81501d15 100644 --- a/core/src/mindustry/content/Planets.java +++ b/core/src/mindustry/content/Planets.java @@ -2,6 +2,7 @@ package mindustry.content; import arc.graphics.*; import mindustry.ctype.*; +import mindustry.graphics.*; import mindustry.graphics.g3d.*; import mindustry.maps.planet.*; import mindustry.type.*; @@ -38,6 +39,7 @@ public class Planets implements ContentList{ atmosphereRadOut = 0.3f; startSector = 15; alwaysUnlocked = true; + landCloudColor = Pal.spore.cpy().a(0.5f); }}; } } diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 19498a5086..cf0593afc6 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -421,14 +421,14 @@ public class UnitTypes implements ContentList{ mechStepShake = 0.15f; ammoType = AmmoTypes.powerHigh; - speed = 0.39f; + speed = 0.4f; boostMultiplier = 2.2f; engineOffset = 12f; engineSize = 6f; lowAltitude = true; riseSpeed = 0.02f; - health = 7500f; + health = 8000f; armor = 9f; canBoost = true; landShake = 4f; @@ -453,8 +453,8 @@ public class UnitTypes implements ContentList{ cooldownTime = 200f; bullet = new ContinuousLaserBulletType(){{ - damage = 30f; - length = 175f; + damage = 32f; + length = 180f; hitEffect = Fx.hitMeltHeal; drawSize = 420f; lifetime = 160f; diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index a416b5d2fd..d5f6343190 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -36,7 +36,6 @@ import java.text.*; import java.util.*; import static arc.Core.*; -import static mindustry.Vars.net; import static mindustry.Vars.*; /** @@ -195,7 +194,7 @@ public class Control implements ApplicationListener, Loadable{ }); Events.run(Trigger.newGame, () -> { - Building core = player.bestCore(); + var core = player.bestCore(); if(core == null) return; @@ -203,6 +202,8 @@ public class Control implements ApplicationListener, Loadable{ player.set(core); if(showLandAnimation){ + //delay player respawn so animation can play. + player.deathTimer = -70f; //TODO this sounds pretty bad due to conflict if(settings.getInt("musicvol") > 0){ Musics.land.stop(); @@ -211,14 +212,14 @@ public class Control implements ApplicationListener, Loadable{ } app.post(() -> ui.hudfrag.showLand()); - renderer.zoomIn(Fx.coreLand.lifetime); - app.post(() -> Fx.coreLand.at(core.getX(), core.getY(), 0, core.block)); + renderer.showLaunch(); - Time.run(Fx.coreLand.lifetime, () -> { + Time.run(coreLandDuration, () -> { Fx.launch.at(core); Effect.shake(5f, 5f, core); + core.thrusterTime = 1f; - if(state.isCampaign()){ + if(state.isCampaign() && Vars.showSectorLandInfo){ ui.announce("[accent]" + state.rules.sector.name() + "\n" + (state.rules.sector.info.resources.any() ? "[lightgray]" + bundle.get("sectors.resources") + "[white] " + state.rules.sector.info.resources.toString(" ", u -> u.emoji()) : ""), 5); @@ -328,6 +329,7 @@ public class Control implements ApplicationListener, Loadable{ slot.load(); slot.setAutosave(true); state.rules.sector = sector; + state.rules.cloudColor = sector.planet.landCloudColor; //if there is no base, simulate a new game and place the right loadout at the spawn position if(state.rules.defaultTeam.cores().isEmpty() || hadNoCore){ diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java index 5183069725..efe7c3af48 100644 --- a/core/src/mindustry/core/Renderer.java +++ b/core/src/mindustry/core/Renderer.java @@ -18,6 +18,7 @@ import mindustry.game.EventType.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.graphics.g3d.*; +import mindustry.world.blocks.storage.*; import mindustry.world.blocks.storage.CoreBlock.*; import static arc.Core.*; @@ -27,6 +28,12 @@ public class Renderer implements ApplicationListener{ /** These are global variables, for headless access. Cached. */ public static float laserOpacity = 0.5f, bridgeOpacity = 0.75f; + private static final float cloudScaling = 1700f, cfinScl = -2f, cfinOffset = 0.3f, calphaFinOffset = 0.25f; + private static final float[] cloudAlphas = {0, 0.5f, 1f, 0.1f, 0, 0f}; + private static final float cloudAlpha = 0.81f; + private static final float[] thrusterSize = {0f, 0f, 0f, 0f, 0.3f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 0f}; + private static final Interp landInterp = Interp.pow3; + public final BlockRenderer blocks = new BlockRenderer(); public final MinimapRenderer minimap = new MinimapRenderer(); public final OverlayRenderer overlays = new OverlayRenderer(); @@ -44,7 +51,8 @@ public class Renderer implements ApplicationListener{ private @Nullable CoreBuild landCore; private Color clearColor = new Color(0f, 0f, 0f, 1f); - private float targetscale = Scl.scl(4), camerascale = targetscale, landscale, landTime, weatherAlpha, minZoomScl = Scl.scl(0.01f); + private float cloudSeed = 0f; + private float targetscale = Scl.scl(4), camerascale = targetscale, landscale, landTime, landPTimer, weatherAlpha, minZoomScl = Scl.scl(0.01f); private float shakeIntensity, shaketime; private Vec2 camShakeOffset = new Vec2(); @@ -97,10 +105,14 @@ public class Renderer implements ApplicationListener{ drawStatus = Core.settings.getBool("blockstatus"); if(landTime > 0){ + if(!state.isPaused()){ + updateLandParticles(); + } + if(!state.isPaused()){ landTime -= Time.delta; } - landscale = Interp.pow5In.apply(minZoomScl, Scl.scl(4f), 1f - landTime / Fx.coreLand.lifetime); + landscale = landInterp.apply(minZoomScl, Scl.scl(4f), 1f - landTime / coreLandDuration); camerascale = landscale; weatherAlpha = 0f; }else{ @@ -281,45 +293,134 @@ public class Renderer implements ApplicationListener{ } - private void drawLanding(){ - CoreBuild entity = landCore == null ? player.bestCore() : landCore; - //var clouds = assets.get("sprites/clouds.png", Texture.class); - if(landTime > 0 && entity != null){ - float fout = landTime / Fx.coreLand.lifetime; + void updateLandParticles(){ + float tsize = Mathf.sample(thrusterSize, (landTime + 35f) / coreLandDuration); - //TODO clouds - /* - float scaling = 10000f; - float sscl = 1f + fout*1.5f; - float offset = -0.38f; + landPTimer += tsize * Time.delta; + if(landCore != null && landPTimer >= 1f){ + landCore.tile.getLinkedTiles(t -> { + if(Mathf.chance(0.4f)){ + Fx.coreLandDust.at(t.worldx(), t.worldy(), landCore.angleTo(t) + Mathf.range(30f), Tmp.c1.set(t.floor().mapColor).mul(1.5f + Mathf.range(0.15f))); + } + }); - Tmp.tr1.set(clouds); - Tmp.tr1.set((camera.position.x - camera.width/2f * sscl) / scaling, (camera.position.y - camera.height/2f * sscl) / scaling, (camera.position.x + camera.width/2f * sscl) / scaling, (camera.position.y + camera.height/2f * sscl) / scaling); - Draw.alpha(Mathf.slope(Mathf.clamp(((1f - fout) + offset)/(1f + offset)))); - Draw.mixcol(Pal.spore, 0.5f); - Draw.rect(Tmp.tr1, camera.position.x, camera.position.y, camera.width, camera.height); - Draw.reset();*/ + landPTimer = 0f; + } + } - TextureRegion reg = entity.block.fullIcon; + void drawLanding(){ + CoreBuild build = landCore == null ? player.bestCore() : landCore; + var clouds = assets.get("sprites/clouds.png", Texture.class); + if(landTime > 0 && build != null){ + float fout = landTime / coreLandDuration; + float fin = 1f - fout; + + //core + var block = (CoreBlock)build.block; + TextureRegion reg = block.fullIcon; float scl = Scl.scl(4f) / camerascale; - float s = reg.width * Draw.scl * scl * 4f * fout; + float shake = 0f; + float s = reg.width * Draw.scl * scl * 3.6f * Interp.pow2Out.apply(fout); + float rotation = Interp.pow2In.apply(fout) * 135f, x = build.x + Mathf.range(shake), y = build.y + Mathf.range(shake); + float thrustOpen = 0.25f; + float frame = fin >= thrustOpen ? 1f : fin / thrustOpen; Draw.color(Pal.lightTrail); - Draw.rect("circle-shadow", entity.x, entity.y, s, s); + //TODO spikier heat + Draw.rect("circle-shadow", x, y, s, s); - Angles.randLenVectors(1, (1f- fout), 100, 1000f * scl * (1f-fout), (x, y, ffin, ffout) -> { - Lines.stroke(scl * ffin); - Lines.lineAngle(entity.x + x, entity.y + y, Mathf.angle(x, y), (ffin * 20 + 1f) * scl); + Draw.color(Pal.lightTrail); + + float pfin = Interp.pow3Out.apply(fin), pf = Interp.pow2In.apply(fout); + + //particles + Angles.randLenVectors(1, pfin, 100, 800f * scl * pfin, (ax, ay, ffin, ffout) -> { + Lines.stroke(scl * ffin * pf * 3f); + Lines.lineAngle(build.x + ax, build.y + ay, Mathf.angle(ax, ay), (ffin * 20 + 1f) * scl); }); Draw.color(); - Draw.mixcol(Color.white, fout); - Draw.rect(reg, entity.x, entity.y, reg.width * Draw.scl * scl, reg.height * Draw.scl * scl, fout * 135f); + Draw.mixcol(Color.white, Interp.pow2In.apply(fout)); + Draw.scl(scl); + + Draw.alpha(1f); + + //thruster flame + float strength = (1f + (block.size - 3)/2.5f) * scl * Mathf.sample(thrusterSize, fin) * (0.95f + Mathf.absin(2f, 0.1f)); + float offset = (block.size - 3) * 3f * scl; + + for(int i = 0; i < 4; i++){ + Tmp.v1.trns(i * 90 + rotation, 1f); + + Tmp.v1.setLength((block.size * tilesize/2f + 1f)*scl + strength*2f + offset); + Draw.color(build.team.color); + Fill.circle(Tmp.v1.x + x, Tmp.v1.y + y, 6f * strength); + + Tmp.v1.setLength((block.size * tilesize/2f + 1f)*scl + strength*0.5f + offset); + Draw.color(Color.white); + Fill.circle(Tmp.v1.x + x, Tmp.v1.y + y, 3f * strength); + } + + drawThrusters(block, x, y, rotation, frame); + + Drawf.spinSprite(block.region, x, y, rotation); + + Draw.alpha(Interp.pow4In.apply(frame)); + drawThrusters(block, x, y, rotation, frame); + Draw.alpha(1f); + + Drawf.spinSprite(block.teamRegions[build.team.id], x, y, rotation); + + Draw.scl(); Draw.reset(); + + //clouds + float scaling = cloudScaling; + float sscl = Math.max(1f + Mathf.clamp(fin + cfinOffset)* cfinScl, 0f) * landscale; + + Tmp.tr1.set(clouds); + Tmp.tr1.set( + (camera.position.x - camera.width/2f * sscl) / scaling, + (camera.position.y - camera.height/2f * sscl) / scaling, + (camera.position.x + camera.width/2f * sscl) / scaling, + (camera.position.y + camera.height/2f * sscl) / scaling); + + Tmp.tr1.scroll(10f * cloudSeed, 10f * cloudSeed); + + Draw.alpha(Mathf.sample(cloudAlphas, fin + calphaFinOffset) * cloudAlpha); + Draw.mixcol(state.rules.cloudColor, state.rules.cloudColor.a); + Draw.rect(Tmp.tr1, camera.position.x, camera.position.y, camera.width, camera.height); + Draw.reset(); } } + void drawThrusters(CoreBlock block, float x, float y, float rotation, float frame){ + float length = block.thrusterLength * (frame - 1f) - 1f/4f; + float alpha = Draw.getColor().a; + + //two passes for consistent lighting + for(int j = 0; j < 2; j++){ + for(int i = 0; i < 4; i++){ + var reg = i >= 2 ? block.thruster2 : block.thruster1; + float rot = (i * 90) + rotation % 90f; + Tmp.v1.trns(rot, length * Draw.xscl); + + //second pass applies extra layer of shading + if(j == 1){ + Tmp.v1.rotate(-90f); + Draw.alpha((rotation % 90f) / 90f * alpha); + rot -= 90f; + Draw.rect(reg, x + Tmp.v1.x, y + Tmp.v1.y, rot); + }else{ + Draw.alpha(alpha); + Draw.rect(reg, x + Tmp.v1.x, y + Tmp.v1.y, rot); + } + } + } + Draw.alpha(1f); + } + public void scaleCamera(float amount){ targetscale *= (amount / 4) + 1; clampScale(); @@ -350,9 +451,10 @@ public class Renderer implements ApplicationListener{ clampScale(); } - public void zoomIn(float duration){ + public void showLaunch(){ landscale = minZoomScl; - landTime = duration; + landTime = coreLandDuration; + cloudSeed = Mathf.random(1f); } public void takeMapScreenshot(){ diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java index e1363a281f..453ccb1c71 100644 --- a/core/src/mindustry/core/World.java +++ b/core/src/mindustry/core/World.java @@ -287,6 +287,7 @@ public class World{ if(liquid != null) content.add(liquid); } + state.rules.cloudColor = sector.planet.landCloudColor; sector.info.resources = content.asArray(); sector.info.resources.sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id))); sector.saveInfo(); diff --git a/core/src/mindustry/entities/units/AIController.java b/core/src/mindustry/entities/units/AIController.java index c1764052da..0af7565424 100644 --- a/core/src/mindustry/entities/units/AIController.java +++ b/core/src/mindustry/entities/units/AIController.java @@ -6,6 +6,7 @@ import arc.util.*; import mindustry.*; import mindustry.ai.*; import mindustry.entities.*; +import mindustry.game.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; @@ -154,6 +155,7 @@ public class AIController implements UnitController{ } protected Teamc targetFlag(float x, float y, BlockFlag flag, boolean enemy){ + if(unit.team == Team.derelict) return null; Tile target = Geometry.findClosest(x, y, enemy ? indexer.getEnemy(unit.team, flag) : indexer.getAllied(unit.team, flag)); return target == null ? null : target.build; } diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java index f66dd658ea..385d7671e9 100644 --- a/core/src/mindustry/game/Rules.java +++ b/core/src/mindustry/game/Rules.java @@ -109,6 +109,8 @@ public class Rules{ public Team defaultTeam = Team.sharded; /** team of the enemy in waves/sectors. */ public Team waveTeam = Team.crux; + /** color of clouds that is displayed when the player is landing */ + public Color cloudColor = new Color(0f, 0f, 0f, 0f); /** name of the custom mode that this ruleset describes, or null. */ public @Nullable String modeName; /** Whether cores incinerate items when full, just like in the campaign. */ diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index 0c52d3a701..06499d9ca0 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -55,6 +55,8 @@ public class Planet extends UnlockableContent{ public boolean bloom = false; /** Whether this planet is displayed. */ public boolean visible = true; + /** Tint of clouds displayed when landing. */ + public Color landCloudColor = new Color(1f, 1f, 1f, 0.5f); /** For suns, this is the color that shines on other planets. Does nothing for children. */ public Color lightColor = Color.white.cpy(); /** Atmosphere tint for landable planets. */ diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 8aa18cf014..8963e1fcd1 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -29,6 +29,10 @@ public class CoreBlock extends StorageBlock{ //hacky way to pass item modules between methods private static ItemModule nextItems; + public @Load("@-thruster1") TextureRegion thruster1; //top right + public @Load("@-thruster2") TextureRegion thruster2; //bot left + public float thrusterLength = 14f/4f; + public UnitType unitType = UnitTypes.alpha; public float captureInvicibility = 60f * 15f; @@ -176,6 +180,35 @@ public class CoreBlock extends StorageBlock{ public boolean noEffect = false; public Team lastDamage = Team.derelict; public float iframes = -1f; + public float thrusterTime = 0f; + + @Override + public void draw(){ + //draw thrusters when just landed + if(thrusterTime > 0){ + float frame = thrusterTime; + + Draw.alpha(1f); + drawThrusters(frame); + Draw.rect(block.region, x, y); + Draw.alpha(Interp.pow4In.apply(frame)); + drawThrusters(frame); + Draw.reset(); + + drawTeamTop(); + }else{ + super.draw(); + } + } + + public void drawThrusters(float frame){ + float length = thrusterLength * (frame - 1f) - 1f/4f; + for(int i = 0; i < 4; i++){ + var reg = i >= 2 ? thruster2 : thruster1; + float dx = Geometry.d4x[i] * length, dy = Geometry.d4y[i] * length; + Draw.rect(reg, x + dx, y + dy, i * 90); + } + } @Override public void damage(@Nullable Team source, float damage){ @@ -234,6 +267,7 @@ public class CoreBlock extends StorageBlock{ @Override public void updateTile(){ iframes -= Time.delta; + thrusterTime -= Time.delta/90f; } @Override diff --git a/gradle.properties b/gradle.properties index 6df565d95f..1366866c20 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,4 +10,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=d7b814ff69853e3bc8fa0703d3b2829cbff65e9e +archash=6e9fd338866c05cd42ec20f26ec7fa7c3a25d6d5 From f5222674ff820fab215d3205c6eaad5fa5713e63 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 26 Jul 2021 19:54:22 -0400 Subject: [PATCH 024/130] Unused sprite cleanup --- core/assets-raw/sprites/effects/landheat.png | Bin 24599 -> 0 bytes core/src/mindustry/core/Renderer.java | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 core/assets-raw/sprites/effects/landheat.png diff --git a/core/assets-raw/sprites/effects/landheat.png b/core/assets-raw/sprites/effects/landheat.png deleted file mode 100644 index 762e7735e7110b9d420db469c0fb734988a23d43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24599 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 N44$rjF6*2UngGy}_45D# diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java index efe7c3af48..24a5c6bf07 100644 --- a/core/src/mindustry/core/Renderer.java +++ b/core/src/mindustry/core/Renderer.java @@ -358,7 +358,7 @@ public class Renderer implements ApplicationListener{ Tmp.v1.setLength((block.size * tilesize/2f + 1f)*scl + strength*0.5f + offset); Draw.color(Color.white); - Fill.circle(Tmp.v1.x + x, Tmp.v1.y + y, 3f * strength); + Fill.circle(Tmp.v1.x + x, Tmp.v1.y + y, 3.5f * strength); } drawThrusters(block, x, y, rotation, frame); From adbe55b0db881856ae0bc5a6a173e18d7cf1d2e1 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 27 Jul 2021 09:08:09 -0400 Subject: [PATCH 025/130] Minor cloud bugfixes / Removed flow rate option --- core/assets/bundles/bundle.properties | 1 - core/src/mindustry/core/Renderer.java | 30 ++++++++++--------- .../mindustry/entities/comp/BuildingComp.java | 2 +- .../ui/dialogs/SettingsMenuDialog.java | 2 -- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 303aae648f..099e1b7140 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -841,7 +841,6 @@ setting.blockreplace.name = Automatic Block Suggestions setting.linear.name = Linear Filtering setting.hints.name = Hints setting.logichints.name = Logic Hints -setting.flow.name = Display Resource Flow Rate setting.backgroundpause.name = Pause In Background setting.buildautopause.name = Auto-Pause Building setting.doubletapmine.name = Double-Tap to Mine diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java index 24a5c6bf07..b0ba92f5ae 100644 --- a/core/src/mindustry/core/Renderer.java +++ b/core/src/mindustry/core/Renderer.java @@ -375,23 +375,25 @@ public class Renderer implements ApplicationListener{ Draw.reset(); - //clouds - float scaling = cloudScaling; - float sscl = Math.max(1f + Mathf.clamp(fin + cfinOffset)* cfinScl, 0f) * landscale; + if(state.rules.cloudColor.a > 0.0001f){ + //clouds + float scaling = cloudScaling; + float sscl = Math.max(1f + Mathf.clamp(fin + cfinOffset)* cfinScl, 0f) * landscale; - Tmp.tr1.set(clouds); - Tmp.tr1.set( - (camera.position.x - camera.width/2f * sscl) / scaling, - (camera.position.y - camera.height/2f * sscl) / scaling, - (camera.position.x + camera.width/2f * sscl) / scaling, - (camera.position.y + camera.height/2f * sscl) / scaling); + Tmp.tr1.set(clouds); + Tmp.tr1.set( + (camera.position.x - camera.width/2f * sscl) / scaling, + (camera.position.y - camera.height/2f * sscl) / scaling, + (camera.position.x + camera.width/2f * sscl) / scaling, + (camera.position.y + camera.height/2f * sscl) / scaling); - Tmp.tr1.scroll(10f * cloudSeed, 10f * cloudSeed); + Tmp.tr1.scroll(10f * cloudSeed, 10f * cloudSeed); - Draw.alpha(Mathf.sample(cloudAlphas, fin + calphaFinOffset) * cloudAlpha); - Draw.mixcol(state.rules.cloudColor, state.rules.cloudColor.a); - Draw.rect(Tmp.tr1, camera.position.x, camera.position.y, camera.width, camera.height); - Draw.reset(); + Draw.alpha(Mathf.sample(cloudAlphas, fin + calphaFinOffset) * cloudAlpha); + Draw.mixcol(state.rules.cloudColor, state.rules.cloudColor.a); + Draw.rect(Tmp.tr1, camera.position.x, camera.position.y, camera.width, camera.height); + Draw.reset(); + } } } diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 47de632e6b..25e0114e23 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -1102,7 +1102,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, table.row(); table.table(this::displayConsumption).growX(); - boolean displayFlow = (block.category == Category.distribution || block.category == Category.liquid) && Core.settings.getBool("flow") && block.displayFlow; + boolean displayFlow = (block.category == Category.distribution || block.category == Category.liquid) && block.displayFlow; if(displayFlow){ String ps = " " + StatUnit.perSecond.localized(); diff --git a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java index 64333796cf..f15693634e 100644 --- a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -451,8 +451,6 @@ public class SettingsMenuDialog extends Dialog{ if(!mobile){ Core.settings.put("swapdiagonal", false); } - - graphics.checkPref("flow", true); } public void exportData(Fi file) throws IOException{ From 269c48b65b8d8301f68568a208abfe7c4efe7a92 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 27 Jul 2021 12:42:50 -0400 Subject: [PATCH 026/130] AmmoType refactoring --- core/src/mindustry/Vars.java | 2 + core/src/mindustry/content/UnitTypes.java | 65 +++++------ core/src/mindustry/core/ContentLoader.java | 1 - core/src/mindustry/core/Control.java | 4 +- core/src/mindustry/core/Renderer.java | 2 +- core/src/mindustry/ctype/ContentType.java | 2 +- core/src/mindustry/mod/ClassMap.java | 7 +- core/src/mindustry/mod/ContentParser.java | 21 ++-- core/src/mindustry/type/AmmoType.java | 27 +---- core/src/mindustry/type/AmmoTypes.java | 101 ------------------ core/src/mindustry/type/UnitType.java | 5 +- .../src/mindustry/type/ammo/ItemAmmoType.java | 57 ++++++++++ .../mindustry/type/ammo/PowerAmmoType.java | 58 ++++++++++ .../mindustry/ui/dialogs/PlanetDialog.java | 1 + .../mindustry/ui/fragments/HudFragment.java | 15 +-- gradle.properties | 2 +- 16 files changed, 176 insertions(+), 194 deletions(-) delete mode 100644 core/src/mindustry/type/AmmoTypes.java create mode 100644 core/src/mindustry/type/ammo/ItemAmmoType.java create mode 100644 core/src/mindustry/type/ammo/PowerAmmoType.java diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index 8a9f850a61..6343998991 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -146,6 +146,8 @@ public class Vars implements Loadable{ public static int maxTextureSize = 2048; /** Whether to show the core landing animation. */ public static boolean showLandAnimation = true; + /** Whether to show the campaign core launch animation. */ + public static boolean showLaunchAnimation = true; /** Whether to show sector info upon landing. */ public static boolean showSectorLandInfo = true; /** Whether to check for memory use before taking screenshots. */ diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index cf0593afc6..571f01f9ad 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -14,6 +14,7 @@ import mindustry.entities.effect.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.type.*; +import mindustry.type.ammo.*; import mindustry.type.weapons.*; import mindustry.world.meta.*; @@ -89,7 +90,7 @@ public class UnitTypes implements ContentList{ hitSize = 10f; health = 540; armor = 4f; - ammoType = AmmoTypes.coal; + ammoType = new ItemAmmoType(Items.coal); immunities.add(StatusEffects.burning); @@ -124,7 +125,7 @@ public class UnitTypes implements ContentList{ health = 900; armor = 9f; mechFrontSway = 0.55f; - ammoType = AmmoTypes.graphite; + ammoType = new ItemAmmoType(Items.graphite); weapons.add(new Weapon("artillery"){{ top = false; @@ -158,7 +159,7 @@ public class UnitTypes implements ContentList{ armor = 10f; canDrown = false; mechFrontSway = 1f; - ammoType = AmmoTypes.thorium; + ammoType = new ItemAmmoType(Items.thorium); mechStepParticles = true; mechStepShake = 0.15f; @@ -223,7 +224,7 @@ public class UnitTypes implements ContentList{ canDrown = false; mechFrontSway = 1.9f; mechSideSway = 0.6f; - ammoType = AmmoTypes.thorium; + ammoType = new ItemAmmoType(Items.thorium); weapons.add( new Weapon("reign-weapon"){{ @@ -286,7 +287,7 @@ public class UnitTypes implements ContentList{ commandLimit = 8; abilities.add(new RepairFieldAbility(10f, 60f * 4, 60f)); - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(1000); weapons.add(new Weapon("heal-weapon"){{ top = false; @@ -323,7 +324,7 @@ public class UnitTypes implements ContentList{ commandLimit = 9; abilities.add(new ShieldRegenFieldAbility(20f, 40f, 60f * 5, 60f)); - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(1300); weapons.add(new Weapon("heal-shotgun-weapon"){{ top = false; @@ -376,7 +377,7 @@ public class UnitTypes implements ContentList{ commandLimit = 10; mechFrontSway = 0.55f; - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(1500); speed = 0.4f; hitSize = 13f; @@ -419,7 +420,7 @@ public class UnitTypes implements ContentList{ mechStepParticles = true; mechStepShake = 0.15f; - ammoType = AmmoTypes.powerHigh; + ammoType = new PowerAmmoType(2500); speed = 0.4f; boostMultiplier = 2.2f; @@ -497,7 +498,7 @@ public class UnitTypes implements ContentList{ hovering = true; visualElevation = 0.2f; allowLegStep = true; - ammoType = AmmoTypes.powerHigh; + ammoType = new PowerAmmoType(4000); groundLayer = Layer.legUnit; speed = 0.3f; @@ -562,7 +563,7 @@ public class UnitTypes implements ContentList{ health = 200; mechSideSway = 0.25f; range = 40f; - ammoType = AmmoTypes.coal; + ammoType = new ItemAmmoType(Items.coal); weapons.add(new Weapon(){{ reload = 24f; @@ -600,7 +601,7 @@ public class UnitTypes implements ContentList{ legMoveSpace = 1.4f; hovering = true; armor = 3f; - ammoType = AmmoTypes.coal; + ammoType = new ItemAmmoType(Items.coal); allowLegStep = true; visualElevation = 0.2f; @@ -640,7 +641,7 @@ public class UnitTypes implements ContentList{ legBaseOffset = 2f; hovering = true; armor = 5f; - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(1000); buildSpeed = 0.75f; @@ -712,7 +713,7 @@ public class UnitTypes implements ContentList{ legLengthScl = 0.96f; rippleScale = 2f; legSpeed = 0.2f; - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(2000); buildSpeed = 1f; legSplashDamage = 32; @@ -816,7 +817,7 @@ public class UnitTypes implements ContentList{ legLengthScl = 0.93f; rippleScale = 3f; legSpeed = 0.19f; - ammoType = AmmoTypes.powerHigh; + ammoType = new ItemAmmoType(Items.graphite, 8); buildSpeed = 1f; legSplashDamage = 80; @@ -971,7 +972,7 @@ public class UnitTypes implements ContentList{ targetFlags = new BlockFlag[]{BlockFlag.factory, null}; commandLimit = 5; circleTarget = true; - ammoType = AmmoTypes.graphite; + ammoType = new ItemAmmoType(Items.graphite); weapons.add(new Weapon(){{ minShootVelocity = 0.75f; @@ -1010,7 +1011,7 @@ public class UnitTypes implements ContentList{ targetFlags = new BlockFlag[]{BlockFlag.launchPad, BlockFlag.storage, BlockFlag.battery, null}; engineOffset = 12f; engineSize = 3f; - ammoType = AmmoTypes.graphite; + ammoType = new ItemAmmoType(Items.graphite); weapons.add(new Weapon("zenith-missiles"){{ reload = 40f; @@ -1056,7 +1057,7 @@ public class UnitTypes implements ContentList{ engineSize = 5.3f; hitSize = 46f; targetFlags = new BlockFlag[]{BlockFlag.generator, BlockFlag.core, null}; - ammoType = AmmoTypes.thorium; + ammoType = new ItemAmmoType(Items.thorium); BulletType missiles = new MissileBulletType(2.7f, 14){{ width = 8f; @@ -1132,7 +1133,7 @@ public class UnitTypes implements ContentList{ destructibleWreck = false; armor = 13f; targetFlags = new BlockFlag[]{BlockFlag.reactor, BlockFlag.core, null}; - ammoType = AmmoTypes.thorium; + ammoType = new ItemAmmoType(Items.thorium); BulletType fragBullet = new FlakBulletType(4f, 5){{ shootEffect = Fx.shootBig; @@ -1212,7 +1213,7 @@ public class UnitTypes implements ContentList{ range = 50f; isCounted = false; - ammoType = AmmoTypes.powerLow; + ammoType = new PowerAmmoType(500); mineTier = 1; mineSpeed = 2.5f; @@ -1233,7 +1234,7 @@ public class UnitTypes implements ContentList{ hitSize = 9f; lowAltitude = true; - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(900); mineTier = 2; mineSpeed = 3.5f; @@ -1293,7 +1294,7 @@ public class UnitTypes implements ContentList{ buildSpeed = 2.6f; isCounted = false; - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(1100); weapons.add( new Weapon("heal-weapon-mount"){{ @@ -1347,7 +1348,7 @@ public class UnitTypes implements ContentList{ targetAir = false; targetFlags = new BlockFlag[]{BlockFlag.battery, BlockFlag.factory, null}; - ammoType = AmmoTypes.powerHigh; + ammoType = new PowerAmmoType(3000); weapons.add( new Weapon(){{ @@ -1485,7 +1486,7 @@ public class UnitTypes implements ContentList{ accel = 0.3f; rotateSpeed = 2.6f; rotateShooting = false; - ammoType = AmmoTypes.graphite; + ammoType = new ItemAmmoType(Items.graphite); trailLength = 20; trailX = 5.5f; @@ -1529,7 +1530,7 @@ public class UnitTypes implements ContentList{ hitSize = 20f; armor = 7f; rotateShooting = false; - ammoType = AmmoTypes.graphite; + ammoType = new ItemAmmoType(Items.graphite); trailLength = 22; trailX = 7f; @@ -1593,7 +1594,7 @@ public class UnitTypes implements ContentList{ inaccuracy = 5f; velocityRnd = 0.1f; shootSound = Sounds.missile; - ammoType = AmmoTypes.thorium; + ammoType = new ItemAmmoType(Items.thorium); ejectEffect = Fx.none; bullet = new MissileBulletType(2.7f, 12){{ @@ -1627,7 +1628,7 @@ public class UnitTypes implements ContentList{ accel = 0.2f; rotateSpeed = 1.3f; rotateShooting = false; - ammoType = AmmoTypes.thorium; + ammoType = new ItemAmmoType(Items.thorium); trailLength = 50; trailX = 18f; @@ -1713,7 +1714,7 @@ public class UnitTypes implements ContentList{ accel = 0.19f; rotateSpeed = 0.9f; rotateShooting = false; - ammoType = AmmoTypes.powerHigh; + ammoType = new PowerAmmoType(4000); float spawnTime = 60f * 15f; @@ -1771,7 +1772,7 @@ public class UnitTypes implements ContentList{ trailScl = 1.3f; rotateShooting = false; range = 100f; - ammoType = AmmoTypes.power; + ammoType = new PowerAmmoType(900); armor = 3f; @@ -1849,7 +1850,7 @@ public class UnitTypes implements ContentList{ trailX = 5.5f; trailY = -4f; trailScl = 1.9f; - ammoType = AmmoTypes.coal; + ammoType = new ItemAmmoType(Items.coal); buildSpeed = 2f; @@ -1918,7 +1919,7 @@ public class UnitTypes implements ContentList{ hitSize = 20f; armor = 6f; rotateShooting = false; - ammoType = AmmoTypes.graphite; + ammoType = new ItemAmmoType(Items.graphite); trailLength = 23; trailX = 9f; @@ -2054,7 +2055,7 @@ public class UnitTypes implements ContentList{ accel = 0.2f; rotateSpeed = 1.4f; rotateShooting = false; - ammoType = AmmoTypes.powerHigh; + ammoType = new PowerAmmoType(3500); ammoCapacity = 40; //clip size is massive due to energy field @@ -2099,7 +2100,7 @@ public class UnitTypes implements ContentList{ accel = 0.2f; rotateSpeed = 1.1f; rotateShooting = false; - ammoType = AmmoTypes.powerHigh; + ammoType = new PowerAmmoType(4500); trailLength = 70; trailX = 23f; diff --git a/core/src/mindustry/core/ContentLoader.java b/core/src/mindustry/core/ContentLoader.java index e00fec3061..f74ae47f07 100644 --- a/core/src/mindustry/core/ContentLoader.java +++ b/core/src/mindustry/core/ContentLoader.java @@ -34,7 +34,6 @@ public class ContentLoader{ new StatusEffects(), new Liquids(), new Bullets(), - new AmmoTypes(), new UnitTypes(), new Blocks(), new Loadouts(), diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index d5f6343190..936fc15ea1 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -203,7 +203,7 @@ public class Control implements ApplicationListener, Loadable{ if(showLandAnimation){ //delay player respawn so animation can play. - player.deathTimer = -70f; + player.deathTimer = -80f; //TODO this sounds pretty bad due to conflict if(settings.getInt("musicvol") > 0){ Musics.land.stop(); @@ -212,7 +212,7 @@ public class Control implements ApplicationListener, Loadable{ } app.post(() -> ui.hudfrag.showLand()); - renderer.showLaunch(); + renderer.showLanding(); Time.run(coreLandDuration, () -> { Fx.launch.at(core); diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java index b0ba92f5ae..e728149e15 100644 --- a/core/src/mindustry/core/Renderer.java +++ b/core/src/mindustry/core/Renderer.java @@ -453,7 +453,7 @@ public class Renderer implements ApplicationListener{ clampScale(); } - public void showLaunch(){ + public void showLanding(){ landscale = minZoomScl; landTime = coreLandDuration; cloudSeed = Mathf.random(1f); diff --git a/core/src/mindustry/ctype/ContentType.java b/core/src/mindustry/ctype/ContentType.java index e62377628c..8dfffce5e3 100644 --- a/core/src/mindustry/ctype/ContentType.java +++ b/core/src/mindustry/ctype/ContentType.java @@ -16,7 +16,7 @@ public enum ContentType{ typeid_UNUSED, error, planet, - ammo; + ammo_UNUSED; public static final ContentType[] all = values(); } diff --git a/core/src/mindustry/mod/ClassMap.java b/core/src/mindustry/mod/ClassMap.java index 99c62e1d15..778bb894ad 100644 --- a/core/src/mindustry/mod/ClassMap.java +++ b/core/src/mindustry/mod/ClassMap.java @@ -1,6 +1,8 @@ package mindustry.mod; import arc.struct.*; +import mindustry.type.ammo.*; + /** Generated class. Maps simple class names to concrete classes. For use in JSON mods. */ @SuppressWarnings("deprecation") public class ClassMap{ @@ -52,9 +54,8 @@ public class ClassMap{ classes.put("Research", mindustry.game.Objectives.Research.class); classes.put("SectorComplete", mindustry.game.Objectives.SectorComplete.class); classes.put("AmmoType", mindustry.type.AmmoType.class); - classes.put("AmmoTypes", mindustry.type.AmmoTypes.class); - classes.put("ItemAmmoType", mindustry.type.AmmoTypes.ItemAmmoType.class); - classes.put("PowerAmmoType", mindustry.type.AmmoTypes.PowerAmmoType.class); + classes.put("ItemAmmoType", ItemAmmoType.class); + classes.put("PowerAmmoType", PowerAmmoType.class); classes.put("Category", mindustry.type.Category.class); classes.put("ErrorContent", mindustry.type.ErrorContent.class); classes.put("Item", mindustry.type.Item.class); diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java index 262249efa9..5c4d48cecd 100644 --- a/core/src/mindustry/mod/ContentParser.java +++ b/core/src/mindustry/mod/ContentParser.java @@ -29,7 +29,7 @@ import mindustry.gen.*; import mindustry.graphics.*; import mindustry.mod.Mods.*; import mindustry.type.*; -import mindustry.type.AmmoTypes.*; +import mindustry.type.ammo.*; import mindustry.type.weather.*; import mindustry.world.*; import mindustry.world.blocks.units.*; @@ -97,9 +97,12 @@ public class ContentParser{ return result; }); put(AmmoType.class, (type, data) -> { - if(data.isString()){ - return field(AmmoTypes.class, data); - } + //string -> item + //if liquid ammo support is added, this should scan for liquids as well + if(data.isString()) return find(ContentType.item, data.asString()); + //number -> power + if(data.isNumber()) return new PowerAmmoType(data.asFloat()); + var bc = resolve(data.getString("type", ""), ItemAmmoType.class); data.remove("type"); AmmoType result = make(bc); @@ -357,16 +360,6 @@ public class ContentParser{ if(!value.has("sector") || !value.get("sector").isNumber()) throw new RuntimeException("SectorPresets must have a sector number."); return new SectorPreset(name, locate(ContentType.planet, value.getString("planet", "serpulo")), value.getInt("sector")); - }, - ContentType.ammo, (TypeParser)(mod, name, value) -> { - if(value.isString()){ - return (AmmoType)field(AmmoTypes.class, value.asString()); - } - - AmmoType item = make(resolve(value.getString("type", null), ItemAmmoType.class)); - currentContent = item; - read(() -> readFields(item, value)); - return item; } ); diff --git a/core/src/mindustry/type/AmmoType.java b/core/src/mindustry/type/AmmoType.java index 45fd8e06bc..78e89fd0d4 100644 --- a/core/src/mindustry/type/AmmoType.java +++ b/core/src/mindustry/type/AmmoType.java @@ -1,29 +1,12 @@ package mindustry.type; import arc.graphics.*; -import mindustry.ctype.*; import mindustry.gen.*; -import mindustry.graphics.*; /** Type of ammo that a unit uses. */ -public class AmmoType extends Content{ - public String icon = Iconc.itemCopper + ""; - public Color color = Pal.ammo; - public Color barColor = Pal.ammo; - public float range = 85f; - - public AmmoType(char icon, Color color){ - this.icon = icon + ""; - this.color = color; - } - - public AmmoType(){ - } - - public void resupply(Unit unit){} - - @Override - public ContentType getContentType(){ - return ContentType.ammo; - } +public interface AmmoType{ + String icon(); + Color color(); + Color barColor(); + void resupply(Unit unit); } diff --git a/core/src/mindustry/type/AmmoTypes.java b/core/src/mindustry/type/AmmoTypes.java deleted file mode 100644 index fb50fcaa17..0000000000 --- a/core/src/mindustry/type/AmmoTypes.java +++ /dev/null @@ -1,101 +0,0 @@ -package mindustry.type; - -import mindustry.content.*; -import mindustry.ctype.*; -import mindustry.entities.*; -import mindustry.gen.*; -import mindustry.graphics.*; - -public class AmmoTypes implements ContentList{ - public static AmmoType - powerLow, - power, - powerHigh, - copper, - graphite, - coal, - thorium; - - @Override - public void load(){ - powerLow = new PowerAmmoType(500); - power = new PowerAmmoType(1000); - powerHigh = new PowerAmmoType(2000); - copper = new ItemAmmoType(Items.copper); - graphite = new ItemAmmoType(Items.graphite); - coal = new ItemAmmoType(Items.coal); - thorium = new ItemAmmoType(Items.thorium); - } - - public static class PowerAmmoType extends AmmoType{ - public float totalPower = 1000; - - public PowerAmmoType(){ - super(Iconc.power, Pal.powerLight); - barColor = color; - } - - public PowerAmmoType(float totalPower){ - this(); - this.totalPower = totalPower; - } - - @Override - public void resupply(Unit unit){ - float range = unit.hitSize + this.range; - - Building build = Units.closestBuilding(unit.team, unit.x, unit.y, range, u -> u.block.consumes.hasPower() && u.block.consumes.getPower().buffered); - - if(build != null){ - float amount = build.power.status * build.block.consumes.getPower().capacity; - float powerPerAmmo = totalPower / unit.type.ammoCapacity; - float ammoRequired = unit.type.ammoCapacity - unit.ammo; - float powerRequired = ammoRequired * powerPerAmmo; - float powerTaken = Math.min(amount, powerRequired); - - if(powerTaken > 1){ - build.power.status -= powerTaken / build.block.consumes.getPower().capacity; - unit.ammo += powerTaken / powerPerAmmo; - - Fx.itemTransfer.at(build.x, build.y, Math.max(powerTaken / 100f, 1f), Pal.power, unit); - } - } - } - } - - public static class ItemAmmoType extends AmmoType{ - public int ammoPerItem = 15; - public Item item; - - public ItemAmmoType(Item item){ - this.item = item; - this.color = item.color; - } - - public ItemAmmoType(){ - } - - @Override - public void resupply(Unit unit){ - //do not resupply when it would waste resources - if(unit.type.ammoCapacity - unit.ammo < ammoPerItem) return; - - float range = unit.hitSize + this.range; - - Building build = Units.closestBuilding(unit.team, unit.x, unit.y, range, u -> u.block.allowResupply && u.items.has(item)); - - if(build != null){ - Fx.itemTransfer.at(build.x, build.y, ammoPerItem / 2f, item.color, unit); - unit.ammo = Math.min(unit.ammo + ammoPerItem, unit.type.ammoCapacity); - build.items.remove(item, 1); - } - } - - @Override - public void load(){ - if(item != null){ - icon = item.emoji(); - } - } - } -} diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index cd095d0acc..5e1d44e367 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -24,6 +24,7 @@ import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.graphics.MultiPacker.*; +import mindustry.type.ammo.*; import mindustry.ui.*; import mindustry.world.*; import mindustry.world.blocks.environment.*; @@ -97,7 +98,7 @@ public class UnitType extends UnlockableContent{ public int itemCapacity = -1; public int ammoCapacity = -1; - public AmmoType ammoType = AmmoTypes.copper; + public AmmoType ammoType = new ItemAmmoType(Items.copper); public int mineTier = -1; public float buildSpeed = -1f, mineSpeed = 1f; public Sound mineSound = Sounds.minebeam; @@ -195,7 +196,7 @@ public class UnitType extends UnlockableContent{ bars.row(); if(state.rules.unitAmmo){ - bars.add(new Bar(ammoType.icon + " " + Core.bundle.get("stat.ammo"), ammoType.barColor, () -> unit.ammo / ammoCapacity)); + bars.add(new Bar(ammoType.icon() + " " + Core.bundle.get("stat.ammo"), ammoType.barColor(), () -> unit.ammo / ammoCapacity)); bars.row(); } diff --git a/core/src/mindustry/type/ammo/ItemAmmoType.java b/core/src/mindustry/type/ammo/ItemAmmoType.java new file mode 100644 index 0000000000..6263209e75 --- /dev/null +++ b/core/src/mindustry/type/ammo/ItemAmmoType.java @@ -0,0 +1,57 @@ +package mindustry.type.ammo; + +import arc.graphics.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.type.*; + +public class ItemAmmoType implements AmmoType{ + public float range = 85f; + public int ammoPerItem = 15; + public Item item; + + public ItemAmmoType(Item item){ + this.item = item; + } + + public ItemAmmoType(Item item, int ammoPerItem){ + this.item = item; + this.ammoPerItem = ammoPerItem; + } + + public ItemAmmoType(){ + } + + @Override + public String icon(){ + return item.emoji(); + } + + @Override + public Color color(){ + return item.color; + } + + @Override + public Color barColor(){ + return Pal.ammo; + } + + @Override + public void resupply(Unit unit){ + //do not resupply when it would waste resources + if(unit.type.ammoCapacity - unit.ammo < ammoPerItem) return; + + float range = unit.hitSize + this.range; + + Building build = Units.closestBuilding(unit.team, unit.x, unit.y, range, u -> u.block.allowResupply && u.items.has(item)); + + if(build != null){ + Fx.itemTransfer.at(build.x, build.y, ammoPerItem / 2f, item.color, unit); + unit.ammo = Math.min(unit.ammo + ammoPerItem, unit.type.ammoCapacity); + build.items.remove(item, 1); + } + } +} diff --git a/core/src/mindustry/type/ammo/PowerAmmoType.java b/core/src/mindustry/type/ammo/PowerAmmoType.java new file mode 100644 index 0000000000..49d0b4dbb5 --- /dev/null +++ b/core/src/mindustry/type/ammo/PowerAmmoType.java @@ -0,0 +1,58 @@ +package mindustry.type.ammo; + +import arc.graphics.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.type.*; + +public class PowerAmmoType implements AmmoType{ + public float range = 85f; + public float totalPower = 1000; + + public PowerAmmoType(float totalPower){ + this.totalPower = totalPower; + } + + public PowerAmmoType(){ + + } + + @Override + public String icon(){ + return Iconc.power + ""; + } + + @Override + public Color color(){ + return Pal.powerLight; + } + + @Override + public Color barColor(){ + return Pal.powerLight; + } + + @Override + public void resupply(Unit unit){ + float range = unit.hitSize + this.range; + + Building build = Units.closestBuilding(unit.team, unit.x, unit.y, range, u -> u.block.consumes.hasPower() && u.block.consumes.getPower().buffered); + + if(build != null){ + float amount = build.power.status * build.block.consumes.getPower().capacity; + float powerPerAmmo = totalPower / unit.type.ammoCapacity; + float ammoRequired = unit.type.ammoCapacity - unit.ammo; + float powerRequired = ammoRequired * powerPerAmmo; + float powerTaken = Math.min(amount, powerRequired); + + if(powerTaken > 1){ + build.power.status -= powerTaken / build.block.consumes.getPower().capacity; + unit.ammo += powerTaken / powerPerAmmo; + + Fx.itemTransfer.at(build.x, build.y, Math.max(powerTaken / 100f, 1f), Pal.power, unit); + } + } + } +} diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 00f29b0a39..229bc9aa9b 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -921,6 +921,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ zoom = 0.5f; ui.hudfrag.showLaunchDirect(); + //TODO animation; 140 is fine Time.runTask(launchDuration, () -> control.playSector(from, sector)); }); } diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java index 9b857b1ce2..49b262aaa0 100644 --- a/core/src/mindustry/ui/fragments/HudFragment.java +++ b/core/src/mindustry/ui/fragments/HudFragment.java @@ -553,19 +553,6 @@ public class HudFragment extends Fragment{ Core.scene.add(image); } - public void showLaunch(){ - Image image = new Image(); - image.color.a = 0f; - image.setFillParent(true); - image.actions(Actions.fadeIn(40f / 60f)); - image.update(() -> { - if(state.isMenu()){ - image.remove(); - } - }); - Core.scene.add(image); - } - public void showLand(){ Image image = new Image(); image.color.a = 1f; @@ -726,7 +713,7 @@ public class HudFragment extends Fragment{ t.add(new SideBar(() -> player.unit().healthf(), () -> true, true)).width(bw).growY().padRight(pad); t.image(() -> player.icon()).scaling(Scaling.bounded).grow().maxWidth(54f); t.add(new SideBar(() -> player.dead() ? 0f : player.displayAmmo() ? player.unit().ammof() : player.unit().healthf(), () -> !player.displayAmmo(), false)).width(bw).growY().padLeft(pad).update(b -> { - b.color.set(player.displayAmmo() ? player.dead() || player.unit() instanceof BlockUnitc ? Pal.ammo : player.unit().type.ammoType.color : Pal.health); + b.color.set(player.displayAmmo() ? player.dead() || player.unit() instanceof BlockUnitc ? Pal.ammo : player.unit().type.ammoType.color() : Pal.health); }); t.getChildren().get(1).toFront(); diff --git a/gradle.properties b/gradle.properties index 1366866c20..b48fdbacb0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,4 +10,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=6e9fd338866c05cd42ec20f26ec7fa7c3a25d6d5 +archash=a9dedf9345fe888e54ab2be3c56bf8d4d2aeb2b8 From 00e3a59463f41bdce5b12cf5b4715a253f7af306 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 27 Jul 2021 16:26:13 -0400 Subject: [PATCH 027/130] Land animation progress / IntelliJ android plugin hack --- core/assets/scripts/global.js | 1 + core/src/mindustry/core/Renderer.java | 60 +++++++++++++------ core/src/mindustry/input/DesktopInput.java | 3 +- core/src/mindustry/input/MobileInput.java | 4 +- core/src/mindustry/mod/ClassMap.java | 6 +- core/src/mindustry/type/Weather.java | 6 +- .../mindustry/ui/dialogs/PlanetDialog.java | 5 +- settings.gradle | 6 +- .../mindustry/tools/ScriptMainGenerator.java | 1 + 9 files changed, 61 insertions(+), 31 deletions(-) diff --git a/core/assets/scripts/global.js b/core/assets/scripts/global.js index bb17455eac..4f81328cce 100755 --- a/core/assets/scripts/global.js +++ b/core/assets/scripts/global.js @@ -107,6 +107,7 @@ importPackage(Packages.mindustry.maps.planet) importPackage(Packages.mindustry.net) importPackage(Packages.mindustry.service) importPackage(Packages.mindustry.type) +importPackage(Packages.mindustry.type.ammo) importPackage(Packages.mindustry.type.weapons) importPackage(Packages.mindustry.type.weather) importPackage(Packages.mindustry.ui) diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java index e728149e15..32d93fe5dc 100644 --- a/core/src/mindustry/core/Renderer.java +++ b/core/src/mindustry/core/Renderer.java @@ -44,6 +44,7 @@ public class Renderer implements ApplicationListener{ public @Nullable Bloom bloom; public FrameBuffer effectBuffer = new FrameBuffer(); public boolean animateShields, drawWeather = true, drawStatus; + public float weatherAlpha; /** minZoom = zooming out, maxZoom = zooming in */ public float minZoom = 1.5f, maxZoom = 6f; public Seq envRenderers = new Seq<>(); @@ -51,9 +52,25 @@ public class Renderer implements ApplicationListener{ private @Nullable CoreBuild landCore; private Color clearColor = new Color(0f, 0f, 0f, 1f); - private float cloudSeed = 0f; - private float targetscale = Scl.scl(4), camerascale = targetscale, landscale, landTime, landPTimer, weatherAlpha, minZoomScl = Scl.scl(0.01f); - private float shakeIntensity, shaketime; + private float + //seed for cloud visuals, 0-1 + cloudSeed = 0f, + //target camera scale that is lerp-ed to + targetscale = Scl.scl(4), + //current actual camera scale + camerascale = targetscale, + //minimum camera zoom value for landing/launching; constant TODO make larger? + minZoomScl = Scl.scl(0.02f), + //starts at coreLandDuration, ends at 0. if positive, core is landing. + landTime, + //timer for core landing particles + landPTimer, + //intensity for screen shake + shakeIntensity, + //current duration of screen shake + shakeTime; + //for landTime > 0: if true, core is currently *launching*, otherwise landing. + private boolean isLaunching; private Vec2 camShakeOffset = new Vec2(); public Renderer(){ @@ -63,7 +80,7 @@ public class Renderer implements ApplicationListener{ public void shake(float intensity, float duration){ shakeIntensity = Math.max(shakeIntensity, intensity); - shaketime = Math.max(shaketime, duration); + shakeTime = Math.max(shakeTime, duration); } public void addEnvRenderer(int mask, Runnable render){ @@ -112,9 +129,13 @@ public class Renderer implements ApplicationListener{ if(!state.isPaused()){ landTime -= Time.delta; } - landscale = landInterp.apply(minZoomScl, Scl.scl(4f), 1f - landTime / coreLandDuration); - camerascale = landscale; + camerascale = landInterp.apply(minZoomScl, Scl.scl(4f), 1f - landTime / coreLandDuration); weatherAlpha = 0f; + + //snap camera to cutscene core regardless of player input + if(landCore != null){ + camera.position.set(landCore); + } }else{ weatherAlpha = Mathf.lerpDelta(weatherAlpha, 1f, 0.08f); } @@ -126,12 +147,12 @@ public class Renderer implements ApplicationListener{ landTime = 0f; graphics.clear(Color.black); }else{ - if(shaketime > 0){ + if(shakeTime > 0){ float intensity = shakeIntensity * (settings.getInt("screenshake", 4) / 4f) * 0.75f; camShakeOffset.setToRandomDirection().scl(Mathf.random(intensity)); camera.position.add(camShakeOffset); shakeIntensity -= 0.25f * Time.delta; - shaketime -= Time.delta; + shakeTime -= Time.delta; shakeIntensity = Mathf.clamp(shakeIntensity, 0f, 100f); }else{ camShakeOffset.setZero(); @@ -148,16 +169,13 @@ public class Renderer implements ApplicationListener{ } } - public boolean isLanding(){ + /** @return whether a launch/land cutscene is playing. */ + public boolean isCutscene(){ return landTime > 0; } - public float weatherAlpha(){ - return weatherAlpha; - } - public float landScale(){ - return landTime > 0 ? landscale : 1f; + return landTime > 0 ? camerascale : 1f; } @Override @@ -290,7 +308,7 @@ public class Renderer implements ApplicationListener{ } private void drawBackground(){ - + //nothing to draw currently } void updateLandParticles(){ @@ -378,7 +396,7 @@ public class Renderer implements ApplicationListener{ if(state.rules.cloudColor.a > 0.0001f){ //clouds float scaling = cloudScaling; - float sscl = Math.max(1f + Mathf.clamp(fin + cfinOffset)* cfinScl, 0f) * landscale; + float sscl = Math.max(1f + Mathf.clamp(fin + cfinOffset)* cfinScl, 0f) * camerascale; Tmp.tr1.set(clouds); Tmp.tr1.set( @@ -454,11 +472,19 @@ public class Renderer implements ApplicationListener{ } public void showLanding(){ - landscale = minZoomScl; + isLaunching = false; + camerascale = minZoomScl; landTime = coreLandDuration; cloudSeed = Mathf.random(1f); } + public void showLaunch(){ + isLaunching = true; + landCore = player.team().core(); + cloudSeed = Mathf.random(1f); + //TODO other stuff. + } + public void takeMapScreenshot(){ int w = world.width() * tilesize, h = world.height() * tilesize; int memory = w * h * 4 / 1024 / 1024; diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java index 6506db2d34..11f37f34dc 100644 --- a/core/src/mindustry/input/DesktopInput.java +++ b/core/src/mindustry/input/DesktopInput.java @@ -204,7 +204,6 @@ public class DesktopInput extends InputHandler{ panning = false; } - //TODO awful UI state checking code if(((player.dead() || state.isPaused()) && !ui.chatfrag.shown()) && !scene.hasField() && !scene.hasDialog()){ if(input.keyDown(Binding.mouse_move)){ panCam = true; @@ -237,7 +236,7 @@ public class DesktopInput extends InputHandler{ } } - if(!player.dead() && !state.isPaused() && !scene.hasField()){ + if(!player.dead() && !state.isPaused() && !scene.hasField() && !renderer.isCutscene()){ updateMovement(player.unit()); if(Core.input.keyTap(Binding.respawn)){ diff --git a/core/src/mindustry/input/MobileInput.java b/core/src/mindustry/input/MobileInput.java index c97e92455c..7429eddaaa 100644 --- a/core/src/mindustry/input/MobileInput.java +++ b/core/src/mindustry/input/MobileInput.java @@ -681,7 +681,7 @@ public class MobileInput extends InputHandler implements GestureListener{ } } - if(!player.dead() && !state.isPaused()){ + if(!player.dead() && !state.isPaused() && !renderer.isCutscene()){ updateMovement(player.unit()); } @@ -822,7 +822,7 @@ public class MobileInput extends InputHandler implements GestureListener{ shiftDeltaX %= tilesize; shiftDeltaY %= tilesize; } - }else if(!renderer.isLanding()){ + }else{ //pan player Core.camera.position.x -= deltaX; Core.camera.position.y -= deltaY; diff --git a/core/src/mindustry/mod/ClassMap.java b/core/src/mindustry/mod/ClassMap.java index 778bb894ad..9b7b017cf8 100644 --- a/core/src/mindustry/mod/ClassMap.java +++ b/core/src/mindustry/mod/ClassMap.java @@ -1,8 +1,6 @@ package mindustry.mod; import arc.struct.*; -import mindustry.type.ammo.*; - /** Generated class. Maps simple class names to concrete classes. For use in JSON mods. */ @SuppressWarnings("deprecation") public class ClassMap{ @@ -54,8 +52,6 @@ public class ClassMap{ classes.put("Research", mindustry.game.Objectives.Research.class); classes.put("SectorComplete", mindustry.game.Objectives.SectorComplete.class); classes.put("AmmoType", mindustry.type.AmmoType.class); - classes.put("ItemAmmoType", ItemAmmoType.class); - classes.put("PowerAmmoType", PowerAmmoType.class); classes.put("Category", mindustry.type.Category.class); classes.put("ErrorContent", mindustry.type.ErrorContent.class); classes.put("Item", mindustry.type.Item.class); @@ -75,6 +71,8 @@ public class ClassMap{ classes.put("Weapon", mindustry.type.Weapon.class); classes.put("Weather", mindustry.type.Weather.class); classes.put("WeatherEntry", mindustry.type.Weather.WeatherEntry.class); + classes.put("ItemAmmoType", mindustry.type.ammo.ItemAmmoType.class); + classes.put("PowerAmmoType", mindustry.type.ammo.PowerAmmoType.class); classes.put("PointDefenseWeapon", mindustry.type.weapons.PointDefenseWeapon.class); classes.put("RepairBeamWeapon", mindustry.type.weapons.RepairBeamWeapon.class); classes.put("HealBeamMount", mindustry.type.weapons.RepairBeamWeapon.HealBeamMount.class); diff --git a/core/src/mindustry/type/Weather.java b/core/src/mindustry/type/Weather.java index 86935bd8d1..0f62e423a4 100644 --- a/core/src/mindustry/type/Weather.java +++ b/core/src/mindustry/type/Weather.java @@ -342,15 +342,15 @@ public class Weather extends UnlockableContent{ @Override public void draw(){ - if(renderer.weatherAlpha() > 0.0001f && renderer.drawWeather && Core.settings.getBool("showweather")){ + if(renderer.weatherAlpha > 0.0001f && renderer.drawWeather && Core.settings.getBool("showweather")){ Draw.draw(Layer.weather, () -> { - Draw.alpha(renderer.weatherAlpha() * opacity * weather.opacityMultiplier); + Draw.alpha(renderer.weatherAlpha * opacity * weather.opacityMultiplier); weather.drawOver(self()); Draw.reset(); }); Draw.draw(Layer.debris, () -> { - Draw.alpha(renderer.weatherAlpha() * opacity * weather.opacityMultiplier); + Draw.alpha(renderer.weatherAlpha * opacity * weather.opacityMultiplier); weather.drawUnder(self()); Draw.reset(); }); diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 229bc9aa9b..946d1effc3 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -920,8 +920,9 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ launching = true; zoom = 0.5f; - ui.hudfrag.showLaunchDirect(); - //TODO animation; 140 is fine + //TODO + renderer.showLaunch(); + hide(); Time.runTask(launchDuration, () -> control.playSector(from, sector)); }); } diff --git a/settings.gradle b/settings.gradle index 76eaa676a6..7a19432101 100644 --- a/settings.gradle +++ b/settings.gradle @@ -22,7 +22,11 @@ if(new File(settingsDir, 'local.properties').exists()){ if(System.getenv("JITPACK") == "true") hasSdk = false if(hasSdk){ - include 'android' + //hack: pretend the Android module doesn't exist when imported through IntelliJ + //why? because IntelliJ chokes on the new version of the Android plugin + if(!System.getProperty("jna.tmpdir")?.contains("JetBrains")){ + include 'android' + } }else{ println("No Android SDK found. Skipping Android module.") } diff --git a/tools/src/mindustry/tools/ScriptMainGenerator.java b/tools/src/mindustry/tools/ScriptMainGenerator.java index 14ffde2b2b..42ffc6d797 100644 --- a/tools/src/mindustry/tools/ScriptMainGenerator.java +++ b/tools/src/mindustry/tools/ScriptMainGenerator.java @@ -80,6 +80,7 @@ public class ScriptMainGenerator{ "mindustry.ai.types", "mindustry.type.weather", "mindustry.type.weapons", + "mindustry.type.ammo", "mindustry.game.Objectives", "mindustry.world.blocks", "mindustry.world.draw", From 235fee091ed867dd7edaad8ab0161b60adc26565 Mon Sep 17 00:00:00 2001 From: Sunny Kim <58885089+sk7725@users.noreply.github.com> Date: Wed, 28 Jul 2021 06:08:29 +0900 Subject: [PATCH 028/130] keep v6 mod compatibility (#5655) --- core/src/mindustry/world/Block.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index 94732f338a..ee354135ac 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -793,6 +793,11 @@ public class Block extends UnlockableContent{ } clipSize = Math.max(clipSize, size * tilesize); + + //only kept to ensure compatibility with v6 mods. + if(expanded){ + clipSize += tilesize * 10f; + } if(emitLight){ clipSize = Math.max(clipSize, lightRadius * 2f); From 3d3e33912e5a2e1087946858ad6c6b5d9f9dd8d6 Mon Sep 17 00:00:00 2001 From: Volas171 <60143910+Volas171@users.noreply.github.com> Date: Tue, 27 Jul 2021 16:09:50 -0500 Subject: [PATCH 029/130] Mindustry Reborn CAMS (update servers_v7.json) (#5651) * CAMS * space --- servers_v7.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/servers_v7.json b/servers_v7.json index 9e6ad5f4ab..7d7c41026f 100644 --- a/servers_v7.json +++ b/servers_v7.json @@ -5,16 +5,12 @@ }, { "name": "C.A.M.S.", - "address": ["baseduser.eu.org:6569", "v7.thedimas.pp.ua"] + "address": ["baseduser.eu.org:6569", "v7.thedimas.pp.ua", "mindustry.me:7000"] }, { "name": "hexpvp.ml", "address": "hexpvp.ml" }, - { - "name": "[accent]Mindustry [red]Reborn", - "address": "mindustry.me:7000" - }, { "name": "Omega", "address": ["185.86.230.61:25571", "185.86.230.61:25570", "185.86.230.62:25572"] From 737fa4fa69f7c919b1d9ea089c3945770d2ab607 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 27 Jul 2021 17:43:12 -0400 Subject: [PATCH 030/130] WIP launch animation progress --- android/build.gradle | 2 +- core/src/mindustry/Vars.java | 2 - core/src/mindustry/core/Control.java | 2 +- core/src/mindustry/core/Renderer.java | 48 ++++++++++++------- .../mindustry/ui/dialogs/PlanetDialog.java | 4 +- .../mindustry/ui/fragments/HudFragment.java | 17 +++++-- .../ui/fragments/LoadingFragment.java | 4 ++ 7 files changed, 55 insertions(+), 24 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 5f355a0ec7..d073b66a15 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,6 +7,7 @@ buildscript{ } dependencies{ + //note that later versions, like alpha05, fail to work correctly classpath 'com.android.tools.build:gradle:7.1.0-alpha02' } } @@ -18,7 +19,6 @@ configurations{ natives } repositories{ mavenCentral() maven{ url "https://maven.google.com" } - jcenter() //remove later once google/JetBrains fixes the dependency } task deploy(type: Copy){ diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index 6343998991..f27fc0f77c 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -103,8 +103,6 @@ public class Vars implements Loadable{ public static final float invasionGracePeriod = 20; /** min armor fraction damage; e.g. 0.05 = at least 5% damage */ public static final float minArmorDamage = 0.1f; - /** launch animation duration */ - public static final float launchDuration = 140f; /** land animation duration */ public static final float coreLandDuration = 150f; /** size of tiles in units */ diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index 936fc15ea1..ff42a5e6c0 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -544,7 +544,7 @@ public class Control implements ApplicationListener, Loadable{ core.items.each((i, a) -> i.unlock()); } - if(Core.input.keyTap(Binding.pause) && !scene.hasDialog() && !scene.hasKeyboard() && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){ + if(Core.input.keyTap(Binding.pause) && !renderer.isCutscene() && !scene.hasDialog() && !scene.hasKeyboard() && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){ state.set(state.is(State.playing) ? State.paused : State.playing); } diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java index 32d93fe5dc..4d107c06ed 100644 --- a/core/src/mindustry/core/Renderer.java +++ b/core/src/mindustry/core/Renderer.java @@ -31,7 +31,7 @@ public class Renderer implements ApplicationListener{ private static final float cloudScaling = 1700f, cfinScl = -2f, cfinOffset = 0.3f, calphaFinOffset = 0.25f; private static final float[] cloudAlphas = {0, 0.5f, 1f, 0.1f, 0, 0f}; private static final float cloudAlpha = 0.81f; - private static final float[] thrusterSize = {0f, 0f, 0f, 0f, 0.3f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 0f}; + private static final float[] thrusterSizes = {0f, 0f, 0f, 0f, 0.3f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 0f}; private static final Interp landInterp = Interp.pow3; public final BlockRenderer blocks = new BlockRenderer(); @@ -70,7 +70,7 @@ public class Renderer implements ApplicationListener{ //current duration of screen shake shakeTime; //for landTime > 0: if true, core is currently *launching*, otherwise landing. - private boolean isLaunching; + private boolean launching; private Vec2 camShakeOffset = new Vec2(); public Renderer(){ @@ -129,7 +129,9 @@ public class Renderer implements ApplicationListener{ if(!state.isPaused()){ landTime -= Time.delta; } - camerascale = landInterp.apply(minZoomScl, Scl.scl(4f), 1f - landTime / coreLandDuration); + float fin = landTime / coreLandDuration; + if(!launching) fin = 1f - fin; + camerascale = landInterp.apply(minZoomScl, Scl.scl(4f), fin); weatherAlpha = 0f; //snap camera to cutscene core regardless of player input @@ -312,7 +314,8 @@ public class Renderer implements ApplicationListener{ } void updateLandParticles(){ - float tsize = Mathf.sample(thrusterSize, (landTime + 35f) / coreLandDuration); + float time = launching ? coreLandDuration - landTime : landTime; + float tsize = Mathf.sample(thrusterSizes, (time + 35f) / coreLandDuration); landPTimer += tsize * Time.delta; if(landCore != null && landPTimer >= 1f){ @@ -331,9 +334,12 @@ public class Renderer implements ApplicationListener{ var clouds = assets.get("sprites/clouds.png", Texture.class); if(landTime > 0 && build != null){ float fout = landTime / coreLandDuration; + + if(launching) fout = 1f - fout; + float fin = 1f - fout; - //core + //draw core var block = (CoreBlock)build.block; TextureRegion reg = block.fullIcon; float scl = Scl.scl(4f) / camerascale; @@ -341,7 +347,15 @@ public class Renderer implements ApplicationListener{ float s = reg.width * Draw.scl * scl * 3.6f * Interp.pow2Out.apply(fout); float rotation = Interp.pow2In.apply(fout) * 135f, x = build.x + Mathf.range(shake), y = build.y + Mathf.range(shake); float thrustOpen = 0.25f; - float frame = fin >= thrustOpen ? 1f : fin / thrustOpen; + float thrusterFrame = fin >= thrustOpen ? 1f : fin / thrustOpen; + float thrusterSize = Mathf.sample(thrusterSizes, fin); + + //when launching, thrusters stay out the entire time. + if(launching){ + Interp i = Interp.pow2Out; + thrusterFrame = i.apply(Mathf.clamp(fout*13f)); + thrusterSize = i.apply(Mathf.clamp(fout*9f)); + } Draw.color(Pal.lightTrail); //TODO spikier heat @@ -351,20 +365,20 @@ public class Renderer implements ApplicationListener{ float pfin = Interp.pow3Out.apply(fin), pf = Interp.pow2In.apply(fout); - //particles + //draw particles Angles.randLenVectors(1, pfin, 100, 800f * scl * pfin, (ax, ay, ffin, ffout) -> { Lines.stroke(scl * ffin * pf * 3f); Lines.lineAngle(build.x + ax, build.y + ay, Mathf.angle(ax, ay), (ffin * 20 + 1f) * scl); }); Draw.color(); - Draw.mixcol(Color.white, Interp.pow2In.apply(fout)); + Draw.mixcol(Color.white, Interp.pow5In.apply(fout)); Draw.scl(scl); Draw.alpha(1f); - //thruster flame - float strength = (1f + (block.size - 3)/2.5f) * scl * Mathf.sample(thrusterSize, fin) * (0.95f + Mathf.absin(2f, 0.1f)); + //draw thruster flame + float strength = (1f + (block.size - 3)/2.5f) * scl * thrusterSize * (0.95f + Mathf.absin(2f, 0.1f)); float offset = (block.size - 3) * 3f * scl; for(int i = 0; i < 4; i++){ @@ -379,12 +393,12 @@ public class Renderer implements ApplicationListener{ Fill.circle(Tmp.v1.x + x, Tmp.v1.y + y, 3.5f * strength); } - drawThrusters(block, x, y, rotation, frame); + drawThrusters(block, x, y, rotation, thrusterFrame); Drawf.spinSprite(block.region, x, y, rotation); - Draw.alpha(Interp.pow4In.apply(frame)); - drawThrusters(block, x, y, rotation, frame); + Draw.alpha(Interp.pow4In.apply(thrusterFrame)); + drawThrusters(block, x, y, rotation, thrusterFrame); Draw.alpha(1f); Drawf.spinSprite(block.teamRegions[build.team.id], x, y, rotation); @@ -393,8 +407,8 @@ public class Renderer implements ApplicationListener{ Draw.reset(); + //draw clouds if(state.rules.cloudColor.a > 0.0001f){ - //clouds float scaling = cloudScaling; float sscl = Math.max(1f + Mathf.clamp(fin + cfinOffset)* cfinScl, 0f) * camerascale; @@ -472,16 +486,18 @@ public class Renderer implements ApplicationListener{ } public void showLanding(){ - isLaunching = false; + launching = false; camerascale = minZoomScl; landTime = coreLandDuration; cloudSeed = Mathf.random(1f); } public void showLaunch(){ - isLaunching = true; + Vars.ui.hudfrag.showLaunch(); + launching = true; landCore = player.team().core(); cloudSeed = Mathf.random(1f); + landTime = coreLandDuration; //TODO other stuff. } diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 946d1effc3..74d0265058 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -913,6 +913,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ }else{ CoreBlock block = from.info.bestCoreType instanceof CoreBlock b ? b : (CoreBlock)Blocks.coreShard; + //TODO load launchFrom sector right before launching so animation is correct loadouts.show(block, from, () -> { from.removeItems(universe.getLastLoadout().requirements()); from.removeItems(universe.getLaunchResources()); @@ -923,7 +924,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ //TODO renderer.showLaunch(); hide(); - Time.runTask(launchDuration, () -> control.playSector(from, sector)); + //run with less delay, as the loading animation is delayed by several frames + Time.runTask(coreLandDuration - 8f, () -> control.playSector(from, sector)); }); } }else if(mode == select){ diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java index 49b262aaa0..5fc4654cd2 100644 --- a/core/src/mindustry/ui/fragments/HudFragment.java +++ b/core/src/mindustry/ui/fragments/HudFragment.java @@ -545,11 +545,21 @@ public class HudFragment extends Fragment{ } } - public void showLaunchDirect(){ + public void showLaunch(){ + float margin = 30f; + Image image = new Image(); image.color.a = 0f; + image.touchable = Touchable.disabled; image.setFillParent(true); - image.actions(Actions.fadeIn(launchDuration / 60f, Interp.pow2In), Actions.delay(8f / 60f), Actions.remove()); + image.actions(Actions.delay((coreLandDuration - margin) / 60f), Actions.fadeIn(margin / 60f, Interp.pow2In), Actions.delay(6f / 60f), Actions.remove()); + image.update(() -> { + image.toFront(); + ui.loadfrag.toFront(); + if(state.isMenu()){ + image.remove(); + } + }); Core.scene.add(image); } @@ -558,9 +568,10 @@ public class HudFragment extends Fragment{ image.color.a = 1f; image.touchable = Touchable.disabled; image.setFillParent(true); - image.actions(Actions.fadeOut(0.8f), Actions.remove()); + image.actions(Actions.fadeOut(35f / 60f), Actions.remove()); image.update(() -> { image.toFront(); + ui.loadfrag.toFront(); if(state.isMenu()){ image.remove(); } diff --git a/core/src/mindustry/ui/fragments/LoadingFragment.java b/core/src/mindustry/ui/fragments/LoadingFragment.java index 348783fe05..902e6ea3ca 100644 --- a/core/src/mindustry/ui/fragments/LoadingFragment.java +++ b/core/src/mindustry/ui/fragments/LoadingFragment.java @@ -45,6 +45,10 @@ public class LoadingFragment extends Fragment{ }); } + public void toFront(){ + table.toFront(); + } + public void setProgress(Floatp progress){ bar.reset(0f); bar.visible = true; From 5ca5025fb1076789813333bb84451d1767362362 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 27 Jul 2021 19:02:04 -0400 Subject: [PATCH 031/130] Final core launch animation / Added option to skip core animations --- core/assets/bundles/bundle.properties | 1 + core/src/mindustry/Vars.java | 8 ++--- core/src/mindustry/content/Fx.java | 10 ++++++ core/src/mindustry/core/Control.java | 7 +++- core/src/mindustry/core/Renderer.java | 19 ++++++++-- .../mindustry/ui/dialogs/PlanetDialog.java | 36 ++++++++++++++----- .../ui/dialogs/SettingsMenuDialog.java | 2 ++ 7 files changed, 65 insertions(+), 18 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 099e1b7140..f03d682c12 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -835,6 +835,7 @@ category.items = Items category.crafting = Input/Output category.function = Function category.optional = Optional Enhancements +setting.skipcoreanimation.name = Skip Core Launch/Land Animation setting.landscape.name = Lock Landscape setting.shadows.name = Shadows setting.blockreplace.name = Automatic Block Suggestions diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index f27fc0f77c..dbd8e9cc42 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -103,8 +103,8 @@ public class Vars implements Loadable{ public static final float invasionGracePeriod = 20; /** min armor fraction damage; e.g. 0.05 = at least 5% damage */ public static final float minArmorDamage = 0.1f; - /** land animation duration */ - public static final float coreLandDuration = 150f; + /** land/launch animation duration */ + public static final float coreLandDuration = 160f; /** size of tiles in units */ public static final int tilesize = 8; /** size of one tile payload (^2) */ @@ -142,10 +142,6 @@ public class Vars implements Loadable{ public static boolean clientLoaded = false; /** max GL texture size */ public static int maxTextureSize = 2048; - /** Whether to show the core landing animation. */ - public static boolean showLandAnimation = true; - /** Whether to show the campaign core launch animation. */ - public static boolean showLaunchAnimation = true; /** Whether to show sector info upon landing. */ public static boolean showSectorLandInfo = true; /** Whether to check for memory use before taking screenshots. */ diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index dc11b79f36..28ab6e7a3b 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -184,6 +184,16 @@ public class Fx{ Lines.square(e.x, e.y, tilesize / 2f * e.rotation + e.fin() * 3f); }), + coreLaunchConstruct = new Effect(35, e -> { + color(Pal.accent); + stroke(4f - e.fin() * 3f); + Lines.square(e.x, e.y, tilesize / 2f * e.rotation * 1.2f + e.fin() * 5f); + + randLenVectors(e.id, 5 + (int)(e.rotation * 5), e.rotation * 3f + (tilesize * e.rotation) * e.finpow() * 1.5f, (x, y) -> { + Lines.lineAngle(e.x + x, e.y + y, Mathf.angle(x, y), 1f + e.fout() * (4f + e.rotation)); + }); + }), + tapBlock = new Effect(12, e -> { color(Pal.accent); stroke(3f - e.fin() * 2f); diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index ff42a5e6c0..e4f84b8d38 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -201,7 +201,7 @@ public class Control implements ApplicationListener, Loadable{ camera.position.set(core); player.set(core); - if(showLandAnimation){ + if(!settings.getBool("skipcoreanimation")){ //delay player respawn so animation can play. player.deathTimer = -80f; //TODO this sounds pretty bad due to conflict @@ -544,6 +544,11 @@ public class Control implements ApplicationListener, Loadable{ core.items.each((i, a) -> i.unlock()); } + //cannot launch while paused + if(state.is(State.paused) && renderer.isCutscene()){ + state.set(State.playing); + } + if(Core.input.keyTap(Binding.pause) && !renderer.isCutscene() && !scene.hasDialog() && !scene.hasKeyboard() && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){ state.set(state.is(State.playing) ? State.paused : State.playing); } diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java index 4d107c06ed..e7fe48677e 100644 --- a/core/src/mindustry/core/Renderer.java +++ b/core/src/mindustry/core/Renderer.java @@ -51,6 +51,7 @@ public class Renderer implements ApplicationListener{ public TextureRegion[] bubbles = new TextureRegion[16], splashes = new TextureRegion[12]; private @Nullable CoreBuild landCore; + private @Nullable CoreBlock launchCoreType; private Color clearColor = new Color(0f, 0f, 0f, 1f); private float //seed for cloud visuals, 0-1 @@ -340,7 +341,7 @@ public class Renderer implements ApplicationListener{ float fin = 1f - fout; //draw core - var block = (CoreBlock)build.block; + var block = launching && launchCoreType != null ? launchCoreType : (CoreBlock)build.block; TextureRegion reg = block.fullIcon; float scl = Scl.scl(4f) / camerascale; float shake = 0f; @@ -373,6 +374,15 @@ public class Renderer implements ApplicationListener{ Draw.color(); Draw.mixcol(Color.white, Interp.pow5In.apply(fout)); + + //accent tint indicating that the core was just constructed + if(launching){ + float f = Mathf.clamp(1f - fout * 12f); + if(f > 0.001f){ + Draw.mixcol(Pal.accent, f); + } + } + Draw.scl(scl); Draw.alpha(1f); @@ -492,13 +502,16 @@ public class Renderer implements ApplicationListener{ cloudSeed = Mathf.random(1f); } - public void showLaunch(){ + public void showLaunch(CoreBlock coreType){ Vars.ui.hudfrag.showLaunch(); + launchCoreType = coreType; launching = true; landCore = player.team().core(); cloudSeed = Mathf.random(1f); landTime = coreLandDuration; - //TODO other stuff. + if(landCore != null){ + Fx.coreLaunchConstruct.at(landCore.x, landCore.y, coreType.size); + } } public void takeMapScreenshot(){ diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 74d0265058..2f213fd6c8 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -32,6 +32,7 @@ import mindustry.type.*; import mindustry.ui.*; import mindustry.world.blocks.storage.*; +import static arc.Core.*; import static mindustry.Vars.*; import static mindustry.graphics.g3d.PlanetRenderer.*; import static mindustry.ui.dialogs.PlanetDialog.Mode.*; @@ -913,19 +914,38 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ }else{ CoreBlock block = from.info.bestCoreType instanceof CoreBlock b ? b : (CoreBlock)Blocks.coreShard; - //TODO load launchFrom sector right before launching so animation is correct loadouts.show(block, from, () -> { + var schemCore = universe.getLastLoadout().findCore(); from.removeItems(universe.getLastLoadout().requirements()); from.removeItems(universe.getLaunchResources()); - launching = true; - zoom = 0.5f; + if(settings.getBool("skipcoreanimation")){ + //just... go there + control.playSector(from, sector); + //hide only after load screen is shown + Time.runTask(8f, this::hide); + }else{ + //hide immediately so launch sector is visible + hide(); - //TODO - renderer.showLaunch(); - hide(); - //run with less delay, as the loading animation is delayed by several frames - Time.runTask(coreLandDuration - 8f, () -> control.playSector(from, sector)); + //allow planet dialog to finish hiding before actually launching + Time.runTask(5f, () -> { + Runnable doLaunch = () -> { + renderer.showLaunch(schemCore); + //run with less delay, as the loading animation is delayed by several frames + Time.runTask(coreLandDuration - 8f, () -> control.playSector(from, sector)); + }; + + //load launchFrom sector right before launching so animation is correct + if(!from.isBeingPlayed()){ + //run *after* the loading animation is done + Time.runTask(9f, doLaunch); + control.playSector(from); + }else{ + doLaunch.run(); + } + }); + } }); } }else if(mode == select){ diff --git a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java index f15693634e..7ba99bf975 100644 --- a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -448,6 +448,8 @@ public class SettingsMenuDialog extends Dialog{ } } + graphics.checkPref("skipcoreanimation", false); + if(!mobile){ Core.settings.put("swapdiagonal", false); } From d66bb3a5395cf2299ed4523949037ef4aecd58e3 Mon Sep 17 00:00:00 2001 From: buthed010203 Date: Tue, 27 Jul 2021 20:20:27 -0400 Subject: [PATCH 032/130] Better Plan Skipping 2: Electric Boogaloo (#5659) Fixing a problem that I created. Just allows for plan switching when items are low when the player isnt in range of the building they were previously building. Before: ![](https://aethex.is-a.fail/55tN9oFIC.png) After: ![](https://extremely.questionable.link/55tNBlX8h.png) --- core/src/mindustry/entities/comp/BuilderComp.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/mindustry/entities/comp/BuilderComp.java b/core/src/mindustry/entities/comp/BuilderComp.java index f9a5af6ca2..81b8bef2da 100644 --- a/core/src/mindustry/entities/comp/BuilderComp.java +++ b/core/src/mindustry/entities/comp/BuilderComp.java @@ -20,7 +20,6 @@ import mindustry.type.*; import mindustry.world.*; import mindustry.world.blocks.*; import mindustry.world.blocks.ConstructBlock.*; -import mindustry.world.blocks.storage.CoreBlock.*; import java.util.*; @@ -177,7 +176,7 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{ /** @return whether this request should be skipped, in favor of the next one. */ boolean shouldSkip(BuildPlan request, @Nullable Building core){ //requests that you have at least *started* are considered - if(state.rules.infiniteResources || team.rules().infiniteResources || request.breaking || core == null || request.isRotation(team)) return false; + if(state.rules.infiniteResources || team.rules().infiniteResources || request.breaking || core == null || request.isRotation(team) || (isBuilding() && !within(plans.last(), buildingRange))) return false; return (request.stuck && !core.items.has(request.block.requirements)) || (Structs.contains(request.block.requirements, i -> !core.items.has(i.item, Math.min(i.amount, 15)) && Mathf.round(i.amount * state.rules.buildCostMultiplier) > 0) && !request.initialized); } From b64432dafd74e01ba86c91fd902eb3339dad7572 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 28 Jul 2021 08:38:45 -0400 Subject: [PATCH 033/130] Allow placing blocks with 0 requirements of an item --- core/src/mindustry/entities/comp/BuilderComp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/entities/comp/BuilderComp.java b/core/src/mindustry/entities/comp/BuilderComp.java index 81b8bef2da..f45824ea1b 100644 --- a/core/src/mindustry/entities/comp/BuilderComp.java +++ b/core/src/mindustry/entities/comp/BuilderComp.java @@ -96,7 +96,7 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{ if(!(tile.build instanceof ConstructBuild cb)){ if(!current.initialized && !current.breaking && Build.validPlace(current.block, team, current.x, current.y, current.rotation)){ - boolean hasAll = infinite || current.isRotation(team) || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item)); + boolean hasAll = infinite || current.isRotation(team) || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item, Mathf.round(i.amount * state.rules.buildCostMultiplier))); if(hasAll){ Call.beginPlace(self(), current.block, team, current.x, current.y, current.rotation); From 193015f1cd6ebd87f82587c4d5f00d9b87580ee2 Mon Sep 17 00:00:00 2001 From: JrTRinny <85090668+JrTRinny@users.noreply.github.com> Date: Wed, 28 Jul 2021 21:44:35 +0700 Subject: [PATCH 034/130] update bundle_th.properties (#5591) * separated from `#5491` * follow latest changes like settings tooltips, large launch pad removal and clean up team PvP * follow latest changes * descriptions for new content * line spacings and edit errors * derelict tooltips * open games * remove resource flow rate --- core/assets/bundles/bundle_th.properties | 155 ++++++++++++----------- 1 file changed, 84 insertions(+), 71 deletions(-) diff --git a/core/assets/bundles/bundle_th.properties b/core/assets/bundles/bundle_th.properties index f973f39a9a..4553c81ef3 100644 --- a/core/assets/bundles/bundle_th.properties +++ b/core/assets/bundles/bundle_th.properties @@ -5,7 +5,7 @@ discord = เข้าร่วมเซิร์ฟเวอร์ Discord ข link.discord.description = พื้นที่พูดคุยอย่างเป็นทางการของ Mindustry link.reddit.description = Subreddit ของ Mindustry link.github.description = แหล่งโค้ดของเกม -link.changelog.description = รายการอัพเดต +link.changelog.description = รายการอัปเดต link.dev-builds.description = เวอร์ชั่นระหว่างพัฒนา (ไม่เสถียร) link.trello.description = บอร์ด Trello อย่างเป็นทางการสำหรับฟีเจอร์ต่างๆ ที่วางแผนไว้ link.itch.io.description = หน้าเว็บ itch.io สำหรับดาวน์โหลดบน PC @@ -36,10 +36,10 @@ load.scripts = สคริปต์ be.update = เวอร์ชั่นรุ่นพัฒนาล่าสุดออกแล้ว: be.update.confirm = ดาวน์โหลดเวอร์ชั่นใหม่แล้วรีสตาร์ทเลยไหม? -be.updating = กำลังอัพเดต... +be.updating = กำลังอัปเดต... be.ignore = ยกเลิก -be.noupdates = ไม่พบอัพเดตใหม่ -be.check = ตรวจหาอัพเดตใหม่ +be.noupdates = ไม่พบอัปเดตใหม่ +be.check = ตรวจหาอัปเดตใหม่ mods.browser = ค้นหาม็อด mods.browser.selected = เลือกแล้ว @@ -93,7 +93,7 @@ level.highscore = คะแนนสูงสุด: [accent]{0} level.mode = เกมโหมด: coreattack = < แกนกลางถูกโจมตี! > nearpoint = [[ [scarlet]ออกจากจุดเกิดด่วน![] ]\nการทำลายล้างกำลังใกล้เข้ามา -database = ฐานข้อมูลหลัก +database = ฐานข้อมูลแกนกลาง savegame = เซฟเกม loadgame = โหลดเกม joingame = เข้าร่วมเกม @@ -101,6 +101,7 @@ customgame = เกมที่กำหนดเอง newgame = เริ่มเกมใหม่ none = <ไม่มี> none.found = [lightgray]<ไม่เจออะไรเลย> +none.inmap = [lightgray]<ไม่มีในแมพ> minimap = มินิแมพ position = ตำแหน่ง close = ปิด @@ -155,7 +156,7 @@ mod.jarwarn = [scarlet]ม็อดไฟล์ JAR นั้นค่อนข mod.item.remove = ไอเท็มนี้เป็นส่วนหนึ่งของม็อด [accent]'{0}'[] หากต้องการนำออก กรุณาถอนการติดตั้งม็อดนั้น mod.remove.confirm = ม็อดนี้จะถูกลบ mod.author = [lightgray]ผู้สร้าง:[] {0} -mod.missing = เซฟนี้มีม็อดที่คุณพึ่งอัพเดตหรือไม่ได้ติดตั้งแล้ว อาจทำให้เซฟเสีย คุณแน่จะหรือว่าจะโหลดเซฟนี้?\n[lightgray]ม็อดที่ใช้:\n{0} +mod.missing = เซฟนี้มีม็อดที่คุณพึ่งอัปเดตหรือไม่ได้ติดตั้งแล้ว อาจทำให้เซฟเสีย คุณแน่จะหรือว่าจะโหลดเซฟนี้?\n[lightgray]ม็อดที่ใช้:\n{0} mod.preview.missing = ก่อนที่จะนำม็อดไปลงในเวิร์กช็อป คุณต้องใส่รูปพรีวิวก่อน\nใส่รูปชื่อ[accent] preview.png[] ลงในโฟลเดอร์ของม็อดแล้วลองอีกครั้ง mod.folder.missing = ม็อดที่อยู่ในรูปแบบโฟลเดอร์เท่านั้นที่สามารถลงในเวิร์กช็อปได้\nunzip ไฟล์แล้วลบไฟล์ zip เก่า แล้วรีสตาร์ทเกมหรือรีโหลดม็อด mod.scripts.disable = เครื่องของคุณไม่รองรับม็อดที่มีสคริปต์ คุณจำเป็นต้องปิดม็อดเหล่านี้ก่อนจึงจะสามารถเล่นได้ @@ -166,10 +167,10 @@ noname = ใส่ชื่อ[accent]ผู้เล่น[]ก่อน planetmap = แผนที่ดาวเคราะห์ launchcore = ส่งแกนกลาง filename = ชื่อไฟล์: -unlocked = เนื้อหาใหม่ปลดล็อค! +unlocked = เนื้อหาใหม่ปลดล็อก! available = มีการวิจัยใหม่พร้อมปลดล็อก! completed = [accent]วิจัยแล้ว -techtree = การวิจัย +techtree = ต้นไม้แห่งเทคโนโลยี research.legacy = พบข้อมูลการวิจัยของเวอร์ชั่น [accent]5.0[]\nคุณต้องการ[accent]โหลดข้อมูล[]หรือ[accent]ทิ้งข้อมูลไป[]และเริ่มต้นวิจัยในแคมเปญใหม่ (แนะนำ) research.load = โหลด research.discard = ทอดทิ้ง @@ -186,19 +187,19 @@ server.kicked.kick = คุณถูกเตะออกจากเซิร server.kicked.whitelist = คุณไม่ได้ถูกรับเชิญ\nคนที่ถูกรับเชิญเท่านั้นที่จะเข้าได้ server.kicked.serverClose = เซิร์ฟเวอร์ถูกปิด server.kicked.vote = คุณถูกโหวตเตะออก บัยบาย -server.kicked.clientOutdated = ไคลเอนต์เก่า! กรุณาอัพเดตเกมของคุณ! -server.kicked.serverOutdated = เซิร์ฟเวอร์เก่า! โปรดถามเจ้าของเซิร์ฟเวอร์เพื่ออัพเดต! +server.kicked.clientOutdated = ไคลเอนต์เก่า! กรุณาอัปเดตเกมของคุณ! +server.kicked.serverOutdated = เซิร์ฟเวอร์เก่า! โปรดถามเจ้าของเซิร์ฟเวอร์เพื่ออัปเดต! server.kicked.banned = คุณถูกแบนในเซิร์ฟเวอร์นี้ server.kicked.typeMismatch = เซิร์ฟเวอร์นี้ไม่เข้ากับประเภทบิลด์ของคุณ server.kicked.playerLimit = เซิร์ฟเวอร์เต็ม กรุณารอให้เซิร์ฟเวอร์ว่างก่อน server.kicked.recentKick = คุณเพิ่งถูกเตะออกจากเซิร์ฟเวอร์นี้\nกรุณารอสักครู่เพื่อเข้าร่วมอีกครั้ง -server.kicked.nameInUse = มีคนที่ใช้ชืชื่อนี้\nอยู่ในเซิฟเวอร์แล้ว +server.kicked.nameInUse = มีคนที่ใช้ชื่อนี้\nอยู่ในเซิร์ฟเวอร์แล้ว server.kicked.nameEmpty = ชื่อของคุณไม่สามารถใช้ได้ server.kicked.idInUse = คุณเชื่อมต่อกับเซิร์ฟเวอร์นี้อยู่แล้ว เราไม่อนุญาตให้เชื่อมต่อสองบัญชีในเซิร์ฟเวอร์เดียวกัน server.kicked.customClient = เซิร์ฟเวอร์นี้ไม่รองรับเวอร์ชั่นที่ถูกปรับแต่ง กรุณาโหลดเวอร์ชั่นอย่างเป็นทางการของ Mindustry server.kicked.gameover = จบเกม! server.kicked.serverRestarting = เซิร์ฟเวอร์กำลังเริ่มใหม่ -server.versions = เวอร์ชั่นของคุณ:[accent] {0}[]\nเวอร์ชั่นของเซิฟเวอร์:[accent] {1}[] +server.versions = เวอร์ชั่นของคุณ:[accent] {0}[]\nเวอร์ชั่นของเซิร์ฟเวอร์:[accent] {1}[] host.info = ปุ่ม[accent]โฮสต์[]นั้นโฮสต์เซิร์ฟเวอร์ที่พอร์ต [scarlet]6567[] \nทุกคนที่อยู่ใน [lightgray]Wi-Fi หรือเครือข่ายท้องถิ่น[]เดียวกันจะสามารถเห็นเซิร์ฟเวอร์ของคุณในรายชื่อของ\nเซิร์ฟเวอร์ได้\n\nถ้าคุณต้องการให้ผู้เล่นอื่นๆ สามารถเชื่อมต่อได้จากทุกที่โดยใช้ IP คุณจำเป็นจะต้องใช้การ[accent]การส่งต่อพอร์ต (Port Forwarding)[] \n\n[lightgray]โน๊ต: ถ้าผู้เล่นคนใดมีปัญหาในการเชื่อมต่อ LAN ของคุณ เช็คให้แน่ใจว่าคุณได้อนุญาตให้ Mindustry เข้าถึงเครือข่ายท้องถิ่นของคุณในการตั้งค่า Firewall จำไว้ว่าเครือข่ายสาธารณะบางครั้งอาจไม่อนุญาตการ\nค้นหาเซิร์ฟเวอร์ join.info = คุณสามารถใส่ [accent]IP ของเซิร์ฟเวอร์[]เพื่อที่จะเชื่อมต่อหรือค้นหาเซิร์ฟเวอร์ เซิร์ฟเวอร์ที่ใช้[accent]เครือข่ายท้องถิ่น[]จะสามารถเชื่อมโดยใช้\n LAN หรือ WAN ก็ได้\n\n[lightgray]ถ้าคุณอยากเชื่อมต่อกับใครบางคนโดยใช้ IP คุณต้องไปถามโฮสต์เอาว่า IP ของโฮสต์คืออะไร ซึ่งสามารถหาได้โดยการค้นหาในกูเกิ้ลว่า "ip ของฉัน" จากเครื่องของโฮสต์ hostserver = โฮสต์เกมผู้เล่นหลายคน @@ -214,6 +215,7 @@ hosts.none = [lightgray]ไม่พบเซิร์ฟเวอร์ท้ host.invalid = [scarlet]ไม่สามารถเชื่อมต่อกับโฮสต์ได้ servers.local = เซิร์ฟเวอร์ท้องถิ่น +servers.local.steam = เกมสาธารณะ & เซิร์ฟเวอร์ท้องถิ่น servers.remote = เซิร์ฟเวอร์ทางไกล servers.global = เซิร์ฟเวอร์ของชุมชน @@ -255,14 +257,14 @@ disconnect.error = การเชื่อมต่อมีปัญหา disconnect.closed = การเชื่อมต่อถูกปิดแล้ว disconnect.timeout = หมดเวลา disconnect.data = การโหลดข้อมูลของโลกผิดพลาด! -cantconnect = ไม่สามารถเข้าร่วมเซิฟเวอร์ ([accent]{0}[]) +cantconnect = ไม่สามารถเข้าร่วมเซิร์ฟเวอร์ ([accent]{0}[]) connecting = [accent]กำลังเชื่อมต่อ... reconnecting = [accent]กำลังเชื่อมต่อใหม่... connecting.data = [accent]กำลังโหลดข้อมูลของโลก ... server.port = พอร์ต: server.addressinuse = มีคนใช้ที่อยู่นี้แล้ว! server.invalidport = เลขพอร์ตไม่ถูกต้อง! -server.error = [crimson]การโฮสต์เซิฟเวอร์ผิดพลาด +server.error = [crimson]การโฮสต์เซิร์ฟเวอร์ผิดพลาด save.new = เซฟใหม่ save.overwrite = คุณแน่ใจหรือว่าจะเซฟทับ\nเซฟนี้? overwrite = เขียนทับ @@ -340,14 +342,14 @@ loadimage = โหลดรูป saveimage = เซฟรูป unknown = ไม่ทราบ custom = กำหนดเอง -builtin = Built-In +builtin = ติดตัว map.delete.confirm = คุณแน่ใจหรือว่าจะลบแมพนี้? การกระทำครั้งนี้ไม่สามารถย้อนกลับได้! map.random = [accent]สุ่มแมพ map.nospawn = แมพนี้ไม่มีแกนกลางให้ผู้เล่นเกิด! กรุณาใส่แกนกลาง[accent]สีเหลือง[] ในตัวแก้ไข map.nospawn.pvp = แมพนี้ไม่มีแกนกลางของศัตรูสำหรับให้ผู้เล่นเกิด! กรุณาใส่แกนกลาง[scarlet]ที่ไม่ใช่สีส้ม[] ในตัวแก้ไข map.nospawn.attack = แมพนี้ไม่มีแกนกลางของศัตรูสำหรับให้ผู้เล่นโจมตี! กรุณาใส่แกนกลาง[scarlet]สีแดง[] ในตัวแก้ไข map.invalid = โหลดแมพผิดพลาด: ไฟล์แมพเสียหายหรือไม่ถูกต้อง -workshop.update = อัพเดตไอเท็ม +workshop.update = อัปเดตไอเท็ม workshop.error = ผิดพลาดในการนำเวิร์กช็อปมา รายละเอียดดังนี้: {0} map.publish.confirm = คุณแน่ใจหรือว่าจะเผยแพร่แมพนี้?\n\n[lightgray]คุณต้องแน่ใจก่อนว่าคุณเห็นด้วยกับ Workshop EULA, มิฉนั้นแมพจะไม่ปรากฏ! workshop.menu = เลือกว่าจะทำอะไรกับไอเท็มนี้ @@ -357,7 +359,7 @@ eula = Steam EULA missing = ไอเท็มนี้ถูกลบหรือย้าย\n[lightgray]ยกเลิกการเชื่อมต่อของหน้ารายการเวิร์กช็อปแล้ว publishing = [accent]กำลังเผยแพร่... publish.confirm = คุณแน่ใจหรือว่าจะเผยแพร่สิ่งนี้?\n\n[lightgray]คุณต้องแน่ใจก่อนว่าคุณเห็นด้วยกับ Workshop EULA มิฉนั้นไอเท็มของคุณจะไม่ปรากฏ! -publish.error = การเผยแพร่ไอเท็มดังต่อไปนี้ผิดพลาด: {0} +publish.error = เกิดข้อผิดพลาดการเผยแพร่ไอเท็มดังต่อไปนี้: {0} steam.error = ไม่สามารถเริ่ม Steam service ได้\nError: {0} editor.brush = แปรง @@ -401,7 +403,7 @@ editor.default = [lightgray]<ค่าเริ่มต้น> details = รายละเอียด... edit = แก้ไข... editor.name = ชื่อ: -editor.spawn = สปาวน์ยูนิต +editor.spawn = สร้างยูนิต editor.removeunit = ลบยูนิต editor.teams = ทีม editor.errorload = โหลดไฟล์ผิดพลาด @@ -411,7 +413,7 @@ editor.errorlegacy = แมพนี้เก่าเกินไปและ editor.errornot = นี่ไม่ใช้ไฟล์แมพ editor.errorheader = ไฟล์แมพนี้เสียหรือไม่ถูกต้อง editor.errorname = แมพไม่มีการกำหนดชื่อ คุณกำลังโหลดไฟล์เซฟอยู่หรือป่าว? -editor.update = อัพเดต +editor.update = อัปเดต editor.randomize = สุ่ม editor.apply = ใช้ editor.generate = การกำเนิด @@ -420,8 +422,8 @@ editor.loadmap = โหลดแมพ editor.savemap = เซฟแมพ editor.saved = เซฟเรียบร้อย! editor.save.noname = แมพของคุณไม่มีชื่อ! สามารถตั้งชื่อได้ในเมนู 'ข้อมูลแมพ' -editor.save.overwrite = แมพของคุณไปทับกับแมพ built-in! เปลี่ยนชื่อได้ในเมนู 'ข้อมูลแมพ' -editor.import.exists = [scarlet]ไม่สามารถนำเข้าได้:[] มีแมพ built-in ที่ชื่อ '{0}' อยู่แล้ว! +editor.save.overwrite = แมพของคุณไปทับกับแมพติดตัว! เปลี่ยนชื่อได้ในเมนู 'ข้อมูลแมพ' +editor.import.exists = [scarlet]ไม่สามารถนำเข้าได้:[] มีแมพติดตัวที่ชื่อ '{0}' อยู่แล้ว! editor.import = นำเข้า... editor.importmap = นำเข้าแมพ editor.importmap.description = นำเข้าแมพที่มีอยู่แล้ว @@ -521,7 +523,7 @@ mapeditor = แก้ไขแมพ abandon = ละทิ้ง abandon.text = โซนนี้และทรัพยากรทั้งหมดจะถูกยืดไปเป็นของศัตรู -locked = ล็อค +locked = ล็อก complete = [lightgray]ต้องมี: requirement.wave = ถึงคลื่นที่ {0} ใน {1} requirement.core = ทำลายแกนกลางของศัตรูใน {0} @@ -545,15 +547,15 @@ add = เพิ่ม... guardian = การ์เดียน connectfail = [crimson]การเชื่อมต่อผิดพลาด:\n\n[accent]{0} -error.unreachable = เซิฟเวอร์ไม่สามารถเข้าถึงได้\nแน่ใจหรือว่าที่อยู่เขียนถูกต้อง? +error.unreachable = เซิร์ฟเวอร์ไม่สามารถเข้าถึงได้\nแน่ใจหรือว่าที่อยู่เขียนถูกต้อง? error.invalidaddress = ที่อยู่ไม่ถูกต้อง error.timedout = Timed out!\nเช็คให้แน่ใจว่า port forwarding ของโฮสต์เปิดอยู่และที่อยู่นั้นถูกต้อง! -error.mismatch = Packet error:\nอาจเกิดจากเวอร์ชั่นของ ไคลเอนต์/เซิร์ฟเวอร์ ไม่ตรงกัน\nเช็คให้แน่ใจว่าเซิฟเวอร์ใช้ Mindustry เวอร์ชั่นล่าสุด! +error.mismatch = Packet error:\nอาจเกิดจากเวอร์ชั่นของ ไคลเอนต์/เซิร์ฟเวอร์ ไม่ตรงกัน\nเช็คให้แน่ใจว่าเซิร์ฟเวอร์ใช้ Mindustry เวอร์ชั่นล่าสุด! error.alreadyconnected = เชื่อมต่ออยู่แล้ว error.mapnotfound = ไม่พบไฟล์แมพ error.io = Network I/O error error.any = Error: เครือข่ายที่ไม่รู้จัก -error.bloom = ไม่สามารถเริ่มต้น bloom ได้\nอุปกรณ์ของคุณอาจไม่รองรับ +error.bloom = ไม่สามารถเริ่มต้นบลูมได้\nอุปกรณ์ของคุณอาจไม่รองรับ weather.rain.name = ฝน weather.snow.name = หิมะ @@ -565,6 +567,7 @@ sectors.unexplored = [lightgray]ยังไม่ได้สำรวจ sectors.resources = ทรัพยากร: sectors.production = การผลิต: sectors.export = การส่งออก: +sectors.import = การนำเข้า: sectors.time = เวลา: sectors.threat = ภัยคุกคาม: sectors.wave = คลื่น: @@ -577,7 +580,7 @@ sectors.rename = เปลี่ยนชื่อเซ็กเตอร์ sectors.enemybase = [scarlet]ฐานทัพศัตรู sectors.vulnerable = [scarlet]เสี่ยงภัย sectors.underattack = [scarlet]เซ็กเตอร์ถูกโจมตี! เสียหาย [accent]{0}% -sectors.survives = [accent]จะอยู่รอดอีก {0} คลื่น +sectors.survives = [accent]จะอยู่รอดได้ {0} คลื่น sectors.go = ไป sector.curcapture = ยึดครองแล้ว sector.curlost = เราเสียเซ็กเตอร์! @@ -655,10 +658,10 @@ settings.resetKey = รีเซ็ต settings.controls = การควบคุม settings.game = เกม settings.sound = เสียง -settings.graphics = กราฟฟิค +settings.graphics = กราฟิก settings.cleardata = เคลียร์ข้อมูลเกม... settings.clear.confirm = คุณแน่ใจหรือว่าจะเคลียร์ข้อมูลเกม?\nสิ่งที่ทำไปแล้วจะไม่สามารถย้อนกลับได้! -settings.clearall.confirm = [scarlet]คำเตือน![]\nการกระทำนี้จะลบข้อมูลทั้งหมด นั้นรวมไปถึงเซฟ แมพ การวิจัยแล้วและก็ปุ่มควบตุม\nเมื่อคุณกด 'โอเค' เกมจะลบข้อมูลทุกอย่างและออกโดยอัตโนมัติ +settings.clearall.confirm = [scarlet]คำเตือน![]\nการกระทำนี้จะลบข้อมูลทั้งหมด นั้นรวมไปถึงเซฟ แมพ การวิจัยแล้วและก็ปุ่มควบคุม\nเมื่อคุณกด 'โอเค' เกมจะลบข้อมูลทุกอย่างและออกโดยอัตโนมัติ settings.clearsaves.confirm = คุณแน่ใจหรือว่าคุณต้องการเคลียร์เซฟทั้งหมด? settings.clearsaves = เคลียร์เซฟ settings.clearresearch = เคลียร์การวิจัย @@ -715,7 +718,7 @@ stat.speedincrease = เพิ่มความเร็ว stat.range = ระยะ stat.drilltier = แร่ที่ขุดได้ stat.drillspeed = ความเร็วการขุดเฉลี่ย -stat.boosteffect = แอฟเฟ็คของบูสต์ +stat.boosteffect = เอฟเฟกต์ของบูสต์ stat.maxunits = จำนวนยูนิตสูงสุด stat.armor = เกราะ stat.health = พลังชีวิต @@ -724,7 +727,7 @@ stat.maxconsecutive = ติดต่อกันสูงสุด stat.buildcost = ใช้ stat.inaccuracy = ความคลาดเคลื่อน stat.shots = นัด -stat.reload = นัด/วินาที +stat.reload = อัตราการยิง stat.ammo = กระสุน stat.shieldhealth = พลังชีวิตโล่ stat.cooldowntime = เวลาคูลดาวน์ @@ -747,7 +750,7 @@ stat.commandlimit = จำนวนยูนิตที่สั่งการ stat.abilities = ทักษะ stat.canboost = สามารถบูสต์ stat.flying = บินได้ -stat.ammouse = ใช้กระสุน +stat.ammouse = การใช้กระสุน stat.damagemultiplier = พหุคูณดาเมจ stat.healthmultiplier = พหุคูณพลังชีวิต stat.speedmultiplier = พหุคูณความเร็ว @@ -758,7 +761,7 @@ stat.healing = การรักษา ability.forcefield = โล่พลังงาน ability.repairfield = สนามซ่อมแซม -ability.statusfield = สนามเอฟเฟกต์ {0} +ability.statusfield = {0} สนามเอฟเฟกต์ ability.unitspawn = โรงงาน{0} ability.shieldregenfield = สนามรักษาโล่ ability.movelightning = ปล่อยสายฟ้าเมื่อเคลื่อนที่ @@ -793,7 +796,7 @@ bullet.damage = [stat]{0}[lightgray] ดาเมจ bullet.splashdamage = [stat]{0}[lightgray] ดาเมจกระจาย ~[stat] {1}[lightgray] ช่อง bullet.incendiary = [stat]ติดไฟ bullet.homing = [stat]ติดตามตัว -bullet.frag = [stat]กระจาย +bullet.frags = [stat]{0}[lightgray]x กระจาย กระสุน: bullet.lightning = [stat]{0}[lightgray]x สายฟ้า ~ [stat]{1}[lightgray] ดาเมจ bullet.buildingdamage = [lightgray]ดาเมจต่อสิ่งก่อสร้าง [stat]{0}%[lightgray] bullet.knockback = [stat]{0}[lightgray] ดันกลับ @@ -806,6 +809,7 @@ bullet.reload = [lightgray]ความเร็วการยิง: [stat]{0} unit.blocks = บล็อก unit.blockssquared = บล็อก² unit.powersecond = หน่วย/วินาที +unit.tilessecond = ช่อง/วินาที unit.liquidsecond = หน่วย/วินาที unit.itemssecond = ไอเท็ม/วินาที unit.liquidunits = หน่วยของเหลว @@ -822,7 +826,7 @@ unit.items = ไอเท็ม unit.thousands = k unit.millions = [] []ล้าน unit.billions = [] []พันล้าน -unit.pershot = [] []กระสุน/การยิง +unit.pershot = [] []ไอเท็ม/การยิง category.purpose = วัตถุประสงค์ category.general = ทั่วไป category.power = พลังงาน @@ -831,20 +835,18 @@ category.items = ไอเท็ม category.crafting = การผลิต category.function = ฟังค์ชั่น category.optional = ทางเลือกการเพิ่มประสิทธิภาพ -setting.landscape.name = ล็อคภูมิทัศน์แนวนอน +setting.landscape.name = ล็อกภูมิทัศน์แนวนอน setting.shadows.name = เงา setting.blockreplace.name = แนะนำบล็อกโดยอัตโนมัติ setting.linear.name = การกรองเชิงเส้น setting.hints.name = คำแนะนำ setting.logichints.name = คำแนะนำลอจิก -setting.flow.name = แสดงอัตราการไหลของทรัพยากร setting.backgroundpause.name = หยุดในพื้นหลัง setting.buildautopause.name = หยุดสร้างชั่วคราวแบบอัตโนมัติ setting.doubletapmine.name = แตะสองครั้งเพื่อขุด setting.modcrashdisable.name = ปิดม็อดเมื่อเกมขัดข้อง setting.animatedwater.name = แอนิเมชั่นพื้นและน้ำ setting.animatedshields.name = แอนิเมชั่นเกราะ -setting.antialias.name = Antialias[lightgray] (จำเป็นต้องรีสตาร์ท)[] setting.playerindicators.name = ตัวบอกผู้เล่น setting.indicators.name = ตัวบอกศัตรู/พักพวก setting.autotarget.name = เล็งเป้าอัตโนมัติ @@ -853,7 +855,8 @@ setting.touchscreen.name = การควบคุมแบบหน้าจ setting.fpscap.name = FPS สูงสุด setting.fpscap.none = ∞ setting.fpscap.text = {0} FPS -setting.uiscale.name = ขนาด UI[lightgray] (จำเป็นต้องรีสตาร์ท)[] +setting.uiscale.name = อัตราขนาด UI +setting.uiscale.description = จำเป็นต้องรีสตาร์ทเพื่อใส่การเปลี่ยนแปลง setting.swapdiagonal.name = การวางเป็นเส้นทแยงเสมอ setting.difficulty.training = ฝึกซ้อม setting.difficulty.easy = ง่าย @@ -862,16 +865,17 @@ setting.difficulty.hard = ยาก setting.difficulty.insane = ยากมาก setting.difficulty.name = ระดับความยาก: setting.screenshake.name = การสั่นของจอ -setting.effects.name = แสดงเอฟเฟ็ค +setting.effects.name = แสดงเอฟเฟ็กต์ setting.destroyedblocks.name = แสดงบล็อกที่ถูกทำลาย -setting.blockstatus.name = แสดงสเตตัสของบล็อก +setting.blockstatus.name = แสดงสถานะของบล็อก setting.conveyorpathfinding.name = ตรวจสอบเส้นทางการวางอัจฉริยะ setting.sensitivity.name = ความเร็วของตัวควบคุม setting.saveinterval.name = ระยะห่างระหว่างการเซฟ setting.seconds = {0} วินาที setting.milliseconds = {0} มิลลิวินาที setting.fullscreen.name = เต็มจอ -setting.borderlesswindow.name = วินโดว์แบบไร้ขอบ[lightgray] (อาจจะต้องรีตาร์ท) +setting.borderlesswindow.name = หน้าต่างแบบไร้ขอบ +setting.borderlesswindow.description = อาจจะต้องรีสตาร์ทเพื่อใส่การเปลี่ยนแปลง setting.fps.name = แสดง FPS และ Ping setting.smoothcamera.name = กล้องแบบลื่นไหล setting.vsync.name = VSync @@ -887,19 +891,19 @@ setting.sfxvol.name = ระดับเสียง SFX setting.mutesound.name = ปิดเสียง setting.crashreport.name = ส่งรายงานการแครชแบบไม่ระบุตัวตน setting.savecreate.name = สร้างเซฟโดยอัตโนมัติ -setting.publichost.name = การมองเห็นเซิฟเวอร์สาธารณะ +setting.publichost.name = การมองเห็นเซิร์ฟเวอร์สาธารณะ setting.playerlimit.name = จำกัดผู้เล่น setting.chatopacity.name = ความโปร่งแสงของแชท setting.lasersopacity.name = ความโปร่งแสงของเลเซอร์พลังงาน setting.bridgeopacity.name = ความโปร่งแสงของสะพาน setting.playerchat.name = แสดงบับเบิ้ลแชทของผู้เล่น setting.showweather.name = แสดงแกรฟฟิกสภาพอากาศ -public.confirm = คุณต้องการให้เกมของคุณเปิดเป็นสาธารณะหรือไม่?\n[accent]ทุกคนจะสามารถเข้าร่วมเกมของคุณได้\n[lightgray]คุณสามารถเปลี่ยนการตั้งค่านี้ได้ที่ ตั้งค่า->เกม->การมองเห็นเซิฟเวอร์สาธารณะ -public.confirm.really = หากคุณอยากเล่นกับเล่นกับเพื่อน ใช้ [green]Invite Friend[] ดีกว่า แทนที่จะใช้ [scarlet]Public server[]!\nคุณแน่ใจนะว่าจะเปลี่ยนเกมคุณเป็น[scarlet]สาธารณะ[]? -public.beta = เกมเวอร์ชั่นเบต้าไม่สามารถเปิดเซิฟเวอร์สาธารณะได้ -uiscale.reset = ขนาดของ UI มีการเปลี่ยนแปลง\nกด "โอเค" เพื่อยืนยันขนาด UI นี้\n[scarlet]เปลี่ยนกลับไปเป็นแบบเดิมและออกในอีก[accent] {0}[] วินาที... +public.confirm = คุณต้องการให้เกมของคุณเปิดเป็นสาธารณะหรือไม่?\n[accent]ทุกคนจะสามารถเข้าร่วมเกมของคุณได้\n[lightgray]คุณสามารถเปลี่ยนการตั้งค่านี้ได้ที่ ตั้งค่า->เกม->การมองเห็นเซิร์ฟเวอร์สาธารณะ +public.confirm.really = หากคุณอยากเล่นกับเล่นกับเพื่อน ใช้[green]ชวนเพื่อน[]ดีกว่า แทนที่จะใช้[scarlet]เซิร์ฟเวอร์สาธารณะ[]!\nคุณแน่ใจนะว่าจะเปลี่ยนเกมคุณเป็น[scarlet]สาธารณะ[]? +public.beta = เกมเวอร์ชั่นเบต้าไม่สามารถเปิดเซิร์ฟเวอร์สาธารณะได้ +uiscale.reset = อัตราขนาดของ UI ได้มีการเปลี่ยนแปลง\nกด "โอเค" เพื่อยืนยันขนาด UI นี้\n[scarlet]จะเปลี่ยนกลับไปเป็นแบบเดิมและออกในอีก[accent] {0}[] วินาที... uiscale.cancel = ยกเลิกและออก -setting.bloom.name = Bloom +setting.bloom.name = บลูม keybind.title = ตั้งค่าปุ่ม keybinds.mobile = [scarlet]การตั้งค่าปุ่มส่วนใหญ่ไม่สามารถใช้ในมือถือได้ เฉพาะการเคลื่อนไหวพื้นฐานเท่านั้นที่ใช้ได้ category.general.name = ทั่วไป @@ -972,7 +976,7 @@ keybind.chat_history_prev.name = ประวัติแชทก่อนห keybind.chat_history_next.name = ประวัติแชทถัดไป keybind.chat_scroll.name = เลื่อนแชท keybind.chat_mode.name = เปลี่ยนโหมดแชท -keybind.drop_unit.name = ดรอปยูนิต +keybind.drop_unit.name = วางยูนิต keybind.zoom_minimap.name = ซูมมินิแมพ mode.help.title = คำอธิบายโหมด mode.survival.name = เอาชีวิตรอด @@ -994,6 +998,7 @@ rules.wavetimer = นับถอยหลังการปล่อยคล rules.waves = คลื่น rules.attack = โหมดการโจมตี rules.buildai = AI ก่อสร้าง +rules.cleanupdeadteams = ลบล้างสิ่งก่อสร้างศัตรูที่พ่ายแพ้ (PvP) rules.corecapture = ยืดแกนกลางเมื่อทำลาย rules.polygoncoreprotection = รัศมีปกป้องแกนกลางแบบหลายเหลี่ยม rules.enemyCheat = AI (ทีมสีแดง) มีทรัพยากรไม่จำกัด @@ -1085,7 +1090,7 @@ unit.sei.name = เซย์ unit.omura.name = โอมูร่า unit.retusa.name = เรธูซ่า unit.oxynoe.name = อ๊อกซิโนอ์ -unit.cyerce.name = ไซเยิส +unit.cyerce.name = เซียรส์ unit.aegires.name = เอเกียเรส unit.navanax.name = นาวาแน็คซ์ unit.alpha.name = อัลฟ่า @@ -1247,7 +1252,7 @@ block.wave.name = คลื่นน้ำ block.tsunami.name = สึนามิ block.swarmer.name = สวอร์มเมอร์ block.salvo.name = ซัลโว -block.ripple.name = ริปเปิล +block.ripple.name = ริปเปิ้ล block.phase-conveyor.name = สายพานเฟส block.bridge-conveyor.name = สะพานไอเท็ม block.plastanium-compressor.name = เครื่องอัดพลาสตาเนี่ยม @@ -1268,7 +1273,7 @@ block.bridge-conduit.name = สะพานของเหลว block.rotary-pump.name = ปั๊มโรตารี่ block.thorium-reactor.name = เตาปฏิกรณ์ทอเรี่ยม block.mass-driver.name = เครื่องโอนถ่ายมวล -block.blast-drill.name = เครื่องขุดระเบิดอากาศ +block.blast-drill.name = เครื่องขุดแอร์บลาสต์ block.thermal-pump.name = ปั๊มความร้อน block.thermal-generator.name = เครื่องกำเนิดไฟฟ้าจากความร้อน block.alloy-smelter.name = เครื่องหลอมอัลลอย @@ -1288,7 +1293,6 @@ block.meltdown.name = เมลท์ดาวน์ block.foreshadow.name = ฟอร์ชาโดว์ block.container.name = ตู้เก็บของ block.launch-pad.name = ฐานส่งของ -block.launch-pad-large.name = ฐานส่งของขนาดใหญ่ block.segment.name = เซ็กเมนต์ block.command-center.name = ศูนย์ควบคุม block.ground-factory.name = โรงงานยูนิตพื้นดิน @@ -1309,11 +1313,11 @@ block.payload-source.name = จุดกำเนิดสิ่งบรรท block.disassembler.name = เครื่องถอดแยกส่วนประกอบ block.silicon-crucible.name = เบ้าหลอมซิลิคอน block.overdrive-dome.name = โดมเร่งประสิทธิภาพ +block.interplanetary-accelerator.name = ฐานเร่งความเร็วระหว่างดาวเคราะห์ #experimental, may be removed block.block-forge.name = เครื่องสร้างบล็อก block.block-loader.name = เครื่องโหลดบล็อก block.block-unloader.name = เครื่องถ่ายบล็อก -block.interplanetary-accelerator.name = เครื่องส่งจรวดระหว่างดาวเคราะห์ block.switch.name = สวิตช์ block.micro-processor.name = ตัวประมวลผลขนาดเล็ก @@ -1343,11 +1347,12 @@ hint.desktopPause = กด [accent][[Space][] เพื่อหยุดชั hint.placeDrill = เลือกเมนู \ue85e [accent]เครื่องขุด[] ในแท็บเมนูขวาล่าง แล้วเลือก \uf870 [accent]เครื่องขุด[] แล้วกดที่แร่ทองแดงเพื่อวาง hint.placeDrill.mobile = เลือกเมนู \ue85e [accent]เครื่องขุด[] ในแท็บเมนูขวาล่าง แล้วเลือก \uf870 [accent]เครื่องขุด[] แล้วกดที่แร่ทองแดงเพื่อวาง\n\nกด \ue800 [accent]ติ้กถูก[] ที่ขวาล่างเพื่อยืนยัน hint.placeConveyor = สายพานจะย้ายไอเท็มจากเครื่องขุดไปยังบล็อกอื่นๆ เลือก \uf896 [accent]สายพาน[] จากแท็บ \ue814 [accent]การเคลื่อนย้าย[]\n\nคลิ๊กแล้วลากเพื่อวางหลายๆ สายพาน\n[accent]เลื่อน[]เพื่อหมุน -hint.placeConveyor.mobile = สายพานจะเคลื่อนย้ายไอเท็มจากที่ขุดไปยังบล็อกอื่นๆ เลือก \uf896 [accent]สายพาน[] จากแท็บ \ue814 [accent]การเคลื่อนย้าย[]\n\nเอานิ้วจิ้มลงไปสักแป็บนึงแล้วลากเพื่อวางหลายๆ อัน +hint.placeConveyor.mobile = สายพานจะเคลื่อนย้ายไอเท็มจากที่ขุดไปยังบล็อกอื่นๆ เลือก \uf896 [accent]สายพาน[] จากแท็บ \ue814 [accent]การเคลื่อนย้าย[]\n\nเอานิ้วจิ้มลงไปสักแป๊บนึงแล้วลากเพื่อวางหลายๆ อัน hint.placeTurret = วาง \uf861 [accent]ป้อมปืน[] เพื่อป้องกันฐานทัพจากศัตรู\n\nป้อมปืนต้องมีกระสุน ในกรณีนี้ \uf838 ทองแดง\nใช้สายพานลากจากเครื่องขุดไปที่ป้อมปืนเพื่อเติมกระสุน hint.breaking = [accent]คลิ๊กขวา[] แล้วลากเพื่อทำลายบล็อก -hint.breaking.mobile = เปิดใช้ \ue817 [accent]ค้อน[] ตรงล่างขวาแล้วเลือกเพื่อทำลายบล็อก\n\nเอานิ้วจิ้มลงไปสักแป็บนึงแล้วลากเพื่อเลือกหลายๆ อัน +hint.breaking.mobile = เปิดใช้ \ue817 [accent]ค้อน[] ตรงล่างขวาแล้วเลือกเพื่อทำลายบล็อก\n\nเอานิ้วจิ้มลงไปสักแป๊บนึงแล้วลากเพื่อเลือกหลายๆ อัน hint.blockInfo = ดูข้อมูลของบล็อกโดยการเลือกจาก[accent]เมนูการสร้าง[] แล้วกดที่รูป [accent][[?][] ตรงด้านขวา +hint.derelict = สิ่งก่อสร้างที่ถูก[accent]ทิ้งร้าง[]คือเศษซากพังทลายของฐานเก่าแก่ที่ไม่สามารถใช้งานได้แล้ว\n\nสิ่งก่อสร้างพวกนี้สามารถ[accent]ทุบทิ้ง[]เพื่อเก็บเกี่ยวทรัพยากรที่อยู่ในนั้นได้ hint.research = ใช้ปุ่ม \ue875 [accent]วิจัย[] เพื่อวิจัยเทคโนโลยีใหม่ๆ hint.research.mobile = ใช้ปุ่ม \ue875 [accent]วิจัย[] ใน \ue88c [accent]เมนู[] เพื่อวิจัยเทคโนโลยีใหม่ๆ hint.unitControl = กด [accent][[L-Ctrl][] ค้างไว้แล้วกด[accent]คลิ๊ก[]เพื่อควบคุมยานพวกพ้องหรือป้อมปืน @@ -1361,12 +1366,12 @@ hint.boost = กด [accent][[L-Shift][] เพื่อบูสต์ข้า hint.command = กด [accent][[G][] เพื่อสั่งการยูนิตข้างๆ ของตัว[accent]ชนิดคล้ายกัน[]จัดเป็นรูปแบบล้อมรอบคุณ\n\nถ้าจะสั่งการยูนิตพื้นดิน คุณต้องควบคุมยูนิตประเภทเดียวกันอยู่ก่อน hint.command.mobile = [accent][[กดสองครั้ง][] ที่ตัวยูนิตของคุณเพื่อสั่งการยูนิตรอบข้างให้มารวมตัวกันเป็นวงล้อมรอบคุณ hint.payloadPickup = กด [accent][[[] เพื่อหยิบบล็อกเล็กๆ หรือยูนิต -hint.payloadPickup.mobile = [accent]กดค้างไว้[] ที่บล็อกเล็กๆ หรือตัวยูนิตเพื่อหยิบขึ้นมา +hint.payloadPickup.mobile = [accent]กดค้างไว้[]ที่บล็อกเล็กๆ หรือตัวยูนิตเพื่อหยิบขึ้นมา hint.payloadDrop = กด [accent]][] เพื่อปล่อยสิ่งที่บรรทุกอยู่ hint.payloadDrop.mobile = [accent]กดค้างไว้[]ที่พื้นที่โล่งๆ เพื่อปล่อยสิ่งที่บรรทุกอยู่ -hint.waveFire = ป้อมปืน[accent]คลื่นน้ำ[]หากมีน้ำเป็นกระสุนจะช่วยดับไฟรอบข้างให้อัตโนมัติ +hint.waveFire = ป้อมปืน[accent]คลื่นน้ำ[]หากเติมน้ำเข้าไปจะช่วยดับไฟรอบข้างให้อัตโนมัติ hint.generator = \uf879 [accent]เครื่องกำเนิดไฟฟ้าเผาไหม้[]จะเผาถ่านและส่งพลังงานไปยังบล็อกที่อยู่ใกล้ๆ\n\nระยะของพลังงานสามารถขยายได้ด้วย \uf87f [accent]ตัวจ่ายพลังงาน[] -hint.guardian = หน่วย[accent]การ์เดียน[]มีเกราะป้องกันหนาแน่น กระสุนเปราะบางอย่าง[accent]ทองแดง[]และ[accent]ตะกั่ว[][scarlet]ไม่มีประสิทธิภาพ[]\n\nควรใช้ป้อมปืนที่ดีกว่านี้หรือใช้ \uf835 [accent]กราไฟท์[]ใน \uf861ดูโอ/\uf859ซัลโวเป็นกระสุนเพื่อทำลายการ์เดียน +hint.guardian = หน่วย[accent]การ์เดียน[]มีเกราะป้องกันหนาแน่น กระสุนเปราะบางอย่าง[accent]ทองแดง[]และ[accent]ตะกั่ว[][scarlet]ไม่มีประสิทธิภาพ[]\n\nควรใช้ป้อมปืนที่ดีกว่านี้หรือใช้ \uf835 [accent]กราไฟท์[]ใส่ใน \uf861 ดูโอ/ \uf859 ซัลโวเป็นกระสุนเพื่อทำลายการ์เดียน hint.coreUpgrade = สามารถอัพเกรดแกนกลางได้โดย[accent]วางแกนกลางที่ใหญ่กว่าทับมัน[]\n\nวาง  [accent]แกนกลาง: ฟาวน์เดชั่น[]ทับ  [accent]แกนกลาง: ชาร์ด[] ต้องแน่ใจว่ารอบข้างมีที่ว่างก่อนจะวาง hint.presetLaunch = [accent]เซ็กเตอร์ลงจอด[]สีเทา อย่างเช่น[accent]ป่าหนาวแหน็บ[] สามารถลงจอดจากที่ไหนที่ได้ในแผนที่ พวกนั้นไม่จำเป็นต้องยืดครองเซ็กเตอร์รอบข้างเพื่อส่งแกนกลางไป\n\n[accent]เซ็กเตอร์ที่มีเลข[] อย่างเช่นอันนี้[accent]ไม่จำเป็น[]ต้องยืดครอง hint.coreIncinerate = เมื่อแกนกลางมีจำนวนไอเท็มชนิดหนึ่งที่เต็ม ไอเท็มชนิดนั้นที่เข้ามาเพิ่มจะ[accent]ถูกเผา[] @@ -1386,9 +1391,9 @@ item.titanium.description = ใช้อย่างแพร่หลายใ item.titanium.details = โลหะเบาซึ่งหายากตามธรรมชาติ เป็นโลหะที่แข็งแรงใช้ได้ จึงใช้กันอย่างแพร่หลายในการแปรรูปหรือสิ่งก่อสร้าง item.thorium.description = ใช้ในการเสริมเกราะของสิ่งก่อสร้างต่างๆ หรือนำไปเป็นเป็นเชื้อเพลิงนิวเคลียร์ item.thorium.details = แร่ธาตุที่หาได้ยากมากในธรรมชาติ เป็นแร่ธาตุที่ทั้งแข็งแกร่งและหนาแน่น จึงใช้กันอย่างแพร่หลายในสิ่งก่อสร้างคงทน มีคุณสมบัติพิเศษคือกัมมันตภาพรังสี ทำให้แร่ธาตุนี้อาจเป็นภัยหากใช้ในทางที่ผิด -item.scrap.description = ใช้ในเตาหลอมแร่และเครื่องบดเพื่อเปลี่ยนเป็นวัสดุอื่นๆ +item.scrap.description = ใช้ในเตาหลอมแร่และเครื่องบดอัดเพื่อเปลี่ยนเป็นวัสดุอื่นๆ item.scrap.details = เศษที่เหลือจากสิ่งก่อสร้างและยูนิตเก่า มีร่องรอยของโลหะหลายชนิดอยู่ เกิดจากฐานทัพโบราณในสมัยสงครามเก่าแก่ถูกทำลาย ทำให้วัสดุต่างๆ พังลงมารวมกับ -item.silicon.description = ใช้ในแผงโซล่าเซลล์ อุปกรณ์อิเล็กทรอนิกที่ซับซ้อนหรือนำไปเป็นกระสุนติดตามตัวสำหรับป้อมปืน +item.silicon.description = ใช้ในแผงโซล่าเซลล์ อุปกรณ์อิเล็กทรอนิกที่ซับซ้อน\nหรือนำไปเป็นกระสุนติดตามตัวสำหรับป้อมปืน item.silicon.details = วัสดุกึ่งตัวนำที่มีประโยชน์มาก ผลิตจากการเผาทรายและถ่านหินเข้าด้วยกัน ใช้ในสิ่งก่อสร้างแทบทุกชนิดตั้งแต่ต้นเกมยันปลายเกม จึงควรผลิตวัสดุนี้ให้เยอะที่สุด item.plastanium.description = ใช้ในอากาศยานขั้นสูง เป็นฉนวนกันความร้อนหรือนำไปเป็นกระสุนกระจาย item.plastanium.details = วัสดุที่เบาและดัดได้ ผลิตจากการอัดไทเทเนี่ยมและน้ำมันเข้าด้วยกัน @@ -1410,13 +1415,14 @@ liquid.oil.details = ของเหลวเฉื่อยพบได้ไ liquid.cryofluid.description = ใช้ในการหล่อเย็นเตาปฏิกร สิ่งก่อสร้างหรือโรงงานต่างๆ liquid.cryofluid.details = ของเหลวเฉื่อยและไม่กัดกร่อน ผลิตจากน้ำและไทเทเนี่ยม มีคุณสมบัติการถ่ายเทความร้อนสูง -block.resupply-point.description = เติมกระสุนยูนิตรอบข้างด้วยกระสุนทองแดง ใช้ไม่ได้กับยูนิตที่ใช้พลังงานเป็นกระสุน +block.derelict = [lightgray] ถูกทิ้งร้าง +block.resupply-point.description = เติมกระสุนยูนิตรอบข้างด้วยกระสุนทองแดง ใช้กับยูนิตที่ใช้พลังงานเป็นกระสุนไม่ได้ block.armored-conveyor.description = เลื่อนไอเท็มไปข้างหน้า เร็วเท่าสายพานไทเทเนี่ยม แต่มีเกราะที่แข็งแรงกว่า ไม่รับไอเท็มจากด้านข้างยกเว้นเป็นสายพานชนิดเดียวกัน block.illuminator.description = ตัวเปล่งแสงขนาดกะทัดรัด ส่องสว่างในที่มืดได้ดี\nแถมยังกำหนดสีของแสงได้ด้วย... เจ๋งใช่มั้ยล่ะ block.message.description = เก็บข้อความ ใช้สื่อสารกับพันธมิตร block.graphite-press.description = อัดก้อนถ่านหินให้เป็นแผ่นกราไฟต์บริสุทธิ์ block.multi-press.description = อัดก้อนถ่านหินให้เป็นแผ่นกราไฟต์บริสุทธิ์ ใช้น้ำและพลังงานในการแปรรูปถ่านหินให้เร็วและมีประสิทธิภาพมากขึ้น -block.silicon-smelter.description = ผลิตซิลิกอนจากทรายและถ่านหินบริสุทธิ์ +block.silicon-smelter.description = ผลิตซิลิกอนจากการหลอมทรายและถ่านหินเข้าด้วยกัน block.kiln.description = เผาทรายและตะกั่วเป็นกระจกเมต้า block.plastanium-compressor.description = บีบอัดน้ำมันและไทเทเนี่ยมเข้าด้วยกันเพื่อผลิตพลาสตาเนี่ยม block.phase-weaver.description = สังเคราะห์ใยเฟสจากทรายและทอเรี่ยม ใช้พลังงานจำนวนมากในการทำงาน @@ -1524,22 +1530,22 @@ block.duo.description = ป้อมปืนขนาดเล็ก ยิง block.scatter.description = ยิงก้อนตะกั่ว เศษเหล็กหรือกระจกเมต้าใส่ยานบินศัตรูที่อยู่ใกล้เคียง block.scorch.description = เผาศัตรูพื้นดินที่อยู่ใกล้ๆ มีประสิทธิภาพสูงสุดเมื่อใช้ในระยะใกล้ block.hail.description = ป้อมปืนใหญ่ขนาดย่อม ยิงลูกระเบิดใส่ศัตรูพื้นดินจากระยะไกล -block.wave.description = ป้อมปืนขนาดกลาง พ่นของเหลวสาดใส่ศัตรู จะดับไฟให้อัตโนมัติเมื่อใส่น้ำเข้าไป -block.lancer.description = ป้อมปืนเลเซอร์ต่อต้านพื้นดินขนาดกลาง ชาร์จและยิงลำแสงพลังงานอันทรงพลังใส่ศัตรู -block.arc.description = ป้อมปืนไฟฟ้าระยะใกล้ ยิงสายฟ้าใส่ศัตรูพื้นดิน จะทำดาเมจมหาศาลเมื่อศัตรูเปียกน้ำ -block.swarmer.description = ป้อมยิงขีปนาวุธขนาดกลาง ยิงขีปนาวุธติดตามตัวใส่ศัตรูทั้งอากาศและพื้นดิน +block.wave.description = พ่นของเหลวสาดใส่ศัตรู จะดับไฟให้อัตโนมัติเมื่อใส่น้ำเข้าไป +block.lancer.description = ชาร์จแล้วยิงลำแสงพลังงานอันทรงพลังใส่ศัตรูพื้นดิน +block.arc.description = ยิงสายฟ้าใส่ศัตรูพื้นดิน จะทำดาเมจมหาศาลเมื่อศัตรูเปียกน้ำ +block.swarmer.description = ยิงขีปนาวุธติดตามตัวใส่ศัตรูทั้งอากาศและพื้นดิน block.salvo.description = ป้อมปืนขนาดกลาง ระดมยิงกระสุนหนักใส่ศัตรูอย่างรวดเร็ว -block.fuse.description = ป้อมปืนระยะใกล้ขนาดใหญ่ ยิงลำแสงเจาะทะลุสามเส้นใส่ศัตรูที่อยู่ใกล้เคียง -block.ripple.description = ป้อมปืนใหญ่พลังงานสูง ยิงกระจุกของลูกระเบิดใส่ศัตรูพื้นดินจากระยะไกล -block.cyclone.description = ป้อมปืนต่อต้านทั้งอากาศยานและพื้นดิน ยิงกระสุนเป็นกระจุกระเบิดใส่ยูนิตศัตรูอย่างรวดเร็ว +block.fuse.description = ป้อมปืนระยะใกล้ขนาดใหญ่ ยิงลำแสงเจาะทะลุสามแฉกใส่ศัตรูที่อยู่ใกล้เคียง +block.ripple.description = ป้อมปืนใหญ่ทรงพลัง ยิงลูกระเบิดเป็นกระจุกใส่ศัตรูพื้นดินจากระยะไกล +block.cyclone.description = ป้อมปืนรวดเร็วดั่งพายุ ยิงก้อนสะเก็ดระเบิดใส่ยูนิตศัตรูอย่างรวดเร็ว block.spectre.description = ปืนใหญ่คู่ขนาดยักษ์ ยิงกระสุนเจาะเกราะใส่ศัตรูทั้งบนอากาศและพื้นดิน block.meltdown.description = ชาร์จแล้วยิงลำแสงเลเซอร์ใส่ศัตรูที่อยู่ใกล้เคียงอย่างต่อเนื่อง ต้องมีของเหลวมาหล่อเย็นป้อมปืนเพื่อทำงาน block.foreshadow.description = ป้อมปืนเรลกันขนาดมหึมา ยิงลำแสงพลังงานใส่เป้าหมายเดี่ยวขนาดใหญ่\nมีระยะการยิงไกลมาก จะเลือกยิงยูนิตที่มีพลังชีวิตมากที่สุดก่อน -block.repair-point.description = ซ่อมแซมยูนิตที่อยู่ในรัศมีอย่างต่อเนื่อง +block.repair-point.description = ซ่อมแซมยูนิตที่อยู่ในรัศมีของมันอย่างต่อเนื่อง block.segment.description = สร้างความเสียหายและทำลายกระสุนที่กำลังเข้ามา ไม่สามารถทำลายลำแสงเลเซอร์ได้ block.parallax.description = ยิงลำแสงที่ดึงยานบินศัตรูเข้าหา สร้างความเสียหายแก่พวกมันระหว่างทาง block.tsunami.description = ยิงกระแสของเหลวอันทรงพลังใส่ศัตรู จะดับไฟให้อัตโนมัติเมื่อใส่น้ำเข้าไป -block.silicon-crucible.description = หลอมซิลิกอนจากทรายและถ่าน ใช้ไพราไทต์เป็นแหล่งความร้อนเพิ่มเติม ทำงานเร็วกว่าถ้าตั้งอยู่ในพื้นที่ร้อน +block.silicon-crucible.description = หลอมซิลิกอนจากทรายและถ่านหิน ใช้ไพราไทต์เป็นแหล่งความร้อนเพิ่มเติม จะทำงานเร็วกว่าถ้าตั้งอยู่ในพื้นที่ร้อน block.disassembler.description = แยกแร่หลอมออกเป็นแร่ธาตุปริมาณเล็กน้อยโดยมีประสิทธิภาพต่ำ สามารถผลิตทอเรี่ยมได้ block.overdrive-dome.description = เร่งประสิทธิภาพสิ่งก่อสร้างรอบข้างอย่างมหาศาล ต้องมีใยเฟสกับซิลิกอนเพื่อทำงาน block.payload-conveyor.description = เคลื่อนย้ายสิ่งของบรรทุกหนัก อย่างเช่นยูนิต @@ -1561,6 +1567,8 @@ block.memory-bank.description = เก็บข้อมูลเป็นตั block.logic-display.description = แสดงกราฟิกโดยควบคุมจากตัวประมวลผลลอจิก block.large-logic-display.description = แสดงกราฟิกโดยควบคุมจากตัวประมวลผลลอจิก มีขนาดใหญ่กว่า block.interplanetary-accelerator.description = หอคอยเรลกันแม่เหล็กไฟฟ้าขนาดมหึมา เร่งความเร็วแกนกลางเพื่อบินสู่อวกาศไปยังดาวเคราะห์อื่นๆ +block.repair-turret.description = ซ่อมแซมยูนิตที่อยู่ในรัศมีของมันอย่างต่อเนื่อง สามารถใช้ของเหลวมาหล่อเย็นเพื่อเพิ่มประสิทธิภาพได้ +block.payload-propulsion-tower.description = บล็อกขนส่งสิ่งบรรทุกทางไกล\nยิงสิ่งบรรทุกไปยังหอเคลื่อนย้ายสิ่งบรรทุกอีกเครื่องที่เชื่อมต่อไว้ unit.dagger.description = ยิงกระสุนธรรมดาใส่ศัตรูที่อยู่ใกล้เคียง unit.mace.description = ยิงเปลวไฟใส่ศัตรูที่อยู่ใกล้เคียง ทำให้ศัตรูถูกเผาไหม้ @@ -1595,6 +1603,11 @@ unit.omura.description = ยิงลำแสงปืนเรลกันเ unit.alpha.description = ปกป้องแกนกลางชาร์ดจากศัตรู สร้างสิ่งต่างๆ unit.beta.description = ปกป้องแกนกลางฟาวน์เดชั่นจากศัตรู สร้างสิ่งต่างๆ unit.gamma.description = ปกป้องแกนกลางนิวเคลียสจากศัตรู สร้างสิ่งต่างๆ +unit.retusa.description = วางทุ่นระเบิดระยะใกล้ ซ่อมแซมยูนิตพวกพ้องที่อยู่ใกล้เคียง +unit.oxynoe.description = ยิงเปลวไฟเผาไหม้ใส่ศัตรูที่อยู่ใกล้เคียงและซ่อมแซมสิ่งก่อสร้างของพวกพ้อง\nทำลายกระสุนที่กำลังเข้ามาด้วยปืนป้องกันจุด +unit.cyerce.description = ยิงขีปนาวุธพลาสม่าติดตามตัวเป็นกระจุกระเบิดใส่ศัตรู\nซ่อมแซมยูนิตพวกพ้องที่อยู่ใกล้เคียง +unit.aegires.description = ช็อตทุกสิ่งก่อสร้างและยูนิตศัตรูที่เข้ามาในสนามพลังงานของมัน\nซ่อมแซมสิ่งก่อสร้างและยูนิตพวกพ้อง +unit.navanax.description = ยิงลูกระเบิดคลื่นชีพจรแม่เหล็กขนาดใหญ่ สร้างความเสียหายอย่างหนักให้กับเครือข่ายพลังงานศัตรู\nและซ่อมแซมสิ่งก่อสร้างของพวกพ้อง\nหลอมละลายศัตรูที่อยู่ใกล้เคียงด้วยป้อมปืนเลเซอร์อัตโนมัติสี่ป้อม lst.read = อ่านเลขจากเซลล์ความจำที่เชื่อมต่อไว้ lst.write = เขียนเลขไปยังเซลล์ความจำที่เชื่อมต่อไว้ From 108baa467dcf7be4105d34937133e69ed073577f Mon Sep 17 00:00:00 2001 From: Sharlotte <60801210+Sharlottes@users.noreply.github.com> Date: Wed, 28 Jul 2021 23:44:44 +0900 Subject: [PATCH 035/130] Update bundle_ko.properties (#5604) * Update bundle_ko.properties * Update bundle_ko.properties * Update bundle_ko.properties * halha * Update bundle_ko.properties --- core/assets/bundles/bundle_ko.properties | 32 ++++++++++++++++-------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 4c68f6efef..27ec3beb4c 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -122,7 +122,6 @@ committingchanges = 바뀐 점 적용 done = 완료 feature.unsupported = 기기가 이 기능을 지원하지 않습니다. -mods.initfailed = [red]⚠[]이전 Mindustry 인스턴스를 초기화하지 못했습니다. 잘못된 모드로 인해 발생한 것일 수 있습니다.\n\n 게임 충돌 무한반복을 막기 위해, [red]모든 모드가 비활성화되었습니다.[]\n\n이 시스템을 비활성화할려면, [accent]설정->게임->로딩 중 충돌 시 모드 비활성화[]설정을 끄세요. mods = 모드 mods.none = [lightgray]모드를 찾을 수 없습니다! mods.guide = 모드 제작 가이드 @@ -566,6 +565,7 @@ sectors.unexplored = [lightgray]미개척지 sectors.resources = 자원: sectors.production = 생산량: sectors.export = 수출량: +sectors.import = 수입량: sectors.time = 진행 시간: sectors.threat = 위험도: sectors.wave = 단계: @@ -725,7 +725,7 @@ stat.maxconsecutive = 최대 체인 stat.buildcost = 건설 비용 stat.inaccuracy = 오차각 stat.shots = 발사 수 -stat.reload = 초당 발사 수 +stat.reload = 발사 주기 stat.ammo = 탄약 stat.shieldhealth = 보호막 내구도 stat.cooldowntime = 쿨타임 @@ -794,7 +794,7 @@ bullet.damage = [stat]{0}[lightgray] 피해량 bullet.splashdamage = [stat]{0}[lightgray] 범위 피해량 ~ [stat]{1}[lightgray] 타일 bullet.incendiary = [stat]방화 bullet.homing = [stat]유도 -bullet.frag = [stat]파편 +bullet.frags = [stat]{0}[lightgray]개 파편 탄환: bullet.lightning = [stat]{0}[lightgray]x 전격 ~ [stat]{1}[lightgray] 피해량 bullet.buildingdamage = [stat]{0}%[lightgray] 건물 피해량 bullet.knockback = [stat]{0}[lightgray] 넉백 @@ -846,7 +846,6 @@ setting.doubletapmine.name = 연속 터치로 채광 setting.modcrashdisable.name = 로딩 중 충돌 시 모드 비활성화 setting.animatedwater.name = 액체 애니메이션 효과 setting.animatedshields.name = 보호막 애니메이션 효과 -setting.antialias.name = 위신호 제거 필터[lightgray] (재시작 필요)[] setting.playerindicators.name = 플레이어 위치 표시기 setting.indicators.name = 적 위치 표시기 setting.autotarget.name = 자동 조준 @@ -855,7 +854,8 @@ setting.touchscreen.name = 터치스크린 조작 setting.fpscap.name = 최대 FPS setting.fpscap.none = 없음 setting.fpscap.text = {0} FPS -setting.uiscale.name = UI 스케일링[lightgray] (재시작 필요)[] +setting.uiscale.name = UI 스케일링 +setting.uiscale.description = 적용하려면 재시작이 필요합니다. setting.swapdiagonal.name = 항상 대각선 배치 setting.difficulty.training = 훈련 setting.difficulty.easy = 무난 @@ -873,7 +873,8 @@ setting.saveinterval.name = 저장 간격 setting.seconds = {0} 초 setting.milliseconds = {0} 밀리초 setting.fullscreen.name = 전체 화면 -setting.borderlesswindow.name = 테두리 없는 창 모드[lightgray] (재시작이 필요할 수 있습니다) +setting.borderlesswindow.name = 테두리 없는 창 모드 +setting.borderlesswindow.description = 적용하려면 재시작이 필요할 수도 있습니다. setting.fps.name = FPS와 핑 표시 setting.smoothcamera.name = 부드러운 시점 setting.vsync.name = 수직 동기화 @@ -996,6 +997,7 @@ rules.wavetimer = 시간 제한이 있는 단계 rules.waves = 단계 rules.attack = 공격 모드 rules.buildai = AI 건설 +rules.cleanupdeadteams = 패배한 팀 건물 정리하기 (PvP) rules.corecapture = 코어 파괴 시 점령 rules.polygoncoreprotection = 다각형 코어 건설 금지구역 rules.enemyCheat = 적Ai 무한자원 @@ -1047,7 +1049,7 @@ item.silicon.name = 실리콘 item.plastanium.name = 플라스터늄 item.phase-fabric.name = 메타 item.surge-alloy.name = 설금 -item.spore-pod.name = 포자 +item.spore-pod.name = 포자 꼬투리 item.sand.name = 모래 item.blast-compound.name = 폭발물 item.pyratite.name = 파이라타이트 @@ -1290,7 +1292,6 @@ block.meltdown.name = 멜트다운 block.foreshadow.name = 포어쉐도우 block.container.name = 컨테이너 block.launch-pad.name = 지역 자원 수송기 -block.launch-pad-large.name = 대형 지역 자원 수송기 block.segment.name = 세그먼트 block.command-center.name = 유닛 지휘소 block.ground-factory.name = 지상 공장 @@ -1311,11 +1312,11 @@ block.payload-source.name = 화물 공급기 block.disassembler.name = 광재 분해기 block.silicon-crucible.name = 실리콘 도가니 block.overdrive-dome.name = 대형 과부하 프로젝터 +block.interplanetary-accelerator.name = 성간 코어 가속기 #experimental, may be removed / 이 아래의 블록들은 테스트용 임시 블록들이였습니다. block.block-forge.name = 블록 제작대 block.block-loader.name = 블록 로더 block.block-unloader.name = 블록 언로더 -block.interplanetary-accelerator.name = 성간 코어 가속기 block.switch.name = 스위치 block.micro-processor.name = 마이크로 프로세서 @@ -1350,6 +1351,7 @@ hint.placeTurret = 적에게서 기지를 막아내려면 \uf861 [accent]포탑[ hint.breaking = 블록을 부수려면 [accent]우클릭[]이나 드래그를 하십시오. hint.breaking.mobile = 블록을 부수려면 오른쪽 아래의 \ue817 [accent]망치[]를 눌러 해체 모드를 활성화하십시오.\n\n손가락으로 누른 채로 끌어서 해체 범위를 지정하십시오. hint.blockInfo = [accent]건설 메뉴[]에서 블록을 선택해서 정보를 보십시오, 그다음 오른쪽의 [accent][[?][] 버튼을 선택하십시오. +hint.derelict = [accent]버려진[] 구조물들은 더 이상 작동하지 않는 오래된 기지의 부서진 잔해입니다.\n\n이 구조물들은 자원으로 다시 [accent]철거[]될 수 있습니다. hint.research = 새 기술을 연구하려면 \ue875 [accent]연구[]버튼을 누르십시오. hint.research.mobile = 새 기술을 연구하려면 \ue88c [accent]메뉴[] 아래의 \ue875 [accent]연구[]버튼을 누르십시오. hint.unitControl = 아군 유닛과 포탑을 조종하려면 [accent][[왼쪽 ctrl][]을 누른 채로 [accent]클릭[] 하십시오. @@ -1401,6 +1403,7 @@ liquid.slag.description = 다양한 종류의 금속들이 함께 섞여 녹아 liquid.oil.description = 고급 재료 생산에 사용되는 액체. 석탄으로 전환하거나 무기로 뿌려서 불을 지를 수 있습니다. liquid.cryofluid.description = 물과 티타늄으로 만든 비부식성 액체. 열용량이 매우 높으며 냉각수로 광범위하게 사용됩니다. +block.derelict = [lightgray] 버려짐[] block.resupply-point.description = 주변 유닛들에 구리 탄약을 보급합니다. 배터리 전력이 필요한 유닛들은 호환되지 않습니다. block.armored-conveyor.description = 앞으로 자원들을 운반합니다. 측면에서 자원들을 받아들이지 않습니다. block.illuminator.description = 발광합니다. @@ -1545,6 +1548,8 @@ block.memory-bank.description = 프로세서를 위한 데이터를 저장합니 block.logic-display.description = 프로세서를 이용해 그래픽을 출력할 수 있습니다. block.large-logic-display.description = 프로세서를 이용해 그래픽을 출력할 수 있습니다. block.interplanetary-accelerator.description = 거대한 전자기 레일건 타워. 코어를 행성 간 이동을 위한 탈출 속도까지 가속합니다. +block.repair-turret.description = 가장 가까운 유닛을 지속적으로 수리합니다. 냉각수를 넣을 수 있습니다. +block.payload-propulsion-tower.description = 장거리 화물 운반 구조물. 화물을 연결된 다른 화물 추진탑으로 발사합니다. unit.dagger.description = 주변 모든 적에게 일반적인 탄환을 발사합니다. unit.mace.description = 주변 모든 적에게 화염 줄기를 발사합니다. @@ -1579,6 +1584,11 @@ unit.omura.description = 적에게 장거리 관통 레일건을 발사합니다 unit.alpha.description = 적으로부터 코어: 조각을 방어합니다. 구조물을 짓습니다. unit.beta.description = 적으로부터 코어: 기반을 방어합니다. 구조물을 짓습니다. unit.gamma.description = 적으로부터 코어: 핵심을 방어합니다. 구조물을 짓습니다. +unit.retusa.description = 근접 시한지뢰를 설치합니다. 아군 유닛을 수리할 수 있습니다. +unit.oxynoe.description = 주변 적에게 블록을 수리하는 화염을 발사합니다. 주변 적 탄환을 요격 포탑으로 요격할 수 있습니다. +unit.cyerce.description = 주변 적에게 유도 집속 미사일을 발사합니다. 아군 유닛을 수리할 수 있습니다. +unit.aegires.description = 애너지 필드 안의 모든 적 유닛과 블록을 감전시킵니다. 아군에겐 전격으로 수리합니다. +unit.navanax.description = 적 전력망에 상당한 피해를 주고 아군 블록을 수리하는 거대한 EMP 고폭탄을 발사합니다. 4개의 자율 레이저 포탑으로 주변 적을 녹입니다. lst.read = 연결된 메모리 셀에서 숫자 읽기 lst.write = 연결된 메모리 셀에 숫자 쓰기 @@ -1631,7 +1641,7 @@ lenum.always = 항상 참 lenum.idiv = 정수 나누기 lenum.div = 나누기\n0으로 나누면 [accent]null[]을 반환합니다. lenum.mod = 나머지 -lenum.equal = 동치 비교. 형변환 가능\nNull이 아닌 객체가 숫자와 비교할려면 1이 되고, Null이면 0이 됩니다. +lenum.equal = 동치 비교. 형변환 가능\nNull이 아닌 객체가 숫자와 비교하려면 1이 되고, Null이면 0이 됩니다. lenum.notequal = 동치 부정. 형변환 가능 lenum.strictequal = 엄격한 동치 비교. 형변환 불가능\n[accent]null[]를 확인하는데 쓸 수 있습니다. lenum.shl = 왼쪽으로 비트 이동 @@ -1818,7 +1828,7 @@ block.inverted-sorter.details = block.distributor.details = block.overflow-gate.details = block.underflow-gate.details = -block.mass-driver.details = [lightgray][비공식][]발사할려면 최소 아이템 10개가 필요하다. +block.mass-driver.details = [lightgray][비공식][]발사하려면 최소 아이템 10개가 필요하다. block.mechanical-pump.details = block.rotary-pump.details = block.thermal-pump.details = From a97573c5a973de8795cf0b369a6d64164a4b2819 Mon Sep 17 00:00:00 2001 From: VizardAlpha <43859764+VizardAlpha@users.noreply.github.com> Date: Wed, 28 Jul 2021 16:45:02 +0200 Subject: [PATCH 036/130] Updates bundle_fr.properties (#5611) * Updates bundle_fr.properties Add and translate. Commits on Jul 13, 2021 Commits on Jul 17, 2021 Commits on Jul 18, 2021 * Minor. Correcting translation errors * Add commit * Add commit * Add new commit Translation not finish; unit.oxynoe.description = Fires structure-repairing streams of flame at nearby enemies. Targets nearby enemy projectiles with a point defense turret. * Translation finish * Added hint & tooltip for derelict structures * Correction of an error hint.placeTurret = Placez des \fuf861 -> hint.placeTurret = Placez des \uf861 * Fixed #5645 servers.local.steam = Open Games & Serveurs Locaux Not finish * Removed flow rate option --- core/assets/bundles/bundle_fr.properties | 36 ++++++++++++++++-------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index 942ae5c750..4f75f0d673 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -101,6 +101,7 @@ customgame = Partie personnalisée newgame = Nouvelle partie none = none.found = [lightgray] +none.inmap = [lightgray] minimap = Mini-carte position = Position close = Fermer @@ -214,6 +215,7 @@ hosts.none = [lightgray]Aucune partie en LAN trouvée ! host.invalid = [scarlet]Impossible de se connecter à l'hôte. servers.local = Serveurs locaux +servers.local.steam = Open Games & Serveurs Locaux servers.remote = Serveurs distants servers.global = Serveurs communautaires @@ -725,7 +727,7 @@ stat.maxconsecutive = Max Consécutif stat.buildcost = Coût de construction stat.inaccuracy = Précision stat.shots = Tirs -stat.reload = Tirs/Seconde +stat.reload = Cadence de tir stat.ammo = Munitions stat.shieldhealth = Santé du bouclier stat.cooldowntime = Temps de refroidissement @@ -794,7 +796,8 @@ bullet.damage = [stat]{0}[lightgray] dégâts bullet.splashdamage = [stat]{0}[lightgray] dégâts de zone ~[stat] {1}[lightgray] blocs bullet.incendiary = [stat]incendiaire bullet.homing = [stat]autoguidé -bullet.frag = [stat]fragmentation +bullet.fragbullets = [stat]{0}[lightgray]x balles à fragmentation +bullet.frag.stats = [stat]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 @@ -841,14 +844,12 @@ setting.blockreplace.name = Suggestion automatique des Blocs setting.linear.name = Filtrage linéaire setting.hints.name = Astuces setting.logichints.name = Astuces pour les commandes des processeurs -setting.flow.name = Afficher le Débit des ressources setting.backgroundpause.name = Pause en Arrière-plan setting.buildautopause.name = Confirmation avant construction setting.doubletapmine.name = Double-clic pour Miner setting.modcrashdisable.name = Désactiver les mods lors d'un crash au démarrage setting.animatedwater.name = Surfaces Animées setting.animatedshields.name = Boucliers Animés -setting.antialias.name = Anticrénelage[lightgray] (redémarrage du jeu nécessaire)[] setting.playerindicators.name = Indicateurs alliés setting.indicators.name = Indicateurs ennemis setting.autotarget.name = Visée automatique @@ -857,7 +858,8 @@ setting.touchscreen.name = Commandes d'écran tactile setting.fpscap.name = Max FPS setting.fpscap.none = Illimité setting.fpscap.text = {0} FPS -setting.uiscale.name = Échelle de l'interface[lightgray] (redémarrage du jeu nécessaire)[] +setting.uiscale.name = Échelle de l'interface +setting.uiscale.description = Redémarrage du jeu nécessaire pour appliquer les changements. setting.swapdiagonal.name = Autoriser le placement en diagonale setting.difficulty.training = Entraînement setting.difficulty.easy = Facile @@ -875,7 +877,8 @@ setting.saveinterval.name = Intervalle des Sauvegardes automatiques setting.seconds = {0} secondes setting.milliseconds = {0} millisecondes setting.fullscreen.name = Plein Écran -setting.borderlesswindow.name = Fenêtre sans bords[lightgray] (peut nécessiter le redémarrage du jeu) +setting.borderlesswindow.name = Fenêtré sans bordures +setting.borderlesswindow.description = Un redémarrage peut être nécessaire pour appliquer les changements. setting.fps.name = Afficher FPS et Ping setting.smoothcamera.name = Lissage de la Caméra setting.vsync.name = Synchronisation Verticale @@ -1005,6 +1008,7 @@ rules.wavetimer = Compte à rebours des vagues rules.waves = Vagues rules.attack = Mode « Attaque » rules.buildai = Constructions de l'IA +rules.cleanupdeadteams = Détruire les structures des équipes vaincues (JcJ) rules.corecapture = Capture du Noyau lors de sa Destruction rules.polygoncoreprotection = Protection du noyau polygonal rules.enemyCheat = Ressources infinies pour l'IA (équipe rouge) @@ -1299,7 +1303,6 @@ block.meltdown.name = Fusion block.foreshadow.name = Présage block.container.name = Conteneur block.launch-pad.name = Rampe de lancement -block.launch-pad-large.name = Grande rampe de lancement block.segment.name = Diviseur block.command-center.name = Centre de Commande block.ground-factory.name = Usine d'Unités Terrestres @@ -1320,11 +1323,11 @@ block.payload-source.name = Source de Charge utile block.disassembler.name = Désassembleur 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 #experimental, may be removed block.block-forge.name = Forgeur de Blocs block.block-loader.name = Chargeur de Blocs block.block-unloader.name = Déchargeur de Blocs -block.interplanetary-accelerator.name = Accélérateur Interplanétaire block.switch.name = Interrupteur block.micro-processor.name = Micro Processeur @@ -1338,7 +1341,7 @@ block.memory-bank.name = Banque de mémoire team.blue.name = bleu team.crux.name = crux team.sharded.name = sharded -team.derelict.name = derelict +team.derelict.name = Vestige team.green.name = vert team.purple.name = mauve @@ -1357,8 +1360,9 @@ hint.placeConveyor = Les Convoyeurs transportent les ressources des foreuses ver hint.placeConveyor.mobile = Les Convoyeurs transportent les ressources des foreuses vers d'autres blocs. Sélectionnez un \uf896 [accent]Convoyeur[] dans l'onglet \ue814 [accent]Distribution[].\n\nMaintenez votre doigt et déplacez-le pour placer plusieurs convoyeurs. hint.placeTurret = Placez des \uf861 [accent]Tourelles[] pour défendre votre base contre les ennemis.\n\nLes Tourelles nécessitent des munitions (dans ce cas, du \uf838Cuivre).\nUtilisez les convoyeurs et les foreuses pour les ravitailler. hint.breaking = Maintenez [accent]Clic-droit[] pour détruire des blocs. -hint.breaking.mobile = Activez le \ue817 [accent]marteau[] en bas à droite Touchez pour détruire des blocs.\n\nRetenez votre doigt pendant une seconde et déplacez-le pour détruire les blocs dans la zone de sélection. +hint.breaking.mobile = Activez le \ue817 [accent]marteau[] en bas à droite, Touchez pour détruire des blocs.\n\nRetenez votre doigt pendant une seconde et déplacez-le pour détruire les blocs dans la zone de sélection. hint.blockInfo = Pour afficher les informations relatives à un bloc, il suffit de le sélectionner dans le [accent]menu de construction[], puis de cliquer sur le bouton [accent][[?][] à droite. +hint.derelict = [accent]Les structures abandonnées[] sont des vestiges brisés d'anciennes bases qui ne fonctionnent plus. Ces structures peuvent être [accent]déconstruites pour obtenir des ressources. hint.research = Utilisez le bouton \ue875 [accent]Recherche[] pour rechercher de nouvelles technologies. hint.research.mobile = Utilisez le bouton \ue875 [accent]Recherche[] dans le \ue88c [accent]Menu[] pour rechercher de nouvelles technologies. hint.unitControl = Retenez [accent][[Ctrl-gauche][] et [accent]cliquez[] pour contrôler une tourelle ou une unité alliée. @@ -1410,6 +1414,7 @@ liquid.slag.description = Différents types de métaux en fusion mélangés. Peu liquid.oil.description = Un liquide utilisé dans la production de matériaux avancés. Peut être transformé en charbon ou pulvérisé sur les ennemis, puis enflammé. liquid.cryofluid.description = Un liquide inerte, non corrosif, créé à partir d’eau et de titane. Possède une capacité d'absorption de chaleur extrêmement élevée. Largement utilisé comme liquide de refroidissement. +block.derelict = [lightgray] Vestiges block.resupply-point.description = Approvisionne les unités proches en munitions. Pas compatible avec celles qui ont besoin d'énergie pour tirer. block.illuminator.description = Une petite source lumineuse compacte et configurable. Nécessite de l'énergie pour fonctionner. block.armored-conveyor.description = Déplace les objets à la même vitesse que les convoyeurs en titane, mais est plus résistant. Seulement d'autres convoyeurs peuvent faire entrer des ressources par ses côtés. @@ -1518,7 +1523,7 @@ block.scatter.description = Une tourelle anti-aérienne essentielle. Mitraille l block.scorch.description = Brûle les ennemis terrestres près de lui. Très efficace à courte portée. block.hail.description = Une petite tourelle d'artillerie visant les ennemis terrestres. Efficace à longue portée. block.wave.description = Une tourelle de taille moyenne tirant un jet de liquide. Peut éteindre les incendies automatiquement si elle est alimentée en eau. -block.lancer.description = Une tourelle de taille moyenne chargeant et tirant de puissants lasers aux ennemis terrestres. +block.lancer.description = Une tourelle de taille moyenne chargeant et tirant de puissants lasers sur les ennemis terrestres. block.arc.description = Une petite tourelle tirant des arcs électriques sur les ennemis. block.swarmer.description = Une tourelle de taille moyenne attaquant les ennemis terrestres et aériens à l'aide de missiles autoguidés. Consomme beaucoup de munitions. block.salvo.description = Une version plus grande et améliorée de la tourelle Duo. Tire par salves. @@ -1531,7 +1536,7 @@ block.foreshadow.description = Une tourelle massive tirant une puissante balle s block.repair-point.description = Soigne l'unité endommagée la plus proche. block.segment.description = Endommage et détruit les tirs ennemis. Les lasers ne peuvent pas être ciblés. block.parallax.description = Tire un rayon tracteur qui attire les ennemis volants, infligeant aussi des dégâts. -block.tsunami.description = Tire un puissant jet de liquide aux ennemis. Peut éteindre les incendies automatiquement si elle est alimentée en eau. +block.tsunami.description = Tire un puissant jet de liquide sur les ennemis. Peut éteindre les incendies automatiquement si elle est alimentée en eau. block.silicon-crucible.description = Raffine du silicium avec du sable et du charbon en utilisant de la pyratite comme source de chaleur additionnelle. Cette usine est plus efficace dans les endroits chauds. block.disassembler.description = Cette version avancée du séparateur peut produire du thorium. block.overdrive-dome.description = Accélère le fonctionnement des bâtiments autour de lui. Requiert du silicium et du tissu phasé pour fonctionner. @@ -1554,6 +1559,8 @@ block.memory-bank.description = Stocke des informations pour un processeur logiq block.logic-display.description = Affiche des images à partir des instructions d'un processeur logique. block.large-logic-display.description = Affiche des images à partir des instructions d'un processeur logique. Possède une plus grande résolution qu'un écran. block.interplanetary-accelerator.description = Un énorme canon électromagnétique à rails. Accélère les Noyaux pour qu'ils échappent à la gravité de leur planète et leur permettent un déploiement interplanétaire. +block.repair-turret.description = Répare en continu l'unité endommagée la plus proche dans son périmètre. Accepte le liquide de refroidissement en option. +block.payload-propulsion-tower.description = Structure de transport de charges utiles à longue portée. Projette des charges utiles vers d'autres tours de propulsion de charges utiles reliées. unit.dagger.description = Tire des balles normales aux ennemis proches. unit.mace.description = Tire des jets de flammes aux ennemis proches. @@ -1588,6 +1595,11 @@ unit.omura.description = Tire avec un canon à rails à longue portée, une puis unit.alpha.description = Défend le Noyau fragment contre les ennemis. Peut construire des structures. unit.beta.description = Défend le Noyau fondation contre les ennemis. Peut construire des structures. unit.gamma.description = Défend le Noyau épicentre contre les ennemis. Peut construire des structures. +unit.retusa.description = Pose des mines de proximité. Répare les unités alliées. +unit.oxynoe.description = Tire des jets de flammes qui réparent les structures et endommage les ennemis proches. Cible les projectiles ennemis proches avec une tourelle de défense ponctuelle. +unit.cyerce.description = Tire des missiles à fragmentation sur les ennemis. Répare les unités alliées. +unit.aegires.description = Secoue toutes les unités et structures ennemies qui entrent dans son champ d'énergie. Répare tous les alliés. +unit.navanax.description = Tire des projectiles explosifs EMP, infligeant des dommages importants aux réseaux électriques ennemis et réparant les structures alliées. Fait fondre les ennemis proches avec 4 tourelles laser autonomes. lst.read = Lit un nombre depuis un bloc de mémoire relié au processeur. lst.write = Écrit un nombre dans un bloc de mémoire relié au processeur. From 2f71a4092f6a0ec31f8ce55a70b9624942322199 Mon Sep 17 00:00:00 2001 From: Catchears Date: Wed, 28 Jul 2021 16:45:15 +0200 Subject: [PATCH 037/130] german v7 update (#5631) --- core/assets/bundles/bundle_de.properties | 25 +++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index 4e08fe56a9..6c2e66c459 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -101,6 +101,7 @@ customgame = Benutzerdefiniertes Spiel newgame = Neues Spiel none = none.found = [lightgray] +none.inmap = [lightgray] minimap = Minimap position = Position close = Schließen @@ -565,6 +566,7 @@ sectors.unexplored = [lightgray]Unentdeckt sectors.resources = Ressourcen: sectors.production = Produktion: sectors.export = Export: +sectors.import = Import: sectors.time = Zeit: sectors.threat = Gefahr: sectors.wave = Welle: @@ -724,7 +726,7 @@ stat.maxconsecutive = Max. Konsekutive stat.buildcost = Baukosten stat.inaccuracy = Ungenauigkeit stat.shots = Schüsse -stat.reload = Schüsse/Sekunde +stat.reload = Schussrate stat.ammo = Munition stat.shieldhealth = Schildlebenspunkte stat.cooldowntime = Cooldown-Zeit @@ -793,7 +795,7 @@ bullet.damage = [stat]{0}[lightgray] Schaden bullet.splashdamage = [stat]{0}[lightgray] Flächenschaden ~[stat] {1}[lightgray] Kacheln bullet.incendiary = [stat]entzündend bullet.homing = [stat]zielsuchend -bullet.frag = [stat]explosiv +bullet.frag = [stat]{0}[lightgray]x explosive Projektile: bullet.lightning = [stat]{0}[lightgray]x Blitz ~ [stat]{1}[lightgray] Schaden bullet.buildingdamage = [stat]{0}%[lightgray]Blockschaden bullet.knockback = [stat]{0}[lightgray] zurückstoßend @@ -806,6 +808,7 @@ bullet.reload = [stat]{0}[lightgray]x Feuerrate unit.blocks = Blöcke unit.blockssquared = Blöcke² unit.powersecond = Stromeinheiten/Sekunde +unit.tilessecond = Blöcke/Sekunde unit.liquidsecond = Flüssigkeitseinheiten/Sekunde unit.itemssecond = Materialeinheiten/Sekunde unit.liquidunits = Flüssigkeitseinheiten @@ -844,7 +847,6 @@ setting.doubletapmine.name = Doppeltippen zum Abbauen setting.modcrashdisable.name = Mods bei Absturz deaktivieren setting.animatedwater.name = Animiertes Wasser setting.animatedshields.name = Animierte Schilde -setting.antialias.name = Antialias[lightgray] (Neustart erforderlich)[] setting.playerindicators.name = Spieler-Indikatoren setting.indicators.name = Verbündeten-Indikatoren setting.autotarget.name = Auto-Zielauswahl @@ -853,7 +855,8 @@ setting.touchscreen.name = Touchscreen-Steuerung setting.fpscap.name = Max. FPS setting.fpscap.none = Kein(e) setting.fpscap.text = {0} FPS -setting.uiscale.name = UI-Skalierung[lightgray] (Neustart erforderlich)[] +setting.uiscale.name = UI-Skalierung +setting.uiscale.description = Neustart erforderlich. setting.swapdiagonal.name = Immer diagonale Platzierung setting.difficulty.training = Training setting.difficulty.easy = Leicht @@ -871,7 +874,8 @@ setting.saveinterval.name = Autosave-Häufigkeit setting.seconds = {0} Sekunden setting.milliseconds = {0} Millisekunden setting.fullscreen.name = Vollbild -setting.borderlesswindow.name = Randloses Fenster [lightgray](Neustart vielleicht erforderlich) +setting.borderlesswindow.name = Randloses Fenster +setting.borderlesswindow.description = Neustart vielleicht erforderlich. setting.fps.name = FPS anzeigen setting.smoothcamera.name = Sanfte Kamerabewegungen setting.vsync.name = VSync @@ -994,6 +998,7 @@ rules.wavetimer = Wellen-Timer rules.waves = Wellen rules.attack = Angriff-Modus rules.buildai = KI kann bauen +rules.cleanupdeadteams = Blöcke von erorberten Teams zerstören (PvP) rules.corecapture = Kern nach Zerstörung einnehmen rules.polygoncoreprotection = Polygonaler Kernschutz rules.enemyCheat = Unbegrenzte Ressourcen für die KI (Rotes Team) @@ -1288,7 +1293,6 @@ block.meltdown.name = Meltdown block.foreshadow.name = Foreshadow block.container.name = Behälter block.launch-pad.name = Launchpad -block.launch-pad-large.name = Großes Launchpad block.segment.name = Segment block.command-center.name = Kommandozentrale block.ground-factory.name = Bodenfabrik @@ -1309,11 +1313,11 @@ block.payload-source.name = Frachtquelle block.disassembler.name = Großer Trenner block.silicon-crucible.name = Silizium Schmelztiegel block.overdrive-dome.name = Beschleunigungs-Maschine +block.interplanetary-accelerator.name = Interplanetarischer Beschleuniger #experimental, may be removed block.block-forge.name = Block-Fabrik block.block-loader.name = Block-Lader block.block-unloader.name = Block-Entlader -block.interplanetary-accelerator.name = Interplanetarischer Beschleuniger block.switch.name = Schalter block.micro-processor.name = Mikroprozessor @@ -1543,6 +1547,8 @@ block.memory-bank.description = Speichert Informationen für einen Prozessor. Ho block.logic-display.description = Zeigt mithilfe eines Prozessors Beliebiges an. block.large-logic-display.description = Zeigt mithilfe eines Prozessors Beliebiges an. block.interplanetary-accelerator.description = Ein Riesen-Railgun-Turm, der mithilfe des Elektromagnetismus Kerne auf die nötige Geschwindigkeit bringt, um interplanetarisches Reisen zu ermöglichen. +block.repair-turret.description = Heilt durchgehend die nächste befreundete, beschädigte Einheit in der Umgebung. Verwendet optional Kühlung. +block.payload-propulsion-tower.description = Frachttransportationsturm mit hoher Reichweite. Schießt Fracht zu verbundenen Türmen. unit.dagger.description = Schießt normale Kugeln auf alle Feinde in der Nähe. unit.mace.description = Schießt Feuer auf alle Gegner in der Nähe. @@ -1577,6 +1583,11 @@ unit.omura.description = Schießt eine Railgun mit hoher Reichweite, um Gegner z unit.alpha.description = Beschützt den Scherbenkern vor Feinden. Baut Blöcke. unit.beta.description = Beschützt den Fundamentkern vor Feinden. Baut Blöcke. unit.gamma.description = Beschützt den Nukleuskern vor Feinden. Baut Blöcke. +unit.retusa.description = Platziert Minen und heilt verbündete Einheiten. +unit.oxynoe.description = Schießt Block-heilendes Feuer auf Gegner und zerstört gegnerische Projektile. +unit.cyerce.description = Schießt zielsuchende Cluster-Raketen auf Gegner und heilt verbündete Einheiten. +unit.aegires.description = Schockt alle gegnerische Einheiten und Blöcke, die das Energiefeld betreten. Heilt alle verbündete. +unit.navanax.description = Schießt explosive EMP-Projektile, die gegnerische Stromnetze zerstören und eigene Blöcke heilen. Zerschmilzt Gegner mit 4 autonomen Laserstrahlen. lst.read = Liest einen Wert aus einer verbundenen Spiecherzelle. lst.write = Schreibt eine Zahl in einer verbundene Speicherzelle. From 5cb5434ffea0623d95d98ad6670c0c1d82ce8a5a Mon Sep 17 00:00:00 2001 From: Ksawi <66205430+Ksawi999@users.noreply.github.com> Date: Wed, 28 Jul 2021 16:45:49 +0200 Subject: [PATCH 038/130] Update bundle_pl.properties (#5572) * Update bundle_pl.properties Added translation of statuses and processor functions. Changed few translations. * content.status.name * Update bundle_pl.properties * Update bundle_pl.properties * Flares in omura.description * Update bundle_pl.properties * Now better? * Update bundle_pl.properties * Better names * Update bundle_pl.properties * bullet.lightning * mods.browser * Badania -> Zbadaj * Final statuses names (I think) * Ready to merge * Tutorial (as in #5206) * Research * Final changes --- core/assets/bundles/bundle_pl.properties | 312 +++++++++++++---------- 1 file changed, 176 insertions(+), 136 deletions(-) diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index c89019a76f..b1c464655d 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -41,7 +41,7 @@ be.ignore = Zignoruj be.noupdates = Nie znaleziono aktualizacji. be.check = Sprawdź aktualizacje -mod.featured.dialog.title = Przeglądarka Modów +mods.browser = Przeglądarka Modów mods.browser.selected = Wybrany Mod mods.browser.add = Zainsta-\nluj Moda mods.browser.reinstall = Przeins-\ntaluj @@ -67,6 +67,14 @@ schematic.delete.confirm = Ten schemat zostanie usunięty. schematic.rename = Zmień nazwę schematu schematic.info = {0}x{1}, {2} bloków schematic.disabled = [scarlet]Schematy są wyłączone[]\nNie możesz używać schematów na tej [accent]mapie[] lub [accent]serwerze. +schematic.tags = Tagi: +schematic.edittags = Zmień Znacznik +schematic.addtag = Dodaj Znacznik +schematic.texttag = Tekst Znacznika +schematic.icontag = Ikona Znacznika +schematic.renametag = Zmień Nazwę Znacznika +schematic.tagdelconfirm = Czy kompletnie usunąć znacznik? +schematic.tagexists = Taki znacznik już istnieje. stats = Statystyki stat.wave = Fale powstrzymane:[accent] {0} @@ -159,7 +167,7 @@ planetmap = Mapa Planety launchcore = Wystrzel Rdzeń filename = Nazwa Pliku: unlocked = Odblokowano nową zawartość! -available =Nowe Odkrycie dostępne +available = Nowe Odkrycie dostępne completed = [accent]Ukończony techtree = Drzewo Techno-\nlogiczne research.legacy = Znaleziono badania z wersji [accent]5.0[].\nChcesz [accent]załadować je[], czy [accent]usunąć[] dane z drzewa technologicznego w nowej kampanii (zalecane)? @@ -502,7 +510,7 @@ memory = Pam: {0}mb memory2 = Pam:\n {0}mb +\n {1}mb language.restart = Uruchom grę ponownie, aby nowo ustawiony język zaczął funkcjonować. settings = Ustawienia -tutorial = Poradnik +tutorial = Samouczek tutorial.retake = Ponów Samouczek editor = Edytor mapeditor = Edytor Map @@ -530,7 +538,7 @@ launch.from = Wystrzelony z: [accent]{0} launch.destination = Cel: {0} configure.invalid = Ilość musi być liczbą pomiędzy 0 a {0}. add = Dodaj... -boss.health = Zdrowie Strażnika +guardian = Zdrowie Strażnika connectfail = [crimson]Nie można połączyć się z serwerem:\n\n[accent]{0} error.unreachable = Serwer niedostępny.\nSprawdź, czy adres jest wpisany poprawnie. @@ -620,6 +628,20 @@ sector.extractionOutpost.description = Odległa placówka zbudowana przez wroga sector.impact0078.description = Tutaj leżą pozostałości międzygwiezdnego statku transportowego, który jako pierwszy wszedł do tego układu.\n\nWydobądź jak najwięcej z wraku. Zbadaj każdą nienaruszoną technologię. sector.planetaryTerminal.description = Ostatni cel.\n\nTa baza przybrzeżna zawiera strukturę zdolną do wyrzucania rdzeni na lokalne planety. Jest wyjątkowo dobrze strzeżona.\n\nProdukuj jednostki morskie. Jak najszybciej wyeliminuj wroga. Zbadaj tą strukturę. +status.burning.name = Podpalenie +status.freezing.name = Zamrożenie +status.wet.name = Mokrość +status.muddy.name = Zabłocenie +status.melting.name = Topnienie +status.sapped.name = Osłabienie +status.electrified.name = Naelektryzowanie +status.spore-slowed.name = Zarodnikowe Spowolnienie +status.tarred.name = Osmołowanie +status.overclock.name = Przyspieszenie +status.shocked.name = Porażenie +status.blasted.name = Wysadzenie +status.unmoving.name = Unieruchomienie + settings.language = Język settings.data = Dane Gry settings.reset = Przywróć Domyślne @@ -655,7 +677,8 @@ stat.input = Wejście stat.output = Wyjście stat.booster = Wzmacniacz stat.tiles = Wymagane Pola -stat.affinities = Uwydajnienie +stat.affinities = Uwydajnienia +stat.opposites = Przeciwieństwa stat.powercapacity = Pojemność mocy stat.powershot = moc/strzał stat.damage = Obrażenia @@ -703,7 +726,7 @@ stat.lightningchance = Szansa Na Błyskawicę stat.lightningdamage = Obrażenia Błyskawic stat.flammability = Palność stat.radioactivity = Radioaktywność -stat.charge = Charge +stat.charge = Naładowanie stat.heatcapacity = Pojemność Cieplna stat.viscosity = Lepkość stat.temperature = Temperatura @@ -717,13 +740,21 @@ stat.abilities = Umiejętności stat.canboost = Może przyspieszyć stat.flying = Może latać stat.ammouse = Zużycie Amunicji +stat.damagemultiplier = Mnożnik Obrażeń +stat.healthmultiplier = Mnożnik Zdrowia +stat.speedmultiplier = Mnożnik Prędkości +stat.reloadmultiplier = Mnożnik Prędkości Przeładowywania +stat.buildspeedmultiplier = Mnożnik Prędkości Budowania +stat.reactive = Reaguje +stat.healing = Leczy -ability.forcefield = Pole Mocy +ability.forcefield = Pole Siłowe ability.repairfield = Pole Naprawy ability.statusfield = Pole Statusu ability.unitspawn = Fabryka Jednostek {0} ability.shieldregenfield = Strefa Tarczy Regenerującej ability.movelightning = Pioruny Poruszania +ability.energyfield = Pole Energii: [accent]{0}[] obrażenia ~ [accent]{1}[] bloki / [accent]{2}[] cele bar.drilltierreq = Wymagane Lepsze Wiertło bar.noresources = Brak Zasobów @@ -746,6 +777,7 @@ bar.power = Prąd bar.progress = Postęp Budowy bar.input = Wejście bar.output = Wyjście +bar.strength = [stat]{0}[lightgray]x siły units.processorcontrol = [lightgray]Kontrolowany przez procesor @@ -756,6 +788,7 @@ bullet.sapping = [stat]wyczerpujący bullet.homing = [stat]naprowadzający bullet.shock = [stat]piorunowy bullet.frag = [stat]fragmentacyjny +bullet.lightning = [stat]{0}[lightgray]x błyskawice ~ [stat]{1}[lightgray] Obrażenia bullet.buildingdamage = [stat]{0}%[lightgray] obrażeń budynkom bullet.knockback = [stat]{0}[lightgray] odrzut bullet.pierce = [stat]{0}[lightgray]x przebicia @@ -769,6 +802,7 @@ bullet.reload = [stat]{0}[lightgray]x szybkość ataku unit.blocks = bloki unit.blockssquared = bloki² unit.powersecond = jednostek prądu na sekundę +unit.tilessecond = bloków na sekundę unit.liquidsecond = jednostek płynu na sekundę unit.itemssecond = przedmiotów na sekundę unit.liquidunits = jednostek płynu @@ -991,7 +1025,8 @@ rules.weather.duration = Czas trwania: content.item.name = Przedmioty content.liquid.name = Płyny content.unit.name = Jednostki -content.block.name = Klocki +content.block.name = Bloki +content.status.name = Efekty Statusu content.sector.name = Sektory item.copper.name = Miedź @@ -1157,7 +1192,7 @@ block.distributor.name = Dystrybutor block.sorter.name = Sortownik block.inverted-sorter.name = Odwrotny Sortownik block.message.name = Wiadomość -block.illuminator.name = Illuminator +block.illuminator.name = Iluminator block.overflow-gate.name = Brama Przepełnieniowa block.underflow-gate.name = Brama Niedomiaru block.silicon-smelter.name = Huta Krzemu @@ -1397,7 +1432,7 @@ block.phase-conveyor.description = Zaawansowany blok transportowy dla przedmiot block.sorter.description = Sortuje przedmioty. Jeśli przedmiot pasuje to przechodzi dalej, jeśli nie - to przechodzi na boki. block.inverted-sorter.description = Sortuje przedmioty jak zwykły sortownik, ale odpowiednie surowce wyciągane są na boki. block.router.description = Akceptuje przedmioty z jednego miejsca i rozdziela je do trzech innych kierunków. Przydatne w rozdzielaniu materiałów z jednego źródła do wielu celów.\n\n[scarlet]Nigdy nie używaj przy punkcje wejścia materiałów produkcyjnych, ponieważ zostaną one zatkane przez materiały wyjściowe.[] -block.router.details = Konieczne zło. Nie zaleca się stosowania obok nakładów produkcyjnych, ponieważ zostaną one zatkane. +block.router.details = Nieuniknione zło. Nie zaleca się stosowania obok nakładów produkcyjnych, ponieważ zostaną one zatkane. block.distributor.description = Zaawansowany rozdzielacz, rozdzielający przedmioty do 7 innych kierunków. block.overflow-gate.description = Rozdzielacz, który przerzuca przedmioty, kiedy główna droga jest przepełniona. block.underflow-gate.description = Odwrotność bramy przepełnieniowej, który przepuszcza przedmioty główną drogą, gdy boczne drogi są przepełnione. @@ -1517,150 +1552,155 @@ unit.risso.description = Strzela sporą ilością pocisków i rakiet w najbliżs unit.minke.description = Strzela granatami i standardowymi pociskami w najbliższych przeciwników. unit.bryde.description = Strzela granatami i rakietami na dużą odległość we wrogów. unit.sei.description = Strzela dużą ilością rakiet oraz przebijających zbroje pocisków we wrogów. -unit.omura.description = Strzela przebijającym superszybkim pociskiem we wrogów ze sporej odległości. Produkuje Błyski (jednostki). +unit.omura.description = Strzela przebijającym superszybkim pociskiem we wrogów ze sporej odległości. Produkuje jednostki Flare. unit.alpha.description = Chroni Rdzeń: Odłamek przed wrogami. Buduje struktury. unit.beta.description = Chroni Rdzeń: Podstawa przed wrogami. Buduje struktury. unit.gamma.description = Chroni Rdzeń: Jądro przed wrogami. Buduje struktury. -lst.read = Read a number from a linked memory cell. -lst.write = Write a number to a linked memory cell. -lst.print = Add text to the print buffer.\nDoes not display anything until [accent]Print Flush[] is used. -lst.draw = Add an operation to the drawing buffer.\nDoes not display anything until [accent]Draw Flush[] is used. -lst.drawflush = Flush queued [accent]Draw[] operations to a display. -lst.printflush = Flush queued [accent]Print[] operations to a message block. -lst.getlink = Get a processor link by index. Starts at 0. -lst.control = Control a building. -lst.radar = Locate units around a building with range. -lst.sensor = Get data from a building or unit. -lst.set = Set a variable. -lst.operation = Perform an operation on 1-2 variables. -lst.end = Jump to the top of the instruction stack. -lst.jump = Conditionally jump to another statement. -lst.unitbind = Bind to the next unit of a type, and store it in [accent]@unit[]. -lst.unitcontrol = Control the currently bound unit. -lst.unitradar = Locate units around the currently bound unit. -lst.unitlocate = Locate a specific type of position/building anywhere on the map.\nRequires a bound unit. +lst.read = Wczytuje liczbę z połączonej komórki pamięci. +lst.write = Zapisuje liczbę do połączonej komórki pamięci. +lst.print = Dodaje tekst do buforu drukującego.\nNie wyświetla niczego dopóki [accent]Print Flush[] nie jest użyte. +lst.draw = Dodaje operacje do buforu rysującego.\nNie wyświetla niczego dopóki [accent]Draw Flush[] nie jest użyte. +lst.drawflush = Wyświetla oczekujące operacje z funkcji [accent]Draw[] na wyświetlaczu. +lst.printflush = Dodaje oczekujące operacje z funkcji [accent]Print[] do bloku wiadomości. +lst.getlink = Zdobywa połączenie procesora przez indeks. Zaczyna się od 0. +lst.control = Kontroluje budynek. +lst.radar = Lokalizuje jednostki wokół budynku w jego zasięgu. +lst.sensor = Zdobywa dane z budynku lub jednostki. +lst.set = Ustawia zmienną. +lst.operation = Wykonuje operację na 1-2 zmiennych. +lst.end = Przeskakuje na początek stosu instrukcji. +lst.wait = Czeka określoną liczbę sekund. +lst.lookup = Znajduje typ przedmiotu/cieczy/jednostki/bloku poprzez ID.\nCałkowite zliczenia każdego typu można uzyskać za pomocą:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] +lst.jump = Warunkowo przeskakuje do innego stanu. +lst.unitbind = Powiązuje z następną jednostką danego typu i przechowuje ją w [accent]@unit[]. +lst.unitcontrol = Kontroluje obecnie powiązaną jednostkę. +lst.unitradar = Lokalizuje jednostki wokół obecnie powiązanej jednostki. +lst.unitlocate = Lokalizuje specyficzny typ pozycji/budynku gdziekolwiek na mapie.\nWymaga powiązanej jednostki. -logic.nounitbuild = [red]Unit building logic is not allowed here. +logic.nounitbuild = [red]Logika budowania jednostek nie jest tu dozwolona. -lenum.type = Type of building/unit.\ne.g. for any router, this will return [accent]@router[].\nNot a string. -lenum.shoot = Shoot at a position. -lenum.shootp = Shoot at a unit/building with velocity prediction. -lenum.configure = Building configuration, e.g. sorter item. -lenum.enabled = Whether the block is enabled. +lenum.type = Typ budynku/jednostki.\nnp. dla każdego rozdzielacza, zwróci [accent]@router[].\nNie jest łańcuchem znaków (string). +lenum.shoot = Strzel w określoną pozycje. +lenum.shootp = Strzel w jednostkę/budynek z przewidywaną prędkością. +lenum.configure = Konfiguracja budowania, np. sortowany przedmiot w sortowniku. +lenum.enabled = Sprawdza czy blok jest włączony. -laccess.color = Illuminator color. -laccess.controller = Unit controller. If processor controlled, returns processor.\nIf in a formation, returns leader.\nOtherwise, returns the unit itself. -laccess.dead = Whether a unit/building is dead or no longer valid. -laccess.controlled = Returns:\n[accent]@ctrlProcessor[] if unit controller is processor\n[accent]@ctrlPlayer[] if unit/building controller is player\n[accent]@ctrlFormation[] if unit is in formation\nOtherwise, 0. -laccess.commanded = [red]Deprecated. Will be removed![]\nUse [accent]controlled[] instead. +laccess.color = Kolor iluminatora. +laccess.controller = Kontroler jednostki. Jeśli jest kontrolowana przez procesor, zwraca procesor.\nJeśli we formacji, zwracja przywódcę.\nW innym wypadku zwraca samą jednostkę. +laccess.dead = Sprawdza czy jednostka/budynek jest zniszczony lub już nie istnieje. +laccess.controlled = Zwraca:\n[accent]@ctrlProcessor[] jeśli kontrolerem jednostki jest procesor\n[accent]@ctrlPlayer[] jeśli kontrolerem jednostki/budynku jest gracz\n[accent]@ctrlFormation[] jeśli jednostka jest w formacji\nW innym wypadku 0. +laccess.commanded = [red]Przestarzałe. Zostanie usunięte![]\nZamiast tego użyj [accent]controlled[]. +laccess.progress = Postęp akcji, od 0 do 1.\nZwraca produkcję, przeładowanie wieżyczki lub postęp konstrukcji. -graphicstype.clear = Fill the display with a color. -graphicstype.color = Set color for next drawing operations. -graphicstype.stroke = Set line width. -graphicstype.line = Draw line segment. -graphicstype.rect = Fill a rectangle. -graphicstype.linerect = Draw a rectangle outline. -graphicstype.poly = Fill a regular polygon. -graphicstype.linepoly = Draw a regular polygon outline. -graphicstype.triangle = Fill a triangle. -graphicstype.image = Draw an image of some content.\nex: [accent]@router[] or [accent]@dagger[]. +graphicstype.clear = Wypełnia wyświetlacz kolorem. +graphicstype.color = Ustawia kolor następnych operacji rysujących. +graphicstype.stroke = Ustawia grubość linii. +graphicstype.line = Rysuje segment linii. +graphicstype.rect = Wypełnia prostokąt. +graphicstype.linerect = Rysuje obwód prostokąta. +graphicstype.poly = Wypełnia regularny wielokąt. +graphicstype.linepoly = Rysuje obwód regularnego wielokąta. +graphicstype.triangle = Wypełnia trójkąt. +graphicstype.image = Rysuje ikonę jakiejś treści.\nnp. [accent]@router[] lub [accent]@dagger[]. -lenum.always = Always true. -lenum.idiv = Integer division. -lenum.div = Division.\nReturns [accent]null[] on divide-by-zero. +lenum.always = Zawsze prawda. +lenum.idiv = Dzielenie liczb całkowitych. +lenum.div = Dzielenie.\nZwraca [accent]null[] w trakcie dzielenia przez zero. lenum.mod = Modulo. -lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0. -lenum.notequal = Not equal. Coerces types. -lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[]. -lenum.shl = Bit-shift left. -lenum.shr = Bit-shift right. -lenum.or = Bitwise OR. -lenum.land = Logical AND. -lenum.and = Bitwise AND. -lenum.not = Bitwise flip. -lenum.xor = Bitwise XOR. +lenum.equal = Równość. Wymusza typ.\nNiezerowe objekty połączone z liczbami stają się 1, w innym wypadku 0. +lenum.notequal = Nierówność. Wymusza typ. +lenum.strictequal = Ścisła równość. Nie wymusza typów.\nMoże być użyte do wykrycia [accent]null[]. +lenum.shl = Przesunięcie bitowe w lewo. +lenum.shr = Przesunięcie bitowe w prawo. +lenum.or = Bitowe OR (lub). +lenum.land = Logiczne AND (i). +lenum.and = Bitowe AND (i). +lenum.not = Bitowe NOT. +lenum.xor = Bitowe XOR. + +lenum.min = Minimum dwóch liczb. +lenum.max = Maksimum dwóch liczb. +lenum.angle = Kąt wektoru w stopniach. +lenum.len = Długość wektoru. + +lenum.sin = Sinus, w stopniach. +lenum.cos = Cosinus, w stopniach. +lenum.tan = Tangens, w stopniach. -lenum.min = Minimum of two numbers. -lenum.max = Maximum of two numbers. -lenum.angle = Angle of vector in degrees. -lenum.len = Length of vector. -lenum.sin = Sine, in degrees. -lenum.cos = Cosine, in degrees. -lenum.tan = Tangent, in degrees. #not a typo, look up 'range notation' -lenum.rand = Random decimal in range [0, value). -lenum.log = Natural logarithm (ln). -lenum.log10 = Base 10 logarithm. -lenum.noise = 2D simplex noise. -lenum.abs = Absolute value. -lenum.sqrt = Square root. +lenum.rand = Losowa liczba w przedziale [0, wartość). +lenum.log = Logarytm naturalny (ln). +lenum.log10 = Logarytm o podstawie 10. +lenum.noise = Szum simplex 2D. +lenum.abs = Wartość bezwzględna. +lenum.sqrt = Pierwiastek kwadratowy. -lenum.any = Any unit. -lenum.ally = Ally unit. -lenum.attacker = Unit with a weapon. -lenum.enemy = Enemy unit. -lenum.boss = Guardian unit. -lenum.flying = Flying unit. -lenum.ground = Ground unit. -lenum.player = Unit controlled by a player. +lenum.any = Dowolna jednostka. +lenum.ally = Sojusznicza jednostka. +lenum.attacker = Jednostka z bronią. +lenum.enemy = Przeciwnik. +lenum.boss = Strażnik. +lenum.flying = Latająca jednostka. +lenum.ground = Jednostka lądowa. +lenum.player = Jednostka kontrolowana przez gracza. -lenum.ore = Ore deposit. -lenum.damaged = Damaged ally building. -lenum.spawn = Enemy spawn point.\nMay be a core or a position. -lenum.building = Building in a specific group. +lenum.ore = Depozyt rudy. +lenum.damaged = Uszkodzony sojuszniczy budynek. +lenum.spawn = Punkt zrzutu przeciwnika.\nMoże być rdzeniem lub pozycją. +lenum.building = Budynek ze specyficznej grupy. -lenum.core = Any core. -lenum.storage = Storage building, e.g. Vault. -lenum.generator = Buildings that generate power. -lenum.factory = Buildings that transform resources. -lenum.repair = Repair points. -lenum.rally = Command center. -lenum.battery = Any battery. -lenum.resupply = Resupply points.\nOnly relevant when [accent]"Unit Ammo"[] is enabled. -lenum.reactor = Impact/Thorium reactor. -lenum.turret = Any turret. +lenum.core = Dowolny rdzeń. +lenum.storage = Budynek przechowujący, np. Magazyn. +lenum.generator = Budynki generujące prąd. +lenum.factory = Budynki przetwarzające surowce. +lenum.repair = Punkty naprawy. +lenum.rally = Centrum dowodzenia. +lenum.battery = Dowolna bateria. +lenum.resupply = Punkty uzupełniające.\nMa znaczenie tylko gdy [accent]"Unit Ammo"[] jest załączone. +lenum.reactor = Reaktor uderzeniowy/torowy. +lenum.turret = Dowolna wieżyczka. -sensor.in = The building/unit to sense. +sensor.in = Wykrywany budynek/jednostka. -radar.from = Building to sense from.\nSensor range is limited by building range. -radar.target = Filter for units to sense. -radar.and = Additional filters. -radar.order = Sorting order. 0 to reverse. -radar.sort = Metric to sort results by. -radar.output = Variable to write output unit to. +radar.from = Budynek wykrywający.\nZasięg czujnika jest limitowany przez zasięg budynku. +radar.target = Filtr wykrywanych jednostek. +radar.and = Dodatkowe filtry. +radar.order = Kolejność sortowania. 0 aby odwrócić. +radar.sort = Wartość, według której będą sortowane wyniki. +radar.output = Zmienna, do której zostanie przypisana jednostka wyjściowa. -unitradar.target = Filter for units to sense. -unitradar.and = Additional filters. -unitradar.order = Sorting order. 0 to reverse. -unitradar.sort = Metric to sort results by. -unitradar.output = Variable to write output unit to. +unitradar.target = Filtr wykrywanych jednostek. +unitradar.and = Dodatkowe filtry. +unitradar.order = Kolejność sortowania. 0 aby odwrócić. +unitradar.sort = Wartość, według której będą sortowane wyniki. +unitradar.output = Zmienna, do której zostanie przypisana jednostka wyjściowa. -control.of = Building to control. -control.unit = Unit/building to aim at. -control.shoot = Whether to shoot. +control.of = Kontrolowany budynek. +control.unit = Jednostka/budynek, w którą ma celować. +control.shoot = Strzelanie. -unitlocate.enemy = Whether to locate enemy buildings. -unitlocate.found = Whether the object was found. -unitlocate.building = Output variable for located building. -unitlocate.outx = Output X coordinate. -unitlocate.outy = Output Y coordinate. -unitlocate.group = Building group to look for. +unitlocate.enemy = Lokalizowanie budynków przeciwnika. +unitlocate.found = Znalezienie obiektu. +unitlocate.building = Zmienna wyjściowa dla zlokalizowanego budynku. +unitlocate.outx = Wyjściowy koordynat X. +unitlocate.outy = Wyjściowy koordynat Y. +unitlocate.group = Grupa szukanych budynków. -lenum.idle = Don't move, but keep building/mining.\nThe default state. -lenum.stop = Stop moving/mining/building. -lenum.move = Move to exact position. -lenum.approach = Approach a position with a radius. -lenum.pathfind = Pathfind to the enemy spawn. -lenum.target = Shoot a position. -lenum.targetp = Shoot a target with velocity prediction. -lenum.itemdrop = Drop an item. -lenum.itemtake = Take an item from a building. -lenum.paydrop = Drop current payload. -lenum.paytake = Pick up payload at current location. -lenum.flag = Numeric unit flag. -lenum.mine = Mine at a position. -lenum.build = Build a structure. -lenum.getblock = Fetch a building and type at coordinates.\nUnit must be in range of position.\nSolid non-buildings will have the type [accent]@solid[]. -lenum.within = Check if unit is near a position. -lenum.boost = Start/stop boosting. +lenum.idle = Przestań się poruszać, jednak nadal buduj/wydobywaj.\nDomyślny stan. +lenum.stop = Przestań poruszać się/kopać/budować. +lenum.move = Przemieść się do określonej pozycji. +lenum.approach = Podejdź do pozycji w promieniu. +lenum.pathfind = Odnajdź ścieżkę do punktu zrzutu przeciwników. +lenum.target = Strzel w określoną pozycje. +lenum.targetp = Strzel w jednostkę/budynek z przewidywaną prędkością. +lenum.itemdrop = Upuść przedmiot. +lenum.itemtake = Zabierz przedmiot z budynku. +lenum.paydrop = Upuść obecny ładunek. +lenum.paytake = Podnieś ładunek z obecnego miejsca. +lenum.flag = Numeryczny znacznik jednostki. +lenum.mine = Kop na danej pozycji. +lenum.build = Buduj strukturę. +lenum.getblock = Pobierz budynek i typ z koordynatów.\nJednostka musi być w zasięgu pozycji.\nSolidne niebudynki będą miały typ [accent]@solid[]. +lenum.within = Sprawdź czy jednostka jest w pobliżu pozycji. +lenum.boost = Zacznij/zakończ boostować. From fef8ee925ba2003f620c0883a95e56581d5a6ae4 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 28 Jul 2021 11:51:20 -0400 Subject: [PATCH 039/130] Potential fix for #5660 --- core/src/mindustry/content/Blocks.java | 4 ++-- core/src/mindustry/input/InputHandler.java | 2 +- core/src/mindustry/world/blocks/storage/CoreBlock.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 9a1c16842e..841c6265d0 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -657,8 +657,8 @@ public class Blocks implements ContentList{ craftTime = 35f; size = 2; - consumes.power(1f); - consumes.liquid(Liquids.slag, 0.07f); + consumes.power(1.1f); + consumes.liquid(Liquids.slag, 4f / 60f); }}; disassembler = new Separator("disassembler"){{ diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 1f0486a223..f97385122c 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -356,7 +356,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ Events.fire(new TapEvent(player, tile)); } - @Remote(targets = Loc.both, called = Loc.both, forward = true) + @Remote(targets = Loc.both, called = Loc.server, forward = true) public static void buildingControlSelect(Player player, Building build){ if(player == null || build == null || player.dead()) return; diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 8963e1fcd1..621c36b25a 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -248,7 +248,7 @@ public class CoreBlock extends StorageBlock{ @Override public void onControlSelect(Player player){ Fx.spawn.at(player); - if(net.client()){ + if(net.client() && player == Vars.player){ control.input.controlledType = null; } From aa74679998e30f3e926bf4f43e1bce38fd32fdc6 Mon Sep 17 00:00:00 2001 From: YellOw139 <70975516+YellOw139@users.noreply.github.com> Date: Wed, 28 Jul 2021 23:57:54 +0300 Subject: [PATCH 040/130] [Bundle][RO] Update (#5573) * [Bundle][RO] Update Changelog: - New strings/changes up to commit 8041c305ad3a4a2f046b835b4acc533b33c471b7 - Typo fixes & various other improvements * Update bundle_ro.properties * Update bundle_ro.properties * settings * Update bundle_ro.properties * new blocks * new units I * new units II * Update bundle_ro.properties * Update bundle_ro.properties --- core/assets/bundles/bundle_ro.properties | 39 ++++++++++++++++-------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/core/assets/bundles/bundle_ro.properties b/core/assets/bundles/bundle_ro.properties index 71c94ec606..3dd9d388b0 100644 --- a/core/assets/bundles/bundle_ro.properties +++ b/core/assets/bundles/bundle_ro.properties @@ -100,6 +100,7 @@ joingame = Intră în Joc customgame = Personalizat newgame = Joc Nou none.found = [lightgray] +none.inmap = [lightgray] none = minimap = Minihartă position = Poziție @@ -564,7 +565,8 @@ weather.fog.name = Ceață sectors.unexplored = [lightgray]Neexplorat sectors.resources = Resurse: sectors.production = Producție: -sectors.export = Export: +sectors.export = Exportă: +sectors.import = Importă: sectors.time = Timp: sectors.threat = Amenințare: sectors.wave = Valul: @@ -643,7 +645,7 @@ status.electrified.name = Electrificat status.spore-slowed.name = Încetinit de Spori status.tarred.name = Păcurit status.overclock.name = Suprasolicitat -status.shocked.name = Șoc +status.shocked.name = Electrocutat status.blasted.name = Explozie status.unmoving.name = Nemișcat @@ -724,7 +726,7 @@ stat.maxconsecutive = Maxim Consecutive stat.buildcost = Cost Construcție stat.inaccuracy = Inacuratețe stat.shots = Lovituri -stat.reload = Lovituri/Secundă +stat.reload = Rata de Tragere stat.ammo = Muniție stat.shieldhealth = Viață Scut stat.cooldowntime = Timp de Reîncărcare @@ -793,10 +795,10 @@ bullet.damage = [stat]{0}[lightgray] forță bullet.splashdamage = [stat]{0}[lightgray] forță pe raza ~[stat] {1}[lightgray] pătrate bullet.incendiary = [stat]incendiar bullet.homing = [stat]cu radar -bullet.frag = [stat]se sparge +bullet.frags = [stat]{0}[lightgray]x fragmente: bullet.lightning = [stat]{0}[lightgray]x fulgere ~ [stat]{1}[lightgray] forță bullet.buildingdamage = [stat]{0}%[lightgray] forță/clădire -bullet.knockback = [stat]{0} [lightgray]împingere +bullet.knockback = [stat]{0}[lightgray] împingere bullet.pierce = [stat]{0}[lightgray]x penetrează bullet.infinitepierce = [stat]penetrează bullet.healpercent = [stat]{0}[lightgray]% reparare @@ -806,6 +808,7 @@ bullet.reload = [stat]{0}[lightgray]x lovituri unit.blocks = blocuri unit.blockssquared = blocuri² unit.powersecond = electricitate/secundă +unit.tilessecond = pătrate/secundă unit.liquidsecond = unități lichid/secundă unit.itemssecond = materiale/secundă unit.liquidunits = unități lichid @@ -821,7 +824,7 @@ unit.shieldhealth = viață scut unit.items = materiale unit.thousands = mii unit.millions = mil -unit.billions = b +unit.billions = mld unit.pershot = /lovitură category.purpose = Utilizare category.general = General @@ -844,7 +847,6 @@ setting.doubletapmine.name = Dublu-Click pt a Mina setting.modcrashdisable.name = Dezactivează Modurile în Cazul unui Crash la Pornire setting.animatedwater.name = Suprafețe Animate setting.animatedshields.name = Scuturi Animate -setting.antialias.name = Antialiasing[lightgray] (necesită repornire)[] setting.playerindicators.name = Indicatori Jucător setting.indicators.name = Indicatori Inamic setting.autotarget.name = Auto-Țintire @@ -853,7 +855,8 @@ setting.touchscreen.name = Controale Touchscreen setting.fpscap.name = FPS Maxim setting.fpscap.none = Niciuna setting.fpscap.text = FPS (0) -setting.uiscale.name = Scară Interfață [lightgray] (repornirea necesară)[] +setting.uiscale.name = Scară Interfață +setting.uiscale.description = Repornire necesară pt a aplica schimbările. setting.swapdiagonal.name = Plasează Mereu Diagonal setting.difficulty.training = Antrenament setting.difficulty.easy = Ușor @@ -871,7 +874,8 @@ setting.saveinterval.name = Interval de Salvare setting.seconds = {0} secunde setting.milliseconds = {0} millisecunde setting.fullscreen.name = Ecran Complet -setting.borderlesswindow.name = Fereastră Fără Margine[lightgray] (repornirea poate fi necesară) +setting.borderlesswindow.name = Fereastră Fără Margine +setting.borderlesswindow.description = Repornirea poate fi necesară pt a aplica schimbările. setting.fps.name = Vezi FPS & Ping setting.smoothcamera.name = Cameră Graduală setting.vsync.name = VSync @@ -994,6 +998,7 @@ rules.wavetimer = Valuri pe Timp rules.waves = Valuri rules.attack = Modul Atac rules.buildai = AI-ul Construiește +rules.cleanupdeadteams = Îndepărtează Clădirile Echipelor Învinse (PvP) rules.corecapture = Capturează Nucleele Distruse rules.enemyCheat = Resurse infinite pt AI (echipa roșie) rules.blockhealthmultiplier = Multiplicatorul Vieții Blocurilor @@ -1278,7 +1283,7 @@ block.surge-wall.name = Perete de Aliaj block.surge-wall-large.name = Perete Mare de Aliaj block.cyclone.name = Ciclon block.fuse.name = Fuse -block.shock-mine.name = Mină cu Șocuri +block.shock-mine.name = Mină cu Electroșocuri block.overdrive-projector.name = Proiector de Suprasolicitare block.force-projector.name = Proiector de Forță block.arc.name = Arc @@ -1288,7 +1293,6 @@ block.meltdown.name = Meltdown block.foreshadow.name = Foreshadow block.container.name = Container block.launch-pad.name = Platformă de Lansare -block.launch-pad-large.name = Platformă de Lansare Mare block.segment.name = Segment block.command-center.name = Centru de Comandă block.ground-factory.name = Fabrică Unități Artilerie @@ -1348,6 +1352,7 @@ hint.placeTurret = Construiește \uf861 [accent]Arme[] pt a-ți apăra baza de i hint.breaking = Ține apăsat [accent]click-dreapta[] și trage pe ecran pt a distruge blocuri. hint.breaking.mobile = Activează \ue817 [accent]ciocanul[] din dreapta-jos și dă click pt a distruge blocuri.\n\nȚine apăsat cu degetul pt o secundă și trage pt a distruge mai multe blocuri deodată. hint.blockInfo = Poți vedea informații despre un bloc selectându-l în [accent]meniul de construcție[] și dând click pe butonul [accent][[?][] din dreapta. +hint.derelict = [accent]Structurile abandonate[] sunt rămășițe stricate ale bazelor vechi care nu mai funcționează.\n\nAceste structuri pot fi [accent]deconstruite[] pt resurse. hint.research = Folosește butonul \ue875 [accent]Cercetează[] pt a cerceta noi tehnologii. hint.research.mobile = Folosește butonul \ue875 [accent]Cercetează[] din \ue88c [accent]Meniu[] pt a cerceta noi tehnologii. hint.unitControl = Ține apăsat [accent][[Ctrl][] și [accent]dă click[] pt a controla unități aliate sau arme. @@ -1399,6 +1404,7 @@ liquid.slag.description = Rafinată în separatoare înapoi în materialele cons liquid.oil.description = Folosit în producerea avansată de materiale și ca muniție incendiară. liquid.cryofluid.description = Folosit ca răcitor în reactoare, arme și fabrici. +block.derelict = [lightgray] Structuri Abandonate block.resupply-point.description = Realimentează unitățile din apropiere cu muniție de cupru. Nu este compatibil cu unitățile care se încarcă din baterii. block.armored-conveyor.description = Transportă materialele înainte. Nu acceptă materiale de pe lateral decât de la alte benzi. block.illuminator.description = Emite lumină. @@ -1457,7 +1463,7 @@ block.router.details = Un rău necesar. Nu folosi niciodată pt a introduce mate block.distributor.description = Distribuie materialele primite în alte 7 direcții în mod egal. block.overflow-gate.description = Transportă materialele doar la stânga și dreapta dacă drumul din față este blocat. block.underflow-gate.description = Opusul porții de revărsare. Transportă materialele în față dacă benzile din stânga și dreapta sunt blocate. -block.mass-driver.description = Dispozitiv folosit pt transportul materialelor pe distanțe mari. Adună mai multe materiale și apoi le lansează până la un alt distributor în masă pe o rază mare. +block.mass-driver.description = Structură de transport al materialelor pe distanțe mari. Adună mai multe materiale și apoi le lansează către un alt distributor în masă. block.mechanical-pump.description = Pompează lichide din mediul înconjurător. Nu necesită electricitate. block.rotary-pump.description = Pompează lichide din mediul înconjurător. Necesită electricitate. block.thermal-pump.description = Pompează lichide din mediul înconjurător. @@ -1543,6 +1549,8 @@ block.memory-bank.description = Stochează informație pt un procesor. Capacitat block.logic-display.description = Afișează grafica transmisă de un procesor logic. block.large-logic-display.description = Afișează grafica transmisă de un procesor logic. block.interplanetary-accelerator.description = Un turn masiv cu o armă railgun electromagnetică. Accelerează nucleele la viteză cosmică pt lansare interplanetară. +block.repair-turret.description = Repară încontinuu cea mai deteriorată unitate din vecinătate. Poate accepta răcitor. +block.payload-propulsion-tower.description = Structură de transport al încărcăturii pe distanțe mari. Lansează încărcătura către un alt turn propulsor conectat. unit.dagger.description = Trage cu gloanțe standard către toți inamicii din apropiere. unit.mace.description = Trage cu jeturi de flacără aprinsă către toți inamicii din apropiere. @@ -1577,6 +1585,11 @@ unit.omura.description = Trage cu un railgun cu gloanțe care penetrează scutur unit.alpha.description = Apără nucleul Shard de inamici. Construiește structuri. unit.beta.description = Apără nucleul Foundation de inamici. Construiește structuri. unit.gamma.description = Apără nucleul Core de inamici. Construiește structuri. +unit.retusa.description = Plasează mine de proximitate. Repară unitățile aliate. +unit.oxynoe.description = Trage cu jeturi de flacără către inamicii din apropiere, reparând structurile aliate. Țintește proiectilele inamice din apropiere cu o armă care le deteriorează și distruge. +unit.cyerce.description = Trage cu bombe cu dispersie echipate cu radar către inamici. Repară unitățile aliate. +unit.aegires.description = Electrocutează toate unitățile și structurile inamice care intră în câmpul său de energie. Repară toți aliații. +unit.navanax.description = Trage cu proiectile EMP explozive, lovind rețelele electrice inamice cu o forță semnificativă și reparând structurile aliate. Topește inamicii din apropiere cu cele 4 arme autonome cu laser. lst.read = Citește un număr dintr-o celulă de memorie conectată. lst.write = Scrie un număr într-o celulă de memorie conectată. @@ -1591,6 +1604,8 @@ lst.sensor = Obține date de la o clădire sau unitate. lst.set = Setează o variabilă. lst.operation = Efectuează o operație pe 1-2 variabile. lst.end = Sari la începutul listei de instrucțiuni. +lst.wait = Așteaptă un anumit număr de secunde. +lst.lookup = Caută un tip de material/lichid/unitate/bloc după ID.\nNumărul total din fiecare tip poate fi accesat cu:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] lst.jump = Dacă condiția este adevărată, mergi la o altă instrucțiune. lst.unitbind = Controlează următoarea unitate de tipul selectat și reține-o în [accent]@unit[]. lst.unitcontrol = Controlează unitatea controlată de procesor. From 59aff44a5500b15bc53b3007a739d97432781bad Mon Sep 17 00:00:00 2001 From: Prosta4okua <31485341+Prosta4okua@users.noreply.github.com> Date: Wed, 28 Jul 2021 23:58:06 +0300 Subject: [PATCH 041/130] Update bundle_uk_UA.properties (#5540) --- core/assets/bundles/bundle_uk_UA.properties | 66 +++++++++++++++++---- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index 062421a05c..915c29534e 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -55,15 +55,24 @@ schematic.delete.confirm = Ви справді хочете видалити ц schematic.rename = Перейменувати схему schematic.info = {0}x{1}, блоків: {2} schematic.disabled = [scarlet]Схеми вимкнені[]\nВам не дозволяється використовувати схеми на цій [accent]мапі[] чи [accent]сервері. +schematic.tags = Мітки: +schematic.edittags = Редагувати мітки +schematic.addtag = Додати мітку +schematic.texttag = Текстова мітка +schematic.icontag = Мітка із значком +schematic.renametag = Перейменувати мітку +schematic.tagdelconfirm = Видалити цю мітку повністю? +schematic.tagexists = Схожа мітка вже існує. + mod.featured.title = Переглядач модифікацій mods.browser = Переглядач модифікацій -mods.browser.selected = Обрана модифікація +mods.browser.selected = Вибрана модифікація mods.browser.add = Установити mods.browser.reinstall = Перевстановити mods.github.open = Відкрити mods.browser.sortdate = Сортувати за давністю -mods.browser.sortstars = Сортувати за кількостю зірок +mods.browser.sortstars = Сортувати за популярністю stats = Статистика stat.wave = Хвиль відбито:[accent] {0} @@ -298,7 +307,6 @@ data.exported = Дані вивантажено. data.invalid = Це не дійсні ігрові дані. data.import.confirm = Вивантаження зовнішніх даних перезапише[scarlet] ВСІ[] ваші поточні ігрові дані.\n[accent]Це неможливо скасувати![]\n\nЯк тільки дані імпортуються, гра негайно закриється. quit.confirm = Ви дійсно хочете вийти? -quit.confirm.tutorial = Ви впевнені, що знаєте, що робите?\nНавчання можна пройти наново[accent] Налаштування->Гра->Пройти навчання ще раз.[] loading = [accent]Завантаження… reloading = [accent]Перезавантаження модифікацій… saving = [accent]Збереження… @@ -463,11 +471,13 @@ filter.option.circle-scale = Масштаб круга filter.option.octaves = Циклічність застосування filter.option.falloff = Спад циклічності filter.option.angle = Кут +filter.option.rotate = Повернути filter.option.amount = Кількість filter.option.block = Блок filter.option.floor = Поверхня filter.option.flooronto = Цільова поверхня filter.option.target = Ціль +filter.option.replacement = Заміщення filter.option.wall = Стіна filter.option.ore = Руда filter.option.floor2 = Друга поверхня @@ -483,7 +493,8 @@ load = Завантажити save = Зберегти fps = FPS: {0} ping = Затримка: {0} мс -memory = Mem: {0}мб +tps = TPS: {0} +memory = Mem: {0} мб memory2 = Mem:\n {0}мб +\n {1}мб language.restart = Перезапустіть свою гру, щоби налаштування мови набули чинності. settings = Налаштування @@ -513,7 +524,7 @@ launch.from = Запуск з [accent]{0} launch.destination = Пункт призначення: {0} configure.invalid = Кількість має бути числом між 0 та {0}. add = Додати… -boss.health = Здоров’я Вартового +guardian = Вартовий connectfail = [crimson]Помилка з’єднання:\n\n[accent]{0} error.unreachable = Сервер не є доступним.\nЧи правильно написана адреса? error.invalidaddress = Некоректна адреса. @@ -553,6 +564,7 @@ sector.missingresources = [scarlet]Недостатньо ресурсів у я sector.attacked = Сектор [accent]{0}[white] під атакою! sector.lost = Сектор [accent]{0}[white] втрачено! sector.captured = Сектор [accent]{0}[white]захоплено! +sector.changeicon = Змінити значок threat.low = низька threat.medium = середня threat.high = висока @@ -600,6 +612,7 @@ status.wet.name = Вологий status.muddy.name = Забризканий гряззю status.melting.name = Плавиться status.sapped.name = Виснажений +status.electrified.name = Наелектризований status.spore-slowed.name = Сповільнений спорами status.tarred.name = Покритий нафтою status.overclock.name = Прискорений @@ -628,6 +641,7 @@ settings.clearcampaignsaves.confirm = Ви справді хочете очис paused = [accent]< Пауза > clear = Очистити banned = [scarlet]Заблоковано +unsupported.environment = [scarlet]Непідтримуване середовище yes = Так no = Ні info.title = Інформація @@ -636,6 +650,7 @@ error.crashtitle = Виникла помилка unit.nobuild = [scarlet]Ця одиниця не може будувати lastaccessed = [lightgray]Остання зміна від {0} block.unknown = [lightgray]??? +stat.showinmap = <завантажте мапу для показу> stat.description = Призначення stat.input = Ввід stat.output = Вивід @@ -665,6 +680,7 @@ stat.memorycapacity = Ємність пам’яті stat.basepowergeneration = Базова генерація енергії stat.productiontime = Час виробництва stat.repairtime = Час повного відновлення блоку +stat.repairspeed = Швидкість відновлення stat.weapons = Зброя stat.bullet = Кулі stat.speedincrease = Збільшення швидкості @@ -713,11 +729,12 @@ stat.reactive = Реактивний ability.forcefield = Щитове поле ability.repairfield = Ремонтувальне поле -ability.statusfield = Поле підсилення +ability.statusfield = {0} Поле підсилення ability.unitspawn = Завод одиниць «{0}» ability.shieldregenfield = Поле, що відновлює щити ability.movelightning = Блискавки під час руху -bar.drilltierreq = Потребується кращий бур +ability.energyfield = Енергетичне поле: [accent]{0}[] шкоди ~ [accent]{1}[] блоків / [accent]{2}[] цілей +bar.drilltierreq = Потрібен ліпший бур bar.noresources = Бракує ресурсів bar.corereq = Необхідне основне ядро bar.drillspeed = Швидкість буріння: {0} за с. @@ -738,6 +755,7 @@ bar.power = Енергія bar.progress = Хід будування bar.input = Ввід bar.output = Вивід +bar.strength = x[stat]{0}[lightgray] сила units.processorcontrol = [lightgray]Керується процесором bullet.damage = [stat]{0}[lightgray] шкода bullet.splashdamage = [stat]{0}[lightgray] шкода по ділянці ~[stat] {1}[lightgray] плиток @@ -755,6 +773,7 @@ bullet.reload = [stat]{0}[lightgray]x швидкість перезаряджа unit.blocks = блоки unit.blockssquared = блоків² unit.powersecond = одиниць енергії за секунду +unit.tilessecond = плиток за секунду unit.liquidsecond = одиниць рідини за секунду unit.itemssecond = предметів за секунду unit.liquidunits = одиниць рідини @@ -939,6 +958,8 @@ rules.wavetimer = Таймер для хвиль rules.waves = Хвилі rules.attack = Режим атаки rules.buildai = Будування ШІ +rules.corecapture = Захоплення ядра після знищення +rules.polygoncoreprotection = Полігональний захист ядер rules.enemyCheat = Нескінченні ресурси для червоної команди ШІ rules.blockhealthmultiplier = Множник здоров’я блоків rules.blockdamagemultiplier = Множник шкоди блоків @@ -1022,6 +1043,11 @@ unit.minke.name = Смугач unit.bryde.name = Брайд unit.sei.name = Сейвал unit.omura.name = Омура +unit.retusa.name = Ретуза +unit.oxynoe.name = Оксино +unit.cyerce.name = Саєс +unit.aegires.name = Еґірес +unit.navanax.name = Наванакс unit.alpha.name = Альфа unit.beta.name = Бета unit.gamma.name = Гамма @@ -1081,6 +1107,7 @@ block.sand-water.name = Пісок із водою block.darksand-water.name = Темний пісок із водою block.char.name = Випалена земля block.dacite.name = Дацит +block.rhyolite.name = Риоліт block.dacite-wall.name = Дацитова стіна block.dacite-boulder.name = Дацитовий валун block.ice-snow.name = Крижаний сніг @@ -1098,7 +1125,8 @@ block.spore-cluster.name = Скупчення спор block.metal-floor.name = Металева підлога 1 block.metal-floor-2.name = Металева підлога 2 block.metal-floor-3.name = Металева підлога 3 -block.metal-floor-5.name = Металева підлога 4 +block.metal-floor-4.name = Металева підлога 4 +block.metal-floor-5.name = Металева підлога 5 block.metal-floor-damaged.name = Пошкоджена металева підлога block.dark-panel-1.name = Темна панель 1 block.dark-panel-2.name = Темна панель 2 @@ -1188,6 +1216,7 @@ block.solar-panel.name = Сонячна панель block.solar-panel-large.name = Велика сонячна панель block.oil-extractor.name = Екстрактор нафти block.repair-point.name = Ремонтний пункт +block.repair-point.name = Ремонтна башта block.pulse-conduit.name = Імпульсний трубопровід block.plated-conduit.name = Зміцнений трубопровід block.phase-conduit.name = Фазовий трубопровід @@ -1230,6 +1259,12 @@ block.exponential-reconstructor.name = Експоненційний реконс block.tetrative-reconstructor.name = Тетративний реконструктор block.payload-conveyor.name = Вантажний конвеєр block.payload-router.name = Розвантажувальний маршрутизатор +block.duct.name = Duct +block.duct-router.name = Канальний маршрутизатор +block.duct-bridge.name = Канальний міст +block.payload-propulsion-tower.name = Вантажна катапульта +block.payload-void.name = Вантажний вакуум +block.payload-source.name = Вантажне джерело block.disassembler.name = Розбирач block.silicon-crucible.name = Кремнієвий тигель block.overdrive-dome.name = Великий прискорювач @@ -1246,8 +1281,8 @@ block.large-logic-display.name = Великий логічний дисплей block.memory-cell.name = Комірка пам’яті block.memory-bank.name = Блок пам’яті team.blue.name = Синя -team.crux.name = Червона -team.sharded.name = Помаранчева +team.crux.name = Загарбники +team.sharded.name = Розколоті team.orange.name = Помаранчева team.derelict.name = Знедолена team.green.name = Зелена @@ -1268,6 +1303,7 @@ hint.placeConveyor.mobile = Конвеєри переміщують предме hint.placeTurret = Розмістіть  [accent]башти[], щоби захистити базу від ворогів.\n\nБашти потребують боєприпасів. У цьому випадку \uf838мідь.\nДля її подачі використовуйте конвеєри та бури. hhint.breaking = Натисніть [accent]ПКМ[] і тягніть, щоби зруйнувати блоки. hint.breaking.mobile = Активуйте  [accent]молот[] внизу праворуч і торкніться блоків, щоби їх розібрати.\n\nУтримуйте палець протягом секунди і протягніть, щоби розібрати виділене. +hint.blockInfo = Подивіться інформацію про блок. Перейдіть до [accent]меню будівництва[] і натисніть на кнопку [accent][[?][] правпоруч hint.research = Використовуйте кнопку  [accent]Дослідження[] для дослідження нової технології. hint.research.mobile = Використовуйте  [accent]Дослідження[] в  [accent]меню[] для дослідження нової технології. hint.unitControl = Утримуйте [accent][[лівий Ctrl][] і [accent]натисніть[] на одиницю чи башту, щоби контролювати її. @@ -1300,7 +1336,7 @@ item.graphite.description = Використовується для боєпри item.sand.description = Використовується для виробництва інших удосконалених матеріалів. item.coal.description = Використовується для виробництва палива і вдосконалених матеріалів. item.coal.details = Виглядає скам’янілою рослинною речовиною, утвореною задовго до Сівби. -item.titanium.description = Використовується в транспортуванні рідин, бурів та авіації. +item.titanium.description = Використовується в транспортуванні будівль, бурів та в заводах. item.thorium.description = Використовується в міцних конструкціях і як ядерне паливо. item.scrap.description = Використовується в Плавильнях і Подрібнювачах для перероблення в інші матеріали в інші матеріали. item.scrap.details = Залишки старих споруд та підрозділів. @@ -1507,6 +1543,8 @@ lst.sensor = Отримати дані з певної будівлі чи од lst.set = Установити значення змінної. lst.operation = Виконує операцію над 1-2 змінними. lst.end = Перейти до верхньої частини стеку операцій. +lst.wait = Зачекати певну кількість секунд. +lst.lookup = Знайдіть тип елемента, рідини, одиниці чи блоку за ідентифікатором.\nМожна отримати доступ до загальної кількості кожного типу через \n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] lst.jump = Умовне переходження до іншої операції. lst.unitbind = Прив’язка до одиниці певного типу та його зберігання в [accent]@unit[]. lst.unitcontrol = Контролювати поточну прив’язану одиницю. @@ -1518,7 +1556,7 @@ logic.nounitbuild = [red]Будування за допомогою процес lenum.type = Тип будівлі чи одиниці.\nНаприклад, для будь-якого маршрутизатора (англ. router), функція вертатиме [accent]@router[].\nНе є рядком. lenum.shoot = Стріляти в зазначену позицію. lenum.shootp = Стріляти в одиницю чи будівлю із передбаченням швидкості. -lenum.configure = Конфігурація будівлі, як-от в сортувальника. +lenum.config = Конфігурація будівлі, як-от в сортувальника. lenum.enabled = Чи блок увімкнено. laccess.color = Колір освітлювача. @@ -1526,6 +1564,7 @@ laccess.controller = Керувач одиницями. Якщо процесо laccess.dead = Чи є одиниця або будівля мертвою або недійсною. laccess.controlled = Повертає \n[accent]@ctrlProcessor[] якщо одиниця контролюється процесором;\n[accent]@ctrlPlayer[] якщо одиниця чи будівля контролюєть гравцем\n[accent]@ctrlFormation[] якщо одиниця у загоні (формуванні)\nІнакше — 0. laccess.commanded = [red]Застаріле. Буде видалено![]\nВикористовуйте натомість [accent]controlled[]. +laccess.progress = Прогрес дії, від 0 до 1.\nПовертає виробництво, перезавантаження башти або хід будівництва. graphicstype.clear = Залити дисплей вказаним кольором. graphicstype.color = Установити колір для подальшої операції малювання. @@ -1560,6 +1599,9 @@ lenum.len = Довжина вектора. lenum.sin = Синус, у градусах. lenum.cos = Косинус, у градусах. lenum.tan = Тангенс, у градусах. +lenum.asin = Арксинус, у градусах. +lenum.acos = Арккосинус, у градусах. +lenum.atan = Арктангенс, у градусах. #це не одруківка, пошукайте 'позначення діапазону' lenum.rand = Випадкове десяткове число у діапазоні [0, значення). lenum.log = Натуральний логарифм (ln). From fa0f1611064657480f9febc64346afb5a457f6ba Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 28 Jul 2021 17:08:48 -0400 Subject: [PATCH 042/130] Minor swarmer range buff --- core/src/mindustry/content/Blocks.java | 2 +- core/src/mindustry/graphics/FloorRenderer.java | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 841c6265d0..8aa3bc4afa 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1604,7 +1604,7 @@ public class Blocks implements ContentList{ shots = 4; burstSpacing = 5; inaccuracy = 10f; - range = 215f; + range = 235f; xRand = 6f; size = 2; health = 300 * size * size; diff --git a/core/src/mindustry/graphics/FloorRenderer.java b/core/src/mindustry/graphics/FloorRenderer.java index 1e2247f71e..836481b92c 100644 --- a/core/src/mindustry/graphics/FloorRenderer.java +++ b/core/src/mindustry/graphics/FloorRenderer.java @@ -281,10 +281,13 @@ public class FloorRenderer{ for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize && tilex < world.width(); tilex++){ for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize && tiley < world.height(); tiley++){ Tile tile = world.rawTile(tilex, tiley); + boolean wall = tile.block().cacheLayer != CacheLayer.normal; - if(tile.block().cacheLayer != CacheLayer.normal){ + if(wall){ used.add(tile.block().cacheLayer); - }else{ + } + + if(!wall || world.isAccessible(tilex, tiley)){ used.add(tile.floor().cacheLayer); } } From bdb4ae2f85d02457d41f2c9ec7caadd00bc52097 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 28 Jul 2021 17:28:01 -0400 Subject: [PATCH 043/130] Typo fix --- core/src/mindustry/game/Gamemode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/game/Gamemode.java b/core/src/mindustry/game/Gamemode.java index 43425914c4..6e9dffc06e 100644 --- a/core/src/mindustry/game/Gamemode.java +++ b/core/src/mindustry/game/Gamemode.java @@ -23,7 +23,7 @@ public enum Gamemode{ rules.waves = true; rules.waveTimer = true; - rules.waveSpacing = 60f * Time.toMinutes; + rules.waveSpacing = 2f * Time.toMinutes; rules.teams.get(rules.waveTeam).infiniteResources = true; }, map -> map.teams.contains(state.rules.waveTeam.id)), pvp(rules -> { From 78f55765c1f81f3362b2a60f6d3555e912099923 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 28 Jul 2021 17:49:01 -0400 Subject: [PATCH 044/130] Clear fallback sprite for core thrusters --- core/assets-raw/sprites/effects/clear-effect.png | Bin 0 -> 83 bytes .../mindustry/world/blocks/storage/CoreBlock.java | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 core/assets-raw/sprites/effects/clear-effect.png diff --git a/core/assets-raw/sprites/effects/clear-effect.png b/core/assets-raw/sprites/effects/clear-effect.png new file mode 100644 index 0000000000000000000000000000000000000000..92e99b0ef349ed7a58e567c0c298464beac76842 GIT binary patch literal 83 zcmeAS@N?(olHy`uVBq!ia0y~yU|GZx^prw!Kz#wLpWw8 f|EN~zVPs%?$|TbFx-Xi6fq}u()z4*}Q$iB}f?pEn literal 0 HcmV?d00001 diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 621c36b25a..f5c8b690dd 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -29,8 +29,8 @@ public class CoreBlock extends StorageBlock{ //hacky way to pass item modules between methods private static ItemModule nextItems; - public @Load("@-thruster1") TextureRegion thruster1; //top right - public @Load("@-thruster2") TextureRegion thruster2; //bot left + public @Load(value = "@-thruster1", fallback = "clear-effect") TextureRegion thruster1; //top right + public @Load(value = "@-thruster2", fallback = "clear-effect") TextureRegion thruster2; //bot left public float thrusterLength = 14f/4f; public UnitType unitType = UnitTypes.alpha; From 4734261097cd65f772d4c0b159cfa209da365081 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 28 Jul 2021 18:08:17 -0400 Subject: [PATCH 045/130] Fixed unit building not starting when some resources are missing --- build.gradle | 6 +++++- core/src/mindustry/entities/comp/BuilderComp.java | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 419d78ee4f..fb96ef2132 100644 --- a/build.gradle +++ b/build.gradle @@ -341,7 +341,11 @@ project(":core"){ } } def changelogs = file("../fastlane/metadata/android/en-US/changelogs/") - new File(changelogs, androidVersion + ".txt").text = (result) + try{ + new File(changelogs, androidVersion + ".txt").text = (result) + }catch(Exception e){ + e.printStackTrace() + } } } diff --git a/core/src/mindustry/entities/comp/BuilderComp.java b/core/src/mindustry/entities/comp/BuilderComp.java index f45824ea1b..288150e938 100644 --- a/core/src/mindustry/entities/comp/BuilderComp.java +++ b/core/src/mindustry/entities/comp/BuilderComp.java @@ -96,7 +96,7 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{ if(!(tile.build instanceof ConstructBuild cb)){ if(!current.initialized && !current.breaking && Build.validPlace(current.block, team, current.x, current.y, current.rotation)){ - boolean hasAll = infinite || current.isRotation(team) || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item, Mathf.round(i.amount * state.rules.buildCostMultiplier))); + boolean hasAll = infinite || current.isRotation(team) || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item, Math.min(Mathf.round(i.amount * state.rules.buildCostMultiplier), 1))); if(hasAll){ Call.beginPlace(self(), current.block, team, current.x, current.y, current.rotation); From 8702ebd7062c07231ac201b27c1b847c2bd6a9b5 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 28 Jul 2021 18:20:08 -0400 Subject: [PATCH 046/130] Update deployment.yml --- .github/workflows/deployment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index b623093ff1..c4328bde36 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -39,7 +39,7 @@ jobs: cp -a Mindustry/core/build/javadoc/. docs/ cd docs git add . - git commit -m "Update ${RELEASE_VERSION:1}" + git commit --allow-empty -m "Update ${RELEASE_VERSION:1}" git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/MindustryGame/docs cd ../Mindustry - name: Update F-Droid build string From 132b1fe0c4400556fddbde8ae52f5de2f196695b Mon Sep 17 00:00:00 2001 From: buthed010203 Date: Wed, 28 Jul 2021 18:23:23 -0400 Subject: [PATCH 047/130] This bothers me (#5664) * This bothers me absolutely horrible * Update gradle.properties --- gradle.properties | 2 -- 1 file changed, 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index b48fdbacb0..3506311dc0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,5 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xms256m -Xmx1024m --illegal-access=permit -# Don't recompute annotations if sources haven't been changed -kapt.incremental.apt = true # Multithreaded kapt.use.worker.api=true # Compilation avoidance (see https://kotlinlang.org/docs/kapt.html#compile-avoidance-for-kapt-since-1-3-20) From ccb973d1dd55caeb036c68aa36b1db21d5487aca Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 29 Jul 2021 09:16:53 -0400 Subject: [PATCH 048/130] Log incompatible mod class loaders --- core/src/mindustry/mod/Mods.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/src/mindustry/mod/Mods.java b/core/src/mindustry/mod/Mods.java index cde7f8450f..ba51c54c1b 100644 --- a/core/src/mindustry/mod/Mods.java +++ b/core/src/mindustry/mod/Mods.java @@ -785,6 +785,17 @@ public class Mods implements Loadable{ loader = platform.loadJar(sourceFile, mainLoader); mainLoader.addChild(loader); Class main = Class.forName(mainClass, true, loader); + + //detect mods that incorrectly package mindustry in the jar + if((main.getSuperclass().getName().equals("mindustry.mod.Plugin") || main.getSuperclass().getName().equals("mindustry.mod.Mod")) && + main.getSuperclass().getClassLoader() != Mod.class.getClassLoader()){ + throw new IllegalArgumentException( + "This mod/plugin has loaded Mindustry dependencies from its own class loader. " + + "You are incorrectly including Mindustry dependencies in the mod JAR - " + + "make sure Mindustry is declared as `compileOnly` in Gradle, and that the JAR is created with `runtimeClasspath`!" + ); + } + metas.put(main, meta); mainMod = (Mod)main.getDeclaredConstructor().newInstance(); }else{ From a36f872b61ee5353f4c07c50932ed227fa46f9a1 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 29 Jul 2021 09:20:51 -0400 Subject: [PATCH 049/130] Use ModLoadException instead of IllegalArgumentException --- core/src/mindustry/mod/Mods.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/core/src/mindustry/mod/Mods.java b/core/src/mindustry/mod/Mods.java index ba51c54c1b..43845886d7 100644 --- a/core/src/mindustry/mod/Mods.java +++ b/core/src/mindustry/mod/Mods.java @@ -723,7 +723,7 @@ public class Mods implements Loadable{ if(!metaf.exists()){ Log.warn("Mod @ doesn't have a '[mod/plugin].[h]json' file, skipping.", sourceFile); - throw new IllegalArgumentException("Invalid file: No mod.json found."); + throw new ModLoadException("Invalid file: No mod.json found."); } ModMeta meta = json.fromJson(ModMeta.class, Jval.read(metaf.readString()).toString(Jformat.plain)); @@ -750,7 +750,7 @@ public class Mods implements Loadable{ //unload mods.remove(other); }else{ - throw new IllegalArgumentException("A mod with the name '" + baseName + "' is already imported."); + throw new ModLoadException("A mod with the name '" + baseName + "' is already imported."); } } @@ -779,7 +779,7 @@ public class Mods implements Loadable{ (meta.getMinMajor() >= 105 || headless) ){ if(ios){ - throw new IllegalArgumentException("Java class mods are not supported on iOS."); + throw new ModLoadException("Java class mods are not supported on iOS."); } loader = platform.loadJar(sourceFile, mainLoader); @@ -789,7 +789,7 @@ public class Mods implements Loadable{ //detect mods that incorrectly package mindustry in the jar if((main.getSuperclass().getName().equals("mindustry.mod.Plugin") || main.getSuperclass().getName().equals("mindustry.mod.Mod")) && main.getSuperclass().getClassLoader() != Mod.class.getClassLoader()){ - throw new IllegalArgumentException( + throw new ModLoadException( "This mod/plugin has loaded Mindustry dependencies from its own class loader. " + "You are incorrectly including Mindustry dependencies in the mod JAR - " + "make sure Mindustry is declared as `compileOnly` in Gradle, and that the JAR is created with `runtimeClasspath`!" @@ -1028,6 +1028,12 @@ public class Mods implements Loadable{ } } + public static class ModLoadException extends RuntimeException{ + public ModLoadException(String message){ + super(message); + } + } + public enum ModState{ enabled, contentErrors, From 47398f71a8022ebd1f95848d4ea78c2af760244a Mon Sep 17 00:00:00 2001 From: buthed010203 Date: Thu, 29 Jul 2021 11:13:10 -0400 Subject: [PATCH 050/130] Utility method for mods (#5667) * Utility method for mods I don't want to have to read something this horrible ever again ![](https://aethex.is-a.fail/55DesOkHk.png) * Update StorageBlock.java --- core/src/mindustry/world/blocks/storage/StorageBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/world/blocks/storage/StorageBlock.java b/core/src/mindustry/world/blocks/storage/StorageBlock.java index f0f5e6af05..260e3487bd 100644 --- a/core/src/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/mindustry/world/blocks/storage/StorageBlock.java @@ -41,7 +41,7 @@ public class StorageBlock extends Block{ } public class StorageBuild extends Building{ - protected @Nullable Building linkedCore; + public @Nullable Building linkedCore; @Override public boolean acceptItem(Building source, Item item){ From 296f9b9da52e672ae60c1c25258a7f4e04161a94 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 29 Jul 2021 11:26:01 -0400 Subject: [PATCH 051/130] Smoother bridge animation start/stop --- .../mindustry/world/blocks/distribution/ItemBridge.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/src/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/mindustry/world/blocks/distribution/ItemBridge.java index f8f3af4ab9..ffdcc793d0 100644 --- a/core/src/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/ItemBridge.java @@ -178,7 +178,7 @@ public class ItemBridge extends Block{ public int link = -1; public IntSeq incoming = new IntSeq(false, 4); public float warmup; - public float time; + public float time, timeSpeed; public boolean wasMoved, moved; public float transportCounter; @@ -295,7 +295,10 @@ public class ItemBridge extends Block{ moved = false; } - time += wasMoved ? delta() : 0f; + //smooth out animation, so it doesn't stop/start immediately + timeSpeed = Mathf.approachDelta(timeSpeed, wasMoved ? 1f : 0f, 1f / 60f); + + time += timeSpeed * delta(); checkIncoming(); From 9e1ba3e235dae8bf764f927ea7f7fd7ab44ffb58 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 09:33:35 -0400 Subject: [PATCH 052/130] Darkened chat background slightly --- core/src/mindustry/ai/formations/Formation.java | 10 ---------- core/src/mindustry/async/AsyncCore.java | 3 ++- core/src/mindustry/ui/fragments/ChatFragment.java | 2 +- gradle.properties | 2 +- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/core/src/mindustry/ai/formations/Formation.java b/core/src/mindustry/ai/formations/Formation.java index db2ce02e14..cbbb02a541 100644 --- a/core/src/mindustry/ai/formations/Formation.java +++ b/core/src/mindustry/ai/formations/Formation.java @@ -175,16 +175,6 @@ public class Formation{ return -1; } - // debug - public SlotAssignment getSlotAssignmentAt(int index){ - return slotAssignments.get(index); - } - - // debug - public int getSlotAssignmentCount(){ - return slotAssignments.size; - } - /** Writes new slot locations to each member */ public void updateSlots(){ positionOffset.set(anchor); diff --git a/core/src/mindustry/async/AsyncCore.java b/core/src/mindustry/async/AsyncCore.java index 88272feb95..5de761d0ca 100644 --- a/core/src/mindustry/async/AsyncCore.java +++ b/core/src/mindustry/async/AsyncCore.java @@ -2,6 +2,7 @@ package mindustry.async; import arc.*; import arc.struct.*; +import arc.util.async.*; import mindustry.game.EventType.*; import java.util.concurrent.*; @@ -49,7 +50,7 @@ public class AsyncCore{ executor = Executors.newFixedThreadPool(processes.size, r -> { Thread thread = new Thread(r, "AsyncLogic-Thread"); thread.setDaemon(true); - thread.setUncaughtExceptionHandler((t, e) -> Core.app.post(() -> { throw new RuntimeException(e); })); + thread.setUncaughtExceptionHandler((t, e) -> Threads.throwAppException(e)); return thread; }); } diff --git a/core/src/mindustry/ui/fragments/ChatFragment.java b/core/src/mindustry/ui/fragments/ChatFragment.java index 75eaac5ab0..4b4bd3e46d 100644 --- a/core/src/mindustry/ui/fragments/ChatFragment.java +++ b/core/src/mindustry/ui/fragments/ChatFragment.java @@ -32,7 +32,7 @@ public class ChatFragment extends Table{ private Font font; private GlyphLayout layout = new GlyphLayout(); private float offsetx = Scl.scl(4), offsety = Scl.scl(4), fontoffsetx = Scl.scl(2), chatspace = Scl.scl(50); - private Color shadowColor = new Color(0, 0, 0, 0.4f); + private Color shadowColor = new Color(0, 0, 0, 0.5f); private float textspacing = Scl.scl(10); private Seq history = new Seq<>(); private int historyPos = 0; diff --git a/gradle.properties b/gradle.properties index 3506311dc0..b4b9d4eeb2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=a9dedf9345fe888e54ab2be3c56bf8d4d2aeb2b8 +archash=1412891bd14e01db3f3cb3576cf4f7dd502dd14b From 676a064b6ba3b3c077a6df86eaa4e1de2c181ff5 Mon Sep 17 00:00:00 2001 From: RebornTrack970 <62565267+RebornTrack970@users.noreply.github.com> Date: Fri, 30 Jul 2021 17:46:25 +0300 Subject: [PATCH 053/130] Updated TR bundle to Build 21565 (#5671) --- core/assets/bundles/bundle_tr.properties | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 8fbcd2b97c..9ed3cf52b6 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -101,6 +101,7 @@ customgame = Özel Oyun newgame = Yeni Oyun none = none.found = [lightgray] +none.inmap = [lightgray] minimap = Harita position = Pozisyon close = Kapat @@ -214,6 +215,7 @@ hosts.none = [lightgray]Yerel oyun bulunamadı! host.invalid = [scarlet]Kurucuya bağlanılamıyor. servers.local = Yerel Sunucular +servers.local.steam = Açık Oyunar & Yerel Sunucular servers.remote = Uzak Sunucular servers.global = Topluluk Sunucuları @@ -565,6 +567,7 @@ sectors.unexplored = [lightgray]Keşfedilmemiş sectors.resources = Kaynaklar: sectors.production = Üretim: sectors.export = İhracat: +sectors.import = İthalat: sectors.time = Zaman: sectors.threat = Tehlike: sectors.wave = Dalga: @@ -806,6 +809,7 @@ bullet.reload = [stat]{0}[lightgray]x atış hızı unit.blocks = blok unit.blockssquared = blok² unit.powersecond = enerji birimi/saniye +unit.tilessecond = alan/saniye unit.liquidsecond = sıvı birimi/saniye unit.itemssecond = eşya/saniye unit.liquidunits = sıvı birimi @@ -871,7 +875,8 @@ setting.saveinterval.name = Kayıt Aralığı setting.seconds = {0} Saniye setting.milliseconds = {0} milisaniye setting.fullscreen.name = Tam Ekran -setting.borderlesswindow.name = Kenarsız Pencere [lightgray](yeniden açmak gerekebilir) +setting.borderlesswindow.name = Kenarsız Pencere +setting.borderlesswindow.description = Oyunu baştan açman gerekebilir. setting.fps.name = FPS Göster setting.smoothcamera.name = Yumuşak Geçişli Kamera setting.vsync.name = VSync @@ -994,6 +999,7 @@ rules.wavetimer = Dalga Zamanlayıcısı rules.waves = Dalgalar rules.attack = Saldırı Modu rules.buildai = Yapay Zeka İnşası +rules.cleanupdeadteams = Kaybeden Takımın Bloklarını Temizle (PvP) rules.corecapture = Yıkımca Çekirdeği Elegeçir rules.polygoncoreprotection = Çokgenli Çekirdek Koruması rules.enemyCheat = Sonsuz AI (Kırmızı Takım) Kaynakları @@ -1288,7 +1294,6 @@ block.meltdown.name = Meltdown block.foreshadow.name = Foreshadow block.container.name = Konteyner block.launch-pad.name = Kalkış Pisti -block.launch-pad-large.name = Büyük Kalkış Pisti block.segment.name = Segment block.command-center.name = Komuta Merkezi block.ground-factory.name = Yer Birimi Fabrikası @@ -1348,6 +1353,7 @@ hint.placeTurret = \uf861 [accent]Silahlar[] seni düşman birimlerinden korumak hint.breaking = Blokları silmek için silmek istediğiniz objelerin üstüne [accent]Sağ Tıklayın[]. Birden fazla obje silmek için sağ tuşu basılı tutun ve farenizi sürükleyin. hint.breaking.mobile = Ekranın sağ altındaki \ue817 [accent]çekiç[] tuşuna basın ve silmek istediğiniz objelere tıklayın. \n\nBirden fazla obje silmek için parmağınızı ekranda 1 saniye basılı tutun ve parmağınızı sürükleyin. hint.blockInfo = Bir blok hakkında bilgiyi görüntülemek için [accent]inşa menüsüne[] tıklayın. Sonra sağdaki [accent][[?][] sembolüne tıklayın. +hint.derelict = [accent]Sahipsiz[] binalar artık çalışmaz durumdadır. \n\nBu binaları [accent]yıkarsanız[] size malzeme verirler. hint.research = \ue875 [accent]Araştırma[] sekmesini kullanarak yeni teknolojiler araştırabilirsiniz. hint.research.mobile = \ue88c [accent]Menüdeki[] \ue875 [accent]Araştırma[] sekmesini kullanarak yeni teknolojiler araştırabilirsiniz. hint.unitControl = Kendi takımınızdaki taret ve birimleri kontrol etmek için [accent][[Sol CTRL][] tuşunu basılı tutarak istediğiniz taretin yada birimin üstüne sol tıklayın. @@ -1369,8 +1375,6 @@ hint.generator = \uf879 [accent]Termik Jeneratör[] kömür yakarak enerji üret hint.guardian = [accent]Gardiyan[] birimleri güçlü bir zırha sahiptir. [accent]bakır[] ve [accent]kurşun[] gibi mermilere karşı [scarlet]Dayanıklıdır[].\n\nGardiyanları öldürmek için [accent]salvo[] gibi daha güçlü taretleri ve \uf835 [accent]grafit[] gibi daha çok hasar veren mermileri kullanın. hint.coreUpgrade = Merkezinizi, [accent]merkezinizin üstüne daha gelişmiş bir merkez[] koyarak geliştirebilirsiniz. \n\n[accent]Parçacık[] olarak adlandırılan fakirhanenizin üstüne [accent]Temel[] olarak adlandırılan merkezinizi koyun. Merkezinizin etrafında hiçbir yapı olmamalıdır. hint.presetLaunch = [accent]Donmuş Ormanlar[] gibi [accent]ana sektörlere iniş[] herhangi bir yerden yapılabilir. Yakındaki bir sektörden fırlatma gerektirmez.\n\nBunun gibi [accent]sayı ile isimlendirilmiş[] sektörleri ele geçirmek [accent]isteğe bağlıdır.[]. -hint.coreUpgrade = Bir çekirdeğin Üstüne başka bir çekirdek koayarak onu geliştirebilirsin!\n\n Daha gelişmiş çekirdekler daha fazla kapasite demektir. -hint.presetLaunch = Hikaye Sektörlerine her yerden fırltış yapabilirsin! Ancak Numaralı Sektörlere temas olmadan Fırlatış yapılamaz. hint.coreIncinerate = Bir çekirdek ağzına kadar dolduktan sonra, ekstra itemler [accent]eritilir[]. hint.coopCampaign = Arkadaşlarınla Multiplayer Campaign oynarken, her yaptığınız Araştırma ve item aktarımı, senin oyun içi Campaign ine de aktarılır. #Yukarıdaki bağzı cümleler Anti Dragon tarafından çevirildi. @@ -1401,6 +1405,7 @@ liquid.slag.description = Çeşitli tipte erimiş metallerin birbirine karışı liquid.oil.description = İleri seviye malzeme üretiminde kullanılan bir sıvıdır. Yakıt olarak kömür haline getirilebilir veya püskürtülüp ateşe verilerek bir silah olarak kullanılabilir. liquid.cryofluid.description = Su ve titanyumdan oluşturulan inaktif bir sıvı. Son derece yüksek ısı kapasitesine sahiptir. Soğutucu olarak yaygın olarak kullanılır. +block.derelict = [lightgray] Sahipsiz block.resupply-point.description = Yakındaki birimlere mermi verir. Elektikle çalışmaz. block.armored-conveyor.description = Materyalleri titanyum konveyörlerle aynı hızda taşır ama daha fazla zırha sahiptir. Diğer konveyörler dışında yan taraflardan materyal kabul etmez. block.illuminator.description = Küçük, kompakt, yapılandırılabilir bir ışık kaynağı. Çalışması için enerji gerekir. @@ -1504,7 +1509,6 @@ block.vault.description = Her materyalden az miktarda saklar. Materyalleri kasad block.container.description = Her materyalden az miktarda saklar. Materyalleri konteynerden almak için bir boşaltıcı bloğu kullanılabilir. block.unloader.description = Materyalleri bir konteyner, kasa, veya çekirdekten çıkarıp; bir konveyöre veya dibindeki bir bloğa koyar. Çıkardığı materyal türü dokunularak değiştirilebilir. block.launch-pad.description = Başka Bir Sektöre item gönderir. -block.launch-pad-large.description = Kalkış pistinin daha gelişmiş bir versiyonu. Daha fazla materyali daha sık gönderebilir. block.duo.description = Küçük, ucuz bir taret. Yer birimlerine karşı etkilidir. block.scatter.description = Önemli bir uçaksavar tareti. Düşman birimlerine hurda ya da kurşun uçaksavar mermileri atar. block.scorch.description = Etrafındaki düşmanları ateşe verir. Yakın mesafede çok etkilidir. @@ -1519,6 +1523,7 @@ block.ripple.description = Çok güçlü bir havan tareti. Uzak mesafedeki düş block.cyclone.description = Büyük bir anti hava ve anti kara tareti. Yakınındaki düşmanlara patlayıcı uçaksavar mermi kümeleri atar. block.spectre.description = Dev bir çift namlulu top. Hava ve kara birimlerine iri, zırh delici mermiler atar. block.meltdown.description = Dev bir lazer topu. Yüklenip yakındaki düşmanlara uzun süreli lazer ışınları yollar. Çalışması için soğutucu gerekir. +block.foreshadow.description = Çok uzaktaki Tek bir hedefe inanılmaz güçlü bir şok ışını vurur. En fazla canı olan elemanı hedef alır. block.repair-point.description = Kendisine en yakın hasarlı birimi tamir eder. block.segment.description = Gelen mermilere zarar verir ve onları yok eder. Lazer mermilere etki etmez. block.parallax.description = Çekici bir ışın fırlatarak hava düşmanlarını kendine çeker. Onlara az da olsa zarar verir. @@ -1545,6 +1550,8 @@ block.memory-bank.description = Bilgi saklar. Yüksek kapasiteye sahiptir. block.logic-display.description = Bir işlemciden bilgi alarak grafik gösteririr. block.large-logic-display.description = Bir işlemciden bilgi alarak grafik gösteririr. block.interplanetary-accelerator.description = Gezegenler Arası ulaşım şimdi parmaklarının ucunda... +block.repair-turret.description = Sürekli en yakın elemanı tamir eder. Soğutucu kullanabilir. +block.payload-propulsion-tower.description = Kütle sürücü gibi bir yerden başka bir yere fırlatır, ancak malzeme yerine yük fırlatmakta kullanılır. #burdan sonraki her şeyi benim translate etmem gerekti!!! -RTOmega unit.dagger.description = Düşmanlara basit mermilerle ateş eder. unit.mace.description = Düşmanlara alev atar. @@ -1579,6 +1586,11 @@ unit.omura.description = Uzun menzil bir ışın atıcıya sahiptir. Mermisi ner unit.alpha.description = Çekirdeği korur. Bina inşa eder. unit.beta.description = Çekirdeği korur. Bina inşa eder. unit.gamma.description = Çekirdeği korur. Bina inşa eder. +unit.retusa.description = Sensörlü mayın döşer. Yakındakileri tamir eder. +unit.oxynoe.description = Tamir edici ateş fırlatır. Düşman mermilerini havada vurur. +unit.cyerce.description = Takipçi toplu füze atar. Yakındakileri tamir eder. +unit.aegires.description = Enerji alanına giren düşmanları şoklar. Yakındakileri tamir eder. +unit.navanax.description = Devasa patlayıcı EMP gülleleri fırlatır, düşman elektir sistemlerini yok eder ve müttefiklerini tamir eder. Yaklaşan düşmanları 4 mini oto-laser turreti ile eritir. lst.read = Bağlı hafıza kutusundaki numarayı okur. lst.write = Bağlı hafıza kutuaundaki numaraya yazar. @@ -1593,6 +1605,8 @@ lst.sensor = Bloklardan bilgi alır. lst.set = Bir değişken ata. lst.operation = Değişkenlerle işlem yap. lst.end = Döngünün sonuna atla. +lst.wait = Belli süre bekler. +lst.lookup = ID kullanarak herhangi bir blok,eleman,bina vs ye bak.\nToplam sayı kullanımı:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] lst.jump = Bir yerden başka bir yere atla. lst.unitbind = Bir birimi bağla: [accent]@unit[]. lst.unitcontrol = Bağlı birimi kontrol et. From fc41ad36f7bd25fabcf4dc07873286536057ec90 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 11:58:01 -0400 Subject: [PATCH 054/130] Fixed damaged building memory leak --- core/src/mindustry/ai/BlockIndexer.java | 59 ++++++++++--------- core/src/mindustry/entities/Units.java | 2 +- .../mindustry/entities/comp/BuildingComp.java | 13 ++++ core/src/mindustry/maps/Maps.java | 2 + core/src/mindustry/maps/SectorDamage.java | 2 +- core/src/mindustry/world/Tile.java | 2 +- .../world/blocks/ConstructBlock.java | 5 ++ 7 files changed, 54 insertions(+), 31 deletions(-) diff --git a/core/src/mindustry/ai/BlockIndexer.java b/core/src/mindustry/ai/BlockIndexer.java index a01e6e1b39..6cc184ad38 100644 --- a/core/src/mindustry/ai/BlockIndexer.java +++ b/core/src/mindustry/ai/BlockIndexer.java @@ -13,7 +13,6 @@ import mindustry.game.Teams.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; -import mindustry.world.blocks.*; import mindustry.world.meta.*; import java.util.*; @@ -32,7 +31,7 @@ public class BlockIndexer{ /** Stores all ore quadrants on the map. Maps ID to qX to qY to a list of tiles with that ore. */ private IntSeq[][][] ores; /** Stores all damaged tile entities by team. */ - private ObjectSet[] damagedTiles = new ObjectSet[Team.all.length]; + private Seq[] damagedTiles = new Seq[Team.all.length]; /** All ores available on this map. */ private ObjectSet allOres = new ObjectSet<>(); /** Stores teams that are present here as tiles. */ @@ -59,7 +58,7 @@ public class BlockIndexer{ }); Events.on(WorldLoadEvent.class, event -> { - damagedTiles = new ObjectSet[Team.all.length]; + damagedTiles = new Seq[Team.all.length]; flagMap = new TileArray[Team.all.length][BlockFlag.all.length]; activeTeams = new Seq<>(Team.class); @@ -74,10 +73,6 @@ public class BlockIndexer{ for(Tile tile : world.tiles){ process(tile); - if(tile.build != null && tile.build.damaged()){ - notifyTileDamaged(tile.build); - } - var drop = tile.drop(); if(drop != null){ @@ -104,6 +99,7 @@ public class BlockIndexer{ public void removeIndex(Tile tile){ var team = tile.team(); if(tile.build != null && tile.isCenter()){ + var build = tile.build; var flags = tile.block().flags; var data = team.data(); @@ -118,7 +114,15 @@ public class BlockIndexer{ //unregister building from building quadtree if(data.buildings != null){ - data.buildings.remove(tile.build); + data.buildings.remove(build); + } + + //is no longer registered + build.wasDamaged = false; + + //unregister damaged buildings + if(build.damaged() && damagedTiles[team.id] != null){ + damagedTiles[team.id].remove(build); } } } @@ -175,25 +179,12 @@ public class BlockIndexer{ } /** Returns all damaged tiles by team. */ - public ObjectSet getDamaged(Team team){ - breturnArray.clear(); - + public Seq getDamaged(Team team){ if(damagedTiles[team.id] == null){ - damagedTiles[team.id] = new ObjectSet<>(); + return null; } - ObjectSet set = damagedTiles[team.id]; - for(Building build : set){ - if((!build.isValid() || build.team != team || !build.damaged()) || build.block instanceof ConstructBlock){ - breturnArray.add(build); - } - } - - for(Building tile : breturnArray){ - set.remove(tile); - } - - return set; + return damagedTiles[team.id]; } /** Get all allied blocks with a flag. */ @@ -271,12 +262,22 @@ public class BlockIndexer{ return returnArray; } - public void notifyTileDamaged(Building entity){ - if(damagedTiles[entity.team.id] == null){ - damagedTiles[entity.team.id] = new ObjectSet<>(); + public void notifyBuildHealed(Building build){ + if(build.wasDamaged && !build.damaged() && damagedTiles[build.team.id] != null){ + damagedTiles[build.team.id].remove(build); + build.wasDamaged = false; + } + } + + public void notifyBuildDamaged(Building build){ + if(build.wasDamaged || !build.damaged()) return; + + if(damagedTiles[build.team.id] == null){ + damagedTiles[build.team.id] = new Seq<>(false); } - damagedTiles[entity.team.id].add(entity); + damagedTiles[build.team.id].add(build); + build.wasDamaged = true; } public void allBuildings(float x, float y, float range, Cons cons){ @@ -417,6 +418,8 @@ public class BlockIndexer{ data.buildings = new QuadTree<>(new Rect(0, 0, world.unitWidth(), world.unitHeight())); } data.buildings.insert(tile.build); + + notifyBuildDamaged(tile.build); } if(!tile.block().isStatic()){ diff --git a/core/src/mindustry/entities/Units.java b/core/src/mindustry/entities/Units.java index 52e6ad749c..ae4f8e00eb 100644 --- a/core/src/mindustry/entities/Units.java +++ b/core/src/mindustry/entities/Units.java @@ -143,7 +143,7 @@ public class Units{ /** Returns the nearest damaged tile. */ public static Building findDamagedTile(Team team, float x, float y){ - return Geometry.findClosest(x, y, indexer.getDamaged(team)); + return indexer.getDamaged(team).min(b -> b.dst2(x, y)); } /** Returns the nearest ally tile in a range. */ diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 25e0114e23..d5bedacc3e 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -63,6 +63,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, transient boolean enabled = true; transient float enabledControlTime; transient String lastAccessed; + transient boolean wasDamaged; //used only by the indexer PowerModule power; ItemModule items; @@ -1344,6 +1345,18 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, return tile.build == self() && !dead(); } + @MethodPriority(100) + @Override + public void heal(){ + indexer.notifyBuildHealed(self()); + } + + @MethodPriority(100) + @Override + public void heal(float amount){ + indexer.notifyBuildHealed(self()); + } + @Override public float hitSize(){ return tile.block().size * tilesize; diff --git a/core/src/mindustry/maps/Maps.java b/core/src/mindustry/maps/Maps.java index 613067f61f..b6a2f1fc1e 100644 --- a/core/src/mindustry/maps/Maps.java +++ b/core/src/mindustry/maps/Maps.java @@ -420,6 +420,8 @@ public class Maps{ writeCache(map); }catch(Exception e){ e.printStackTrace(); + }finally{ + pix.dispose(); } }); }catch(Exception e){ diff --git a/core/src/mindustry/maps/SectorDamage.java b/core/src/mindustry/maps/SectorDamage.java index 786074c3dd..5ee6e1f15a 100644 --- a/core/src/mindustry/maps/SectorDamage.java +++ b/core/src/mindustry/maps/SectorDamage.java @@ -496,7 +496,7 @@ public class SectorDamage{ other.build.addPlan(false); other.remove(); }else{ - indexer.notifyTileDamaged(other.build); + indexer.notifyBuildDamaged(other.build); } }else if(other.solid() && !other.synthetic()){ //skip damage propagation through solid blocks diff --git a/core/src/mindustry/world/Tile.java b/core/src/mindustry/world/Tile.java index ebe5d21414..624dc300b6 100644 --- a/core/src/mindustry/world/Tile.java +++ b/core/src/mindustry/world/Tile.java @@ -675,7 +675,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{ build.health = health; if(build.damaged()){ - indexer.notifyTileDamaged(build); + indexer.notifyBuildDamaged(build); } } diff --git a/core/src/mindustry/world/blocks/ConstructBlock.java b/core/src/mindustry/world/blocks/ConstructBlock.java index 0bc7115142..63f66a9afa 100644 --- a/core/src/mindustry/world/blocks/ConstructBlock.java +++ b/core/src/mindustry/world/blocks/ConstructBlock.java @@ -84,6 +84,11 @@ public class ConstructBlock extends Block{ if(builder != null && builder.getControllerName() != null){ tile.build.lastAccessed = builder.getControllerName(); } + + //make sure block indexer knows it's damaged + if(tile.build.damaged()){ + indexer.notifyBuildDamaged(tile.build); + } } //last builder was this local client player, call placed() From d855840fe2fd35a04669d988f4648198168814c2 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 13:05:12 -0400 Subject: [PATCH 055/130] Fixed #5672 --- core/assets/bundles/bundle.properties | 1 - gradle.properties | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index f03d682c12..4611e95efc 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -876,7 +876,6 @@ setting.seconds = {0} seconds setting.milliseconds = {0} milliseconds setting.fullscreen.name = Fullscreen setting.borderlesswindow.name = Borderless Window -setting.borderlesswindow.description = Restart may be required to apply changes. setting.fps.name = Show FPS & Ping setting.smoothcamera.name = Smooth Camera setting.vsync.name = VSync diff --git a/gradle.properties b/gradle.properties index b4b9d4eeb2..cab920b8aa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=1412891bd14e01db3f3cb3576cf4f7dd502dd14b +archash=0923799dd6adf2626b72cc30fc880425ea7eb3e0 From a7cc6185ad31cd27810705fa777528f286462521 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 14:27:46 -0400 Subject: [PATCH 056/130] Proper name/impl for "borderless windowed" on Windows --- core/assets/bundles/bundle.properties | 2 ++ .../ui/dialogs/SettingsMenuDialog.java | 20 ++++++++++++++++--- gradle.properties | 2 +- tests/src/test/java/power/FakeGraphics.java | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 4611e95efc..49674781a9 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -876,6 +876,8 @@ setting.seconds = {0} seconds setting.milliseconds = {0} milliseconds setting.fullscreen.name = Fullscreen setting.borderlesswindow.name = Borderless Window +setting.borderlesswindow.name.windows = Borderless Fullscreen +setting.borderlesswindow.description = Restart may be required to apply changes. setting.fps.name = Show FPS & Ping setting.smoothcamera.name = Smooth Camera setting.vsync.name = VSync diff --git a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java index 7ba99bf975..38b6587322 100644 --- a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -369,6 +369,12 @@ public class SettingsMenuDialog extends Dialog{ if(!mobile){ graphics.checkPref("vsync", true, b -> Core.graphics.setVSync(b)); graphics.checkPref("fullscreen", false, b -> { + if(b && settings.getBool("borderlesswindow")){ + Core.graphics.setWindowedMode(Core.graphics.getWidth(), Core.graphics.getHeight()); + settings.put("borderlesswindow", false); + graphics.rebuild(); + } + if(b){ Core.graphics.setFullscreenMode(Core.graphics.getDisplayMode()); }else{ @@ -376,7 +382,14 @@ public class SettingsMenuDialog extends Dialog{ } }); - graphics.checkPref("borderlesswindow", false, b -> Core.graphics.setUndecorated(b)); + graphics.checkPref("borderlesswindow", false, b -> { + if(b && settings.getBool("fullscreen")){ + Core.graphics.setWindowedMode(Core.graphics.getWidth(), Core.graphics.getHeight()); + settings.put("fullscreen", false); + graphics.rebuild(); + } + Core.graphics.setBorderless(b); + }); Core.graphics.setVSync(Core.settings.getBool("vsync")); if(Core.settings.getBool("fullscreen")){ @@ -384,7 +397,7 @@ public class SettingsMenuDialog extends Dialog{ } if(Core.settings.getBool("borderlesswindow")){ - Core.app.post(() -> Core.graphics.setUndecorated(true)); + Core.app.post(() -> Core.graphics.setBorderless(true)); } }else if(!ios){ graphics.checkPref("landscape", false, b -> { @@ -612,7 +625,8 @@ public class SettingsMenuDialog extends Dialog{ Setting(String name){ this.name = name; - title = bundle.get("setting." + name + ".name"); + String winkey = "setting." + name + ".name.windows"; + title = OS.isWindows && bundle.has(winkey) ? bundle.get(winkey) : bundle.get("setting." + name + ".name"); description = bundle.getOrNull("setting." + name + ".description"); } diff --git a/gradle.properties b/gradle.properties index cab920b8aa..76a0b34f29 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=0923799dd6adf2626b72cc30fc880425ea7eb3e0 +archash=e83b7b1c440763e585bcc3871b21e8dc89cf5a07 diff --git a/tests/src/test/java/power/FakeGraphics.java b/tests/src/test/java/power/FakeGraphics.java index 5f64aa61f3..4bbd0bb24c 100644 --- a/tests/src/test/java/power/FakeGraphics.java +++ b/tests/src/test/java/power/FakeGraphics.java @@ -154,7 +154,7 @@ public class FakeGraphics extends Graphics{ } @Override - public void setUndecorated(boolean undecorated){ + public void setBorderless(boolean undecorated){ } From eac11045fff6b4a302aefedf3514649aae902f00 Mon Sep 17 00:00:00 2001 From: Andrew Antsiferov Date: Fri, 30 Jul 2021 21:57:23 +0300 Subject: [PATCH 057/130] Fix typo (#5674) of the -> of the tile. --- core/src/mindustry/world/Tile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/world/Tile.java b/core/src/mindustry/world/Tile.java index 624dc300b6..776cb976f3 100644 --- a/core/src/mindustry/world/Tile.java +++ b/core/src/mindustry/world/Tile.java @@ -108,7 +108,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{ } /** - * Returns the flammability of the Used for fire calculations. + * Returns the flammability of the tile. Used for fire calculations. * Takes flammability of floor liquid into account. */ public float getFlammability(){ From 2d35a024e293eca641181784d3aaf5e4f3580099 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 15:29:12 -0400 Subject: [PATCH 058/130] arc --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 76a0b34f29..896a0fed1f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=e83b7b1c440763e585bcc3871b21e8dc89cf5a07 +archash=6181955e8f540af889fe825140285aa26316a810 From 0c03c47eb9bb577c25a17140e483e5844d50d240 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 16:26:25 -0400 Subject: [PATCH 059/130] Disabled crash sending + arc --- core/src/mindustry/net/CrashSender.java | 12 +++++------- .../src/mindustry/ui/dialogs/SettingsMenuDialog.java | 1 + gradle.properties | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/core/src/mindustry/net/CrashSender.java b/core/src/mindustry/net/CrashSender.java index 1f3720c8ac..75e1b5b2f9 100644 --- a/core/src/mindustry/net/CrashSender.java +++ b/core/src/mindustry/net/CrashSender.java @@ -6,19 +6,14 @@ import arc.func.*; import arc.struct.*; import arc.util.*; import arc.util.io.*; -import arc.util.serialization.*; -import arc.util.serialization.JsonValue.*; -import arc.util.serialization.JsonWriter.*; import mindustry.*; import mindustry.core.*; -import mindustry.gen.*; import java.io.*; import java.text.*; import java.util.*; import static arc.Core.*; -import static mindustry.Vars.net; import static mindustry.Vars.*; public class CrashSender{ @@ -126,6 +121,9 @@ public class CrashSender{ }catch(Throwable ignored){ } + //disabled until further notice. + /* + JsonValue value = new JsonValue(ValueType.object); boolean fn = netActive, fs = netServer; @@ -144,7 +142,7 @@ public class CrashSender{ ex(() -> value.addChild("trace", new JsonValue(parseException(exception)))); ex(() -> value.addChild("javaVersion", new JsonValue(OS.javaVersion))); ex(() -> value.addChild("javaArch", new JsonValue(OS.osArchBits))); - + Log.info("Sending crash report."); //post to crash report URL, exit code indicates send success @@ -154,7 +152,7 @@ public class CrashSender{ }).block(r -> { Log.info("Crash sent successfully."); System.exit(1); - }); + });*/ ret(); }catch(Throwable death){ diff --git a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java index 38b6587322..10f399bbe2 100644 --- a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -392,6 +392,7 @@ public class SettingsMenuDialog extends Dialog{ }); Core.graphics.setVSync(Core.settings.getBool("vsync")); + if(Core.settings.getBool("fullscreen")){ Core.app.post(() -> Core.graphics.setFullscreenMode(Core.graphics.getDisplayMode())); } diff --git a/gradle.properties b/gradle.properties index 896a0fed1f..be8f1289e5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=6181955e8f540af889fe825140285aa26316a810 +archash=1af9470cb128e1039ab18687bc7cebb767af2207 From 3b9700793c597ca957c93d2eec3403e1d1900dc0 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 16:43:26 -0400 Subject: [PATCH 060/130] arc --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index be8f1289e5..fa2c4dd9da 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=1af9470cb128e1039ab18687bc7cebb767af2207 +archash=87dc1fa9933949b3e8ea9acfb4df8323e79faea4 From 7d72c4dc63305eb2e38237595a025c3abd846b38 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 18:13:30 -0400 Subject: [PATCH 061/130] arc --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index fa2c4dd9da..3a34b63ae9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=87dc1fa9933949b3e8ea9acfb4df8323e79faea4 +archash=b276a42320695b3f5367d7205b66797ab99934ae From 6d58997f71de4b14c21b154488084893e7fef53c Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 18:35:50 -0400 Subject: [PATCH 062/130] arc --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 3a34b63ae9..8b55d416f4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=b276a42320695b3f5367d7205b66797ab99934ae +archash=5158cb48c45ebd950ef2da200638ca497903d15f From d02a017c03acbdc0460182a8663bbe5b327765f3 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 18:59:18 -0400 Subject: [PATCH 063/130] arc --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8b55d416f4..198bed30a8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=5158cb48c45ebd950ef2da200638ca497903d15f +archash=41c08078107a6af4e180125dad3a174cab98656a From f354b6bcca6db7cba2fa253bb375a8db6b292b32 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 19:43:29 -0400 Subject: [PATCH 064/130] pulverizer drawSpinSprite --- core/src/mindustry/content/Blocks.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 8aa3bc4afa..b48e0ccc96 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -702,7 +702,9 @@ public class Blocks implements ContentList{ craftTime = 40f; updateEffect = Fx.pulverizeSmall; hasItems = hasPower = true; - drawer = new DrawRotator(); + drawer = new DrawRotator(){{ + drawSpinSprite = true; + }}; ambientSound = Sounds.grinding; ambientSoundVolume = 0.025f; From 8f6fe08b1c29e9532c9584435f5363b23ac3477d Mon Sep 17 00:00:00 2001 From: BlueWolf <61173114+BlueWolf3682@users.noreply.github.com> Date: Fri, 30 Jul 2021 19:51:35 -0600 Subject: [PATCH 065/130] fix some misleading comments (#5676) --- core/src/mindustry/world/blocks/environment/Floor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/world/blocks/environment/Floor.java b/core/src/mindustry/world/blocks/environment/Floor.java index 9bb4cc5aed..c2fa4c1165 100644 --- a/core/src/mindustry/world/blocks/environment/Floor.java +++ b/core/src/mindustry/world/blocks/environment/Floor.java @@ -28,7 +28,7 @@ public class Floor extends Block{ public float dragMultiplier = 1f; /** Damage taken per tick on this tile. */ public float damageTaken = 0f; - /** How many ticks it takes to drown on this. */ + /** How many ticks it takes to drown on this. 0 to disable. */ public float drownTime = 0f; /** Effect when walking on this floor. */ public Effect walkEffect = Fx.none; @@ -42,11 +42,11 @@ public class Floor extends Block{ public StatusEffect status = StatusEffects.none; /** Intensity of applied status effect. */ public float statusDuration = 60f; - /** liquids that drop from this block, used for pumps */ + /** liquids that drop from this block, used for pumps. */ public @Nullable Liquid liquidDrop = null; /** Multiplier for pumped liquids, used for deep water. */ public float liquidMultiplier = 1f; - /** whether this block can be drowned in */ + /** whether this block is liquid. */ public boolean isLiquid; /** if true, this block cannot be mined by players. useful for annoying things like sand. */ public boolean playerUnmineable = false; From 589430055e651b53214d56673bda1bd87f390c92 Mon Sep 17 00:00:00 2001 From: JrTRinny <85090668+JrTRinny@users.noreply.github.com> Date: Sat, 31 Jul 2021 09:19:27 +0700 Subject: [PATCH 066/130] translation update (#5670) --- core/assets/bundles/bundle_th.properties | 31 ++++++++++++------------ 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/core/assets/bundles/bundle_th.properties b/core/assets/bundles/bundle_th.properties index 4553c81ef3..ff7832ad63 100644 --- a/core/assets/bundles/bundle_th.properties +++ b/core/assets/bundles/bundle_th.properties @@ -605,7 +605,7 @@ planet.sun.name = ดวงอาทิตย์ sector.impact0078.name = อิมแพค 0078 sector.groundZero.name = กราวน์ ซีโร่ sector.craters.name = บ่ออุกกาบาต -sector.frozenForest.name = ป่าหนาวแหน็บ +sector.frozenForest.name = ป่าหนาวเหน็บ sector.ruinousShores.name = ชายฝั่งพังทลาย sector.stainedMountains.name = ภูเขาหลากสี sector.desolateRift.name = เดโซเลต ริฟต์ @@ -624,8 +624,8 @@ sector.frozenForest.description = แม้แต่ที่นี่ ที่ sector.saltFlats.description = ณ ขอบของทะเลทราย เป็นที่ตั้งของที่ราบเกลือ สามารถพบทรัพยากรบางอย่างได้ที่นี่\n\nศัตรูได้ตั้งฐานเก็บทรัพยากรไว้ที่นี่ ทำลายแกนกลางของพวกมัน อย่าให้มีอะไรเหลือ sector.craters.description = น้ำขังอยู่ในหลุมอุกกาบาศแห่งนี้ อนุสรณ์สถานของสงครามเก่าแก่ ยึดพื้นที่นี่มา เก็บทราย เผา[accent]กระจกเมต้า[] ปั๊มน้ำเพื่อมาหล่อเย็นป้อมปืนและเครื่องขุดเจาะ sector.ruinousShores.description = ถัดจากทะเลทราย เป็นที่ตั้งของชายฝั่ง ที่ครั้งก่อน เคยเป็นที่ตั้งของฐานป้องกันชายฝั่ง ซึ่งทุกทำลายไปซะส่วนใหญ่แล้ว มีเหลือแค่ระบบการป้องกันพื้นฐาน ทุกอย่างที่เหลือถูกทำลายเหลือเพียงแค่เศษเหล็ก\n\nทำการขยายการสำรวจต่อไป ค้นพบกับเทคโนโลยีอีกครั้ง -sector.stainedMountains.description = เข้าลึกไปในพื้นที่ จะพบกับภูเขา ซึ่งยังไม่ถูกสปอร์แตะต้อง\nขุด[accent]ไทเทเนี่ยม[]ที่อุดมสมบูรณ์ในพื้นที่นี้ เรียนรู้ที่จะใช้มัน\n\nมีศัตรูมากขึ้นในบริเวณนี้ อย่าปล่อยให้พวกมันส่งยูนิตที่แข็งแกร่งที่สุดของพวกมันออกมา -sector.overgrowth.description = พื้นที่นี้ถูกปกคลุมไปด้วยพืช เข้าใกล้กับแหล่งกำเนิดของสปอร์\nศัตรูได้ตั้งฐานเฝ้าระวังไว้ที่นี่ สร้างยูนิตเมส ทำลายฐานซะ\nวิจัย[accent]เครื่องพัฒนารุ่นยกกำลัง[]เพื่อผลิตยูนิตขนาดที่ใหญ่ขึ้น +sector.stainedMountains.description = เข้าลึกไปในพื้นที่ จะพบกับภูเขา ซึ่งยังไม่ถูกสปอร์แตะต้อง\nขุด[accent]ไทเทเนี่ยม[]ที่อุดมสมบูรณ์ในพื้นที่นี้ เรียนรู้ที่จะใช้มัน\n\nมีศัตรูปรากฏตัวมากขึ้นในบริเวณนี้ อย่าปล่อยให้พวกมันส่งยูนิตที่แข็งแกร่งที่สุดออกมา +sector.overgrowth.description = พื้นที่นี้ถูกปกคลุมไปด้วยพืช เข้าใกล้กับแหล่งกำเนิดของสปอร์\nศัตรูได้ตั้งฐานเฝ้าระวังไว้ที่นี่ สร้างยูนิตเมส ทำลายฐานทิ้งซะ\nวิจัย[accent]เครื่องพัฒนารุ่นยกกำลัง[]เพื่อผลิตยูนิตขนาดที่ใหญ่ขึ้น sector.tarFields.description = ขอบของพื้นที่ผลิตน้ำมัน อยู่ระหว่างภูเขาและทะเลทราย หนึ่งในพื้นที่ที่มีแหล่งน้ำมันดิบที่ใช้งานได้\nแม้ว่าจะถูกทิ้งร้าง พื้นที่นี้ยังคงมีฐานทัพของศัตรูอยู่ใกล้ๆ อย่าประมาทกับพวกมัน\n\n[lightgray]วิจัยเทคโนโลยีการแปรรูปน้ำมันหากเป็นไปได้ sector.desolateRift.description = เป็นพื้นที่ที่อันตรายมาก ทรัพยากรมากมาย แต่พื้นที่แคบ ความเสี่ยงการโดนทำลายล้างสูง ออกไปจากที่นี่ให้เร็วที่สุด อย่าถูกหลอกโดยระยะเวลาระหว่างการโจมตีของศัตรูที่เว้นไว้นานกว่าปกติ sector.nuclearComplex.description = สถานที่ผลิตและแปรรูปทอเรี่ยมเก่า ถูกทำลายไม่เหลือสิ้น\nวิจัยทอเรี่ยมและวิธีการใช้มัน\n\nศัตรูในบริเวณนี้มีจำนวนมาก คอยตรวจตราหาผู้บุกรุกอยู่ตลอดเวลา @@ -835,6 +835,7 @@ category.items = ไอเท็ม category.crafting = การผลิต category.function = ฟังค์ชั่น category.optional = ทางเลือกการเพิ่มประสิทธิภาพ +setting.skipcoreanimation.name = ข้ามแอนิเมชั่นบิน/ลงจอดของแกนกลาง setting.landscape.name = ล็อกภูมิทัศน์แนวนอน setting.shadows.name = เงา setting.blockreplace.name = แนะนำบล็อกโดยอัตโนมัติ @@ -1372,8 +1373,8 @@ hint.payloadDrop.mobile = [accent]กดค้างไว้[]ที่พื hint.waveFire = ป้อมปืน[accent]คลื่นน้ำ[]หากเติมน้ำเข้าไปจะช่วยดับไฟรอบข้างให้อัตโนมัติ hint.generator = \uf879 [accent]เครื่องกำเนิดไฟฟ้าเผาไหม้[]จะเผาถ่านและส่งพลังงานไปยังบล็อกที่อยู่ใกล้ๆ\n\nระยะของพลังงานสามารถขยายได้ด้วย \uf87f [accent]ตัวจ่ายพลังงาน[] hint.guardian = หน่วย[accent]การ์เดียน[]มีเกราะป้องกันหนาแน่น กระสุนเปราะบางอย่าง[accent]ทองแดง[]และ[accent]ตะกั่ว[][scarlet]ไม่มีประสิทธิภาพ[]\n\nควรใช้ป้อมปืนที่ดีกว่านี้หรือใช้ \uf835 [accent]กราไฟท์[]ใส่ใน \uf861 ดูโอ/ \uf859 ซัลโวเป็นกระสุนเพื่อทำลายการ์เดียน -hint.coreUpgrade = สามารถอัพเกรดแกนกลางได้โดย[accent]วางแกนกลางที่ใหญ่กว่าทับมัน[]\n\nวาง  [accent]แกนกลาง: ฟาวน์เดชั่น[]ทับ  [accent]แกนกลาง: ชาร์ด[] ต้องแน่ใจว่ารอบข้างมีที่ว่างก่อนจะวาง -hint.presetLaunch = [accent]เซ็กเตอร์ลงจอด[]สีเทา อย่างเช่น[accent]ป่าหนาวแหน็บ[] สามารถลงจอดจากที่ไหนที่ได้ในแผนที่ พวกนั้นไม่จำเป็นต้องยืดครองเซ็กเตอร์รอบข้างเพื่อส่งแกนกลางไป\n\n[accent]เซ็กเตอร์ที่มีเลข[] อย่างเช่นอันนี้[accent]ไม่จำเป็น[]ต้องยืดครอง +hint.coreUpgrade = สามารถอัปเกรดแกนกลางได้โดย[accent]วางแกนกลางที่ใหญ่กว่าทับมัน[]\n\nวาง  [accent]แกนกลาง: ฟาวน์เดชั่น[]ทับ  [accent]แกนกลาง: ชาร์ด[] ต้องแน่ใจว่ารอบข้างมีที่ว่างก่อนจะวาง +hint.presetLaunch = [accent]เซ็กเตอร์ลงจอด[]สีเทา อย่างเช่น[accent]ป่าหนาวเหน็บ[] สามารถลงจอดจากที่ไหนที่ได้ในแผนที่ พวกนั้นไม่จำเป็นต้องยืดครองเซ็กเตอร์รอบข้างเพื่อส่งแกนกลางไป\n\n[accent]เซ็กเตอร์ที่มีเลข[] อย่างเช่นอันนี้[accent]ไม่จำเป็น[]ต้องยืดครอง hint.coreIncinerate = เมื่อแกนกลางมีจำนวนไอเท็มชนิดหนึ่งที่เต็ม ไอเท็มชนิดนั้นที่เข้ามาเพิ่มจะ[accent]ถูกเผา[] hint.coopCampaign = ตอนที่เล่น[accent]แคมเปญร่วมกัน[]กับเพื่อน ไอเท็มที่ผลิตในแมพนี้จะถูกส่ง[accent]ไปยังเซ็กเตอร์ของคุณด้วย[]\n\nการวิจัยใหม่ที่โฮสต์ได้วิจัยก็เก็บเป็นของคุณด้วย @@ -1536,7 +1537,7 @@ block.arc.description = ยิงสายฟ้าใส่ศัตรูพ block.swarmer.description = ยิงขีปนาวุธติดตามตัวใส่ศัตรูทั้งอากาศและพื้นดิน block.salvo.description = ป้อมปืนขนาดกลาง ระดมยิงกระสุนหนักใส่ศัตรูอย่างรวดเร็ว block.fuse.description = ป้อมปืนระยะใกล้ขนาดใหญ่ ยิงลำแสงเจาะทะลุสามแฉกใส่ศัตรูที่อยู่ใกล้เคียง -block.ripple.description = ป้อมปืนใหญ่ทรงพลัง ยิงลูกระเบิดเป็นกระจุกใส่ศัตรูพื้นดินจากระยะไกล +block.ripple.description = ป้อมปืนใหญ่อันทรงพลัง ยิงลูกระเบิดเป็นกระจุกใส่ศัตรูพื้นดินจากระยะไกล block.cyclone.description = ป้อมปืนรวดเร็วดั่งพายุ ยิงก้อนสะเก็ดระเบิดใส่ยูนิตศัตรูอย่างรวดเร็ว block.spectre.description = ปืนใหญ่คู่ขนาดยักษ์ ยิงกระสุนเจาะเกราะใส่ศัตรูทั้งบนอากาศและพื้นดิน block.meltdown.description = ชาร์จแล้วยิงลำแสงเลเซอร์ใส่ศัตรูที่อยู่ใกล้เคียงอย่างต่อเนื่อง ต้องมีของเหลวมาหล่อเย็นป้อมปืนเพื่อทำงาน @@ -1551,13 +1552,13 @@ block.overdrive-dome.description = เร่งประสิทธิภา block.payload-conveyor.description = เคลื่อนย้ายสิ่งของบรรทุกหนัก อย่างเช่นยูนิต block.payload-router.description = แยกสิ่งของบรรทุกออกเป็นสามทิศทาง block.command-center.description = ควบคุมและสั่งการยูนิตด้วยคำสั่งที่มีมากมาย -block.ground-factory.description = ผลิตยูนิตทางบก ยูนิตที่ผลิตสามารถใช้ได้เลย หรือนำไปใส่ในเครื่องพัฒนาเพื่ออัพเกรด -block.air-factory.description = ผลิตยูนิตทางอากาศ ยูนิตที่ผลิตสามารถใช้ได้เลย หรือนำไปใส่ในเครื่องพัฒนาเพื่ออัพเกรด -block.naval-factory.description = ผลิตยูนิตเรือ ยูนิตที่ผลิตสามารถใช้ได้เลย หรือนำไปใส่ในเครื่องพัฒนาเพื่ออัพเกรด -block.additive-reconstructor.description = อัพเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่สอง -block.multiplicative-reconstructor.description = อัพเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่สาม -block.exponential-reconstructor.description = อัพเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่สี่ -block.tetrative-reconstructor.description = อัพเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่ห้าและรุ่นสุดท้าย +block.ground-factory.description = ผลิตยูนิตทางบก ยูนิตที่ผลิตสามารถใช้ได้เลย หรือนำไปใส่ในเครื่องพัฒนาเพื่ออัปเกรด +block.air-factory.description = ผลิตยูนิตทางอากาศ ยูนิตที่ผลิตสามารถใช้ได้เลย หรือนำไปใส่ในเครื่องพัฒนาเพื่ออัปเกรด +block.naval-factory.description = ผลิตยูนิตเรือ ยูนิตที่ผลิตสามารถใช้ได้เลย หรือนำไปใส่ในเครื่องพัฒนาเพื่ออัปเกรด +block.additive-reconstructor.description = อัปเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่สอง +block.multiplicative-reconstructor.description = อัปเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่สาม +block.exponential-reconstructor.description = อัปเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่สี่ +block.tetrative-reconstructor.description = อัปเกรดยูนิตที่อยู่ข้างในให้เป็นรุ่นที่ห้าและรุ่นสุดท้าย block.switch.description = สวิตช์เปิดปิดได้ สามารถควบคุมหรืออ่านค่าได้ด้วยตัวประมวลผลลอจิก block.micro-processor.description = รันคำสั่งลอจิกเป็นลำดับวนไปวนมา สามารถใช้ควบคุมยูนิตหรือสิ่งก่อสร้าง ไม่ค่อยเร็วเท่าไหร่ block.logic-processor.description = รันคำสั่งลอจิกเป็นลำดับวนไปวนมา สามารถใช้ควบคุมยูนิตหรือสิ่งก่อสร้าง ค่อนข้างเร็ว มีระยะการเชื่อมต่อที่ค่อนข้างไกล @@ -1603,9 +1604,9 @@ unit.omura.description = ยิงลำแสงปืนเรลกันเ unit.alpha.description = ปกป้องแกนกลางชาร์ดจากศัตรู สร้างสิ่งต่างๆ unit.beta.description = ปกป้องแกนกลางฟาวน์เดชั่นจากศัตรู สร้างสิ่งต่างๆ unit.gamma.description = ปกป้องแกนกลางนิวเคลียสจากศัตรู สร้างสิ่งต่างๆ -unit.retusa.description = วางทุ่นระเบิดระยะใกล้ ซ่อมแซมยูนิตพวกพ้องที่อยู่ใกล้เคียง +unit.retusa.description = วางทุ่นระเบิดระยะใกล้ และซ่อมแซมยูนิตพวกพ้องที่อยู่ใกล้เคียง unit.oxynoe.description = ยิงเปลวไฟเผาไหม้ใส่ศัตรูที่อยู่ใกล้เคียงและซ่อมแซมสิ่งก่อสร้างของพวกพ้อง\nทำลายกระสุนที่กำลังเข้ามาด้วยปืนป้องกันจุด -unit.cyerce.description = ยิงขีปนาวุธพลาสม่าติดตามตัวเป็นกระจุกระเบิดใส่ศัตรู\nซ่อมแซมยูนิตพวกพ้องที่อยู่ใกล้เคียง +unit.cyerce.description = ยิงขีปนาวุธพลาสม่าติดตามตัวเป็นกระจุกระเบิดใส่ศัตรู\nซ่อมแซมยูนิตพวกพ้องที่อยู่ใกล้เคียงด้วยปืนซ่อมแซม unit.aegires.description = ช็อตทุกสิ่งก่อสร้างและยูนิตศัตรูที่เข้ามาในสนามพลังงานของมัน\nซ่อมแซมสิ่งก่อสร้างและยูนิตพวกพ้อง unit.navanax.description = ยิงลูกระเบิดคลื่นชีพจรแม่เหล็กขนาดใหญ่ สร้างความเสียหายอย่างหนักให้กับเครือข่ายพลังงานศัตรู\nและซ่อมแซมสิ่งก่อสร้างของพวกพ้อง\nหลอมละลายศัตรูที่อยู่ใกล้เคียงด้วยป้อมปืนเลเซอร์อัตโนมัติสี่ป้อม From b7842bbb2609f8fcbbbd6f675447771c77b27fbb Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 22:49:51 -0400 Subject: [PATCH 067/130] warmup = 1 for bridges without power --- core/src/mindustry/world/blocks/distribution/ItemBridge.java | 4 +++- gradle.properties | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/mindustry/world/blocks/distribution/ItemBridge.java index ffdcc793d0..b18f63d6b6 100644 --- a/core/src/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/ItemBridge.java @@ -178,7 +178,7 @@ public class ItemBridge extends Block{ public int link = -1; public IntSeq incoming = new IntSeq(false, 4); public float warmup; - public float time, timeSpeed; + public float time = 10f, timeSpeed; public boolean wasMoved, moved; public float transportCounter; @@ -355,6 +355,8 @@ public class ItemBridge extends Block{ Draw.color(Color.white, Color.black, Mathf.absin(Time.time, 6f, 0.07f)); } + float warmup = hasPower ? this.warmup : 1f; + Draw.alpha((fadeIn ? Math.max(warmup, 0.25f) : 1f) * Renderer.bridgeOpacity); Draw.rect(endRegion, x, y, i * 90 + 90); diff --git a/gradle.properties b/gradle.properties index 198bed30a8..10c50bb31f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=41c08078107a6af4e180125dad3a174cab98656a +archash=94dd6bbd29ea8e71daffaabb530bb7697017d66d From 90bc18e1bd3d1c99fb0cd24b5a78d720d6505576 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 31 Jul 2021 08:38:03 -0400 Subject: [PATCH 068/130] Fixed #5677 --- core/src/mindustry/ai/BlockIndexer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/ai/BlockIndexer.java b/core/src/mindustry/ai/BlockIndexer.java index 6cc184ad38..6c485ae3e6 100644 --- a/core/src/mindustry/ai/BlockIndexer.java +++ b/core/src/mindustry/ai/BlockIndexer.java @@ -181,7 +181,7 @@ public class BlockIndexer{ /** Returns all damaged tiles by team. */ public Seq getDamaged(Team team){ if(damagedTiles[team.id] == null){ - return null; + return damagedTiles[team.id] = new Seq<>(); } return damagedTiles[team.id]; From ef92236cb4871b1a0781cd021fedf20984a44613 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 31 Jul 2021 09:47:44 -0400 Subject: [PATCH 069/130] Gradle 7.1.1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 69a9715077..05679dc3c1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 1d257c1a35003133cd3e46da2650eb51d4bda282 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 31 Jul 2021 10:58:09 -0400 Subject: [PATCH 070/130] Mod import progress bar --- core/assets/bundles/bundle.properties | 4 +--- core/src/mindustry/ui/Bar.java | 4 +++- core/src/mindustry/ui/dialogs/ModsDialog.java | 13 +++++++++++-- .../src/mindustry/ui/fragments/LoadingFragment.java | 2 +- gradle.properties | 2 +- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 49674781a9..91efc5028d 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -317,7 +317,7 @@ data.invalid = This isn't valid game data. data.import.confirm = Importing external data will overwrite[scarlet] all[] your current game data.\n[accent]This cannot be undone![]\n\nOnce the data is imported, your game will exit immediately. quit.confirm = Are you sure you want to quit? loading = [accent]Loading... -reloading = [accent]Reloading Mods... +downloading = [accent]Downloading... saving = [accent]Saving... respawn = [accent][[{0}][] to respawn in core cancelbuilding = [accent][[{0}][] to clear plan @@ -1103,7 +1103,6 @@ unit.reign.name = Reign unit.vela.name = Vela unit.corvus.name = Corvus -block.resupply-point.name = Resupply Point block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Sand Boulder @@ -1407,7 +1406,6 @@ liquid.oil.description = Used in advanced material production and as incendiary liquid.cryofluid.description = Used as coolant in reactors, turrets and factories. block.derelict = [lightgray] Derelict -block.resupply-point.description = Resupplies nearby units with copper ammunition. Not compatible with units that require battery power. block.armored-conveyor.description = Moves items forward. Does not accept inputs from the sides. block.illuminator.description = Emits light. block.message.description = Stores a message for communication between allies. diff --git a/core/src/mindustry/ui/Bar.java b/core/src/mindustry/ui/Bar.java index 6bab3a146d..56760a6673 100644 --- a/core/src/mindustry/ui/Bar.java +++ b/core/src/mindustry/ui/Bar.java @@ -107,8 +107,10 @@ public class Bar extends Element{ } Draw.colorl(0.1f); + Draw.alpha(parentAlpha); bar.draw(x, y, width, height); Draw.color(color, blinkColor, blink); + Draw.alpha(parentAlpha); Drawable top = Tex.barTop; float topWidth = width * value; @@ -128,7 +130,7 @@ public class Bar extends Element{ GlyphLayout lay = Pools.obtain(GlyphLayout.class, GlyphLayout::new); lay.setText(font, name); - font.setColor(Color.white); + font.setColor(1f, 1f, 1f, parentAlpha); font.draw(name, x + width / 2f - lay.width / 2f, y + height / 2f + lay.height / 2f + 1); Pools.free(lay); diff --git a/core/src/mindustry/ui/dialogs/ModsDialog.java b/core/src/mindustry/ui/dialogs/ModsDialog.java index abad12a00a..578652fa7b 100644 --- a/core/src/mindustry/ui/dialogs/ModsDialog.java +++ b/core/src/mindustry/ui/dialogs/ModsDialog.java @@ -36,6 +36,7 @@ import static mindustry.Vars.*; public class ModsDialog extends BaseDialog{ private ObjectMap textureCache = new ObjectMap<>(); + private float modImportProgress; private String searchtxt = ""; private @Nullable Seq modList; private boolean orderDate = false; @@ -488,11 +489,16 @@ public class ModsDialog extends BaseDialog{ private void handleMod(String repo, HttpResponse result){ try{ Fi file = tmpDirectory.child(repo.replace("/", "") + ".zip"); - Streams.copy(result.getResultAsStream(), file.write(false)); + long len = result.getContentLength(); + Floatc cons = len <= 0 ? f -> {} : p -> modImportProgress = p; + + Streams.copyProgress(result.getResultAsStream(), file.write(false), len, 4096, cons); + var mod = mods.importMod(file); mod.setRepo(repo); file.delete(); Core.app.post(() -> { + try{ setup(); ui.loadfrag.hide(); @@ -510,10 +516,13 @@ public class ModsDialog extends BaseDialog{ } private void githubImportMod(String repo, boolean isJava){ + modImportProgress = 0f; + ui.loadfrag.show("@downloading"); + ui.loadfrag.setProgress(() -> modImportProgress); + if(isJava){ githubImportJavaMod(repo); }else{ - ui.loadfrag.show(); Http.get(ghApi + "/repos/" + repo, res -> { var json = Jval.read(res.getResultAsString()); String mainBranch = json.getString("default_branch"); diff --git a/core/src/mindustry/ui/fragments/LoadingFragment.java b/core/src/mindustry/ui/fragments/LoadingFragment.java index 902e6ea3ca..a5ab8eeff7 100644 --- a/core/src/mindustry/ui/fragments/LoadingFragment.java +++ b/core/src/mindustry/ui/fragments/LoadingFragment.java @@ -38,7 +38,7 @@ public class LoadingFragment extends Fragment{ text("@loading"); - bar = t.add(new Bar()).pad(3).size(500f, 40f).visible(false).get(); + bar = t.add(new Bar()).pad(3).padTop(6).size(500f, 40f).visible(false).get(); t.row(); button = t.button("@cancel", () -> {}).pad(20).size(250f, 70f).visible(false).get(); table = t; diff --git a/gradle.properties b/gradle.properties index 10c50bb31f..3a906d66ae 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=94dd6bbd29ea8e71daffaabb530bb7697017d66d +archash=8d15f16848ae0b2a94e38e63be965fdeb9e51f54 From 78c35221be504e3944ceedb7730e70cc123fb555 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 31 Jul 2021 11:22:18 -0400 Subject: [PATCH 071/130] arc --- core/src/mindustry/ui/Bar.java | 4 ++++ gradle.properties | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/ui/Bar.java b/core/src/mindustry/ui/Bar.java index 56760a6673..d8e2b4b6da 100644 --- a/core/src/mindustry/ui/Bar.java +++ b/core/src/mindustry/ui/Bar.java @@ -68,6 +68,10 @@ public class Bar extends Element{ return this; } + public void flash(){ + blink = 1f; + } + public Bar blink(Color color){ blinkColor.set(color); return this; diff --git a/gradle.properties b/gradle.properties index 3a906d66ae..151ab58719 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=8d15f16848ae0b2a94e38e63be965fdeb9e51f54 +archash=b766da178be7f614e5da1f377bef9677fc357907 From 79bf77f4becd473b7f9f187e7caba5dbaa1404f9 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 31 Jul 2021 18:23:22 -0400 Subject: [PATCH 072/130] WIP team icons --- core/assets-raw/sprites/teams/team-crux.png | Bin 0 -> 479 bytes core/assets-raw/sprites/teams/team-derelict.png | Bin 0 -> 608 bytes core/assets-raw/sprites/teams/team-sharded.png | Bin 0 -> 404 bytes core/assets/bundles/bundle.properties | 2 +- core/assets/icons/icons.properties | 3 +++ .../src/mindustry/entities/comp/BuildingComp.java | 5 +++-- core/src/mindustry/game/Team.java | 1 + core/src/mindustry/ui/Fonts.java | 7 +++++++ tools/src/mindustry/tools/Generators.java | 13 +++++++++++++ tools/src/mindustry/tools/ImagePacker.java | 4 ++++ 10 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 core/assets-raw/sprites/teams/team-crux.png create mode 100644 core/assets-raw/sprites/teams/team-derelict.png create mode 100644 core/assets-raw/sprites/teams/team-sharded.png diff --git a/core/assets-raw/sprites/teams/team-crux.png b/core/assets-raw/sprites/teams/team-crux.png new file mode 100644 index 0000000000000000000000000000000000000000..4fb6783a5b49b3fdced9de4860670f644459bb28 GIT binary patch literal 479 zcmeAS@N?(olHy`uVBq!ia0y~yV6X#W4mJh`hT?-OTo@P_7>k44ofy`glX=O&z&O*> z#W5tK@$Kw`lMWkjI8Xiizy4j^sinrbJkwfscfVu1r?Qc?wDDrbk}Ho_uKN@2ekuIH z>s@b3ZwT+JK9yIIy=iy&ZO(k}Ex&AcKhX8uGdOMls$pt(;cH_g9ge>k;Ez4Ppe&&hUsCMkWnQ$PV{l%*dWe>NDm2aDRK(3}T z(Y#~@SA0|nSIG*d`EdnOB^uoS7i&E!IlFq^Rm~6A&gx#_yGzkHFxfWEr@bE z%x(ETYyaJ={>|wQ%-zRtYJSkkP$=vxKWx0PaY^ILrgUd!*5}XK!X21hPrqskcVw21 zi{)M4!e%yGM0AgoR763Zj>WV7ww_tj=CyI(W93!ZvrFn8C$9=fT3Sk=cb<`g?1hE` zro%>tntm0b`S`}6Cu}Qs87$Gb@X<{6yX>uB4R;w7-434fyJhyVZp literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/teams/team-derelict.png b/core/assets-raw/sprites/teams/team-derelict.png new file mode 100644 index 0000000000000000000000000000000000000000..38ac90dcb1ad7df85191e10d4c509c68634ec97e GIT binary patch literal 608 zcmeAS@N?(olHy`uVBq!ia0y~yV6X#W4mJh`hT?-OTo@P_7>k44ofy`glX=O&z$E4A z;uw)8o)g?97uM?D2#RR(=`=GlTXgZ>iW9XVDymhT z{}hU3R>pX>^t)LG|LI>UY-BtCSDIh-S7E!!m-{A!L>xPD_{dU~bRpj*0{>j*C|l3Y zP+C~PSr}6DZQZ%Nyh|6IT6=%F=T_(ie^FlW_=K{wW_#iWu8YqtPPl2Ey7+rjkjX6f zu6I)PT=#zKdT&YB5q)^?*J%;kM@g^Fn@-@Wc_q#2QgdT>aoR-}$3yAjz9}W?6Cb!# zzI_$!`}N|(rQfZ)HV9syv}fCMyZD8*7aksCFtu2_b(x@U?E}p|j*VNU-Iz2ZGt40A ztP;P;Rp#nlx+R=D^YVgD&s3b1{oL%)#Cw%f+`HCooTT=sEY8zN{Ix-8?yE_@UX%9({n7aT_H-mSyRE|1yC&t+_CE7vpW$IY z*YMMYiKU?*_0&>LKd$-{)0{8*zUpYUQh>_6r?Vu~0u}6@$n&Zxd42TQJD=l^c8B>A zC7t!_qxF0rOS)$N{=ap)*__BNW_%Z&c3Wk6<-Oe_6!kziO1S*jIsmV&bz1P+a7$u}S8sCHL97nCQ~0Lfw72O8T5Js&;4kvrnXT zm)jm#V6GDRXsh9kB;~66qM4S0c}uS!ap4wGvU!lGKHar?@vP&=j@cj7KbUtU^6mBy SR~Q%=7(8A5T-G@yGywo5Di!qr literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/teams/team-sharded.png b/core/assets-raw/sprites/teams/team-sharded.png new file mode 100644 index 0000000000000000000000000000000000000000..a3643d4bba12a305b8a598ff702df49f65d5a6d9 GIT binary patch literal 404 zcmeAS@N?(olHy`uVBq!ia0y~yV6X#W4mJh`hT?-OTo@P_7>k44ofy`glX=O&!06}c z;uw7oEM_ zw)*|u-S@A?Ezf?hC-XEsgSE2j$2^a%HM@SybXZ!mYDfA9t)C_zPc#}o2|nV^c9%`@ zbbI&xiDolCEqr8riOt*2$HwVa!in|{cQ5IipDsU=yd;IyZ@O!`nA?bL?F4zPb21Zj-|NNb&bjk;Q_VGxY3F}KhX4Qo literal 0 HcmV?d00001 diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 91efc5028d..0c01f876a8 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1405,7 +1405,7 @@ liquid.slag.description = Refined in separators into constituent metals, or spra liquid.oil.description = Used in advanced material production and as incendiary ammunition. liquid.cryofluid.description = Used as coolant in reactors, turrets and factories. -block.derelict = [lightgray] Derelict +block.derelict =  [lightgray]Derelict block.armored-conveyor.description = Moves items forward. Does not accept inputs from the sides. block.illuminator.description = Emits light. block.message.description = Stores a message for communication between allies. diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties index 51373139a6..fd80526784 100755 --- a/core/assets/icons/icons.properties +++ b/core/assets/icons/icons.properties @@ -353,3 +353,6 @@ 63353=silicon-arc-furnace|block-silicon-arc-furnace-ui 63352=metal-floor-4|block-metal-floor-4-ui 63351=invincible|status-invincible-ui +63356=sharded|team-sharded +63357=crux|team-crux +63358=derelict|team-derelict diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index d5bedacc3e..fb40d72eb1 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -1072,9 +1072,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } public String getDisplayName(){ + //derelict team icon currently doesn't display return team == Team.derelict ? - block.localizedName + "\n" + Core.bundle.get("block.derelict"): - block.localizedName; + block.localizedName + "\n" + Core.bundle.get("block.derelict") : + block.localizedName + (team == player.team() || team.emoji.isEmpty() ? "" : " " + team.emoji); } public TextureRegion getDisplayIcon(){ diff --git a/core/src/mindustry/game/Team.java b/core/src/mindustry/game/Team.java index c7c70cda01..e331ce1255 100644 --- a/core/src/mindustry/game/Team.java +++ b/core/src/mindustry/game/Team.java @@ -17,6 +17,7 @@ public class Team implements Comparable{ public final int id; public final Color color; public final Color[] palette; + public String emoji = ""; public boolean hasPalette; public String name; diff --git a/core/src/mindustry/ui/Fonts.java b/core/src/mindustry/ui/Fonts.java index 7beff27396..bbd55bbd95 100644 --- a/core/src/mindustry/ui/Fonts.java +++ b/core/src/mindustry/ui/Fonts.java @@ -21,6 +21,7 @@ import arc.util.*; import mindustry.*; import mindustry.core.*; import mindustry.ctype.*; +import mindustry.game.*; import mindustry.gen.*; import java.util.*; @@ -155,6 +156,12 @@ public class Fonts{ } } }); + + for(Team team : Team.baseTeams){ + if(Core.atlas.has("team-" + team.name)){ + team.emoji = stringIcons.get(team.name, ""); + } + } } /** Called from a static context for use in the loading screen.*/ diff --git a/tools/src/mindustry/tools/Generators.java b/tools/src/mindustry/tools/Generators.java index c78e7dbb5f..dd2867172a 100644 --- a/tools/src/mindustry/tools/Generators.java +++ b/tools/src/mindustry/tools/Generators.java @@ -390,6 +390,19 @@ public class Generators{ } }); + generate("team-icons", () -> { + for(Team team : Team.all){ + if(has("team-" + team.name)){ + int rgba = team == Team.derelict ? Color.valueOf("b7b8c9").rgba() : team.color.rgba(); + Pixmap base = get("team-" + team.name); + base.each((x, y) -> base.setRaw(x, y, Color.muli(base.getRaw(x, y), rgba))); + + delete("team-" + team.name); + save(base.outline(Pal.gray, 3), "../ui/team-" + team.name); + } + } + }); + generate("unit-icons", () -> content.units().each(type -> { if(type.isHidden()) return; //hidden units don't generate diff --git a/tools/src/mindustry/tools/ImagePacker.java b/tools/src/mindustry/tools/ImagePacker.java index 0df257f52f..68a06a2f66 100644 --- a/tools/src/mindustry/tools/ImagePacker.java +++ b/tools/src/mindustry/tools/ImagePacker.java @@ -236,6 +236,10 @@ public class ImagePacker{ base.draw(image, 0, 0, image.width, image.height, base.width/2 - wx/2, base.height/2 - wy/2, wx, wy, true, true); } + static void delete(String name){ + ((GenRegion)Core.atlas.find(name)).path.delete(); + } + static void replace(String name, Pixmap image){ Fi.get(name + ".png").writePng(image); ((GenRegion)Core.atlas.find(name)).path.delete(); From 84b69a683aeb6900b5a7669a065230eebf1b91b5 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 31 Jul 2021 18:50:55 -0400 Subject: [PATCH 073/130] PvP team color palettes --- core/src/mindustry/game/Team.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/game/Team.java b/core/src/mindustry/game/Team.java index e331ce1255..671b870f4d 100644 --- a/core/src/mindustry/game/Team.java +++ b/core/src/mindustry/game/Team.java @@ -32,9 +32,9 @@ public class Team implements Comparable{ Color.valueOf("ffd37f"), Color.valueOf("eab678"), Color.valueOf("d4816b")), crux = new Team(2, "crux", Color.valueOf("f25555"), Color.valueOf("fc8e6c"), Color.valueOf("f25555"), Color.valueOf("a04553")), - green = new Team(3, "green", Color.valueOf("54d67d")), - purple = new Team(4, "purple", Color.valueOf("995bb0")), - blue = new Team(5, "blue", Color.valueOf("5a4deb")); + green = new Team(3, "green", Color.valueOf("54d67d"), Color.valueOf("96f58c"), Color.valueOf("54d67d"), Color.valueOf("28785c")), + purple = new Team(4, "purple", Color.valueOf("995bb0"), Color.valueOf("f08dd5"), Color.valueOf("995bb0"), Color.valueOf("312c63")), + blue = new Team(5, "blue", Color.valueOf("554deb"), Color.valueOf("80aaff"), Color.valueOf("554deb"), Color.valueOf("3f207d")); static{ Mathf.rand.setSeed(8); From fc80c23ddeb3ea65a06b5aff2fd7a603d3429a29 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 31 Jul 2021 21:31:36 -0400 Subject: [PATCH 074/130] Auto-generate block paletted team regions for mods --- core/src/mindustry/game/Team.java | 8 ++++++ core/src/mindustry/world/Block.java | 30 +++++++++++++++++++++++ tools/src/mindustry/tools/Generators.java | 2 +- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/game/Team.java b/core/src/mindustry/game/Team.java index 671b870f4d..53366df21b 100644 --- a/core/src/mindustry/game/Team.java +++ b/core/src/mindustry/game/Team.java @@ -17,6 +17,7 @@ public class Team implements Comparable{ public final int id; public final Color color; public final Color[] palette; + public final int[] palettei = new int[3]; public String emoji = ""; public boolean hasPalette; public String name; @@ -61,6 +62,10 @@ public class Team implements Comparable{ palette[0] = color; palette[1] = color.cpy().mul(0.75f); palette[2] = color.cpy().mul(0.5f); + + for(int i = 0; i < 3; i++){ + palettei[i] = palette[i].rgba(); + } } /** Specifies a 3-color team palette. */ @@ -70,6 +75,9 @@ public class Team implements Comparable{ palette[0] = pal1; palette[1] = pal2; palette[2] = pal3; + for(int i = 0; i < 3; i++){ + palettei[i] = palette[i].rgba(); + } hasPalette = true; } diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index ee354135ac..ff4bdf0356 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -886,6 +886,36 @@ public class Block extends UnlockableContent{ } } + //generate paletted team regions + if(teamRegion.found()){ + for(Team team : Team.all){ + //if there's an override, don't generate anything + if(team.hasPalette && !Core.atlas.has(name + "-team-" + team.name)){ + var base = Core.atlas.getPixmap(teamRegion); + Pixmap out = new Pixmap(base.width, base.height); + + for(int x = 0; x < base.width; x++){ + for(int y = 0; y < base.height; y++){ + int color = base.get(x, y); + int index = color == 0xffffffff ? 0 : color == 0xdcc6c6ff ? 1 : color == 0x9d7f7fff ? 2 : -1; + out.setRaw(x, y, index == -1 ? base.get(x, y) : team.palettei[index]); + } + } + + if(Core.settings.getBool("linear")){ + Pixmaps.bleed(out); + } + + packer.add(PageType.main, name + "-team-" + team.name, out); + } + } + + teamRegions = new TextureRegion[Team.all.length]; + for(Team team : Team.all){ + teamRegions[team.id] = teamRegion.found() && team.hasPalette ? Core.atlas.find(name + "-team-" + team.name, teamRegion) : teamRegion; + } + } + Pixmap last = null; var gen = icons(); diff --git a/tools/src/mindustry/tools/Generators.java b/tools/src/mindustry/tools/Generators.java index dd2867172a..b1468997f2 100644 --- a/tools/src/mindustry/tools/Generators.java +++ b/tools/src/mindustry/tools/Generators.java @@ -244,7 +244,7 @@ public class Generators{ teamr.each((x, y) -> { int color = teamr.getRaw(x, y); int index = color == 0xffffffff ? 0 : color == 0xdcc6c6ff ? 1 : color == 0x9d7f7fff ? 2 : -1; - out.setRaw(x, y, index == -1 ? teamr.getRaw(x, y) : team.palette[index].rgba()); + out.setRaw(x, y, index == -1 ? teamr.getRaw(x, y) : team.palettei[index]); }); save(out, block.name + "-team-" + team.name); From e64cd905d62ff28f6d2a64175e257bfcb649d74c Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 1 Aug 2021 13:27:21 -0400 Subject: [PATCH 075/130] Fixed #5685 --- core/src/mindustry/content/Fx.java | 2 +- core/src/mindustry/entities/comp/UnitComp.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index 28ab6e7a3b..d89e93f0d9 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -130,7 +130,7 @@ public class Fx{ Fill.circle(x, y, e.fslope() * 1.5f * size); }), - pointBeam = new Effect(25f, e -> { + pointBeam = new Effect(25f, 300f, e -> { if(!(e.data instanceof Position)) return; Position pos = e.data(); diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java index cfd1554ecc..8da31fb2e1 100644 --- a/core/src/mindustry/entities/comp/UnitComp.java +++ b/core/src/mindustry/entities/comp/UnitComp.java @@ -126,6 +126,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I if(isBuilding()){ return state.rules.infiniteResources ? Float.MAX_VALUE : Math.max(type.clipSize, type.region.width) + buildingRange + tilesize*4f; } + if(mining()){ + return type.clipSize + type.miningRange; + } return type.clipSize; } From 9c1f897fffe6cd4a0d221603e081bd68319906cd Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 1 Aug 2021 17:00:24 -0400 Subject: [PATCH 076/130] Fixed #5684 --- core/src/mindustry/world/blocks/payloads/PayloadBlock.java | 6 ++++++ desktop/src/mindustry/desktop/DesktopLauncher.java | 3 --- desktop/src/mindustry/desktop/steam/SWorkshop.java | 7 +++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java index b0b1d1c5a8..86023894e3 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java @@ -193,8 +193,14 @@ public class PayloadBlock extends Block{ } public void dumpPayload(){ + //translate payload forward slightly + float tx = Angles.trnsx(payload.rotation(), 0.1f), ty = Angles.trnsy(payload.rotation(), 0.1f); + payload.set(payload.x() + tx, payload.y() + ty, payload.rotation()); + if(payload.dump()){ payload = null; + }else{ + payload.set(payload.x() - tx, payload.y() - ty, payload.rotation()); } } diff --git a/desktop/src/mindustry/desktop/DesktopLauncher.java b/desktop/src/mindustry/desktop/DesktopLauncher.java index 1d289847ae..1de468f504 100644 --- a/desktop/src/mindustry/desktop/DesktopLauncher.java +++ b/desktop/src/mindustry/desktop/DesktopLauncher.java @@ -100,9 +100,6 @@ public class DesktopLauncher extends ClientLauncher{ if(SteamAPI.restartAppIfNecessary(SVars.steamID)){ System.exit(0); } - }catch(NullPointerException ignored){ - steam = false; - Log.info("Running in offline mode."); }catch(Throwable e){ steam = false; Log.err("Failed to load Steam native libraries."); diff --git a/desktop/src/mindustry/desktop/steam/SWorkshop.java b/desktop/src/mindustry/desktop/steam/SWorkshop.java index 23a22360d4..9799da60d8 100644 --- a/desktop/src/mindustry/desktop/steam/SWorkshop.java +++ b/desktop/src/mindustry/desktop/steam/SWorkshop.java @@ -33,10 +33,9 @@ public class SWorkshop implements SteamUGCCallback{ ItemInstallInfo info = new ItemInstallInfo(); ugc.getSubscribedItems(ids); - Seq folders = Seq.with(ids).map(f -> { - ugc.getItemInstallInfo(f, info); - return new Fi(info.getFolder()); - }).select(f -> f != null && f.list().length > 0); + Seq folders = Seq.with(ids) + .map(f -> !ugc.getItemInstallInfo(f, info) || info.getFolder() == null ? null : new Fi(info.getFolder())) + .select(f -> f != null && f.list().length > 0); workshopFiles.put(Map.class, folders.select(f -> f.list().length == 1 && f.list()[0].extension().equals(mapExtension)).map(f -> f.list()[0])); workshopFiles.put(Schematic.class, folders.select(f -> f.list().length == 1 && f.list()[0].extension().equals(schematicExtension)).map(f -> f.list()[0])); From d9a92dc10e62ee92d3b8375c928156e5655d4402 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 1 Aug 2021 18:01:36 -0400 Subject: [PATCH 077/130] Minor deployment script fixes --- build.gradle | 4 ++-- core/src/mindustry/world/blocks/power/PowerNode.java | 1 + desktop/build.gradle | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index fb96ef2132..cfab64d455 100644 --- a/build.gradle +++ b/build.gradle @@ -341,10 +341,10 @@ project(":core"){ } } def changelogs = file("../fastlane/metadata/android/en-US/changelogs/") + changelogs.mkdirs() try{ new File(changelogs, androidVersion + ".txt").text = (result) - }catch(Exception e){ - e.printStackTrace() + }catch(Exception ignored){ } } } diff --git a/core/src/mindustry/world/blocks/power/PowerNode.java b/core/src/mindustry/world/blocks/power/PowerNode.java index 313d995340..df49366a8f 100644 --- a/core/src/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/mindustry/world/blocks/power/PowerNode.java @@ -363,6 +363,7 @@ public class PowerNode extends PowerBlock{ @Override public void dropped(){ power.links.clear(); + updatePowerGraph(); } @Override diff --git a/desktop/build.gradle b/desktop/build.gradle index dfcc365f79..981815b7fc 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -126,6 +126,7 @@ platforms.each{ platform -> } args += "Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1" + args += "XX:+ShowCodeDetailsInExceptionMessages" exec{ commandLine args.toList() From 41964cd13080ef45db5165f45a3a503e1cf67e98 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 1 Aug 2021 20:35:10 -0400 Subject: [PATCH 078/130] Unordered damaged building indices --- core/src/mindustry/ai/BlockIndexer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/ai/BlockIndexer.java b/core/src/mindustry/ai/BlockIndexer.java index 6c485ae3e6..f91aa89e11 100644 --- a/core/src/mindustry/ai/BlockIndexer.java +++ b/core/src/mindustry/ai/BlockIndexer.java @@ -181,7 +181,7 @@ public class BlockIndexer{ /** Returns all damaged tiles by team. */ public Seq getDamaged(Team team){ if(damagedTiles[team.id] == null){ - return damagedTiles[team.id] = new Seq<>(); + return damagedTiles[team.id] = new Seq<>(false); } return damagedTiles[team.id]; From a3d1dd91d9f5b409ad5c8ac1c798032e80587688 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 2 Aug 2021 08:53:50 -0400 Subject: [PATCH 079/130] Dispose display framebuffer on remove --- core/src/mindustry/world/blocks/logic/LogicDisplay.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/src/mindustry/world/blocks/logic/LogicDisplay.java b/core/src/mindustry/world/blocks/logic/LogicDisplay.java index 871ab82944..772e17fdba 100644 --- a/core/src/mindustry/world/blocks/logic/LogicDisplay.java +++ b/core/src/mindustry/world/blocks/logic/LogicDisplay.java @@ -106,6 +106,15 @@ public class LogicDisplay extends Block{ }); Draw.blend(); } + + @Override + public void remove(){ + super.remove(); + if(buffer != null){ + buffer.dispose(); + buffer = null; + } + } } static int unpackSign(int value){ From 116422f1e757625b0080efcb197227d25d354a85 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 2 Aug 2021 21:47:29 -0400 Subject: [PATCH 080/130] arc --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 151ab58719..3a15934772 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=b766da178be7f614e5da1f377bef9677fc357907 +archash=e92c0a42c0e735ba5a9a1db7302ca206461bd8a9 From 36deb5e2256da75919819099e377feafdd6c8b34 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 3 Aug 2021 09:25:41 -0400 Subject: [PATCH 081/130] Fixed #5688 --- core/src/mindustry/world/blocks/logic/LogicBlock.java | 5 +++-- gradle.properties | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/world/blocks/logic/LogicBlock.java b/core/src/mindustry/world/blocks/logic/LogicBlock.java index 9ff67fb954..80385a14ac 100644 --- a/core/src/mindustry/world/blocks/logic/LogicBlock.java +++ b/core/src/mindustry/world/blocks/logic/LogicBlock.java @@ -174,7 +174,7 @@ public class LogicBlock extends Block{ public boolean active = true, valid; public int x, y; public String name; - Building lastBuild; + public Building lastBuild; public LogicLink(int x, int y, String name, boolean valid){ this.x = x; @@ -397,7 +397,8 @@ public class LogicBlock extends Block{ var cur = world.build(l.x, l.y); boolean valid = validLink(cur); - if(valid != l.valid || (l.lastBuild != null && l.lastBuild != cur)){ + if(l.lastBuild == null) l.lastBuild = cur; + if(valid != l.valid || l.lastBuild != cur){ l.lastBuild = cur; changed = true; l.valid = valid; diff --git a/gradle.properties b/gradle.properties index 3a15934772..1068749d98 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=e92c0a42c0e735ba5a9a1db7302ca206461bd8a9 +archash=6c4631e2c715e93e10f96a258c307efbaf2564d3 From 7f896723be975bd7767ac46c4465c7dc44306d2d Mon Sep 17 00:00:00 2001 From: Darkness6030 <79508138+Darkness6030@users.noreply.github.com> Date: Tue, 3 Aug 2021 16:33:27 +0300 Subject: [PATCH 082/130] Small changes in reloadmaps command (#5687) Idk is it useful, but why not --- server/src/mindustry/server/ServerControl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/mindustry/server/ServerControl.java b/server/src/mindustry/server/ServerControl.java index a75cc39749..3d378f4d25 100644 --- a/server/src/mindustry/server/ServerControl.java +++ b/server/src/mindustry/server/ServerControl.java @@ -380,6 +380,8 @@ public class ServerControl implements ApplicationListener{ maps.reload(); if(maps.all().size > beforeMaps){ info("@ new map(s) found and reloaded.", maps.all().size - beforeMaps); + }else if(maps.all().size < beforeMaps){ + info("@ old map(s) deleted.", beforeMaps - maps.all().size); }else{ info("Maps reloaded."); } From 4d4ae7b2db1506c182b69f585ae79a529c14022f Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 3 Aug 2021 10:10:42 -0400 Subject: [PATCH 083/130] #5690 --- core/src/mindustry/ui/dialogs/PlanetDialog.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 2f213fd6c8..6ec88d38af 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -633,6 +633,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ dialog.cont.pane(c -> { c.defaults().padBottom(5); + if(sector.preset != null && sector.preset.description != null){ + c.add(sector.preset.displayDescription()).left().row(); + } + c.add(Core.bundle.get("sectors.time") + " [accent]" + sector.save.getPlayTime()).left().row(); if(sector.info.waves && sector.hasBase()){ From f820121e08b3719dc608e589c9d9959b2aeba5b7 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 3 Aug 2021 16:01:27 -0400 Subject: [PATCH 084/130] Sector bugfixes / More sector info --- core/src/mindustry/content/Blocks.java | 1 + core/src/mindustry/game/SectorInfo.java | 32 ++++++++++------ core/src/mindustry/io/JsonIO.java | 3 +- core/src/mindustry/type/Sector.java | 8 ++++ .../mindustry/ui/dialogs/PlanetDialog.java | 38 +++++++++++++++++-- .../ui/fragments/PlacementFragment.java | 5 ++- 6 files changed, 69 insertions(+), 18 deletions(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index b48e0ccc96..5b005dae89 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1297,6 +1297,7 @@ public class Blocks implements ContentList{ drillEffect = Fx.mineHuge; rotateSpeed = 6f; warmupSpeed = 0.01f; + itemCapacity = 20; //more than the laser drill liquidBoostIntensity = 1.8f; diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index 4d2b20b9cc..45af10f817 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -1,5 +1,6 @@ package mindustry.game; +import arc.func.*; import arc.math.*; import arc.struct.*; import arc.util.*; @@ -21,6 +22,7 @@ public class SectorInfo{ private static final int valueWindow = 60; /** refresh period of export in ticks */ private static final float refreshPeriod = 60; + private static float returnf; /** Core input statistics. */ public ObjectMap production = new ObjectMap<>(); @@ -265,23 +267,29 @@ public class SectorInfo{ return map; } + public boolean anyExports(){ + if(export.size == 0) return false; + returnf = 0f; + export.each((i, e) -> returnf += e.mean); + return returnf >= 0.01f; + } + /** @return a newly allocated map with import statistics. Use sparingly. */ //TODO this can be a float map - public ObjectMap importStats(){ + public ObjectMap importStats(Planet planet){ ObjectMap imports = new ObjectMap<>(); - //for all sectors on all planets that have bases and export to this sector - for(Planet planet : content.planets()){ - for(Sector sector : planet.sectors){ - Sector dest = sector.info.getRealDestination(); - if(sector.hasBase() && sector.info != this && dest != null && dest.info == this){ - //add their exports to our imports - sector.info.export.each((item, stat) -> { - imports.get(item, ExportStat::new).mean += stat.mean; - }); - } + eachImport(planet, sector -> sector.info.export.each((item, stat) -> imports.get(item, ExportStat::new).mean += stat.mean)); + return imports; + } + + /** Iterates through every sector this one imports from. */ + public void eachImport(Planet planet, Cons cons){ + for(Sector sector : planet.sectors){ + Sector dest = sector.info.getRealDestination(); + if(sector.hasBase() && sector.info != this && dest != null && dest.info == this){ + cons.get(sector); } } - return imports; } public static class ExportStat{ diff --git a/core/src/mindustry/io/JsonIO.java b/core/src/mindustry/io/JsonIO.java index 9f51b32cb0..3e6beb26e8 100644 --- a/core/src/mindustry/io/JsonIO.java +++ b/core/src/mindustry/io/JsonIO.java @@ -214,7 +214,8 @@ public class JsonIO{ String str = jsonData.asString(); Item item = Vars.content.getByName(ContentType.item, str); Liquid liquid = Vars.content.getByName(ContentType.liquid, str); - return item != null ? item : liquid; + Block block = Vars.content.getByName(ContentType.block, str); + return item != null ? item : liquid == null ? block : liquid; } }); diff --git a/core/src/mindustry/type/Sector.java b/core/src/mindustry/type/Sector.java index 7aea305426..da5ca2229a 100644 --- a/core/src/mindustry/type/Sector.java +++ b/core/src/mindustry/type/Sector.java @@ -11,6 +11,7 @@ import arc.util.*; import mindustry.*; import mindustry.game.Saves.*; import mindustry.game.*; +import mindustry.gen.*; import mindustry.graphics.g3d.PlanetGrid.*; import mindustry.ui.*; import mindustry.world.modules.*; @@ -126,6 +127,13 @@ public class Sector{ return info.contentIcon != null ? info.contentIcon.uiIcon : info.icon == null ? null : Fonts.getLargeIcon(info.icon); } + @Nullable + public String iconChar(){ + if(info.contentIcon != null) return info.contentIcon.emoji(); + if(info.icon != null) return Iconc.codes.get(info.icon) + ""; + return null; + } + public boolean isCaptured(){ return save != null && !info.waves; } diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 6ec88d38af..7dfae6246a 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -371,6 +371,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } if(selectAlpha > 0.001f){ + + for(Sector sec : planet.sectors){ if(sec.hasBase()){ for(Sector enemy : sec.near()){ @@ -378,6 +380,18 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ planets.drawArc(planet, enemy.tile.v, sec.tile.v, Team.crux.color.write(Tmp.c2).a(selectAlpha), Color.clear, 0.24f, 110f, 25); } } + + + if(selected != null && selected != sec && selected.hasBase()){ + //imports + if(sec.info.getRealDestination() == selected && sec.info.anyExports()){ + planets.drawArc(planet, sec.tile.v, selected.tile.v, Color.gray.write(Tmp.c2).a(selectAlpha), Pal.accent, 0.4f, 90f, 25); + } + //exports + if(selected.info.getRealDestination() == sec && selected.info.anyExports()){ + planets.drawArc(planet, selected.tile.v, sec.tile.v, Pal.place.write(Tmp.c2).a(selectAlpha), Pal.accent, 0.4f, 90f, 25); + } + } } } } @@ -605,6 +619,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } void displayItems(Table c, float scl, ObjectMap stats, String name){ + displayItems(c, scl, stats, name, t -> {}); + } + + void displayItems(Table c, float scl, ObjectMap stats, String name, Cons builder){ Table t = new Table().left(); int i = 0; @@ -622,8 +640,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } if(t.getChildren().any()){ - c.add(name).left().row(); - c.add(t).padLeft(10f).left().row(); + c.defaults().left(); + c.add(name).row(); + builder.get(c); + c.add(t).padLeft(10f).row(); } } @@ -660,11 +680,21 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ displayItems(c, sector.getProductionScale(), sector.info.production, "@sectors.production"); //export - displayItems(c, sector.getProductionScale(), sector.info.export, "@sectors.export"); + displayItems(c, sector.getProductionScale(), sector.info.export, "@sectors.export", t -> { + if(sector.info.destination != null){ + String ic = sector.info.destination.iconChar(); + t.add(Iconc.rightOpen + " " + (ic == null || ic.isEmpty() ? "" : ic + " ") + sector.info.destination.name()).padLeft(10f).row(); + } + }); //import if(sector.hasBase()){ - displayItems(c, 1f, sector.info.importStats(), "@sectors.import"); + displayItems(c, 1f, sector.info.importStats(sector.planet), "@sectors.import", t -> { + sector.info.eachImport(sector.planet, other -> { + String ic = other.iconChar(); + t.add(Iconc.rightOpen + " " + (ic == null || ic.isEmpty() ? "" : ic + " ") + other.name()).padLeft(10f).row(); + }); + }); } ItemSeq items = sector.items(); diff --git a/core/src/mindustry/ui/fragments/PlacementFragment.java b/core/src/mindustry/ui/fragments/PlacementFragment.java index b81f6a34f8..04684a2b70 100644 --- a/core/src/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/mindustry/ui/fragments/PlacementFragment.java @@ -15,6 +15,7 @@ import mindustry.core.*; import mindustry.entities.*; import mindustry.entities.units.*; import mindustry.game.EventType.*; +import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.input.*; @@ -38,6 +39,7 @@ public class PlacementFragment extends Fragment{ Block menuHoverBlock; Displayable hover; Object lastDisplayState; + Team lastTeam; boolean wasHovered; Table blockTable, toggler, topTable; ScrollPane blockPane; @@ -283,13 +285,14 @@ public class PlacementFragment extends Fragment{ //don't refresh unnecessarily //refresh only when the hover state changes, or the displayed block changes - if(wasHovered == isHovered && lastDisplayState == displayState) return; + if(wasHovered == isHovered && lastDisplayState == displayState && lastTeam == player.team()) return; topTable.clear(); topTable.top().left().margin(5); lastDisplayState = displayState; wasHovered = isHovered; + lastTeam = player.team(); //show details of selected block, with costs if(displayBlock != null){ From d7d7b73c5483e57b5dacbb6e9963214b68ccdd26 Mon Sep 17 00:00:00 2001 From: RebornTrack970 <62565267+RebornTrack970@users.noreply.github.com> Date: Wed, 4 Aug 2021 00:16:14 +0300 Subject: [PATCH 085/130] Mindustry PvP 1v1 test server Added to Omega (#5692) Fot testing. --- servers_v6.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers_v6.json b/servers_v6.json index 98a1079bd4..8dd970c796 100644 --- a/servers_v6.json +++ b/servers_v6.json @@ -57,7 +57,7 @@ }, { "name": "Omega", - "address": ["178.170.47.34:20204", "157.90.213.2:30308", "157.90.180.53:25738", "185.86.230.61:25578"] + "address": ["178.170.47.34:20204", "157.90.213.2:30308", "157.90.180.53:25738", "185.86.230.61:25578", "mindustry.me:7172"] }, { "name": "md.obvilionnetwork.ru", From 909c64468f26d4e78603272bcf92ae64b686c682 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 4 Aug 2021 09:26:39 -0400 Subject: [PATCH 086/130] Fixed #5695 / Fixed #5697 --- core/src/mindustry/ui/dialogs/PlanetDialog.java | 7 ++++--- .../mindustry/world/blocks/campaign/PayloadLaunchPad.java | 7 ------- gradle.properties | 2 +- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 7dfae6246a..851ecd52df 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -769,10 +769,11 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ t.button(Icon.none, Styles.clearTogglei, () -> { sector.info.icon = null; + sector.info.contentIcon = null; sector.saveInfo(); hide(); updateSelected(); - }).checked(sector.info.icon == null); + }).checked(sector.info.icon == null && sector.info.contentIcon == null); int cols = (int)Math.min(20, Core.graphics.getWidth() / Scl.scl(52f)); @@ -780,7 +781,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ for(var key : defaultIcons){ var value = Icon.icons.get(key); - t.button(value, Styles.cleari, () -> { + t.button(value, Styles.clearTogglei, () -> { sector.info.icon = key; sector.info.contentIcon = null; sector.saveInfo(); @@ -799,7 +800,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ i = 0; for(UnlockableContent u : content.getBy(ctype).as()){ if(!u.isHidden() && u.unlocked()){ - t.button(new TextureRegionDrawable(u.uiIcon), Styles.cleari, iconMed, () -> { + t.button(new TextureRegionDrawable(u.uiIcon), Styles.clearTogglei, iconMed, () -> { sector.info.icon = null; sector.info.contentIcon = u; sector.saveInfo(); diff --git a/core/src/mindustry/world/blocks/campaign/PayloadLaunchPad.java b/core/src/mindustry/world/blocks/campaign/PayloadLaunchPad.java index e5acad5bf7..3c8cf9481f 100644 --- a/core/src/mindustry/world/blocks/campaign/PayloadLaunchPad.java +++ b/core/src/mindustry/world/blocks/campaign/PayloadLaunchPad.java @@ -21,7 +21,6 @@ import mindustry.logic.*; import mindustry.type.*; import mindustry.ui.*; import mindustry.world.blocks.payloads.*; -import mindustry.world.consumers.*; import mindustry.world.meta.*; import static mindustry.Vars.*; @@ -61,12 +60,6 @@ public class PayloadLaunchPad extends PayloadBlock{ return !state.isCampaign() || net.client() ? SystemCursor.arrow : super.getCursor(); } - //cannot be disabled - @Override - public float efficiency(){ - return power != null && (block.consumes.has(ConsumeType.power) && !block.consumes.getPower().buffered) ? power.status : 1f; - } - @Override public boolean shouldConsume(){ return true; diff --git a/gradle.properties b/gradle.properties index 1068749d98..78ea9e6fbc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=6c4631e2c715e93e10f96a258c307efbaf2564d3 +archash=99749ad616e38f96932f863f284c3966c423855b From 2f57705f13e3adf608d41004a2e65cd1e2448db9 Mon Sep 17 00:00:00 2001 From: Arik Date: Wed, 4 Aug 2021 06:27:01 -0700 Subject: [PATCH 087/130] Fix saving tags of overwritten schematic (#5696) --- core/src/mindustry/game/Schematics.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/mindustry/game/Schematics.java b/core/src/mindustry/game/Schematics.java index d1eefe211f..0a91c9d1b3 100644 --- a/core/src/mindustry/game/Schematics.java +++ b/core/src/mindustry/game/Schematics.java @@ -114,6 +114,7 @@ public class Schematics implements Loadable{ target.tiles.addAll(newSchematic.tiles); target.width = newSchematic.width; target.height = newSchematic.height; + newSchematic.labels = target.labels; newSchematic.tags.putAll(target.tags); newSchematic.file = target.file; From a9412c4f6246a907ed9523d76fcee5e22c202143 Mon Sep 17 00:00:00 2001 From: GaviTSRA <61122293+GaviTSRA@users.noreply.github.com> Date: Wed, 4 Aug 2021 15:27:21 +0200 Subject: [PATCH 088/130] Updated hub ip of TSR Server (#5698) --- servers_v6.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers_v6.json b/servers_v6.json index 8dd970c796..f702e643a6 100644 --- a/servers_v6.json +++ b/servers_v6.json @@ -77,7 +77,7 @@ }, { "name": "TSR", - "address": ["de15-3.falix.gg:27422"] + "address": ["ult4.falix.gg:26904"] }, { "name": "Sakura", From 3b7afec360ec802decb053d602755773cea4d337 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 4 Aug 2021 11:35:15 -0400 Subject: [PATCH 089/130] arc --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 78ea9e6fbc..7dfd34d9ae 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=99749ad616e38f96932f863f284c3966c423855b +archash=4bd83c8f1cf35670e48418b6fa2297400895a1c4 From 3be5296572a27b2ece18c59b64fc7b10c9ea79e2 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 4 Aug 2021 13:52:17 -0400 Subject: [PATCH 090/130] Fixed #5699 --- core/src/mindustry/ai/types/LogicAI.java | 10 ++++++++-- core/src/mindustry/entities/comp/UnitComp.java | 8 ++++++++ core/src/mindustry/input/DesktopInput.java | 2 ++ core/src/mindustry/input/MobileInput.java | 5 +---- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/core/src/mindustry/ai/types/LogicAI.java b/core/src/mindustry/ai/types/LogicAI.java index 193e5aaf48..d33d5ad372 100644 --- a/core/src/mindustry/ai/types/LogicAI.java +++ b/core/src/mindustry/ai/types/LogicAI.java @@ -102,7 +102,7 @@ public class LogicAI extends AIController{ } //look where moving if there's nothing to aim at - if(!shoot){ + if(!shoot || !unit.type.omniMovement){ unit.lookAt(unit.prefRotation()); }else if(unit.hasWeapons() && unit.mounts.length > 0 && !unit.mounts[0].weapon.ignoreRotation){ //if there is, look at the object unit.lookAt(unit.mounts[0].aimX, unit.mounts[0].aimY); @@ -131,7 +131,13 @@ public class LogicAI extends AIController{ //do not move when infinite vectors are used. if(vec.isNaN() || vec.isInfinite()) return; - unit.approach(vec); + if(unit.type.omniMovement){ + unit.approach(vec); + }else{ + unit.rotateMove(vec); + } + + } @Override diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java index 8da31fb2e1..ae4001d25f 100644 --- a/core/src/mindustry/entities/comp/UnitComp.java +++ b/core/src/mindustry/entities/comp/UnitComp.java @@ -59,6 +59,14 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I vel.approachDelta(vector, type.accel * realSpeed()); } + public void rotateMove(Vec2 vec){ + moveAt(Tmp.v2.trns(rotation, vec.len())); + + if(!vec.isZero()){ + rotation = Angles.moveToward(rotation, vec.angle(), type.rotateSpeed * Math.max(Time.delta, 1)); + } + } + public void aimLook(Position pos){ aim(pos); lookAt(pos); diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java index 11f37f34dc..c2d61af046 100644 --- a/core/src/mindustry/input/DesktopInput.java +++ b/core/src/mindustry/input/DesktopInput.java @@ -645,6 +645,8 @@ public class DesktopInput extends InputHandler{ if(omni){ unit.moveAt(movement); }else{ + unit.rotateMove(movement); + unit.moveAt(Tmp.v2.trns(unit.rotation, movement.len())); //problem: actual unit rotation is controlled by velocity, but velocity is 1) unpredictable and 2) can be set to 0 diff --git a/core/src/mindustry/input/MobileInput.java b/core/src/mindustry/input/MobileInput.java index 7429eddaaa..2480cad5ab 100644 --- a/core/src/mindustry/input/MobileInput.java +++ b/core/src/mindustry/input/MobileInput.java @@ -922,10 +922,7 @@ public class MobileInput extends InputHandler implements GestureListener{ if(omni){ unit.moveAt(movement); }else{ - unit.moveAt(Tmp.v2.trns(unit.rotation, movement.len())); - if(!movement.isZero()){ - unit.rotation = Angles.moveToward(unit.rotation, movement.angle(), unit.type.rotateSpeed * Math.max(Time.delta, 1)); - } + unit.rotateMove(movement); } //update shooting if not building + not mining From dd738a01088a3a483295bee491647124e460e30e Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 4 Aug 2021 18:31:36 -0400 Subject: [PATCH 091/130] Removed puddle 'generation' --- .../src/main/resources/revisions/PuddleComp/1.json | 1 + core/src/mindustry/entities/Puddles.java | 11 +++++------ core/src/mindustry/entities/comp/PuddleComp.java | 11 +++++------ 3 files changed, 11 insertions(+), 12 deletions(-) create mode 100644 annotations/src/main/resources/revisions/PuddleComp/1.json diff --git a/annotations/src/main/resources/revisions/PuddleComp/1.json b/annotations/src/main/resources/revisions/PuddleComp/1.json new file mode 100644 index 0000000000..2e4c653aed --- /dev/null +++ b/annotations/src/main/resources/revisions/PuddleComp/1.json @@ -0,0 +1 @@ +{version:1,fields:[{name:amount,type:float},{name:liquid,type:mindustry.type.Liquid},{name:tile,type:mindustry.world.Tile},{name:x,type:float},{name:y,type:float}]} \ No newline at end of file diff --git a/core/src/mindustry/entities/Puddles.java b/core/src/mindustry/entities/Puddles.java index 183f64eacc..f0928db3ed 100644 --- a/core/src/mindustry/entities/Puddles.java +++ b/core/src/mindustry/entities/Puddles.java @@ -16,12 +16,12 @@ public class Puddles{ /** Deposits a Puddle between tile and source. */ public static void deposit(Tile tile, Tile source, Liquid liquid, float amount){ - deposit(tile, source, liquid, amount, 0); + deposit(tile, source, liquid, amount, true); } /** Deposits a Puddle at a tile. */ public static void deposit(Tile tile, Liquid liquid, float amount){ - deposit(tile, tile, liquid, amount, 0); + deposit(tile, tile, liquid, amount, true); } /** Returns the Puddle on the specified tile. May return null. */ @@ -29,7 +29,7 @@ public class Puddles{ return map.get(tile.pos()); } - public static void deposit(Tile tile, Tile source, Liquid liquid, float amount, int generation){ + public static void deposit(Tile tile, Tile source, Liquid liquid, float amount, boolean initial){ if(tile == null) return; if(tile.floor().isLiquid && !canStayOn(liquid, tile.floor().liquidDrop)){ @@ -38,7 +38,7 @@ public class Puddles{ Puddle p = map.get(tile.pos()); - if(generation == 0 && p != null && p.lastRipple <= Time.time - 40f){ + if(initial && p != null && p.lastRipple <= Time.time - 40f){ Fx.ripple.at((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f, 1f, tile.floor().liquidDrop.color); p.lastRipple = Time.time; } @@ -55,14 +55,13 @@ public class Puddles{ puddle.tile = tile; puddle.liquid = liquid; puddle.amount = amount; - puddle.generation = generation; puddle.set((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); puddle.add(); map.put(tile.pos(), puddle); }else if(p.liquid == liquid){ p.accepting = Math.max(amount, p.accepting); - if(generation == 0 && p.lastRipple <= Time.time - 40f && p.amount >= maxLiquid / 2f){ + if(initial && p.lastRipple <= Time.time - 40f && p.amount >= maxLiquid / 2f){ Fx.ripple.at((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f, 1f, p.liquid.color); p.lastRipple = Time.time; } diff --git a/core/src/mindustry/entities/comp/PuddleComp.java b/core/src/mindustry/entities/comp/PuddleComp.java index 12f56fbaa4..68972714e7 100644 --- a/core/src/mindustry/entities/comp/PuddleComp.java +++ b/core/src/mindustry/entities/comp/PuddleComp.java @@ -20,7 +20,6 @@ import static mindustry.entities.Puddles.*; @EntityDef(value = {Puddlec.class}, pooled = true) @Component(base = true) abstract class PuddleComp implements Posc, Puddlec, Drawc{ - private static final int maxGeneration = 2; private static final Rect rect = new Rect(), rect2 = new Rect(); private static int seeds; @@ -29,7 +28,6 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ transient float accepting, updateTime, lastRipple; float amount; - int generation; Tile tile; Liquid liquid; @@ -39,22 +37,23 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ @Override public void update(){ - //update code float addSpeed = accepting > 0 ? 3f : 0f; amount -= Time.delta * (1f - liquid.viscosity) / (5f + addSpeed); amount += accepting; accepting = 0f; - if(amount >= maxLiquid / 1.5f && generation < maxGeneration){ + if(amount >= maxLiquid / 1.5f){ float deposited = Math.min((amount - maxLiquid / 1.5f) / 4f, 0.3f) * Time.delta; + int targets = 0; for(Point2 point : Geometry.d4){ Tile other = world.tile(tile.x + point.x, tile.y + point.y); if(other != null && other.block() == Blocks.air){ - Puddles.deposit(other, tile, liquid, deposited, generation + 1); - amount -= deposited / 2f; //tweak to speed up/slow down Puddle propagation + targets ++; + Puddles.deposit(other, tile, liquid, deposited, false); } } + amount -= deposited * targets; } amount = Mathf.clamp(amount, 0, maxLiquid); From aa80f06f7be0849d069044e52ae59a6a8e0308b1 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 4 Aug 2021 19:02:36 -0400 Subject: [PATCH 092/130] Cleanup & bullet bugfixes --- core/src/mindustry/entities/Puddles.java | 4 +--- core/src/mindustry/entities/comp/BulletComp.java | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/mindustry/entities/Puddles.java b/core/src/mindustry/entities/Puddles.java index f0928db3ed..cf398dc1f6 100644 --- a/core/src/mindustry/entities/Puddles.java +++ b/core/src/mindustry/entities/Puddles.java @@ -45,9 +45,7 @@ public class Puddles{ return; } - if(tile.floor().solid){ - return; - } + if(tile.floor().solid) return; Puddle p = map.get(tile.pos()); if(p == null){ diff --git a/core/src/mindustry/entities/comp/BulletComp.java b/core/src/mindustry/entities/comp/BulletComp.java index 839e0b0c44..86b779b82d 100644 --- a/core/src/mindustry/entities/comp/BulletComp.java +++ b/core/src/mindustry/entities/comp/BulletComp.java @@ -81,7 +81,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw } public boolean hasCollided(int id){ - return collided.size != 0 && !collided.contains(id); + return collided.size != 0 && collided.contains(id); } @Replace From 294ab0a81bd20359a23ae9dbaee384f026623807 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 4 Aug 2021 19:16:14 -0400 Subject: [PATCH 093/130] Better initial bridge arrows --- core/src/mindustry/world/blocks/distribution/ItemBridge.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/mindustry/world/blocks/distribution/ItemBridge.java index b18f63d6b6..29438c97fb 100644 --- a/core/src/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/ItemBridge.java @@ -178,7 +178,7 @@ public class ItemBridge extends Block{ public int link = -1; public IntSeq incoming = new IntSeq(false, 4); public float warmup; - public float time = 10f, timeSpeed; + public float time = -8f, timeSpeed; public boolean wasMoved, moved; public float transportCounter; From 46eeb8b9609b487e87791c32ee7046e00428fd8a Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 4 Aug 2021 23:03:15 -0400 Subject: [PATCH 094/130] arc --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7dfd34d9ae..87e2cda59f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=4bd83c8f1cf35670e48418b6fa2297400895a1c4 +archash=3500375b0b164ffbbe75321a5898eae95511e34a From 6cb6a76ef339d0cbad1c41ef992995480d275aef Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 5 Aug 2021 08:22:53 -0400 Subject: [PATCH 095/130] arc --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 87e2cda59f..ccad41c21d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=3500375b0b164ffbbe75321a5898eae95511e34a +archash=fd433d5d1b3406a6f1c1fd7dad7e3591634ceeab From ec30232c4ed5ae26178d8c2a347343a2fcfca243 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 5 Aug 2021 10:27:46 -0400 Subject: [PATCH 096/130] Made AttributeCrafters consume a constant amount of liquid + cultivator water requirement decrease --- core/src/mindustry/content/Blocks.java | 5 ++--- .../world/blocks/production/AttributeCrafter.java | 14 +++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 5b005dae89..a17b403b90 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1046,7 +1046,7 @@ public class Blocks implements ContentList{ mechanicalPump = new Pump("mechanical-pump"){{ requirements(Category.liquid, with(Items.copper, 15, Items.metaglass, 10)); - pumpAmount = 0.11f; + pumpAmount = 7f / 60f; }}; rotaryPump = new Pump("rotary-pump"){{ @@ -1337,14 +1337,13 @@ public class Blocks implements ContentList{ maxBoost = 2f; consumes.power(80f / 60f); - consumes.liquid(Liquids.water, 20f / 60f); + consumes.liquid(Liquids.water, 18f / 60f); }}; oilExtractor = new Fracker("oil-extractor"){{ requirements(Category.production, with(Items.copper, 150, Items.graphite, 175, Items.lead, 115, Items.thorium, 115, Items.silicon, 75)); result = Liquids.oil; updateEffect = Fx.pulverize; - liquidCapacity = 50f; updateEffectChance = 0.05f; pumpAmount = 0.25f; size = 3; diff --git a/core/src/mindustry/world/blocks/production/AttributeCrafter.java b/core/src/mindustry/world/blocks/production/AttributeCrafter.java index d1480f6a16..ac2f7ceeee 100644 --- a/core/src/mindustry/world/blocks/production/AttributeCrafter.java +++ b/core/src/mindustry/world/blocks/production/AttributeCrafter.java @@ -26,11 +26,11 @@ public class AttributeCrafter extends GenericCrafter{ public void setBars(){ super.setBars(); - bars.add("efficiency", entity -> + bars.add("efficiency", (AttributeCrafterBuild entity) -> new Bar(() -> - Core.bundle.format("bar.efficiency", (int)(entity.efficiency() * 100)), + Core.bundle.format("bar.efficiency", (int)(entity.efficiencyScale() * 100)), () -> Pal.lightOrange, - entity::efficiency)); + entity::efficiencyScale)); } @Override @@ -44,8 +44,12 @@ public class AttributeCrafter extends GenericCrafter{ public float attrsum; @Override - public float efficiency(){ - return (baseEfficiency + Math.min(maxBoost, boostScale * attrsum) + attribute.env()) * super.efficiency(); + public float getProgressIncrease(float base){ + return super.getProgressIncrease(base) * efficiencyScale(); + } + + public float efficiencyScale(){ + return baseEfficiency + Math.min(maxBoost, boostScale * attrsum) + attribute.env(); } @Override From 66ce3e75ec5f9b0a646fb80bb75e6ae74a54fe54 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 5 Aug 2021 12:00:35 -0400 Subject: [PATCH 097/130] Allow dumping/moving into payload voids --- core/src/mindustry/world/blocks/payloads/PayloadVoid.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/mindustry/world/blocks/payloads/PayloadVoid.java b/core/src/mindustry/world/blocks/payloads/PayloadVoid.java index fa41218e3c..9ef2cb5800 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadVoid.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadVoid.java @@ -48,6 +48,11 @@ public class PayloadVoid extends PayloadBlock{ drawPayload(); } + @Override + public boolean acceptUnitPayload(Unit unit){ + return true; + } + @Override public void updateTile(){ if(moveInPayload(false) && cons.valid()){ From 6fdbe1d5f05f8c40a346c754f0089ca779ab90a5 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 5 Aug 2021 14:20:23 -0400 Subject: [PATCH 098/130] Fixed minimap not updating when build team changes --- .../src/mindustry/entities/comp/BuildingComp.java | 3 +++ core/src/mindustry/game/EventType.java | 15 +++++++++++++++ core/src/mindustry/graphics/MinimapRenderer.java | 7 ++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index fb40d72eb1..b474a8bfdf 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -49,6 +49,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, static final float timeToSleep = 60f * 1, timeToUncontrol = 60f * 6; static final ObjectSet tmpTiles = new ObjectSet<>(); static final Seq tempBuilds = new Seq<>(); + static final BuildTeamChangeEvent teamChangeEvent = new BuildTeamChangeEvent(); static int sleepingEntities = 0; @Import float x, y, health, maxHealth; @@ -1258,9 +1259,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, /** Changes this building's team in a safe manner. */ public void changeTeam(Team next){ + Team last = this.team; indexer.removeIndex(tile); this.team = next; indexer.addIndex(tile); + Events.fire(teamChangeEvent.set(last, self())); } public boolean canPickup(){ diff --git a/core/src/mindustry/game/EventType.java b/core/src/mindustry/game/EventType.java index 9d590de52c..5ff6a6f264 100644 --- a/core/src/mindustry/game/EventType.java +++ b/core/src/mindustry/game/EventType.java @@ -284,6 +284,21 @@ public class EventType{ } } + /** + * Called after a building's team changes. + * Event object is reused, do not nest! + * */ + public static class BuildTeamChangeEvent{ + public Team previous; + public Building build; + + public BuildTeamChangeEvent set(Team previous, Building build){ + this.build = build; + this.previous = previous; + return this; + } + } + /** Called when a core block is placed/removed or its team is changed. */ public static class CoreChangeEvent{ public CoreBuild core; diff --git a/core/src/mindustry/graphics/MinimapRenderer.java b/core/src/mindustry/graphics/MinimapRenderer.java index 1a3b7dc7f8..51b5f7f483 100644 --- a/core/src/mindustry/graphics/MinimapRenderer.java +++ b/core/src/mindustry/graphics/MinimapRenderer.java @@ -33,13 +33,18 @@ public class MinimapRenderer{ updateAll(); }); - //make sure to call on the graphics thread Events.on(TileChangeEvent.class, event -> { //TODO don't update when the minimap is off? if(!ui.editor.isShown()){ update(event.tile); } }); + + Events.on(BuildTeamChangeEvent.class, event -> { + if(!ui.editor.isShown()){ + update(event.build.tile); + } + }); } public Pixmap getPixmap(){ From 4fa04b9e23a3b04beb424add5ec3f0f833676396 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 5 Aug 2021 23:01:58 -0400 Subject: [PATCH 099/130] Bannable units / Show tech tree icon for unresearched units --- core/assets/bundles/bundle.properties | 1 + core/src/mindustry/game/Rules.java | 2 + .../mindustry/graphics/MinimapRenderer.java | 6 +- core/src/mindustry/type/UnitType.java | 4 + .../ui/dialogs/CustomRulesDialog.java | 135 ++++++++++-------- .../world/blocks/payloads/PayloadSource.java | 4 +- .../world/blocks/payloads/UnitPayload.java | 32 ++++- .../world/blocks/units/Reconstructor.java | 29 +++- .../world/blocks/units/UnitFactory.java | 8 +- 9 files changed, 137 insertions(+), 84 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 0c01f876a8..2e6f7813f4 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -539,6 +539,7 @@ configure = Configure Loadout loadout = Loadout resources = Resources bannedblocks = Banned Blocks +bannedunits = Banned Units addall = Add All launch.from = Launching From: [accent]{0} launch.destination = Destination: {0} diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java index 385d7671e9..515995d79c 100644 --- a/core/src/mindustry/game/Rules.java +++ b/core/src/mindustry/game/Rules.java @@ -94,6 +94,8 @@ public class Rules{ public Seq weather = new Seq<>(1); /** Blocks that cannot be placed. */ public ObjectSet bannedBlocks = new ObjectSet<>(); + /** Units that cannot be built. */ + public ObjectSet bannedUnits = new ObjectSet<>(); /** Reveals blocks normally hidden by build visibility. */ public ObjectSet revealedBlocks = new ObjectSet<>(); /** Unlocked content names. Only used in multiplayer when the campaign is enabled. */ diff --git a/core/src/mindustry/graphics/MinimapRenderer.java b/core/src/mindustry/graphics/MinimapRenderer.java index 51b5f7f483..a66d388357 100644 --- a/core/src/mindustry/graphics/MinimapRenderer.java +++ b/core/src/mindustry/graphics/MinimapRenderer.java @@ -40,11 +40,7 @@ public class MinimapRenderer{ } }); - Events.on(BuildTeamChangeEvent.class, event -> { - if(!ui.editor.isShown()){ - update(event.build.tile); - } - }); + Events.on(BuildTeamChangeEvent.class, event -> update(event.build.tile)); } public Pixmap getPixmap(){ diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 5e1d44e367..93efe9b5bc 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -233,6 +233,10 @@ public class UnitType extends UnlockableContent{ return (envEnabled & env) != 0 && (envDisabled & env) == 0 && (envRequired == 0 || (envRequired & env) == envRequired); } + public boolean isBanned(){ + return state.rules.bannedUnits.contains(this); + } + @Override public void getDependencies(Cons cons){ //units require reconstructors being researched diff --git a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java index 3b5978a290..0bee65257d 100644 --- a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java +++ b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java @@ -28,87 +28,93 @@ public class CustomRulesDialog extends BaseDialog{ private Table main; private Prov resetter; private LoadoutDialog loadoutDialog; - private BaseDialog banDialog; public CustomRulesDialog(){ super("@mode.custom"); loadoutDialog = new LoadoutDialog(); - banDialog = new BaseDialog("@bannedblocks"); - banDialog.addCloseButton(); - - banDialog.shown(this::rebuildBanned); - banDialog.buttons.button("@addall", Icon.add, () -> { - rules.bannedBlocks.addAll(content.blocks().select(Block::canBeBuilt)); - rebuildBanned(); - }).size(180, 64f); - - banDialog.buttons.button("@clear", Icon.trash, () -> { - rules.bannedBlocks.clear(); - rebuildBanned(); - }).size(180, 64f); setFillParent(true); shown(this::setup); addCloseButton(); } - private void rebuildBanned(){ - float previousScroll = banDialog.cont.getChildren().isEmpty() ? 0f : ((ScrollPane)banDialog.cont.getChildren().first()).getScrollY(); - banDialog.cont.clear(); - banDialog.cont.pane(t -> { - t.margin(10f); + private void showBanned(String title, ContentType type, ObjectSet set, Boolf pred){ + BaseDialog bd = new BaseDialog(title); + bd.addCloseButton(); - if(rules.bannedBlocks.isEmpty()){ - t.add("@empty"); - } + Runnable[] rebuild = {null}; - Seq array = Seq.with(rules.bannedBlocks); - array.sort(); + rebuild[0] = () -> { + float previousScroll = bd.cont.getChildren().isEmpty() ? 0f : ((ScrollPane)bd.cont.getChildren().first()).getScrollY(); + bd.cont.clear(); + bd.cont.pane(t -> { + t.margin(10f); - int cols = mobile && Core.graphics.isPortrait() ? 1 : mobile ? 2 : 3; - int i = 0; - - for(Block block : array){ - t.table(Tex.underline, b -> { - b.left().margin(4f); - b.image(block.uiIcon).size(iconMed).padRight(3); - b.add(block.localizedName).color(Color.lightGray).padLeft(3).growX().left().wrap(); - - b.button(Icon.cancel, Styles.clearPartiali, () -> { - rules.bannedBlocks.remove(block); - rebuildBanned(); - }).size(70f).pad(-4f).padLeft(0f); - }).size(300f, 70f).padRight(5); - - if(++i % cols == 0){ - t.row(); + if(set.isEmpty()){ + t.add("@empty"); } - } - }).get().setScrollYForce(previousScroll); - banDialog.cont.row(); - banDialog.cont.button("@add", Icon.add, () -> { - BaseDialog dialog = new BaseDialog("@add"); - dialog.cont.pane(t -> { - t.left().margin(14f); - int[] i = {0}; - content.blocks().each(b -> !rules.bannedBlocks.contains(b) && b.canBeBuilt(), b -> { - int cols = mobile && Core.graphics.isPortrait() ? 4 : 12; - t.button(new TextureRegionDrawable(b.uiIcon), Styles.cleari, iconMed, () -> { - rules.bannedBlocks.add(b); - rebuildBanned(); - dialog.hide(); - }).size(60f); - if(++i[0] % cols == 0){ + Seq array = set.asArray(); + array.sort(); + + int cols = mobile && Core.graphics.isPortrait() ? 1 : mobile ? 2 : 3; + int i = 0; + + for(T con : array){ + t.table(Tex.underline, b -> { + b.left().margin(4f); + b.image(con.uiIcon).size(iconMed).padRight(3); + b.add(con.localizedName).color(Color.lightGray).padLeft(3).growX().left().wrap(); + + b.button(Icon.cancel, Styles.clearPartiali, () -> { + set.remove(con); + rebuild[0].run(); + }).size(70f).pad(-4f).padLeft(0f); + }).size(300f, 70f).padRight(5); + + if(++i % cols == 0){ t.row(); } - }); - }); + } + }).get().setScrollYForce(previousScroll); + bd.cont.row(); + bd.cont.button("@add", Icon.add, () -> { + BaseDialog dialog = new BaseDialog("@add"); + dialog.cont.pane(t -> { + t.left().margin(14f); + int[] i = {0}; + content.getBy(type).each(b -> !set.contains(b) && pred.get(b), b -> { + int cols = mobile && Core.graphics.isPortrait() ? 4 : 12; + t.button(new TextureRegionDrawable(b.uiIcon), Styles.cleari, iconMed, () -> { + set.add(b); + rebuild[0].run(); + dialog.hide(); + }).size(60f); - dialog.addCloseButton(); - dialog.show(); - }).size(300f, 64f); + if(++i[0] % cols == 0){ + t.row(); + } + }); + }); + + dialog.addCloseButton(); + dialog.show(); + }).size(300f, 64f); + }; + + bd.shown(rebuild[0]); + bd.buttons.button("@addall", Icon.add, () -> { + set.addAll(content.getBy(type).select(pred)); + rebuild[0].run(); + }).size(180, 64f); + + bd.buttons.button("@clear", Icon.trash, () -> { + set.clear(); + rebuild[0].run(); + }).size(180, 64f); + + bd.show(); } public void show(Rules rules, Prov resetter){ @@ -157,7 +163,7 @@ public class CustomRulesDialog extends BaseDialog{ )).left().width(300f); main.row(); - main.button("@bannedblocks", banDialog::show).left().width(300f); + main.button("@bannedblocks", () -> showBanned("@bannedblocks", ContentType.block, rules.bannedBlocks, Block::canBeBuilt)).left().width(300f); main.row(); title("@rules.title.unit"); @@ -167,6 +173,9 @@ public class CustomRulesDialog extends BaseDialog{ number("@rules.unitdamagemultiplier", f -> rules.unitDamageMultiplier = f, () -> rules.unitDamageMultiplier); number("@rules.unitbuildspeedmultiplier", f -> rules.unitBuildSpeedMultiplier = f, () -> rules.unitBuildSpeedMultiplier, 0.001f, 50f); + main.button("@bannedunits", () -> showBanned("@bannedunits", ContentType.unit, rules.bannedUnits, u -> !u.isHidden())).left().width(300f); + main.row(); + title("@rules.title.enemy"); check("@rules.attack", b -> rules.attackMode = b, () -> rules.attackMode); check("@rules.buildai", b -> rules.teams.get(rules.waveTeam).ai = rules.teams.get(rules.waveTeam).infiniteResources = b, () -> rules.teams.get(rules.waveTeam).ai); diff --git a/core/src/mindustry/world/blocks/payloads/PayloadSource.java b/core/src/mindustry/world/blocks/payloads/PayloadSource.java index e290463224..62600833b9 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadSource.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadSource.java @@ -71,11 +71,11 @@ public class PayloadSource extends PayloadBlock{ } public boolean canProduce(Block b){ - return b.isVisible() && b.size < size && !(b instanceof CoreBlock); + return b.isVisible() && b.size < size && !(b instanceof CoreBlock) && !state.rules.bannedBlocks.contains(b); } public boolean canProduce(UnitType t){ - return !t.isHidden(); + return !t.isHidden() && !t.isBanned(); } public class PayloadSourceBuild extends PayloadBlockBuild{ diff --git a/core/src/mindustry/world/blocks/payloads/UnitPayload.java b/core/src/mindustry/world/blocks/payloads/UnitPayload.java index 22d11f4b65..a33bb35dcf 100644 --- a/core/src/mindustry/world/blocks/payloads/UnitPayload.java +++ b/core/src/mindustry/world/blocks/payloads/UnitPayload.java @@ -4,6 +4,7 @@ import arc.*; import arc.graphics.*; import arc.graphics.g2d.*; import arc.math.*; +import arc.scene.style.*; import arc.util.*; import arc.util.io.*; import mindustry.*; @@ -13,16 +14,31 @@ import mindustry.entities.*; import mindustry.game.EventType.*; import mindustry.gen.*; +import static mindustry.Vars.*; + public class UnitPayload implements Payload{ - public static final float deactiveDuration = 40f; + public static final float overlayDuration = 40f; public Unit unit; - public float deactiveTime = 0f; + public float overlayTime = 0f; + public @Nullable TextureRegion overlayRegion; public UnitPayload(Unit unit){ this.unit = unit; } + /** Flashes a red overlay region. */ + public void showOverlay(TextureRegion icon){ + overlayRegion = icon; + overlayTime = 1f; + } + + /** Flashes a red overlay region. */ + public void showOverlay(TextureRegionDrawable icon){ + if(icon == null || headless) return; + showOverlay(icon.getRegion()); + } + @Override public void write(Writes write){ write.b(payloadUnit); @@ -62,7 +78,8 @@ public class UnitPayload implements Payload{ if(unit.type == null) return true; if(!Units.canCreate(unit.team, unit.type)){ - deactiveTime = 1f; + overlayTime = 1f; + overlayRegion = null; return false; } @@ -103,16 +120,17 @@ public class UnitPayload implements Payload{ unit.type.drawCell(unit); //draw warning - if(deactiveTime > 0){ + if(overlayTime > 0){ + var region = overlayRegion == null ? Icon.warning.getRegion() : overlayRegion; Draw.color(Color.scarlet); - Draw.alpha(0.8f * Interp.exp5Out.apply(deactiveTime)); + Draw.alpha(0.8f * Interp.exp5Out.apply(overlayTime)); float size = 8f; - Draw.rect(Icon.warning.getRegion(), unit.x, unit.y, size, size); + Draw.rect(region, unit.x, unit.y, size, size); Draw.reset(); - deactiveTime = Math.max(deactiveTime - Time.delta/deactiveDuration, 0f); + overlayTime = Math.max(overlayTime - Time.delta/overlayDuration, 0f); } } diff --git a/core/src/mindustry/world/blocks/units/Reconstructor.java b/core/src/mindustry/world/blocks/units/Reconstructor.java index 89ded06fef..9521a6c87a 100644 --- a/core/src/mindustry/world/blocks/units/Reconstructor.java +++ b/core/src/mindustry/world/blocks/units/Reconstructor.java @@ -116,11 +116,28 @@ public class Reconstructor extends UnitBlock{ @Override public boolean acceptPayload(Building source, Payload payload){ - return this.payload == null - && (this.enabled || source == this) - && relativeTo(source) != rotation - && payload instanceof UnitPayload pay - && hasUpgrade(pay.unit.type); + if(!(this.payload == null + && (this.enabled || source == this) + && relativeTo(source) != rotation + && payload instanceof UnitPayload pay)){ + return false; + } + + var upgrade = upgrade(pay.unit.type); + + if(upgrade != null){ + if(!upgrade.unlockedNow()){ + //flash "not researched" + pay.showOverlay(Icon.tree); + } + + if(upgrade.isBanned()){ + //flash an X, meaning 'banned' + pay.showOverlay(Icon.cancel); + } + } + + return upgrade != null && upgrade.unlockedNow() && !upgrade.isBanned(); } @Override @@ -224,7 +241,7 @@ public class Reconstructor extends UnitBlock{ public boolean hasUpgrade(UnitType type){ UnitType t = upgrade(type); - return t != null && t.unlockedNow(); + return t != null && t.unlockedNow() && !type.isBanned(); } public UnitType upgrade(UnitType type){ diff --git a/core/src/mindustry/world/blocks/units/UnitFactory.java b/core/src/mindustry/world/blocks/units/UnitFactory.java index 8c337e9919..bbef9cb456 100644 --- a/core/src/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/mindustry/world/blocks/units/UnitFactory.java @@ -149,7 +149,7 @@ public class UnitFactory extends UnitBlock{ @Override public void buildConfiguration(Table table){ - Seq units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow()); + Seq units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow() && !u.isBanned()); if(units.any()){ ItemSelection.buildTable(table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit))); @@ -225,6 +225,12 @@ public class UnitFactory extends UnitBlock{ if(currentPlan != -1 && payload == null){ UnitPlan plan = plans.get(currentPlan); + //make sure to reset plan when the unit got banned after placement + if(plan.unit.isBanned()){ + currentPlan = -1; + return; + } + if(progress >= plan.time && consValid()){ progress %= 1f; From b8232326bcf8defefdef2cb60994832113c893ac Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 6 Aug 2021 09:04:07 -0400 Subject: [PATCH 100/130] Fixed #5703 --- core/src/mindustry/world/Block.java | 2 +- core/src/mindustry/world/blocks/storage/CoreBlock.java | 8 +++++++- gradle.properties | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index ff4bdf0356..2d26a96fc5 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -887,7 +887,7 @@ public class Block extends UnlockableContent{ } //generate paletted team regions - if(teamRegion.found()){ + if(teamRegion != null && teamRegion.found()){ for(Team team : Team.all){ //if there's an override, don't generate anything if(team.hasPalette && !Core.atlas.has(name + "-team-" + team.name)){ diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index f5c8b690dd..24f5b6a652 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -302,7 +302,13 @@ public class CoreBlock extends StorageBlock{ @Override public void afterDestroyed(){ if(state.rules.coreCapture){ - tile.setNet(block, lastDamage, 0); + if(!net.client()){ + tile.setBlock(block, lastDamage); + } + + //delay so clients don't destroy it afterwards + Core.app.post(() -> tile.setNet(block, lastDamage, 0)); + //building does not exist on client yet if(!net.client()){ //core is invincible for several seconds to prevent recapture diff --git a/gradle.properties b/gradle.properties index ccad41c21d..8595a5a09d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=fd433d5d1b3406a6f1c1fd7dad7e3591634ceeab +archash=68277c42b4883e5fcb01dfa20fd27a5434ace891 From 588523b311965fba6bca328a41d4b2bd68379863 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 6 Aug 2021 09:34:38 -0400 Subject: [PATCH 101/130] Avoid lambda capture in puddles --- .../mindustry/entities/comp/PuddleComp.java | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/core/src/mindustry/entities/comp/PuddleComp.java b/core/src/mindustry/entities/comp/PuddleComp.java index 68972714e7..0e9e779c58 100644 --- a/core/src/mindustry/entities/comp/PuddleComp.java +++ b/core/src/mindustry/entities/comp/PuddleComp.java @@ -1,5 +1,6 @@ package mindustry.entities.comp; +import arc.func.*; import arc.graphics.*; import arc.graphics.g2d.*; import arc.math.*; @@ -23,6 +24,20 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ private static final Rect rect = new Rect(), rect2 = new Rect(); private static int seeds; + private static Puddle paramPuddle; + private static Cons unitCons = unit -> { + if(unit.isGrounded() && !unit.hovering){ + unit.hitbox(rect2); + if(rect.overlaps(rect2)){ + unit.apply(paramPuddle.liquid.effect, 60 * 2); + + if(unit.vel.len2() > 0.1f * 0.1f){ + Fx.ripple.at(unit.x, unit.y, unit.type.rippleScale, paramPuddle.liquid.color); + } + } + } + }; + @Import int id; @Import float x, y; @@ -64,18 +79,9 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ //effects-only code if(amount >= maxLiquid / 2f && updateTime <= 0f){ - Units.nearby(rect.setSize(Mathf.clamp(amount / (maxLiquid / 1.5f)) * 10f).setCenter(x, y), unit -> { - if(unit.isGrounded() && !unit.hovering){ - unit.hitbox(rect2); - if(rect.overlaps(rect2)){ - unit.apply(liquid.effect, 60 * 2); + paramPuddle = self(); - if(unit.vel.len() > 0.1){ - Fx.ripple.at(unit.x, unit.y, unit.type.rippleScale, liquid.color); - } - } - } - }); + Units.nearby(rect.setSize(Mathf.clamp(amount / (maxLiquid / 1.5f)) * 10f).setCenter(x, y), unitCons); if(liquid.temperature > 0.7f && (tile.build != null) && Mathf.chance(0.5)){ Fires.create(tile); From 316adf63ee16dabf5360081b5773bcc5f6a07df5 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 6 Aug 2021 11:07:30 -0400 Subject: [PATCH 102/130] Multi-target zenith AI --- core/src/mindustry/content/UnitTypes.java | 5 +++++ core/src/mindustry/entities/comp/PuddleComp.java | 4 ++-- core/src/mindustry/type/UnitType.java | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 571f01f9ad..ed9d68beb3 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -935,6 +935,8 @@ public class UnitTypes implements ContentList{ engineOffset = 5.5f; range = 140f; targetAir = false; + //as default AI, flares are not very useful in core rushes, they attack nothing in the way + playerTargetFlags = new BlockFlag[]{null}; targetFlags = new BlockFlag[]{BlockFlag.generator, null}; commandLimit = 4; circleTarget = true; @@ -969,6 +971,8 @@ public class UnitTypes implements ContentList{ range = 140f; faceTarget = false; armor = 3f; + //do not rush core, attack closest + playerTargetFlags = new BlockFlag[]{null}; targetFlags = new BlockFlag[]{BlockFlag.factory, null}; commandLimit = 5; circleTarget = true; @@ -1006,6 +1010,7 @@ public class UnitTypes implements ContentList{ range = 140f; hitSize = 20f; lowAltitude = true; + forceMultiTarget = true; armor = 5f; targetFlags = new BlockFlag[]{BlockFlag.launchPad, BlockFlag.storage, BlockFlag.battery, null}; diff --git a/core/src/mindustry/entities/comp/PuddleComp.java b/core/src/mindustry/entities/comp/PuddleComp.java index 0e9e779c58..63b3f25f6a 100644 --- a/core/src/mindustry/entities/comp/PuddleComp.java +++ b/core/src/mindustry/entities/comp/PuddleComp.java @@ -41,7 +41,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ @Import int id; @Import float x, y; - transient float accepting, updateTime, lastRipple; + transient float accepting, updateTime, lastRipple = Time.time + Mathf.random(40f); float amount; Tile tile; Liquid liquid; @@ -73,7 +73,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ amount = Mathf.clamp(amount, 0, maxLiquid); - if(amount <= 0f){ + if(amount <= 0f || Puddles.get(tile) != self()){ remove(); } diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 93efe9b5bc..0640400182 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -121,6 +121,7 @@ public class UnitType extends UnlockableContent{ public boolean canHeal = false; /** If true, all weapons will attack the same target. */ public boolean singleTarget = false; + public boolean forceMultiTarget = false; public ObjectSet immunities = new ObjectSet<>(); public Sound deathSound = Sounds.bang; @@ -319,7 +320,7 @@ public class UnitType extends UnlockableContent{ } clipSize = Math.max(clipSize, lightRadius * 1.1f); - singleTarget = weapons.size <= 1; + singleTarget = weapons.size <= 1 && !forceMultiTarget; if(itemCapacity < 0){ itemCapacity = Math.max(Mathf.round((int)(hitSize * 4.3), 10), 10); From e57b5b696676e17ea1d5c7a5044473b0ffd7f7ff Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 6 Aug 2021 11:17:10 -0400 Subject: [PATCH 103/130] Implemented Anuken/Mindustry-Suggestions/issues/2800 --- core/src/mindustry/ui/dialogs/DatabaseDialog.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/ui/dialogs/DatabaseDialog.java b/core/src/mindustry/ui/dialogs/DatabaseDialog.java index 5c2aa76d17..45980bdf00 100644 --- a/core/src/mindustry/ui/dialogs/DatabaseDialog.java +++ b/core/src/mindustry/ui/dialogs/DatabaseDialog.java @@ -13,7 +13,9 @@ import mindustry.*; import mindustry.ctype.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.type.*; import mindustry.ui.*; +import mindustry.world.*; import static mindustry.Vars.*; @@ -57,7 +59,17 @@ public class DatabaseDialog extends BaseDialog{ UnlockableContent unlock = (UnlockableContent)array.get(i); Image image = unlocked(unlock) ? new Image(unlock.uiIcon).setScaling(Scaling.fit) : new Image(Icon.lock, Pal.gray); - list.add(image).size(8 * 4).pad(3); + + //banned cross + if(state.isGame() && (unlock instanceof UnitType u && u.isBanned() || unlock instanceof Block b && state.rules.bannedBlocks.contains(b))){ + list.stack(image, new Image(Icon.cancel){{ + setColor(Color.scarlet); + touchable = Touchable.disabled; + }}).size(8 * 4).pad(3); + }else{ + list.add(image).size(8 * 4).pad(3); + } + ClickListener listener = new ClickListener(); image.addListener(listener); if(!mobile && unlocked(unlock)){ From b80129e17b9a8345f6a678658f62165393cdda96 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 6 Aug 2021 11:52:25 -0400 Subject: [PATCH 104/130] Improved environmental block internal names --- .../environment/{craters1.png => crater-stone1.png} | Bin .../environment/{craters2.png => crater-stone2.png} | Bin .../environment/{craters3.png => crater-stone3.png} | Bin .../environment/{craters4.png => crater-stone4.png} | Bin .../environment/{craters5.png => crater-stone5.png} | Bin .../environment/{craters6.png => crater-stone6.png} | Bin .../environment/{deepwater.png => deep-water.png} | Bin .../environment/{slag.png => molten-slag.png} | Bin .../environment/{water.png => shallow-water.png} | Bin core/assets/bundles/bundle.properties | 8 ++++---- core/assets/bundles/bundle_be.properties | 8 ++++---- core/assets/bundles/bundle_bg.properties | 8 ++++---- core/assets/bundles/bundle_cs.properties | 8 ++++---- core/assets/bundles/bundle_da.properties | 8 ++++---- core/assets/bundles/bundle_de.properties | 8 ++++---- core/assets/bundles/bundle_es.properties | 8 ++++---- core/assets/bundles/bundle_et.properties | 8 ++++---- core/assets/bundles/bundle_eu.properties | 8 ++++---- core/assets/bundles/bundle_fi.properties | 8 ++++---- core/assets/bundles/bundle_fil.properties | 8 ++++---- core/assets/bundles/bundle_fr.properties | 8 ++++---- core/assets/bundles/bundle_hu.properties | 8 ++++---- core/assets/bundles/bundle_in_ID.properties | 8 ++++---- core/assets/bundles/bundle_it.properties | 8 ++++---- core/assets/bundles/bundle_ja.properties | 8 ++++---- core/assets/bundles/bundle_ko.properties | 8 ++++---- core/assets/bundles/bundle_lt.properties | 8 ++++---- core/assets/bundles/bundle_nl.properties | 8 ++++---- core/assets/bundles/bundle_nl_BE.properties | 8 ++++---- core/assets/bundles/bundle_pl.properties | 8 ++++---- core/assets/bundles/bundle_pt_BR.properties | 8 ++++---- core/assets/bundles/bundle_pt_PT.properties | 8 ++++---- core/assets/bundles/bundle_ro.properties | 8 ++++---- core/assets/bundles/bundle_ru.properties | 8 ++++---- core/assets/bundles/bundle_sv.properties | 8 ++++---- core/assets/bundles/bundle_th.properties | 8 ++++---- core/assets/bundles/bundle_tk.properties | 8 ++++---- core/assets/bundles/bundle_tr.properties | 8 ++++---- core/assets/bundles/bundle_uk_UA.properties | 8 ++++---- core/assets/bundles/bundle_vi.properties | 8 ++++---- core/assets/bundles/bundle_zh_CN.properties | 8 ++++---- core/assets/bundles/bundle_zh_TW.properties | 8 ++++---- core/assets/icons/icons.properties | 4 ++++ core/src/mindustry/content/Blocks.java | 8 ++++---- core/src/mindustry/io/SaveFileReader.java | 6 +++++- 45 files changed, 145 insertions(+), 137 deletions(-) rename core/assets-raw/sprites/blocks/environment/{craters1.png => crater-stone1.png} (100%) rename core/assets-raw/sprites/blocks/environment/{craters2.png => crater-stone2.png} (100%) rename core/assets-raw/sprites/blocks/environment/{craters3.png => crater-stone3.png} (100%) rename core/assets-raw/sprites/blocks/environment/{craters4.png => crater-stone4.png} (100%) rename core/assets-raw/sprites/blocks/environment/{craters5.png => crater-stone5.png} (100%) rename core/assets-raw/sprites/blocks/environment/{craters6.png => crater-stone6.png} (100%) rename core/assets-raw/sprites/blocks/environment/{deepwater.png => deep-water.png} (100%) rename core/assets-raw/sprites/blocks/environment/{slag.png => molten-slag.png} (100%) rename core/assets-raw/sprites/blocks/environment/{water.png => shallow-water.png} (100%) diff --git a/core/assets-raw/sprites/blocks/environment/craters1.png b/core/assets-raw/sprites/blocks/environment/crater-stone1.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/craters1.png rename to core/assets-raw/sprites/blocks/environment/crater-stone1.png diff --git a/core/assets-raw/sprites/blocks/environment/craters2.png b/core/assets-raw/sprites/blocks/environment/crater-stone2.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/craters2.png rename to core/assets-raw/sprites/blocks/environment/crater-stone2.png diff --git a/core/assets-raw/sprites/blocks/environment/craters3.png b/core/assets-raw/sprites/blocks/environment/crater-stone3.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/craters3.png rename to core/assets-raw/sprites/blocks/environment/crater-stone3.png diff --git a/core/assets-raw/sprites/blocks/environment/craters4.png b/core/assets-raw/sprites/blocks/environment/crater-stone4.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/craters4.png rename to core/assets-raw/sprites/blocks/environment/crater-stone4.png diff --git a/core/assets-raw/sprites/blocks/environment/craters5.png b/core/assets-raw/sprites/blocks/environment/crater-stone5.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/craters5.png rename to core/assets-raw/sprites/blocks/environment/crater-stone5.png diff --git a/core/assets-raw/sprites/blocks/environment/craters6.png b/core/assets-raw/sprites/blocks/environment/crater-stone6.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/craters6.png rename to core/assets-raw/sprites/blocks/environment/crater-stone6.png diff --git a/core/assets-raw/sprites/blocks/environment/deepwater.png b/core/assets-raw/sprites/blocks/environment/deep-water.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/deepwater.png rename to core/assets-raw/sprites/blocks/environment/deep-water.png diff --git a/core/assets-raw/sprites/blocks/environment/slag.png b/core/assets-raw/sprites/blocks/environment/molten-slag.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/slag.png rename to core/assets-raw/sprites/blocks/environment/molten-slag.png diff --git a/core/assets-raw/sprites/blocks/environment/water.png b/core/assets-raw/sprites/blocks/environment/shallow-water.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/water.png rename to core/assets-raw/sprites/blocks/environment/shallow-water.png diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 2e6f7813f4..51fbf226db 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1109,7 +1109,7 @@ block.cliff.name = Cliff block.sand-boulder.name = Sand Boulder block.basalt-boulder.name = Basalt Boulder block.grass.name = Grass -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Salt block.salt-wall.name = Salt Wall @@ -1140,8 +1140,8 @@ block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Deep Water -block.water.name = Water +block.deep-water.name = Deep Water +block.shallow-water.name = Water block.tainted-water.name = Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar @@ -1150,7 +1150,7 @@ block.sand.name = Sand block.darksand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.craters.name = Craters +block.stone-craters.name = Craters block.sand-water.name = Sand Water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_be.properties b/core/assets/bundles/bundle_be.properties index 59d125147c..7d88d0d0db 100644 --- a/core/assets/bundles/bundle_be.properties +++ b/core/assets/bundles/bundle_be.properties @@ -960,7 +960,7 @@ block.parallax.name = Парралакс block.cliff.name = Скала block.sand-boulder.name = Пяшчаны валун block.grass.name = Трава -block.slag.name = Шлак +block.molten-slag.name = Шлак block.space.name = Space block.salt.name = Соль block.salt-wall.name = Саляная сцяна @@ -991,8 +991,8 @@ block.spawn.name = Кропка з’яўлення ворагаў block.core-shard.name = Ядро: «Аскепак» block.core-foundation.name = Ядро: «Штаб» block.core-nucleus.name = Ядро: «Атам» -block.deepwater.name = Глубокаводдзе -block.water.name = Вада +block.deep-water.name = Глубокаводдзе +block.shallow-water.name = Вада block.tainted-water.name = Забруджанная вада block.darksand-tainted-water.name = Тёмный пясок з забруджанай вадой block.tar.name = Нафта @@ -1001,7 +1001,7 @@ block.sand.name = Пясок block.darksand.name = Тёмны пясок block.ice.name = Лёд block.snow.name = Снег -block.craters.name = Кратэры +block.stone-craters.name = Кратэры block.sand-water.name = Пясок з вадой block.darksand-water.name = Тёмный пясок з вадой block.char.name = Выпаленая зямля diff --git a/core/assets/bundles/bundle_bg.properties b/core/assets/bundles/bundle_bg.properties index 42489f046f..37650b0b56 100644 --- a/core/assets/bundles/bundle_bg.properties +++ b/core/assets/bundles/bundle_bg.properties @@ -1074,7 +1074,7 @@ block.cliff.name = Скала block.sand-boulder.name = Пясъчен Камък block.basalt-boulder.name = Базалтов Камък block.grass.name = Трева -block.slag.name = Шлака +block.molten-slag.name = Шлака block.space.name = Космос block.salt.name = Сол block.salt-wall.name = Стена от Сол @@ -1105,8 +1105,8 @@ block.spawn.name = Вражеска Начална Точка block.core-shard.name = Ядро: Шард block.core-foundation.name = Core: Фондация block.core-nucleus.name = Core: Център -block.deepwater.name = Дълбока Вода -block.water.name = Вода +block.deep-water.name = Дълбока Вода +block.shallow-water.name = Вода block.tainted-water.name = Замърсена Вода block.darksand-tainted-water.name = Тъмен Пясък - Замърсена Вода block.tar.name = Катран @@ -1115,7 +1115,7 @@ block.sand.name = Пясък block.darksand.name = Тъмен Пясък block.ice.name = Лед block.snow.name = Сняг -block.craters.name = Кратери +block.stone-craters.name = Кратери block.sand-water.name = Пясък - Вода block.darksand-water.name = Тъмен Пясък - Вода block.char.name = Овъглен Камък diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties index aad326105f..547a068c68 100644 --- a/core/assets/bundles/bundle_cs.properties +++ b/core/assets/bundles/bundle_cs.properties @@ -1023,7 +1023,7 @@ block.cliff.name = Útes block.sand-boulder.name = Pískovec block.basalt-boulder.name = Čedičový balvan block.grass.name = Tráva -block.slag.name = Struska +block.molten-slag.name = Struska block.space.name = Vesmír block.salt.name = Sůl block.salt-wall.name = Solné skály @@ -1054,8 +1054,8 @@ block.spawn.name = Nepřátelská líheň block.core-shard.name = Jádro: Odštěpek block.core-foundation.name = Jádro: Základ block.core-nucleus.name = Jádro: Atom -block.deepwater.name = Hluboká voda -block.water.name = Voda +block.deep-water.name = Hluboká voda +block.shallow-water.name = Voda block.tainted-water.name = Zamořená voda block.darksand-tainted-water.name = Zamořená voda s černým pískem block.tar.name = Dehet @@ -1064,7 +1064,7 @@ block.sand.name = Písek block.darksand.name = Černý písek block.ice.name = Led block.snow.name = Sníh -block.craters.name = Krátery +block.stone-craters.name = Krátery block.sand-water.name = Voda s pískem block.darksand-water.name = Voda s černým pískem block.char.name = Dřevěné uhlí diff --git a/core/assets/bundles/bundle_da.properties b/core/assets/bundles/bundle_da.properties index d7937f0154..00faecd003 100644 --- a/core/assets/bundles/bundle_da.properties +++ b/core/assets/bundles/bundle_da.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Klippe block.sand-boulder.name = Sandkampesten block.grass.name = Græs -block.slag.name = Ildgrød +block.molten-slag.name = Ildgrød block.space.name = Rum block.salt.name = Salt block.salt-wall.name = Saltvæg @@ -991,8 +991,8 @@ block.spawn.name = Fjendtligt Ankomstpunkt block.core-shard.name = Kerne: Skår block.core-foundation.name = Kerne: Fundament block.core-nucleus.name = Kerne: Nukleus -block.deepwater.name = Dybt Vand -block.water.name = Vand +block.deep-water.name = Dybt Vand +block.shallow-water.name = Vand block.tainted-water.name = Moget Vand block.darksand-tainted-water.name = Mørkt Sand Moget Vand block.tar.name = Tjærre @@ -1001,7 +1001,7 @@ block.sand.name = Sand block.darksand.name = Mørkt Sand block.ice.name = Is block.snow.name = Sne -block.craters.name = Kratere +block.stone-craters.name = Kratere block.sand-water.name = Sandet Lavvande block.darksand-water.name = Mørkt Sandet Lavvande block.char.name = Trækul diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index 6c2e66c459..0f99a93990 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -1107,7 +1107,7 @@ block.cliff.name = Klippe block.sand-boulder.name = Sandbrocken block.basalt-boulder.name = Basaltbrocken block.grass.name = Gras -block.slag.name = Schlacke +block.molten-slag.name = Schlacke block.space.name = Weltall block.salt.name = Salz block.salt-wall.name = Salzwand @@ -1138,8 +1138,8 @@ block.spawn.name = Gegnerischer Startpunkt block.core-shard.name = Kern: Scherbe block.core-foundation.name = Kern: Fundament block.core-nucleus.name = Kern: Nukleus -block.deepwater.name = Tiefes Wasser -block.water.name = Wasser +block.deep-water.name = Tiefes Wasser +block.shallow-water.name = Wasser block.tainted-water.name = Dreckiges Wasser block.darksand-tainted-water.name = Dreckiges Wasser (Dunkler Sand) block.tar.name = Teer @@ -1148,7 +1148,7 @@ block.sand.name = Sand block.darksand.name = Dunkler Sand block.ice.name = Eis block.snow.name = Schnee -block.craters.name = Krater +block.stone-craters.name = Krater block.sand-water.name = Sandiges Wasser block.darksand-water.name = Dunkles sandiges Wasser block.char.name = Holzkohle diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index 8701bc0531..961bce09f4 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -1103,7 +1103,7 @@ block.cliff.name = Pared block.sand-boulder.name = Roca de arena block.basalt-boulder.name = Roca de basalto block.grass.name = Hierba -block.slag.name = Magma +block.molten-slag.name = Magma block.space.name = Espacio block.salt.name = Sal block.salt-wall.name = Muro de sal @@ -1134,8 +1134,8 @@ block.spawn.name = Punto de generación block.core-shard.name = Núcleo: Shard block.core-foundation.name = Núcleo: Foundation block.core-nucleus.name = Núcleo: Nucleus -block.deepwater.name = Aguas profundas -block.water.name = Agua +block.deep-water.name = Aguas profundas +block.shallow-water.name = Agua block.tainted-water.name = Agua contaminada block.darksand-tainted-water.name = Agua contaminada con arena oscura block.tar.name = Alquitrán @@ -1144,7 +1144,7 @@ block.sand.name = Arena block.darksand.name = Arena oscura block.ice.name = Hielo block.snow.name = Nieve -block.craters.name = Cráter +block.stone-craters.name = Cráter block.sand-water.name = Agua con arena block.darksand-water.name = Agua con arena oscura block.char.name = Cenizas diff --git a/core/assets/bundles/bundle_et.properties b/core/assets/bundles/bundle_et.properties index 46cf235d26..61f7ba36d6 100644 --- a/core/assets/bundles/bundle_et.properties +++ b/core/assets/bundles/bundle_et.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Liivakamakas block.grass.name = Rohi -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Sool block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Vaenlaste maandumisala block.core-shard.name = Tuumik: Osake block.core-foundation.name = Tuumik: Arenenud block.core-nucleus.name = Tuumik: Täielik -block.deepwater.name = Sügav vesi -block.water.name = Vesi +block.deep-water.name = Sügav vesi +block.shallow-water.name = Vesi block.tainted-water.name = Riknenud vesi block.darksand-tainted-water.name = Riknenud vesi tumedal liival block.tar.name = Tõrv @@ -1001,7 +1001,7 @@ block.sand.name = Liiv block.darksand.name = Tume liiv block.ice.name = Jää block.snow.name = Lumi -block.craters.name = Kraatrid +block.stone-craters.name = Kraatrid block.sand-water.name = Vesi liival block.darksand-water.name = Vesi tumedal liival block.char.name = Puusüsi diff --git a/core/assets/bundles/bundle_eu.properties b/core/assets/bundles/bundle_eu.properties index 537d0b3133..bc43060854 100644 --- a/core/assets/bundles/bundle_eu.properties +++ b/core/assets/bundles/bundle_eu.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Hondar harkaitza block.grass.name = Belarra -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Gatza block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Etsai-sorrera block.core-shard.name = Muina: Maskorra block.core-foundation.name = Muina: Fundazioa block.core-nucleus.name = Muina: Nukleoa -block.deepwater.name = Ur sakona -block.water.name = Ura +block.deep-water.name = Ur sakona +block.shallow-water.name = Ura block.tainted-water.name = Ur kutsatua block.darksand-tainted-water.name = Hondar ilunez kutsatutako ura block.tar.name = Mundruna @@ -1001,7 +1001,7 @@ block.sand.name = Hondarra block.darksand.name = Hondar iluna block.ice.name = Izotza block.snow.name = Elurra -block.craters.name = Kraterrak +block.stone-craters.name = Kraterrak block.sand-water.name = Hondar ura block.darksand-water.name = Hondar ilun ura block.char.name = Kokea diff --git a/core/assets/bundles/bundle_fi.properties b/core/assets/bundles/bundle_fi.properties index d2a998db77..da3f1075f9 100644 --- a/core/assets/bundles/bundle_fi.properties +++ b/core/assets/bundles/bundle_fi.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Vuoren block.sand-boulder.name = Hiekkalohkare block.grass.name = Ruoho -block.slag.name = Kuono +block.molten-slag.name = Kuono block.space.name = Space block.salt.name = Suolapitoisuus block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Vihollisten syntymispiste block.core-shard.name = Ydin: Siru block.core-foundation.name = Ydin: Pohjaus block.core-nucleus.name = Ydin: Tuma -block.deepwater.name = Syvää vettä -block.water.name = Vettä +block.deep-water.name = Syvää vettä +block.shallow-water.name = Vettä block.tainted-water.name = Saastevettä block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Terva @@ -1001,7 +1001,7 @@ block.sand.name = Hiekka block.darksand.name = Tumma hiekka block.ice.name = Jää block.snow.name = Lumi -block.craters.name = Kraatterit +block.stone-craters.name = Kraatterit block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_fil.properties b/core/assets/bundles/bundle_fil.properties index c5663baa1d..db99a05c9c 100644 --- a/core/assets/bundles/bundle_fil.properties +++ b/core/assets/bundles/bundle_fil.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Sand Boulder block.grass.name = Grass -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Salt block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Deep Water -block.water.name = Water +block.deep-water.name = Deep Water +block.shallow-water.name = Water block.tainted-water.name = Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar @@ -1001,7 +1001,7 @@ block.sand.name = Sand block.darksand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.craters.name = Craters +block.stone-craters.name = Craters block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index 4f75f0d673..5bee2d80d3 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -1117,7 +1117,7 @@ block.cliff.name = Falaise block.sand-boulder.name = Bloc de Sable block.basalt-boulder.name = Rocher de Basalte block.grass.name = Herbe -block.slag.name = Scories +block.molten-slag.name = Scories block.space.name = Espace block.salt.name = Sel block.salt-wall.name = Mur de Sel @@ -1148,8 +1148,8 @@ block.spawn.name = Point d'Apparition Ennemi block.core-shard.name = Noyau: Fragment block.core-foundation.name = Noyau: Fondation block.core-nucleus.name = Noyau: Épicentre -block.deepwater.name = Eau profonde -block.water.name = Eau +block.deep-water.name = Eau profonde +block.shallow-water.name = Eau block.tainted-water.name = Eau Contaminée block.darksand-tainted-water.name = Eau Contaminée avec fond de Sable sombre block.tar.name = Goudron @@ -1158,7 +1158,7 @@ block.sand.name = Sable block.darksand.name = Sable sombre block.ice.name = Glace block.snow.name = Neige -block.craters.name = Cratères +block.stone-craters.name = Cratères block.sand-water.name = Eau avec fond de Sable block.darksand-water.name = Eau avec fond de Sable sombre block.char.name = Cendres diff --git a/core/assets/bundles/bundle_hu.properties b/core/assets/bundles/bundle_hu.properties index 47734eb072..9d60e88be3 100644 --- a/core/assets/bundles/bundle_hu.properties +++ b/core/assets/bundles/bundle_hu.properties @@ -1044,7 +1044,7 @@ block.cliff.name = Cliff block.sand-boulder.name = Sand Boulder block.basalt-boulder.name = Basalt Boulder block.grass.name = Grass -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Salt block.salt-wall.name = Salt Wall @@ -1075,8 +1075,8 @@ block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Deep Water -block.water.name = Water +block.deep-water.name = Deep Water +block.shallow-water.name = Water block.tainted-water.name = Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar @@ -1085,7 +1085,7 @@ block.sand.name = Sand block.darksand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.craters.name = Craters +block.stone-craters.name = Craters block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_in_ID.properties b/core/assets/bundles/bundle_in_ID.properties index c78204530d..d67c0ad2c6 100644 --- a/core/assets/bundles/bundle_in_ID.properties +++ b/core/assets/bundles/bundle_in_ID.properties @@ -1102,7 +1102,7 @@ block.cliff.name = Cliff block.sand-boulder.name = Batu Pasir Besar block.basalt-boulder.name = Batu Basal Besar block.grass.name = Rumput -block.slag.name = Lahar +block.molten-slag.name = Lahar block.space.name = Luar Angkasa block.salt.name = Garam block.salt-wall.name = Bukit Garam @@ -1133,8 +1133,8 @@ block.spawn.name = Muncul Musuh block.core-shard.name = Inti: Bagian block.core-foundation.name = Inti: Pondasi block.core-nucleus.name = Inti: Nukleus -block.deepwater.name = Air Dalam -block.water.name = Air +block.deep-water.name = Air Dalam +block.shallow-water.name = Air block.tainted-water.name = Air Ternoda block.darksand-tainted-water.name = Air Ternodai Pasir Hitam block.tar.name = Minyak Mentah @@ -1143,7 +1143,7 @@ block.sand.name = Pasir block.darksand.name = Pasir Hitam block.ice.name = Es block.snow.name = Salju -block.craters.name = Kawah +block.stone-craters.name = Kawah block.sand-water.name = Air Pasir block.darksand-water.name = Air Pasir Hitam block.char.name = Bara diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties index dd1d40f0f7..49cc18e758 100644 --- a/core/assets/bundles/bundle_it.properties +++ b/core/assets/bundles/bundle_it.properties @@ -1024,7 +1024,7 @@ block.cliff.name = Scogliera block.sand-boulder.name = Masso di Sabbia block.basalt-boulder.name = Masso di Basalto block.grass.name = Erba -block.slag.name = Scoria +block.molten-slag.name = Scoria block.space.name = Spazio block.salt.name = Sale block.salt-wall.name = Muro di Sale @@ -1055,8 +1055,8 @@ block.spawn.name = Punto di Generazione Nemico block.core-shard.name = Nucleo: Frammento block.core-foundation.name = Nucleo: Fondamento block.core-nucleus.name = Nucleo: Kernel -block.deepwater.name = Acqua Profonda -block.water.name = Acqua +block.deep-water.name = Acqua Profonda +block.shallow-water.name = Acqua block.tainted-water.name = Acqua Contaminata block.darksand-tainted-water.name = Acqua Contaminata Scura block.tar.name = Catrame @@ -1065,7 +1065,7 @@ block.sand.name = Sabbia block.darksand.name = Sabbia Scura block.ice.name = Ghiaccio block.snow.name = Neve -block.craters.name = Crateri +block.stone-craters.name = Crateri block.sand-water.name = Acqua Sabbiosa block.darksand-water.name = Acqua Sabbiosa Scura block.char.name = Carbone diff --git a/core/assets/bundles/bundle_ja.properties b/core/assets/bundles/bundle_ja.properties index df0475b176..fad527ac75 100644 --- a/core/assets/bundles/bundle_ja.properties +++ b/core/assets/bundles/bundle_ja.properties @@ -1037,7 +1037,7 @@ block.cliff.name = 崖 block.sand-boulder.name = 巨大な礫 block.basalt-boulder.name = 玄武岩の礫 block.grass.name = 草 -block.slag.name = スラグ +block.molten-slag.name = スラグ block.space.name = Space block.salt.name = 岩塩氷河 block.salt-wall.name = 塩の壁 @@ -1068,8 +1068,8 @@ block.spawn.name = 敵の出現場所 block.core-shard.name = コア: シャード block.core-foundation.name = コア: ファンデーション block.core-nucleus.name = コア: ニュークリアス -block.deepwater.name = 深層水 -block.water.name = 水 +block.deep-water.name = 深層水 +block.shallow-water.name = 水 block.tainted-water.name = 汚れた水 block.darksand-tainted-water.name = 黒い砂で汚れた水 block.tar.name = タール @@ -1078,7 +1078,7 @@ block.sand.name = 砂 block.darksand.name = 黒い砂 block.ice.name = 氷 block.snow.name = 雪 -block.craters.name = クレーター +block.stone-craters.name = クレーター block.sand-water.name = 濁った水 block.darksand-water.name = 黒い砂で濁った水 block.char.name = 焦げ跡 diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 27ec3beb4c..e1f92d697b 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -1106,7 +1106,7 @@ block.cliff.name = 언덕 block.sand-boulder.name = 사암 바위 block.basalt-boulder.name = 현무암 바위 block.grass.name = 잔디 -block.slag.name = 용암 +block.molten-slag.name = 용암 block.space.name = 우주 block.salt.name = 소금 block.salt-wall.name = 소금 벽 @@ -1137,8 +1137,8 @@ block.spawn.name = 적 소환지점 block.core-shard.name = 코어: 조각 block.core-foundation.name = 코어: 기반 block.core-nucleus.name = 코어: 핵심 -block.deepwater.name = 깊은 물 -block.water.name = 물 +block.deep-water.name = 깊은 물 +block.shallow-water.name = 물 block.tainted-water.name = 오염된 물 block.darksand-tainted-water.name = 오염된 젖은 검은 모래 block.tar.name = 타르 @@ -1147,7 +1147,7 @@ block.sand.name = 모래 block.darksand.name = 검은 모래 block.ice.name = 얼음 block.snow.name = 눈 -block.craters.name = 구덩이 +block.stone-craters.name = 구덩이 block.sand-water.name = 젖은 모래 block.darksand-water.name = 젖은 검은 모래 block.char.name = 숯 diff --git a/core/assets/bundles/bundle_lt.properties b/core/assets/bundles/bundle_lt.properties index 0a8290e544..a7bb0f5808 100644 --- a/core/assets/bundles/bundle_lt.properties +++ b/core/assets/bundles/bundle_lt.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Smėlio Riedulys block.grass.name = Žolė -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Druska block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Priešų Atsiradimo Zona block.core-shard.name = Branduolys: Šerdis block.core-foundation.name = Branduolys: Pagrindas block.core-nucleus.name = Branduolys: Centras -block.deepwater.name = Gilus Vanduo -block.water.name = Vanduo +block.deep-water.name = Gilus Vanduo +block.shallow-water.name = Vanduo block.tainted-water.name = Užterštas Vanduo block.darksand-tainted-water.name = Tamsaus Smėlio Užterštas Vanduo block.tar.name = Derva @@ -1001,7 +1001,7 @@ block.sand.name = Smėlis block.darksand.name = Tamsus Smėlis block.ice.name = Ledas block.snow.name = Sniegas -block.craters.name = Krateriai +block.stone-craters.name = Krateriai block.sand-water.name = Smėlio vanduo block.darksand-water.name = Tamsaus Smėlio Vanduo block.char.name = Char diff --git a/core/assets/bundles/bundle_nl.properties b/core/assets/bundles/bundle_nl.properties index 6523ead319..8559cb7185 100644 --- a/core/assets/bundles/bundle_nl.properties +++ b/core/assets/bundles/bundle_nl.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Zandkei block.grass.name = Gras -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Zout block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Vijandelijke Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Diep Water -block.water.name = Water +block.deep-water.name = Diep Water +block.shallow-water.name = Water block.tainted-water.name = Vervuild Water block.darksand-tainted-water.name = Donker Zand Vervuild Water block.tar.name = Olie @@ -1001,7 +1001,7 @@ block.sand.name = Donker Zand block.darksand.name = Donker Zand block.ice.name = Ijs block.snow.name = Sneeuw -block.craters.name = Krarters +block.stone-craters.name = Krarters block.sand-water.name = Zand water block.darksand-water.name = Donker Zand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_nl_BE.properties b/core/assets/bundles/bundle_nl_BE.properties index 2f6d94840c..4fb7a210e4 100644 --- a/core/assets/bundles/bundle_nl_BE.properties +++ b/core/assets/bundles/bundle_nl_BE.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Sand Boulder block.grass.name = Grass -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Salt block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Deep Water -block.water.name = Water +block.deep-water.name = Deep Water +block.shallow-water.name = Water block.tainted-water.name = Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar @@ -1001,7 +1001,7 @@ block.sand.name = Sand block.darksand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.craters.name = Craters +block.stone-craters.name = Craters block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index b1c464655d..1dc7305538 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -1090,7 +1090,7 @@ block.cliff.name = Klif block.sand-boulder.name = Piaskowy Głaz block.basalt-boulder.name = Bazaltowy Głaz block.grass.name = Trawa -block.slag.name = Żużel +block.molten-slag.name = Żużel block.space.name = Kosmos block.salt.name = Sól block.salt-wall.name = Ściana Solna @@ -1121,8 +1121,8 @@ block.spawn.name = Spawn wrogów block.core-shard.name = Rdzeń: Odłamek block.core-foundation.name = Rdzeń: Podstawa block.core-nucleus.name = Rdzeń: Jądro -block.deepwater.name = Głęboka Woda -block.water.name = Woda +block.deep-water.name = Głęboka Woda +block.shallow-water.name = Woda block.tainted-water.name = Skażona Woda block.darksand-tainted-water.name = Skażona Woda z Ciemnym Piaskiem block.tar.name = Smoła @@ -1131,7 +1131,7 @@ block.sand.name = Piasek block.darksand.name = Czarny piasek block.ice.name = Lód block.snow.name = Śnieg -block.craters.name = Kratery +block.stone-craters.name = Kratery block.sand-water.name = Woda z Piaskiem block.darksand-water.name = Woda z Ciemnym Piaskiem block.char.name = Popiół diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties index 20818e5d05..4d9b6fc370 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -1073,7 +1073,7 @@ block.parallax.name = Paralaxe block.cliff.name = Relevo block.sand-boulder.name = Pedregulho de areia block.grass.name = Grama -block.slag.name = Escória +block.molten-slag.name = Escória block.space.name = Space block.salt.name = Sal block.salt-wall.name = Parede de sal @@ -1104,8 +1104,8 @@ block.spawn.name = Área inimiga block.core-shard.name = Fragmento do núcleo block.core-foundation.name = Fundação do núcleo block.core-nucleus.name = Centro do núcleo -block.deepwater.name = Água profunda -block.water.name = Água +block.deep-water.name = Água profunda +block.shallow-water.name = Água block.tainted-water.name = Água tinta block.darksand-tainted-water.name = Água tinta sobre areia escura block.tar.name = Piche @@ -1114,7 +1114,7 @@ block.sand.name = Areia block.darksand.name = Areia escura block.ice.name = Gelo block.snow.name = Neve -block.craters.name = Crateras +block.stone-craters.name = Crateras block.sand-water.name = Água sobre areia block.darksand-water.name = Água sobre areia escura block.char.name = Cinzas diff --git a/core/assets/bundles/bundle_pt_PT.properties b/core/assets/bundles/bundle_pt_PT.properties index 6e08cc7d3f..a0b0605696 100644 --- a/core/assets/bundles/bundle_pt_PT.properties +++ b/core/assets/bundles/bundle_pt_PT.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Pedregulho de areia block.grass.name = Grama -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Sal block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Spawn dos inimigos block.core-shard.name = Fragmento do núcleo block.core-foundation.name = Fundação do núcleo block.core-nucleus.name = Núcleo do núcleo -block.deepwater.name = Água profunda -block.water.name = Água +block.deep-water.name = Água profunda +block.shallow-water.name = Água block.tainted-water.name = Água contaminada block.darksand-tainted-water.name = Água contaminada sobre areia escura block.tar.name = Piche @@ -1001,7 +1001,7 @@ block.sand.name = Areia block.darksand.name = Areia escura block.ice.name = Gelo block.snow.name = Neve -block.craters.name = Crateras +block.stone-craters.name = Crateras block.sand-water.name = Água sobre areia block.darksand-water.name = Água sobre areia escura block.char.name = Char diff --git a/core/assets/bundles/bundle_ro.properties b/core/assets/bundles/bundle_ro.properties index 3dd9d388b0..8be6870cb5 100644 --- a/core/assets/bundles/bundle_ro.properties +++ b/core/assets/bundles/bundle_ro.properties @@ -1107,7 +1107,7 @@ block.cliff.name = Deal block.sand-boulder.name = Bolovan de Nisip block.grass.name = Iarbă block.basalt-boulder.name = Bolovan de Bazalt -block.slag.name = Zgură +block.molten-slag.name = Zgură block.space.name = Cosmos block.salt.name = Sare block.salt-wall.name = Perete de Sare @@ -1138,8 +1138,8 @@ block.spawn.name = Punctul de Lansare Inamic block.core-shard.name = Nucleu: Shard block.core-foundation.name = Nucleu: Foundation block.core-nucleus.name = Nucleu: Core -block.deepwater.name = Apă Adâncă -block.water.name = Apă +block.deep-water.name = Apă Adâncă +block.shallow-water.name = Apă block.tainted-water.name = Apă Tulbure block.darksand-tainted-water.name = Apă Tulbure cu Nisip Negru block.tar.name = Păcură @@ -1148,7 +1148,7 @@ block.sand.name = Nisip block.darksand.name = Nisip Negru block.ice.name = Gheață block.snow.name = Zăpadă -block.craters.name = Cratere +block.stone-craters.name = Cratere block.sand-water.name = Apă cu Nisip block.darksand-water.name = Apă cu Nisip Negru block.char.name = Turbă diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index 25cfa5d9da..c9035e8e59 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -1102,7 +1102,7 @@ block.cliff.name = Скала block.sand-boulder.name = Песчаный валун block.basalt-boulder.name = Базальтовый валун block.grass.name = Трава -block.slag.name = Шлак +block.molten-slag.name = Шлак block.space.name = Космос block.salt.name = Соль block.salt-wall.name = Соляная стена @@ -1133,8 +1133,8 @@ block.spawn.name = Точка появления врагов block.core-shard.name = Ядро: «Осколок» block.core-foundation.name = Ядро: «Штаб» block.core-nucleus.name = Ядро: «Атом» -block.deepwater.name = Глубоководье -block.water.name = Вода +block.deep-water.name = Глубоководье +block.shallow-water.name = Вода block.tainted-water.name = Загрязнённая вода block.darksand-tainted-water.name = Тёмный песок с загрязнённой водой block.tar.name = Нефть @@ -1143,7 +1143,7 @@ block.sand.name = Песок block.darksand.name = Тёмный песок block.ice.name = Лёд block.snow.name = Снег -block.craters.name = Кратеры +block.stone-craters.name = Кратеры block.sand-water.name = Песок с водой block.darksand-water.name = Тёмный песок с водой block.char.name = Выжженная земля diff --git a/core/assets/bundles/bundle_sv.properties b/core/assets/bundles/bundle_sv.properties index 12c3e84a7b..45b6ac8978 100644 --- a/core/assets/bundles/bundle_sv.properties +++ b/core/assets/bundles/bundle_sv.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Sandbumling block.grass.name = Gräs -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Salt block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Djupt Vatten -block.water.name = Vatten +block.deep-water.name = Djupt Vatten +block.shallow-water.name = Vatten block.tainted-water.name = Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tjära @@ -1001,7 +1001,7 @@ block.sand.name = Sand block.darksand.name = Mörk Sand block.ice.name = Is block.snow.name = Snö -block.craters.name = Kratrar +block.stone-craters.name = Kratrar block.sand-water.name = Sandvatten block.darksand-water.name = Mörksandvatten block.char.name = Char diff --git a/core/assets/bundles/bundle_th.properties b/core/assets/bundles/bundle_th.properties index ff7832ad63..6820bd2f71 100644 --- a/core/assets/bundles/bundle_th.properties +++ b/core/assets/bundles/bundle_th.properties @@ -1108,7 +1108,7 @@ block.cliff.name = หน้าผา block.sand-boulder.name = ก้อนหินทราย block.basalt-boulder.name = ก้อนบะซอลต์ block.grass.name = หญ้า -block.slag.name = แร่หลอม +block.molten-slag.name = แร่หลอม block.space.name = อวกาศ block.salt.name = เกลือ block.salt-wall.name = กำแพงเกลือ @@ -1139,8 +1139,8 @@ block.spawn.name = จุดเกิดศัตรู block.core-shard.name = แกนกลาง: ชาร์ด block.core-foundation.name = แกนกลาง: ฟาวน์เดชั่น block.core-nucleus.name = แกนกลาง: นิวเคลียส -block.deepwater.name = น้ำลึก -block.water.name = น้ำ +block.deep-water.name = น้ำลึก +block.shallow-water.name = น้ำ block.tainted-water.name = น้ำเสีย block.darksand-tainted-water.name = น้ำเสียบนทรายดำ block.tar.name = น้ำมันดิบ @@ -1149,7 +1149,7 @@ block.sand.name = ทราย block.darksand.name = ทรายดำ block.ice.name = น้ำแข็ง block.snow.name = หิมะ -block.craters.name = หลุมอุกกาบาต +block.stone-craters.name = หลุมอุกกาบาต block.sand-water.name = น้ำบนทราย block.darksand-water.name = น้ำบนทรายดำ block.char.name = ถ่าน diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties index 8b9f3a97aa..b91132cc5d 100644 --- a/core/assets/bundles/bundle_tk.properties +++ b/core/assets/bundles/bundle_tk.properties @@ -960,7 +960,7 @@ block.parallax.name = Parallax block.cliff.name = Cliff block.sand-boulder.name = Sand Boulder block.grass.name = Grass -block.slag.name = Slag +block.molten-slag.name = Slag block.space.name = Space block.salt.name = Salt block.salt-wall.name = Salt Wall @@ -991,8 +991,8 @@ block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation block.core-nucleus.name = Core: Nucleus -block.deepwater.name = su alti -block.water.name = su +block.deep-water.name = su alti +block.shallow-water.name = su block.tainted-water.name = Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water block.tar.name = Tar @@ -1001,7 +1001,7 @@ block.sand.name = kum block.darksand.name = Dark Sand block.ice.name = buz block.snow.name = kar -block.craters.name = Craters +block.stone-craters.name = Craters block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 9ed3cf52b6..99758d683d 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -1108,7 +1108,7 @@ block.cliff.name = Uçurum block.sand-boulder.name = Kumlu Kaya Parçaları block.basalt-boulder.name = Bazalt Kaya block.grass.name = Çimen -block.slag.name = Cüruf +block.molten-slag.name = Cüruf block.space.name = Uzay block.salt.name = Tuz block.salt-wall.name = Tuz Duvar @@ -1139,8 +1139,8 @@ block.spawn.name = Düşman Doğma Noktası block.core-shard.name = Merkez: Parçacık block.core-foundation.name = Merkez: Temel block.core-nucleus.name = Merkez: Çekirdek -block.deepwater.name = Derin Su -block.water.name = Su +block.deep-water.name = Derin Su +block.shallow-water.name = Su block.tainted-water.name = Kirli Su block.darksand-tainted-water.name = Kara Kumlu Kirli Su block.tar.name = Katran @@ -1149,7 +1149,7 @@ block.sand.name = Kum block.darksand.name = Kara Kum block.ice.name = Buz block.snow.name = Kar -block.craters.name = Krater +block.stone-craters.name = Krater block.sand-water.name = Kumlu Su block.darksand-water.name = Kara Kumlu Su block.char.name = Kömür diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index 915c29534e..a41cafc7d5 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -1061,7 +1061,7 @@ block.cliff.name = Скеля block.sand-boulder.name = Пісочний валун block.basalt-boulder.name = Базальтовий валун block.grass.name = Трава -block.slag.name = Шлак +block.molten-slag.name = Шлак block.space.name = Космос block.salt.name = Сіль block.salt-wall.name = Соляна стіна @@ -1092,8 +1092,8 @@ block.spawn.name = Місце появи противника block.core-shard.name = Ядро «Уламок» block.core-foundation.name = Ядро «Штаб» block.core-nucleus.name = Ядро «Атом» -block.deepwater.name = Глибоководдя -block.water.name = Вода +block.deep-water.name = Глибоководдя +block.shallow-water.name = Вода block.tainted-water.name = Забруднена вода block.darksand-tainted-water.name = Темний пісок із забрудненою водою block.tar.name = Дьоготь @@ -1102,7 +1102,7 @@ block.sand.name = Пісок block.darksand.name = Темний пісок block.ice.name = Лід block.snow.name = Сніг -block.craters.name = Кратери +block.stone-craters.name = Кратери block.sand-water.name = Пісок із водою block.darksand-water.name = Темний пісок із водою block.char.name = Випалена земля diff --git a/core/assets/bundles/bundle_vi.properties b/core/assets/bundles/bundle_vi.properties index 951bb1ecde..52fc53ef3b 100644 --- a/core/assets/bundles/bundle_vi.properties +++ b/core/assets/bundles/bundle_vi.properties @@ -1102,7 +1102,7 @@ block.cliff.name = Vách đá block.sand-boulder.name = Tường cát block.basalt-boulder.name = Tường đá basalt block.grass.name = Cỏ -block.slag.name = Xỉ nóng chảy +block.molten-slag.name = Xỉ nóng chảy block.space.name = Không gian block.salt.name = Muối block.salt-wall.name = Tường muối @@ -1133,8 +1133,8 @@ block.spawn.name = Khu vực tạo ra kẻ địch block.core-shard.name = Căn cứ: Cơ sở block.core-foundation.name = Căn cứ: Trụ sở block.core-nucleus.name = Căn cứ: Trung tâm -block.deepwater.name = Nước sâu -block.water.name = Nước +block.deep-water.name = Nước sâu +block.shallow-water.name = Nước block.tainted-water.name = Nước nhiểm bẩn block.darksand-tainted-water.name = Nước nhiễm bẩn cát đen block.tar.name = Dầu @@ -1143,7 +1143,7 @@ block.sand.name = Cát block.darksand.name = Cát đen block.ice.name = Băng block.snow.name = Tuyết -block.craters.name = Miệng núi lửa +block.stone-craters.name = Miệng núi lửa block.sand-water.name = Nước cát block.darksand-water.name = Nước cát đen block.char.name = Char diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties index 8577a9b6a0..e3f68dc7d1 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -1107,7 +1107,7 @@ block.cliff.name = 悬崖 block.sand-boulder.name = 砂岩 block.basalt-boulder.name = 玄武岩巨石 block.grass.name = 草地 -block.slag.name = 矿渣 +block.molten-slag.name = 矿渣 block.space.name = 太空 block.salt.name = 盐碱地 block.salt-wall.name = 盐墙 @@ -1138,8 +1138,8 @@ block.spawn.name = 敌人出生点 block.core-shard.name = 初代核心 block.core-foundation.name = 次代核心 block.core-nucleus.name = 终代核心 -block.deepwater.name = 深水 -block.water.name = 水 +block.deep-water.name = 深水 +block.shallow-water.name = 水 block.tainted-water.name = 污水 block.darksand-tainted-water.name = 黑沙 污水 block.tar.name = 石油 @@ -1148,7 +1148,7 @@ block.sand.name = 沙子 block.darksand.name = 黑沙 block.ice.name = 冰 block.snow.name = 雪 -block.craters.name = 陨石坑 +block.stone-craters.name = 陨石坑 block.sand-water.name = 沙 水 block.darksand-water.name = 黑沙 水 block.char.name = 焦土 diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index a77a616d24..1863f8a34a 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -1097,7 +1097,7 @@ block.cliff.name = 峭壁 block.sand-boulder.name = 沙礫巨岩 block.basalt-boulder.name = 玄武岩巨石 block.grass.name = 草 -block.slag.name = 熔渣 +block.molten-slag.name = 熔渣 block.space.name = 太空 block.salt.name = 鹽 block.salt-wall.name = 鹽牆 @@ -1128,8 +1128,8 @@ block.spawn.name = 敵人生成 block.core-shard.name = 核心:碎片 block.core-foundation.name = 核心:基地 block.core-nucleus.name = 核心:核子 -block.deepwater.name = 深水 -block.water.name = 水 +block.deep-water.name = 深水 +block.shallow-water.name = 水 block.tainted-water.name = 污水 block.darksand-tainted-water.name = 黑沙污水 block.tar.name = 焦油 @@ -1138,7 +1138,7 @@ block.sand.name = 沙 block.darksand.name = 黑沙 block.ice.name = 冰 block.snow.name = 雪 -block.craters.name = 彈坑 +block.stone-craters.name = 彈坑 block.sand-water.name = 沙水 block.darksand-water.name = 黑沙水 block.char.name = 燒焦 diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties index fd80526784..88b2e7d939 100755 --- a/core/assets/icons/icons.properties +++ b/core/assets/icons/icons.properties @@ -356,3 +356,7 @@ 63356=sharded|team-sharded 63357=crux|team-crux 63358=derelict|team-derelict +63350=deep-water|block-deep-water-ui +63349=shallow-water|block-shallow-water-ui +63348=molten-slag|block-molten-slag-ui +63347=crater-stone|block-crater-stone-ui diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index a17b403b90..03fed2dd61 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -117,7 +117,7 @@ public class Blocks implements ContentList{ new ConstructBlock(i); } - deepwater = new Floor("deepwater"){{ + deepwater = new Floor("deep-water"){{ speedMultiplier = 0.2f; variants = 0; liquidDrop = Liquids.water; @@ -130,7 +130,7 @@ public class Blocks implements ContentList{ albedo = 0.5f; }}; - water = new Floor("water"){{ + water = new Floor("shallow-water"){{ speedMultiplier = 0.5f; variants = 0; status = StatusEffects.wet; @@ -184,7 +184,7 @@ public class Blocks implements ContentList{ cacheLayer = CacheLayer.tar; }}; - slag = new Floor("slag"){{ + slag = new Floor("molten-slag"){{ drownTime = 150f; status = StatusEffects.melting; statusDuration = 240f; @@ -209,7 +209,7 @@ public class Blocks implements ContentList{ stone = new Floor("stone"); - craters = new Floor("craters"){{ + craters = new Floor("crater-stone"){{ variants = 3; blendGroup = stone; }}; diff --git a/core/src/mindustry/io/SaveFileReader.java b/core/src/mindustry/io/SaveFileReader.java index 178980207f..1a059c976b 100644 --- a/core/src/mindustry/io/SaveFileReader.java +++ b/core/src/mindustry/io/SaveFileReader.java @@ -50,7 +50,11 @@ public abstract class SaveFileReader{ "holostone-wall", "dacite-wall", "rock", "boulder", "snowrock", "snow-boulder", - "cliffs", "stone-wall", + "cliffs", "stone-wall", + "craters", "crater-stone", + "deepwater", "deep-water", + "water", "shallow-water", + "slag", "molten-slag", "cryofluidmixer", "cryofluid-mixer" ); From 395f7e0324fa3b597435f6b7f82e52ec1456a6b1 Mon Sep 17 00:00:00 2001 From: RebornTrack970 <62565267+RebornTrack970@users.noreply.github.com> Date: Fri, 6 Aug 2021 20:47:30 +0300 Subject: [PATCH 105/130] Added the Community Server server to Omega (#5705) --- servers_v7.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers_v7.json b/servers_v7.json index 7d7c41026f..4e34aeb15b 100644 --- a/servers_v7.json +++ b/servers_v7.json @@ -13,7 +13,7 @@ }, { "name": "Omega", - "address": ["185.86.230.61:25571", "185.86.230.61:25570", "185.86.230.62:25572"] + "address": ["185.86.230.61:25571", "185.86.230.61:25570", "185.86.230.62:25572","mindustry.me:7175"] }, { "name": "MeowLand", From f0a0b4cfc989ce9629de602f8fae4ce14f6664aa Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 6 Aug 2021 18:01:57 -0400 Subject: [PATCH 106/130] Fixed keyDown not registering at low FPS / Spectre bullet balance --- core/src/mindustry/content/Blocks.java | 2 +- core/src/mindustry/content/Bullets.java | 12 ++++++++---- .../src/mindustry/ui/dialogs/SettingsMenuDialog.java | 2 +- gradle.properties | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 03fed2dd61..0a19f9eee7 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -83,7 +83,7 @@ public class Blocks implements ContentList{ commandCenter, groundFactory, airFactory, navalFactory, additiveReconstructor, multiplicativeReconstructor, exponentialReconstructor, tetrativeReconstructor, - repairPoint, repairTurret, resupplyPoint, + repairPoint, repairTurret, //payloads payloadConveyor, payloadRouter, payloadPropulsionTower, diff --git a/core/src/mindustry/content/Bullets.java b/core/src/mindustry/content/Bullets.java index 560e34f6cd..612053ca51 100644 --- a/core/src/mindustry/content/Bullets.java +++ b/core/src/mindustry/content/Bullets.java @@ -342,11 +342,14 @@ public class Bullets implements ContentList{ lifetime = 60f; }}; - standardDenseBig = new BasicBulletType(7f, 55, "bullet"){{ - hitSize = 5; + standardDenseBig = new BasicBulletType(7.5f, 50, "bullet"){{ + hitSize = 4.8f; width = 15f; height = 21f; shootEffect = Fx.shootBig; + ammoMultiplier = 4; + reloadMultiplier = 1.7f; + knockback = 0.3f; }}; standardThoriumBig = new BasicBulletType(8f, 80, "bullet"){{ @@ -359,7 +362,7 @@ public class Bullets implements ContentList{ knockback = 0.7f; }}; - standardIncendiaryBig = new BasicBulletType(7f, 60, "bullet"){{ + standardIncendiaryBig = new BasicBulletType(7f, 70, "bullet"){{ hitSize = 5; width = 16f; height = 21f; @@ -370,7 +373,8 @@ public class Bullets implements ContentList{ makeFire = true; pierceCap = 2; pierceBuilding = true; - knockback = 0.7f; + knockback = 0.7f; + ammoMultiplier = 3; }}; fireball = new BulletType(1f, 4){ diff --git a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java index 10f399bbe2..8efa0f740e 100644 --- a/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -356,7 +356,7 @@ public class SettingsMenuDialog extends Dialog{ }); graphics.sliderPref("screenshake", 4, 0, 8, i -> (i / 4f) + "x"); - graphics.sliderPref("fpscap", 240, 15, 245, 5, s -> (s > 240 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s))); + graphics.sliderPref("fpscap", 240, 10, 245, 5, s -> (s > 240 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s))); graphics.sliderPref("chatopacity", 100, 0, 100, 5, s -> s + "%"); graphics.sliderPref("lasersopacity", 100, 0, 100, 5, s -> { if(ui.settings != null){ diff --git a/gradle.properties b/gradle.properties index 8595a5a09d..fb533c1a2f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=68277c42b4883e5fcb01dfa20fd27a5434ace891 +archash=e226c78ba913d348c97430e453f038e824c06bcb From cab71958d0948c900114a8a2d096768b4436bd83 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 6 Aug 2021 19:40:27 -0400 Subject: [PATCH 107/130] Implementation of #4921 --- .../world/blocks/units/CommandCenter.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/world/blocks/units/CommandCenter.java b/core/src/mindustry/world/blocks/units/CommandCenter.java index a2c9f34007..ad2b3e075a 100644 --- a/core/src/mindustry/world/blocks/units/CommandCenter.java +++ b/core/src/mindustry/world/blocks/units/CommandCenter.java @@ -26,12 +26,13 @@ public class CommandCenter extends Block{ public Color topColor = null, bottomColor = Color.valueOf("5e5e5e"); public Effect effect = Fx.commandSend; public float effectSize = 150f; + public float forceRadius = 31f, forceStrength = 0.2f; public CommandCenter(String name){ super(name); flags = EnumSet.of(BlockFlag.rally); - destructible = true; + update = true; solid = true; configurable = true; drawDisabled = false; @@ -72,6 +73,22 @@ public class CommandCenter extends Block{ return team.data().command; } + @Override + public void updateTile(){ + super.updateTile(); + + //push away allied units + team.data().tree().intersect(x - forceRadius/2f, y - forceRadius/2f, forceRadius, forceRadius, u -> { + if(!u.isPlayer()){ + float dst = dst(u); + float rs = forceRadius + u.hitSize/2f; + if(dst < rs){ + u.vel.add(Tmp.v1.set(u).sub(x, y).setLength(1f - dst / rs).scl(forceStrength)); + } + } + }); + } + @Override public void draw(){ super.draw(); From 5f296336891f5a1ad7bc4a1d15d5365fd0e32d4f Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 6 Aug 2021 23:19:45 -0400 Subject: [PATCH 108/130] Fixed #5707 --- core/src/mindustry/world/blocks/production/Separator.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/mindustry/world/blocks/production/Separator.java b/core/src/mindustry/world/blocks/production/Separator.java index a863178208..8fb7a09998 100644 --- a/core/src/mindustry/world/blocks/production/Separator.java +++ b/core/src/mindustry/world/blocks/production/Separator.java @@ -8,6 +8,7 @@ import arc.util.io.*; import mindustry.annotations.Annotations.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.logic.*; import mindustry.type.*; import mindustry.world.*; import mindustry.world.consumers.*; @@ -123,6 +124,12 @@ public class Separator extends Block{ } } + @Override + public double sense(LAccess sensor){ + if(sensor == LAccess.progress) return progress; + return super.sense(sensor); + } + @Override public boolean canDump(Building to, Item item){ return !consumes.itemFilters.get(item.id); From ce9bfdbcaee57f56c0ae8182ff5c30de9e7bb43e Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 7 Aug 2021 08:26:49 -0400 Subject: [PATCH 109/130] Fixed #5710 --- .../mindustry/entities/abilities/EnergyFieldAbility.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/entities/abilities/EnergyFieldAbility.java b/core/src/mindustry/entities/abilities/EnergyFieldAbility.java index 5e5acce3bc..3844fc3915 100644 --- a/core/src/mindustry/entities/abilities/EnergyFieldAbility.java +++ b/core/src/mindustry/entities/abilities/EnergyFieldAbility.java @@ -133,7 +133,11 @@ public class EnergyFieldAbility extends Ability{ } }else{ anyNearby = true; - other.damage(damage); + if(other instanceof Building b){ + b.damage(unit.team, damage); + }else{ + other.damage(damage); + } if(other instanceof Statusc s){ s.apply(status, statusDuration); } From ca8fa02687721f935c84807776ff33b36a435bee Mon Sep 17 00:00:00 2001 From: Fatonndev <56699208+Fatonndev@users.noreply.github.com> Date: Sat, 7 Aug 2021 15:28:29 +0300 Subject: [PATCH 110/130] add oblivion pvp server (#5709) --- servers_v6.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers_v6.json b/servers_v6.json index f702e643a6..1c9ccc0590 100644 --- a/servers_v6.json +++ b/servers_v6.json @@ -61,7 +61,7 @@ }, { "name": "md.obvilionnetwork.ru", - "address": ["obvilionnetwork.ru", "obvilionnetwork.ru:7001", "obvilionnetwork.ru:7002"] + "address": ["obvilionnetwork.ru", "obvilionnetwork.ru:7001", "obvilionnetwork.ru:7002", "obvilionnetwork.ru:7003"] }, { "name": "Mindustry PLAY", From b1b89290b97160466d5d840f03a23a20b370f6fa Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 7 Aug 2021 12:08:30 -0400 Subject: [PATCH 111/130] Implemented Anuken/Mindustry-Suggestions/issues/2809 --- .../blocks/production/disassembler.png | Bin 2260 -> 2264 bytes core/src/mindustry/input/Placement.java | 9 ++++++++- gradle.properties | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/core/assets-raw/sprites/blocks/production/disassembler.png b/core/assets-raw/sprites/blocks/production/disassembler.png index 7dbfcb14742caad5cde944dc723cfc0c919f96e7..4e4a4d3433803439bff11a56c0b27d58b65d9bca 100644 GIT binary patch delta 1796 zcmca2ctdc4Vf`de7srr_Id5ZayJO5nY~y&!WMh2VbYpll)egFP$chR36l^>?Nl9mk zv7U3CL)V|44LiIef^s*uawqqAPSm z^ZOF@mvhQhZC`rr`u6$a`t|JF%P(^OUO%rp(J%ka&PS0Ce4D%K#XIMoOzHahb4|8V z^p%aw4AFwu+UI^btaRv4%{EaTXKs1xpYpvNKmV@fcw6&kinxW~ir4a+I0S2Ae*bHq z9~W$X?6KgddxGB+R*6q-xBu~6-%wdyzII!QudqM!`^}##f+W2&s;7C2O<0gCY$Cas zL&H&UQK!0MQ%!@K^`hT#qV)_BB8^^WK83AuZqfK8yhSOZC6Sfkl~RPSP{dk}i%--& zlp@wP!YjPEl(XWed5OFTEQ}% z|wMmB4=fMQq8%c?#NK^I1o zC(rkS%6;*z9HERhPo95&_I$J2 zC*dfU3rAwNb6h{VT=>BWe~+1~T6MYW{=C@nYt1iN&aX4t`T4{@9TNQe=3{Z-ii2-s zufKV)wSM`1nF)6D>rm2*P>(R);?j* zzt^+J>bA(Im0PMq-S612+~#;LX#3>(OsRf%Y1cYk{)j#mpi{@$Ev_JV0zz1`RO|K3%d(@GFs$aea} z&Xv-;?5z*Kd?#D_W740WM_W}b|9rcH(85Bw?A+S8U*WgF#P@#DVtw|yy`pFd0X>A73%k}+L>>7m_^qKdhD zo!p$)3vq}za)k>k7OkAJt@?Iz%>hfPU4DXV_%`O;%2t!lkl@|g!|8dUE1{G#{W4EU z{r5@y7VSzxS(m5DxzzeIY~q;sB)k4^Xm*AWLqso!-1YII<1uv2nL2tLW)#CqdUUjU<^0LEYo*c&+47Mk(|4{Puc{EI;NLn*3%$|H5?(*i{?%!^!1EVPg6Ri z>cQ>&>3*P6h4^H1f6qLrpPXBl2430fD}M0FG$GG_7tiU2?vPTOtm)?OXHZqNC`#|B zkXfBF0Oy152H_oh$amavlgwQutUwsnk5dm<(`aELhA ziA4NZ5!tkpYg1X^{ql$(3tV25bzN#_;g(M=-EvnqmG^}1!BocREy|IH{$B{F;urq^ SyOM!{fx*+&&t;ucLK6V>AVz!u delta 1791 zcmca1ctvo6VSS&ci(^Q|oVT&I{V}E@wvn!0SyPfEawjIa7%mX$=*pU^~~mQvOx5zShS0VQ=pcX%f=?nMVi|r-uej!PHqcuxmRIx{rl2n=}9Oy0_`^x3AaP{Q7zI!8g6C#Q#r?4bQynwGFr7-ji7$@KI@_@k}2>`}w85 zDcx3O3<=tYer=ds7vVBv{`qZ9sTmKG)&DORRNTK`bm83oxu2NSnM(iGiYYerXWy^+ z{a5?du?icfd)ANSe7-LF^nv~VAJw!cPn!Lwt;>9r`JlE;&R;8;GxvPaNhYB!xlL-x zB8;jUP9`5!Tqf{eNO3Q@U%#4(p<5}SGxAg390;}={r(S7>xz*Pl@qfA0Sf97Yu*KnV?qwUU#g&h44 zgbvR77I@h;R!Bj8{~ou_2erXrs!rWow{|ReyGW12VPd?J_`<6`)!hPtS6%BPn8f39 zS{lvYI{dR=)%Ql#DaHD+pkwsErEWX6G)=0}>M{Q)BXy`xFO{3MpQfG{5pqzfH=5bSTf8shk(d%oSC&YogkQuV%}XMv*q`8R)Rwuu~fs`G!M#E^S6)ycOdDmrv+(~6D7+CLAx zHdkJM&aAaY>uuasL393tW``;_ zJL-^C`NC}tt64a_7Z}~}`uDKe`J1zrzDD?q%hJ`}q1`OKsuk`<-ZNMkQUsMw_)l<| zaANtqm5l06B0m|7>*YV(eQ>|^e|o)5JlEoteNiXQC+a5nT4cZXR+gE%UA$iZ)A!%Y z<0llZ7F$r*Hc9H4#wW(xGX%u9T@~`mh~w$=-p17>;MjezK%;MIhRcPPja>oG+CLi> z@kX?AG(UWOukYCHCgmGRs%w>8Ch%)WKb)te@=17)QbpU^y-F?<`6cSzoYg01%yx>$uh_y>j09)=R&nr|Jiu$XK!L`r@rE?f>^Cy!W1FU_bxii=vjr zrvpE0$-ZmWZ@+$1JH_OSR-=R9k^)mfrRiRoySLk(V4t&i;cJnDuLMpn+ne@@F;)4E zs3Z4UjHQEYF#r5J9S)dn0#tfU}V_M5hFdxrQ?IUuTqA)uW5&pJckIw3uPx3v#B)-5e>R; zI7Ab^JUJpVulls|?wz-0n(~^QJ0RA=d7-(cSASBA$-FHqm0CCwROdVYe73#gLFD}U zHLg=Q&N6*bu|KHnboy6{u98cJP=e?ab(awL@XXu^9Pc=1p2%CY?cmjp1(ABJN4gxg zD&FFhygp?~X_A^!Ow$$vmH)D;P34A_pQk)oHgSGHw3KV??GizsJk5zuZ_gx$!uBIZR@flPB|yW&SJu!minJZS*`WYD4y?svUwKEqAIsA_qCU$ zs~?pg{&zav;?ScBuD&+kTh0U>n{&1Ec*lMNj#4r?p?L)tjE~ZswMLxt?oF_ky@Z zAyw|dPt>>9zYY8TCCK8vd;HAfVV{C`n!J0tw7lfA&{7$hpCN3~I*wANSN&eOOpO1x z?^O5a)3qKgTlDq-$*3W8zIE_`^b)@{DRwvJKPCO+<8*X*S9hOXs| zSFM?N_A0z>&c1$6JmSZS$fliKo5}+3mqz?p;PRrZ>(cMZ>p4V4`Y#q@FJP$&QZ diff --git a/core/src/mindustry/input/Placement.java b/core/src/mindustry/input/Placement.java index f4afb96683..55044dc8e0 100644 --- a/core/src/mindustry/input/Placement.java +++ b/core/src/mindustry/input/Placement.java @@ -108,7 +108,13 @@ public class Placement{ points.addAll(result); } + public static boolean isSidePlace(Seq plans){ + return plans.size > 1 && Mathf.mod(Tile.relativeTo(plans.first().x, plans.first().y, plans.get(1).x, plans.get(1).y) - plans.first().rotation, 2) == 1; + } + public static void calculateBridges(Seq plans, ItemBridge bridge){ + if(isSidePlace(plans)) return; + //check for orthogonal placement + unlocked state if(!(plans.first().x == plans.peek().x || plans.first().y == plans.peek().y) || !bridge.unlockedNow()){ return; @@ -170,6 +176,8 @@ public class Placement{ } public static void calculateDuctBridges(Seq plans, DuctBridge bridge){ + if(isSidePlace(plans)) return; + //check for orthogonal placement + unlocked state if(!(plans.first().x == plans.peek().x || plans.first().y == plans.peek().y) || !bridge.unlockedNow()){ return; @@ -180,7 +188,6 @@ public class Placement{ var result = plans1.clear(); var team = player.team(); - var rot = plans.first().rotation; outer: for(int i = 0; i < plans.size;){ diff --git a/gradle.properties b/gradle.properties index fb533c1a2f..dc2ce3354d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=e226c78ba913d348c97430e453f038e824c06bcb +archash=28f7dea17ba559a28e79111adc93cf0496ced031 From 6cb2c0e8a7350b0f8a74c3b5a85f683822ff12e4 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 7 Aug 2021 12:22:34 -0400 Subject: [PATCH 112/130] Anuken/Mindustry-Suggestions/issues/2810 --- core/src/mindustry/content/UnitTypes.java | 4 ++-- .../world/blocks/distribution/Conveyor.java | 18 ++++++++++++++++-- .../mindustry/world/blocks/liquid/Conduit.java | 17 +++++++++++++++-- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index ed9d68beb3..d045e36f62 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -429,7 +429,7 @@ public class UnitTypes implements ContentList{ lowAltitude = true; riseSpeed = 0.02f; - health = 8000f; + health = 8200f; armor = 9f; canBoost = true; landShake = 4f; @@ -454,7 +454,7 @@ public class UnitTypes implements ContentList{ cooldownTime = 200f; bullet = new ContinuousLaserBulletType(){{ - damage = 32f; + damage = 35f; length = 180f; hitEffect = Fx.hitMeltHeal; drawSize = 420f; diff --git a/core/src/mindustry/world/blocks/distribution/Conveyor.java b/core/src/mindustry/world/blocks/distribution/Conveyor.java index 1714e038df..c45b6a7981 100644 --- a/core/src/mindustry/world/blocks/distribution/Conveyor.java +++ b/core/src/mindustry/world/blocks/distribution/Conveyor.java @@ -32,6 +32,8 @@ public class Conveyor extends Block implements Autotiler{ public float speed = 0f; public float displayedSpeed = 0f; + public @Nullable Block junctionReplacement, bridgeReplacement; + public Conveyor(String name){ super(name); rotate = true; @@ -55,6 +57,14 @@ public class Conveyor extends Block implements Autotiler{ stats.add(Stat.itemsMoved, displayedSpeed, StatUnit.itemsSecond); } + @Override + public void init(){ + super.init(); + + if(junctionReplacement == null) junctionReplacement = Blocks.junction; + if(bridgeReplacement == null || !(bridgeReplacement instanceof ItemBridge)) bridgeReplacement = Blocks.itemBridge; + } + @Override public void drawRequestRegion(BuildPlan req, Eachable list){ int[] bits = getTiling(req, list); @@ -79,7 +89,9 @@ public class Conveyor extends Block implements Autotiler{ @Override public void handlePlacementLine(Seq plans){ - Placement.calculateBridges(plans, (ItemBridge)Blocks.itemBridge); + if(bridgeReplacement == null) return; + + Placement.calculateBridges(plans, (ItemBridge)bridgeReplacement); } @Override @@ -94,12 +106,14 @@ public class Conveyor extends Block implements Autotiler{ @Override public Block getReplacement(BuildPlan req, Seq requests){ + if(junctionReplacement == null) return this; + Boolf cont = p -> requests.contains(o -> o.x == req.x + p.x && o.y == req.y + p.y && (req.block instanceof Conveyor || req.block instanceof Junction)); return cont.get(Geometry.d4(req.rotation)) && cont.get(Geometry.d4(req.rotation - 2)) && req.tile() != null && req.tile().block() instanceof Conveyor && - Mathf.mod(req.tile().build.rotation - req.rotation, 2) == 1 ? Blocks.junction : this; + Mathf.mod(req.tile().build.rotation - req.rotation, 2) == 1 ? junctionReplacement : this; } public class ConveyorBuild extends Building implements ChainedBuilding{ diff --git a/core/src/mindustry/world/blocks/liquid/Conduit.java b/core/src/mindustry/world/blocks/liquid/Conduit.java index dc0f03767e..1218ef9030 100644 --- a/core/src/mindustry/world/blocks/liquid/Conduit.java +++ b/core/src/mindustry/world/blocks/liquid/Conduit.java @@ -31,6 +31,7 @@ public class Conduit extends LiquidBlock implements Autotiler{ public @Load("@-cap") TextureRegion capRegion; public boolean leaks = true; + public @Nullable Block junctionReplacement, bridgeReplacement; public Conduit(String name){ super(name); @@ -41,6 +42,14 @@ public class Conduit extends LiquidBlock implements Autotiler{ noUpdateDisabled = true; } + @Override + public void init(){ + super.init(); + + if(junctionReplacement == null) junctionReplacement = Blocks.liquidJunction; + if(bridgeReplacement == null || !(bridgeReplacement instanceof ItemBridge)) bridgeReplacement = Blocks.bridgeConduit; + } + @Override public void drawRequestRegion(BuildPlan req, Eachable list){ int[] bits = getTiling(req, list); @@ -58,12 +67,14 @@ public class Conduit extends LiquidBlock implements Autotiler{ @Override public Block getReplacement(BuildPlan req, Seq requests){ + if(junctionReplacement == null) return this; + Boolf cont = p -> requests.contains(o -> o.x == req.x + p.x && o.y == req.y + p.y && o.rotation == req.rotation && (req.block instanceof Conduit || req.block instanceof LiquidJunction)); return cont.get(Geometry.d4(req.rotation)) && cont.get(Geometry.d4(req.rotation - 2)) && req.tile() != null && req.tile().block() instanceof Conduit && - Mathf.mod(req.build().rotation - req.rotation, 2) == 1 ? Blocks.liquidJunction : this; + Mathf.mod(req.build().rotation - req.rotation, 2) == 1 ? junctionReplacement : this; } @Override @@ -73,7 +84,9 @@ public class Conduit extends LiquidBlock implements Autotiler{ @Override public void handlePlacementLine(Seq plans){ - Placement.calculateBridges(plans, (ItemBridge)Blocks.bridgeConduit); + if(bridgeReplacement == null) return; + + Placement.calculateBridges(plans, (ItemBridge)bridgeReplacement); } @Override From 71c4f27d6078fe30768a32110e478ff453ea4f93 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 7 Aug 2021 12:34:11 -0400 Subject: [PATCH 113/130] Removed pointless 'device' switcher / Anuken/Mindustry-Suggestions/issues/2811 (but only partially) --- core/src/mindustry/content/UnitTypes.java | 6 +++--- core/src/mindustry/ui/dialogs/KeybindDialog.java | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index d045e36f62..67d7bde521 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -413,7 +413,7 @@ public class UnitTypes implements ContentList{ vela = new UnitType("vela"){{ hitSize = 24f; - rotateSpeed = 1.6f; + rotateSpeed = 1.7f; canDrown = false; mechFrontSway = 1f; buildSpeed = 3f; @@ -422,7 +422,7 @@ public class UnitTypes implements ContentList{ mechStepShake = 0.15f; ammoType = new PowerAmmoType(2500); - speed = 0.4f; + speed = 0.44f; boostMultiplier = 2.2f; engineOffset = 12f; engineSize = 6f; @@ -1335,7 +1335,7 @@ public class UnitTypes implements ContentList{ quad = new UnitType("quad"){{ armor = 8f; health = 6000; - speed = 1.4f; + speed = 1.3f; rotateSpeed = 2f; accel = 0.05f; drag = 0.017f; diff --git a/core/src/mindustry/ui/dialogs/KeybindDialog.java b/core/src/mindustry/ui/dialogs/KeybindDialog.java index 0aefcb2a38..f718333ee3 100644 --- a/core/src/mindustry/ui/dialogs/KeybindDialog.java +++ b/core/src/mindustry/ui/dialogs/KeybindDialog.java @@ -115,9 +115,8 @@ public class KeybindDialog extends Dialog{ } }).disabled(sectionControls.get(section, 0) + 1 >= devices.size).size(40); - table.add(stable).colspan(4); + //table.add(stable).colspan(4).row(); - table.row(); table.add().height(10); table.row(); if(section.device.type() == DeviceType.controller){ From 644d00b268dcd4b67051714275fc9ab5469c66a1 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 7 Aug 2021 17:37:55 -0400 Subject: [PATCH 114/130] Misc ammo balancing --- core/src/mindustry/content/Bullets.java | 10 +++++----- core/src/mindustry/input/DesktopInput.java | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/mindustry/content/Bullets.java b/core/src/mindustry/content/Bullets.java index 612053ca51..600bf4fddf 100644 --- a/core/src/mindustry/content/Bullets.java +++ b/core/src/mindustry/content/Bullets.java @@ -113,6 +113,7 @@ public class Bullets implements ContentList{ splashDamageRadius = 25f * 0.75f; splashDamage = 35f; status = StatusEffects.burning; + statusDuration = 60f * 12f; frontColor = Pal.lightishOrange; backColor = Pal.lightOrange; makeFire = true; @@ -132,7 +133,6 @@ public class Bullets implements ContentList{ frontColor = Pal.missileYellow; status = StatusEffects.blasted; - statusDuration = 60f; }}; flakGlassFrag = new BasicBulletType(3f, 5, "bullet"){{ @@ -177,7 +177,7 @@ public class Bullets implements ContentList{ width = 6f; height = 8f; hitEffect = Fx.flakExplosion; - splashDamage = 22f * 1.5f; + splashDamage = 25f * 1.5f; splashDamageRadius = 20f; fragBullet = flakGlassFrag; fragBullets = 6; @@ -432,13 +432,13 @@ public class Bullets implements ContentList{ hittable = false; }}; - pyraFlame = new BulletType(3.35f, 25f){{ - ammoMultiplier = 4f; + pyraFlame = new BulletType(4f, 45f){{ + ammoMultiplier = 6f; hitSize = 7f; lifetime = 18f; pierce = true; collidesAir = false; - statusDuration = 60f * 6; + statusDuration = 60f * 10; shootEffect = Fx.shootPyraFlame; hitEffect = Fx.hitFlameSmall; despawnEffect = Fx.none; diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java index c2d61af046..efe122e893 100644 --- a/core/src/mindustry/input/DesktopInput.java +++ b/core/src/mindustry/input/DesktopInput.java @@ -43,7 +43,7 @@ public class DesktopInput extends InputHandler{ /** Whether player is currently deleting removal requests. */ public boolean deleting = false, shouldShoot = false, panning = false; /** Mouse pan speed. */ - public float panScale = 0.005f, panSpeed = 4.5f, panBoostSpeed = 11f; + public float panScale = 0.005f, panSpeed = 4.5f, panBoostSpeed = 15f; /** Delta time between consecutive clicks. */ public long selectMillis = 0; /** Previously selected tile. */ From 99b34204231a3614cd61f5f5ef7e8a5b140aacae Mon Sep 17 00:00:00 2001 From: Yakuzet <52811148+Yakuzet@users.noreply.github.com> Date: Sun, 8 Aug 2021 01:12:31 +0300 Subject: [PATCH 115/130] fix update TR bundle (#5715) translated some new things and fixed some translation --- core/assets/bundles/bundle_tr.properties | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 99758d683d..6a243b035f 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -18,7 +18,7 @@ linkfail = Link açılamadı!\nURL kopyalandı. screenshot = Ekran görüntüsü {0} konumuna kaydedildi screenshot.invalid = Harita çok büyük, muhtemelen ekran görüntüsü için yeterli bellek yok. gameover = Kaybettin -gameover.waiting = [accent]Harita Bekleniyor... +gameover.waiting = [accent]Sonraki Harita Bekleniyor... gameover.pvp = [accent] {0}[] Takımı kazandı! gameover.disconnect = Bağlantı Koptu! highscore = [accent]Yeni rekor! @@ -35,7 +35,7 @@ load.mod = Modlar load.scripts = Betikler be.update = Yeni bir erken erişim sürümü var: -be.update.confirm = Yüklenip yeniden başlatılsın mı? +be.update.confirm = İndirip yeniden başlatılsın mı? be.updating = Yeni sürüm yükleniyor... be.ignore = Hayır be.noupdates = Yeni güncelleme bulunamadı. @@ -54,30 +54,30 @@ schematic.add = Şemayı Kaydet... schematics = Şemalar schematic.replace = Aynı isimde bir şema zaten var. Üzerine yazılsın mı? schematic.exists = Aynı isimde bir şema zaten var. -schematic.import = Şema İçeri Aktar... +schematic.import = Şemayı İçeri Aktar... schematic.exportfile = Dışa Aktar schematic.importfile = İçe Aktar -schematic.browseworkshop = Atölyeyi incele +schematic.browseworkshop = Atölyeyi araştır schematic.copy = Panoya Kopyala schematic.copy.import = Panodan İçeri Aktar -schematic.shareworkshop = Atölyede Kaydet +schematic.shareworkshop = Atölyede paylaş schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Şemayı döndür schematic.saved = Şema Kaydedildi. -schematic.delete.confirm = Bu şema tamamen yok edilecek. +schematic.delete.confirm = Bu şema tamamen silinecek. schematic.rename = Şemayı yeniden adlandır schematic.info = {0}x{1}, {2} blok -schematic.disabled = [scarlet]Schematics disabled[]\nYou are not allowed to use schematics on this [accent]map[] or [accent]server. +schematic.disabled = [scarlet]Şema devre dışı bırakıldı[]\nBu şemayı [accent]bu haritada[] veya [accent]server'da kullanma iznin yok. schematic.tags = Etiketler: schematic.edittags = Etiketleri Düzenle schematic.addtag = Etiket Ekle schematic.texttag = Yazı Etiketi -schematic.icontag = İcon Etiketi +schematic.icontag = İkon Etiketi schematic.renametag = Etiketi Yeniden Adlandır schematic.tagdelconfirm = Bu Etiketi Silmek istediğine emin misin? schematic.tagexists = Böyle bir Etiket zaten var. stats = İstatistikler -stat.wave = Yenilen Dalgalar:[accent] {0} +stat.wave = Bozguna Uğratılan Dalgalar:[accent] {0} stat.enemiesDestroyed = Yok Edilen Düşmanlar:[accent] {0} stat.built = İnşa Edilen Yapılar:[accent] {0} stat.destroyed = Yok Edilen Yapılar:[accent] {0} @@ -89,7 +89,7 @@ stat.rank = Rütbe: [accent]{0} globalitems = [accent]Toplanan Kaynaklar map.delete = "[accent]{0}[]" haritasını silmek istediğine emin misin? level.highscore = Rekor: [accent]{0} -level.select = Seviye Seçimi +level.select = Bölüm Seçimi level.mode = Oyun Modu: coreattack = < Merkez saldırı altında! > nearpoint = [[ [scarlet]İNİŞ PİSTİNDEN AYRIL[] ]\nimha tehlikesi @@ -122,7 +122,7 @@ committingchanges = Değişiklikler Uygulanıyor done = Bitti feature.unsupported = Cihazınızda bu özellik desteklenmemektedir. -mods.initfailed = [red]⚠[] OH NO! Mindustry Çöktü. Bu Büyük ihtimalle bir moddan kaynaklandı.\n\nSonsuz Çökmeyi önlemek için, [red]tüm modlar kapatıldı.[]\n\nBu özelliği kapamak için, [accent]Ayarlar->Oyun->Modları Çökmede Kapa[]. +mods.initfailed = [red]⚠[] OLAMAZ! Mindustry Çöktü. Bu Büyük ihtimalle bir moddan kaynaklandı.\n\nSonsuz Çökmeyi önlemek için, [red]tüm modlar kapatıldı.[]\n\nBu özelliği kapamak için, [accent]Ayarlar->Oyun->Modları Başlangıçta Çökme Durumunda Kapat[]. mods = Modlar mods.none = [lightgray]Hiç mod bulunamadı! mods.guide = Mod Rehberi From e40ab50e10302a14818f2bd4e32f167d5a5207ac Mon Sep 17 00:00:00 2001 From: buthed010203 Date: Sat, 7 Aug 2021 21:24:03 -0400 Subject: [PATCH 116/130] why are there soaces here ? (#5716) good question --- core/src/mindustry/entities/comp/BuildingComp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index b474a8bfdf..9e7ffc8d79 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -1074,7 +1074,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, public String getDisplayName(){ //derelict team icon currently doesn't display - return team == Team.derelict ? + return team == Team.derelict ? block.localizedName + "\n" + Core.bundle.get("block.derelict") : block.localizedName + (team == player.team() || team.emoji.isEmpty() ? "" : " " + team.emoji); } From 00a2c1aad0a626b663c6379013ad322395a53729 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 8 Aug 2021 13:37:55 -0400 Subject: [PATCH 117/130] Refactored fireball into FireBulletType --- core/assets/scripts/global.js | 2 +- core/src/mindustry/content/Bullets.java | 52 +-------------- core/src/mindustry/content/UnitTypes.java | 6 +- .../mindustry/entities/bullet/BulletType.java | 18 +++--- .../entities/bullet/FireBulletType.java | 64 +++++++++++++++++++ .../entities/bullet/MassDriverBolt.java | 2 +- core/src/mindustry/mod/ClassMap.java | 3 +- .../mindustry/ui/dialogs/KeybindDialog.java | 13 ++-- .../world/blocks/distribution/DuctRouter.java | 2 +- 9 files changed, 92 insertions(+), 70 deletions(-) create mode 100644 core/src/mindustry/entities/bullet/FireBulletType.java diff --git a/core/assets/scripts/global.js b/core/assets/scripts/global.js index 4f81328cce..37b756544e 100755 --- a/core/assets/scripts/global.js +++ b/core/assets/scripts/global.js @@ -90,7 +90,6 @@ importPackage(Packages.mindustry.editor) importPackage(Packages.mindustry.entities) importPackage(Packages.mindustry.entities.abilities) importPackage(Packages.mindustry.entities.bullet) -importPackage(Packages.mindustry.entities.comp) importPackage(Packages.mindustry.entities.effect) importPackage(Packages.mindustry.entities.units) importPackage(Packages.mindustry.game) @@ -157,6 +156,7 @@ const ResearchEvent = Packages.mindustry.game.EventType.ResearchEvent const UnlockEvent = Packages.mindustry.game.EventType.UnlockEvent const StateChangeEvent = Packages.mindustry.game.EventType.StateChangeEvent const CoreChangeEvent = Packages.mindustry.game.EventType.CoreChangeEvent +const BuildTeamChangeEvent = Packages.mindustry.game.EventType.BuildTeamChangeEvent const TileChangeEvent = Packages.mindustry.game.EventType.TileChangeEvent const TilePreChangeEvent = Packages.mindustry.game.EventType.TilePreChangeEvent const GameOverEvent = Packages.mindustry.game.EventType.GameOverEvent diff --git a/core/src/mindustry/content/Bullets.java b/core/src/mindustry/content/Bullets.java index 600bf4fddf..abef6c9c16 100644 --- a/core/src/mindustry/content/Bullets.java +++ b/core/src/mindustry/content/Bullets.java @@ -1,17 +1,9 @@ package mindustry.content; import arc.graphics.*; -import arc.graphics.g2d.*; -import arc.math.*; -import arc.util.*; import mindustry.ctype.*; -import mindustry.entities.*; import mindustry.entities.bullet.*; -import mindustry.gen.*; import mindustry.graphics.*; -import mindustry.world.*; - -import static mindustry.Vars.*; public class Bullets implements ContentList{ public static BulletType @@ -377,47 +369,9 @@ public class Bullets implements ContentList{ ammoMultiplier = 3; }}; - fireball = new BulletType(1f, 4){ - { - pierce = true; - collidesTiles = false; - collides = false; - drag = 0.03f; - hitEffect = despawnEffect = Fx.none; - } + fireball = new FireBulletType(1f, 4); - @Override - public void init(Bullet b){ - b.vel.setLength(0.6f + Mathf.random(2f)); - } - - @Override - public void draw(Bullet b){ - Draw.color(Pal.lightFlame, Pal.darkFlame, Color.gray, b.fin()); - Fill.circle(b.x, b.y, 3f * b.fout()); - Draw.reset(); - } - - @Override - public void update(Bullet b){ - if(Mathf.chance(0.04 * Time.delta)){ - Tile tile = world.tileWorld(b.x, b.y); - if(tile != null){ - Fires.create(tile); - } - } - - if(Mathf.chance(0.1 * Time.delta)){ - Fx.fireballsmoke.at(b.x, b.y); - } - - if(Mathf.chance(0.1 * Time.delta)){ - Fx.ballfire.at(b.x, b.y); - } - } - }; - - basicFlame = new BulletType(3.35f, 16f){{ + basicFlame = new BulletType(3.35f, 17f){{ ammoMultiplier = 3f; hitSize = 7f; lifetime = 18f; @@ -432,7 +386,7 @@ public class Bullets implements ContentList{ hittable = false; }}; - pyraFlame = new BulletType(4f, 45f){{ + pyraFlame = new BulletType(4f, 50f){{ ammoMultiplier = 6f; hitSize = 7f; lifetime = 18f; diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 67d7bde521..cbf721be16 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -101,10 +101,10 @@ public class UnitTypes implements ContentList{ reload = 11f; recoil = 1f; ejectEffect = Fx.none; - bullet = new BulletType(4.1f, 32f){{ + bullet = new BulletType(4.1f, 35f){{ ammoMultiplier = 3f; hitSize = 7f; - lifetime = 12f; + lifetime = 13f; pierce = true; statusDuration = 60f * 4; shootEffect = Fx.shootSmallFlame; @@ -344,7 +344,7 @@ public class UnitTypes implements ContentList{ bullet = new LightningBulletType(){{ lightningColor = hitColor = Pal.heal; - damage = 12f; + damage = 14f; lightningLength = 7; lightningLengthRand = 7; shootEffect = Fx.shootHeal; diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index 3640299921..213c911a6b 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -343,15 +343,6 @@ public class BulletType extends Content implements Cloneable{ if(instantDisappear){ b.time = lifetime; } - - if(fragBullet != null || splashDamageRadius > 0 || lightning > 0){ - despawnHit = true; - } - - if(lightRadius == -1){ - lightRadius = Math.max(18, hitSize * 5f); - } - drawSize = Math.max(drawSize, trailLength * speed * 2f); } public void update(Bullet b){ @@ -412,6 +403,15 @@ public class BulletType extends Content implements Cloneable{ if(lightningType == null){ lightningType = !collidesAir ? Bullets.damageLightningGround : Bullets.damageLightning; } + + if(fragBullet != null || splashDamageRadius > 0 || lightning > 0){ + despawnHit = true; + } + + if(lightRadius == -1){ + lightRadius = Math.max(18, hitSize * 5f); + } + drawSize = Math.max(drawSize, trailLength * speed * 2f); } @Override diff --git a/core/src/mindustry/entities/bullet/FireBulletType.java b/core/src/mindustry/entities/bullet/FireBulletType.java new file mode 100644 index 0000000000..a2b14e4481 --- /dev/null +++ b/core/src/mindustry/entities/bullet/FireBulletType.java @@ -0,0 +1,64 @@ +package mindustry.entities.bullet; + +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; +import mindustry.graphics.*; + +public class FireBulletType extends BulletType{ + public Color colorFrom = Pal.lightFlame, colorMid = Pal.darkFlame, colorTo = Color.gray; + public float radius = 3f; + public float velMin = 0.6f, velMax = 2.6f; + public float fireTrailChance = 0.04f; + public Effect trailEffect2 = Fx.ballfire; + public float fireEffectChance = 0.1f, fireEffectChance2 = 0.1f; + + { + pierce = true; + collidesTiles = false; + collides = false; + drag = 0.03f; + hitEffect = despawnEffect = Fx.none; + trailEffect = Fx.fireballsmoke; + } + + public FireBulletType(float speed, float damage){ + super(speed, damage); + } + + public FireBulletType(){} + + @Override + public void init(Bullet b){ + super.init(b); + + b.vel.setLength(Mathf.random(velMin, velMax)); + } + + @Override + public void draw(Bullet b){ + Draw.color(colorFrom, colorMid, colorTo, b.fin()); + Fill.circle(b.x, b.y, radius * b.fout()); + Draw.reset(); + } + + @Override + public void update(Bullet b){ + super.update(b); + + if(Mathf.chanceDelta(fireTrailChance)){ + Fires.create(b.tileOn()); + } + + if(Mathf.chanceDelta(fireEffectChance)){ + trailEffect.at(b.x, b.y); + } + + if(Mathf.chanceDelta(fireEffectChance2)){ + trailEffect2.at(b.x, b.y); + } + } +} diff --git a/core/src/mindustry/entities/bullet/MassDriverBolt.java b/core/src/mindustry/entities/bullet/MassDriverBolt.java index 91dae839a8..006c490183 100644 --- a/core/src/mindustry/entities/bullet/MassDriverBolt.java +++ b/core/src/mindustry/entities/bullet/MassDriverBolt.java @@ -13,7 +13,7 @@ import static mindustry.Vars.*; public class MassDriverBolt extends BulletType{ public MassDriverBolt(){ - super(1f, 50); + super(1f, 75); collidesTiles = false; lifetime = 1f; despawnEffect = Fx.smeltsmoke; diff --git a/core/src/mindustry/mod/ClassMap.java b/core/src/mindustry/mod/ClassMap.java index 9b7b017cf8..9faafacdeb 100644 --- a/core/src/mindustry/mod/ClassMap.java +++ b/core/src/mindustry/mod/ClassMap.java @@ -31,6 +31,7 @@ public class ClassMap{ classes.put("BulletType", mindustry.entities.bullet.BulletType.class); classes.put("ContinuousLaserBulletType", mindustry.entities.bullet.ContinuousLaserBulletType.class); classes.put("EmpBulletType", mindustry.entities.bullet.EmpBulletType.class); + classes.put("FireBulletType", mindustry.entities.bullet.FireBulletType.class); classes.put("FlakBulletType", mindustry.entities.bullet.FlakBulletType.class); classes.put("LaserBoltBulletType", mindustry.entities.bullet.LaserBoltBulletType.class); classes.put("LaserBulletType", mindustry.entities.bullet.LaserBulletType.class); @@ -140,7 +141,7 @@ public class ClassMap{ classes.put("DuctBridge", mindustry.world.blocks.distribution.DuctBridge.class); classes.put("DuctBridgeBuild", mindustry.world.blocks.distribution.DuctBridge.DuctBridgeBuild.class); classes.put("DuctRouter", mindustry.world.blocks.distribution.DuctRouter.class); - classes.put("DuctBuild", mindustry.world.blocks.distribution.DuctRouter.DuctBuild.class); + classes.put("DuctRouterBuild", mindustry.world.blocks.distribution.DuctRouter.DuctRouterBuild.class); classes.put("ExtendingItemBridge", mindustry.world.blocks.distribution.ExtendingItemBridge.class); classes.put("ExtendingItemBridgeBuild", mindustry.world.blocks.distribution.ExtendingItemBridge.ExtendingItemBridgeBuild.class); classes.put("ItemBridge", mindustry.world.blocks.distribution.ItemBridge.class); diff --git a/core/src/mindustry/ui/dialogs/KeybindDialog.java b/core/src/mindustry/ui/dialogs/KeybindDialog.java index f718333ee3..c51003724c 100644 --- a/core/src/mindustry/ui/dialogs/KeybindDialog.java +++ b/core/src/mindustry/ui/dialogs/KeybindDialog.java @@ -13,6 +13,7 @@ import arc.struct.*; import arc.util.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.ui.*; import static arc.Core.*; @@ -72,7 +73,7 @@ public class KeybindDialog extends Dialog{ } if(sections.length != 1){ - TextButton button = new TextButton(bundle.get("section." + section.name + ".name", Strings.capitalize(section.name))/*, "toggle"*/); + TextButton button = new TextButton(bundle.get("section." + section.name + ".name", Strings.capitalize(section.name))); if(section.equals(this.section)) button.toggle(); @@ -115,6 +116,7 @@ public class KeybindDialog extends Dialog{ } }).disabled(sectionControls.get(section, 0) + 1 >= devices.size).size(40); + //no alternate devices until further notice //table.add(stable).colspan(4).row(); table.add().height(10); @@ -126,6 +128,7 @@ public class KeybindDialog extends Dialog{ table.row(); String lastCategory = null; + var tstyle = Styles.defaultt; for(KeyBind keybind : keybinds.getKeybinds()){ if(lastCategory != keybind.category() && keybind.category() != null){ @@ -148,7 +151,7 @@ public class KeybindDialog extends Dialog{ table.add(axt).left().minWidth(90).padRight(20); } - table.button(bundle.get("settings.rebind", "Rebind"), () -> { + table.button("@settings.rebind", tstyle, () -> { rebindAxis = true; rebindMin = true; openDialog(section, keybind); @@ -159,13 +162,13 @@ public class KeybindDialog extends Dialog{ table.add(keybinds.get(section, keybind).key.toString(), style.keyColor).left().minWidth(90).padRight(20); - table.button(bundle.get("settings.rebind", "Rebind"), () -> { + table.button("@settings.rebind", tstyle, () -> { rebindAxis = false; rebindMin = false; openDialog(section, keybind); }).width(130f); } - table.button(bundle.get("settings.resetKey", "Reset"), () -> { + table.button("@settings.resetKey", tstyle, () -> { keybinds.resetToDefault(section, keybind); setup(); }).width(130f); @@ -174,7 +177,7 @@ public class KeybindDialog extends Dialog{ table.visible(() -> this.section.equals(section)); - table.button(bundle.get("settings.reset", "Reset to Defaults"), () -> { + table.button("@settings.reset", () -> { keybinds.resetToDefaults(); setup(); }).colspan(4).padTop(4).fill(); diff --git a/core/src/mindustry/world/blocks/distribution/DuctRouter.java b/core/src/mindustry/world/blocks/distribution/DuctRouter.java index 69f90d52d4..c9f8cb0967 100644 --- a/core/src/mindustry/world/blocks/distribution/DuctRouter.java +++ b/core/src/mindustry/world/blocks/distribution/DuctRouter.java @@ -48,7 +48,7 @@ public class DuctRouter extends Block{ Draw.rect(topRegion, req.drawx(), req.drawy(), req.rotation * 90); } - public class DuctBuild extends Building{ + public class DuctRouterBuild extends Building{ public float progress; public @Nullable Item current; From 01f759a99278c08f0876d03701fe28d367ee7cff Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 8 Aug 2021 20:42:48 -0400 Subject: [PATCH 118/130] Fixed #5722 --- core/src/mindustry/game/SectorInfo.java | 2 + core/src/mindustry/game/Universe.java | 51 ++++++++++++------- .../mindustry/ui/dialogs/DatabaseDialog.java | 2 +- .../src/mindustry/ui/dialogs/FileChooser.java | 1 + 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index 45af10f817..80859f48bc 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -78,6 +78,8 @@ public class SectorInfo{ public int waveVersion = -1; /** Whether this sector was indicated to the player or not. */ public boolean shown = false; + /** Temporary seq for last imported items. Do not use. */ + public transient ItemSeq lastImported = new ItemSeq(); /** Special variables for simulation. */ public float sumHealth, sumRps, sumDps, waveHealthBase, waveHealthSlope, waveDpsBase, waveDpsSlope, bossHealth, bossDps, curEnemyHealth, curEnemyDps; diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java index a9215f70d0..8d563f9957 100644 --- a/core/src/mindustry/game/Universe.java +++ b/core/src/mindustry/game/Universe.java @@ -147,8 +147,35 @@ public class Universe{ //update relevant sectors for(Planet planet : content.planets()){ + + //first pass: clear import stats for(Sector sector : planet.sectors){ - if(sector.hasSave() && sector.hasBase()){ + if(sector.hasBase() && !sector.isBeingPlayed()){ + sector.info.lastImported.clear(); + } + } + + //second pass: update export & import statistics + for(Sector sector : planet.sectors){ + if(sector.hasBase() && !sector.isBeingPlayed()){ + + //export to another sector + if(sector.info.destination != null){ + Sector to = sector.info.destination; + if(to.hasBase()){ + ItemSeq items = new ItemSeq(); + //calculated exported items to this sector + sector.info.export.each((item, stat) -> items.add(item, (int)(stat.mean * newSecondsPassed * sector.getProductionScale()))); + to.addItems(items); + to.info.lastImported.add(items); + } + } + } + } + + //third pass: everything else + for(Sector sector : planet.sectors){ + if(sector.hasBase()){ //if it is being attacked, capture time is 0; otherwise, increment the timer if(sector.isAttacked()){ @@ -198,26 +225,16 @@ public class Universe{ float scl = sector.getProductionScale(); - //export to another sector - if(sector.info.destination != null){ - Sector to = sector.info.destination; - if(to.hasBase()){ - ItemSeq items = new ItemSeq(); - //calculated exported items to this sector - sector.info.export.each((item, stat) -> items.add(item, (int)(stat.mean * newSecondsPassed * scl))); - to.addItems(items); - } - } + //add production, making sure that it's capped + sector.info.production.each((item, stat) -> sector.info.items.add(item, Math.min((int)(stat.mean * newSecondsPassed * scl), sector.info.storageCapacity - sector.info.items.get(item)))); - sector.info.export.each((item, amount) -> { - if(sector.info.items.get(item) <= 0 && sector.info.production.get(item, ExportStat::new).mean < 0){ - //disable export when production is negative. - sector.info.export.get(item).mean = 0f; + sector.info.export.each((item, stat) -> { + if(sector.info.items.get(item) <= 0 && sector.info.production.get(item, ExportStat::new).mean < 0 && stat.mean > 0){ + //cap export by import when production is negative. + stat.mean = Math.min(sector.info.lastImported.get(item) / (float)newSecondsPassed, stat.mean); } }); - //add production, making sure that it's capped - sector.info.production.each((item, stat) -> sector.info.items.add(item, Math.min((int)(stat.mean * newSecondsPassed * scl), sector.info.storageCapacity - sector.info.items.get(item)))); //prevent negative values with unloaders sector.info.items.checkNegative(); diff --git a/core/src/mindustry/ui/dialogs/DatabaseDialog.java b/core/src/mindustry/ui/dialogs/DatabaseDialog.java index 45980bdf00..ede404aa9a 100644 --- a/core/src/mindustry/ui/dialogs/DatabaseDialog.java +++ b/core/src/mindustry/ui/dialogs/DatabaseDialog.java @@ -52,7 +52,7 @@ public class DatabaseDialog extends BaseDialog{ table.table(list -> { list.left(); - int cols = Mathf.clamp((Core.graphics.getWidth() - 30) / (32 + 10), 1, 18); + int cols = (int)Mathf.clamp((Core.graphics.getWidth() - Scl.scl(30)) / Scl.scl(32 + 10), 1, 22); int count = 0; for(int i = 0; i < array.size; i++){ diff --git a/core/src/mindustry/ui/dialogs/FileChooser.java b/core/src/mindustry/ui/dialogs/FileChooser.java index 6ece055569..9259130d5c 100644 --- a/core/src/mindustry/ui/dialogs/FileChooser.java +++ b/core/src/mindustry/ui/dialogs/FileChooser.java @@ -39,6 +39,7 @@ public class FileChooser extends BaseDialog{ if(!lastDirectory.exists()){ lastDirectory = homeDirectory; + directory = lastDirectory; } onResize(() -> { From 5b27f4786d048bead5aed3a4464666d5bce080f3 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 9 Aug 2021 09:37:45 -0400 Subject: [PATCH 119/130] ItemBuffer struct --- core/src/mindustry/world/ItemBuffer.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/world/ItemBuffer.java b/core/src/mindustry/world/ItemBuffer.java index e9001ac534..d91da022ce 100644 --- a/core/src/mindustry/world/ItemBuffer.java +++ b/core/src/mindustry/world/ItemBuffer.java @@ -2,6 +2,8 @@ package mindustry.world; import arc.util.*; import arc.util.io.*; +import mindustry.annotations.Annotations.*; +import mindustry.gen.*; import mindustry.type.*; import static mindustry.Vars.*; @@ -20,7 +22,7 @@ public class ItemBuffer{ public void accept(Item item, short data){ //if(!accepts()) return; - buffer[index++] = Pack.longInt(Float.floatToIntBits(Time.time), Pack.shortInt(item.id, data)); + buffer[index++] = TimeItem.get(data, item.id, Time.time); } public void accept(Item item){ @@ -30,10 +32,10 @@ public class ItemBuffer{ public Item poll(float speed){ if(index > 0){ long l = buffer[0]; - float time = Float.intBitsToFloat(Pack.leftInt(l)); + float time = TimeItem.time(l); if(Time.time >= time + speed || Time.time < time){ - return content.item(Pack.leftShort(Pack.rightInt(l))); + return content.item(TimeItem.item(l)); } } return null; @@ -63,4 +65,11 @@ public class ItemBuffer{ } index = Math.min(index, length - 1); } + + @Struct + class TimeItemStruct{ + short data; + short item; + float time; + } } From 42486cd784b1c416b52fe780f1f357510a5b3a9f Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 9 Aug 2021 09:59:49 -0400 Subject: [PATCH 120/130] Fixed export/import lines curving through planet --- core/src/mindustry/graphics/g3d/PlanetRenderer.java | 4 +++- core/src/mindustry/ui/dialogs/PlanetDialog.java | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/graphics/g3d/PlanetRenderer.java b/core/src/mindustry/graphics/g3d/PlanetRenderer.java index 37c38e3833..14a2560fdd 100644 --- a/core/src/mindustry/graphics/g3d/PlanetRenderer.java +++ b/core/src/mindustry/graphics/g3d/PlanetRenderer.java @@ -215,8 +215,10 @@ public class PlanetRenderer implements Disposable{ } public void drawArc(Planet planet, Vec3 a, Vec3 b, Color from, Color to, float length, float timeScale, int pointCount){ + float dot = 1f - (Tmp.v32.set(a).nor().dot(Tmp.v33.set(b).nor()) + 1f)/2f; + Vec3 avg = Tmp.v31.set(b).add(a).scl(0.5f); - avg.setLength(planet.radius*(1f+length)); + avg.setLength(planet.radius*(1f+length) + dot * 1.3f); points.clear(); points.addAll(Tmp.v33.set(b).setLength(outlineRad), Tmp.v31, Tmp.v34.set(a).setLength(outlineRad)); diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 851ecd52df..a41428d6fc 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -385,11 +385,11 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ if(selected != null && selected != sec && selected.hasBase()){ //imports if(sec.info.getRealDestination() == selected && sec.info.anyExports()){ - planets.drawArc(planet, sec.tile.v, selected.tile.v, Color.gray.write(Tmp.c2).a(selectAlpha), Pal.accent, 0.4f, 90f, 25); + planets.drawArc(planet, sec.tile.v, selected.tile.v, Color.gray.write(Tmp.c2).a(selectAlpha), Pal.accent.write(Tmp.c3).a(selectAlpha), 0.4f, 90f, 25); } //exports if(selected.info.getRealDestination() == sec && selected.info.anyExports()){ - planets.drawArc(planet, selected.tile.v, sec.tile.v, Pal.place.write(Tmp.c2).a(selectAlpha), Pal.accent, 0.4f, 90f, 25); + planets.drawArc(planet, selected.tile.v, sec.tile.v, Pal.place.write(Tmp.c2).a(selectAlpha), Pal.accent.write(Tmp.c3).a(selectAlpha), 0.4f, 90f, 25); } } } From c60f6d155fe63e1a6340069c8a72bd72e0ca3d96 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 9 Aug 2021 11:41:39 -0400 Subject: [PATCH 121/130] Fixed #5725 --- core/src/mindustry/entities/Puddles.java | 2 +- core/src/mindustry/entities/comp/PuddleComp.java | 16 +++++++++++++--- .../mindustry/graphics/g3d/PlanetRenderer.java | 3 ++- core/src/mindustry/io/SaveVersion.java | 3 ++- .../mindustry/world/blocks/production/Pump.java | 2 +- .../mindustry/world/modules/LiquidModule.java | 5 +++-- gradle.properties | 2 +- 7 files changed, 23 insertions(+), 10 deletions(-) diff --git a/core/src/mindustry/entities/Puddles.java b/core/src/mindustry/entities/Puddles.java index cf398dc1f6..8422329c6c 100644 --- a/core/src/mindustry/entities/Puddles.java +++ b/core/src/mindustry/entities/Puddles.java @@ -54,8 +54,8 @@ public class Puddles{ puddle.liquid = liquid; puddle.amount = amount; puddle.set((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); - puddle.add(); map.put(tile.pos(), puddle); + puddle.add(); }else if(p.liquid == liquid){ p.accepting = Math.max(amount, p.accepting); diff --git a/core/src/mindustry/entities/comp/PuddleComp.java b/core/src/mindustry/entities/comp/PuddleComp.java index 63b3f25f6a..38df428c41 100644 --- a/core/src/mindustry/entities/comp/PuddleComp.java +++ b/core/src/mindustry/entities/comp/PuddleComp.java @@ -41,6 +41,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ @Import int id; @Import float x, y; + transient private boolean mismatch = false; transient float accepting, updateTime, lastRipple = Time.time + Mathf.random(40f); float amount; Tile tile; @@ -73,8 +74,15 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ amount = Mathf.clamp(amount, 0, maxLiquid); - if(amount <= 0f || Puddles.get(tile) != self()){ + if(amount <= 0f){ remove(); + return; + } + + if(Puddles.get(tile) != self()){ + mismatch = true; + remove(); + return; } //effects-only code @@ -83,7 +91,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ Units.nearby(rect.setSize(Mathf.clamp(amount / (maxLiquid / 1.5f)) * 10f).setCenter(x, y), unitCons); - if(liquid.temperature > 0.7f && (tile.build != null) && Mathf.chance(0.5)){ + if(liquid.temperature > 0.7f && tile.build != null && Mathf.chance(0.5)){ Fires.create(tile); } @@ -126,7 +134,9 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ @Override public void remove(){ - Puddles.remove(tile); + if(!mismatch){ + Puddles.remove(tile); + } } @Override diff --git a/core/src/mindustry/graphics/g3d/PlanetRenderer.java b/core/src/mindustry/graphics/g3d/PlanetRenderer.java index 14a2560fdd..64b3dd7c39 100644 --- a/core/src/mindustry/graphics/g3d/PlanetRenderer.java +++ b/core/src/mindustry/graphics/g3d/PlanetRenderer.java @@ -215,10 +215,11 @@ public class PlanetRenderer implements Disposable{ } public void drawArc(Planet planet, Vec3 a, Vec3 b, Color from, Color to, float length, float timeScale, int pointCount){ + //increase curve height when on opposite side of planet, so it doesn't tunnel through float dot = 1f - (Tmp.v32.set(a).nor().dot(Tmp.v33.set(b).nor()) + 1f)/2f; Vec3 avg = Tmp.v31.set(b).add(a).scl(0.5f); - avg.setLength(planet.radius*(1f+length) + dot * 1.3f); + avg.setLength(planet.radius*(1f+length) + dot * 1.35f); points.clear(); points.addAll(Tmp.v33.set(b).setLength(outlineRad), Tmp.v31, Tmp.v34.set(a).setLength(outlineRad)); diff --git a/core/src/mindustry/io/SaveVersion.java b/core/src/mindustry/io/SaveVersion.java index 904591f268..527742d836 100644 --- a/core/src/mindustry/io/SaveVersion.java +++ b/core/src/mindustry/io/SaveVersion.java @@ -408,7 +408,8 @@ public abstract class SaveVersion extends SaveFileReader{ for(int j = 0; j < total; j++){ String name = stream.readUTF(); - map[type.ordinal()][j] = content.getByName(type, fallback.get(name, name)); + //fallback only for blocks + map[type.ordinal()][j] = content.getByName(type, type == ContentType.block ? fallback.get(name, name) : name); } } diff --git a/core/src/mindustry/world/blocks/production/Pump.java b/core/src/mindustry/world/blocks/production/Pump.java index fd150ba38a..de524f72f6 100644 --- a/core/src/mindustry/world/blocks/production/Pump.java +++ b/core/src/mindustry/world/blocks/production/Pump.java @@ -87,7 +87,7 @@ public class Pump extends LiquidBlock{ public void draw(){ Draw.rect(name, x, y); - Drawf.liquid(liquidRegion, x, y, liquids.total() / liquidCapacity, liquids.current().color); + Drawf.liquid(liquidRegion, x, y, liquids.currentAmount() / liquidCapacity, liquids.current().color); } @Override diff --git a/core/src/mindustry/world/modules/LiquidModule.java b/core/src/mindustry/world/modules/LiquidModule.java index 5713129506..3f17a09940 100644 --- a/core/src/mindustry/world/modules/LiquidModule.java +++ b/core/src/mindustry/world/modules/LiquidModule.java @@ -143,11 +143,12 @@ public class LiquidModule extends BlockModule{ int count = legacy ? read.ub() : read.s(); for(int j = 0; j < count; j++){ - int liquidid = legacy ? read.ub() : read.s(); + Liquid liq = content.liquid(legacy ? read.ub() : read.s()); + int liquidid = liq.id; float amount = read.f(); liquids[liquidid] = amount; if(amount > 0){ - current = content.liquid(liquidid); + current = liq; } this.total += amount; } diff --git a/gradle.properties b/gradle.properties index dc2ce3354d..3c125e34d9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=28f7dea17ba559a28e79111adc93cf0496ced031 +archash=40c21b302ccc1e74f4c2a37f937c88acaec99254 From 7e047ef7262be2ffa0ef257d88cc4557521f1134 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 9 Aug 2021 12:13:07 -0400 Subject: [PATCH 122/130] Stone craters name fix --- core/assets/bundles/bundle.properties | 2 +- core/assets/bundles/bundle_be.properties | 2 +- core/assets/bundles/bundle_bg.properties | 2 +- core/assets/bundles/bundle_cs.properties | 2 +- core/assets/bundles/bundle_da.properties | 2 +- core/assets/bundles/bundle_de.properties | 2 +- core/assets/bundles/bundle_es.properties | 2 +- core/assets/bundles/bundle_et.properties | 2 +- core/assets/bundles/bundle_eu.properties | 2 +- core/assets/bundles/bundle_fi.properties | 2 +- core/assets/bundles/bundle_fil.properties | 2 +- core/assets/bundles/bundle_fr.properties | 2 +- core/assets/bundles/bundle_hu.properties | 2 +- core/assets/bundles/bundle_in_ID.properties | 2 +- core/assets/bundles/bundle_it.properties | 2 +- core/assets/bundles/bundle_ja.properties | 2 +- core/assets/bundles/bundle_ko.properties | 2 +- core/assets/bundles/bundle_lt.properties | 2 +- core/assets/bundles/bundle_nl.properties | 2 +- core/assets/bundles/bundle_nl_BE.properties | 2 +- core/assets/bundles/bundle_pl.properties | 2 +- core/assets/bundles/bundle_pt_BR.properties | 2 +- core/assets/bundles/bundle_pt_PT.properties | 2 +- core/assets/bundles/bundle_ro.properties | 2 +- core/assets/bundles/bundle_ru.properties | 2 +- core/assets/bundles/bundle_sv.properties | 2 +- core/assets/bundles/bundle_th.properties | 2 +- core/assets/bundles/bundle_tk.properties | 2 +- core/assets/bundles/bundle_tr.properties | 2 +- core/assets/bundles/bundle_uk_UA.properties | 2 +- core/assets/bundles/bundle_vi.properties | 2 +- core/assets/bundles/bundle_zh_CN.properties | 2 +- core/assets/bundles/bundle_zh_TW.properties | 2 +- 33 files changed, 33 insertions(+), 33 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 51fbf226db..341e7f785d 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1150,7 +1150,7 @@ block.sand.name = Sand block.darksand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.stone-craters.name = Craters +block.crater-stone.name = Craters block.sand-water.name = Sand Water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_be.properties b/core/assets/bundles/bundle_be.properties index 7d88d0d0db..5124f7c3c7 100644 --- a/core/assets/bundles/bundle_be.properties +++ b/core/assets/bundles/bundle_be.properties @@ -1001,7 +1001,7 @@ block.sand.name = Пясок block.darksand.name = Тёмны пясок block.ice.name = Лёд block.snow.name = Снег -block.stone-craters.name = Кратэры +block.crater-stone.name = Кратэры block.sand-water.name = Пясок з вадой block.darksand-water.name = Тёмный пясок з вадой block.char.name = Выпаленая зямля diff --git a/core/assets/bundles/bundle_bg.properties b/core/assets/bundles/bundle_bg.properties index 37650b0b56..d9c9dbc9f9 100644 --- a/core/assets/bundles/bundle_bg.properties +++ b/core/assets/bundles/bundle_bg.properties @@ -1115,7 +1115,7 @@ block.sand.name = Пясък block.darksand.name = Тъмен Пясък block.ice.name = Лед block.snow.name = Сняг -block.stone-craters.name = Кратери +block.crater-stone.name = Кратери block.sand-water.name = Пясък - Вода block.darksand-water.name = Тъмен Пясък - Вода block.char.name = Овъглен Камък diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties index 547a068c68..e79b28b90f 100644 --- a/core/assets/bundles/bundle_cs.properties +++ b/core/assets/bundles/bundle_cs.properties @@ -1064,7 +1064,7 @@ block.sand.name = Písek block.darksand.name = Černý písek block.ice.name = Led block.snow.name = Sníh -block.stone-craters.name = Krátery +block.crater-stone.name = Krátery block.sand-water.name = Voda s pískem block.darksand-water.name = Voda s černým pískem block.char.name = Dřevěné uhlí diff --git a/core/assets/bundles/bundle_da.properties b/core/assets/bundles/bundle_da.properties index 00faecd003..e18a09d242 100644 --- a/core/assets/bundles/bundle_da.properties +++ b/core/assets/bundles/bundle_da.properties @@ -1001,7 +1001,7 @@ block.sand.name = Sand block.darksand.name = Mørkt Sand block.ice.name = Is block.snow.name = Sne -block.stone-craters.name = Kratere +block.crater-stone.name = Kratere block.sand-water.name = Sandet Lavvande block.darksand-water.name = Mørkt Sandet Lavvande block.char.name = Trækul diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index 0f99a93990..55f13ee6a1 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -1148,7 +1148,7 @@ block.sand.name = Sand block.darksand.name = Dunkler Sand block.ice.name = Eis block.snow.name = Schnee -block.stone-craters.name = Krater +block.crater-stone.name = Krater block.sand-water.name = Sandiges Wasser block.darksand-water.name = Dunkles sandiges Wasser block.char.name = Holzkohle diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index 961bce09f4..54bc3a9fb1 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -1144,7 +1144,7 @@ block.sand.name = Arena block.darksand.name = Arena oscura block.ice.name = Hielo block.snow.name = Nieve -block.stone-craters.name = Cráter +block.crater-stone.name = Cráter block.sand-water.name = Agua con arena block.darksand-water.name = Agua con arena oscura block.char.name = Cenizas diff --git a/core/assets/bundles/bundle_et.properties b/core/assets/bundles/bundle_et.properties index 61f7ba36d6..1cc5726bac 100644 --- a/core/assets/bundles/bundle_et.properties +++ b/core/assets/bundles/bundle_et.properties @@ -1001,7 +1001,7 @@ block.sand.name = Liiv block.darksand.name = Tume liiv block.ice.name = Jää block.snow.name = Lumi -block.stone-craters.name = Kraatrid +block.crater-stone.name = Kraatrid block.sand-water.name = Vesi liival block.darksand-water.name = Vesi tumedal liival block.char.name = Puusüsi diff --git a/core/assets/bundles/bundle_eu.properties b/core/assets/bundles/bundle_eu.properties index bc43060854..dbc1825e7c 100644 --- a/core/assets/bundles/bundle_eu.properties +++ b/core/assets/bundles/bundle_eu.properties @@ -1001,7 +1001,7 @@ block.sand.name = Hondarra block.darksand.name = Hondar iluna block.ice.name = Izotza block.snow.name = Elurra -block.stone-craters.name = Kraterrak +block.crater-stone.name = Kraterrak block.sand-water.name = Hondar ura block.darksand-water.name = Hondar ilun ura block.char.name = Kokea diff --git a/core/assets/bundles/bundle_fi.properties b/core/assets/bundles/bundle_fi.properties index da3f1075f9..71a42b0512 100644 --- a/core/assets/bundles/bundle_fi.properties +++ b/core/assets/bundles/bundle_fi.properties @@ -1001,7 +1001,7 @@ block.sand.name = Hiekka block.darksand.name = Tumma hiekka block.ice.name = Jää block.snow.name = Lumi -block.stone-craters.name = Kraatterit +block.crater-stone.name = Kraatterit block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_fil.properties b/core/assets/bundles/bundle_fil.properties index db99a05c9c..7581748a30 100644 --- a/core/assets/bundles/bundle_fil.properties +++ b/core/assets/bundles/bundle_fil.properties @@ -1001,7 +1001,7 @@ block.sand.name = Sand block.darksand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.stone-craters.name = Craters +block.crater-stone.name = Craters block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index 5bee2d80d3..2fb0b33c5c 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -1158,7 +1158,7 @@ block.sand.name = Sable block.darksand.name = Sable sombre block.ice.name = Glace block.snow.name = Neige -block.stone-craters.name = Cratères +block.crater-stone.name = Cratères block.sand-water.name = Eau avec fond de Sable block.darksand-water.name = Eau avec fond de Sable sombre block.char.name = Cendres diff --git a/core/assets/bundles/bundle_hu.properties b/core/assets/bundles/bundle_hu.properties index 9d60e88be3..c7cee9bc4e 100644 --- a/core/assets/bundles/bundle_hu.properties +++ b/core/assets/bundles/bundle_hu.properties @@ -1085,7 +1085,7 @@ block.sand.name = Sand block.darksand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.stone-craters.name = Craters +block.crater-stone.name = Craters block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_in_ID.properties b/core/assets/bundles/bundle_in_ID.properties index d67c0ad2c6..9252a94e7f 100644 --- a/core/assets/bundles/bundle_in_ID.properties +++ b/core/assets/bundles/bundle_in_ID.properties @@ -1143,7 +1143,7 @@ block.sand.name = Pasir block.darksand.name = Pasir Hitam block.ice.name = Es block.snow.name = Salju -block.stone-craters.name = Kawah +block.crater-stone.name = Kawah block.sand-water.name = Air Pasir block.darksand-water.name = Air Pasir Hitam block.char.name = Bara diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties index 49cc18e758..f9ba38c603 100644 --- a/core/assets/bundles/bundle_it.properties +++ b/core/assets/bundles/bundle_it.properties @@ -1065,7 +1065,7 @@ block.sand.name = Sabbia block.darksand.name = Sabbia Scura block.ice.name = Ghiaccio block.snow.name = Neve -block.stone-craters.name = Crateri +block.crater-stone.name = Crateri block.sand-water.name = Acqua Sabbiosa block.darksand-water.name = Acqua Sabbiosa Scura block.char.name = Carbone diff --git a/core/assets/bundles/bundle_ja.properties b/core/assets/bundles/bundle_ja.properties index fad527ac75..c6b5b42c56 100644 --- a/core/assets/bundles/bundle_ja.properties +++ b/core/assets/bundles/bundle_ja.properties @@ -1078,7 +1078,7 @@ block.sand.name = 砂 block.darksand.name = 黒い砂 block.ice.name = 氷 block.snow.name = 雪 -block.stone-craters.name = クレーター +block.crater-stone.name = クレーター block.sand-water.name = 濁った水 block.darksand-water.name = 黒い砂で濁った水 block.char.name = 焦げ跡 diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index e1f92d697b..89dbb2eaa5 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -1147,7 +1147,7 @@ block.sand.name = 모래 block.darksand.name = 검은 모래 block.ice.name = 얼음 block.snow.name = 눈 -block.stone-craters.name = 구덩이 +block.crater-stone.name = 구덩이 block.sand-water.name = 젖은 모래 block.darksand-water.name = 젖은 검은 모래 block.char.name = 숯 diff --git a/core/assets/bundles/bundle_lt.properties b/core/assets/bundles/bundle_lt.properties index a7bb0f5808..4add695c67 100644 --- a/core/assets/bundles/bundle_lt.properties +++ b/core/assets/bundles/bundle_lt.properties @@ -1001,7 +1001,7 @@ block.sand.name = Smėlis block.darksand.name = Tamsus Smėlis block.ice.name = Ledas block.snow.name = Sniegas -block.stone-craters.name = Krateriai +block.crater-stone.name = Krateriai block.sand-water.name = Smėlio vanduo block.darksand-water.name = Tamsaus Smėlio Vanduo block.char.name = Char diff --git a/core/assets/bundles/bundle_nl.properties b/core/assets/bundles/bundle_nl.properties index 8559cb7185..b9de625fe1 100644 --- a/core/assets/bundles/bundle_nl.properties +++ b/core/assets/bundles/bundle_nl.properties @@ -1001,7 +1001,7 @@ block.sand.name = Donker Zand block.darksand.name = Donker Zand block.ice.name = Ijs block.snow.name = Sneeuw -block.stone-craters.name = Krarters +block.crater-stone.name = Krarters block.sand-water.name = Zand water block.darksand-water.name = Donker Zand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_nl_BE.properties b/core/assets/bundles/bundle_nl_BE.properties index 4fb7a210e4..ce3afc9610 100644 --- a/core/assets/bundles/bundle_nl_BE.properties +++ b/core/assets/bundles/bundle_nl_BE.properties @@ -1001,7 +1001,7 @@ block.sand.name = Sand block.darksand.name = Dark Sand block.ice.name = Ice block.snow.name = Snow -block.stone-craters.name = Craters +block.crater-stone.name = Craters block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index 1dc7305538..38d2bfbcbe 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -1131,7 +1131,7 @@ block.sand.name = Piasek block.darksand.name = Czarny piasek block.ice.name = Lód block.snow.name = Śnieg -block.stone-craters.name = Kratery +block.crater-stone.name = Kratery block.sand-water.name = Woda z Piaskiem block.darksand-water.name = Woda z Ciemnym Piaskiem block.char.name = Popiół diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties index 4d9b6fc370..ee276a99a0 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -1114,7 +1114,7 @@ block.sand.name = Areia block.darksand.name = Areia escura block.ice.name = Gelo block.snow.name = Neve -block.stone-craters.name = Crateras +block.crater-stone.name = Crateras block.sand-water.name = Água sobre areia block.darksand-water.name = Água sobre areia escura block.char.name = Cinzas diff --git a/core/assets/bundles/bundle_pt_PT.properties b/core/assets/bundles/bundle_pt_PT.properties index a0b0605696..a9894b0d6b 100644 --- a/core/assets/bundles/bundle_pt_PT.properties +++ b/core/assets/bundles/bundle_pt_PT.properties @@ -1001,7 +1001,7 @@ block.sand.name = Areia block.darksand.name = Areia escura block.ice.name = Gelo block.snow.name = Neve -block.stone-craters.name = Crateras +block.crater-stone.name = Crateras block.sand-water.name = Água sobre areia block.darksand-water.name = Água sobre areia escura block.char.name = Char diff --git a/core/assets/bundles/bundle_ro.properties b/core/assets/bundles/bundle_ro.properties index 8be6870cb5..529254eb2e 100644 --- a/core/assets/bundles/bundle_ro.properties +++ b/core/assets/bundles/bundle_ro.properties @@ -1148,7 +1148,7 @@ block.sand.name = Nisip block.darksand.name = Nisip Negru block.ice.name = Gheață block.snow.name = Zăpadă -block.stone-craters.name = Cratere +block.crater-stone.name = Cratere block.sand-water.name = Apă cu Nisip block.darksand-water.name = Apă cu Nisip Negru block.char.name = Turbă diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index c9035e8e59..d72304ef21 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -1143,7 +1143,7 @@ block.sand.name = Песок block.darksand.name = Тёмный песок block.ice.name = Лёд block.snow.name = Снег -block.stone-craters.name = Кратеры +block.crater-stone.name = Кратеры block.sand-water.name = Песок с водой block.darksand-water.name = Тёмный песок с водой block.char.name = Выжженная земля diff --git a/core/assets/bundles/bundle_sv.properties b/core/assets/bundles/bundle_sv.properties index 45b6ac8978..4a0ab8db0f 100644 --- a/core/assets/bundles/bundle_sv.properties +++ b/core/assets/bundles/bundle_sv.properties @@ -1001,7 +1001,7 @@ block.sand.name = Sand block.darksand.name = Mörk Sand block.ice.name = Is block.snow.name = Snö -block.stone-craters.name = Kratrar +block.crater-stone.name = Kratrar block.sand-water.name = Sandvatten block.darksand-water.name = Mörksandvatten block.char.name = Char diff --git a/core/assets/bundles/bundle_th.properties b/core/assets/bundles/bundle_th.properties index 6820bd2f71..4dca059487 100644 --- a/core/assets/bundles/bundle_th.properties +++ b/core/assets/bundles/bundle_th.properties @@ -1149,7 +1149,7 @@ block.sand.name = ทราย block.darksand.name = ทรายดำ block.ice.name = น้ำแข็ง block.snow.name = หิมะ -block.stone-craters.name = หลุมอุกกาบาต +block.crater-stone.name = หลุมอุกกาบาต block.sand-water.name = น้ำบนทราย block.darksand-water.name = น้ำบนทรายดำ block.char.name = ถ่าน diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties index b91132cc5d..6c573d95d1 100644 --- a/core/assets/bundles/bundle_tk.properties +++ b/core/assets/bundles/bundle_tk.properties @@ -1001,7 +1001,7 @@ block.sand.name = kum block.darksand.name = Dark Sand block.ice.name = buz block.snow.name = kar -block.stone-craters.name = Craters +block.crater-stone.name = Craters block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 6a243b035f..9f32da7999 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -1149,7 +1149,7 @@ block.sand.name = Kum block.darksand.name = Kara Kum block.ice.name = Buz block.snow.name = Kar -block.stone-craters.name = Krater +block.crater-stone.name = Krater block.sand-water.name = Kumlu Su block.darksand-water.name = Kara Kumlu Su block.char.name = Kömür diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index a41cafc7d5..09e3df9cd8 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -1102,7 +1102,7 @@ block.sand.name = Пісок block.darksand.name = Темний пісок block.ice.name = Лід block.snow.name = Сніг -block.stone-craters.name = Кратери +block.crater-stone.name = Кратери block.sand-water.name = Пісок із водою block.darksand-water.name = Темний пісок із водою block.char.name = Випалена земля diff --git a/core/assets/bundles/bundle_vi.properties b/core/assets/bundles/bundle_vi.properties index 52fc53ef3b..067d3703d9 100644 --- a/core/assets/bundles/bundle_vi.properties +++ b/core/assets/bundles/bundle_vi.properties @@ -1143,7 +1143,7 @@ block.sand.name = Cát block.darksand.name = Cát đen block.ice.name = Băng block.snow.name = Tuyết -block.stone-craters.name = Miệng núi lửa +block.crater-stone.name = Miệng núi lửa block.sand-water.name = Nước cát block.darksand-water.name = Nước cát đen block.char.name = Char diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties index e3f68dc7d1..e306743ea4 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -1148,7 +1148,7 @@ block.sand.name = 沙子 block.darksand.name = 黑沙 block.ice.name = 冰 block.snow.name = 雪 -block.stone-craters.name = 陨石坑 +block.crater-stone.name = 陨石坑 block.sand-water.name = 沙 水 block.darksand-water.name = 黑沙 水 block.char.name = 焦土 diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index 1863f8a34a..de77a25028 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -1138,7 +1138,7 @@ block.sand.name = 沙 block.darksand.name = 黑沙 block.ice.name = 冰 block.snow.name = 雪 -block.stone-craters.name = 彈坑 +block.crater-stone.name = 彈坑 block.sand-water.name = 沙水 block.darksand-water.name = 黑沙水 block.char.name = 燒焦 From 353433a3838c68ef959e310468c9128a6ecd4493 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 9 Aug 2021 14:19:34 -0400 Subject: [PATCH 123/130] Fine, I'll do it myself (#5717) --- core/src/mindustry/ai/types/FlyingAI.java | 9 ++++++++- .../entities/abilities/MoveLightningAbility.java | 8 +++++++- gradle.properties | 4 +++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/ai/types/FlyingAI.java b/core/src/mindustry/ai/types/FlyingAI.java index 0f2cb8c5e8..db5ae84dab 100644 --- a/core/src/mindustry/ai/types/FlyingAI.java +++ b/core/src/mindustry/ai/types/FlyingAI.java @@ -41,6 +41,12 @@ public class FlyingAI extends AIController{ @Override protected Teamc findMainTarget(float x, float y, float range, boolean air, boolean ground){ + var core = targetFlag(x, y, BlockFlag.core, true); + + if(core != null && Mathf.within(x, y, core.getX(), core.getY(), range)){ + return core; + } + for(var flag : unit.team.isAI() ? unit.type.targetFlags : unit.type.playerTargetFlags){ if(flag == null){ Teamc result = target(x, y, range, air, ground); @@ -50,7 +56,8 @@ public class FlyingAI extends AIController{ if(result != null) return result; } } - return targetFlag(x, y, BlockFlag.core, true); + + return core; } protected void attack(float circleLength){ diff --git a/core/src/mindustry/entities/abilities/MoveLightningAbility.java b/core/src/mindustry/entities/abilities/MoveLightningAbility.java index 4cc62b7172..0a56d3bd15 100644 --- a/core/src/mindustry/entities/abilities/MoveLightningAbility.java +++ b/core/src/mindustry/entities/abilities/MoveLightningAbility.java @@ -24,6 +24,8 @@ public class MoveLightningAbility extends Ability{ public Color color = Color.valueOf("a9d8ff"); /** Shifts where the lightning spawns along the Y axis */ public float offset = 0f; + /** Offset along the X axis. */ + public float width = 0f; /** Jittering heat sprite like the shield on v5 Javelin */ public String heatRegion = "error"; /** Bullet type that is fired. Can be null */ @@ -33,6 +35,8 @@ public class MoveLightningAbility extends Ability{ public Effect shootEffect = Fx.sparkShoot; public Sound shootSound = Sounds.spark; + + protected float side = 1f; MoveLightningAbility(){} @@ -61,7 +65,7 @@ public class MoveLightningAbility extends Ability{ public void update(Unit unit){ float scl = Mathf.clamp((unit.vel().len() - minSpeed) / (maxSpeed - minSpeed)); if(Mathf.chance(Time.delta * chance * scl)){ - float x = unit.x + Angles.trnsx(unit.rotation, offset, 0), y = unit.y + Angles.trnsy(unit.rotation, offset, 0); + float x = unit.x + Angles.trnsx(unit.rotation, offset, width * side), y = unit.y + Angles.trnsy(unit.rotation, offset, width * side); shootEffect.at(x, y, unit.rotation, color); shootSound.at(unit); @@ -73,6 +77,8 @@ public class MoveLightningAbility extends Ability{ if(bullet != null){ bullet.create(unit, unit.team, x, y, unit.rotation + bulletAngle + Mathf.range(bulletSpread)); } + + side *= -1f; } } diff --git a/gradle.properties b/gradle.properties index 3c125e34d9..d0b05818da 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,6 @@ kapt.include.compile.classpath=false kotlin.stdlib.default.dependency=false #needed for android compilation android.useAndroidX=true -archash=40c21b302ccc1e74f4c2a37f937c88acaec99254 +#used for slow jitpack builds; TODO see if this actually works +http.socketTimeout=80000 +http.connectionTimeout=80000archash=40c21b302ccc1e74f4c2a37f937c88acaec99254 From ed71777a17465f36b71d84e0ea07e5f3841877c5 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 9 Aug 2021 14:27:42 -0400 Subject: [PATCH 124/130] . --- gradle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/gradle.properties b/gradle.properties index d0b05818da..eae04d207f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,3 +11,4 @@ android.useAndroidX=true #used for slow jitpack builds; TODO see if this actually works http.socketTimeout=80000 http.connectionTimeout=80000archash=40c21b302ccc1e74f4c2a37f937c88acaec99254 +archash=40c21b302ccc1e74f4c2a37f937c88acaec99254 From 9c1063c7ccf0b45ea555143a021c414e42f2a615 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 9 Aug 2021 16:53:49 -0400 Subject: [PATCH 125/130] Misc minor bugfixes --- core/assets/maps/extractionOutpost.msav | Bin 20024 -> 20196 bytes .../mindustry/entities/comp/BuildingComp.java | 3 ++- .../world/blocks/power/LightBlock.java | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/assets/maps/extractionOutpost.msav b/core/assets/maps/extractionOutpost.msav index 7ce6a6904ef7acbd790b88e8055f0dfc9dc11d54..288046fd926ca338cedc1bef297a41c810bc5df8 100644 GIT binary patch literal 20196 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%0DeOlJL_r6E&RO(&cHSG$g@9rMxmjW!^?Fc(dih z%*V(OM zp?>AIp4O*bO8VNL621JM92MLnrMy7W;*;U~?n@z@J96{f=d~#5_i0FOozb)DQ-YjI z$gJ1eFE;OLJK(J_(e_Gk;TFpb_LF`NQNj27US0JG@SBwtQdw%VdV=moNtN&iT=T=D zE^RShe>LmZo2ID#%98HOPgNv?&RV3b&C$@{+SE;497+KPr(a#&qr4({)pxd?D>Tn7X|nR`$=xg@WqsP~m`yCF*L-i^iJ>m9 za(#8R`ShPGzBFUESXFw^hD!Yhvga*NMIN8w{B_AS&OXhpdnA+A9G-Yt`>@&Eq`-T9 z%cdR;UZQ%>zJI0N_ibxc1eG|RS}wh}LQ6weAimLQrdQh1N0+8`uun8Q`)F$E($A4g zwr;t2)WN^?gkX`J6WhKW(H)&^q775zUrmBo++``Z$ia3b4Xq4u<+QWcEZ-H zyF{$MdXqw-vbRwBy)7O#(^B(YUG3KO=&p))K3}kXQJMf-edV>wp8bDjeQinqax+rr z`lVe@cf7N>HY4Eb<||vKEmE+oJvJ{YA}FLn*Hm13Yu4o5dD$B}H9m0uSYmZ-Q&FVu0Cqf6?OP>`OKu&EiZQM(_Omd zL_vthrM^PRoJA3JoR*8#+z3%ywUb#Mz3-_O_oGKbWslmwGOZh~5(v$PfA}@tn zqGekxb~RQmF>`U(uGP~;^A}AOyI*w6 z>-Bk)sbZ6-_16BBa_3u?6>##zOVJlsKeOm3Ht#j8i^!A=arHlJEu!(&X8G2oB3xZn zUu7J{>f-~sxU`C2J2%A1dM{icaJ%RD#PB@=!3p8#h29HCzO1?7cw*(X%D;yTHKokH zM5g#@ez@^$3RAY_q_XWIkM}OD=-wFRuz=^$!*eTk^k*#o+;!>LhZ?pE0f*9AmM#gK z$hD&A?$(KKyP`s#CN$anSRBPXWr0~{=Y&A9-yBZ@J2=gwXQ;|t@=`v$X~X|nCQn72PRIDzQT4(VSV6- zrX=m-R+&OyeD*A2d^|%d-0x<}XSU-S%RA>)R@mLHiQO1EedB^%g-nZNQq(eiE-gyx z>i%*nE4kgSzE1a8SkTk&rg=fV8Ddx1#JDsqF4*5UjC%Dbv*|)uUv%coeVPw_x4!## zW5WsA;0Ho0=d~IhwD!8<9qWHkd)B!vQ?gY{Gux7*3PYyqf9ATWlHt6@ooQWf=8W9- zm;a0#w|B^x|N3Zcnfj=~Y?+L?{rV-MAyYpWEQ}2GXWWkvZ$H}A6tJ}3CCT;-e}XXKf*rRApL_H|jlj{`NA zE$~>Sbf;oAOX}eov3`}P%BTXrxk{6tck6EW(7TSk%VfQlR-(0d$p)79uDQ2)jnWq{ z5MS@d%JKfWr$1-DV~MiF$~DJ&^^Tm-O*L2lyZXs>7X3a0_2&O9qJ}eTd2srpw3!aYryd!)rd$?!X3edcYdqzdV~*HQoojOgo@`EFR8~?pOgejb@8=b3 z_I^AY)SJ|`SJLrv*V#GmTW>5|KBbiVlhTCB#vHd<^F61&oWSewB#GU08Q-hAp6{C$ zZP`*iN9KUdwq(0G&(tkY1M`qo&`P;6*->I!|NL_U4 zQnuq?PMvSr(j4YyVjdK=b4kZJA;+dY3ua|3JS${(nqi&C0gh#lqcl78mMd&>Eb1@v zJGfu+bI+6?-#Je)R0za3#b!q_J$q>BY0|o^Jl( z7i_$H)e4rsR|D5FR)uzcoECa~d57x6#zwAF-R#pp+%aBPX

_C*Z+SoB91mPUvcC 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 literal 20024 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%0AyIp?>|kwS7scoOQk9)SYf0Yg;bXzL;|(Rk?ci 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 diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 9e7ffc8d79..5dc11a407e 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -160,7 +160,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } public final void readBase(Reads read){ - health = read.f(); + //cap health by block health in case of nerfs + health = Math.min(read.f(), block.health); byte rot = read.b(); team = Team.get(read.b()); diff --git a/core/src/mindustry/world/blocks/power/LightBlock.java b/core/src/mindustry/world/blocks/power/LightBlock.java index 16f109d626..2f1f05d606 100644 --- a/core/src/mindustry/world/blocks/power/LightBlock.java +++ b/core/src/mindustry/world/blocks/power/LightBlock.java @@ -35,7 +35,8 @@ public class LightBlock extends Block{ @Override public void init(){ - lightRadius = radius; + //double needed for some reason + lightRadius = radius*2f; emitLight = true; super.init(); } From 6246a1d39c481159659edc297f8527e56e731725 Mon Sep 17 00:00:00 2001 From: Matthew Peng <54301439+MEEPofFaith@users.noreply.github.com> Date: Mon, 9 Aug 2021 15:04:21 -0700 Subject: [PATCH 126/130] Option to make a unit not appear on the title screen. (#5728) --- core/src/mindustry/graphics/MenuRenderer.java | 2 +- core/src/mindustry/type/UnitType.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/graphics/MenuRenderer.java b/core/src/mindustry/graphics/MenuRenderer.java index 3bb562bde1..1cd431c7e8 100644 --- a/core/src/mindustry/graphics/MenuRenderer.java +++ b/core/src/mindustry/graphics/MenuRenderer.java @@ -29,7 +29,7 @@ public class MenuRenderer implements Disposable{ private float time = 0f; private float flyerRot = 45f; private int flyers = Mathf.chance(0.2) ? Mathf.random(35) : Mathf.random(15); - private UnitType flyerType = content.units().select(u -> u.hitSize <= 20f && u.flying && u.region.found()).random(); + private UnitType flyerType = content.units().select(u -> u.hitSize <= 20f && u.flying && u.onTitleScreen && u.region.found()).random(); public MenuRenderer(){ Time.mark(); diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 0640400182..0aa8f45175 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -42,6 +42,8 @@ public class UnitType extends UnlockableContent{ /** If true, the unit is always at elevation 1. */ public boolean flying; + /** If `flying` and this is true, the unit can appear on the title screen */ + public boolean onTitleScreen = true; /** Creates a new instance of this unit class. */ public Prov constructor; /** The default AI controller to assign on creation. */ From 6d517396b3816f5b685253f6effd1f34bcd845a8 Mon Sep 17 00:00:00 2001 From: buthed010203 Date: Mon, 9 Aug 2021 18:05:19 -0400 Subject: [PATCH 127/130] ??? (#5727) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index eae04d207f..2917c3abef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,5 +10,5 @@ kotlin.stdlib.default.dependency=false android.useAndroidX=true #used for slow jitpack builds; TODO see if this actually works http.socketTimeout=80000 -http.connectionTimeout=80000archash=40c21b302ccc1e74f4c2a37f937c88acaec99254 +http.connectionTimeout=80000 archash=40c21b302ccc1e74f4c2a37f937c88acaec99254 From 6c963a2de7be2057007c4f3a76eea7b5aac9e152 Mon Sep 17 00:00:00 2001 From: JrTRinny <85090668+JrTRinny@users.noreply.github.com> Date: Tue, 10 Aug 2021 20:38:46 +0700 Subject: [PATCH 128/130] comment fix (#5730) * there is no mech pads * factories --- core/src/mindustry/game/Rules.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java index 515995d79c..ad70638368 100644 --- a/core/src/mindustry/game/Rules.java +++ b/core/src/mindustry/game/Rules.java @@ -50,7 +50,7 @@ public class Rules{ public boolean unitAmmo = false; /** Whether cores add to unit limit */ public boolean unitCapVariable = true; - /** How fast unit pads build units. */ + /** How fast unit factories build units. */ public float unitBuildSpeedMultiplier = 1f; /** How much damage any other units deal. */ public float unitDamageMultiplier = 1f; From be38bba0e49ef025b456f21e02ab4611f63da706 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 10 Aug 2021 10:16:15 -0400 Subject: [PATCH 129/130] #5729 --- core/src/mindustry/content/Blocks.java | 4 ++-- core/src/mindustry/world/Block.java | 2 +- .../mindustry/world/blocks/payloads/PayloadMassDriver.java | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 0a19f9eee7..e890c43bde 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1847,13 +1847,13 @@ public class Blocks implements ContentList{ range = 195f; reloadTime = 90f; firingMoveFract = 0.5f; - shootDuration = 220f; + shootDuration = 230f; powerUse = 17f; shootSound = Sounds.laserbig; loopSound = Sounds.beam; loopSoundVolume = 2f; - shootType = new ContinuousLaserBulletType(70){{ + shootType = new ContinuousLaserBulletType(75){{ length = 200f; hitEffect = Fx.hitMeltdown; hitColor = Pal.meltdownHit; diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index 2d26a96fc5..a68376aac8 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -430,7 +430,7 @@ public class Block extends UnlockableContent{ boolean buffered = cons.buffered; float capacity = cons.capacity; - bars.add("power", entity -> new Bar(() -> buffered ? Core.bundle.format("bar.poweramount", Float.isNaN(entity.power.status * capacity) ? "" : (int)(entity.power.status * capacity)) : + bars.add("power", entity -> new Bar(() -> buffered ? Core.bundle.format("bar.poweramount", Float.isNaN(entity.power.status * capacity) ? "" : UI.formatAmount((int)(entity.power.status * capacity))) : Core.bundle.get("bar.power"), () -> Pal.powerBar, () -> Mathf.zero(cons.requestedPower(entity)) && entity.power.graph.getPowerProduced() + entity.power.graph.getBatteryStored() > 0f ? 1f : entity.power.status)); } diff --git a/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java b/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java index 5e04456ac3..7087c5f008 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java @@ -60,6 +60,7 @@ public class PayloadMassDriver extends PayloadBlock{ sync = true; rotate = true; outputsPayload = true; + group = BlockGroup.units; //point2 is relative config(Point2.class, (PayloadDriverBuild tile, Point2 point) -> tile.link = Point2.pack(point.x + tile.tileX(), point.y + tile.tileY())); From e7e64379dd5e2118d44225e7f097acd43cad979c Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 10 Aug 2021 15:12:58 -0400 Subject: [PATCH 130/130] () --- core/src/mindustry/async/PhysicsProcess.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/async/PhysicsProcess.java b/core/src/mindustry/async/PhysicsProcess.java index c8594a3ee2..c62281802c 100644 --- a/core/src/mindustry/async/PhysicsProcess.java +++ b/core/src/mindustry/async/PhysicsProcess.java @@ -42,10 +42,10 @@ public class PhysicsProcess implements AsyncProcess{ if(entity.physref == null){ PhysicsBody body = new PhysicsBody(); - body.x = entity.x(); - body.y = entity.y(); + body.x = entity.x; + body.y = entity.y; body.mass = entity.mass(); - body.radius = entity.hitSize() / 2f; + body.radius = entity.hitSize / 2f; PhysicRef ref = new PhysicRef(entity, body); refs.add(ref);