Compare commits

..

137 Commits
v117 ... v119

Author SHA1 Message Date
Anuken
29be8176c1 Fixed some crashes 2020-11-29 11:08:12 -05:00
Anuken
67c6e0179f Merge remote-tracking branch 'origin/master' 2020-11-29 10:37:11 -05:00
Anuken
e3f2966db3 Nevermind, reverting to beta for last pre-release 2020-11-29 10:37:07 -05:00
Anuken
9e53b3b7e6 Update bug_report.md 2020-11-29 10:33:51 -05:00
Anuken
8f186a16b3 Build beginPlace+Break access tracking / Instant rotation 2020-11-29 10:12:24 -05:00
Anuken
9a3b21d77a Fixed #3650 2020-11-29 09:54:52 -05:00
Anuken
23fc86fac1 Updated wiki links 2020-11-28 23:59:56 -05:00
Anuken
3d6fd8a351 De-abstracted weather 2020-11-28 23:23:39 -05:00
Anuken
3c51d82a1a Fixed #3648 2020-11-28 22:45:36 -05:00
Anuken
b63501b1c7 Core overfill bugfix 2020-11-28 21:51:26 -05:00
Anuken
810238d0f9 Cleanup 2020-11-28 20:30:43 -05:00
Anuken
bb16d1c613 Removed Abstract block classes for better code inspection 2020-11-28 19:12:27 -05:00
Anuken
b8cb17c0c5 Campaign production fixes 2020-11-28 15:08:53 -05:00
Anuken
9ca3cd49b8 Merge remote-tracking branch 'origin/master' 2020-11-28 13:57:23 -05:00
Anuken
e6544b73db Switching modifier from beta to release 2020-11-28 13:57:19 -05:00
Anuken
2e30cd31c2 Merge pull request #3646 from Slava0135/unit-payload
Unit Payload spawning units on block removing/destruction
2020-11-28 13:56:45 -05:00
slava0135
e6078bd4f6 oopsie x4 2020-11-28 21:49:59 +03:00
slava0135
b0477394e6 oopsie x3 2020-11-28 21:45:42 +03:00
slava0135
699750762f removing unnecessary stuff 2020-11-28 21:38:50 +03:00
slava0135
ee3348d160 oopsie x2 2020-11-28 21:10:12 +03:00
slava0135
6dc2486ce0 oopsie 2020-11-28 21:06:20 +03:00
slava0135
724a0018b8 unit payload improvements 2020-11-28 20:39:09 +03:00
slava0135
3b20c68a6f Merge branch 'master' of https://github.com/Anuken/Mindustry 2020-11-28 19:53:04 +03:00
Anuken
98206446e6 Merge remote-tracking branch 'origin/master' 2020-11-28 11:31:14 -05:00
Anuken
6e62859d0e Fixed #3644 2020-11-28 11:31:07 -05:00
Anuken
1f1701f1d6 Update README.md 2020-11-28 10:44:14 -05:00
Anuken
e6c99e0c6d Update README.md 2020-11-28 10:42:50 -05:00
Anuken
e6c15b526a Merge pull request #3620 from AydenRennaker/patch-8
Update servers_v6.json
2020-11-28 09:50:22 -05:00
Anuken
4de516b527 Merge pull request #3639 from LeoSko/patch-2
Update servers_v6.json
2020-11-28 09:50:02 -05:00
slava0135
815a483d2c typo in Fires:
/** Start a fire on the tile. If there already is a file there, refreshes its lifetime. */
2020-11-28 17:49:39 +03:00
Anuken
2816aeb6e9 Merge pull request #3451 from Angel-24/patch-2
[Bundle][ES] Translation update
2020-11-28 09:46:30 -05:00
Anuken
f40e523764 Merge pull request #3567 from CPXMC/patch-6
Update bundle_zh_CN.properties
2020-11-28 09:46:23 -05:00
Anuken
8a424111f0 Fixed #3633 2020-11-28 09:43:35 -05:00
Leonid Skorospelov
47922834f9 Update servers_v6.json
Ranked 1v1 gradually moving to v6
2020-11-28 14:16:30 +02:00
Anuken
2a6b0fd0ce Fixed vaults not counting withdrawn items 2020-11-27 18:09:47 -05:00
Anuken
47e622dee3 (more) Campaign balancing 2020-11-27 18:07:10 -05:00
Anuken
99125e9218 Merge remote-tracking branch 'origin/master' 2020-11-27 17:37:28 -05:00
Anuken
66918f0322 Campaign balancing 2020-11-27 17:37:22 -05:00
Anuken
b8a2c609cb Merge pull request #3629 from Catchears/typo
typo
2020-11-27 16:19:16 -05:00
Wiki Updater
968277477a typo 2020-11-27 22:18:08 +01:00
Anuken
d06b32c20b Added boss to sector damage calculations 2020-11-27 14:18:09 -05:00
Anuken
525dc0cd7e Added bosses for sectors missing them 2020-11-27 12:35:20 -05:00
Anuken
8b6fc7f3ac Fixed #3628 2020-11-27 12:27:56 -05:00
Anuken
8dd66fb942 Campaign tweaks 2020-11-27 11:56:01 -05:00
Angel_24
7e5c69a107 Update bundle_es.properties 2020-11-27 13:07:38 +01:00
Angel_24
e4a95ab4c4 Merge pull request #2 from Angel-24/master
Master
2020-11-27 10:21:25 +01:00
Angel_24
40dd3d5677 Update bundle_es.properties 2020-11-27 10:07:38 +01:00
Anuken
e39eceee28 Allow research even if sector was attacked after capture 2020-11-26 21:48:45 -05:00
AydenRennaker
ca29909bec Update servers_v6.json
Add Atanner Gaming server back to list. 

Updates are looking good :)
2020-11-26 18:32:31 -08:00
Anuken
869c329fbf Fixed Nuclear Complex gen / Increased damage simulation harshness 2020-11-26 21:29:22 -05:00
Anuken
c8b425116e Fixed Impact0078 ore gen / Misc campaign fixes 2020-11-26 20:46:17 -05:00
Anuken
0a290d2e10 Auto-rebuilding of broken attack sector blocks on restart 2020-11-26 20:19:13 -05:00
Anuken
9863cbc991 Disabled unit explosion team damage 2020-11-26 19:30:49 -05:00
Anuken
91c50ae126 Disabled explosion fires for item flammability <= 1
coming soon: spore bombing?
2020-11-26 19:25:26 -05:00
Anuken
dae46ceb6d Campaign bugfixes / Balancing 2020-11-26 18:53:20 -05:00
Anuken
6b3919e8f7 Added Call#setItem 2020-11-26 16:49:01 -05:00
Anuken
20637fa358 Merge remote-tracking branch 'origin/master' 2020-11-26 15:32:01 -05:00
Anuken
1d8ec9abd9 Campaign bugfixes 2020-11-26 15:31:58 -05:00
Anuken
d3f58c0e83 Campaign bugfixes 2020-11-26 15:31:19 -05:00
Anuken
84474040c0 Fungal Pass map fixes 2020-11-26 14:24:35 -05:00
Anuken
3fe4ae38b6 Misc cleanup 2020-11-26 12:53:19 -05:00
Anuken
465219540c Added prompt for loading legacy research data 2020-11-26 10:22:01 -05:00
Angel_24
0e354dbf23 Merge pull request #1 from Angel-24/patch-2
Patch 2
2020-11-26 10:46:59 +01:00
Angel_24
d1563ee55e Merge branch 'master' into patch-2 2020-11-26 10:43:13 +01:00
Angel_24
fa3a19d766 Update bundle_es.properties 2020-11-26 08:52:46 +01:00
Angel_24
0d4add667f Update bundle_es.properties 2020-11-26 08:49:44 +01:00
Angel_24
7f214f1343 Update bundle_es.properties 2020-11-26 08:47:11 +01:00
Anuken
e1ddf115e0 Merged turret types 2020-11-25 20:41:38 -05:00
Anuken
56f1d0548e Merge remote-tracking branch 'origin/master' 2020-11-25 20:23:24 -05:00
Anuken
38471d68d7 Fixed Salt Flats being deadlocked 2020-11-25 20:23:17 -05:00
Anuken
17a571f22a Merge pull request #3604 from sk7725/patch-30
[KO]Quick Fix
2020-11-25 20:06:10 -05:00
Sunny Kim
dd9c3fc8d6 Update bundle_ko.properties 2020-11-26 10:01:15 +09:00
Sunny Kim
a70e29127b [KO]quick patch 2020-11-26 09:59:07 +09:00
Anuken
6be2b6021b Merge pull request #3603 from skykatik/patch-12
Some typos
2020-11-25 18:28:30 -05:00
Skat
488147759a Some typos 2020-11-26 02:04:08 +03:00
Anuken
9a7d359626 Merge pull request #3579 from Quezler/patch-68
Remove stray newline
2020-11-25 17:49:40 -05:00
Anuken
0437d50a5c Merge pull request #3598 from summetdev/patch-8
Remove unused imports
2020-11-25 17:49:24 -05:00
Anuken
f49f151901 Merge pull request #3601 from genNAowl/projector-block-group
Add Projectors Blockgroup
2020-11-25 17:27:56 -05:00
Angel_24
245e5d515a Update contributors 2020-11-25 23:22:17 +01:00
Leonwang4234
2b8c11c451 projectors blockgroup 2020-11-25 14:19:56 -08:00
Anuken
11d864f2b5 Merge remote-tracking branch 'origin/master' 2020-11-25 16:25:43 -05:00
Anuken
977b55bf32 Testing BE builds 2020-11-25 16:25:39 -05:00
Anuken
b06be81f1e Merge pull request #3600 from summetdev/patch-10
GitHub Actions: Manual Triggers
2020-11-25 16:24:33 -05:00
Anuken
93313664f0 Testing BE builds 2020-11-25 16:14:39 -05:00
Antsiferov Andrew
25cb2b0abf Add workflow_dispatch event 2020-11-26 00:09:17 +03:00
Anuken
b841af3a48 Testing BE builds 2020-11-25 16:09:11 -05:00
Anuken
709f43b83c Testing BE builds 2020-11-25 16:00:35 -05:00
Anuken
aabc094dd9 Testing BE builds 2020-11-25 15:47:44 -05:00
Anuken
58acc0a970 Merge remote-tracking branch 'origin/master' 2020-11-25 15:42:56 -05:00
Anuken
c874089f27 Bugfixes 2020-11-25 15:42:51 -05:00
Angel_24
1cc73a4077 Finished Spanish Translation, for now... 2020-11-25 21:26:24 +01:00
Antsiferov Andrew
4ac26d86f5 Remove unused imports 2020-11-25 20:04:32 +00:00
Angel_24
a693289867 Update bundle_es.properties 2020-11-25 20:57:32 +01:00
Anuken
010e5341dc Merge pull request #3596 from Catchears/ai
Fix ai schematics with power weapons and steam gens
2020-11-25 14:14:28 -05:00
Wiki Updater
51790e0bf9 fix ai schematics with power weapons and steam gens 2020-11-25 19:52:36 +01:00
Anuken
40b67349d9 Fixed quotes 2020-11-25 11:56:10 -05:00
Anuken
735cb74483 Merge remote-tracking branch 'origin/master' 2020-11-25 11:15:50 -05:00
Anuken
bc55e43def Fixed #3591 2020-11-25 11:15:46 -05:00
Anuken
084d7e8355 Merge pull request #3583 from Quezler/patch-69
automatic reconnect
2020-11-25 11:14:04 -05:00
Anuken
22e60612ac Merge remote-tracking branch 'origin/master' 2020-11-25 11:09:33 -05:00
Anuken
b271c4be32 Fixed deploy CI, again 2020-11-25 11:09:29 -05:00
Patrick 'Quezler' Mounier
f26b3358ef Update core/src/mindustry/ui/dialogs/JoinDialog.java
Co-authored-by: Anuken <arnukren@gmail.com>
2020-11-25 17:08:03 +01:00
Patrick 'Quezler' Mounier
3d6390a76a Set the ping to null when canceling manually as well 2020-11-25 16:51:57 +01:00
Patrick 'Quezler' Mounier
ff20928bec Anukify reconnect logic 2020-11-25 16:49:36 +01:00
Anuken
59387389a4 Merge pull request #3563 from skykatik/patch-11
Deleted unnecessary DateTimeFormatter declaration
2020-11-25 10:33:46 -05:00
Anuken
fb200c6d11 arc 2020-11-25 10:16:40 -05:00
Anuken
8418770bbf Merge remote-tracking branch 'origin/master' 2020-11-25 10:15:22 -05:00
Anuken
eaa7b04c3d Fixed CI / Fixed exponentially increasing broken blocks 2020-11-25 10:15:14 -05:00
Anuken
6131ef23fc Merge pull request #3578 from Quezler/patch-67
Remove unused import
2020-11-25 09:36:41 -05:00
Angel_24
1467a3a7fd Update bundle_es.properties 2020-11-25 14:59:07 +01:00
Patrick 'Quezler' Mounier
b002d8b446 Update bundle.properties 2020-11-25 10:42:13 +01:00
Patrick 'Quezler' Mounier
f5e06cca54 Update NetClient.java 2020-11-25 10:41:41 +01:00
Patrick 'Quezler' Mounier
642b877ab0 Update JoinDialog.java 2020-11-25 10:40:42 +01:00
Angel_24
2a618a6600 Update bundle_es.properties 2020-11-25 10:36:48 +01:00
Angel_24
fa48f1b2e0 Merge branch 'master' into patch-2 2020-11-25 10:26:11 +01:00
Angel_24
69063e9dc5 Update contributors 2020-11-25 10:23:07 +01:00
Patrick 'Quezler' Mounier
8ee3f2b2e6 Remove stray newline 2020-11-25 09:38:04 +01:00
Patrick 'Quezler' Mounier
40bf0741f0 Remove unused import 2020-11-25 09:36:12 +01:00
Anuken
6633b07fb2 Merge pull request #3561 from Volas171/patch-2
Update contributors
2020-11-24 18:55:00 -05:00
Volas171
e65971db47 h 2020-11-24 18:30:59 -05:00
CPXMC
9f8e1b93f1 Update bundle_zh_CN.properties
单位,方块,物品的简介翻译交给你们了(滑稽
2020-11-24 22:02:28 +08:00
Skat
1637360952 Deleted unnecessary DateTimeFormatter declaration 2020-11-24 13:00:08 +03:00
Angel_24
38f4154d18 Update bundle_es.properties 2020-11-24 10:47:35 +01:00
Angel_24
7ffbb93ba7 Update contributors 2020-11-24 10:30:33 +01:00
Angel_24
8004b6ce1d Update bundle_es.properties 2020-11-24 09:39:08 +01:00
Volas171
97254a6672 Update contributors 2020-11-23 22:27:08 -05:00
Angel_24
7c79ee469e Update contributors 2020-11-23 20:11:27 +01:00
Angel_24
741e6b55b0 Update contributors 2020-11-23 20:09:33 +01:00
Angel_24
6f75116197 Update bundle_es.properties 2020-11-23 20:06:37 +01:00
Angel_24
143be734c5 Update bundle_es.properties 2020-11-23 14:13:23 +01:00
Angel_24
ad6a3bf150 Update bundle_es.properties 2020-11-23 11:29:07 +01:00
Angel_24
07b12890e8 Update bundle_es.properties 2020-11-20 18:14:55 +01:00
Angel_24
c014f86f2b Update bundle_es.properties
"Titanium" conveyor duplicated on "Plastanium"
2020-11-20 17:39:52 +01:00
Angel_24
ef2ff385b8 Añadido el "cada" de nuevo
Sabía que se me olvidaba algo, pero no tuve tiempo de revisarlo.
2020-11-19 19:21:40 +01:00
Angel_24
31d401340c Update bundle_es.properties 2020-11-19 14:57:16 +01:00
Angel_24
c3df430a4e Update bundle_es.properties 2020-11-19 14:56:12 +01:00
Angel_24
071d98dbfa Update bundle_es.properties 2020-11-18 20:48:12 +01:00
121 changed files with 1392 additions and 907 deletions

View File

@@ -17,7 +17,9 @@ assignees: ''
**Link(s) to mod(s) used**: *The mod repositories or zip files that are related to the issue, if applicable.* **Link(s) to mod(s) used**: *The mod repositories or zip files that are related to the issue, if applicable.*
**Save file**: *The (zipped) save file you were playing on when the bug happened. THIS IS REQUIRED FOR ANY ISSUE HAPPENING IN-GAME, REGARDLESS OF WHETHER YOU THINK IT HAPPENS EVERYWHERE. DO NOT DELETE OR OMIT THIS LINE UNLESS YOU ARE SURE THAT THE ISSUE DOES NOT HAPPEN IN-GAME.* **Save file**: *The (zipped) save file you were playing on when the bug happened. THIS IS REQUIRED FOR ANY ISSUE HAPPENING IN-GAME OR IN MULTIPLAYER, REGARDLESS OF WHETHER YOU THINK IT HAPPENS EVERYWHERE. DO NOT DELETE OR OMIT THIS LINE UNLESS YOU ARE SURE THAT THE ISSUE DOES NOT HAPPEN IN-GAME.*
If you remove the line above without reading it properly and understanding what it means, I will reap your soul. Even if you're playing on someone's server, you can still save the game to a slot.
**Crash report**: *The contents of relevant crash report files. REQUIRED if you are reporting a crash.* **Crash report**: *The contents of relevant crash report files. REQUIRED if you are reporting a crash.*

View File

@@ -15,45 +15,49 @@ jobs:
uses: actions/setup-java@v1 uses: actions/setup-java@v1
with: with:
java-version: 14 java-version: 14
- name: Set env
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
- name: Create artifacts - name: Create artifacts
run: | run: |
./gradlew desktop:dist server:dist core:javadoc -Pbuildversion=${GITHUB_REF:1} ./gradlew desktop:dist server:dist core:javadoc -Pbuildversion=${RELEASE_VERSION:1}
- name: Update docs - name: Update docs
run: | run: |
cd ../ cd ../
git config --global user.email "cli@github.com"
git config --global user.name "Github Actions"
git clone --depth=1 https://github.com/MindustryGame/docs.git git clone --depth=1 https://github.com/MindustryGame/docs.git
cp -a Mindustry/core/build/docs/javadoc/. docs/ cp -a Mindustry/core/build/docs/javadoc/. docs/
cd docs cd docs
git add . git add .
git commit -m "Update ${GITHUB_REF:1}" git commit -m "Update ${RELEASE_VERSION:1}"
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/MindustryGame/docs git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/MindustryGame/docs
cd ../Mindustry cd ../Mindustry
- name: Add Arc release - name: Add Arc release
run: | run: |
git clone --depth=1 --branch=master https://github.com/Anuken/Arc ../Arc git clone --depth=1 --branch=master https://github.com/Anuken/Arc ../Arc
cd ../Arc cd ../Arc
git tag ${GITHUB_REF} git tag ${RELEASE_VERSION}
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/Arc ${GITHUB_REF}; git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/Arc ${RELEASE_VERSION};
cd ../Mindustry cd ../Mindustry
- name: Update F-Droid build string - name: Update F-Droid build string
run: | run: |
git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
cd ../MindustryBuilds cd ../MindustryBuilds
echo "Updating version to ${GITHUB_REF:1}" echo "Updating version to ${RELEASE_VERSION:1}"
echo versionName=6-fdroid-${GITHUB_REF:1}$'\n'versionCode=${GITHUB_REF:1} > version_fdroid.txt echo versionName=6-fdroid-${RELEASE_VERSION:1}$'\n'versionCode=${RELEASE_VERSION:1} > version_fdroid.txt
git add . git add .
git commit -m "Updating to build ${GITHUB_REF:1}" git commit -m "Updating to build ${RELEASE_VERSION:1}"
cd ../Mindustry cd ../Mindustry
- name: Upload client artifacts - name: Upload client artifacts
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
file: desktop/libs/Mindustry.jar file: desktop/build/libs/Mindustry.jar
tag: ${{ github.ref }} tag: ${{ github.ref }}
- name: Upload server artifacts - name: Upload server artifacts
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
file: server/libs/server-release.jar file: server/build/libs/server-release.jar
tag: ${{ github.ref }} tag: ${{ github.ref }}

View File

@@ -1,6 +1,6 @@
name: Tests name: Tests
on: [push] on: [push, workflow_dispatch]
jobs: jobs:
buildJava14: buildJava14:
@@ -15,6 +15,7 @@ jobs:
- name: Run unit tests - name: Run unit tests
run: ./gradlew test run: ./gradlew test
- name: Trigger BE build - name: Trigger BE build
if: ${{ github.repository == 'Anuken/Mindustry' }}
run: | run: |
git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
cd ../MindustryBuilds cd ../MindustryBuilds

View File

@@ -61,5 +61,5 @@ Post feature requests and feedback [here](https://github.com/Anuken/Mindustry-Su
## Downloads ## Downloads
| [![](https://static.itch.io/images/badge.svg)](https://anuke.itch.io/mindustry) | [![](https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png)](https://play.google.com/store/apps/details?id=io.anuke.mindustry) | [![](https://fdroid.gitlab.io/artwork/badge/get-it-on.png)](https://f-droid.org/packages/io.anuke.mindustry) | [![](https://flathub.org/assets/badges/flathub-badge-en.svg)](https://flathub.org/apps/details/com.github.Anuken.Mindustry) | | [![](https://static.itch.io/images/badge.svg)](https://anuke.itch.io/mindustry) | [![](https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png)](https://play.google.com/store/apps/details?id=io.anuke.mindustry) | [![](https://fdroid.gitlab.io/artwork/badge/get-it-on.png)](https://f-droid.org/packages/io.anuke.mindustry) | [![](https://flathub.org/assets/badges/flathub-badge-en.svg)](https://flathub.org/apps/details/com.github.Anuken.Mindustry)
|--- |--- |--- |--- | |--- |--- |--- |--- |

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
id="svg542"
sodipodi:docname="planet.svg"
inkscape:version="1.0.1 (0767f8302a, 2020-10-17)">
<metadata
id="metadata548">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs546" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1316"
id="namedview544"
showgrid="false"
inkscape:pagecheckerboard="true"
inkscape:zoom="15.75"
inkscape:cx="-16.385458"
inkscape:cy="16.16535"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg542" />
<path
id="polygon2"
style="fill:#ffffff"
d="M 5.5 0 L 5 0.5 L 4.5 1 L 3.5 1 L 3 1.5 L 2.5 2 L 2 2.5 L 1.5 3 L 1 3.5 L 1 4.5 L 0.5 5 L 0 5.5 L 0 6.5 L 0 7.5 L 0 8.5 L 0 9.5 L 0 10.5 L 0.5 11 L 1 11.5 L 1 12.5 L 1.5 13 L 2 13.5 L 2.5 14 L 3 14.5 L 3.5 15 L 4.5 15 L 5 15.5 L 5.5 16 L 6.5 16 L 7.5 16 L 8.5 16 L 9.5 16 L 10.5 16 L 11 15.5 L 11.5 15 L 12.5 15 L 13 14.5 L 13.5 14 L 14 13.5 L 14.5 13 L 15 12.5 L 15 11.5 L 15.5 11 L 16 10.5 L 16 9.5 L 16 8.5 L 16 7.5 L 16 6.5 L 16 5.5 L 15.5 5 L 15 4.5 L 15 3.5 L 14.5 3 L 14 2.5 L 13.5 2 L 13 1.5 L 12.5 1 L 11.5 1 L 11 0.5 L 10.5 0 L 9.5 0 L 8.5 0 L 7.5 0 L 6.5 0 L 5.5 0 z M 6.5 1 L 7 1.5 L 7.5 2 L 8.5 2 L 9 2.5 L 9 3.5 L 9.5 4 L 10 4.5 L 10.5 5 L 11 5.5 L 11.5 6 L 12.5 6 L 13.5 6 L 14.5 6 L 15 6.5 L 15 7.5 L 15 8.5 L 15 9.5 L 14.5 10 L 14 10.5 L 14 11.5 L 13.5 12 L 13 12.5 L 12.5 13 L 12 13.5 L 11.5 14 L 10.5 14 L 10 14.5 L 9.5 15 L 8.5 15 L 8 14.5 L 7.5 14 L 7 13.5 L 7 12.5 L 7.5 12 L 8 11.5 L 8.5 11 L 9 10.5 L 9 9.5 L 9 8.5 L 8.5 8 L 8 7.5 L 7.5 7 L 6.5 7 L 5.5 7 L 4.5 7 L 4 7.5 L 3.5 8 L 3 8.5 L 2.5 9 L 2 9.5 L 1.5 10 L 1 9.5 L 1 8.5 L 1 7.5 L 1 6.5 L 1.5 6 L 2 5.5 L 2 4.5 L 2.5 4 L 3 3.5 L 3.5 3 L 4 2.5 L 4.5 2 L 5.5 2 L 6 1.5 L 6.5 1 z M 11.5 9 L 11 9.5 L 11 10.5 L 11.5 11 L 12.5 11 L 13 10.5 L 13 9.5 L 12.5 9 L 11.5 9 z " />
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

View File

@@ -1,2 +1,3 @@
mschxœ-k mschxњ-Ќ‹
1 „ÇMÅîуôPÅ В0 EoЧКєўТЏЄ®И ¶Ґ«Ёџ.CfІJ‡<NЗ*Ш»Г<C2BB>lцЮѕиmЖ0№ељзTжЂN)>]6!NОРьж0,)Ь‡&ЩІЌцbKqщЌу~И$њя+А­Vh¶•т №} ¶U
кwZР;¤$ґ ]Сґ…]P,(І»ЉЎkҐ№ъЕ¶,e

View File

@@ -23,7 +23,7 @@ gameover.waiting = [accent]Waiting for next map...
highscore = [accent]New highscore! highscore = [accent]New highscore!
copied = Copied. copied = Copied.
indev.notready = This part of the game isn't ready yet indev.notready = This part of the game isn't ready yet
indev.campaign = [accent]You've reached the end of the campaign![]\n\nThis is as far as the content goes. Interplanetary travel will be added in future updates. indev.campaign = [accent]Congratulations! You've reached the end of the campaign![]\n\nThis is as far as the content goes right now. Interplanetary travel will be added in future updates.
load.sound = Sounds load.sound = Sounds
load.map = Maps load.map = Maps
@@ -149,6 +149,9 @@ unlocked = New content unlocked!
available = New research available! available = New research available!
completed = [accent]Completed completed = [accent]Completed
techtree = Tech Tree techtree = Tech Tree
research.legacy = [accent]5.0[] research data found.\nDo you want to [accent]load this data[], or [accent]discard it[] and restart research in the new campaign (recommended)?
research.load = Load
research.discard = Discard
research.list = [lightgray]Research: research.list = [lightgray]Research:
research = Research research = Research
researched = [lightgray]{0} researched. researched = [lightgray]{0} researched.
@@ -230,6 +233,7 @@ disconnect.timeout = Timed out.
disconnect.data = Failed to load world data! disconnect.data = Failed to load world data!
cantconnect = Unable to join game ([accent]{0}[]). cantconnect = Unable to join game ([accent]{0}[]).
connecting = [accent]Connecting... connecting = [accent]Connecting...
reconnecting = [accent]Reconnecting...
connecting.data = [accent]Loading world data... connecting.data = [accent]Loading world data...
server.port = Port: server.port = Port:
server.addressinuse = Address already in use! server.addressinuse = Address already in use!
@@ -1456,7 +1460,7 @@ unit.reign.description = Fires a barrage of massive piercing bullets at all near
unit.nova.description = Fires laser bolts that damage enemies and repair allied structures. Capable of flight. unit.nova.description = Fires laser bolts that damage enemies and repair allied structures. Capable of flight.
unit.pulsar.description = Fires arcs of electricity that damage enemies and repair allied structures. Capable of flight. unit.pulsar.description = Fires arcs of electricity that damage enemies and repair allied structures. Capable of flight.
unit.quasar.description = Fires piercing laser beams that damage enemies and repair allied structures. Capable of flight. Shielded. unit.quasar.description = Fires piercing laser beams that damage enemies and repair allied structures. Capable of flight. Shielded.
unit.vela.description = Fires a massive continuous laser beam that damages enemies, causes fires and repair allied structures. Capable of flight. unit.vela.description = Fires a massive continuous laser beam that damages enemies, causes fires and repairs allied structures. Capable of flight.
unit.corvus.description = Fires a massive laser blast that damages enemies and repairs allied structures. Can step over most terrain. unit.corvus.description = Fires a massive laser blast that damages enemies and repairs allied structures. Can step over most terrain.
unit.crawler.description = Runs toward enemies and self-destructs, causing a large explosion. unit.crawler.description = Runs toward enemies and self-destructs, causing a large explosion.
unit.atrax.description = Fires debilitating orbs of slag at ground targets. Can step over most terrain. unit.atrax.description = Fires debilitating orbs of slag at ground targets. Can step over most terrain.

File diff suppressed because it is too large Load Diff

View File

@@ -19,8 +19,8 @@ screenshot.invalid = 맵이 너무 커서 스크린샷에 사용될 메모리가
gameover = 게임 오버 gameover = 게임 오버
gameover.pvp = [accent]{0}[] 팀이 승리했습니다! gameover.pvp = [accent]{0}[] 팀이 승리했습니다!
highscore = [accent]새로운 최고 점수! highscore = [accent]새로운 최고 점수!
copied = 복사됨. copied = 복사
indev.popup = 현재 [accent]v6[] 버전은 [accent]알파[] 단계입니다.\n[lightgray]이 말은:[]\n- [scarlet]캠페인이 아직 완전히 개발되지 않음[]\n- 몇몇 컨텐츠가 빠짐\n- 대부분의 [scarlet]유닛 AI[]가 작동하지 않음\n- 많은 유닛들이 아직 미완성\n- 보이는 것은 모두 바뀌거나 제거될 수 있음\n\n[accent]Github[] 에서 버그 또는 강제종료 오류를 신고 해 주세요. indev.popup = 현재 [accent]v6[] 버전은 [accent]베타[] 단계입니다.\n\n[accent]Github[] 에서 버그 또는 강제종료 오류를 신고 해 주세요.
indev.notready = 이 부분은 아직 준비가 되지 않았습니다. indev.notready = 이 부분은 아직 준비가 되지 않았습니다.
load.sound = 소리 load.sound = 소리
@@ -71,15 +71,15 @@ map.delete = 정말로 "[accent]{0}[]" 맵을 삭제하시겠습니까?
level.highscore = 최고 점수: [accent]{0} level.highscore = 최고 점수: [accent]{0}
level.select = 맵 선택 level.select = 맵 선택
level.mode = 게임 모드: level.mode = 게임 모드:
coreattack = < 코어가 공격 받고 있습니다! > coreattack = < 코어가 공격 받고 있습니다! >
nearpoint = [[ [scarlet]즉시 스폰지점에서 떠나세요[] ]\n전멸 임박 nearpoint = [[ [scarlet]즉시 스폰지점에서 떠나세요[] ]\n인근 건물들과 유닛들은 초토화됩니다!
database = 코어 데이터베이스 database = 코어 데이터베이스
savegame = 게임 저장 savegame = 게임 저장
loadgame = 게임 불러오기 loadgame = 게임 불러오기
joingame = 게임 참여 joingame = 게임 참여
customgame = 사용자 지정 게임 customgame = 사용자 지정 게임
newgame = 새 게임 newgame = 새 게임
none = <없음> none = < 없음 >
minimap = 미니맵 minimap = 미니맵
position = 위치 position = 위치
close = 닫기 close = 닫기
@@ -291,8 +291,8 @@ waiting = [lightgray]대기중...
waiting.players = 상대 플레이어를 기다리는 중... waiting.players = 상대 플레이어를 기다리는 중...
wave.enemies = [lightgray]적 유닛 {0}명 남음 wave.enemies = [lightgray]적 유닛 {0}명 남음
wave.enemy = [lightgray]{0}명 남음 wave.enemy = [lightgray]{0}명 남음
wave.guardianwarn = [accent]{0}[] 단계 후에 가디언이 접근합니다. wave.guardianwarn = [accent]{0}[] 단계 후에 수호자가 접근합니다.
wave.guardianwarn.one = [accent]{0}[] 단계 후에 가디언이 접근합니다. wave.guardianwarn.one = [accent]{0}[] 단계 후에 수호자가 접근합니다.
loadimage = 사진 불러오기 loadimage = 사진 불러오기
saveimage = 사진 저장 saveimage = 사진 저장
unknown = 알 수 없음 unknown = 알 수 없음
@@ -335,13 +335,13 @@ editor.center = 중앙
workshop = 창작마당 workshop = 창작마당
waves.title = 단계 waves.title = 단계
waves.remove = 삭제 waves.remove = 삭제
waves.never = 여기까지 유닛생성 waves.never = 여기까지 유닛 생성
waves.every = waves.every =
waves.waves = 단계마다 waves.waves = 단계마다
waves.perspawn = 마리 생성 waves.perspawn = 마리 생성
waves.shields = 보호막/단계 waves.shields = 방어막/단계
waves.to = 부터 waves.to = 부터
waves.guardian = 가디언 waves.guardian = 수호자
waves.preview = 미리보기 waves.preview = 미리보기
waves.edit = 편집 waves.edit = 편집
waves.copy = 클립보드로 복사 waves.copy = 클립보드로 복사
@@ -495,7 +495,7 @@ zone.objective = [lightgray]목표: [accent]{0}
zone.objective.survival = 생존 zone.objective.survival = 생존
zone.objective.attack = 적 코어 파괴 zone.objective.attack = 적 코어 파괴
add = 추가... add = 추가...
boss.health = 보스 체력 boss.health = 수호자 체력
connectfail = [scarlet]연결 오류:\n\n[accent]{0} connectfail = [scarlet]연결 오류:\n\n[accent]{0}
error.unreachable = 서버에 연결하지 못했습니다.\n서버 주소가 정확히 입력되었나요? error.unreachable = 서버에 연결하지 못했습니다.\n서버 주소가 정확히 입력되었나요?
@@ -522,11 +522,11 @@ sectors.resume = 재개
sectors.launch = 출격 sectors.launch = 출격
sectors.select = 선택 sectors.select = 선택
sectors.nonelaunch = [lightgray]없음 (sun) sectors.nonelaunch = [lightgray]없음 (sun)
sectors.rename = Rename Sector sectors.rename = 구역 명명
sector.missingresources = [scarlet]Insufficient Core Resources sector.missingresources = [scarlet]자원 부족
planet.serpulo.name = Serpulo planet.serpulo.name = 세르플
planet.sun.name = Sun planet.sun.name = 태양
sector.groundZero.name = 전초기지 sector.groundZero.name = 전초기지
sector.craters.name = 크레이터 sector.craters.name = 크레이터
@@ -561,26 +561,26 @@ settings.controls = 조작
settings.game = 게임 settings.game = 게임
settings.sound = 소리 settings.sound = 소리
settings.graphics = 그래픽 settings.graphics = 그래픽
settings.cleardata = 게임 데이터 초기화... settings.cleardata = 게임 데이터 초기화
settings.clear.confirm = 정말로 이 데이터를 지우시겠습니까?\n완료된 작업은 취소할 수 없습니다! settings.clear.confirm = 정말로 이 데이터를 지우시겠습니까?\n되돌릴 수 없습니다!
settings.clearall.confirm = [scarlet]경고![]\n이 작업은 저장된 맵, 맵파일, 잠금 해제된 목록과 키 매핑, 그리고 모든 데이터를 삭제합니다.\n확인 버튼을 다시 눌러 모든 데이터를 삭제하고 게임에서 나갑니다. settings.clearall.confirm = [scarlet]경고![]\n이 작업은 저장된 맵, 맵파일, 잠금 해제된 목록과 키 매핑, 그리고 모든 데이터를 삭제합니다.\n확인 버튼을 다시 눌러 모든 데이터를 삭제하고 게임에서 나갑니다.
settings.clearsaves.confirm = 정말로 모든 저장을 삭제 하시겠습니까? settings.clearsaves.confirm = 정말로 모든 저장된 파일들을 삭제하시겠습니까?
settings.clearsaves = 저장 초기화 settings.clearsaves = 저장 초기화
settings.clearresearch = Clear Research settings.clearresearch = 연구 초기화
settings.clearresearch.confirm = Are you sure you want to clear all of your campaign research? settings.clearresearch.confirm = 정말로 모든 연구를 삭제하시겠습니까?
settings.clearcampaignsaves = Clear Campaign Saves settings.clearcampaignsaves = 캠페인 맵 초기화
settings.clearcampaignsaves.confirm = Are you sure you want to clear all of your campaign saves? settings.clearcampaignsaves.confirm = 정말로 캠페인을 초기화하시겠습니까?
paused = [accent]< 일시정지 > paused = [accent]< 일시정지 >
clear = 초기화 clear = 초기화
banned = [scarlet]차단됨 banned = [scarlet]차단됨
unplaceable.sectorcaptured = [scarlet]점령된 구역이 필요합니다 unplaceable.sectorcaptured = [scarlet]구역 점령 필요
yes = yes =
no = 아니오 no = 아니오
info.title = 정보 info.title = 정보
error.title = [scarlet]오류가 발생했습니다. error.title = [scarlet]오류가 발생했습니다.
error.crashtitle = 오류가 발생했습니다 error.crashtitle = 오류가 발생했습니다
unit.nobuild = [scarlet]이 유닛은 건설할 수 없습니다. unit.nobuild = [scarlet]건설 불가
lastaccessed = [lightgray]마지막 접근: {0} lastaccessed = [lightgray]마지막 조작: {0}
block.unknown = [lightgray]??? block.unknown = [lightgray]???
stat.input = 입력 stat.input = 입력
@@ -588,70 +588,70 @@ stat.output = 출력
stat.booster = 가속 stat.booster = 가속
stat.tiles = 필요한 타일 stat.tiles = 필요한 타일
stat.affinities = 친화력 stat.affinities = 친화력
stat.powercapacity = Power Capacity stat.powercapacity = 전력량
stat.powershot = Power/Shot stat.powershot = 전력량/발
stat.damage = Damage stat.damage = 공격력
stat.targetsair = Targets Air stat.targetsair = 공중 공격
stat.targetsground = Targets Ground stat.targetsground = 지상 공격
stat.itemsmoved = Move Speed stat.itemsmoved = 이동 속도
stat.launchtime = Time Between Launches stat.launchtime = 발사 간격
stat.shootrange = Range stat.shootrange = 사거리
stat.size = Size stat.size = 크기
stat.displaysize = Display Size stat.displaysize = 화면 크기
stat.liquidcapacity = Liquid Capacity stat.liquidcapacity = 액체 수용량
stat.powerrange = Power Range stat.powerrange = 전선 길이
stat.linkrange = Link Range stat.linkrange = 감지 길이
stat.instructions = Instructions stat.instructions = 최대 명령어 수
stat.powerconnections = Max Connections stat.powerconnections = 최대 연결 개수
stat.poweruse = Power Use stat.poweruse = 전력 요구량
stat.powerdamage = Power/Damage stat.powerdamage = 전력량/피해량
stat.itemcapacity = Item Capacity stat.itemcapacity = 자원 수용량
stat.memorycapacity = Memory Capacity stat.memorycapacity = 변수 개수
stat.basepowergeneration = Base Power Generation stat.basepowergeneration = 기본 발전량
stat.productiontime = Production Time stat.productiontime = 소요 시간
stat.repairtime = Block Full Repair Time stat.repairtime = 건물 완전 복구 시간
stat.speedincrease = Speed Increase stat.speedincrease = 속도 증가
stat.range = Range stat.range = 사거리
stat.drilltier = Drillables stat.drilltier = 채굴 가능 자원
stat.drillspeed = Base Drill Speed stat.drillspeed = 기본 채굴 속도
stat.boosteffect = Boost Effect stat.boosteffect = 버프 효과
stat.maxunits = Max Active Units stat.maxunits = 최대 유닛 수
stat.health = Health stat.health = 체력
stat.buildtime = Build Time stat.buildtime = 건설 시간
stat.maxconsecutive = Max Consecutive stat.maxconsecutive = 최대 체인 길이
stat.buildcost = Build Cost stat.buildcost = 건설 비용
stat.inaccuracy = Inaccuracy stat.inaccuracy = 오차각
stat.shots = Shots stat.shots = 발사 당 탄
stat.reload = Shots/Second stat.reload = 발/초
stat.ammo = Ammo stat.ammo = 탄약
stat.shieldhealth = Shield Health stat.shieldhealth = 보호막 체력
stat.cooldowntime = Cooldown Time stat.cooldowntime = 쿨타임
stat.explosiveness = Explosiveness stat.explosiveness = 폭발성
stat.basedeflectchance = Base Deflect Chance stat.basedeflectchance = 기본 반사 확률
stat.lightningchance = Lightning Chance stat.lightningchance = 전격 확률
stat.lightningdamage = Lightning Damage stat.lightningdamage = 전격 공격량
stat.flammability = Flammability stat.flammability = 휘발성
stat.radioactivity = Radioactivity stat.radioactivity = 방사성
stat.heatcapacity = HeatCapacity stat.heatcapacity = 열용량
stat.viscosity = Viscosity stat.viscosity = 점성
stat.temperature = Temperature stat.temperature = 온도
stat.speed = Speed stat.speed = 속도
stat.buildspeed = Build Speed stat.buildspeed = 건설 속도
stat.minespeed = Mine Speed stat.minespeed = 채굴 속도
stat.minetier = Mine Tier stat.minetier = 채굴 티어
stat.payloadcapacity = Payload Capacity stat.payloadcapacity = 화물 수용량
stat.commandlimit = Command Limit stat.commandlimit = 지휘 한계
stat.abilities = Abilities stat.abilities = 능력
ability.forcefield = Force Field ability.forcefield = 보호막
ability.repairfield = Repair Field ability.repairfield = 수리장
ability.statusfield = Status Field ability.statusfield = 버프장
ability.unitspawn = {0} Factory ability.unitspawn = {0} 공장
ability.shieldregenfield = Shield Regen Field ability.shieldregenfield = 방어막 복구장
bar.drilltierreq = 더 좋은 드릴이 필요 bar.drilltierreq = 더 좋은 드릴이 필요
bar.noresources = 자원 부족 bar.noresources = 자원 부족
bar.corereq = 코어 기지 필요 bar.corereq = 코어 필요
bar.drillspeed = 드릴 속도: {0}/s bar.drillspeed = 드릴 속도: {0}/s
bar.pumpspeed = 펌프 속도: {0}/s bar.pumpspeed = 펌프 속도: {0}/s
bar.efficiency = 효율: {0}% bar.efficiency = 효율: {0}%
@@ -688,7 +688,7 @@ bullet.multiplier = [stat]{0}[lightgray]x 탄약 배수
bullet.reload = [stat]{0}[lightgray]x 발사 속도 bullet.reload = [stat]{0}[lightgray]x 발사 속도
unit.blocks = 블록 unit.blocks = 블록
unit.blockssquared = blocks² unit.blockssquared = 블록²
unit.powersecond = 전력/초 unit.powersecond = 전력/초
unit.liquidsecond = 액체/초 unit.liquidsecond = 액체/초
unit.itemssecond = 개/초 unit.itemssecond = 개/초
@@ -701,7 +701,7 @@ unit.persecond = /초
unit.perminute = /분 unit.perminute = /분
unit.timesspeed = x 배 unit.timesspeed = x 배
unit.percent = % unit.percent = %
unit.shieldhealth = 보호막 체력 unit.shieldhealth = 방어막 체력
unit.items = 자원 unit.items = 자원
unit.thousands = unit.thousands =
unit.millions = 백만 unit.millions = 백만
@@ -711,7 +711,7 @@ category.power = 전력
category.liquids = 액체 category.liquids = 액체
category.items = 자원 category.items = 자원
category.crafting = 입력/출력 category.crafting = 입력/출력
category.function = Function category.function = 기능
category.optional = 보조 자원 category.optional = 보조 자원
setting.landscape.name = 가로화면 잠금 setting.landscape.name = 가로화면 잠금
setting.shadows.name = 그림자 setting.shadows.name = 그림자
@@ -722,7 +722,7 @@ setting.flow.name = 자원 흐름량 표시
setting.buildautopause.name = 건설 자동 일시정지 setting.buildautopause.name = 건설 자동 일시정지
setting.animatedwater.name = 액체 애니메이션 효과 setting.animatedwater.name = 액체 애니메이션 효과
setting.animatedshields.name = 보호막 애니메이션 효과 setting.animatedshields.name = 보호막 애니메이션 효과
setting.antialias.name = 안티 에일리어싱[lightgray] (재시작 필요)[] setting.antialias.name = 위신호 제거 필터[lightgray] (재시작 필요)[]
setting.playerindicators.name = 플레이어 위치 표시기 setting.playerindicators.name = 플레이어 위치 표시기
setting.indicators.name = 적 위치 표시기 setting.indicators.name = 적 위치 표시기
setting.autotarget.name = 자동 조준 setting.autotarget.name = 자동 조준
@@ -734,10 +734,10 @@ setting.fpscap.text = {0} FPS
setting.uiscale.name = UI 스케일링[lightgray] (재시작 필요)[] setting.uiscale.name = UI 스케일링[lightgray] (재시작 필요)[]
setting.swapdiagonal.name = 항상 대각선 배치 setting.swapdiagonal.name = 항상 대각선 배치
setting.difficulty.training = 훈련 setting.difficulty.training = 훈련
setting.difficulty.easy = 쉬움 setting.difficulty.easy = 무난
setting.difficulty.normal = 보통 setting.difficulty.normal = 보통
setting.difficulty.hard = 어려움 setting.difficulty.hard = 혼돈
setting.difficulty.insane = 미침 setting.difficulty.insane = 박멸
setting.difficulty.name = 난이도: setting.difficulty.name = 난이도:
setting.screenshake.name = 화면 흔들림 setting.screenshake.name = 화면 흔들림
setting.effects.name = 효과 보임 setting.effects.name = 효과 보임
@@ -769,7 +769,7 @@ setting.savecreate.name = 자동 저장 활성화
setting.publichost.name = 멀티플레이 공용 서버로 표시 setting.publichost.name = 멀티플레이 공용 서버로 표시
setting.playerlimit.name = 플레이어 제한 setting.playerlimit.name = 플레이어 제한
setting.chatopacity.name = 채팅창 투명도 setting.chatopacity.name = 채팅창 투명도
setting.lasersopacity.name = 력 레이저 투명도 setting.lasersopacity.name = 투명도
setting.bridgeopacity.name = 터널 투명도 setting.bridgeopacity.name = 터널 투명도
setting.playerchat.name = 채팅 말풍선 표시 setting.playerchat.name = 채팅 말풍선 표시
public.confirm = 게임을 모두에게 공개하시겠습니까?\n[accent]모든 플레이어가 게임에 참여할 수 있습니다.\n[lightgray]설정->게임->멀티플레이 공용 서버로 표시에서 나중에 변경할 수 있습니다.\n\n[sky]번역자 추가[]\n[accent]친구끼리 하려고 이 기능을 활성화 한 뒤에, 친구 외에 다른 플레이어가 들어왔을 때\n해당 플레이어를 차단하는 행위는 비매너를 넘어서는 얌체 행위 그 자체입니다.\n정말로 [scarlet]많은 다른 플레이어들이 오길 원한다[]면 확인하세요. public.confirm = 게임을 모두에게 공개하시겠습니까?\n[accent]모든 플레이어가 게임에 참여할 수 있습니다.\n[lightgray]설정->게임->멀티플레이 공용 서버로 표시에서 나중에 변경할 수 있습니다.\n\n[sky]번역자 추가[]\n[accent]친구끼리 하려고 이 기능을 활성화 한 뒤에, 친구 외에 다른 플레이어가 들어왔을 때\n해당 플레이어를 차단하는 행위는 비매너를 넘어서는 얌체 행위 그 자체입니다.\n정말로 [scarlet]많은 다른 플레이어들이 오길 원한다[]면 확인하세요.
@@ -794,8 +794,8 @@ keybind.clear_building.name = 설계도 초기화
keybind.press = 키를 누르세요... keybind.press = 키를 누르세요...
keybind.press.axis = 마우스 휠 또는 키를 누르세요... keybind.press.axis = 마우스 휠 또는 키를 누르세요...
keybind.screenshot.name = 맵 스크린샷 keybind.screenshot.name = 맵 스크린샷
keybind.toggle_power_lines.name = 력 레이저 토글 keybind.toggle_power_lines.name = 선 가시도 설정
keybind.toggle_block_status.name = 블록 상태 토글 keybind.toggle_block_status.name = 블록 상태 가시도
keybind.move_x.name = X축 이동 keybind.move_x.name = X축 이동
keybind.move_y.name = Y축 이동 keybind.move_y.name = Y축 이동
keybind.mouse_move.name = 커서를 따라서 이동 keybind.mouse_move.name = 커서를 따라서 이동

View File

@@ -17,11 +17,14 @@ linkfail = 打开链接失败!\n网址已复制到您的剪贴板。
screenshot = 屏幕截图已保存到 {0} screenshot = 屏幕截图已保存到 {0}
screenshot.invalid = 地图太大,可能没有足够的内存用于截图。 screenshot.invalid = 地图太大,可能没有足够的内存用于截图。
gameover = 游戏结束 gameover = 游戏结束
gameover.disconnect = 断开连接
gameover.pvp = [accent] {0}[]队获胜! gameover.pvp = [accent] {0}[]队获胜!
gameover.waiting = [accent]正在等待下一张地图...
highscore = [accent]新纪录! highscore = [accent]新纪录!
copied = 已复制 copied = 已复制
indev.popup = [accent]6.0[]仍在[accent]测试版[].\n[lightgray]这意味着:[]\n[scarlet]- 战役玩法完全没有完成[]\n- 很多内容还没有做完\n - 大多[scarlet]单位AI[]无法正确地运行\n- 单位系统完全没有完成\n- 一切您所看到的内容都可能会移除或调整。\n\n在[accent]Github[]提交错误报告。\n[#66ccff]来自译者WinterUnderTheSnow的忠告不建议新玩家游玩还在测试阶段的6.0!建议您先从[orange]v104.6[#66ccff]或[orange]v104.10[#66ccff]开始游玩! indev.popup = [accent]6.0[]仍在[accent]测试版[].\n[lightgray]这意味着:[]\n[scarlet]- 战役玩法完全没有完成[]\n- 很多内容还没有做完\n - 大多[scarlet]单位AI[]无法正确地运行\n- 单位系统完全没有完成\n- 一切您所看到的内容都可能会移除或调整。\n\n在[accent]Github[]提交错误报告。\n[#66ccff]来自译者WinterUnderTheSnow的忠告不建议新玩家游玩还在测试阶段的6.0!建议您先从[orange]v104.6[#66ccff]或[orange]v104.10[#66ccff]开始游玩!
indev.notready = 这部分玩法还未开发完成。 indev.notready = 这部分玩法还未开发完成。
indev.campaign = [accent]您已经到达战役模式的结尾![]\n\n这是内容所能做到的。 未来的更新中将添加行星际旅行。
load.sound = 音乐加载中 load.sound = 音乐加载中
load.map = 地图加载中 load.map = 地图加载中
@@ -57,6 +60,7 @@ schematic.rename = 重命名蓝图
schematic.info = {0}x{1}{2} 个方块 schematic.info = {0}x{1}{2} 个方块
schematic.disabled = [scarlet]蓝图已禁用![]\n您不能在此[accent]地图[]或[accent]服务器[]上使用蓝图. schematic.disabled = [scarlet]蓝图已禁用![]\n您不能在此[accent]地图[]或[accent]服务器[]上使用蓝图.
stats = 统计资料
stat.wave = 防守波数:[accent]{0} stat.wave = 防守波数:[accent]{0}
stat.enemiesDestroyed = 消灭敌人:[accent]{0} stat.enemiesDestroyed = 消灭敌人:[accent]{0}
stat.built = 建造建筑:[accent]{0} stat.built = 建造建筑:[accent]{0}
@@ -189,6 +193,10 @@ servers.local = 本地服务器
servers.remote = 远程服务器 servers.remote = 远程服务器
servers.global = 全球服务器 servers.global = 全球服务器
servers.showhidden = 显示隐藏的服务器
server.shown = 显示
server.hidden = 隐藏
trace = 跟踪玩家 trace = 跟踪玩家
trace.playername = 玩家名称:[accent]{0} trace.playername = 玩家名称:[accent]{0}
trace.ip = IP 地址:[accent]{0} trace.ip = IP 地址:[accent]{0}
@@ -267,6 +275,9 @@ cancel = 取消
openlink = 打开链接 openlink = 打开链接
copylink = 复制链接 copylink = 复制链接
back = 返回 back = 返回
crash.export = 导出崩溃日志
crash.none = 找不到崩溃日志。
crash.exported = 崩溃日志已导出。
data.export = 导出数据 data.export = 导出数据
data.import = 导入数据 data.import = 导入数据
data.openfolder = 打开数据文件夹 data.openfolder = 打开数据文件夹
@@ -283,6 +294,7 @@ cancelbuilding = [accent][[{0}][]来清除规划
selectschematic = [accent][[{0}][]来选择复制 selectschematic = [accent][[{0}][]来选择复制
pausebuilding = [accent][[{0}][]来暂停建造 pausebuilding = [accent][[{0}][]来暂停建造
resumebuilding = [scarlet][[{0}][]来恢复建造 resumebuilding = [scarlet][[{0}][]来恢复建造
showui = UI已隐藏\n按[accent][[{0}][]显示UI
wave = [accent]第{0}波 wave = [accent]第{0}波
wave.cap = [accent]Wave {0}/{1} wave.cap = [accent]Wave {0}/{1}
wave.waiting = [lightgray]下一波倒计时:{0}秒 wave.waiting = [lightgray]下一波倒计时:{0}秒
@@ -290,6 +302,8 @@ wave.waveInProgress = [lightgray]波次袭来
waiting = [lightgray]等待中… waiting = [lightgray]等待中…
waiting.players = 等待玩家中… waiting.players = 等待玩家中…
wave.enemies = [lightgray]剩余 {0} 个敌人 wave.enemies = [lightgray]剩余 {0} 个敌人
wave.enemycores = [accent]{0}[lightgray] 敌人核心(多个)
wave.enemycore = [accent]{0}[lightgray] 敌人核心
wave.enemy = [lightgray]剩余 {0} 个敌人 wave.enemy = [lightgray]剩余 {0} 个敌人
wave.guardianwarn = Boss 将在[accent]{0}[]波后到来。 wave.guardianwarn = Boss 将在[accent]{0}[]波后到来。
wave.guardianwarn.one = Boss 将在[accent]{0}[]波后到来。 wave.guardianwarn.one = Boss 将在[accent]{0}[]波后到来。
@@ -350,6 +364,7 @@ waves.invalid = 剪贴板中的波次信息无效。
waves.copied = 波次信息已复制。 waves.copied = 波次信息已复制。
waves.none = 没有定义敌人。\n请注意这将自动替换为默认的敌人列表。 waves.none = 没有定义敌人。\n请注意这将自动替换为默认的敌人列表。
#these are intentionally in lower case
wavemode.counts = 数目 wavemode.counts = 数目
wavemode.totals = 总和 wavemode.totals = 总和
wavemode.health = 生命值 wavemode.health = 生命值
@@ -462,6 +477,8 @@ load = 载入游戏
save = 保存 save = 保存
fps = 帧数:{0} fps = 帧数:{0}
ping = 延迟:{0}毫秒 ping = 延迟:{0}毫秒
memory = 内存: {0}mb
memory2 = 内存:\n {0}mb +\n {1}mb
language.restart = 为了使语言设置生效请重启游戏。 language.restart = 为了使语言设置生效请重启游戏。
settings = 设置 settings = 设置
tutorial = 教程 tutorial = 教程
@@ -476,24 +493,21 @@ complete = [lightgray]完成:
requirement.wave = {1}中的第{0}波次 requirement.wave = {1}中的第{0}波次
requirement.core = 在{0}中摧毁敌方核心 requirement.core = 在{0}中摧毁敌方核心
requirement.research = 研究 {0} requirement.research = 研究 {0}
requirement.produce = 生产 {0}
requirement.capture = 占领 {0} requirement.capture = 占领 {0}
bestwave = [lightgray]最高波次:{0}
launch.text = 发射 launch.text = 发射
research.multiplayer = 仅有服主可研究物品。 research.multiplayer = 仅有服主可研究物品。
map.multiplayer = 仅有服主可查看区域。
uncover = 解锁 uncover = 解锁
configure = 设定装运的数量 configure = 设定装运的数量
loadout = 装运 loadout = 装运
resources = 资源 resources = 资源
bannedblocks = 禁用建筑 bannedblocks = 禁用建筑
addall = 添加所有 addall = 添加所有
launch.from = 发射地: [accent]{0}
launch.destination = 目的地: {0} launch.destination = 目的地: {0}
configure.invalid = 数量必须是0到{0}之间的数字。 configure.invalid = 数量必须是0到{0}之间的数字。
zone.unlocked = [lightgray]{0} 已解锁。
zone.requirement.complete = 完成{0}。\n已达成解锁{1}的要求。
zone.resources = 地图中的资源:
zone.objective = [lightgray]目标:[accent]{0}
zone.objective.survival = 生存
zone.objective.attack = 摧毁敌方核心
add = 添加… add = 添加…
boss.health = Boss 生命值 boss.health = Boss 生命值
@@ -517,17 +531,41 @@ weather.fog.name = 雾
sectors.unexplored = [lightgray]未探索 sectors.unexplored = [lightgray]未探索
sectors.resources = 资源: sectors.resources = 资源:
sectors.production = 产出: sectors.production = 产出:
sectors.export = 输出:
sectors.time = 时间:
sectors.threat = 威胁
sectors.wave = 进攻波:
sectors.stored = 贮存: sectors.stored = 贮存:
sectors.resume = 继续 sectors.resume = 继续
sectors.launch = 发射 sectors.launch = 发射
sectors.select = 选择 sectors.select = 选择
sectors.nonelaunch = [lightgray]无 (太阳) sectors.nonelaunch = [lightgray]无 (太阳)
sectors.rename = 重命名区块 sectors.rename = 重命名区块
sectors.enemybase = [scarlet]敌人基地
sectors.vulnerable = [scarlet]脆弱的
sectors.underattack = [scarlet]遭到攻击![accent]{0}% 被摧毁
sectors.survives = [accent]存活{0}波
sectors.go = 进入
sector.curcapture = 区域已占领
sector.curlost = 区域丢失
sector.missingresources = [scarlet]核心资源不足 sector.missingresources = [scarlet]核心资源不足
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]已占领!
threat.low =
threat.medium =
threat.high =
threat.extreme = 极高
threat.eradication = 根除
planets = 行星
planet.serpulo.name = 塞普罗 planet.serpulo.name = 塞普罗
planet.sun.name = 太阳 planet.sun.name = 太阳
sector.impact0078.name = 影响0078
sector.groundZero.name = 零号地区 sector.groundZero.name = 零号地区
sector.craters.name = 陨石带 sector.craters.name = 陨石带
sector.frozenForest.name = 冰冻森林 sector.frozenForest.name = 冰冻森林
@@ -539,6 +577,10 @@ sector.overgrowth.name = 增生区
sector.tarFields.name = 油田 sector.tarFields.name = 油田
sector.saltFlats.name = 盐碱荒滩 sector.saltFlats.name = 盐碱荒滩
sector.fungalPass.name = 真菌通道 sector.fungalPass.name = 真菌通道
sector.biomassFacility.name = 生物质合成设施
sector.windsweptIslands.name = 风吹群岛
sector.extractionOutpost.name = 萃取前哨
sector.planetaryTerminal.name = 行星发射终端
sector.groundZero.description = 踏上旅程的最佳位置。这儿的敌人威胁很小,但资源也少。\n收集尽可能多的铅和铜。\n出发吧 sector.groundZero.description = 踏上旅程的最佳位置。这儿的敌人威胁很小,但资源也少。\n收集尽可能多的铅和铜。\n出发吧
sector.frozenForest.description = 即使是靠近山脉的这里,孢子也已经扩散。他们不能长期停留在寒冷的温度中。\n\n开始运用电力。建造火力发电机并学会使用修理者。 sector.frozenForest.description = 即使是靠近山脉的这里,孢子也已经扩散。他们不能长期停留在寒冷的温度中。\n\n开始运用电力。建造火力发电机并学会使用修理者。
@@ -573,7 +615,6 @@ settings.clearcampaignsaves.confirm = 您确定要清除战役进度?
paused = [accent]< 暂停 > paused = [accent]< 暂停 >
clear = 清除 clear = 清除
banned = [scarlet]已禁止 banned = [scarlet]已禁止
unplaceable.sectorcaptured = [scarlet]需要占领区块
yes = yes =
no = no =
info.title = [accent]详情 info.title = [accent]详情
@@ -583,6 +624,7 @@ unit.nobuild = [scarlet]单位未能建造
lastaccessed = [lightgray]上次操作: {0} lastaccessed = [lightgray]上次操作: {0}
block.unknown = [lightgray]??? block.unknown = [lightgray]???
stat.description = 介绍
stat.input = 输入 stat.input = 输入
stat.output = 输出 stat.output = 输出
stat.booster = 增强物品/液体 stat.booster = 增强物品/液体
@@ -610,6 +652,8 @@ stat.memorycapacity = 内存容量
stat.basepowergeneration = 基础能源输出 stat.basepowergeneration = 基础能源输出
stat.productiontime = 生产时间 stat.productiontime = 生产时间
stat.repairtime = 建筑完全修复时间 stat.repairtime = 建筑完全修复时间
stat.weapons = 武器
stat.bullet = 子弹
stat.speedincrease = 提速 stat.speedincrease = 提速
stat.range = 范围 stat.range = 范围
stat.drilltier = 可钻探矿物 stat.drilltier = 可钻探矿物
@@ -642,12 +686,15 @@ stat.minetier = 采矿等级
stat.payloadcapacity = 载货容量 stat.payloadcapacity = 载货容量
stat.commandlimit = 指挥上限 stat.commandlimit = 指挥上限
stat.abilities = 能力 stat.abilities = 能力
stat.canboost = 助推器
stat.flying = 飞行
ability.forcefield = 力墙场 ability.forcefield = 力墙场
ability.repairfield = 修复场 ability.repairfield = 修复场
ability.statusfield = 状态场 ability.statusfield = 状态场
ability.unitspawn = {0} 工厂 ability.unitspawn = {0} 工厂
ability.shieldregenfield = 护盾再生场 ability.shieldregenfield = 护盾再生场
ability.movelightning = 闪电移动
bar.drilltierreq = 需要更好的钻头 bar.drilltierreq = 需要更好的钻头
bar.noresources = 缺失资源 bar.noresources = 缺失资源
@@ -676,12 +723,14 @@ units.processorcontrol = [lightgray]由处理器控制
bullet.damage = [stat]{0}[lightgray] 伤害 bullet.damage = [stat]{0}[lightgray] 伤害
bullet.splashdamage = [stat]{0}[lightgray] 范围伤害 ~[stat] {1}[lightgray] 格 bullet.splashdamage = [stat]{0}[lightgray] 范围伤害 ~[stat] {1}[lightgray] 格
bullet.incendiary = [stat] 燃烧 bullet.incendiary = [stat] 燃烧
bullet.sapping = [stat]sapping
bullet.homing = [stat] 追踪 bullet.homing = [stat] 追踪
bullet.shock = [stat] 电击 bullet.shock = [stat] 电击
bullet.frag = [stat] 分裂 bullet.frag = [stat] 分裂
bullet.knockback = [stat]{0}[lightgray] 击退 bullet.knockback = [stat]{0}[lightgray] 击退
bullet.pierce = [stat]{0}[lightgray]x 穿透 bullet.pierce = [stat]{0}[lightgray]x 穿透
bullet.infinitepierce = [stat]pierce bullet.infinitepierce = [stat]pierce
bullet.healpercent = [stat]{0}[lightgray]% 修复
bullet.freezing = [stat] 冰冻 bullet.freezing = [stat] 冰冻
bullet.tarred = [stat] 减速 bullet.tarred = [stat] 减速
bullet.multiplier = [stat]{0}[lightgray]x 装弹数量 bullet.multiplier = [stat]{0}[lightgray]x 装弹数量
@@ -706,6 +755,7 @@ unit.items = 物品
unit.thousands = K unit.thousands = K
unit.millions = M unit.millions = M
unit.billions = B unit.billions = B
category.purpose = 介绍
category.general = 普通 category.general = 普通
category.power = 能量 category.power = 能量
category.liquids = 液体 category.liquids = 液体
@@ -719,6 +769,7 @@ setting.blockreplace.name = 自动推荐合适的建筑
setting.linear.name = 抗锯齿 setting.linear.name = 抗锯齿
setting.hints.name = 提示 setting.hints.name = 提示
setting.flow.name = 显示资源传送速度[scarlet] (实验性) setting.flow.name = 显示资源传送速度[scarlet] (实验性)
setting.backgroundpause.name = 在背景中暂停
setting.buildautopause.name = 自动暂停建造 setting.buildautopause.name = 自动暂停建造
setting.animatedwater.name = 流动的水 setting.animatedwater.name = 流动的水
setting.animatedshields.name = 动态画面 setting.animatedshields.name = 动态画面
@@ -747,7 +798,6 @@ setting.conveyorpathfinding.name = 传送带自动寻路
setting.sensitivity.name = 控制器灵敏度 setting.sensitivity.name = 控制器灵敏度
setting.saveinterval.name = 自动保存间隔 setting.saveinterval.name = 自动保存间隔
setting.seconds = {0} 秒 setting.seconds = {0} 秒
setting.blockselecttimeout.name = 建筑选择超时
setting.milliseconds = {0} 毫秒 setting.milliseconds = {0} 毫秒
setting.fullscreen.name = 全屏 setting.fullscreen.name = 全屏
setting.borderlesswindow.name = 无边界窗口[lightgray](可能需要重启) setting.borderlesswindow.name = 无边界窗口[lightgray](可能需要重启)
@@ -836,6 +886,8 @@ keybind.menu.name = 菜单
keybind.pause.name = 暂停 keybind.pause.name = 暂停
keybind.pause_building.name = 暂停/继续建造 keybind.pause_building.name = 暂停/继续建造
keybind.minimap.name = 小地图 keybind.minimap.name = 小地图
keybind.planet_map.name = 行星地图
keybind.research.name = 研究
keybind.chat.name = 聊天 keybind.chat.name = 聊天
keybind.player_list.name = 玩家列表 keybind.player_list.name = 玩家列表
keybind.console.name = 控制台 keybind.console.name = 控制台
@@ -899,6 +951,7 @@ content.item.name = 物品
content.liquid.name = 液体 content.liquid.name = 液体
content.unit.name = 部队 content.unit.name = 部队
content.block.name = content.block.name =
content.sector.name = 区域
item.copper.name = item.copper.name =
item.lead.name = item.lead.name =
@@ -959,6 +1012,7 @@ block.resupply-point.name = 补给点
block.parallax.name = 差扰光束 block.parallax.name = 差扰光束
block.cliff.name = 悬崖 block.cliff.name = 悬崖
block.sand-boulder.name = 砂岩 block.sand-boulder.name = 砂岩
block.basalt-boulder.name = 玄武岩巨石
block.grass.name = 草地 block.grass.name = 草地
block.slag.name = 矿渣 block.slag.name = 矿渣
block.space.name = 太空 block.space.name = 太空
@@ -1056,7 +1110,6 @@ block.conveyor.name = 传送带
block.titanium-conveyor.name = 钛传送带 block.titanium-conveyor.name = 钛传送带
block.plastanium-conveyor.name = 塑钢传送带 block.plastanium-conveyor.name = 塑钢传送带
block.armored-conveyor.name = 装甲传送带 block.armored-conveyor.name = 装甲传送带
block.armored-conveyor.description = 运送物品,与钛传送带一样的速度,但有更强的装甲。除其他传送带,不接受任何边上的输入。
block.junction.name = 连接器 block.junction.name = 连接器
block.router.name = 路由器 block.router.name = 路由器
block.distributor.name = 分配器 block.distributor.name = 分配器
@@ -1064,7 +1117,6 @@ block.sorter.name = 分类器
block.inverted-sorter.name = 反向分类器 block.inverted-sorter.name = 反向分类器
block.message.name = 信息板 block.message.name = 信息板
block.illuminator.name = 照明器 block.illuminator.name = 照明器
block.illuminator.description = 小型、紧凑、可配置的光源。需要能量运行。
block.overflow-gate.name = 溢流门 block.overflow-gate.name = 溢流门
block.underflow-gate.name = 反向溢流门 block.underflow-gate.name = 反向溢流门
block.silicon-smelter.name = 硅冶炼厂 block.silicon-smelter.name = 硅冶炼厂
@@ -1160,6 +1212,11 @@ block.payload-router.name = 载荷路由器
block.disassembler.name = 解离机 block.disassembler.name = 解离机
block.silicon-crucible.name = 热能坩埚 block.silicon-crucible.name = 热能坩埚
block.overdrive-dome.name = 超速穹顶投射器 block.overdrive-dome.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.switch.name = 开关
block.micro-processor.name = 微型处理器 block.micro-processor.name = 微型处理器
@@ -1178,30 +1235,45 @@ team.derelict.name = 灰
team.green.name = 绿 team.green.name = 绿
team.purple.name = team.purple.name =
tutorial.next = [lightgray]<点击以继续> hint.skip = 跳过
tutorial.intro = 您已进入[scarlet] Mindustry 教程[]。[]\n使用[accent][[WASD][]键移动机甲和视角。\n[accent]按住[[Ctrl]并转动鼠标滚轮[]缩放视野。\n让我们从[accent]采集铜矿[]开始。先移动到铜矿旁边,然后点按矿脉附近散落的矿物。\n\n[accent]{0}/{1} 铜 hint.desktopMove = 使用[accent][[WASD][]来移动.
tutorial.intro.mobile = 您已进入[scarlet] Mindustry 教程[]。\n在屏幕上滑动来继续。\n[accent]双指捏合[] 来缩小和放大。\n让我们从[accent]采集铜矿[]开始。先移动到铜矿旁边,然后点按矿脉附近散落的矿物。\n\n[accent]铜 {0}/{1} hint.zoom = [accent]滚动[]放大或缩小.
tutorial.drill = 手动采矿效率不高。\n[accent]钻头[]可以自动采矿。\n让我们在在铜矿上放一个。\n点击右下角的钻头菜单。\n选择[accent]机械钻头[]。\n单击将其放置在铜矿上。\n[accent]右键单击[]来停止。 hint.mine = 移动到\uf8c4铜矿附近并点按[accent]tap[]进行手动开采
tutorial.drill.mobile = 手动采矿效率不高。\n[accent]钻头[]可以自动采矿。\n点右下角的钻头菜单。\n选择[accent]机械钻头[]。\n点一下将其放在铜矿上点[accent]对号[]来确定。\n点[accent]叉号[]来取消。 hint.desktopShoot = [accent][[Left-click][]射击.
tutorial.blockinfo = 每种钻头都有其独特的数据。每个钻头只能开采部分矿石。\n若要查看建筑的详细信息[accent]在菜单中点击问号。[]\n\n[accent]现在查看机械钻头的数据吧。[] hint.depositItems = 要转移物品,请将其从飞船上拖到核心。
tutorial.conveyor = [accent]传送带[]可以把物资传送到核心。\n请在钻头到核心间建造一条传送带。 hint.respawn = 要重生飞船,请按[accent][[V][].
tutorial.conveyor.mobile = [accent]传送带[]可以把物资传送到核心。\n请在钻头到核心间建造一条传送带。\n[accent]长按数秒[]并向一个方向拖动来直线放置。\n\n[accent]{0}/{1} 条传送带\n[accent]0/1 物品 hint.respawn.mobile = 您已切换控制单元/结构. 如果要重生飞船请[accent]点击左上方的图标(那个和你长得一样的).[]
tutorial.turret = 必须建造防御建筑来击退[lightgray]敌人[]。\n请在核心附近造一个双管炮。 hint.desktopPause = 按[accent][[Space][]暂停和取消暂停游戏.
tutorial.drillturret = 双管炮需要[accent]铜[]作弹药来射击。\n可以放一个钻头在炮塔附近供应铜。 hint.placeDrill = 选择\ue85e[accent]钻头[]右下角菜单中的标签,然后选择一个\uf870 [accent]钻头[]然后单击铜矿将其放置.
tutorial.pause = 在战斗中,您可以[accent]暂停游戏[]。\n暂停时您可以规划建筑物。\n\n按[accent]空格[]暂停。 hint.placeDrill.mobile = 选择\ue85e[accent]钻头[]右下角菜单中的标签,然后选择一个\uf870 [accent]钻头[]然后点击铜矿将其放置.\n\n按下\ue800 [accent]复选标记[]在右下角按钮确认.
tutorial.pause.mobile = 在战斗中,您可以[accent]暂停游戏[]。\n暂停时您可以规划建筑物。\n\n[accent]点击左上角的按钮以暂停。 hint.placeConveyor = 传送带将物品从钻头移到其他块中。选择一个\uf896 [accent]传送带[]从\ue814 [accent]布局[]标签.\n\n单击并拖动以放置多个传送带.\n[accent]滚动[]旋转.
tutorial.unpause = 现在再次按空格以继续。 hint.placeConveyor.mobile = 传送带将物品从钻头移到其他块中。选择一个\uf896 [accent]传送带[]从\ue814 [accent]布局[]标签.\n\n按住手指一秒钟然后拖动以放置多个传送带.
tutorial.unpause.mobile = 现在再次点按以继续 hint.placeTurret = 放置\uf861 [accent]炮塔[]保卫你的基地从敌人手中.\n\n炮塔需要弹药-在这种情况下e, \uf838copper.\n使用传送带和钻头为它们供弹
tutorial.breaking = 建筑经常需要拆除。\n[accent]按住鼠标右键[]来拆除选中的建筑。[]\n\n[accent]使用范围拆除来拆除核心左侧的废墙。 hint.breaking = [accent]右击[]并拖动以拆除方块.
tutorial.breaking.mobile = 建筑经常需要拆除。\n[accent]选择拆除模式[],点击建筑以拆除。\n[accent]长按几秒[]并拖动来范围拆除。\n点击对号来确定。\n\n[accent]使用范围拆除来拆除核心左侧的废墙。 hint.breaking.mobile = 激活\ue817 [accent]锤子[]在右下角点击以拆除方块.\n\n按住手指一秒钟然后拖动以选择.
tutorial.withdraw = 有时,从建筑中取出物品是必要的。\n[accent]点击包含物品的建筑[],然后[accent]点击在方框中的物品[]。\n可以通过[accent]点击或长按[]来取出物品。\n\n[accent]从核心中取出一些铜[]。 hint.research = 使用\ue875 [accent]科技树[]按钮研究新技术.
tutorial.deposit = 将物品从机甲拖向建筑来放下物品。\n\n[accent]将铜放回核心[]。 hint.research.mobile = 使用\ue875 [accent]科技树[]按钮在\ue88c [accent]菜单[]去研究新技术.
tutorial.waves = [lightgray]敌人[]来了。\n\n保护核心防御两波攻击。造更多的炮塔。[accent]点击[]以射击。\n建造更多的炮塔和钻头并采更多的矿 hint.unitControl = 按住[accent][[L-ctrl][]和[accent]点击[]控制友军单位或炮塔
tutorial.waves.mobile = [lightgray]敌人[]来了。\n\n保护核心防御两波攻击。造更多的炮塔。你的机甲将对敌人自动开火。\n建造更多的炮塔和钻头并采更多的矿 hint.unitControl.mobile = [accent][双击[]控制友军单位或炮塔(双击)
tutorial.launch = 进入特定波次后,你可以[accent]发射核心(起飞)[][accent]带走核心中的所有资源[]并抛下所有的建筑。\n装运的资源可用于研究科技。\n\n[accent]点击发射按钮。 hint.launch = 一旦收集到足够的资源,您就可以[accent]发射[]通过选择附近的区域从\ue827 [accent]地图[]在右下角.
hint.launch.mobile = 一旦收集到足够的资源,您就可以[accent]发射[]通过选择附近的区域从\ue827 [accent]地图[]在\ue88c [accent]菜单[].
hint.schematicSelect = 按住[accent][[F][]并拖动以选择要复制和粘贴的块.\n\n[accent][[Middle Click][]复制单个块类型.
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]能量节点[].
item.copper.description = 一种最基本的的建筑材料。在各种类型的建筑中被广泛使用。 item.copper.description = 一种最基本的的建筑材料。在各种类型的建筑中被广泛使用。
item.copper.details = 铜. 在Serpulo上的金属异常丰富。 除非加固,否则结构较弱。
item.lead.description = 一种基本的电力材料。广泛用于电子设备和液体输送模块。 item.lead.description = 一种基本的电力材料。广泛用于电子设备和液体输送模块。
item.lead.details = Dense. Inert. Extensively used in batteries.\nNote: Likely toxic to biological life forms. Not that there are many left here.
item.metaglass.description = 一种致密坚硬的复合玻璃。广泛用于液体输送和存储。 item.metaglass.description = 一种致密坚硬的复合玻璃。广泛用于液体输送和存储。
item.graphite.description = 一种高密度的碳材料,用于弹药和电器元件。 item.graphite.description = 一种高密度的碳材料,用于弹药和电器元件。
item.sand.description = 一种常见的材料,广泛用于冶炼,包括制作合金和助熔剂。 item.sand.description = 一种常见的材料,广泛用于冶炼,包括制作合金和助熔剂。

View File

@@ -101,3 +101,5 @@ jalastram (freesound.org)
newlocknew (freesound.org) newlocknew (freesound.org)
dsmolenaers (freesound.org) dsmolenaers (freesound.org)
Headphaze (freesound.org) Headphaze (freesound.org)
VolasYouKnow
Ángel Rodríguez Aguilera

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -112,8 +112,8 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
super.add(module); super.add(module);
//autoload modules when necessary //autoload modules when necessary
if(module instanceof Loadable){ if(module instanceof Loadable l){
assets.load((Loadable)module); assets.load(l);
} }
} }

View File

@@ -56,7 +56,7 @@ public class Vars implements Loadable{
/** URL for sending crash reports to */ /** URL for sending crash reports to */
public static final String crashReportURL = "http://192.99.169.18/report"; public static final String crashReportURL = "http://192.99.169.18/report";
/** URL the links to the wiki's modding guide.*/ /** URL the links to the wiki's modding guide.*/
public static final String modGuideURL = "https://mindustrygame.github.io/wiki/modding/"; public static final String modGuideURL = "https://mindustrygame.github.io/wiki/modding/1-modding/";
/** URL to the JSON file containing all the global, public servers. Not queried in BE. */ /** URL to the JSON file containing all the global, public servers. Not queried in BE. */
public static final String serverJsonURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers.json"; public static final String serverJsonURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers.json";
/** URL to the JSON file containing all the BE servers. Only queried in BE. */ /** URL to the JSON file containing all the BE servers. Only queried in BE. */
@@ -88,7 +88,7 @@ public class Vars implements Loadable{
/** duration of time between turns in ticks */ /** duration of time between turns in ticks */
public static final float turnDuration = 2 * Time.toMinutes; public static final float turnDuration = 2 * Time.toMinutes;
/** chance of an invasion per turn, 1 = 100% */ /** chance of an invasion per turn, 1 = 100% */
public static final float baseInvasionChance = 1f / 75f; public static final float baseInvasionChance = 1f / 100f;
/** how many turns have to pass before invasions start */ /** how many turns have to pass before invasions start */
public static final int invasionGracePeriod = 20; public static final int invasionGracePeriod = 20;
/** min armor fraction damage; e.g. 0.05 = at least 5% damage */ /** min armor fraction damage; e.g. 0.05 = at least 5% damage */

View File

@@ -55,11 +55,12 @@ public class BaseAI{
public void update(){ public void update(){
if(data.team.rules().aiCoreSpawn && timer.get(timerSpawn, 60 * 2.5f) && data.hasCore()){ if(data.team.rules().aiCoreSpawn && timer.get(timerSpawn, 60 * 2.5f) && data.hasCore()){
CoreBlock block = (CoreBlock)data.core().block; CoreBlock block = (CoreBlock)data.core().block;
int coreUnits = Groups.unit.count(u -> u.team == data.team && u.type == block.unitType);
//create AI core unit //create AI core unit(s)
if(!state.isEditor() && !Groups.unit.contains(u -> u.team() == data.team && u.type == block.unitType)){ if(!state.isEditor() && coreUnits < data.cores.size){
Unit unit = block.unitType.create(data.team); Unit unit = block.unitType.create(data.team);
unit.set(data.core()); unit.set(data.cores.random());
unit.add(); unit.add();
Fx.spawn.at(unit); Fx.spawn.at(unit);
} }

View File

@@ -67,7 +67,7 @@ public class FormationAI extends AIController implements FormationMember{
if(core != null && leader.mineTile.drop() != null && unit.within(core, unit.type.range) && !unit.acceptsItem(leader.mineTile.drop())){ if(core != null && leader.mineTile.drop() != null && unit.within(core, unit.type.range) && !unit.acceptsItem(leader.mineTile.drop())){
if(core.acceptStack(unit.stack.item, unit.stack.amount, unit) > 0){ if(core.acceptStack(unit.stack.item, unit.stack.amount, unit) > 0){
Call.transferItemTo(unit.stack.item, unit.stack.amount, unit.x, unit.y, core); Call.transferItemTo(unit, unit.stack.item, unit.stack.amount, unit.x, unit.y, core);
unit.clearItem(); unit.clearItem();
} }

View File

@@ -65,7 +65,7 @@ public class MinerAI extends AIController{
if(unit.within(core, unit.type.range)){ if(unit.within(core, unit.type.range)){
if(core.acceptStack(unit.stack.item, unit.stack.amount, unit) > 0){ if(core.acceptStack(unit.stack.item, unit.stack.amount, unit) > 0){
Call.transferItemTo(unit.stack.item, unit.stack.amount, unit.x, unit.y, core); Call.transferItemTo(unit, unit.stack.item, unit.stack.amount, unit.x, unit.y, core);
} }
unit.clearItem(); unit.clearItem();

View File

@@ -14,8 +14,6 @@ import mindustry.world.blocks.*;
import mindustry.world.blocks.campaign.*; import mindustry.world.blocks.campaign.*;
import mindustry.world.blocks.defense.*; import mindustry.world.blocks.defense.*;
import mindustry.world.blocks.defense.turrets.*; import mindustry.world.blocks.defense.turrets.*;
import mindustry.world.blocks.defense.turrets.PointDefenseTurret;
import mindustry.world.blocks.defense.turrets.TractorBeamTurret;
import mindustry.world.blocks.distribution.*; import mindustry.world.blocks.distribution.*;
import mindustry.world.blocks.environment.*; import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.experimental.*; import mindustry.world.blocks.experimental.*;
@@ -1216,18 +1214,18 @@ public class Blocks implements ContentList{
requirements(Category.power, with(Items.lead, 100, Items.silicon, 75, Items.phaseFabric, 25, Items.plastanium, 75, Items.thorium, 50)); requirements(Category.power, with(Items.lead, 100, Items.silicon, 75, Items.phaseFabric, 25, Items.plastanium, 75, Items.thorium, 50));
size = 2; size = 2;
powerProduction = 4.5f; powerProduction = 4.5f;
itemDuration = 60 * 15f; itemDuration = 60 * 14f;
}}; }};
solarPanel = new SolarGenerator("solar-panel"){{ solarPanel = new SolarGenerator("solar-panel"){{
requirements(Category.power, with(Items.lead, 10, Items.silicon, 15)); requirements(Category.power, with(Items.lead, 10, Items.silicon, 15));
powerProduction = 0.08f; powerProduction = 0.1f;
}}; }};
largeSolarPanel = new SolarGenerator("solar-panel-large"){{ largeSolarPanel = new SolarGenerator("solar-panel-large"){{
requirements(Category.power, with(Items.lead, 100, Items.silicon, 145, Items.phaseFabric, 15)); requirements(Category.power, with(Items.lead, 80, Items.silicon, 110, Items.phaseFabric, 15));
size = 3; size = 3;
powerProduction = 1f; powerProduction = 1.3f;
}}; }};
thoriumReactor = new NuclearReactor("thorium-reactor"){{ thoriumReactor = new NuclearReactor("thorium-reactor"){{
@@ -1390,7 +1388,7 @@ public class Blocks implements ContentList{
size = 5; size = 5;
unitCapModifier = 24; unitCapModifier = 24;
researchCostMultiplier = 0.05f; researchCostMultiplier = 0.06f;
}}; }};
vault = new StorageBlock("vault"){{ vault = new StorageBlock("vault"){{
@@ -1515,7 +1513,7 @@ public class Blocks implements ContentList{
flags = EnumSet.of(BlockFlag.turret, BlockFlag.extinguisher); flags = EnumSet.of(BlockFlag.turret, BlockFlag.extinguisher);
}}; }};
lancer = new ChargeTurret("lancer"){{ lancer = new PowerTurret("lancer"){{
requirements(Category.turret, with(Items.copper, 25, Items.lead, 50, Items.silicon, 45)); requirements(Category.turret, with(Items.copper, 25, Items.lead, 50, Items.silicon, 45));
range = 165f; range = 165f;
chargeTime = 40f; chargeTime = 40f;

View File

@@ -37,7 +37,7 @@ public class Bullets implements ContentList{
waterShot, cryoShot, slagShot, oilShot, heavyWaterShot, heavyCryoShot, heavySlagShot, heavyOilShot, waterShot, cryoShot, slagShot, oilShot, heavyWaterShot, heavyCryoShot, heavySlagShot, heavyOilShot,
//environment, misc. //environment, misc.
damageLightning, damageLightningGround, fireball, basicFlame, pyraFlame, driverBolt, healBullet, healBulletBig; damageLightning, damageLightningGround, fireball, basicFlame, pyraFlame, driverBolt;
@Override @Override
public void load(){ public void load(){
@@ -374,20 +374,6 @@ public class Bullets implements ContentList{
knockback = 0.7f; knockback = 0.7f;
}}; }};
healBullet = new LaserBoltBulletType(5.2f, 13){{
healPercent = 3f;
collidesTeam = true;
backColor = Pal.heal;
frontColor = Color.white;
}};
healBulletBig = new LaserBoltBulletType(5.2f, 15){{
healPercent = 5.5f;
collidesTeam = true;
backColor = Pal.heal;
frontColor = Color.white;
}};
fireball = new BulletType(1f, 4){ fireball = new BulletType(1f, 4){
{ {
pierce = true; pierce = true;

View File

@@ -83,7 +83,7 @@ public class SectorPresets implements ContentList{
}}; }};
desolateRift = new SectorPreset("desolateRift", serpulo, 123){{ desolateRift = new SectorPreset("desolateRift", serpulo, 123){{
captureWave = 30; captureWave = 18;
difficulty = 8; difficulty = 8;
}}; }};

View File

@@ -98,11 +98,11 @@ public class TechTree implements ContentList{
node(platedConduit, () -> { node(platedConduit, () -> {
}); });
});
node(rotaryPump, () -> { node(rotaryPump, () -> {
node(thermalPump, () -> { node(thermalPump, () -> {
});
}); });
}); });
}); });
@@ -422,7 +422,7 @@ public class TechTree implements ContentList{
node(additiveReconstructor, Seq.with(new SectorComplete(biomassFacility)), () -> { node(additiveReconstructor, Seq.with(new SectorComplete(biomassFacility)), () -> {
node(multiplicativeReconstructor, () -> { node(multiplicativeReconstructor, () -> {
node(exponentialReconstructor, () -> { node(exponentialReconstructor, Seq.with(new SectorComplete(overgrowth)), () -> {
node(tetrativeReconstructor, () -> { node(tetrativeReconstructor, () -> {
}); });
@@ -471,7 +471,8 @@ public class TechTree implements ContentList{
node(desolateRift, Seq.with( node(desolateRift, Seq.with(
new SectorComplete(impact0078), new SectorComplete(impact0078),
new Research(thermalGenerator), new Research(thermalGenerator),
new Research(thoriumReactor) new Research(thoriumReactor),
new Research(coreNucleus)
), () -> { ), () -> {
node(planetaryTerminal, Seq.with( node(planetaryTerminal, Seq.with(
new SectorComplete(desolateRift), new SectorComplete(desolateRift),
@@ -512,8 +513,7 @@ public class TechTree implements ContentList{
new Research(groundFactory), new Research(groundFactory),
new Research(additiveReconstructor), new Research(additiveReconstructor),
new Research(airFactory), new Research(airFactory),
new Research(door), new Research(door)
new Research(waterExtractor)
), () -> { ), () -> {
}); });

View File

@@ -292,6 +292,7 @@ public class UnitTypes implements ContentList{
shootSound = Sounds.lasershoot; shootSound = Sounds.lasershoot;
bullet = new LaserBoltBulletType(5.2f, 14){{ bullet = new LaserBoltBulletType(5.2f, 14){{
lifetime = 37f;
healPercent = 5f; healPercent = 5f;
collidesTeam = true; collidesTeam = true;
backColor = Pal.heal; backColor = Pal.heal;
@@ -311,7 +312,7 @@ public class UnitTypes implements ContentList{
mineTier = 2; mineTier = 2;
mineSpeed = 5f; mineSpeed = 5f;
commandLimit = 8; commandLimit = 9;
abilities.add(new ShieldRegenFieldAbility(20f, 40f, 60f * 5, 60f)); abilities.add(new ShieldRegenFieldAbility(20f, 40f, 60f * 5, 60f));
ammoType = AmmoTypes.power; ammoType = AmmoTypes.power;
@@ -619,7 +620,7 @@ public class UnitTypes implements ContentList{
drag = 0.4f; drag = 0.4f;
hitSize = 12f; hitSize = 12f;
rotateSpeed = 3f; rotateSpeed = 3f;
health = 800; health = 900;
immunities = ObjectSet.with(StatusEffects.burning, StatusEffects.melting); immunities = ObjectSet.with(StatusEffects.burning, StatusEffects.melting);
legCount = 6; legCount = 6;
legLength = 13f; legLength = 13f;
@@ -650,7 +651,7 @@ public class UnitTypes implements ContentList{
bullet = new SapBulletType(){{ bullet = new SapBulletType(){{
sapStrength = 0.4f; sapStrength = 0.4f;
length = 75f; length = 75f;
damage = 18; damage = 20;
shootEffect = Fx.shootSmall; shootEffect = Fx.shootSmall;
hitColor = color = Color.valueOf("bf92f9"); hitColor = color = Color.valueOf("bf92f9");
despawnEffect = Fx.none; despawnEffect = Fx.none;
@@ -670,7 +671,7 @@ public class UnitTypes implements ContentList{
bullet = new SapBulletType(){{ bullet = new SapBulletType(){{
sapStrength = 0.8f; sapStrength = 0.8f;
length = 40f; length = 40f;
damage = 15; damage = 16;
shootEffect = Fx.shootSmall; shootEffect = Fx.shootSmall;
hitColor = color = Color.valueOf("bf92f9"); hitColor = color = Color.valueOf("bf92f9");
despawnEffect = Fx.none; despawnEffect = Fx.none;
@@ -975,7 +976,7 @@ public class UnitTypes implements ContentList{
zenith = new UnitType("zenith"){{ zenith = new UnitType("zenith"){{
health = 700; health = 700;
speed = 1.7f; speed = 1.8f;
accel = 0.04f; accel = 0.04f;
drag = 0.016f; drag = 0.016f;
flying = true; flying = true;
@@ -997,7 +998,7 @@ public class UnitTypes implements ContentList{
velocityRnd = 0.2f; velocityRnd = 0.2f;
shootSound = Sounds.missile; shootSound = Sounds.missile;
bullet = new MissileBulletType(3f, 12){{ bullet = new MissileBulletType(3f, 14){{
width = 8f; width = 8f;
height = 8f; height = 8f;
shrinkY = 0f; shrinkY = 0f;
@@ -1005,7 +1006,7 @@ public class UnitTypes implements ContentList{
homingRange = 60f; homingRange = 60f;
keepVelocity = false; keepVelocity = false;
splashDamageRadius = 25f; splashDamageRadius = 25f;
splashDamage = 10f; splashDamage = 14f;
lifetime = 60f; lifetime = 60f;
trailColor = Pal.unitBack; trailColor = Pal.unitBack;
backColor = Pal.unitBack; backColor = Pal.unitBack;
@@ -1251,8 +1252,8 @@ public class UnitTypes implements ContentList{
mineTier = 3; mineTier = 3;
mineSpeed = 4f; mineSpeed = 4f;
health = 500; health = 460;
armor = 5f; armor = 3f;
speed = 2.5f; speed = 2.5f;
accel = 0.06f; accel = 0.06f;
drag = 0.017f; drag = 0.017f;
@@ -1264,6 +1265,7 @@ public class UnitTypes implements ContentList{
engineSize = 3f; engineSize = 3f;
payloadCapacity = (2 * 2) * tilePayload; payloadCapacity = (2 * 2) * tilePayload;
buildSpeed = 2.6f; buildSpeed = 2.6f;
isCounted = false;
ammoType = AmmoTypes.power; ammoType = AmmoTypes.power;
@@ -1274,7 +1276,13 @@ public class UnitTypes implements ContentList{
x = 8f; x = 8f;
y = -6f; y = -6f;
rotate = true; rotate = true;
bullet = Bullets.healBulletBig; bullet = new LaserBoltBulletType(5.2f, 10){{
lifetime = 35f;
healPercent = 5.5f;
collidesTeam = true;
backColor = Pal.heal;
frontColor = Color.white;
}};
}}, }},
new Weapon("heal-weapon-mount"){{ new Weapon("heal-weapon-mount"){{
shootSound = Sounds.lasershoot; shootSound = Sounds.lasershoot;
@@ -1282,7 +1290,13 @@ public class UnitTypes implements ContentList{
x = 4f; x = 4f;
y = 5f; y = 5f;
rotate = true; rotate = true;
bullet = Bullets.healBullet; bullet = new LaserBoltBulletType(5.2f, 8){{
lifetime = 35f;
healPercent = 3f;
collidesTeam = true;
backColor = Pal.heal;
frontColor = Color.white;
}};
}}); }});
}}; }};
@@ -1349,7 +1363,7 @@ public class UnitTypes implements ContentList{
collides = false; collides = false;
healPercent = 15f; healPercent = 15f;
splashDamage = 240f; splashDamage = 230f;
splashDamageRadius = 120f; splashDamageRadius = 120f;
}}; }};
}}); }});

View File

@@ -53,10 +53,11 @@ public class Weathers implements ContentList{
baseSpeed = 5.4f; baseSpeed = 5.4f;
attrs.set(Attribute.light, -0.1f); attrs.set(Attribute.light, -0.1f);
attrs.set(Attribute.water, -0.1f); attrs.set(Attribute.water, -0.1f);
opacityMultiplier = 0.5f; opacityMultiplier = 0.35f;
force = 0.1f; force = 0.1f;
sound = Sounds.wind; sound = Sounds.wind;
soundVol = 0.3f; soundVol = 0.8f;
duration = 7f * Time.toMinutes;
}}; }};
sporestorm = new ParticleWeather("sporestorm"){{ sporestorm = new ParticleWeather("sporestorm"){{
@@ -77,7 +78,8 @@ public class Weathers implements ContentList{
opacityMultiplier = 0.75f; opacityMultiplier = 0.75f;
force = 0.1f; force = 0.1f;
sound = Sounds.wind; sound = Sounds.wind;
soundVol = 0.3f; soundVol = 0.7f;
duration = 7f * Time.toMinutes;
}}; }};
fog = new ParticleWeather("fog"){{ fog = new ParticleWeather("fog"){{

View File

@@ -334,10 +334,29 @@ public class Control implements ApplicationListener, Loadable{
state.wave = 1; state.wave = 1;
//set up default wave time //set up default wave time
state.wavetime = state.rules.waveSpacing * 2f; state.wavetime = state.rules.waveSpacing * 2f;
//reset captured state
sector.info.wasCaptured = false;
//re-enable waves
state.rules.waves = true;
//reset win wave?? //reset win wave??
state.rules.winWave = state.rules.attackMode ? -1 : sector.preset != null ? sector.preset.captureWave : 40; state.rules.winWave = state.rules.attackMode ? -1 : sector.preset != null ? sector.preset.captureWave : 40;
//if there's still an enemy base left, fix it
if(state.rules.attackMode){
//replace all broken blocks
for(var plan : state.rules.waveTeam.data().blocks){
Tile tile = world.tile(plan.x, plan.y);
if(tile != null){
tile.setBlock(content.block(plan.block), state.rules.waveTeam, plan.rotation);
if(plan.config != null && tile.build != null){
tile.build.configure(plan.config);
}
}
}
state.rules.waveTeam.data().blocks.clear();
}
//kill all units, since they should be dead anyway //kill all units, since they should be dead anyway
Groups.unit.clear(); Groups.unit.clear();
Groups.fire.clear(); Groups.fire.clear();

View File

@@ -109,6 +109,13 @@ public class Logic implements ApplicationListener{
} }
state.rules.waveTeam.rules().aiTier = state.getSector().threat * 0.8f; state.rules.waveTeam.rules().aiTier = state.getSector().threat * 0.8f;
state.rules.waveTeam.rules().infiniteResources = true; state.rules.waveTeam.rules().infiniteResources = true;
//fill enemy cores by default.
for(var core : state.rules.waveTeam.cores()){
for(Item item : content.items()){
core.items.set(item, core.block.itemCapacity);
}
}
} }
//save settings //save settings
@@ -128,8 +135,8 @@ public class Logic implements ApplicationListener{
//convert all blocks to neutral, randomly killing them //convert all blocks to neutral, randomly killing them
if(tile.isCenter() && tile.build != null && tile.build.team == state.rules.waveTeam){ if(tile.isCenter() && tile.build != null && tile.build.team == state.rules.waveTeam){
Building b = tile.build; Building b = tile.build;
Call.setTeam(b, Team.derelict);
Time.run(Mathf.random(0f, 60f * 6f), () -> { Time.run(Mathf.random(0f, 60f * 6f), () -> {
Call.setTeam(b, Team.derelict);
if(Mathf.chance(0.25)){ if(Mathf.chance(0.25)){
b.kill(); b.kill();
} }
@@ -260,6 +267,8 @@ public class Logic implements ApplicationListener{
if(state.rules.sector == null) return; if(state.rules.sector == null) return;
state.rules.sector.info.wasCaptured = true;
//fire capture event //fire capture event
Events.fire(new SectorCaptureEvent(state.rules.sector)); Events.fire(new SectorCaptureEvent(state.rules.sector));

View File

@@ -41,7 +41,7 @@ public class NetClient implements ApplicationListener{
private boolean connecting = false; private boolean connecting = false;
/** If true, no message will be shown on disconnect. */ /** If true, no message will be shown on disconnect. */
private boolean quiet = false; private boolean quiet = false;
/** Whether to supress disconnect events completely.*/ /** Whether to suppress disconnect events completely.*/
private boolean quietReset = false; private boolean quietReset = false;
/** Counter for data timeout. */ /** Counter for data timeout. */
private float timeoutTime = 0f; private float timeoutTime = 0f;
@@ -258,6 +258,11 @@ public class NetClient implements ApplicationListener{
netClient.disconnectQuietly(); netClient.disconnectQuietly();
logic.reset(); logic.reset();
if(reason == KickReason.serverRestarting){
ui.join.reconnect();
return;
}
if(!reason.quiet){ if(!reason.quiet){
if(reason.extraText() != null){ if(reason.extraText() != null){
ui.showText(reason.toString(), reason.extraText()); ui.showText(reason.toString(), reason.extraText());

View File

@@ -422,7 +422,7 @@ public class NetServer implements ApplicationListener{
currentlyKicking[0] = session; currentlyKicking[0] = session;
} }
}else{ }else{
player.sendMessage("[scarlet]No player[orange]'" + args[0] + "'[scarlet] found."); player.sendMessage("[scarlet]No player [orange]'" + args[0] + "'[scarlet] found.");
} }
} }
}); });
@@ -447,6 +447,11 @@ public class NetServer implements ApplicationListener{
return; return;
} }
if(currentlyKicking[0].target.team() != player.team()){
player.sendMessage("[scarlet]You can't vote for other teams.");
return;
}
if(!arg[0].toLowerCase().equals("y") && !arg[0].toLowerCase().equals("n")){ if(!arg[0].toLowerCase().equals("y") && !arg[0].toLowerCase().equals("n")){
player.sendMessage("[scarlet]Vote either 'y' (yes) or 'n' (no)."); player.sendMessage("[scarlet]Vote either 'y' (yes) or 'n' (no).");
return; return;

View File

@@ -311,7 +311,7 @@ public class World{
//TODO bad code //TODO bad code
boolean hasSnow = floors[0].name.contains("ice") || floors[0].name.contains("snow"); boolean hasSnow = floors[0].name.contains("ice") || floors[0].name.contains("snow");
boolean hasRain = !hasSnow && content.contains(Liquids.water) && !floors[0].name.contains("sand"); boolean hasRain = !hasSnow && content.contains(Liquids.water) && !floors[0].name.contains("sand");
boolean hasDesert = !hasSnow && !hasRain && floors[0].name.contains("sand"); boolean hasDesert = !hasSnow && !hasRain && floors[0] == Blocks.sand;
boolean hasSpores = floors[0].name.contains("spore") || floors[0].name.contains("moss") || floors[0].name.contains("tainted"); boolean hasSpores = floors[0].name.contains("spore") || floors[0].name.contains("moss") || floors[0].name.contains("tainted");
if(hasSnow){ if(hasSnow){

View File

@@ -31,7 +31,7 @@ public abstract class Content implements Comparable<Content>, Disposable{
*/ */
public void load(){} public void load(){}
/** @return whether an error ocurred during mod loading. */ /** @return whether an error occurred during mod loading. */
public boolean hasErrored(){ public boolean hasErrored(){
return minfo.error != null; return minfo.error != null;
} }

View File

@@ -110,7 +110,7 @@ public abstract class UnlockableContent extends MappableContent{
/** Makes this piece of content unlocked; if it already unlocked, nothing happens. */ /** Makes this piece of content unlocked; if it already unlocked, nothing happens. */
public void unlock(){ public void unlock(){
if(!unlocked()){ if(!net.client() && !unlocked()){
unlocked = true; unlocked = true;
Core.settings.put(name + "-unlocked", true); Core.settings.put(name + "-unlocked", true);

View File

@@ -17,7 +17,7 @@ import mindustry.ui.*;
public class WaveGraph extends Table{ public class WaveGraph extends Table{
public Seq<SpawnGroup> groups = new Seq<>(); public Seq<SpawnGroup> groups = new Seq<>();
public int from, to = 20; public int from = 0, to = 20;
private Mode mode = Mode.counts; private Mode mode = Mode.counts;
private int[][] values; private int[][] values;
@@ -114,7 +114,7 @@ public class WaveGraph extends Table{
Lines.line(cx, cy, cx, cy + len); Lines.line(cx, cy, cx, cy + len);
if(i == values.length/2){ if(i == values.length/2){
font.draw("" + (i + from), cx, cy - 2f, Align.center); font.draw("" + (i + from + 1), cx, cy - 2f, Align.center);
} }
} }
font.setColor(Color.white); font.setColor(Color.white);

View File

@@ -2,7 +2,6 @@ package mindustry.entities;
import arc.*; import arc.*;
import arc.func.*; import arc.func.*;
import arc.graphics.*;
import arc.math.*; import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.struct.*; import arc.struct.*;
@@ -33,15 +32,22 @@ public class Damage{
private static Unit tmpUnit; private static Unit tmpUnit;
/** Creates a dynamic explosion based on specified parameters. */ /** Creates a dynamic explosion based on specified parameters. */
public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, Color color, boolean damage){ public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, boolean damage){
dynamicExplosion(x, y, flammability, explosiveness, power, radius, damage, true, null);
}
/** Creates a dynamic explosion based on specified parameters. */
public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, boolean damage, boolean fire, @Nullable Team ignoreTeam){
if(damage){ if(damage){
for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i++){ for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i++){
int branches = 5 + Mathf.clamp((int)(power / 30), 1, 20); int branches = 5 + Mathf.clamp((int)(power / 30), 1, 20);
Time.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.derelict, Pal.power, 3, x, y, Mathf.random(360f), branches + Mathf.range(2))); Time.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.derelict, Pal.power, 3, x, y, Mathf.random(360f), branches + Mathf.range(2)));
} }
for(int i = 0; i < Mathf.clamp(flammability / 4, 0, 30); i++){ if(fire){
Time.run(i / 2f, () -> Call.createBullet(Bullets.fireball, Team.derelict, x, y, Mathf.random(360f), Bullets.fireball.damage, 1, 1)); for(int i = 0; i < Mathf.clamp(flammability / 4, 0, 30); i++){
Time.run(i / 2f, () -> Call.createBullet(Bullets.fireball, Team.derelict, x, y, Mathf.random(360f), Bullets.fireball.damage, 1, 1));
}
} }
int waves = Mathf.clamp((int)(explosiveness / 4), 0, 30); int waves = Mathf.clamp((int)(explosiveness / 4), 0, 30);
@@ -49,7 +55,7 @@ public class Damage{
for(int i = 0; i < waves; i++){ for(int i = 0; i < waves; i++){
int f = i; int f = i;
Time.run(i * 2f, () -> { Time.run(i * 2f, () -> {
Damage.damage(x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 2f); Damage.damage(ignoreTeam, x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 2f, false);
Fx.blockExplosionSmoke.at(x + Mathf.range(radius), y + Mathf.range(radius)); Fx.blockExplosionSmoke.at(x + Mathf.range(radius), y + Mathf.range(radius));
}); });
} }

View File

@@ -15,7 +15,7 @@ public class Fires{
private static final float baseLifetime = 1000f; private static final float baseLifetime = 1000f;
private static final IntMap<Fire> map = new IntMap<>(); private static final IntMap<Fire> map = new IntMap<>();
/** Start a fire on the tile. If there already is a file there, refreshes its lifetime. */ /** Start a fire on the tile. If there already is a fire there, refreshes its lifetime. */
public static void create(Tile tile){ public static void create(Tile tile){
if(net.client() || tile == null || !state.rules.fire) return; //not clientside. if(net.client() || tile == null || !state.rules.fire) return; //not clientside.

View File

@@ -53,7 +53,7 @@ public class Lightning{
world.raycastEach(World.toTile(from.getX()), World.toTile(from.getY()), World.toTile(to.getX()), World.toTile(to.getY()), (wx, wy) -> { world.raycastEach(World.toTile(from.getX()), World.toTile(from.getY()), World.toTile(to.getX()), World.toTile(to.getY()), (wx, wy) -> {
Tile tile = world.tile(wx, wy); Tile tile = world.tile(wx, wy);
if(tile != null && tile.block().insulated){ if(tile != null && tile.block().insulated && tile.team() != team){
bhit = true; bhit = true;
//snap it instead of removing //snap it instead of removing
lines.get(lines.size -1).set(wx * tilesize, wy * tilesize); lines.get(lines.size -1).set(wx * tilesize, wy * tilesize);

View File

@@ -273,7 +273,8 @@ public abstract class BulletType extends Content{
} }
if(weaveMag > 0){ if(weaveMag > 0){
b.vel.rotate(Mathf.sin(Mathf.randomSeed(b.id, 10f) + b.time, weaveScale, weaveMag) * Time.delta); float scl = Mathf.randomSeed(id, 0.9f, 1.1f);
b.vel.rotate(Mathf.sin(b.time + Mathf.PI * weaveScale/2f * scl, weaveScale * scl, weaveMag) * Time.delta);
} }
if(trailChance > 0){ if(trailChance > 0){

View File

@@ -16,11 +16,13 @@ abstract class BoundedComp implements Velc, Posc, Healthc, Flyingc{
@Override @Override
public void update(){ public void update(){
//repel unit out of bounds if(!net.client() || isLocal()){
if(x < 0) vel.x += (-x/warpDst); //repel unit out of bounds
if(y < 0) vel.y += (-y/warpDst); if(x < 0) vel.x += (-x/warpDst);
if(x > world.unitWidth()) vel.x -= (x - world.unitWidth())/warpDst; if(y < 0) vel.y += (-y/warpDst);
if(y > world.unitHeight()) vel.y -= (y - world.unitHeight())/warpDst; if(x > world.unitWidth()) vel.x -= (x - world.unitWidth())/warpDst;
if(y > world.unitHeight()) vel.y -= (y - world.unitHeight())/warpDst;
}
//clamp position if not flying //clamp position if not flying
if(isGrounded()){ if(isGrounded()){

View File

@@ -11,6 +11,7 @@ import mindustry.annotations.Annotations.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.entities.units.*; import mindustry.entities.units.*;
import mindustry.game.EventType.*; import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.type.*; import mindustry.type.*;
@@ -28,6 +29,7 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
@Import float x, y, rotation; @Import float x, y, rotation;
@Import UnitType type; @Import UnitType type;
@Import Team team;
@SyncLocal Queue<BuildPlan> plans = new Queue<>(1); @SyncLocal Queue<BuildPlan> plans = new Queue<>(1);
@SyncLocal transient boolean updateBuilding = true; @SyncLocal transient boolean updateBuilding = true;
@@ -75,27 +77,27 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
Tile tile = world.tile(current.x, current.y); Tile tile = world.tile(current.x, current.y);
if(!(tile.block() instanceof ConstructBlock)){ if(!(tile.block() instanceof ConstructBlock)){
if(!current.initialized && !current.breaking && Build.validPlace(current.block, team(), current.x, current.y, current.rotation)){ if(!current.initialized && !current.breaking && Build.validPlace(current.block, team, current.x, current.y, current.rotation)){
boolean hasAll = infinite || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item)); boolean hasAll = infinite || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item));
if(hasAll){ if(hasAll){
Call.beginPlace(current.block, team(), current.x, current.y, current.rotation); Call.beginPlace(self(), current.block, team, current.x, current.y, current.rotation);
}else{ }else{
current.stuck = true; current.stuck = true;
} }
}else if(!current.initialized && current.breaking && Build.validBreak(team(), current.x, current.y)){ }else if(!current.initialized && current.breaking && Build.validBreak(team, current.x, current.y)){
Call.beginBreak(team(), current.x, current.y); Call.beginBreak(self(), team, current.x, current.y);
}else{ }else{
plans.removeFirst(); plans.removeFirst();
return; return;
} }
}else if(tile.team() != team()){ }else if(tile.team() != team){
plans.removeFirst(); plans.removeFirst();
return; return;
} }
if(tile.build instanceof ConstructBuild && !current.initialized){ if(tile.build instanceof ConstructBuild && !current.initialized){
Core.app.post(() -> Events.fire(new BuildSelectEvent(tile, team(), (Builderc)this, current.breaking))); Core.app.post(() -> Events.fire(new BuildSelectEvent(tile, team, (Builderc)this, current.breaking)));
current.initialized = true; current.initialized = true;
} }
@@ -128,7 +130,7 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
control.input.drawBreaking(request); control.input.drawBreaking(request);
}else{ }else{
request.block.drawRequest(request, control.input.allRequests(), request.block.drawRequest(request, control.input.allRequests(),
Build.validPlace(request.block, team(), request.x, request.y, request.rotation) || control.input.requestMatches(request)); Build.validPlace(request.block, team, request.x, request.y, request.rotation) || control.input.requestMatches(request));
} }
} }
@@ -138,7 +140,7 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
/** @return whether this request should be skipped, in favor of the next one. */ /** @return whether this request should be skipped, in favor of the next one. */
boolean shouldSkip(BuildPlan request, @Nullable Building core){ boolean shouldSkip(BuildPlan request, @Nullable Building core){
//requests that you have at least *started* are considered //requests that you have at least *started* are considered
if(state.rules.infiniteResources || team().rules().infiniteResources || request.breaking || core == null) return false; if(state.rules.infiniteResources || team.rules().infiniteResources || request.breaking || core == null) return false;
return (request.stuck && !core.items.has(request.block.requirements)) || (Structs.contains(request.block.requirements, i -> !core.items.has(i.item) && Mathf.round(i.amount * state.rules.buildCostMultiplier) > 0) && !request.initialized); return (request.stuck && !core.items.has(request.block.requirements)) || (Structs.contains(request.block.requirements, i -> !core.items.has(i.item) && Mathf.round(i.amount * state.rules.buildCostMultiplier) > 0) && !request.initialized);
} }

View File

@@ -14,6 +14,7 @@ import arc.scene.ui.layout.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
import arc.util.io.*; import arc.util.io.*;
import mindustry.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.audio.*; import mindustry.audio.*;
import mindustry.content.*; import mindustry.content.*;
@@ -29,8 +30,8 @@ import mindustry.logic.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.ui.*; import mindustry.ui.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.*;
import mindustry.world.blocks.ConstructBlock.*; import mindustry.world.blocks.ConstructBlock.*;
import mindustry.world.blocks.*;
import mindustry.world.blocks.environment.*; import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.payloads.*; import mindustry.world.blocks.payloads.*;
import mindustry.world.blocks.power.*; import mindustry.world.blocks.power.*;
@@ -435,7 +436,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
} }
/** Handle a stack input. */ /** Handle a stack input. */
public void handleStack(Item item, int amount, Teamc source){ public void handleStack(Item item, int amount, @Nullable Teamc source){
noSleep(); noSleep();
items.add(item, amount); items.add(item, amount);
} }
@@ -519,6 +520,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
public void dumpLiquid(Liquid liquid){ public void dumpLiquid(Liquid liquid){
int dump = this.cdump; int dump = this.cdump;
if(liquids.get(liquid) <= 0.0001f) return;
if(!net.client() && state.isCampaign() && team == state.rules.defaultTeam) liquid.unlock(); if(!net.client() && state.isCampaign() && team == state.rules.defaultTeam) liquid.unlock();
for(int i = 0; i < proximity.size; i++){ for(int i = 0; i < proximity.size; i++){
@@ -619,6 +622,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
* containers, it gets added to the block's inventory. * containers, it gets added to the block's inventory.
*/ */
public void offload(Item item){ public void offload(Item item){
produced(item, 1);
int dump = this.cdump; int dump = this.cdump;
if(!net.client() && state.isCampaign() && team == state.rules.defaultTeam) item.unlock(); if(!net.client() && state.isCampaign() && team == state.rules.defaultTeam) item.unlock();
@@ -652,6 +656,14 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
return false; return false;
} }
public void produced(Item item){
produced(item, 1);
}
public void produced(Item item, int amount){
if(Vars.state.rules.sector != null && team == state.rules.defaultTeam) Vars.state.rules.sector.info.handleProduction(item, amount);
}
/** Try dumping any item near the */ /** Try dumping any item near the */
public boolean dump(){ public boolean dump(){
return dump(null); return dump(null);
@@ -970,34 +982,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}); });
} }
Damage.dynamicExplosion(x, y, flammability, explosiveness * 3.5f, power, tilesize * block.size / 2f, Pal.darkFlame, state.rules.damageExplosions); Damage.dynamicExplosion(x, y, flammability, explosiveness * 3.5f, power, tilesize * block.size / 2f, state.rules.damageExplosions);
if(!floor().solid && !floor().isLiquid){ if(!floor().solid && !floor().isLiquid){
Effect.rubble(x, y, block.size); Effect.rubble(x, y, block.size);
} }
} }
/**
* Returns the flammability of the Used for fire calculations.
* Takes flammability of floor liquid into account.
*/
public float getFlammability(){
if(!block.hasItems){
if(floor().isLiquid && !block.solid){
return floor().liquidDrop.flammability;
}
return 0;
}else{
float result = items.sum((item, amount) -> item.flammability * amount);
if(block.hasLiquids){
result += liquids.sum((liquid, amount) -> liquid.flammability * amount / 3f);
}
return result;
}
}
public String getDisplayName(){ public String getDisplayName(){
return block.localizedName; return block.localizedName;
} }

View File

@@ -26,7 +26,7 @@ abstract class FireComp implements Timedc, Posc, Firec, Syncc{
@Override @Override
public void update(){ public void update(){
if(Mathf.chance(0.1 * Time.delta)){ if(Mathf.chance(0.09 * Time.delta)){
Fx.fire.at(x + Mathf.range(4f), y + Mathf.range(4f)); Fx.fire.at(x + Mathf.range(4f), y + Mathf.range(4f));
} }
@@ -59,7 +59,7 @@ abstract class FireComp implements Timedc, Posc, Firec, Syncc{
} }
if(baseFlammability < 0 || block != tile.block()){ if(baseFlammability < 0 || block != tile.block()){
baseFlammability = tile.build == null ? 0 : tile.build.getFlammability(); baseFlammability = tile.build == null ? 0 : tile.getFlammability();
block = tile.block(); block = tile.block();
} }
@@ -77,12 +77,12 @@ abstract class FireComp implements Timedc, Posc, Firec, Syncc{
} }
} }
if(Mathf.chance(0.1 * Time.delta)){ if(Mathf.chance(0.025 * Time.delta)){
Puddlec p = Puddles.get(tile); Puddlec p = Puddles.get(tile);
puddleFlammability = p != null ? p.getFlammability() / 3f : 0; puddleFlammability = p != null ? p.getFlammability() / 3f : 0;
if(damage){ if(damage){
entity.damage(0.4f); entity.damage(1.6f);
} }
Damage.damageUnits(null, tile.worldx(), tile.worldy(), tilesize, 3f, Damage.damageUnits(null, tile.worldx(), tile.worldy(), tilesize, 3f,
unit -> !unit.isFlying() && !unit.isImmune(StatusEffects.burning), unit -> !unit.isFlying() && !unit.isImmune(StatusEffects.burning),

View File

@@ -46,8 +46,8 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{
} }
void wobble(){ void wobble(){
x += Mathf.sin(Time.time() + id() * 99, 25f, 0.05f) * Time.delta * elevation; x += Mathf.sin(Time.time() + (id() % 10) * 12, 25f, 0.05f) * Time.delta * elevation;
y += Mathf.cos(Time.time() + id() * 99, 25f, 0.05f) * Time.delta * elevation; y += Mathf.cos(Time.time() + (id() % 10) * 12, 25f, 0.05f) * Time.delta * elevation;
} }
void moveAt(Vec2 vector, float acceleration){ void moveAt(Vec2 vector, float acceleration){

View File

@@ -55,7 +55,7 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{
if(core != null && mineTile != null && mineTile.drop() != null && !acceptsItem(mineTile.drop()) && within(core, mineTransferRange) && !offloadImmediately()){ if(core != null && mineTile != null && mineTile.drop() != null && !acceptsItem(mineTile.drop()) && within(core, mineTransferRange) && !offloadImmediately()){
int accepted = core.acceptStack(item(), stack().amount, this); int accepted = core.acceptStack(item(), stack().amount, this);
if(accepted > 0){ if(accepted > 0){
Call.transferItemTo(item(), accepted, Call.transferItemTo(self(), item(), accepted,
mineTile.worldx() + Mathf.range(tilesize / 2f), mineTile.worldx() + Mathf.range(tilesize / 2f),
mineTile.worldy() + Mathf.range(tilesize / 2f), core); mineTile.worldy() + Mathf.range(tilesize / 2f), core);
clearItem(); clearItem();
@@ -76,8 +76,12 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{
if(mineTimer >= 50f + item.hardness*15f){ if(mineTimer >= 50f + item.hardness*15f){
mineTimer = 0; mineTimer = 0;
if(state.rules.sector != null && team() == state.rules.defaultTeam) state.rules.sector.info.handleProduction(item, 1);
if(core != null && within(core, mineTransferRange) && core.acceptStack(item, 1, this) == 1 && offloadImmediately()){ if(core != null && within(core, mineTransferRange) && core.acceptStack(item, 1, this) == 1 && offloadImmediately()){
Call.transferItemTo(item, 1, //add item to inventory before it is transferred
if(item() == item) addItem(item);
Call.transferItemTo(self(), item, 1,
mineTile.worldx() + Mathf.range(tilesize / 2f), mineTile.worldx() + Mathf.range(tilesize / 2f),
mineTile.worldy() + Mathf.range(tilesize / 2f), core); mineTile.worldy() + Mathf.range(tilesize / 2f), core);
}else if(acceptsItem(item)){ }else if(acceptsItem(item)){

View File

@@ -310,7 +310,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f); drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f);
//apply knockback based on spawns //apply knockback based on spawns
if(team != state.rules.waveTeam && state.hasSpawns()){ if(team != state.rules.waveTeam && state.hasSpawns() && (!net.client() || isLocal())){
float relativeSize = state.rules.dropZoneRadius + hitSize/2f + 1f; float relativeSize = state.rules.dropZoneRadius + hitSize/2f + 1f;
for(Tile spawn : spawner.getSpawns()){ for(Tile spawn : spawner.getSpawns()){
if(within(spawn.worldx(), spawn.worldy(), relativeSize)){ if(within(spawn.worldx(), spawn.worldy(), relativeSize)){
@@ -397,9 +397,12 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
/** Actually destroys the unit, removing it and creating explosions. **/ /** Actually destroys the unit, removing it and creating explosions. **/
public void destroy(){ public void destroy(){
float explosiveness = 2f + item().explosiveness * stack().amount / 2.4f; float explosiveness = 2f + item().explosiveness * stack().amount * 1.53f;
float flammability = item().flammability * stack().amount / 2.4f; float flammability = item().flammability * stack().amount / 1.9f;
Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, Pal.darkFlame, state.rules.damageExplosions);
if(!spawnedByCore){
Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, state.rules.damageExplosions, item().flammability > 1, team);
}
float shake = hitSize / 3f; float shake = hitSize / 3f;
@@ -415,7 +418,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
} }
//if this unit crash landed (was flying), damage stuff in a radius //if this unit crash landed (was flying), damage stuff in a radius
if(type.flying){ if(type.flying && !spawnedByCore){
Damage.damage(team,x, y, Mathf.pow(hitSize, 0.94f) * 1.25f, Mathf.pow(hitSize, 0.75f) * type.crashDamageMultiplier * 5f, true, false, true); Damage.damage(team,x, y, Mathf.pow(hitSize, 0.94f) * 1.25f, Mathf.pow(hitSize, 0.75f) * type.crashDamageMultiplier * 5f, true, false, true);
} }

View File

@@ -91,6 +91,10 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc, Velc, Statusc{
mount.bullet.time = mount.bullet.lifetime - 10f; mount.bullet.time = mount.bullet.lifetime - 10f;
mount.bullet = null; mount.bullet = null;
} }
if(mount.sound != null){
mount.sound.stop();
}
} }
} }

View File

@@ -18,6 +18,7 @@ public class EventType{
impactPower, impactPower,
thoriumReactorOverheat, thoriumReactorOverheat,
fireExtinguish, fireExtinguish,
acceleratorUse,
newGame, newGame,
tutorialComplete, tutorialComplete,
flameAmmo, flameAmmo,

View File

@@ -59,7 +59,7 @@ public class Objectives{
@Override @Override
public boolean complete(){ public boolean complete(){
return preset.sector.save != null && !preset.sector.isAttacked() && preset.sector.hasBase(); return preset.sector.save != null && (!preset.sector.isAttacked() || preset.sector.info.wasCaptured) && preset.sector.hasBase();
} }
@Override @Override

View File

@@ -23,6 +23,8 @@ public class SectorInfo{
/** Core input statistics. */ /** Core input statistics. */
public ObjectMap<Item, ExportStat> production = new ObjectMap<>(); public ObjectMap<Item, ExportStat> production = new ObjectMap<>();
/** Raw item production statistics. */
public ObjectMap<Item, ExportStat> rawProduction = new ObjectMap<>();
/** Export statistics. */ /** Export statistics. */
public ObjectMap<Item, ExportStat> export = new ObjectMap<>(); public ObjectMap<Item, ExportStat> export = new ObjectMap<>();
/** Items stored in all cores. */ /** Items stored in all cores. */
@@ -33,6 +35,8 @@ public class SectorInfo{
public int storageCapacity = 0; public int storageCapacity = 0;
/** Whether a core is available here. */ /** Whether a core is available here. */
public boolean hasCore = true; public boolean hasCore = true;
/** Whether this sector was ever fully captured. */
public boolean wasCaptured = false;
/** Sector that was launched from. */ /** Sector that was launched from. */
public @Nullable Sector origin; public @Nullable Sector origin;
/** Launch destination. */ /** Launch destination. */
@@ -69,19 +73,27 @@ public class SectorInfo{
public boolean shown = false; public boolean shown = false;
/** Special variables for simulation. */ /** Special variables for simulation. */
public float sumHealth, sumRps, sumDps, waveHealthBase, waveHealthSlope, waveDpsBase, waveDpsSlope; public float sumHealth, sumRps, sumDps, waveHealthBase, waveHealthSlope, waveDpsBase, waveDpsSlope, bossHealth, bossDps;
/** Wave where first boss shows up. */
public int bossWave = -1;
/** Counter refresh state. */ /** Counter refresh state. */
private transient Interval time = new Interval(); private transient Interval time = new Interval();
/** Core item storage to prevent spoofing. */ /** Core item storage input/output deltas. */
private transient int[] coreItemCounts; private @Nullable transient int[] coreDeltas;
/** Core item storage input/output deltas. */
private @Nullable transient int[] productionDeltas;
/** Handles core item changes. */ /** Handles core item changes. */
public void handleCoreItem(Item item, int amount){ public void handleCoreItem(Item item, int amount){
if(coreItemCounts == null){ if(coreDeltas == null) coreDeltas = new int[content.items().size];
coreItemCounts = new int[content.items().size]; coreDeltas[item.id] += amount;
} }
coreItemCounts[item.id] += amount;
/** Handles raw production stats. */
public void handleProduction(Item item, int amount){
if(productionDeltas == null) productionDeltas = new int[content.items().size];
productionDeltas[item.id] += amount;
} }
/** @return the real location items go when launched on this sector */ /** @return the real location items go when launched on this sector */
@@ -172,6 +184,11 @@ public class SectorInfo{
damage = 0; damage = 0;
hasSpawns = spawner.countSpawns() > 0; hasSpawns = spawner.countSpawns() > 0;
//cap production at raw production.
production.each((item, stat) -> {
stat.mean = Math.min(stat.mean, rawProduction.get(item, ExportStat::new).mean);
});
if(state.rules.sector != null){ if(state.rules.sector != null){
state.rules.sector.saveInfo(); state.rules.sector.saveInfo();
} }
@@ -185,8 +202,6 @@ public class SectorInfo{
//updating in multiplayer as a client doesn't make sense //updating in multiplayer as a client doesn't make sense
if(net.client()) return; if(net.client()) return;
CoreBuild ent = state.rules.defaultTeam.core();
//refresh throughput //refresh throughput
if(time.get(refreshPeriod)){ if(time.get(refreshPeriod)){
@@ -204,30 +219,34 @@ public class SectorInfo{
stat.mean = stat.means.rawMean(); stat.mean = stat.means.rawMean();
}); });
if(coreItemCounts == null){ if(coreDeltas == null) coreDeltas = new int[content.items().size];
coreItemCounts = new int[content.items().size]; if(productionDeltas == null) productionDeltas = new int[content.items().size];
}
//refresh core items //refresh core items
for(Item item : content.items()){ for(Item item : content.items()){
ExportStat stat = production.get(item, ExportStat::new); updateDelta(item, production, coreDeltas);
if(!stat.loaded){ updateDelta(item, rawProduction, productionDeltas);
stat.means.fill(stat.mean);
stat.loaded = true;
}
//get item delta production.get(item).mean = Math.min(production.get(item).mean, rawProduction.get(item).mean);
int delta = coreItemCounts[item.id];
//store means
stat.means.add(delta);
stat.mean = stat.means.rawMean();
} }
Arrays.fill(coreItemCounts, 0); Arrays.fill(coreDeltas, 0);
Arrays.fill(productionDeltas, 0);
} }
} }
void updateDelta(Item item, ObjectMap<Item, ExportStat> map, int[] deltas){
ExportStat stat = map.get(item, ExportStat::new);
if(!stat.loaded){
stat.means.fill(stat.mean);
stat.loaded = true;
}
//store means
stat.means.add(deltas[item.id]);
stat.mean = stat.means.rawMean();
}
public ObjectFloatMap<Item> exportRates(){ public ObjectFloatMap<Item> exportRates(){
ObjectFloatMap<Item> map = new ObjectFloatMap<>(); ObjectFloatMap<Item> map = new ObjectFloatMap<>();
export.each((item, value) -> map.put(item, value.mean)); export.each((item, value) -> map.put(item, value.mean));

View File

@@ -6,7 +6,7 @@ import arc.struct.*;
import arc.util.*; import arc.util.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.game.EventType.*; import mindustry.game.EventType.*;
import mindustry.io.legacy.*; import mindustry.game.SectorInfo.*;
import mindustry.maps.*; import mindustry.maps.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.blocks.storage.*; import mindustry.world.blocks.storage.*;
@@ -27,13 +27,6 @@ public class Universe{
public Universe(){ public Universe(){
load(); load();
//load legacy research
Events.on(ClientLoadEvent.class, e -> {
if(Core.settings.has("unlocks")){
LegacyIO.readResearch();
}
});
//update base coverage on capture //update base coverage on capture
Events.on(SectorCaptureEvent.class, e -> { Events.on(SectorCaptureEvent.class, e -> {
if(!net.client() && state.isCampaign()){ if(!net.client() && state.isCampaign()){
@@ -188,6 +181,7 @@ public class Universe{
}else if(attacked && wavesPassed > 0 && sector.info.winWave > 1 && sector.info.wave + wavesPassed >= sector.info.winWave && !sector.hasEnemyBase()){ }else if(attacked && wavesPassed > 0 && sector.info.winWave > 1 && sector.info.wave + wavesPassed >= sector.info.winWave && !sector.hasEnemyBase()){
//autocapture the sector //autocapture the sector
sector.info.waves = false; sector.info.waves = false;
sector.info.wasCaptured = true;
//fire the event //fire the event
Events.fire(new SectorCaptureEvent(sector)); Events.fire(new SectorCaptureEvent(sector));
@@ -206,6 +200,13 @@ public class Universe{
} }
} }
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;
}
});
//add production, making sure that it's capped //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.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 //prevent negative values with unloaders

View File

@@ -96,18 +96,17 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
} }
@Remote(called = Loc.server, unreliable = true) @Remote(called = Loc.server, unreliable = true)
public static void transferItemTo(Item item, int amount, float x, float y, Building build){ public static void setItem(Building build, Item item, int amount){
if(build == null || build.items == null) return; if(build == null || build.items == null) return;
for(int i = 0; i < Mathf.clamp(amount / 5, 1, 8); i++){ build.items.set(item, amount);
Time.run(i * 3, () -> createItemTransfer(item, amount, x, y, build, () -> {}));
}
build.items.add(item, amount);
} }
@Remote(called = Loc.server, unreliable = true) @Remote(called = Loc.server, unreliable = true)
public static void transferItemTo(Unit unit, Item item, int amount, float x, float y, Building build){ public static void transferItemTo(@Nullable Unit unit, Item item, int amount, float x, float y, Building build){
if(build == null || build.items == null) return; if(build == null || build.items == null) return;
unit.stack.amount = Math.max(unit.stack.amount - amount, 0);
if(unit != null && unit.item() == item) unit.stack.amount = Math.max(unit.stack.amount - amount, 0);
for(int i = 0; i < Mathf.clamp(amount / 3, 1, 8); i++){ for(int i = 0; i < Mathf.clamp(amount / 3, 1, 8); i++){
Time.run(i * 3, () -> createItemTransfer(item, amount, x, y, build, () -> {})); Time.run(i * 3, () -> createItemTransfer(item, amount, x, y, build, () -> {}));
} }

View File

@@ -769,7 +769,7 @@ public class MobileInput extends InputHandler implements GestureListener{
@Override @Override
public boolean pan(float x, float y, float deltaX, float deltaY){ public boolean pan(float x, float y, float deltaX, float deltaY){
if(Core.scene.hasDialog() || Core.settings.getBool("keyboard")) return false; if(Core.scene == null || Core.scene.hasDialog() || Core.settings.getBool("keyboard")) return false;
float scale = Core.camera.width / Core.graphics.getWidth(); float scale = Core.camera.width / Core.graphics.getWidth();
deltaX *= scale; deltaX *= scale;

View File

@@ -286,7 +286,8 @@ public abstract class SaveVersion extends SaveFileReader{
public void writeEntities(DataOutput stream) throws IOException{ public void writeEntities(DataOutput stream) throws IOException{
//write team data with entities. //write team data with entities.
Seq<TeamData> data = state.teams.getActive().and(Team.sharded.data()); Seq<TeamData> data = state.teams.getActive().copy();
if(!data.contains(Team.sharded.data())) data.add(Team.sharded.data());
stream.writeInt(data.size); stream.writeInt(data.size);
for(TeamData team : data){ for(TeamData team : data){
stream.writeInt(team.team.id); stream.writeInt(team.team.id);
@@ -313,12 +314,23 @@ public abstract class SaveVersion extends SaveFileReader{
public void readEntities(DataInput stream) throws IOException{ public void readEntities(DataInput stream) throws IOException{
int teamc = stream.readInt(); int teamc = stream.readInt();
for(int i = 0; i < teamc; i++){ for(int i = 0; i < teamc; i++){
Team team = Team.get(stream.readInt()); Team team = Team.get(stream.readInt());
TeamData data = team.data(); TeamData data = team.data();
int blocks = stream.readInt(); int blocks = stream.readInt();
data.blocks.clear();
data.blocks.ensureCapacity(Math.min(blocks, 1000));
var reads = Reads.get(stream);
var set = new IntSet();
for(int j = 0; j < blocks; j++){ for(int j = 0; j < blocks; j++){
data.blocks.addLast(new BlockPlan(stream.readShort(), stream.readShort(), stream.readShort(), content.block(stream.readShort()).id, TypeIO.readObject(Reads.get(stream)))); short x = stream.readShort(), y = stream.readShort(), rot = stream.readShort(), bid = stream.readShort();
var obj = TypeIO.readObject(reads);
//cannot have two in the same position
if(set.add(Point2.pack(x, y))){
data.blocks.addLast(new BlockPlan(x, y, rot, content.block(bid).id, obj));
}
} }
} }

View File

@@ -14,7 +14,7 @@ import mindustry.world.*;
/** "Compiles" a sequence of statements into instructions. */ /** "Compiles" a sequence of statements into instructions. */
public class LAssembler{ public class LAssembler{
public static ObjectMap<String, Func<String[], LStatement>> customParsers = new ObjectMap<>(); public static ObjectMap<String, Func<String[], LStatement>> customParsers = new ObjectMap<>();
public static final int maxTokenLength = 40; public static final int maxTokenLength = 36;
private int lastVar; private int lastVar;
/** Maps names to variable IDs. */ /** Maps names to variable IDs. */

View File

@@ -68,6 +68,11 @@ public class SectorDamage{
float enemyDps = info.waveDpsBase + info.waveDpsSlope * (i); float enemyDps = info.waveDpsBase + info.waveDpsSlope * (i);
float enemyHealth = info.waveHealthBase + info.waveHealthSlope * (i); float enemyHealth = info.waveHealthBase + info.waveHealthSlope * (i);
if(info.bossWave == i){
enemyDps += info.bossDps;
enemyHealth += info.bossHealth;
}
//happens due to certain regressions //happens due to certain regressions
if(enemyHealth < 0 || enemyDps < 0) continue; if(enemyHealth < 0 || enemyDps < 0) continue;
@@ -305,6 +310,7 @@ public class SectorDamage{
//calculate DPS and health for the next few waves and store in list //calculate DPS and health for the next few waves and store in list
var reg = new LinearRegression(); var reg = new LinearRegression();
SpawnGroup bossGroup = null;
Seq<Vec2> waveDps = new Seq<>(), waveHealth = new Seq<>(); Seq<Vec2> waveDps = new Seq<>(), waveHealth = new Seq<>();
for(int wave = state.wave; wave < state.wave + 10; wave ++){ for(int wave = state.wave; wave < state.wave + 10; wave ++){
@@ -320,6 +326,11 @@ public class SectorDamage{
float healthMult = 1f + Mathf.clamp(group.type.armor / 20f); float healthMult = 1f + Mathf.clamp(group.type.armor / 20f);
StatusEffect effect = (group.effect == null ? StatusEffects.none : group.effect); StatusEffect effect = (group.effect == null ? StatusEffects.none : group.effect);
int spawned = group.getSpawned(wave); int spawned = group.getSpawned(wave);
//save the boss group
if(group.effect == StatusEffects.boss){
bossGroup = group;
continue;
}
if(spawned <= 0) continue; if(spawned <= 0) continue;
sumWaveHealth += spawned * (group.getShield(wave) + group.type.health * effect.healthMultiplier * healthMult); sumWaveHealth += spawned * (group.getShield(wave) + group.type.health * effect.healthMultiplier * healthMult);
sumWaveDps += spawned * group.type.dpsEstimate * effect.damageMultiplier; sumWaveDps += spawned * group.type.dpsEstimate * effect.damageMultiplier;
@@ -328,6 +339,21 @@ public class SectorDamage{
waveHealth.add(new Vec2(wave, sumWaveHealth)); waveHealth.add(new Vec2(wave, sumWaveHealth));
} }
if(bossGroup != null){
float bossMult = 1.1f;
//calculate first boss appearaance
for(int wave = state.wave; wave < state.wave + 60; wave++){
int spawned = bossGroup.getSpawned(wave - 1);
if(spawned > 0){
//set up relevant stats
info.bossWave = wave;
info.bossDps = spawned * bossGroup.type.dpsEstimate * StatusEffects.boss.damageMultiplier * bossMult;
info.bossHealth = spawned * (bossGroup.getShield(wave) + bossGroup.type.health * StatusEffects.boss.healthMultiplier * (1f + Mathf.clamp(bossGroup.type.armor / 20f))) * bossMult;
break;
}
}
}
//calculate linear regression of the wave data and store it //calculate linear regression of the wave data and store it
reg.calculate(waveHealth); reg.calculate(waveHealth);
info.waveHealthBase = reg.intercept; info.waveHealthBase = reg.intercept;
@@ -338,9 +364,9 @@ public class SectorDamage{
info.waveDpsSlope = reg.slope; info.waveDpsSlope = reg.slope;
//enemy units like to aim for a lot of non-essential things, so increase resulting health slightly //enemy units like to aim for a lot of non-essential things, so increase resulting health slightly
info.sumHealth = sumHealth * 1.2f; info.sumHealth = sumHealth * 1.05f;
//players tend to have longer range units/turrets, so assume DPS is higher //players tend to have longer range units/turrets, so assume DPS is higher
info.sumDps = sumDps * 1.2f; info.sumDps = sumDps * 1.05f;
info.sumRps = sumRps; info.sumRps = sumRps;
info.wavesSurvived = getWavesSurvived(info); info.wavesSurvived = getWavesSurvived(info);
@@ -356,7 +382,7 @@ public class SectorDamage{
for(Tile tile : tiles){ for(Tile tile : tiles){
if((tile.block() instanceof CoreBlock && tile.team() == state.rules.waveTeam) || tile.overlay() == Blocks.spawn){ if((tile.block() instanceof CoreBlock && tile.team() == state.rules.waveTeam) || tile.overlay() == Blocks.spawn){
frontier.add(tile); frontier.add(tile);
values[tile.x][tile.y] = fraction * 26; values[tile.x][tile.y] = fraction * 24;
} }
} }

View File

@@ -3,6 +3,8 @@ package mindustry.maps.planet;
import arc.graphics.*; import arc.graphics.*;
import arc.math.*; import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import mindustry.content.*;
import mindustry.game.*;
import mindustry.maps.generators.*; import mindustry.maps.generators.*;
public class TantrosPlanetGenerator extends PlanetGenerator{ public class TantrosPlanetGenerator extends PlanetGenerator{
@@ -18,4 +20,13 @@ public class TantrosPlanetGenerator extends PlanetGenerator{
float depth = (float)noise.octaveNoise3D(2, 0.56, 1.7f, position.x, position.y, position.z) / 2f; float depth = (float)noise.octaveNoise3D(2, 0.56, 1.7f, position.x, position.y, position.z) / 2f;
return c1.write(out).lerp(c2, Mathf.clamp(Mathf.round(depth, 0.15f))).a(0.6f); return c1.write(out).lerp(c2, Mathf.clamp(Mathf.round(depth, 0.15f))).a(0.6f);
} }
@Override
protected void generate(){
pass((x, y) -> {
floor = Blocks.deepwater;
});
Schematics.placeLaunchLoadout(width / 2, height / 2);
}
} }

View File

@@ -225,7 +225,7 @@ public class ContentParser{
currentContent = block; currentContent = block;
read(() -> { read(() -> {
if(value.has("consumes")){ if(value.has("consumes") && value.get("consumes").isObject()){
for(JsonValue child : value.get("consumes")){ for(JsonValue child : value.get("consumes")){
if(child.name.equals("item")){ if(child.name.equals("item")){
block.consumes.item(find(ContentType.item, child.asString())); block.consumes.item(find(ContentType.item, child.asString()));
@@ -309,6 +309,10 @@ public class ContentParser{
} }
if(value.has("controller")){
unit.defaultController = make(resolve(value.getString("controller"), "mindustry.ai.type"));
}
//read extra default waves //read extra default waves
if(value.has("waves")){ if(value.has("waves")){
JsonValue waves = value.remove("waves"); JsonValue waves = value.remove("waves");

View File

@@ -247,7 +247,7 @@ public class Mods implements Loadable{
mods.add(mod); mods.add(mod);
}catch(Throwable e){ }catch(Throwable e){
if(e instanceof ClassNotFoundException && e.getMessage().contains("mindustry.plugin.Plugin")){ if(e instanceof ClassNotFoundException && e.getMessage().contains("mindustry.plugin.Plugin")){
Log.info("Plugin @ is outdated and needs to be ported to 6.0! Update its main class to inherit from 'mindustry.mod.Plugin'."); Log.info("Plugin @ is outdated and needs to be ported to 6.0! Update its main class to inherit from 'mindustry.mod.Plugin'. See https://mindustrygame.github.io/wiki/modding/6-migrationv6/");
}else{ }else{
Log.err("Failed to load mod file @. Skipping.", file); Log.err("Failed to load mod file @. Skipping.", file);
Log.err(e); Log.err(e);
@@ -677,7 +677,7 @@ public class Mods implements Loadable{
public Seq<String> missingDependencies = new Seq<>(); public Seq<String> missingDependencies = new Seq<>();
/** Script files to run. */ /** Script files to run. */
public Seq<Fi> scripts = new Seq<>(); public Seq<Fi> scripts = new Seq<>();
/** Content with intialization code. */ /** Content with initialization code. */
public ObjectSet<Content> erroredContent = new ObjectSet<>(); public ObjectSet<Content> erroredContent = new ObjectSet<>();
/** Current state of this mod. */ /** Current state of this mod. */
public ModState state = ModState.enabled; public ModState state = ModState.enabled;
@@ -708,7 +708,7 @@ public class Mods implements Loadable{
return !erroredContent.isEmpty(); return !erroredContent.isEmpty();
} }
/** @return whether this mod is supported by the game verison */ /** @return whether this mod is supported by the game version */
public boolean isSupported(){ public boolean isSupported(){
if(isOutdated()) return false; if(isOutdated()) return false;

View File

@@ -13,7 +13,7 @@ import mindustry.io.*;
public class Weapon{ public class Weapon{
/** displayed weapon region */ /** displayed weapon region */
public String name; public String name = "";
/** bullet shot */ /** bullet shot */
public BulletType bullet; public BulletType bullet;
/** shell ejection effect */ /** shell ejection effect */

View File

@@ -19,9 +19,9 @@ import mindustry.world.blocks.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public abstract class Weather extends UnlockableContent{ public class Weather extends UnlockableContent{
/** Default duration of this weather event in ticks. */ /** Default duration of this weather event in ticks. */
public float duration = 9f * Time.toMinutes; public float duration = 10f * Time.toMinutes;
public float opacityMultiplier = 1f; public float opacityMultiplier = 1f;
public Attributes attrs = new Attributes(); public Attributes attrs = new Attributes();
public Sound sound = Sounds.none; public Sound sound = Sounds.none;
@@ -262,7 +262,7 @@ public abstract class Weather extends UnlockableContent{
/** Creates a weather entry with some approximate weather values. */ /** Creates a weather entry with some approximate weather values. */
public WeatherEntry(Weather weather){ public WeatherEntry(Weather weather){
this(weather, weather.duration * 3f, weather.duration * 6f, weather.duration / 2f, weather.duration * 1.5f); this(weather, weather.duration * 2f, weather.duration * 6f, weather.duration / 2f, weather.duration * 1.5f);
} }
public WeatherEntry(Weather weather, float minFrequency, float maxFrequency, float minDuration, float maxDuration){ public WeatherEntry(Weather weather, float minFrequency, float maxFrequency, float minDuration, float maxDuration){

View File

@@ -29,7 +29,11 @@ public class Bar extends Element{
public Bar(Prov<String> name, Prov<Color> color, Floatp fraction){ public Bar(Prov<String> name, Prov<Color> color, Floatp fraction){
this.fraction = fraction; this.fraction = fraction;
lastValue = value = Mathf.clamp(fraction.get()); try{
lastValue = value = Mathf.clamp(fraction.get());
}catch(Exception e){ //getting the fraction may involve referring to invalid data
lastValue = value = 0f;
}
update(() -> { update(() -> {
try{ try{
this.name = name.get(); this.name = name.get();
@@ -78,6 +82,9 @@ public class Bar extends Element{
lastValue = computed; lastValue = computed;
} }
if(Float.isNaN(computed)) computed = 0;
if(Float.isInfinite(computed)) computed = 1f;
blink = Mathf.lerpDelta(blink, 0f, 0.2f); blink = Mathf.lerpDelta(blink, 0f, 0.2f);
value = Mathf.lerpDelta(value, computed, 0.15f); value = Mathf.lerpDelta(value, computed, 0.15f);

View File

@@ -8,6 +8,7 @@ import arc.scene.ui.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
import arc.util.Timer.*;
import arc.util.serialization.*; import arc.util.serialization.*;
import mindustry.*; import mindustry.*;
import mindustry.core.*; import mindustry.core.*;
@@ -33,6 +34,10 @@ public class JoinDialog extends BaseDialog{
int refreshes; int refreshes;
boolean showHidden; boolean showHidden;
String lastIp;
int lastPort;
Task ping;
public JoinDialog(){ public JoinDialog(){
super("@joingame"); super("@joingame");
@@ -445,13 +450,34 @@ public class JoinDialog extends BaseDialog{
logic.reset(); logic.reset();
net.reset(); net.reset();
Vars.netClient.beginConnecting(); Vars.netClient.beginConnecting();
net.connect(ip, port, () -> { net.connect(lastIp = ip, lastPort = port, () -> {
hide(); hide();
add.hide(); add.hide();
}); });
}); });
} }
public void reconnect(){
if(lastIp == null || lastIp.isEmpty()) return;
ui.loadfrag.show("@reconnecting");
ping = Timer.schedule(() -> {
net.pingHost(lastIp, lastPort, host -> {
if(ping == null) return;
ping.cancel();
ping = null;
connect(lastIp, lastPort);
}, exception -> {});
}, 1, 1);
ui.loadfrag.setButton(() -> {
ui.loadfrag.hide();
if(ping == null) return;
ping.cancel();
ping = null;
});
}
void safeConnect(String ip, int port, int version){ void safeConnect(String ip, int port, int version){
if(version != Version.build && Version.build != -1 && version != -1){ if(version != Version.build && Version.build != -1 && version != -1){
ui.showInfo("[scarlet]" + (version > Version.build ? KickReason.clientOutdated : KickReason.serverOutdated).toString() + "\n[]" + ui.showInfo("[scarlet]" + (version > Version.build ? KickReason.clientOutdated : KickReason.serverOutdated).toString() + "\n[]" +

View File

@@ -23,6 +23,7 @@ import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.graphics.g3d.*; import mindustry.graphics.g3d.*;
import mindustry.input.*; import mindustry.input.*;
import mindustry.io.legacy.*;
import mindustry.maps.*; import mindustry.maps.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.ui.*; import mindustry.ui.*;
@@ -140,6 +141,14 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
return this; return this;
} }
//load legacy research
if(Core.settings.has("unlocks") && !Core.settings.has("junction-unlocked")){
Core.app.post(() -> {
ui.showCustomConfirm("@research", "@research.legacy", "@research.load", "@research.discard", LegacyIO::readResearch, () -> Core.settings.remove("unlocks"));
});
}
rebuildButtons();
mode = look; mode = look;
selected = hovered = launchSector = null; selected = hovered = launchSector = null;
launching = false; launching = false;
@@ -553,7 +562,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
if(t.getChildren().any()){ if(t.getChildren().any()){
c.add(name).left().row(); c.add(name).left().row();
c.add(t).padLeft(10f).row(); c.add(t).padLeft(10f).left().row();
} }
}; };
@@ -702,6 +711,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
stable.table(t -> { stable.table(t -> {
t.add("@sectors.resources").padRight(4); t.add("@sectors.resources").padRight(4);
for(UnlockableContent c : sector.info.resources){ for(UnlockableContent c : sector.info.resources){
if(c == null) continue; //apparently this is possible.
t.image(c.icon(Cicon.small)).padRight(3).size(Cicon.small.size); t.image(c.icon(Cicon.small)).padRight(3).size(Cicon.small.size);
} }
}).padLeft(10f).fillX().row(); }).padLeft(10f).fillX().row();

View File

@@ -20,7 +20,7 @@ public class Build{
private static final IntSet tmp = new IntSet(); private static final IntSet tmp = new IntSet();
@Remote(called = Loc.server) @Remote(called = Loc.server)
public static void beginBreak(Team team, int x, int y){ public static void beginBreak(@Nullable Unit unit, Team team, int x, int y){
if(!validBreak(team, x, y)){ if(!validBreak(team, x, y)){
return; return;
} }
@@ -40,14 +40,14 @@ public class Build{
tile.setBlock(sub, team, rotation); tile.setBlock(sub, team, rotation);
tile.<ConstructBuild>bc().setDeconstruct(previous); tile.<ConstructBuild>bc().setDeconstruct(previous);
tile.build.health = tile.build.maxHealth * prevPercent; tile.build.health = tile.build.maxHealth * prevPercent;
if(unit != null && unit.isPlayer()) tile.build.lastAccessed = unit.getPlayer().name;
Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(tile, team, true))); Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(tile, team, true)));
} }
/** Places a ConstructBlock at this location. */ /** Places a ConstructBlock at this location. */
@Remote(called = Loc.server) @Remote(called = Loc.server)
public static void beginPlace(Block result, Team team, int x, int y, int rotation){ public static void beginPlace(@Nullable Unit unit, Block result, Team team, int x, int y, int rotation){
if(!validPlace(result, team, x, y, rotation)){ if(!validPlace(result, team, x, y, rotation)){
return; return;
} }
@@ -57,6 +57,15 @@ public class Build{
//just in case //just in case
if(tile == null) return; if(tile == null) return;
//auto-rotate the block to the correct orientation and bail out
if(tile.team() == team && tile.block == result && tile.build != null){
if(unit != null && unit.isPlayer()) tile.build.lastAccessed = unit.getPlayer().name;
tile.build.rotation = Mathf.mod(rotation, 4);
tile.build.updateProximity();
tile.build.noSleep();
return;
}
Block previous = tile.block(); Block previous = tile.block();
Block sub = ConstructBlock.get(result.size); Block sub = ConstructBlock.get(result.size);
Seq<Building> prevBuild = new Seq<>(9); Seq<Building> prevBuild = new Seq<>(9);
@@ -76,6 +85,7 @@ public class Build{
build.setConstruct(previous.size == sub.size ? previous : Blocks.air, result); build.setConstruct(previous.size == sub.size ? previous : Blocks.air, result);
build.prevBuild = prevBuild; build.prevBuild = prevBuild;
if(unit != null && unit.isPlayer()) build.lastAccessed = unit.getPlayer().name;
result.placeBegan(tile, previous); result.placeBegan(tile, previous);

View File

@@ -103,6 +103,28 @@ public class Tile implements Position, QuadTreeObject, Displayable{
return -1; return -1;
} }
/**
* Returns the flammability of the Used for fire calculations.
* Takes flammability of floor liquid into account.
*/
public float getFlammability(){
if(!block.hasItems){
if(floor.liquidDrop != null && !block.solid){
return floor.liquidDrop.flammability;
}
return 0;
}else if(build != null){
float result = build.items.sum((item, amount) -> item.flammability * amount);
if(block.hasLiquids){
result += build.liquids.sum((liquid, amount) -> liquid.flammability * amount / 3f);
}
return result;
}
return 0;
}
/** Convenience method that returns the building of this tile with a cast. /** Convenience method that returns the building of this tile with a cast.
* Method name is shortened to prevent conflict. */ * Method name is shortened to prevent conflict. */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@@ -19,6 +19,7 @@ import mindustry.graphics.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.ui.*; import mindustry.ui.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.storage.CoreBlock.*;
import mindustry.world.modules.*; import mindustry.world.modules.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
@@ -275,8 +276,9 @@ public class ConstructBlock extends Block{
if(clampedAmount > 0 && accumulated > 0){ //if it's positive, add it to the core if(clampedAmount > 0 && accumulated > 0){ //if it's positive, add it to the core
if(core != null && requirements[i].item.unlockedNow()){ //only accept items that are unlocked if(core != null && requirements[i].item.unlockedNow()){ //only accept items that are unlocked
int accepting = core.acceptStack(requirements[i].item, accumulated, builder); int accepting = Math.min(accumulated, ((CoreBuild)core).storageCapacity - core.items.get(requirements[i].item));
core.handleStack(requirements[i].item, accepting, builder); //transfer items directly, as this is not production.
core.items.add(requirements[i].item, accepting);
accumulator[i] -= accepting; accumulator[i] -= accepting;
}else{ }else{
accumulator[i] -= accumulated; accumulator[i] -= accumulated;

View File

@@ -1,5 +1,6 @@
package mindustry.world.blocks.campaign; package mindustry.world.blocks.campaign;
import arc.*;
import arc.Graphics.*; import arc.Graphics.*;
import arc.Graphics.Cursor.*; import arc.Graphics.Cursor.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
@@ -8,6 +9,7 @@ import arc.scene.ui.layout.*;
import arc.util.*; import arc.util.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.game.EventType.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.type.*; import mindustry.type.*;
@@ -91,6 +93,7 @@ public class Accelerator extends Block{
if(!state.isCampaign() || !consValid()) return; if(!state.isCampaign() || !consValid()) return;
ui.showInfo("@indev.campaign"); ui.showInfo("@indev.campaign");
Events.fire(Trigger.acceleratorUse);
} }
@Override @Override

View File

@@ -56,6 +56,11 @@ public class LaunchPad extends Block{
bars.add("items", entity -> new Bar(() -> Core.bundle.format("bar.items", entity.items.total()), () -> Pal.items, () -> (float)entity.items.total() / itemCapacity)); bars.add("items", entity -> new Bar(() -> Core.bundle.format("bar.items", entity.items.total()), () -> Pal.items, () -> (float)entity.items.total() / itemCapacity));
} }
@Override
public boolean outputsItems(){
return false;
}
public class LaunchPadBuild extends Building{ public class LaunchPadBuild extends Building{
@Override @Override

View File

@@ -48,6 +48,7 @@ public class ForceProjector extends Block{
super(name); super(name);
update = true; update = true;
solid = true; solid = true;
group = BlockGroup.projectors;
hasPower = true; hasPower = true;
hasLiquids = true; hasLiquids = true;
hasItems = true; hasItems = true;

View File

@@ -31,6 +31,7 @@ public class MendProjector extends Block{
super(name); super(name);
solid = true; solid = true;
update = true; update = true;
group = BlockGroup.projectors;
hasPower = true; hasPower = true;
hasItems = true; hasItems = true;
} }

View File

@@ -32,6 +32,7 @@ public class OverdriveProjector extends Block{
super(name); super(name);
solid = true; solid = true;
update = true; update = true;
group = BlockGroup.projectors;
hasPower = true; hasPower = true;
hasItems = true; hasItems = true;
canOverdrive = false; canOverdrive = false;

View File

@@ -11,7 +11,7 @@ import mindustry.world.meta.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public abstract class BaseTurret extends Block{ public class BaseTurret extends Block{
public float range = 80f; public float range = 80f;
public float rotateSpeed = 5; public float rotateSpeed = 5;

View File

@@ -1,63 +0,0 @@
package mindustry.world.blocks.defense.turrets;
import arc.audio.*;
import arc.math.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.entities.*;
import mindustry.entities.bullet.*;
import mindustry.type.*;
import mindustry.gen.*;
import static mindustry.Vars.*;
public class ChargeTurret extends PowerTurret{
public float chargeTime = 30f;
public int chargeEffects = 5;
public float chargeMaxDelay = 10f;
public Effect chargeEffect = Fx.none;
public Effect chargeBeginEffect = Fx.none;
public Sound chargeSound = Sounds.none;
public ChargeTurret(String name){
super(name);
}
public class ChargeTurretBuild extends PowerTurretBuild{
public boolean shooting;
@Override
public void shoot(BulletType ammo){
useAmmo();
tr.trns(rotation, size * tilesize / 2f);
chargeBeginEffect.at(x + tr.x, y + tr.y, rotation);
chargeSound.at(x + tr.x, y + tr.y, 1);
for(int i = 0; i < chargeEffects; i++){
Time.run(Mathf.random(chargeMaxDelay), () -> {
if(!isValid()) return;
tr.trns(rotation, size * tilesize / 2f);
chargeEffect.at(x + tr.x, y + tr.y, rotation);
});
}
shooting = true;
Time.run(chargeTime, () -> {
if(!isValid()) return;
tr.trns(rotation, size * tilesize / 2f);
recoil = recoilAmount;
heat = 1f;
bullet(ammo, rotation + Mathf.range(inaccuracy));
effects();
shooting = false;
});
}
@Override
public boolean shouldTurn(){
return !shooting;
}
}
}

View File

@@ -54,6 +54,7 @@ public class LaserTurret extends PowerTurret{
super.updateTile(); super.updateTile();
if(bulletLife > 0 && bullet != null){ if(bulletLife > 0 && bullet != null){
wasShooting = true;
tr.trns(rotation, size * tilesize / 2f, 0f); tr.trns(rotation, size * tilesize / 2f, 0f);
bullet.rotation(rotation); bullet.rotation(rotation);
bullet.set(x + tr.x, y + tr.y); bullet.set(x + tr.x, y + tr.y);
@@ -65,6 +66,7 @@ public class LaserTurret extends PowerTurret{
bullet = null; bullet = null;
} }
}else if(reload > 0){ }else if(reload > 0){
wasShooting = true;
Liquid liquid = liquids.current(); Liquid liquid = liquids.current();
float maxUsed = consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount; float maxUsed = consumes.<ConsumeLiquidBase>get(ConsumeType.liquid).amount;
@@ -76,7 +78,6 @@ public class LaserTurret extends PowerTurret{
coolEffect.at(x + Mathf.range(size * tilesize / 2f), y + Mathf.range(size * tilesize / 2f)); coolEffect.at(x + Mathf.range(size * tilesize / 2f), y + Mathf.range(size * tilesize / 2f));
} }
} }
} }
@Override @Override

View File

@@ -9,7 +9,7 @@ import mindustry.world.meta.values.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public abstract class ReloadTurret extends BaseTurret{ public class ReloadTurret extends BaseTurret{
public float reloadTime = 10f; public float reloadTime = 10f;
public ReloadTurret(String name){ public ReloadTurret(String name){

View File

@@ -27,7 +27,7 @@ import mindustry.world.meta.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public abstract class Turret extends ReloadTurret{ public class Turret extends ReloadTurret{
//after being logic-controlled and this amount of time passes, the turret will resume normal AI //after being logic-controlled and this amount of time passes, the turret will resume normal AI
public final static float logicControlCooldown = 60 * 2; public final static float logicControlCooldown = 60 * 2;
@@ -40,6 +40,7 @@ public abstract class Turret extends ReloadTurret{
public Effect ammoUseEffect = Fx.none; public Effect ammoUseEffect = Fx.none;
public Sound shootSound = Sounds.shoot; public Sound shootSound = Sounds.shoot;
//general info
public int maxAmmo = 30; public int maxAmmo = 30;
public int ammoPerShot = 1; public int ammoPerShot = 1;
public float ammoEjectBack = 1f; public float ammoEjectBack = 1f;
@@ -61,6 +62,14 @@ public abstract class Turret extends ReloadTurret{
public boolean targetAir = true; public boolean targetAir = true;
public boolean targetGround = true; public boolean targetGround = true;
//charging
public float chargeTime = -1f;
public int chargeEffects = 5;
public float chargeMaxDelay = 10f;
public Effect chargeEffect = Fx.none;
public Effect chargeBeginEffect = Fx.none;
public Sound chargeSound = Sounds.none;
public Sortf unitSort = Unit::dst2; public Sortf unitSort = Unit::dst2;
protected Vec2 tr = new Vec2(); protected Vec2 tr = new Vec2();
@@ -136,7 +145,7 @@ public abstract class Turret extends ReloadTurret{
public @Nullable Posc target; public @Nullable Posc target;
public Vec2 targetPos = new Vec2(); public Vec2 targetPos = new Vec2();
public BlockUnitc unit = Nulls.blockUnit; public BlockUnitc unit = Nulls.blockUnit;
public boolean wasShooting; public boolean wasShooting, charging;
@Override @Override
public void created(){ public void created(){
@@ -196,7 +205,7 @@ public abstract class Turret extends ReloadTurret{
} }
public boolean isActive(){ public boolean isActive(){
return target != null || (logicControlled() && logicShooting) || (isControlled() && unit.isShooting()); return target != null || wasShooting;
} }
public void targetPosition(Posc pos){ public void targetPosition(Posc pos){
@@ -313,7 +322,7 @@ public abstract class Turret extends ReloadTurret{
} }
public boolean shouldTurn(){ public boolean shouldTurn(){
return true; return !charging;
} }
/** Consume ammo and return a type. */ /** Consume ammo and return a type. */
@@ -352,11 +361,37 @@ public abstract class Turret extends ReloadTurret{
} }
protected void shoot(BulletType type){ protected void shoot(BulletType type){
recoil = recoilAmount;
heat = 1f;
//when burst spacing is enabled, use the burst pattern //when charging is enabled, use the charge shoot pattern
if(burstSpacing > 0.0001f){ if(chargeTime > 0){
useAmmo();
tr.trns(rotation, size * tilesize / 2f);
chargeBeginEffect.at(x + tr.x, y + tr.y, rotation);
chargeSound.at(x + tr.x, y + tr.y, 1);
for(int i = 0; i < chargeEffects; i++){
Time.run(Mathf.random(chargeMaxDelay), () -> {
if(!isValid()) return;
tr.trns(rotation, size * tilesize / 2f);
chargeEffect.at(x + tr.x, y + tr.y, rotation);
});
}
charging = true;
Time.run(chargeTime, () -> {
if(!isValid()) return;
tr.trns(rotation, size * tilesize / 2f);
recoil = recoilAmount;
heat = 1f;
bullet(type, rotation + Mathf.range(inaccuracy));
effects();
charging = false;
});
//when burst spacing is enabled, use the burst pattern
}else if(burstSpacing > 0.0001f){
for(int i = 0; i < shots; i++){ for(int i = 0; i < shots; i++){
Time.run(burstSpacing * i, () -> { Time.run(burstSpacing * i, () -> {
if(!isValid() || !hasAmmo()) return; if(!isValid() || !hasAmmo()) return;
@@ -367,6 +402,8 @@ public abstract class Turret extends ReloadTurret{
bullet(type, rotation + Mathf.range(inaccuracy)); bullet(type, rotation + Mathf.range(inaccuracy));
effects(); effects();
useAmmo(); useAmmo();
recoil = recoilAmount;
heat = 1f;
}); });
} }
@@ -388,6 +425,8 @@ public abstract class Turret extends ReloadTurret{
shotCounter++; shotCounter++;
recoil = recoilAmount;
heat = 1f;
effects(); effects();
useAmmo(); useAmmo();
} }

Some files were not shown because too many files have changed in this diff Show More