Compare commits
141 Commits
pre0.16.3-
...
pre0.16.5-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
510f7d7513 | ||
|
|
3128eb38c0 | ||
|
|
14ef654612 | ||
|
|
bc5193f95e | ||
|
|
8cbb4a38bc | ||
|
|
fce08c83ef | ||
|
|
018e99f9e6 | ||
|
|
7fe390b34b | ||
|
|
8c7202c569 | ||
|
|
ab386bb53c | ||
|
|
87c791b8c7 | ||
|
|
00e3e2d19d | ||
|
|
8d7d5c7b04 | ||
|
|
849a18e159 | ||
|
|
a4357d0843 | ||
|
|
e2b4a78b59 | ||
|
|
01387b5488 | ||
|
|
168e2f80b8 | ||
|
|
4f79ef8708 | ||
|
|
16497833df | ||
|
|
cd6a50d5a0 | ||
|
|
4c5a61f2d8 | ||
|
|
1fd8d39970 | ||
|
|
d133d64890 | ||
|
|
b27aa8b60d | ||
|
|
230d67492e | ||
|
|
4f9d5b282c | ||
|
|
a2955e8722 | ||
|
|
df892671d5 | ||
|
|
7fa96eee1a | ||
|
|
a1030906c7 | ||
|
|
e6a9a4f4be | ||
|
|
efa1247596 | ||
|
|
069fcee721 | ||
|
|
66621404f1 | ||
|
|
e09609ea21 | ||
|
|
d02ae67bc0 | ||
|
|
27327d57c4 | ||
|
|
cce93b6df9 | ||
|
|
546104ba5b | ||
|
|
ca5816ba14 | ||
|
|
e5bd16476e | ||
|
|
94431d4c2e | ||
|
|
f98d6892f1 | ||
|
|
1fe436cbe3 | ||
|
|
c5a37a9920 | ||
|
|
eed7e96096 | ||
|
|
a7f36a4162 | ||
|
|
8ba872d45d | ||
|
|
7a55451faa | ||
|
|
372571bd80 | ||
|
|
77120c0b90 | ||
|
|
01d1e44644 | ||
|
|
0ad8cddefe | ||
|
|
ce67253502 | ||
|
|
cb9f2c0617 | ||
|
|
635d9407ed | ||
|
|
0f9f6565f1 | ||
|
|
a45b6ad57e | ||
|
|
a5de06dedb | ||
|
|
fbfbd1ed98 | ||
|
|
8f06b3bd1a | ||
|
|
7e0dbceefc | ||
|
|
7e3db1de17 | ||
|
|
111790fdab | ||
|
|
bec03de7b8 | ||
|
|
f5dfae3a6c | ||
|
|
d3dec2b5f1 | ||
|
|
f083136998 | ||
|
|
cd3d0b370c | ||
|
|
f4c6632941 | ||
|
|
750cb9a669 | ||
|
|
62a198a017 | ||
|
|
5780ba0f3e | ||
|
|
86edeb1e0c | ||
|
|
53b1852f28 | ||
|
|
e3c385693b | ||
|
|
572c0fbfa1 | ||
|
|
bbdf71167a | ||
|
|
2136ccd9a2 | ||
|
|
2131aea575 | ||
|
|
32b21c7d29 | ||
|
|
8f6f6f316f | ||
|
|
66f9ac2791 | ||
|
|
ac0ba90438 | ||
|
|
990659ce91 | ||
|
|
00c602c844 | ||
|
|
9db62ffc39 | ||
|
|
e7c777e502 | ||
|
|
4991e8cea2 | ||
|
|
111d4e991f | ||
|
|
bedfa74a32 | ||
|
|
f6944dc223 | ||
|
|
a34a3051a3 | ||
|
|
0e13883faf | ||
|
|
e8860eda1b | ||
|
|
33ba4820b3 | ||
|
|
5ed0dda8ab | ||
|
|
bd260b2c6f | ||
|
|
aa01ab07f7 | ||
|
|
684cb90a7d | ||
|
|
172101ed55 | ||
|
|
98b5914726 | ||
|
|
d1518e7ba4 | ||
|
|
72d4faa52a | ||
|
|
862dcbf806 | ||
|
|
3db28f5136 | ||
|
|
f9e37f3c6a | ||
|
|
457681e6ec | ||
|
|
904bcf6852 | ||
|
|
e21e57ff84 | ||
|
|
562a69831a | ||
|
|
706a683540 | ||
|
|
8e2aee5e84 | ||
|
|
c009893377 | ||
|
|
3ae128d4c3 | ||
|
|
cb2164c21d | ||
|
|
951b7407fc | ||
|
|
f68facbe0e | ||
|
|
5535366bb1 | ||
|
|
d75b709f23 | ||
|
|
5a1fd0ca4d | ||
|
|
f4b85e0dbb | ||
|
|
c38bceb87e | ||
|
|
2569e8844e | ||
|
|
e42fa8351e | ||
|
|
9582a625ff | ||
|
|
81abb06f7b | ||
|
|
7cfea0eebe | ||
|
|
01c2bfe955 | ||
|
|
70242e6a07 | ||
|
|
c1edba974f | ||
|
|
546b3f230d | ||
|
|
14593eb487 | ||
|
|
838621a3ae | ||
|
|
283d4a5fce | ||
|
|
490cf44132 | ||
|
|
9dcbd86fc3 | ||
|
|
0a15011ec7 | ||
|
|
f7dfe1d869 | ||
|
|
5e9c9cb5fa |
24
.github/actions/automatic-test/action.yml
vendored
Normal file
24
.github/actions/automatic-test/action.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: 'Automatic Test'
|
||||
description: 'Check for obvious errors.'
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/build-love
|
||||
with:
|
||||
file-path: Techmino.love
|
||||
- name: Download love
|
||||
shell: bash
|
||||
run: |
|
||||
curl -L https://github.com/love2d/love/releases/download/11.3/love-11.3-linux-x86_64.tar.gz | tar xz
|
||||
- name: Prepare PulseAudio
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install pulseaudio pulseaudio-utils pavucontrol alsa-oss alsa-utils -y
|
||||
- name: Run automated test
|
||||
uses: GabrielBB/xvfb-action@v1
|
||||
with:
|
||||
run: |
|
||||
./dest/love Techmino.love --test
|
||||
32
.github/actions/build-android/action.yml
vendored
32
.github/actions/build-android/action.yml
vendored
@@ -59,11 +59,41 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
7z a -tzip love-android/app/src/main/assets/game.love libAndroid
|
||||
- name: update Android information
|
||||
shell: python
|
||||
run: |
|
||||
if '${{ inputs.type }}' == 'Release':
|
||||
appName = 'Techmino'
|
||||
packageName = 'org.love2d.MrZ.Techmino'
|
||||
edition = 'release'
|
||||
elif '${{ inputs.type }}' == 'Snapshot':
|
||||
appName = 'Techmino_Snapshot'
|
||||
packageName = 'org.love2d.MrZ.Techmino.Snapshot'
|
||||
edition = 'snapshot'
|
||||
with open('./love-android/app/src/main/AndroidManifest.xml', "r+", encoding='utf-8') as file:
|
||||
data = file.read()
|
||||
data = data\
|
||||
.replace('@appName', appName)\
|
||||
.replace('@edition', edition)
|
||||
file.seek(0)
|
||||
file.truncate()
|
||||
file.write(data)
|
||||
with open("./love-android/app/build.gradle", "r+", encoding='utf-8') as file:
|
||||
data = file.read()
|
||||
data = data\
|
||||
.replace('@packageName', packageName)\
|
||||
.replace('@versionCode', '${{ inputs.apkCode }}')\
|
||||
.replace('@versionName', '${{ inputs.name }}')\
|
||||
.replace('@storePassword', '${{ inputs.KEY_STORE_PASSWORD }}')\
|
||||
.replace('@keyAlias', '${{ inputs.ALIAS }}')\
|
||||
.replace('@keyPassword', '${{ inputs.KEY_PASSWORD }}')
|
||||
file.seek(0)
|
||||
file.truncate()
|
||||
file.write(data)
|
||||
- name: Build Techmino
|
||||
shell: bash
|
||||
run: |
|
||||
echo "${{ inputs.SIGNING_KEY }}" | base64 -d > love-android/app/android.keystore
|
||||
python3 .github/workflows/updateVersion.py -T Android${{ inputs.type }} -C ${{ inputs.apkCode }} -N ${{ inputs.name }} -S ${{ inputs.KEY_STORE_PASSWORD }} -A ${{ inputs.ALIAS }} -K ${{ inputs.KEY_PASSWORD }}
|
||||
chmod 777 love-android/gradlew
|
||||
cd love-android/
|
||||
./gradlew assembleRelease
|
||||
|
||||
4
.github/actions/build-ios/action.yml
vendored
4
.github/actions/build-ios/action.yml
vendored
@@ -40,6 +40,9 @@ inputs:
|
||||
FASTLANE_DISCORD_WEBHOOK:
|
||||
required: true
|
||||
description: "Fastlane Discord webhook"
|
||||
FASTLANE_ACTION_ID:
|
||||
required: true
|
||||
description: "Fastlane Action ID"
|
||||
FASTLANE_MATCH_PWD:
|
||||
required: true
|
||||
description: "Fastlane Match description password"
|
||||
@@ -71,6 +74,7 @@ runs:
|
||||
lane: '${{ inputs.type }}'
|
||||
subdirectory: 'Techmino-iOS/platform/xcode'
|
||||
env:
|
||||
ACTION_ID: '${{ inputs.FASTLANE_ACTION_ID }}'
|
||||
API_ID: '${{ inputs.APPLE_API_ID }}'
|
||||
API_ISSUER: '${{ inputs.APPLE_API_ISSUER }}'
|
||||
API_KEY: '${{ inputs.APPLE_API_KEY }}'
|
||||
|
||||
2
.github/actions/build-linux/action.yml
vendored
2
.github/actions/build-linux/action.yml
vendored
@@ -33,7 +33,7 @@ runs:
|
||||
cp squashfs-root/icon.png squashfs-root/.DirIcon
|
||||
chmod 777 squashfs-root/love
|
||||
mkdir -p squashfs-root/usr/share/Techmino
|
||||
mv media parts Zframework conf.lua main.lua version.lua squashfs-root/usr/share/Techmino
|
||||
mv media parts Zframework conf.lua main.lua version.lua legals.md license.txt squashfs-root/usr/share/Techmino
|
||||
mv CCloader.so squashfs-root/usr/share/Techmino
|
||||
mv libcold_clear.so squashfs-root/usr/lib
|
||||
chmod 777 appimagetool-x86_64.AppImage
|
||||
|
||||
2
.github/actions/build-love/action.yml
vendored
2
.github/actions/build-love/action.yml
vendored
@@ -7,5 +7,5 @@ inputs:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- run: 7z a -tzip ${{ inputs.file-path }} media parts Zframework conf.lua main.lua version.lua
|
||||
- run: 7z a -tzip ${{ inputs.file-path }} media parts Zframework conf.lua main.lua version.lua legals.md license.txt
|
||||
shell: bash
|
||||
|
||||
18
.github/actions/build-macos/action.yml
vendored
18
.github/actions/build-macos/action.yml
vendored
@@ -59,12 +59,22 @@ runs:
|
||||
MATCH_PASSWORD: '${{ inputs.FASTLANE_MATCH_PWD }}'
|
||||
MATCH_TOKEN: '${{ inputs.FASTLANE_MATCH_TOKEN }}'
|
||||
- name: Modify template
|
||||
shell: python
|
||||
run: |
|
||||
import datetime
|
||||
from io import open
|
||||
thisYear = str(datetime.datetime.today().year)
|
||||
with open('./.github/build/macOS/info.plist.template', 'r', encoding='utf-8') as file:
|
||||
data = file.read()
|
||||
data = data\
|
||||
.replace('@versionName', '${{ inputs.name }}'[1:])\
|
||||
.replace('@thisYear', thisYear)\
|
||||
.replace('@bundleId', '${{ inputs.APPLE_APP_IDENTIFIER }}')
|
||||
with open('./Techmino-macOS/Techmino.app/Contents/info.plist', 'w+', encoding='utf-8') as file:
|
||||
file.write(data)
|
||||
- name: Pack
|
||||
shell: bash
|
||||
run: |
|
||||
python3 .github/workflows/updateVersion.py -T macOS \
|
||||
-N ${{ inputs.name }} \
|
||||
-B ${{ inputs.APPLE_APP_IDENTIFIER }}
|
||||
|
||||
mv Techmino.love Techmino-macOS/Techmino.app/Contents/Resources
|
||||
mv CCloader.dylib Techmino-macOS/Techmino.app/Contents/Frameworks
|
||||
mv ${{ inputs.icon }} Techmino-macOS/Techmino.app/Contents/Resources/iconfile.icns
|
||||
|
||||
13
.github/actions/build-windows/action.yml
vendored
13
.github/actions/build-windows/action.yml
vendored
@@ -30,6 +30,18 @@ runs:
|
||||
with:
|
||||
url: http://www.angusj.com/resourcehacker/resource_hacker.zip
|
||||
- uses: ./.github/actions/build-love
|
||||
- name: update Windows template
|
||||
shell: python
|
||||
run: |
|
||||
Version = '${{ inputs.version }}'.replace('V', '')
|
||||
FileVersion = (f"{Version.replace('.', ',')},0")
|
||||
with open('./.github/build/Windows/Techmino.rc.template', 'r', encoding='utf8') as file:
|
||||
data = file.read()
|
||||
data = data\
|
||||
.replace('@FileVersion', FileVersion)\
|
||||
.replace('@Version', Version)
|
||||
with open('Techmino.rc', 'w+', encoding='utf8') as file:
|
||||
file.write(data)
|
||||
- name: Pack Techmino
|
||||
shell: pwsh
|
||||
run: |
|
||||
@@ -42,7 +54,6 @@ runs:
|
||||
del .\love\readme.txt
|
||||
move .\cold_clear.dll .\love
|
||||
move .\CCloader.dll .\love
|
||||
python .\.github\workflows\updateVersion.py -T Windows -N ${{ inputs.version }}
|
||||
cmd /c '.\ResourceHacker.exe -open .\love\Techmino.exe -save .\love\Techmino.exe -action delete -mask ICONGROUP,,'
|
||||
cmd /c '.\ResourceHacker.exe -open .\Techmino.rc -save .\Techmino.res -action compile'
|
||||
cmd /c '.\ResourceHacker.exe -open .\love\Techmino.exe -save .\love\Techmino.exe -action addoverwrite -res "${{ inputs.icon }}" -mask ICONGROUP,1,'
|
||||
|
||||
12
.github/actions/snapshot-update/action.yml
vendored
12
.github/actions/snapshot-update/action.yml
vendored
@@ -1,12 +0,0 @@
|
||||
name: 'update for a snapshot'
|
||||
description: 'common update logic for snapshot'
|
||||
inputs:
|
||||
commit:
|
||||
required: true
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- shell: bash
|
||||
run: |
|
||||
python3 .github/workflows/updateVersion.py -T Conf
|
||||
python3 .github/workflows/updateVersion.py -T Version -H ${{ inputs.commit }}
|
||||
37
.github/actions/update-version/action.yml
vendored
Normal file
37
.github/actions/update-version/action.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: 'update version'
|
||||
description: 'common update logic for snapshot and release'
|
||||
inputs:
|
||||
commit:
|
||||
required: false
|
||||
type:
|
||||
required: true
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- shell: python
|
||||
name: update snapshot saving folder
|
||||
run: |
|
||||
from io import open
|
||||
if '${{ inputs.type }}'.lower() != 'snapshot':
|
||||
exit(0)
|
||||
with open('conf.lua', 'r+', encoding='utf-8') as file:
|
||||
data = file.read()
|
||||
data = data.replace("t.identity='Techmino'--Saving folder", "t.identity='Techmino_Snapshot'--Saving folder")
|
||||
file.seek(0)
|
||||
file.truncate()
|
||||
file.flush()
|
||||
file.write(data)
|
||||
- shell: python
|
||||
run: |
|
||||
from io import open
|
||||
import re
|
||||
with open('version.lua', 'r+', encoding='utf-8') as file:
|
||||
commitHash = '${{ inputs.commit }}'
|
||||
if commitHash != '':
|
||||
commitHash = '@' + commitHash[0:4]
|
||||
data = file.read()
|
||||
data = re.sub('(\d)"', r'\1' + commitHash + '"', data, 1)
|
||||
file.seek(0)
|
||||
file.truncate()
|
||||
file.flush()
|
||||
file.write(data)
|
||||
54
.github/actions/upload-artifact/action.yml
vendored
Normal file
54
.github/actions/upload-artifact/action.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: "upload artifact"
|
||||
description: "upload file with webdav"
|
||||
inputs:
|
||||
WEBDAV_USERNAME:
|
||||
required: true
|
||||
description: "webdav username"
|
||||
WEBDAV_PASSWORD:
|
||||
required: true
|
||||
description: "webdav password"
|
||||
ARTIFACT_TYPE:
|
||||
required: true
|
||||
description: "file build type"
|
||||
ARTIFACT_PLATFORM:
|
||||
required: true
|
||||
description: "file platform"
|
||||
ARTIFACT_NAME:
|
||||
required: true
|
||||
description: "file name"
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.9'
|
||||
- name: Install Webdav 4
|
||||
shell: bash
|
||||
run: |
|
||||
pip install webdav4
|
||||
- name: Update release
|
||||
shell: python
|
||||
run: |
|
||||
import re
|
||||
from webdav4.client import Client
|
||||
|
||||
client = Client(
|
||||
"http://mc.yuhao7370.top:5212/dav",
|
||||
auth=("${{ inputs.WEBDAV_USERNAME }}", "${{ inputs.WEBDAV_PASSWORD }}"),
|
||||
timeout=None,
|
||||
)
|
||||
if '${{ inputs.ARTIFACT_TYPE }}' == 'release':
|
||||
print('Removing previous ${{ inputs.ARTIFACT_PLATFORM }} release file...')
|
||||
for file in client.ls('Techmino distribution'):
|
||||
if re.search(r'(Techmino_a[0-9]+\.[0-9]+\.[0-9]_${{ inputs.ARTIFACT_PLATFORM }}.*)', file['name']):
|
||||
client.remove(file['name'])
|
||||
print('Uploading new ${{ inputs.ARTIFACT_PLATFORM }} release file...')
|
||||
client.upload_file("${{ inputs.ARTIFACT_NAME }}", 'Techmino distribution/${{ inputs.ARTIFACT_NAME }}')
|
||||
|
||||
if '${{ inputs.ARTIFACT_TYPE }}' == 'test':
|
||||
print('Removing previous ${{ inputs.ARTIFACT_PLATFORM }} test file...')
|
||||
for file in client.ls('Techmino Snapshot'):
|
||||
if re.search(r'(Techmino_pre[0-9]+\.[0-9]+\.[0-9]_[0-9a-z]{7}_${{ inputs.ARTIFACT_PLATFORM }}.*)', file['name']):
|
||||
client.remove(file['name'])
|
||||
print('Uploading new ${{ inputs.ARTIFACT_PLATFORM }} test file...')
|
||||
client.upload_file("${{ inputs.ARTIFACT_NAME }}", 'Techmino Snapshot/${{ inputs.ARTIFACT_NAME }}')
|
||||
68
.github/workflows/dev.yml
vendored
68
.github/workflows/dev.yml
vendored
@@ -27,14 +27,21 @@ jobs:
|
||||
echo "::set-output name=code::$(lua .github/workflows/getVersion.lua -code)"
|
||||
echo "::set-output name=commit::$(git rev-parse --short ${{ GITHUB.SHA }})"
|
||||
|
||||
automatic-test:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/automatic-test
|
||||
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/snapshot-update
|
||||
- uses: ./.github/actions/update-version
|
||||
with:
|
||||
commit: ${{ needs.get-info.outputs.commit }}
|
||||
type: snapshot
|
||||
- uses: ./.github/actions/build-windows
|
||||
with:
|
||||
love-url: https://github.com/love2d/love/releases/download/11.3/love-11.3-win64.zip
|
||||
@@ -53,9 +60,10 @@ jobs:
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/snapshot-update
|
||||
- uses: ./.github/actions/update-version
|
||||
with:
|
||||
commit: ${{ needs.get-info.outputs.commit }}
|
||||
type: snapshot
|
||||
- uses: ./.github/actions/build-linux
|
||||
with:
|
||||
icon: .github/build/Linux/icon_snapshot.png
|
||||
@@ -70,9 +78,10 @@ jobs:
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/snapshot-update
|
||||
- uses: ./.github/actions/update-version
|
||||
with:
|
||||
commit: ${{ needs.get-info.outputs.commit }}
|
||||
type: snapshot
|
||||
- uses: ./.github/actions/build-android
|
||||
with:
|
||||
type: Snapshot
|
||||
@@ -88,15 +97,44 @@ jobs:
|
||||
with:
|
||||
name: Techmino_${{ needs.get-info.outputs.name }}_${{ GITHUB.RUN_NUMBER }}_${{ needs.get-info.outputs.commit }}_Android
|
||||
path: Techmino_Snapshot.apk
|
||||
|
||||
build-android-mini:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/update-version
|
||||
with:
|
||||
commit: ${{ needs.get-info.outputs.commit }}
|
||||
type: snapshot
|
||||
- name: remove media
|
||||
run: |
|
||||
rm -rf media/music media/effect media/vocal
|
||||
- uses: ./.github/actions/build-android
|
||||
with:
|
||||
type: Snapshot
|
||||
apkCode: ${{ needs.get-info.outputs.apkCode }}
|
||||
name: ${{ needs.get-info.outputs.name }}
|
||||
file-path: Techmino_Snapshot_Mini.apk
|
||||
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
|
||||
KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
|
||||
ALIAS: ${{ secrets.ALIAS }}
|
||||
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Techmino_${{ needs.get-info.outputs.name }}_${{ GITHUB.RUN_NUMBER }}_${{ needs.get-info.outputs.commit }}_Android_Mini
|
||||
path: Techmino_Snapshot_Mini.apk
|
||||
|
||||
build-macOS:
|
||||
runs-on: macos-10.15
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/snapshot-update
|
||||
- uses: ./.github/actions/update-version
|
||||
with:
|
||||
commit: ${{ needs.get-info.outputs.commit }}
|
||||
type: snapshot
|
||||
- uses: ./.github/actions/build-macos
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.name }}
|
||||
@@ -117,12 +155,14 @@ jobs:
|
||||
|
||||
build-iOS:
|
||||
runs-on: macos-latest
|
||||
if: (!startsWith( github.ref , 'refs/heads/ci-')) || startsWith( github.ref , 'refs/heads/ci-ios-')
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/snapshot-update
|
||||
- uses: ./.github/actions/update-version
|
||||
with:
|
||||
commit: ${{ needs.get-info.outputs.commit }}
|
||||
type: snapshot
|
||||
- uses: ./.github/actions/build-ios
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.name }}
|
||||
@@ -137,6 +177,7 @@ jobs:
|
||||
APPLE_APP_PROFILE: '${{ secrets.APPLE_APP_PROFILE }}'
|
||||
APPLE_KEYCHAIN_NAME: '${{ secrets.APPLE_KEYCHAIN_NAME }}'
|
||||
APPLE_KEYCHAIN_PWD: '${{ secrets.APPLE_KEYCHAIN_PWD }}'
|
||||
FASTLANE_ACTION_ID: '${{ github.run_id }}'
|
||||
FASTLANE_DISCORD_WEBHOOK: '${{ secrets.FASTLANE_DISCORD_WEBHOOK }}'
|
||||
FASTLANE_MATCH_PWD: '${{ secrets.FASTLANE_MATCH_PWD }}'
|
||||
FASTLANE_MATCH_TOKEN: '${{ secrets.FASTLANE_MATCH_TOKEN }}'
|
||||
@@ -144,4 +185,19 @@ jobs:
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Techmino_${{ needs.get-info.outputs.name }}_${{ GITHUB.RUN_NUMBER }}_${{ needs.get-info.outputs.commit }}_iOS
|
||||
path: "Techmino.ipa"
|
||||
path: Techmino.ipa
|
||||
|
||||
build-love:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/update-version
|
||||
- uses: ./.github/actions/build-love
|
||||
with:
|
||||
file-path: Techmino.love
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Techmino_${{ needs.get-info.outputs.name }}_${{ GITHUB.RUN_NUMBER }}_${{ needs.get-info.outputs.commit }}_Love
|
||||
path: Techmino.love
|
||||
|
||||
17
.github/workflows/getVersion.lua
vendored
17
.github/workflows/getVersion.lua
vendored
@@ -1,22 +1,23 @@
|
||||
if arg[1]=="-apkCode"then
|
||||
local arg=arg[1]
|
||||
if arg=="-apkCode"then
|
||||
local code=require"version".apkCode
|
||||
print(code)
|
||||
elseif arg[1]=="-code"then
|
||||
elseif arg=="-code"then
|
||||
local str=require"version".code
|
||||
print(str)
|
||||
elseif arg[1]=="-name"then
|
||||
local str=require"version".string:gsub("@DEV","")
|
||||
elseif arg=="-name"then
|
||||
local str=require"version".string
|
||||
print(str)
|
||||
elseif arg[1]=="-release"then
|
||||
local str=require"version".string:gsub("V","",1):gsub("@DEV","")
|
||||
elseif arg=="-release"then
|
||||
local str=require"version".string:gsub("V","",1)
|
||||
print(str)
|
||||
elseif arg[1]=="-updateTitle"then
|
||||
elseif arg=="-updateTitle"then
|
||||
local note=require"parts.updateLog"
|
||||
local p1=note:find("\n%d")+1
|
||||
local p2=note:find("\n",p1)-1
|
||||
note=note:sub(p1,p2)
|
||||
print(note)
|
||||
elseif arg[1]=="-updateNote"then
|
||||
elseif arg=="-updateNote"then
|
||||
local note=require"parts.updateLog"
|
||||
local p1=note:find("\n",note:find("\n%d")+1)+1
|
||||
local p2=note:find("\n%d",p1+1)
|
||||
|
||||
379
.github/workflows/release.yml
vendored
379
.github/workflows/release.yml
vendored
@@ -3,7 +3,7 @@ name: Techmino Release CI
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
get-info:
|
||||
@@ -14,233 +14,224 @@ jobs:
|
||||
code: ${{ steps.actual-get-info.outputs.code }}
|
||||
release: ${{ steps.actual-get-info.outputs.release }}
|
||||
updateTitle: ${{ steps.actual-get-info.outputs.updateTitle }}
|
||||
updateNote: ${{ steps.actual-get-info.outputs.updateNote }}
|
||||
commit: ${{ steps.actual-get-info.outputs.commit }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install lua
|
||||
run: |
|
||||
sudo apt-get install lua5.3 -y
|
||||
- name: Get Version
|
||||
id: actual-get-info
|
||||
run: |
|
||||
echo "::set-output name=name::$(lua .github/workflows/getVersion.lua -name)"
|
||||
echo "::set-output name=apkCode::$(lua .github/workflows/getVersion.lua -apkCode)"
|
||||
echo "::set-output name=code::$(lua .github/workflows/getVersion.lua -code)"
|
||||
echo "::set-output name=release::$(lua .github/workflows/getVersion.lua -release)"
|
||||
echo "::set-output name=updateTitle::$(lua .github/workflows/getVersion.lua -updateTitle)"
|
||||
echo "::set-output name=commit::$(git rev-parse --short ${{ GITHUB.SHA }})"
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install lua
|
||||
run: |
|
||||
sudo apt-get install lua5.3 -y
|
||||
- name: Get Version
|
||||
id: actual-get-info
|
||||
run: |
|
||||
UPDATE_NOTE=$(lua .github/workflows/getVersion.lua -updateNote)
|
||||
UPDATE_NOTE="${UPDATE_NOTE//'%'/'%25'}"
|
||||
UPDATE_NOTE="${UPDATE_NOTE//$'\n'/'%0A'}"
|
||||
UPDATE_NOTE="${UPDATE_NOTE//$'\r'/'%0D'}"
|
||||
echo "::set-output name=name::$(lua .github/workflows/getVersion.lua -name)"
|
||||
echo "::set-output name=apkCode::$(lua .github/workflows/getVersion.lua -apkCode)"
|
||||
echo "::set-output name=code::$(lua .github/workflows/getVersion.lua -code)"
|
||||
echo "::set-output name=release::$(lua .github/workflows/getVersion.lua -release)"
|
||||
echo "::set-output name=updateTitle::$(lua .github/workflows/getVersion.lua -updateTitle)"
|
||||
echo "::set-output name=updateNote::$UPDATE_NOTE"
|
||||
echo "::set-output name=commit::$(git rev-parse --short ${{ GITHUB.SHA }})"
|
||||
|
||||
build-windows-x64:
|
||||
runs-on: windows-latest
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update Version
|
||||
run: |
|
||||
python .\.github\workflows\updateVersion.py -T Version
|
||||
- uses: ./.github/actions/build-windows
|
||||
with:
|
||||
love-url: https://github.com/love2d/love/releases/download/11.3/love-11.3-win64.zip
|
||||
love-dir: love-11.3-win64
|
||||
arch: win64
|
||||
version: ${{ needs.get-info.outputs.release }}
|
||||
icon: .\.github\build\Windows\icon.ico
|
||||
- name: Pack Techmino
|
||||
run: 7z a -tzip .\Techmino.a${{ needs.get-info.outputs.release }}.Win64.zip .\love
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino.a${{ needs.get-info.outputs.release }}.Win64.zip
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/update-version
|
||||
- uses: ./.github/actions/build-windows
|
||||
with:
|
||||
love-url: https://github.com/love2d/love/releases/download/11.3/love-11.3-win64.zip
|
||||
love-dir: love-11.3-win64
|
||||
arch: win64
|
||||
version: ${{ needs.get-info.outputs.release }}
|
||||
icon: .\.github\build\Windows\icon.ico
|
||||
- name: Pack Techmino
|
||||
run: 7z a -tzip .\Techmino_a${{ needs.get-info.outputs.release }}_Win64.zip .\love
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino_a${{ needs.get-info.outputs.release }}_Win64.zip
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: release
|
||||
ARTIFACT_PLATFORM: Win64
|
||||
ARTIFACT_NAME: Techmino_a${{ needs.get-info.outputs.release }}_Win64.zip
|
||||
|
||||
build-windows-x86:
|
||||
runs-on: windows-latest
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update Version
|
||||
run: |
|
||||
python .\.github\workflows\updateVersion.py -T Version
|
||||
- uses: ./.github/actions/build-windows
|
||||
with:
|
||||
love-url: https://github.com/love2d/love/releases/download/11.3/love-11.3-win32.zip
|
||||
love-dir: love-11.3-win32
|
||||
arch: win32
|
||||
version: ${{ needs.get-info.outputs.release }}
|
||||
icon: .\.github\build\Windows\icon.ico
|
||||
- name: Pack Techmino
|
||||
run: 7z a -tzip .\Techmino.a${{ needs.get-info.outputs.release }}.Win32.zip .\love
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino.a${{ needs.get-info.outputs.release }}.Win32.zip
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/update-version
|
||||
- uses: ./.github/actions/build-windows
|
||||
with:
|
||||
love-url: https://github.com/love2d/love/releases/download/11.3/love-11.3-win32.zip
|
||||
love-dir: love-11.3-win32
|
||||
arch: win32
|
||||
version: ${{ needs.get-info.outputs.release }}
|
||||
icon: .\.github\build\Windows\icon.ico
|
||||
- name: Pack Techmino
|
||||
run: 7z a -tzip .\Techmino_a${{ needs.get-info.outputs.release }}_Win32.zip .\love
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino_a${{ needs.get-info.outputs.release }}_Win32.zip
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: release
|
||||
ARTIFACT_PLATFORM: Win32
|
||||
ARTIFACT_NAME: Techmino_a${{ needs.get-info.outputs.release }}_Win32.zip
|
||||
|
||||
build-linux:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update Version
|
||||
run: |
|
||||
python3 .github/workflows/updateVersion.py -T Version
|
||||
- uses: ./.github/actions/build-linux
|
||||
with:
|
||||
file-path: Techmino.a${{ needs.get-info.outputs.release }}.AppImage
|
||||
icon: .github/build/Linux/icon.png
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino.a${{ needs.get-info.outputs.release }}.AppImage
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/update-version
|
||||
- uses: ./.github/actions/build-linux
|
||||
with:
|
||||
file-path: Techmino_a${{ needs.get-info.outputs.release }}_Linux.AppImage
|
||||
icon: .github/build/Linux/icon.png
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino_a${{ needs.get-info.outputs.release }}_Linux.AppImage
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: release
|
||||
ARTIFACT_PLATFORM: Linux
|
||||
ARTIFACT_NAME: Techmino_a${{ needs.get-info.outputs.release }}_Linux.AppImage
|
||||
|
||||
build-android:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update Version
|
||||
run: |
|
||||
python3 .github/workflows/updateVersion.py -T Version
|
||||
- uses: ./.github/actions/build-android
|
||||
with:
|
||||
type: Release
|
||||
apkCode: ${{ needs.get-info.outputs.apkCode }}
|
||||
name: ${{ needs.get-info.outputs.name }}
|
||||
file-path: Techmino.a${{ needs.get-info.outputs.release }}.apk
|
||||
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
|
||||
KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
|
||||
ALIAS: ${{ secrets.ALIAS }}
|
||||
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino.a${{ needs.get-info.outputs.release }}.apk
|
||||
|
||||
build-android-mini:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update Version
|
||||
run: |
|
||||
python3 .github/workflows/updateVersion.py -T Version
|
||||
- name: remove media
|
||||
run: |
|
||||
rm -rf media/music media/effect media/vocal
|
||||
- uses: ./.github/actions/build-android
|
||||
with:
|
||||
type: Release
|
||||
apkCode: ${{ needs.get-info.outputs.apkCode }}
|
||||
name: ${{ needs.get-info.outputs.name }}
|
||||
file-path: Techmino.a${{ needs.get-info.outputs.release }}.mini.apk
|
||||
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
|
||||
KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
|
||||
ALIAS: ${{ secrets.ALIAS }}
|
||||
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino.a${{ needs.get-info.outputs.release }}.mini.apk
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/update-version
|
||||
- uses: ./.github/actions/build-android
|
||||
with:
|
||||
type: Release
|
||||
apkCode: ${{ needs.get-info.outputs.apkCode }}
|
||||
name: ${{ needs.get-info.outputs.name }}
|
||||
file-path: Techmino_a${{ needs.get-info.outputs.release }}_Android.apk
|
||||
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
|
||||
KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
|
||||
ALIAS: ${{ secrets.ALIAS }}
|
||||
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino_a${{ needs.get-info.outputs.release }}_Android.apk
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: release
|
||||
ARTIFACT_PLATFORM: Android
|
||||
ARTIFACT_NAME: Techmino_a${{ needs.get-info.outputs.release }}_Android.apk
|
||||
|
||||
build-macOS:
|
||||
runs-on: macos-10.15
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update Version
|
||||
run: |
|
||||
python3 .github/workflows/updateVersion.py -T Version
|
||||
- uses: ./.github/actions/build-macos
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.name }}
|
||||
icon: .github/build/macOS/icon.icns
|
||||
APPLE_API_ID: '${{ secrets.APPLE_API_ID }}'
|
||||
APPLE_API_ISSUER: '${{ secrets.APPLE_API_ISSUER }}'
|
||||
APPLE_API_KEY: '${{ secrets.APPLE_API_KEY }}'
|
||||
APPLE_APP_IDENTIFIER: '${{ secrets.APPLE_APP_IDENTIFIER }}'
|
||||
APPLE_KEYCHAIN_NAME: '${{ secrets.APPLE_KEYCHAIN_NAME }}'
|
||||
APPLE_KEYCHAIN_PWD: '${{ secrets.APPLE_KEYCHAIN_PWD }}'
|
||||
FASTLANE_MATCH_PWD: '${{ secrets.FASTLANE_MATCH_PWD }}'
|
||||
FASTLANE_MATCH_TOKEN: '${{ secrets.FASTLANE_MATCH_TOKEN }}'
|
||||
- name: Pack Techmino
|
||||
run: |
|
||||
mv Techmino.dmg Techmino.a${{ needs.get-info.outputs.release }}.macOS.dmg
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino.a${{ needs.get-info.outputs.release }}.macOS.zip
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/update-version
|
||||
- uses: ./.github/actions/build-macos
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.name }}
|
||||
icon: .github/build/macOS/icon.icns
|
||||
APPLE_API_ID: "${{ secrets.APPLE_API_ID }}"
|
||||
APPLE_API_ISSUER: "${{ secrets.APPLE_API_ISSUER }}"
|
||||
APPLE_API_KEY: "${{ secrets.APPLE_API_KEY }}"
|
||||
APPLE_APP_IDENTIFIER: "${{ secrets.APPLE_APP_IDENTIFIER }}"
|
||||
APPLE_KEYCHAIN_NAME: "${{ secrets.APPLE_KEYCHAIN_NAME }}"
|
||||
APPLE_KEYCHAIN_PWD: "${{ secrets.APPLE_KEYCHAIN_PWD }}"
|
||||
FASTLANE_MATCH_PWD: "${{ secrets.FASTLANE_MATCH_PWD }}"
|
||||
FASTLANE_MATCH_TOKEN: "${{ secrets.FASTLANE_MATCH_TOKEN }}"
|
||||
- name: Pack Techmino
|
||||
run: |
|
||||
mv Techmino.dmg Techmino_a${{ needs.get-info.outputs.release }}_MacOS.dmg
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino_a${{ needs.get-info.outputs.release }}_MacOS.dmg
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: release
|
||||
ARTIFACT_PLATFORM: MacOS
|
||||
ARTIFACT_NAME: Techmino_a${{ needs.get-info.outputs.release }}_MacOS.dmg
|
||||
|
||||
build-iOS:
|
||||
runs-on: macos-latest
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/snapshot-update
|
||||
with:
|
||||
commit: ${{ needs.get-info.outputs.commit }}
|
||||
- uses: ./.github/actions/build-ios
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.name }}
|
||||
type: 'release'
|
||||
APPLE_API_ID: '${{ secrets.APPLE_API_ID }}'
|
||||
APPLE_API_ISSUER: '${{ secrets.APPLE_API_ISSUER }}'
|
||||
APPLE_API_KEY: '${{ secrets.APPLE_API_KEY }}'
|
||||
APPLE_APP_BUILD: '${{ needs.get-info.outputs.code }}.0.${{ github.run_number }}.${{ github.run_attempt }}'
|
||||
APPLE_APP_CHANGELOG: '${{ github.event.commits[0].message }}'
|
||||
APPLE_APP_ID: '${{ secrets.APPLE_APP_ID }}'
|
||||
APPLE_APP_IDENTIFIER: '${{ secrets.APPLE_APP_IDENTIFIER }}'
|
||||
APPLE_APP_PROFILE: '${{ secrets.APPLE_APP_PROFILE }}'
|
||||
APPLE_KEYCHAIN_NAME: '${{ secrets.APPLE_KEYCHAIN_NAME }}'
|
||||
APPLE_KEYCHAIN_PWD: '${{ secrets.APPLE_KEYCHAIN_PWD }}'
|
||||
FASTLANE_DISCORD_WEBHOOK: '${{ secrets.FASTLANE_DISCORD_WEBHOOK }}'
|
||||
FASTLANE_MATCH_PWD: '${{ secrets.FASTLANE_MATCH_PWD }}'
|
||||
FASTLANE_MATCH_TOKEN: '${{ secrets.FASTLANE_MATCH_TOKEN }}'
|
||||
- name: Rename ipa
|
||||
shell: bash
|
||||
run: |
|
||||
mv Techmino.ipa Techmino.a${{ needs.get-info.outputs.release }}.ipa
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino.a${{ needs.get-info.outputs.release }}.ipa
|
||||
|
||||
build-love:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update Version
|
||||
run: |
|
||||
python3 .github/workflows/updateVersion.py -T Version
|
||||
- uses: ./.github/actions/build-love
|
||||
with:
|
||||
file-path: Techmino.a${{ needs.get-info.outputs.release }}.love
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino.a${{ needs.get-info.outputs.release }}.love
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/update-version
|
||||
- uses: ./.github/actions/build-ios
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.name }}
|
||||
type: "release"
|
||||
APPLE_API_ID: "${{ secrets.APPLE_API_ID }}"
|
||||
APPLE_API_ISSUER: "${{ secrets.APPLE_API_ISSUER }}"
|
||||
APPLE_API_KEY: "${{ secrets.APPLE_API_KEY }}"
|
||||
APPLE_APP_BUILD: "${{ needs.get-info.outputs.code }}.0.${{ github.run_number }}.${{ github.run_attempt }}"
|
||||
APPLE_APP_CHANGELOG: "${{ needs.get-info.outputs.updateNote }}"
|
||||
APPLE_APP_ID: "${{ secrets.APPLE_APP_ID }}"
|
||||
APPLE_APP_IDENTIFIER: "${{ secrets.APPLE_APP_IDENTIFIER }}"
|
||||
APPLE_APP_PROFILE: "${{ secrets.APPLE_APP_PROFILE }}"
|
||||
APPLE_KEYCHAIN_NAME: "${{ secrets.APPLE_KEYCHAIN_NAME }}"
|
||||
APPLE_KEYCHAIN_PWD: "${{ secrets.APPLE_KEYCHAIN_PWD }}"
|
||||
FASTLANE_ACTION_ID: "${{ github.run_id }}"
|
||||
FASTLANE_DISCORD_WEBHOOK: "${{ secrets.FASTLANE_DISCORD_WEBHOOK }}"
|
||||
FASTLANE_MATCH_PWD: "${{ secrets.FASTLANE_MATCH_PWD }}"
|
||||
FASTLANE_MATCH_TOKEN: "${{ secrets.FASTLANE_MATCH_TOKEN }}"
|
||||
- name: Rename ipa
|
||||
shell: bash
|
||||
run: |
|
||||
mv Techmino.ipa Techmino_a${{ needs.get-info.outputs.release }}_iOS.ipa
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino_a${{ needs.get-info.outputs.release }}_iOS.ipa
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: release
|
||||
ARTIFACT_PLATFORM: iOS
|
||||
ARTIFACT_NAME: Techmino_a${{ needs.get-info.outputs.release }}_iOS.ipa
|
||||
|
||||
Add-Release-note:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install lua
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get upgrade -y
|
||||
sudo apt-get install lua5.3 -y
|
||||
- name: Get ReleaseNote
|
||||
run: |
|
||||
lua .github/workflows/getVersion.lua -updateNote > updateNote.txt
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
body_path: updateNote.txt
|
||||
- uses: actions/checkout@v2
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
body: ${{ needs.get-info.outputs.updateNote }}
|
||||
|
||||
81
.github/workflows/test.yml
vendored
81
.github/workflows/test.yml
vendored
@@ -33,9 +33,10 @@ jobs:
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/snapshot-update
|
||||
- uses: ./.github/actions/update-version
|
||||
with:
|
||||
commit: ${{ needs.get-info.outputs.commit }}
|
||||
type: snapshot
|
||||
- uses: ./.github/actions/build-windows
|
||||
with:
|
||||
love-url: https://github.com/love2d/love/releases/download/11.3/love-11.3-win64.zip
|
||||
@@ -46,34 +47,59 @@ jobs:
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Techmino.pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}.Windows
|
||||
name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Windows
|
||||
path: love
|
||||
- name: Pack Techmino
|
||||
run: 7z a -tzip .\Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Windows.zip .\love
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: test
|
||||
ARTIFACT_PLATFORM: Windows
|
||||
ARTIFACT_NAME: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Windows.zip
|
||||
# - name: Upload artifact to server
|
||||
# run: |
|
||||
# curl --user "${{ secrets.WEBDAV_USERNAME }}:${{ secrets.WEBDAV_PASSWORD }}" -T Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Windows.zip http://mc.yuhao7370.top:5212/dav/Techmino%20Snapshots/ -v
|
||||
|
||||
build-linux:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/snapshot-update
|
||||
- uses: ./.github/actions/update-version
|
||||
with:
|
||||
commit: ${{ needs.get-info.outputs.commit }}
|
||||
type: snapshot
|
||||
- uses: ./.github/actions/build-linux
|
||||
with:
|
||||
icon: .github/build/Linux/icon_snapshot.png
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Techmino.pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}.Linux
|
||||
name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Linux
|
||||
path: Techmino.AppImage
|
||||
- name: Pack Techmino
|
||||
run: mv Techmino.AppImage Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Linux.AppImage
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: test
|
||||
ARTIFACT_PLATFORM: Linux
|
||||
ARTIFACT_NAME: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Linux.AppImage
|
||||
|
||||
build-android:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/snapshot-update
|
||||
- uses: ./.github/actions/update-version
|
||||
with:
|
||||
commit: ${{ needs.get-info.outputs.commit }}
|
||||
type: snapshot
|
||||
- uses: ./.github/actions/build-android
|
||||
with:
|
||||
type: Snapshot
|
||||
@@ -87,17 +113,28 @@ jobs:
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Techmino.pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}.Android
|
||||
name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Android
|
||||
path: Techmino_Snapshot.apk
|
||||
- name: Pack Techmino
|
||||
run: mv Techmino_Snapshot.apk Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Android.apk
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: test
|
||||
ARTIFACT_PLATFORM: Android
|
||||
ARTIFACT_NAME: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Android.apk
|
||||
|
||||
build-macOS:
|
||||
runs-on: macos-10.15
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/snapshot-update
|
||||
- uses: ./.github/actions/update-version
|
||||
with:
|
||||
commit: ${{ needs.get-info.outputs.commit }}
|
||||
type: snapshot
|
||||
- uses: ./.github/actions/build-macos
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.name }}
|
||||
@@ -113,17 +150,28 @@ jobs:
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Techmino.pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}.macOS
|
||||
name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_MacOS
|
||||
path: Techmino.dmg
|
||||
- name: Pack Techmino
|
||||
run: mv Techmino.dmg Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_MacOS.dmg
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: test
|
||||
ARTIFACT_PLATFORM: MacOS
|
||||
ARTIFACT_NAME: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_MacOS.dmg
|
||||
|
||||
build-iOS:
|
||||
runs-on: macos-latest
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/snapshot-update
|
||||
- uses: ./.github/actions/update-version
|
||||
with:
|
||||
commit: ${{ needs.get-info.outputs.commit }}
|
||||
type: snapshot
|
||||
- uses: ./.github/actions/build-ios
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.name }}
|
||||
@@ -138,11 +186,22 @@ jobs:
|
||||
APPLE_APP_PROFILE: '${{ secrets.APPLE_APP_PROFILE }}'
|
||||
APPLE_KEYCHAIN_NAME: '${{ secrets.APPLE_KEYCHAIN_NAME }}'
|
||||
APPLE_KEYCHAIN_PWD: '${{ secrets.APPLE_KEYCHAIN_PWD }}'
|
||||
FASTLANE_ACTION_ID: '${{ github.run_id }}'
|
||||
FASTLANE_DISCORD_WEBHOOK: '${{ secrets.FASTLANE_DISCORD_WEBHOOK }}'
|
||||
FASTLANE_MATCH_PWD: '${{ secrets.FASTLANE_MATCH_PWD }}'
|
||||
FASTLANE_MATCH_TOKEN: '${{ secrets.FASTLANE_MATCH_TOKEN }}'
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Techmino.pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}.iOS
|
||||
path: "Techmino.ipa"
|
||||
name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_iOS
|
||||
path: Techmino.ipa
|
||||
- name: Pack Techmino
|
||||
run: mv Techmino.ipa Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_iOS.ipa
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: test
|
||||
ARTIFACT_PLATFORM: iOS
|
||||
ARTIFACT_NAME: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_iOS.ipa
|
||||
|
||||
100
.github/workflows/updateVersion.py
vendored
100
.github/workflows/updateVersion.py
vendored
@@ -1,100 +0,0 @@
|
||||
import argparse
|
||||
import re
|
||||
|
||||
def updateConf(): #更新存档位置
|
||||
with open('conf.lua', 'r+', encoding='utf-8') as file:
|
||||
data = file.read()
|
||||
data = data.replace("t.identity='Techmino'--Saving folder", "t.identity='Techmino_Snapshot'--Saving folder")
|
||||
file.seek(0)
|
||||
file.truncate()
|
||||
file.flush()
|
||||
file.write(data)
|
||||
|
||||
def updateVersion(args): #更新版本号
|
||||
with open('version.lua', 'r+', encoding='utf-8') as file:
|
||||
data = file.read()
|
||||
if args.Hash != False:
|
||||
data = data.replace('@DEV', f'@{args.Hash[0:4]}')
|
||||
else:
|
||||
data = data.replace('@DEV', '')
|
||||
file.seek(0)
|
||||
file.truncate()
|
||||
file.flush()
|
||||
file.write(data)
|
||||
|
||||
def updateMacOS(args): #更新macOS打包信息
|
||||
import datetime
|
||||
thisYear = str(datetime.datetime.today().year)
|
||||
with open('./.github/build/macOS/info.plist.template', 'r', encoding='utf-8') as file:
|
||||
data = file.read()
|
||||
data = data\
|
||||
.replace('@versionName', args.Name[1:])\
|
||||
.replace('@thisYear', thisYear)\
|
||||
.replace('@bundleId', args.Bundle)
|
||||
with open('./Techmino-macOS/Techmino.app/Contents/info.plist', 'w+', encoding='utf-8') as file:
|
||||
file.write(data)
|
||||
|
||||
def updateWindows(args): #更新Windows打包信息
|
||||
Version = (args.Name).replace('V', '')
|
||||
FileVersion = (f"{Version.replace('.', ',')},0")
|
||||
with open('./.github/build/Windows/Techmino.rc.template', 'r', encoding='utf8') as file:
|
||||
data = file.read()
|
||||
data = data\
|
||||
.replace('@FileVersion', FileVersion)\
|
||||
.replace('@Version', Version)
|
||||
with open('Techmino.rc', 'w+', encoding='utf8') as file:
|
||||
file.write(data)
|
||||
|
||||
def updateAndroid(args, edition): #更新Android打包信息
|
||||
if edition == 'Release':
|
||||
appName = 'Techmino'
|
||||
packageName = 'org.love2d.MrZ.Techmino'
|
||||
edition = 'release'
|
||||
elif edition == 'Snapshot':
|
||||
appName = 'Techmino_Snapshot'
|
||||
packageName = 'org.love2d.MrZ.Techmino.Snapshot'
|
||||
edition = 'snapshot'
|
||||
with open('./love-android/app/src/main/AndroidManifest.xml', "r+", encoding='utf-8') as file:
|
||||
data = file.read()
|
||||
data = data\
|
||||
.replace('@appName', appName)\
|
||||
.replace('@edition', edition)
|
||||
file.seek(0)
|
||||
file.truncate()
|
||||
file.write(data)
|
||||
with open("./love-android/app/build.gradle", "r+", encoding='utf-8') as file:
|
||||
data = file.read()
|
||||
data = data\
|
||||
.replace('@packageName', packageName)\
|
||||
.replace('@versionCode', args.Code)\
|
||||
.replace('@versionName', args.Name)\
|
||||
.replace('@storePassword', args.Store)\
|
||||
.replace('@keyAlias', args.Alias)\
|
||||
.replace('@keyPassword', args.Key)
|
||||
file.seek(0)
|
||||
file.truncate()
|
||||
file.write(data)
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='用于CI更新程序各类信息')
|
||||
parser.add_argument('-T', '--Type', type=str, help = '更新的种类')
|
||||
parser.add_argument('-B', '--Bundle', type=str, help = '应用包名')
|
||||
parser.add_argument('-H', '--Hash', type=str, default = False, help = 'Github提交Hash')
|
||||
parser.add_argument('-C', '--Code', type=str, default = False, help = 'versionCode')
|
||||
parser.add_argument('-N', '--Name', type=str, default = False, help = 'versionName')
|
||||
parser.add_argument('-S', '--Store', type=str, default = False, help = 'storePassword')
|
||||
parser.add_argument('-A', '--Alias', type=str, default = False, help = 'keyAlias')
|
||||
parser.add_argument('-K', '--Key', type=str, default = False, help = 'keyPassword')
|
||||
args = parser.parse_args()
|
||||
if args.Type == 'Conf':
|
||||
updateConf()
|
||||
elif args.Type == 'Version':
|
||||
updateVersion(args)
|
||||
elif args.Type == 'Windows':
|
||||
updateWindows(args)
|
||||
elif args.Type == 'macOS':
|
||||
updateMacOS(args)
|
||||
elif args.Type == 'AndroidRelease':
|
||||
updateAndroid(args, 'Release')
|
||||
elif args.Type == 'AndroidSnapshot':
|
||||
updateAndroid(args, 'Snapshot')
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,3 +1,8 @@
|
||||
.vscode
|
||||
libAndroid
|
||||
*.ini
|
||||
*.ini
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
Icon?
|
||||
.Trash
|
||||
.file
|
||||
|
||||
@@ -1,63 +1,80 @@
|
||||
local abs=math.abs
|
||||
local function hsv(h,s,v,a)
|
||||
if s<=0 then return v,v,v,a end
|
||||
h=h*6
|
||||
local c=v*s
|
||||
local x=abs((h-1)%2-1)*c
|
||||
if h<1 then return v,x+v-c,v-c,a
|
||||
elseif h<2 then return x+v-c,v,v-c,a
|
||||
elseif h<3 then return v-c,v,x+v-c,a
|
||||
elseif h<4 then return v-c,x+v-c,v,a
|
||||
elseif h<5 then return x+v-c,v-c,v,a
|
||||
else return v,v-c,x+v-c,a
|
||||
end
|
||||
end
|
||||
|
||||
local COLOR={
|
||||
red= {.92, .12, .12},
|
||||
fire= {.92, 0.4, .12},
|
||||
orange= {.92, 0.6, .12},
|
||||
yellow= {.92, .92, .12},
|
||||
lime= {0.7, .92, .12},
|
||||
jade= {0.5, .92, .12},
|
||||
green= {.12, .92, .12},
|
||||
aqua= {.12, .92, 0.6},
|
||||
cyan= {.12, .92, .92},
|
||||
navy= {.12, 0.7, .92},
|
||||
sea= {.12, 0.4, .92},
|
||||
blue= {0.2, 0.2, .92},
|
||||
violet= {0.4, .12, .92},
|
||||
purple= {0.7, .12, .92},
|
||||
magenta= {.92, .12, .92},
|
||||
wine= {.92, .12, 0.5},
|
||||
hsv=hsv,
|
||||
|
||||
lRed= {.95, 0.5, 0.5},
|
||||
lFire= {.95, 0.7, 0.5},
|
||||
lOrange= {.95, 0.8, 0.3},
|
||||
lYellow= {.95, .95, 0.5},
|
||||
lLime= {0.8, .95, 0.4},
|
||||
lJade= {0.6, .95, 0.4},
|
||||
lGreen= {0.5, .95, 0.5},
|
||||
lAqua= {0.4, .95, 0.7},
|
||||
lCyan= {0.5, .95, .95},
|
||||
lNavy= {0.4, .85, .95},
|
||||
lSea= {0.5, 0.7, .95},
|
||||
lBlue= {0.7, 0.7, .95},
|
||||
lViolet= {0.7, 0.4, .95},
|
||||
lPurple= {0.8, 0.4, .95},
|
||||
lMagenta={.95, 0.5, .95},
|
||||
lWine= {.95, 0.4, 0.7},
|
||||
red= {hsv(0.00, 0.89, 0.91)},
|
||||
fire= {hsv(0.04, 0.93, 0.94)},
|
||||
orange= {hsv(0.09, 0.99, 0.96)},
|
||||
yellow= {hsv(0.16, 0.82, 0.90)},
|
||||
lime= {hsv(0.18, 0.89, 0.88)},
|
||||
jade= {hsv(0.23, 1.00, 0.82)},
|
||||
green= {hsv(0.33, 1.00, 0.81)},
|
||||
aqua= {hsv(0.48, 1.00, 0.74)},
|
||||
cyan= {hsv(0.53, 1.00, 0.88)},
|
||||
navy= {hsv(0.56, 1.00, 1.00)},
|
||||
sea= {hsv(0.61, 1.00, 1.00)},
|
||||
blue= {hsv(0.64, 1.00, 0.95)},
|
||||
violet= {hsv(0.73, 1.00, 0.91)},
|
||||
purple= {hsv(0.80, 1.00, 0.81)},
|
||||
magenta= {hsv(0.86, 1.00, 0.78)},
|
||||
wine= {hsv(0.94, 0.96, 0.91)},
|
||||
|
||||
dRed= {0.6, .08, .08},
|
||||
dFire= {0.6, 0.3, .08},
|
||||
dOrange= {0.6, 0.4, .08},
|
||||
dYellow= {0.6, 0.6, .08},
|
||||
dLime= {0.5, 0.6, .08},
|
||||
dJade= {0.3, 0.6, .08},
|
||||
dGreen= {.08, 0.6, .08},
|
||||
dAqua= {.08, 0.6, 0.4},
|
||||
dCyan= {.08, 0.6, 0.6},
|
||||
dNavy= {.08, 0.4, 0.6},
|
||||
dSea= {.08, 0.2, 0.6},
|
||||
dBlue= {0.1, 0.1, 0.6},
|
||||
dViolet= {0.2, .08, 0.6},
|
||||
dPurple= {0.4, .08, 0.6},
|
||||
dMagenta={0.6, .08, 0.6},
|
||||
dWine= {0.6, .08, 0.3},
|
||||
lRed= {hsv(0.00, 0.38, 0.93)},
|
||||
lFire= {hsv(0.04, 0.45, 0.91)},
|
||||
lOrange= {hsv(0.10, 0.53, 0.92)},
|
||||
lYellow= {hsv(0.15, 0.61, 0.95)},
|
||||
lLime= {hsv(0.19, 0.66, 0.92)},
|
||||
lJade= {hsv(0.24, 0.56, 0.90)},
|
||||
lGreen= {hsv(0.34, 0.49, 0.89)},
|
||||
lAqua= {hsv(0.49, 0.59, 0.85)},
|
||||
lCyan= {hsv(0.51, 0.77, 0.88)},
|
||||
lNavy= {hsv(0.54, 0.80, 0.95)},
|
||||
lSea= {hsv(0.56, 0.72, 0.97)},
|
||||
lBlue= {hsv(0.64, 0.44, 0.96)},
|
||||
lViolet= {hsv(0.73, 0.47, 0.95)},
|
||||
lPurple= {hsv(0.80, 0.62, 0.89)},
|
||||
lMagenta= {hsv(0.86, 0.61, 0.89)},
|
||||
lWine= {hsv(0.93, 0.57, 0.92)},
|
||||
|
||||
black= {.05, .05, .05},
|
||||
dGray= {0.3, 0.3, 0.3},
|
||||
gray= {0.6, 0.6, 0.6},
|
||||
lGray= {0.8, 0.8, 0.8},
|
||||
white= {.97, .97, .97},
|
||||
dRed= {hsv(0.00, 0.80, 0.48)},
|
||||
dFire= {hsv(0.04, 0.80, 0.34)},
|
||||
dOrange= {hsv(0.07, 0.80, 0.39)},
|
||||
dYellow= {hsv(0.11, 0.80, 0.37)},
|
||||
dLime= {hsv(0.17, 0.80, 0.26)},
|
||||
dJade= {hsv(0.31, 0.80, 0.27)},
|
||||
dGreen= {hsv(0.33, 0.80, 0.26)},
|
||||
dAqua= {hsv(0.47, 0.80, 0.23)},
|
||||
dCyan= {hsv(0.50, 0.80, 0.30)},
|
||||
dNavy= {hsv(0.59, 0.80, 0.42)},
|
||||
dSea= {hsv(0.64, 0.80, 0.40)},
|
||||
dBlue= {hsv(0.67, 0.80, 0.34)},
|
||||
dViolet= {hsv(0.71, 0.80, 0.35)},
|
||||
dPurple= {hsv(0.76, 0.80, 0.32)},
|
||||
dMagenta= {hsv(0.87, 0.80, 0.28)},
|
||||
dWine= {hsv(0.92, 0.80, 0.28)},
|
||||
|
||||
black= {hsv(0.04, 0.04, 0.14)},
|
||||
dGray= {hsv(0.02, 0.05, 0.44)},
|
||||
gray= {hsv(0.02, 0.05, 0.65)},
|
||||
lGray= {hsv(0.02, 0.06, 0.86)},
|
||||
white= {hsv(0.01, 0.02, 0.99)},
|
||||
}
|
||||
for k,v in next,{
|
||||
R='red', F='fire', O='orange', Y='yellow', L='lime', J='jade', G='green', A='aqua', C='cyan', N='navy', S='sea', B='blue', V='violet', P='purple', M='magenta', W='wine',
|
||||
R='red', F='fire', O='orange', Y='yellow', L='lime', J='jade', G='green', A='aqua', C='cyan', N='navy', S='sea', B='blue', V='violet', P='purple', M='magenta', W='wine',
|
||||
lR='lRed',lF='lFire',lO='lOrange',lY='lYellow',lL='lLime',lJ='lJade',lG='lGreen',lA='lAqua',lC='lCyan',lN='lNavy',lS='lSea',lB='lBlue',lV='lViolet',lP='lPurple',lM='lMagenta',lW='lWine',
|
||||
dR='dRed',dF='dFire',dO='dOrange',dY='dYellow',dL='dLime',dJ='dJade',dG='dGreen',dA='dAqua',dC='dCyan',dN='dNavy',dS='dSea',dB='dBlue',dV='dViolet',dP='dPurple',dM='dMagenta',dW='dWine',
|
||||
D='black',dH='dGray',H='gray',lH='lGray',Z='white',
|
||||
|
||||
@@ -9,6 +9,8 @@ TABLE= require'Zframework.tableExtend'
|
||||
STRING= require'Zframework.stringExtend'
|
||||
PROFILE= require'Zframework.profile'
|
||||
JSON= require'Zframework.json'
|
||||
TEST= require'Zframework.test'
|
||||
|
||||
do--Add pcall & MES for JSON lib
|
||||
local encode,decode=JSON.encode,JSON.decode
|
||||
JSON.encode=function(val)
|
||||
@@ -620,9 +622,8 @@ function love.run()
|
||||
--Left-down infos
|
||||
gc_setColor(devColor[devMode])
|
||||
gc_print("MEM "..gcinfo(),safeX+5,-40)
|
||||
gc_print("Lines "..FREEROW.getCount(),safeX+5,-60)
|
||||
gc_print("Tasks "..TASK.getCount(),safeX+5,-80)
|
||||
gc_print("Voices "..VOC.getQueueCount(),safeX+5,-100)
|
||||
gc_print("Tasks "..TASK.getCount(),safeX+5,-60)
|
||||
gc_print("Voices "..VOC.getQueueCount(),safeX+5,-80)
|
||||
|
||||
--Update & draw frame time
|
||||
table.insert(frameTimeList,1,dt)table.remove(frameTimeList,126)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local type,rem=type,table.remove
|
||||
local rnd=math.random
|
||||
|
||||
local sfxList={}
|
||||
local packSetting={}
|
||||
@@ -55,14 +56,14 @@ function SFX.loadSample(pack)
|
||||
assert(type(pack)=='table',"Usage: SFX.loadsample([table])")
|
||||
assert(pack.name,"No field: name")
|
||||
assert(pack.path,"No field: path")
|
||||
packSetting[pack.name]={
|
||||
base=(_getTuneHeight(pack.base)or 37)-1,
|
||||
}
|
||||
local num=1
|
||||
while love.filesystem.getInfo(pack.path..'/'..num..'.ogg')do
|
||||
Sources[pack.name..num]={love.audio.newSource(pack.path..'/'..num..'.ogg','static')}
|
||||
num=num+1
|
||||
end
|
||||
local base=(_getTuneHeight(pack.base)or 37)-1
|
||||
local top=base+num-1
|
||||
packSetting[pack.name]={base=base,top=top}
|
||||
LOG((num-1).." "..pack.name.." samples loaded")
|
||||
end
|
||||
|
||||
@@ -87,14 +88,21 @@ function SFX.playSample(pack,...)--vol-2, sampSet1, vol-3, sampSet2, vol-1
|
||||
if type(arg[i])=='number'then
|
||||
vol=arg[i]
|
||||
else
|
||||
local tune=arg[i]
|
||||
tune=_getTuneHeight(tune)-packSetting[pack].base
|
||||
SFX.play(pack..tune,vol)
|
||||
local base=packSetting[pack].base
|
||||
local top=packSetting[pack].top
|
||||
local tune=_getTuneHeight(arg[i])--Absolute tune in number
|
||||
local playTune=tune+rnd(-2,2)
|
||||
if playTune<base then--Too low notes
|
||||
playTune=base
|
||||
elseif playTune>top then--Too high notes
|
||||
playTune=top
|
||||
end
|
||||
SFX.play(pack..playTune-base,vol,nil,tune-playTune)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function SFX.play(name,vol,pos)
|
||||
function SFX.play(name,vol,pos,pitch)
|
||||
if volume==0 or vol==0 then return end
|
||||
local S=Sources[name]--Source list
|
||||
if not S then return end
|
||||
@@ -117,6 +125,7 @@ function SFX.play(name,vol,pos)
|
||||
end
|
||||
end
|
||||
S:setVolume(((vol or 1)*volume)^1.626)
|
||||
S:setPitch(pitch and 1.0594630943592953^pitch or 1)
|
||||
S:play()
|
||||
end
|
||||
function SFX.fplay(name,vol,pos)
|
||||
|
||||
@@ -23,7 +23,7 @@ function TASK.update(dt)
|
||||
end
|
||||
function TASK.new(code,...)
|
||||
local thread=coroutine.create(code)
|
||||
resume(thread,...)
|
||||
assert(resume(thread,...))
|
||||
if status(thread)~='dead'then
|
||||
tasks[#tasks+1]={
|
||||
thread=thread,
|
||||
|
||||
12
Zframework/test.lua
Normal file
12
Zframework/test.lua
Normal file
@@ -0,0 +1,12 @@
|
||||
local TEST={}
|
||||
|
||||
--Wait for the scene swapping animation to finish
|
||||
function TEST.yieldUntilNextScene()
|
||||
while SCN.swapping do YIELD()end
|
||||
end
|
||||
|
||||
function TEST.yieldN(frames)
|
||||
for _=1,frames do YIELD()end
|
||||
end
|
||||
|
||||
return TEST
|
||||
@@ -435,7 +435,7 @@ end
|
||||
function switch:press()
|
||||
self.code()
|
||||
if self.sound then
|
||||
SFX.play('move')
|
||||
SFX.play('touch')
|
||||
end
|
||||
end
|
||||
function WIDGET.newSwitch(D)--name,x,y[,lim][,fText][,color][,font=30][,sound=true][,disp],code[,hideF][,hide]
|
||||
@@ -1431,7 +1431,7 @@ function WIDGET.textinput(texts)
|
||||
if W and W.type=='inputBox'then
|
||||
if(not W.regex or texts:match(W.regex))and(not W.limit or #(WIDGET.sel.value..texts)<=W.limit)then
|
||||
WIDGET.sel.value=WIDGET.sel.value..texts
|
||||
SFX.play('move')
|
||||
SFX.play('touch')
|
||||
else
|
||||
SFX.play('finesseError',.3)
|
||||
end
|
||||
|
||||
13
legals.md
13
legals.md
@@ -2,11 +2,7 @@
|
||||
TECHMINO and "26F Studio" are trademarks of 26F Studio.
|
||||
The TECHMINO game and source code are under a GNU Lesser General Public License Version 3.
|
||||
|
||||
|
||||
TECHMINO is not a fan game of Tetris. TECHMINO and 26F Studio are not affiliated with Tetris Holding, LLC or The Tetris Company, Inc. in any way.
|
||||
|
||||
|
||||
"Tetris" is the registered trademark of The Tetris Holding, LLC, licensed to The Tetris Company, Inc.
|
||||
"Tetris" is the registered trademark of The Tetris Holding, LLC, licensed to The Tetris Company, Inc. TECHMINO is not a fan game of Tetris. TECHMINO and 26F Studio are not affiliated with Tetris Holding, LLC or The Tetris Company, Inc. in any way.
|
||||
|
||||
|
||||
Powered by LÖVE, © 2006-2021 LÖVE Development Team.
|
||||
@@ -21,7 +17,10 @@ The Apple logo, "Apple Inc.," iOS, iPadOS, macOS, iPhone, and Mac are registered
|
||||
"Windows", the Windows logo, "Xbox", Xbox logo, and "Microsoft" are registered trademarks of Microsoft Corporation in the United States of America and other countries or regions.
|
||||
|
||||
|
||||
Alibaba Sans is copyrighted by Alibaba Group Holding Limited. Alibaba is a trademark of Alibaba Group Holding Limited in the People’s Republic of China and other countries or regions.
|
||||
Source Han Sans is copyrighted by Adobe Inc. Source Han Sans and Abode are registered trademarks of Adobe Inc. in United States and other countries or regions. Source Han Sans is licensed under the SIL Open Font License.
|
||||
|
||||
|
||||
IBM Plex is copyrighted by the International Business Machines Corporation. IBM and IBM Plex are trademarks of IBM Corp, registered in many jurisdictions worldwide. IBM Plex is licensed under the SIL Open Font License.
|
||||
|
||||
|
||||
JetBrains Mono is copyrighted by the JetBrains Mono Project authors. JetBrains Mono is a trademark of JetBrains s.r.o. JetBrains Mono is licensed under the SIL Open Font License, Version 1.1.
|
||||
@@ -47,5 +46,5 @@ Linux is a registered trademark of Linus Torvalds.
|
||||
|
||||
Touhou Project © Team Shanghai Alice 2002-2021.
|
||||
|
||||
|
||||
All other trademarks are the properties of their respective owners.
|
||||
|
||||
|
||||
115
main.lua
115
main.lua
@@ -90,7 +90,7 @@ for _,v in next,fs.getDirectoryItems('parts/shaders')do
|
||||
end
|
||||
end
|
||||
|
||||
FREEROW= require'parts.freeRow'
|
||||
LINE= require'parts.line'
|
||||
DATA= require'parts.data'
|
||||
|
||||
TEXTURE= require'parts.texture'
|
||||
@@ -104,6 +104,12 @@ PLY= require'parts.player'
|
||||
NETPLY= require'parts.netPlayer'
|
||||
MODES= require'parts.modes'
|
||||
|
||||
setmetatable(TEXTURE,{__index=function(self,k)
|
||||
MES.new('warn',"No texture called: "..k)
|
||||
self[k]=love.graphics.newCanvas(1,1)
|
||||
return self[k]
|
||||
end})
|
||||
|
||||
table.insert(_LOADTIMELIST_,("Load Parts: %.3fs"):format(TIME()-_LOADTIME_))
|
||||
|
||||
--Init Zframework
|
||||
@@ -143,8 +149,8 @@ Z.setOnFnKeys({
|
||||
function()
|
||||
if GAME.playing and not GAME.net then
|
||||
for _=1,8 do
|
||||
local P=PLY_ALIVE[math.random(#PLY_ALIVE)]
|
||||
if P and P~=PLAYERS[1]then
|
||||
if #PLY_ALIVE>1 then
|
||||
local P=PLY_ALIVE[math.random(2,#PLY_ALIVE)]
|
||||
P.lastRecv=PLAYERS[1]
|
||||
P:lose()
|
||||
end
|
||||
@@ -153,7 +159,7 @@ Z.setOnFnKeys({
|
||||
end,
|
||||
function()print(WIDGET.getSelected()or"no widget selected")end,
|
||||
function()for k,v in next,_G do print(k,v)end end,
|
||||
function()if love["_openConsole"]then love["_openConsole"]()end end,
|
||||
function()if love['_openConsole']then love['_openConsole']()end end,
|
||||
})
|
||||
do--Z.setOnFocus
|
||||
local function task_autoSoundOff()
|
||||
@@ -222,7 +228,7 @@ if missionData then
|
||||
DATA.pasteMission(missionData)
|
||||
end
|
||||
local customData=FILE.load('conf/customEnv')
|
||||
if customData and customData.version==VERSION.code then
|
||||
if customData and customData['version']==VERSION.code then
|
||||
TABLE.complete(customData,CUSTOMENV)
|
||||
end
|
||||
TABLE.complete(require"parts.customEnv0",CUSTOMENV)
|
||||
@@ -325,6 +331,7 @@ LANG.init('zh',
|
||||
{
|
||||
zh=require'parts.language.lang_zh',
|
||||
zh_full=require'parts.language.lang_zh_full',
|
||||
zh_trad=require'parts.language.lang_zh_trad',
|
||||
en=require'parts.language.lang_en',
|
||||
fr=require'parts.language.lang_fr',
|
||||
es=require'parts.language.lang_es',
|
||||
@@ -334,7 +341,7 @@ LANG.init('zh',
|
||||
symbol=require'parts.language.lang_symbol',
|
||||
--1. Add language file to LANG folder;
|
||||
--2. Require it;
|
||||
--3. Add a button in parts/scenes/setting_lang.lua;
|
||||
--3. Add a button in parts/scenes/lang.lua;
|
||||
},
|
||||
{
|
||||
block=BLOCK_NAMES
|
||||
@@ -382,8 +389,11 @@ end
|
||||
for _,v in next,fs.getDirectoryItems('parts/modes')do
|
||||
if isSafeFile('parts/modes/'..v)and not MODES[v:sub(1,-5)]then
|
||||
local M={name=v:sub(1,-5)}
|
||||
TABLE.complete(require('parts.modes.'..M.name),M)
|
||||
MODES[M.name]=M
|
||||
local modeData=require('parts.modes.'..M.name)
|
||||
if modeData.env then
|
||||
TABLE.complete(modeData,M)
|
||||
MODES[M.name]=M
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -440,6 +450,14 @@ do
|
||||
fs.remove('record/round_l.rec')
|
||||
fs.remove('record/round_u.rec')
|
||||
end
|
||||
if RANKS.stack_e then
|
||||
RANKS.stack_e=nil
|
||||
RANKS.stack_h=nil
|
||||
RANKS.stack_u=nil
|
||||
fs.remove('record/stack_e.rec')
|
||||
fs.remove('record/stack_h.rec')
|
||||
fs.remove('record/stack_u.rec')
|
||||
end
|
||||
if RANKS.stack_20l then
|
||||
RANKS.stack_20l=nil
|
||||
RANKS.stack_40l=nil
|
||||
@@ -448,17 +466,37 @@ do
|
||||
fs.remove('record/stack_40l.rec')
|
||||
fs.remove('record/stack_100l.rec')
|
||||
end
|
||||
if RANKS.rhythm_e then
|
||||
RANKS.rhythm_e=nil
|
||||
RANKS.rhythm_h=nil
|
||||
RANKS.rhythm_u=nil
|
||||
fs.remove('record/rhythm_e.rec')
|
||||
fs.remove('record/rhythm_h.rec')
|
||||
fs.remove('record/rhythm_u.rec')
|
||||
end
|
||||
if STAT.version~=VERSION.code then
|
||||
for k,v in next,MODE_UPDATE_MAP do
|
||||
if RANKS[k]then
|
||||
RANKS[v]=RANKS[k]
|
||||
RANKS[k]=nil
|
||||
end
|
||||
k='record/'..k
|
||||
if fs.getInfo(k..'.dat')then
|
||||
fs.write('record/'..v..'.rec',fs.read(k..'.dat'))
|
||||
fs.remove(k..'.dat')
|
||||
end
|
||||
if fs.getInfo(k..'.rec')then
|
||||
fs.write('record/'..v..'.rec',fs.read(k..'.rec'))
|
||||
fs.remove(k..'.rec')
|
||||
end
|
||||
end
|
||||
STAT.version=VERSION.code
|
||||
needSave=true
|
||||
love.event.quit('restart')
|
||||
end
|
||||
SETTING.appLock=nil
|
||||
SETTING.dataSaving=nil
|
||||
SETTING.swap=nil
|
||||
SETTING.appLock,SETTING.dataSaving,SETTING.swap=nil
|
||||
if not SETTING.VKSkin then SETTING.VKSkin=1 end
|
||||
for _,v in next,SETTING.skin do if v<1 or v>17 then v=17 end end
|
||||
if SETTING.RS=='ZRS'or SETTING.RS=='BRS'or SETTING.RS=='ASCplus'or SETTING.RS=='C2sym'then SETTING.RS='TRS'end
|
||||
if not RSlist[SETTING.RS]then SETTING.RS='TRS'end
|
||||
if SETTING.ghostType=='greyCell'then SETTING.ghostType='grayCell'end
|
||||
if type(SETTING.skinSet)=='number'then SETTING.skinSet='crystal_scf'end
|
||||
if not TABLE.find({8,10,13,17,22,29,37,47,62,80,100},SETTING.frameMul)then SETTING.frameMul=100 end
|
||||
@@ -494,26 +532,11 @@ do
|
||||
needSave=true
|
||||
end
|
||||
|
||||
for k,v in next,MODE_UPDATE_MAP do
|
||||
if RANKS[k]then
|
||||
RANKS[v]=RANKS[k]
|
||||
RANKS[k]=nil
|
||||
end
|
||||
k='record/'..k
|
||||
if fs.getInfo(k..'.dat')then
|
||||
fs.write('record/'..v..'.rec',fs.read(k..'.dat'))
|
||||
fs.remove(k..'.dat')
|
||||
end
|
||||
if fs.getInfo(k..'.rec')then
|
||||
fs.write('record/'..v..'.rec',fs.read(k..'.rec'))
|
||||
fs.remove(k..'.rec')
|
||||
end
|
||||
end
|
||||
|
||||
if needSave then
|
||||
saveStats()
|
||||
saveProgress()
|
||||
saveSettings()
|
||||
love.event.quit('restart')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -576,3 +599,37 @@ table.sort(REPLAY,function(a,b)return a.fileName>b.fileName end)
|
||||
table.insert(_LOADTIMELIST_,("Initialize Data: %.3fs"):format(TIME()-_LOADTIME_))
|
||||
|
||||
for i=1,#_LOADTIMELIST_ do LOG(_LOADTIMELIST_[i])end
|
||||
|
||||
--Launch testing task if launch param received
|
||||
if TABLE.find(arg,'--test')then
|
||||
TASK.new(function()
|
||||
while not LOADED do YIELD()end
|
||||
|
||||
LOG("\27[92m\27[1mAutomatic Test Started\27[0m")
|
||||
BGM.setVol(0)SFX.setVol(0)
|
||||
love.keypressed('space')
|
||||
TEST.yieldUntilNextScene()
|
||||
|
||||
for k,mode in next,MODES do
|
||||
if k~='netBattle'then
|
||||
LOG("Scanning mode: "..mode.name)
|
||||
loadGame(mode.name,true)
|
||||
TEST.yieldUntilNextScene()
|
||||
SCN.back()
|
||||
TEST.yieldUntilNextScene()
|
||||
end
|
||||
end
|
||||
LOG("\27[92m\27[1mAutomatic Test Passed :)\27[0m")
|
||||
TEST.yieldN(60)
|
||||
love.event.quit(0)
|
||||
end)
|
||||
TASK.new(function()
|
||||
while true do
|
||||
YIELD()
|
||||
if ERRDATA[1]then break end
|
||||
end
|
||||
LOG("\27[91m\27[1mAutomatic Test Failed :(\27[0m\nThe error message is:\n"..table.concat(ERRDATA[1].mes,"\n").."\27[91m\nAborting\27[0m")
|
||||
TEST.yieldN(60)
|
||||
love.event.quit(1)
|
||||
end)
|
||||
end
|
||||
|
||||
BIN
media/music/1989.ogg
Normal file
BIN
media/music/1989.ogg
Normal file
Binary file not shown.
BIN
media/music/peak.ogg
Normal file
BIN
media/music/peak.ogg
Normal file
Binary file not shown.
@@ -686,13 +686,7 @@ do
|
||||
sfx='prerotate'
|
||||
elseif P:ifoverlap(icb,x,y+1)and P:ifoverlap(icb,x-1,y)and P:ifoverlap(icb,x+1,y)then
|
||||
sfx='rotatekick'
|
||||
if P.gameEnv.shakeFX then
|
||||
if d==1 or d==3 then
|
||||
P.fieldOff.va=P.fieldOff.va+(2-d)*6e-3
|
||||
else
|
||||
P.fieldOff.va=P.fieldOff.va+P:getCenterX()*3e-3
|
||||
end
|
||||
end
|
||||
P:_rotateField(d)
|
||||
else
|
||||
sfx='rotate'
|
||||
end
|
||||
|
||||
@@ -12,10 +12,9 @@ local ins,rem=table.insert,table.remove
|
||||
local back={}
|
||||
|
||||
local t
|
||||
local fan,petal
|
||||
local petal
|
||||
function back.init()
|
||||
t=0
|
||||
fan=SVG_TITLE_FAN
|
||||
petal={}
|
||||
end
|
||||
function back.update()
|
||||
@@ -62,7 +61,7 @@ function back.draw()
|
||||
|
||||
gc_setLineWidth(6)
|
||||
gc_setColor(.8,.9,1,.3)
|
||||
for i=1,8 do gc_polygon('line',fan[i])end
|
||||
for i=1,8 do gc_polygon('line',SVG_TITLE_FAN[i])end
|
||||
|
||||
gc_setLineWidth(2)
|
||||
gc_setColor(1,.5,.7,.3)
|
||||
|
||||
@@ -61,7 +61,7 @@ function back.draw()
|
||||
gc.setColor(wingColor[i])
|
||||
local B=crystals[i]
|
||||
gc.draw(crystal_img,B.x,B.y,B.a,k,k,21,0)
|
||||
B=crystals[17-i]
|
||||
B=crystals[8+i]
|
||||
gc.draw(crystal_img,B.x,B.y,B.a,-k,k,21,0)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,8 +44,7 @@ local function _ifoverlapAI(f,bk,x,y)
|
||||
end
|
||||
end end
|
||||
end
|
||||
local discardRow=FREEROW.discard
|
||||
local getRow=FREEROW.get
|
||||
local getRow,discardRow=LINE.new,LINE.discard
|
||||
local function _resetField(f0,f,start)
|
||||
for _=#f,start,-1 do
|
||||
discardRow(f[_])
|
||||
|
||||
@@ -33,6 +33,7 @@ return{
|
||||
P:_showText(text.maxspeed,0,-140,100,'appear',.6)
|
||||
end
|
||||
end
|
||||
P:shakeField(9)
|
||||
D.wave=D.wave+1
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,6 +42,7 @@ return{
|
||||
P:_showText(text.maxspeed,0,-140,100,'appear',.6)
|
||||
end
|
||||
end
|
||||
P:shakeField(10)
|
||||
D.wave=D.wave+1
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
return{
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.lastPiece.atk>0 then
|
||||
P:receive(nil,P.lastPiece.atk,0,generateLine(P.holeRND:random(10)))
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
return{
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.lastPiece.atk>0 then
|
||||
P:receive(nil,P.lastPiece.atk,120,generateLine(P.holeRND:random(10)))
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
return{
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.lastPiece.atk>0 then
|
||||
P:receive(nil,P.lastPiece.atk,30,generateLine(P.holeRND:random(10)))
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
return{
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.lastPiece.atk>0 then
|
||||
P:receive(nil,P.lastPiece.atk,60,generateLine(P.holeRND:random(10)))
|
||||
end
|
||||
|
||||
@@ -11,8 +11,8 @@ return{
|
||||
task=function(P)
|
||||
local F=P.field
|
||||
for i=1,24 do
|
||||
F[i]=FREEROW.get(20)
|
||||
P.visTime[i]=FREEROW.get(20)
|
||||
F[i]=LINE.new(20)
|
||||
P.visTime[i]=LINE.new(20)
|
||||
for x=4,7 do F[i][x]=0 end
|
||||
end
|
||||
if P.holeRND:random()<.6 then
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
return{
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.lastPiece.row>0 then
|
||||
for _=1,#P.clearedRow do
|
||||
local h=#P.field
|
||||
P.field[h+1]=FREEROW.get(20)
|
||||
P.visTime[h+1]=FREEROW.get(20)
|
||||
P.field[h+1]=LINE.new(20)
|
||||
P.visTime[h+1]=LINE.new(20)
|
||||
for i=4,7 do P.field[h+1][i]=0 end
|
||||
end
|
||||
if P.combo>P.modeData.maxCombo then
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
return{
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.lastPiece.row==0 then
|
||||
P:lose()
|
||||
else
|
||||
for _=1,P.lastPiece.row do
|
||||
local h=#P.field
|
||||
P.field[h+1]=FREEROW.get(20)
|
||||
P.visTime[h+1]=FREEROW.get(20)
|
||||
P.field[h+1]=LINE.new(20)
|
||||
P.visTime[h+1]=LINE.new(20)
|
||||
for i=4,7 do P.field[h+1][i]=0 end
|
||||
end
|
||||
if P.combo>P.modeData.maxCombo then
|
||||
|
||||
@@ -6,7 +6,7 @@ return{
|
||||
mText(TEXTOBJ.atk,63,243)
|
||||
mText(TEXTOBJ.eff,63,363)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.atk>=100 then
|
||||
P:win('finish')
|
||||
end
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
return{
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.garbageBeneath==0 then
|
||||
local D=P.modeData
|
||||
D.finished=D.finished+1
|
||||
if FIELD[D.finished+1]then
|
||||
P.waiting=26
|
||||
for i=#P.field,1,-1 do
|
||||
FREEROW.discard(P.field[i])
|
||||
FREEROW.discard(P.visTime[i])
|
||||
P.field[i],P.visTime[i]=nil
|
||||
end
|
||||
setField(P,D.finished+1)
|
||||
|
||||
@@ -6,7 +6,7 @@ return{
|
||||
mStr(r,63,265)
|
||||
PLY.draw.drawTargetLine(P,r)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=10 then
|
||||
P:win('finish')
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ return{
|
||||
mStr(r,63,265)
|
||||
PLY.draw.drawTargetLine(P,r)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=100 then
|
||||
P:win('finish')
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ return{
|
||||
mStr(r,63,265)
|
||||
PLY.draw.drawTargetLine(P,r)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=1000 then
|
||||
P:win('finish')
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ return{
|
||||
mStr(r,63,265)
|
||||
PLY.draw.drawTargetLine(P,r)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=20 then
|
||||
P:win('finish')
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ return{
|
||||
mStr(r,63,265)
|
||||
PLY.draw.drawTargetLine(P,r)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=200 then
|
||||
P:win('finish')
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ return{
|
||||
mStr(r,63,265)
|
||||
PLY.draw.drawTargetLine(P,r)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=40 then
|
||||
P:win('finish')
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ return{
|
||||
mStr(r,63,265)
|
||||
PLY.draw.drawTargetLine(P,r)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=400 then
|
||||
P:win('finish')
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
return{
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if #PLY_ALIVE>1 then
|
||||
P.control=false
|
||||
local id1=P.sid
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
return{
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.piece%7==0 and #PLY_ALIVE>1 then
|
||||
P.control=false
|
||||
local id1=P.sid
|
||||
|
||||
@@ -22,7 +22,7 @@ return{
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local D=P.modeData
|
||||
if P.stat.row>=D.target then
|
||||
if D.target==110 then
|
||||
|
||||
@@ -22,7 +22,7 @@ return{
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local D=P.modeData
|
||||
if P.stat.row>=D.target then
|
||||
if D.target==110 then
|
||||
|
||||
@@ -22,7 +22,7 @@ return{
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local D=P.modeData
|
||||
if P.stat.row>=D.target then
|
||||
if D.target==100 then
|
||||
|
||||
@@ -40,6 +40,7 @@ return{
|
||||
P:_showText(text.maxspeed,0,-140,100,'appear',.6)
|
||||
P.dropDelay,P.gameEnv.drop=2,2
|
||||
end
|
||||
P:shakeField(3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -40,6 +40,7 @@ return{
|
||||
P.dropDelay,P.gameEnv.drop=5,5
|
||||
P:_showText(text.maxspeed,0,-140,100,'appear',.6)
|
||||
end
|
||||
P:shakeField(3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ return{
|
||||
setFont(55)
|
||||
mStr(100-P.stat.dig,63,265)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
for _=1,math.min(10,100-P.stat.dig)-P.garbageBeneath do
|
||||
P:garbageRise(21,1,P:getHolePos())
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ return{
|
||||
setFont(55)
|
||||
mStr(10-P.stat.dig,63,265)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.dig==10 then
|
||||
P:win('finish')
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ return{
|
||||
setFont(55)
|
||||
mStr(400-P.stat.dig,63,265)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
for _=1,math.min(10,400-P.stat.dig)-P.garbageBeneath do
|
||||
P:garbageRise(21,1,P:getHolePos())
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ return{
|
||||
setFont(55)
|
||||
mStr(40-P.stat.dig,63,265)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
for _=1,math.min(10,40-P.stat.dig)-P.garbageBeneath do
|
||||
P:garbageRise(21,1,P:getHolePos())
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@ return{
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local flag
|
||||
local l=P.lastPiece
|
||||
if P.combo>1 then flag=true;P:showText("2x",0,-220,40,'flicker',.3)end
|
||||
|
||||
@@ -10,7 +10,7 @@ return
|
||||
task=function(P)
|
||||
P.modeData.target=50
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=P.modeData.target then
|
||||
if P.modeData.target==50 then
|
||||
P.gameEnv.drop=.25
|
||||
|
||||
56
parts/eventsets/marathon_inf.lua
Normal file
56
parts/eventsets/marathon_inf.lua
Normal file
@@ -0,0 +1,56 @@
|
||||
local dropSpeed={
|
||||
50,42,35,30,25,20,16,13,11,10,
|
||||
9,8,7,6,5,5,4,4,3,3,
|
||||
3,2,2,2,2,1,1,1,1,1,
|
||||
.5,.5,.5,.5,.25,.25,.25,.125,.125,--Total 39 numbers, switch to 20G when reach 400 lines
|
||||
}
|
||||
local lockDelay={
|
||||
57,54,51,48,46,44,42,40,38,36,
|
||||
34,32,30,28,26,25,24,23,22,21,
|
||||
20,20,19,19,18,18,17,17,16,16,
|
||||
15,15,14,14,13,13,13,12,12,12,
|
||||
11,11,11,11,11,10,10,10,10,10,
|
||||
9,9,9,9,9,9,8,8,8,8,
|
||||
8,8,8,8,7,7,7,7,7,7,
|
||||
7,7,6,6,6,6,6,6,6,6,
|
||||
5,5,5,5,5,5,5,5,5,5,
|
||||
4,4,4,4,4,4,4,4,4,4,
|
||||
3,3,3,3,3,3,3,3,3,3,
|
||||
2,2,2,2,2,2,2,2,2,2,
|
||||
1,1,1,1,1,1,1,1,1,--Finish at 1700
|
||||
}
|
||||
|
||||
return
|
||||
{
|
||||
drop=60,lock=60,
|
||||
wait=8,fall=20,
|
||||
mesDisp=function(P)
|
||||
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||
end,
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
end,
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=P.modeData.target then
|
||||
if P.modeData.target%300==0 then
|
||||
P.gameEnv.wait=P.gameEnv.wait-1
|
||||
end
|
||||
if P.modeData.target%100==0 then
|
||||
P.gameEnv.fall=P.gameEnv.fall-1
|
||||
end
|
||||
if P.modeData.target<400 then
|
||||
P.gameEnv.drop=dropSpeed[P.modeData.target/10]
|
||||
elseif P.modeData.target==400 then
|
||||
P:set20G(true)
|
||||
elseif P.modeData.target<1700 then
|
||||
P.gameEnv.lock=lockDelay[(P.modeData.target-400)/10]
|
||||
else
|
||||
P.stat.row=1700
|
||||
P:win('finish')
|
||||
return
|
||||
end
|
||||
P.modeData.target=P.modeData.target+10
|
||||
SFX.play('reach')
|
||||
end
|
||||
end
|
||||
}
|
||||
@@ -12,7 +12,7 @@ return
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=P.modeData.target then
|
||||
if P.modeData.target==200 then
|
||||
P:win('finish')
|
||||
|
||||
@@ -30,7 +30,7 @@ return{
|
||||
mStr(P.stat.row,63,230)
|
||||
mStr(P.stat.clears[4],63,340)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.modeData.rankPoint<140-passPoint then--If Less then X
|
||||
local R=#P.clearedRow
|
||||
if R>0 then
|
||||
|
||||
@@ -8,7 +8,7 @@ return{
|
||||
mesDisp=function(P)
|
||||
PLY.draw.drawProgress(P.modeData.pt,P.modeData.target)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local D=P.modeData
|
||||
|
||||
local c=#P.clearedRow
|
||||
|
||||
@@ -12,7 +12,7 @@ return{
|
||||
mesDisp=function(P)
|
||||
PLY.draw.drawProgress(P.modeData.pt,P.modeData.target)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local D=P.modeData
|
||||
|
||||
local c=#P.clearedRow
|
||||
|
||||
@@ -14,7 +14,7 @@ return
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=P.modeData.target then
|
||||
if P.modeData.target==200 then
|
||||
P:win('finish')
|
||||
|
||||
@@ -12,7 +12,7 @@ return{
|
||||
mesDisp=function(P)
|
||||
PLY.draw.drawProgress(P.modeData.pt,P.modeData.target)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local D=P.modeData
|
||||
|
||||
local c=#P.clearedRow
|
||||
|
||||
@@ -13,7 +13,7 @@ return
|
||||
mesDisp=function(P)
|
||||
PLY.draw.drawProgress(P.modeData.pt,P.modeData.target)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local p=P.modeData.pt+P.lastPiece.row
|
||||
if p>=P.modeData.target then
|
||||
local ENV=P.gameEnv
|
||||
@@ -55,8 +55,8 @@ return
|
||||
P.field[i][P.holeRND:random(10)]=0
|
||||
end
|
||||
else
|
||||
P.field[i]=FREEROW.get(0)
|
||||
P.visTime[i]=FREEROW.get(30)
|
||||
P.field[i]=LINE.new(0)
|
||||
P.visTime[i]=LINE.new(30)
|
||||
for j=1,10 do
|
||||
if P.holeRND:random()>.9 then
|
||||
P.field[i][j]=P.holeRND:random(16)
|
||||
@@ -89,6 +89,7 @@ return
|
||||
ENV.bone=true
|
||||
|
||||
P.modeData.target=62
|
||||
SFX.play('reach')
|
||||
else
|
||||
p=41
|
||||
end
|
||||
@@ -112,6 +113,7 @@ return
|
||||
ENV.fall=4
|
||||
|
||||
P.modeData.target=162
|
||||
SFX.play('reach')
|
||||
elseif T==162 then--Stage 7: speed up+++
|
||||
P:stageComplete(7)
|
||||
P.life=P.life+1
|
||||
@@ -146,6 +148,7 @@ return
|
||||
P.modeData.target=260
|
||||
p=260
|
||||
SFX.play('blip_2')
|
||||
SFX.play('reach')
|
||||
else
|
||||
p=260
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ return{
|
||||
mStr(P.stat.pc,63,340)
|
||||
mText(TEXTOBJ.pc,63,410)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.lastPiece.pc and P.stat.row%4==0 then
|
||||
P.gameEnv.heightLimit=4
|
||||
if P.stat.pc%5==0 then
|
||||
|
||||
@@ -46,6 +46,6 @@ return{
|
||||
mStr(P.stat.pc,63,340)
|
||||
mText(TEXTOBJ.pc,63,410)
|
||||
end,
|
||||
dropPiece=check,
|
||||
hook_drop=check,
|
||||
task=check,
|
||||
}
|
||||
|
||||
@@ -37,6 +37,6 @@ return{
|
||||
mStr(P.stat.pc,63,340)
|
||||
mText(TEXTOBJ.pc,63,410)
|
||||
end,
|
||||
dropPiece=check,
|
||||
hook_drop=check,
|
||||
task=check,
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
local gc=love.graphics
|
||||
local dropSpeed={[0]=40,33,27,20,16,12,11,10,9,8,7,6,5,4,3,3,2,2,1,1}
|
||||
|
||||
return{
|
||||
drop=40,
|
||||
lock=1e99,
|
||||
wait=20,
|
||||
fall=90,
|
||||
mesDisp=function(P)
|
||||
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||
|
||||
setFont(30)
|
||||
mStr(P.modeData.bpm,63,178)
|
||||
|
||||
gc.setLineWidth(4)
|
||||
gc.circle('line',63,200,30)
|
||||
|
||||
local beat=P.modeData.counter/P.modeData.beatFrame
|
||||
gc.setColor(1,1,1,1-beat)
|
||||
gc.setLineWidth(3)
|
||||
gc.circle('line',63,200,30+45*beat)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
if P.stat.row>=P.modeData.target then
|
||||
if P.modeData.target==200 then
|
||||
P:win('finish')
|
||||
else
|
||||
P.modeData.bpm=40+2*P.modeData.target/10
|
||||
P.modeData.beatFrame=math.floor(3600/P.modeData.bpm)
|
||||
P.gameEnv.fall=P.modeData.beatFrame
|
||||
P.gameEnv.wait=math.max(P.gameEnv.wait-2,0)
|
||||
P.gameEnv.drop=dropSpeed[P.modeData.target/10]
|
||||
P.modeData.target=P.modeData.target+10
|
||||
SFX.play('reach')
|
||||
end
|
||||
end
|
||||
end,
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
P.modeData.bpm=40
|
||||
P.modeData.beatFrame=90
|
||||
P.modeData.counter=90
|
||||
while true do
|
||||
YIELD()
|
||||
P.modeData.counter=P.modeData.counter-1
|
||||
if P.modeData.counter==0 then
|
||||
P.modeData.counter=P.modeData.beatFrame
|
||||
SFX.play('click',.3)
|
||||
P:act_hardDrop()
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
local gc=love.graphics
|
||||
local dropSpeed={[0]=30,26,23,20,17,14,12,10,8,6,5,4,3,2,1,1,.5,.5,.25,.25}
|
||||
|
||||
return{
|
||||
drop=30,
|
||||
lock=1e99,
|
||||
wait=10,
|
||||
fall=60,
|
||||
mesDisp=function(P)
|
||||
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||
|
||||
setFont(30)
|
||||
mStr(P.modeData.bpm,63,178)
|
||||
|
||||
gc.setLineWidth(4)
|
||||
gc.circle('line',63,200,30)
|
||||
|
||||
local beat=P.modeData.counter/P.modeData.beatFrame
|
||||
gc.setColor(1,1,1,1-beat)
|
||||
gc.setLineWidth(3)
|
||||
gc.circle('line',63,200,30+45*beat)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
if P.stat.row>=P.modeData.target then
|
||||
if P.modeData.target==200 then
|
||||
P:win('finish')
|
||||
else
|
||||
P.modeData.bpm=60+3*P.modeData.target/10
|
||||
P.modeData.beatFrame=math.floor(3600/P.modeData.bpm)
|
||||
P.gameEnv.fall=P.modeData.beatFrame
|
||||
P.gameEnv.wait=math.max(P.gameEnv.wait-1,0)
|
||||
P.gameEnv.drop=dropSpeed[P.modeData.target/10]
|
||||
P.modeData.target=P.modeData.target+10
|
||||
SFX.play('reach')
|
||||
end
|
||||
end
|
||||
end,
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
P.modeData.bpm=60
|
||||
P.modeData.beatFrame=60
|
||||
P.modeData.counter=60
|
||||
while true do
|
||||
YIELD()
|
||||
P.modeData.counter=P.modeData.counter-1
|
||||
if P.modeData.counter==0 then
|
||||
P.modeData.counter=P.modeData.beatFrame
|
||||
SFX.play('click',.3)
|
||||
P:act_hardDrop()
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
local gc=love.graphics
|
||||
|
||||
return{
|
||||
drop=.5,
|
||||
lock=1e99,
|
||||
wait=5,
|
||||
fall=30,
|
||||
mesDisp=function(P)
|
||||
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||
|
||||
setFont(30)
|
||||
mStr(P.modeData.bpm,63,178)
|
||||
|
||||
gc.setLineWidth(4)
|
||||
gc.circle('line',63,200,30)
|
||||
|
||||
local beat=P.modeData.counter/P.modeData.beatFrame
|
||||
gc.setColor(1,1,1,1-beat)
|
||||
gc.setLineWidth(3)
|
||||
gc.circle('line',63,200,30+45*beat)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
if P.stat.row>=P.modeData.target then
|
||||
if P.modeData.target==200 then
|
||||
P:win('finish')
|
||||
else
|
||||
P.modeData.bpm=120+2*P.modeData.target/10
|
||||
P.modeData.beatFrame=math.floor(3600/P.modeData.bpm)
|
||||
P.gameEnv.fall=P.modeData.beatFrame
|
||||
P.gameEnv.wait=math.max(P.gameEnv.wait-1,0)
|
||||
if P.modeData.target==50 then
|
||||
P.gameEnv.das=5
|
||||
P.gameEnv.drop=.25
|
||||
elseif P.modeData.target==100 then
|
||||
P.gameEnv.das=4
|
||||
P:set20G(true)
|
||||
end
|
||||
P.modeData.target=P.modeData.target+10
|
||||
SFX.play('reach')
|
||||
end
|
||||
end
|
||||
end,
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
P.modeData.bpm=120
|
||||
P.modeData.beatFrame=30
|
||||
P.modeData.counter=30
|
||||
while true do
|
||||
YIELD()
|
||||
P.modeData.counter=P.modeData.counter-1
|
||||
if P.modeData.counter==0 then
|
||||
P.modeData.counter=P.modeData.beatFrame
|
||||
SFX.play('click',.3)
|
||||
P:act_hardDrop()
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
@@ -1,5 +1,24 @@
|
||||
local gc=love.graphics
|
||||
local gc_draw,gc_print,gc_setColor=gc.draw,gc.print,gc.setColor
|
||||
local setFont=setFont
|
||||
|
||||
local PLAYERS,PLY_ALIVE=PLAYERS,PLY_ALIVE
|
||||
|
||||
return{
|
||||
mesDisp=function(P)
|
||||
PLY.draw.drawRoyaleInfo(P)
|
||||
setFont(35)
|
||||
mStr(#PLY_ALIVE.."/"..#PLAYERS,63,175)
|
||||
mStr(P.modeData.ko,80,215)
|
||||
gc_draw(TEXTOBJ.ko,60-TEXTOBJ.ko:getWidth(),222)
|
||||
setFont(20)
|
||||
gc_setColor(1,.5,0,.6)
|
||||
gc_print(P.badge,103,227)
|
||||
gc_setColor(.97,.97,.97)
|
||||
setFont(25)
|
||||
mStr(text.powerUp[P.strength],63,290)
|
||||
gc_setColor(1,1,1)
|
||||
for i=1,P.strength do
|
||||
gc_draw(IMG.badgeIcon,16*i+6,260)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ return{
|
||||
end
|
||||
end
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=40 then
|
||||
P:win('finish')
|
||||
end
|
||||
|
||||
@@ -14,7 +14,7 @@ return{
|
||||
mStr(r,63,265)
|
||||
PLY.draw.drawTargetLine(P,r)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local F=P.field
|
||||
for y=1,#F do
|
||||
local l=F[y]
|
||||
|
||||
22
parts/eventsets/stack_e.lua
Normal file
22
parts/eventsets/stack_e.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
return{
|
||||
fieldH=20,
|
||||
fillClear=false,
|
||||
mesDisp=function(P)
|
||||
setFont(60)
|
||||
mStr(P.stat.row,63,280)
|
||||
mText(TEXTOBJ.line,63,350)
|
||||
PLY.draw.drawMarkLine(P,20,.3,1,1,TIME()%.42<.21 and .95 or .6)
|
||||
end,
|
||||
hook_die=function(P)
|
||||
local cc=P:clearFilledLines(P.garbageBeneath+1,#P.field-P.garbageBeneath)
|
||||
if cc>0 then
|
||||
local h=20-cc-P.garbageBeneath
|
||||
if h>0 then
|
||||
P:garbageRise(21,h,2e10-1)
|
||||
if P.garbageBeneath>=20 then
|
||||
P:lose()
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
22
parts/eventsets/stack_u.lua
Normal file
22
parts/eventsets/stack_u.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
return{
|
||||
fieldH=21,
|
||||
fillClear=false,
|
||||
mesDisp=function(P)
|
||||
setFont(60)
|
||||
mStr(P.stat.row,63,280)
|
||||
mText(TEXTOBJ.line,63,350)
|
||||
PLY.draw.drawMarkLine(P,17,.3,1,1,TIME()%.42<.21 and .95 or .6)
|
||||
end,
|
||||
hook_die=function(P)
|
||||
local cc=P:clearFilledLines(P.garbageBeneath+1,#P.field-P.garbageBeneath)
|
||||
if cc>0 then
|
||||
local h=20-cc-P.garbageBeneath-3
|
||||
if h>0 then
|
||||
P:garbageRise(21,h,2e10-1)
|
||||
if P.garbageBeneath>=20 then
|
||||
P:lose()
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
@@ -21,6 +21,7 @@ return{
|
||||
if D.wave==60 then
|
||||
P:_showText(text.maxspeed,0,-140,100,'appear',.6)
|
||||
end
|
||||
P:shakeField(3)
|
||||
D.timer=0
|
||||
D.wave=D.wave+1
|
||||
end
|
||||
|
||||
@@ -24,6 +24,7 @@ return{
|
||||
if D.wave==30 then
|
||||
P:_showText(text.maxspeed,0,-140,100,'appear',.6)
|
||||
end
|
||||
P:shakeField(9)
|
||||
D.timer=0
|
||||
D.wave=D.wave+1
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ return{
|
||||
mStr(P.stat.clear[7][4],63,250)
|
||||
mText(TEXTOBJ.techrash,63,315)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
if P.lastPiece.row>0 and P.lastPiece.row<4 then
|
||||
P:lose()
|
||||
end
|
||||
|
||||
@@ -8,12 +8,12 @@ return{
|
||||
PLY.draw.applyField(P)
|
||||
local L=P.modeData.history
|
||||
for i=1,#L do
|
||||
gc.setColor(1,.3,.3,.45-i*.04)
|
||||
gc.setColor(1,.3,.3,.5-i*.04)
|
||||
gc.rectangle('fill',30*L[i]-30,0,30,600)
|
||||
end
|
||||
PLY.draw.cancelField(P)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local C=P.lastPiece
|
||||
if C.row>0 then
|
||||
if C.row==4 then
|
||||
|
||||
@@ -4,7 +4,7 @@ return{
|
||||
mStr(P.modeData.tsd,63,250)
|
||||
mText(TEXTOBJ.tsd,63,315)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local C=P.lastPiece
|
||||
if C.row>0 then
|
||||
if C.id==5 and C.row==2 and C.spin then
|
||||
|
||||
@@ -13,7 +13,7 @@ return{
|
||||
PLY.draw.cancelField(P)
|
||||
end
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local C=P.lastPiece
|
||||
if C.row>0 then
|
||||
if C.id==5 and C.row==2 and C.spin then
|
||||
|
||||
@@ -8,12 +8,12 @@ return{
|
||||
PLY.draw.applyField(P)
|
||||
local L=P.modeData.history
|
||||
for i=1,#L do
|
||||
gc.setColor(1,.3,.3,.3-i*.05)
|
||||
gc.setColor(1,.3,.3,.4-i*.05)
|
||||
gc.rectangle('fill',30*L[i]-30,0,30,600)
|
||||
end
|
||||
PLY.draw.cancelField(P)
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local C=P.lastPiece
|
||||
if C.row>0 then
|
||||
if C.id==5 and C.row==2 and C.spin then
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,37 +0,0 @@
|
||||
local FREEROW={}
|
||||
local L={}--Storage
|
||||
local len=0--Length
|
||||
function FREEROW.reset(num)
|
||||
if num<len then
|
||||
for i=len,num+1,-1 do
|
||||
L[i]=nil
|
||||
end
|
||||
elseif num>len then
|
||||
for i=len+1,num do
|
||||
L[i]={0,0,0,0,0,0,0,0,0,0,garbage=false}
|
||||
end
|
||||
end
|
||||
len=num
|
||||
end
|
||||
function FREEROW.get(val,ifGarbage)
|
||||
if len==0 then
|
||||
for i=1,10 do
|
||||
L[i]={0,0,0,0,0,0,0,0,0,0,garbage=false}
|
||||
end
|
||||
len=len+10
|
||||
end
|
||||
local t=L[len]
|
||||
for i=1,10 do t[i]=val end
|
||||
t.garbage=ifGarbage==true
|
||||
L[len]=nil
|
||||
len=len-1
|
||||
return t
|
||||
end
|
||||
function FREEROW.discard(t)
|
||||
len=len+1
|
||||
L[len]=t
|
||||
end
|
||||
function FREEROW.getCount()
|
||||
return len
|
||||
end
|
||||
return FREEROW
|
||||
@@ -10,6 +10,7 @@ local int,rnd=math.floor,math.random
|
||||
|
||||
local SETTING,GAME,SCR=SETTING,GAME,SCR
|
||||
local PLAYERS=PLAYERS
|
||||
local playSFX=SFX.play
|
||||
|
||||
|
||||
|
||||
@@ -174,6 +175,56 @@ function royaleLevelup()
|
||||
end
|
||||
end
|
||||
|
||||
--Sound shortcuts
|
||||
function playClearSFX(cc)
|
||||
if cc<=0 or cc%1~=0 then return end
|
||||
if cc<=4 then
|
||||
playSFX('clear_'..cc)
|
||||
elseif cc<=6 then
|
||||
playSFX('clear_4')
|
||||
elseif cc<=12 then
|
||||
playSFX('clear_4',.8)
|
||||
if cc<=9 then
|
||||
Snd('bass','A3','E4')
|
||||
else
|
||||
Snd('bass','A3','E4','A4')
|
||||
end
|
||||
elseif cc<=16 then
|
||||
playSFX('clear_5',.7)
|
||||
if cc<=14 then
|
||||
Snd('bass',.8,'A3','E4')Snd('lead','A4','E5')
|
||||
else
|
||||
Snd('bass',.8,'A3','G4')Snd('lead','B4','G5')
|
||||
end
|
||||
else
|
||||
playSFX('clear_6',.6)
|
||||
if cc==17 then Snd('bass',.8,'A3','A4')Snd('lead','E5','G5')
|
||||
elseif cc==18 then Snd('bass',.7,'A4')Snd('lead',.8,'C4','G5')Snd('bell','D5')
|
||||
elseif cc==19 then Snd('bass',.7,'A4')Snd('lead',.8,'A4','E5')Snd('bell','B5')
|
||||
elseif cc==20 then Snd('bass',.7,'A4')Snd('lead',.8,'A4','E4')Snd('bell','D5','B5','G6')
|
||||
else Snd('bass',.7,'A4')Snd('lead',.8,'A4','E4')Snd('bell','B5','E6','A6')
|
||||
end
|
||||
end
|
||||
end
|
||||
function playReadySFX(i)
|
||||
if i==3 then
|
||||
Snd('bass','A3')
|
||||
Snd('lead','A4')
|
||||
elseif i==2 then
|
||||
Snd('bass','F3')
|
||||
Snd('lead','A4')
|
||||
Snd('lead','D5')
|
||||
elseif i==1 then
|
||||
Snd('bass','G3')
|
||||
Snd('lead','B4')
|
||||
Snd('lead','E5')
|
||||
elseif i==0 then
|
||||
Snd('bass','A3')
|
||||
Snd('lead','A4')
|
||||
Snd('lead','E5')
|
||||
Snd('lead','A5')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--Game
|
||||
@@ -206,8 +257,8 @@ function setField(P,page)
|
||||
local t=P.showTime*3
|
||||
for y=1,height do
|
||||
local notEmpty=notEmptyLine(F[y])
|
||||
P.field[y]=FREEROW.get(0,notEmpty)
|
||||
P.visTime[y]=FREEROW.get(t)
|
||||
P.field[y]=LINE.new(0,notEmpty)
|
||||
P.visTime[y]=LINE.new(t)
|
||||
if notEmpty then
|
||||
for x=1,10 do
|
||||
P.field[y][x]=F[y][x]
|
||||
@@ -280,8 +331,8 @@ function destroyPlayers()--Destroy all player objects, restore freerows and free
|
||||
P.canvas:release()
|
||||
end
|
||||
while P.field[1]do
|
||||
FREEROW.discard(rem(P.field))
|
||||
FREEROW.discard(rem(P.visTime))
|
||||
rem(P.field)
|
||||
rem(P.visTime)
|
||||
end
|
||||
end
|
||||
TABLE.cut(PLAYERS)
|
||||
@@ -346,7 +397,7 @@ function loadGame(mode,ifQuickPlay,ifNet)--Load a mode and go to game scene
|
||||
local modeText=text.modes[mode]or{"["..MODES[mode].name.."]",""}
|
||||
TEXTOBJ.modeName:set(modeText[1].." "..modeText[2])
|
||||
SCN.go('game',ifQuickPlay and'swipeD'or'fade_togame')
|
||||
SFX.play('enter')
|
||||
playSFX('enter')
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -410,7 +461,7 @@ function gameOver()--Save record
|
||||
P:_showText(text.newRecord,0,-100,100,'beat',.5)
|
||||
if SETTING.autoSave and DATA.saveReplay()then
|
||||
GAME.saved=true
|
||||
SFX.play('connected')
|
||||
playSFX('connected')
|
||||
MES.new('check',text.saveDone)
|
||||
end
|
||||
end
|
||||
@@ -617,13 +668,11 @@ do--function resetGameData(args)
|
||||
GAME.secDangerous=false
|
||||
GAME.stage=1
|
||||
end
|
||||
FREEROW.reset(30*#PLAYERS)
|
||||
TASK.removeTask_code(task_showMods)
|
||||
if GAME.setting.allowMod then
|
||||
TASK.new(task_showMods)
|
||||
end
|
||||
Snd('bass','A3')
|
||||
Snd('lead','A4')
|
||||
playReadySFX(3)
|
||||
collectgarbage()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -345,7 +345,6 @@ EVENTSETS={
|
||||
'marathon_n','marathon_h',
|
||||
'master_n','master_h','master_final','master_m','master_ex','master_ph',
|
||||
'pctrain_n','pctrain_l','pc_inf',
|
||||
'rhythm_e','rhythm_h','rhythm_u',
|
||||
'survivor_e','survivor_n','survivor_h','survivor_l','survivor_u',
|
||||
'tsd_e','tsd_h','tsd_u',
|
||||
'ultra',
|
||||
|
||||
@@ -4,7 +4,7 @@ return{
|
||||
{"Translator Note 1",
|
||||
"",
|
||||
"help",
|
||||
"This translation of the TetroDictionary is provided by me, User670 (Discord: User670#9501).\n\nThe translation may not completely reflect the contents of the original Chinese text.\n\nCorrected by C29H25N3O5.\n\nTo view the list of contributors or make contributions, feel free to visit the GitHub page.",
|
||||
"This translation of the TetroDictionary is provided by me, User670 (Discord: User670#9501).\n\nThe translation may not completely reflect the contents of the original Chinese text.\n\nCorrected by C₂₉H₂₅N₃O₅.\n\nTo view the list of contributors or make contributions, feel free to visit the GitHub page.",
|
||||
"https://github.com/26F-Studio/Techmino/blob/main/parts/language/dict_en.lua",
|
||||
},
|
||||
{"Official Website",
|
||||
@@ -55,6 +55,32 @@ return{
|
||||
"https://tetris.huijiwiki.com",
|
||||
},
|
||||
|
||||
--Organizations
|
||||
{"Github Repository",
|
||||
"githubrepository sourcecode",
|
||||
"org",
|
||||
"Techmino's Github repository. Stars are appreciated.",
|
||||
"https://github.com/26F-Studio/Techmino",
|
||||
},
|
||||
{"Communities",
|
||||
"community communities",
|
||||
"org",
|
||||
"Join Tetris communities and talk with other players!\n\nChina: [QQ] Tetris Research: 112897780\nGlobal: [Discord] Hard Drop: discord.gg/harddrop (click \"Open URL\").",
|
||||
"https://discord.gg/harddrop"
|
||||
},
|
||||
{"Mew",
|
||||
"mew tieba forum",
|
||||
"org",
|
||||
"The Mew forum owned by Chinese Tetris Research Community, and was founded in the second half of 2021. Mew is a Chinese social media that can be thought of a combination of Discord and Reddit, with many channels in a big community. Users can chat in the channels or submit posts to the channel. Mew also has a function called \"Library\" which allows storing documentations systematically. The Tetris Mew forum is currently under construction and not too much contents are available (2/Nov/2021).",
|
||||
"https://mew.fun/n/tetris",
|
||||
},
|
||||
{"Tetris OL Servers",
|
||||
"tetrisonline servers",
|
||||
"org",
|
||||
"Google \"Tetris Online Poland\" for the Poland server.\nClick \"Open URL\" for information about the Tetris Online Study server.",
|
||||
"http://teatube.ltd/tos",
|
||||
},
|
||||
|
||||
--Games
|
||||
{"TTT",
|
||||
"ttt tetris trainer tres bien",
|
||||
@@ -141,7 +167,7 @@ return{
|
||||
{"Tetris Mind Bender",
|
||||
"tetris online official gem",
|
||||
"game",
|
||||
"Another Tetris game from tetris.com. It introduced “Mind Bender” minoes on the basis of marathon mode. Clearing a line with a Mind Bender mino will give you either a good or bad effect.",
|
||||
"Another Tetris game from tetris.com. It introduced \"Mind Bender\" minoes on the basis of marathon mode. Clearing a line with a Mind Bender mino will give you either a good or bad effect.",
|
||||
},
|
||||
|
||||
{"TGM",
|
||||
@@ -405,10 +431,15 @@ return{
|
||||
"term",
|
||||
"In most cases, it's a meme.\nThe shape and position of the O Tetromino (a.k.a. the Square) does not change upon rotation, thus making it lack interesting spins/kicks that other Tetrominoes have, or be stuck in a place unable to get out.\nAs a joke, some people have made heavily edited videos or even programmed games where the O pieces can change shape and \"spin\" into different positions.\nTechmino also supports O-Spin in most modes.",
|
||||
},
|
||||
{"Rotation Systems",--Editted
|
||||
{"Rotation Systems",
|
||||
"wallkick rotationsystem",
|
||||
"term",
|
||||
"Systems that determine how pieces rotate.\n\nRotation systems usually handle two things: basic rotation and kicks.\n\nBasic rotation refers to how pieces rotate in an open area. Because rotating pieces on their geometric center will usually cause the piece to be misaligned from the grid, rotation systems need to specify alternative rotation centers or rotation offsets to align rotated pieces back to the grid.\n\nKicks refer to offsets applied if the rotated piece overlaps with the border of the matrix or other blocks. While older games, like the ones on NES and Gameboy, lack kicks, people soon realized that if a piece is too close to the wall, the floor or other pieces, the piece can (unintuitively) fail to rotate due to overlapping. Games started to implement systems that allow pieces close to walls/floors to rotate, and move them away from the wall/floor into a valid position (\"kicking off the wall/floor\"), and such movements, or offsets used in said movements, are referred to as (wall/floor) kicks.\n\nWhile Super Rotation System (SRS) is the current standard for modern official Tetris games, older games and unofficial games may have their own rotation systems, implementing different basic rotations and kicks.",
|
||||
"Systems that determine how the pieces rotate.\n\nIn modern Tetris games, tetrominoes can rotate on a specfic rotation center (but this may be absent in some games). If the minoes overlap with the walls or the field, the system would attempt to perform some offsets (a process known as \"wall-kicking\"). Wall kicks allow minoes to move into in specific-shaped holes.",
|
||||
},
|
||||
{"Orientation",
|
||||
"orientation direction 0r2l 02 20 rl lr",
|
||||
"term",
|
||||
"In SRS and SRS-like rotation systems, there are standard notations describing the orientations of the minoes:\n 0 for Original orientation; R for right, or 90° clockwise; L for left, or 90° counterclockwise; 2 for spin twice (180°). For example, 0→L means rotating counterclockwise from original orientation (0) to L; 0→R means rotating clockwise from original orientation (0) to R; 2→R means rotating counterclockwise from 2 (180°) to R.",
|
||||
},
|
||||
{"ARS",
|
||||
"ars arikrotationsystem atarirotationsystem",
|
||||
@@ -445,10 +476,10 @@ return{
|
||||
"term",
|
||||
"Nintendo Rotation System\nThe rotation system used in the Tetris games on the NES and Game Boy.\nIt has two mirrored versions; the left-handed version is used on Game Boy, and the right-handed version on the NES.",
|
||||
},
|
||||
{"SRS",--Editted
|
||||
{"SRS",
|
||||
"srs superrotationsystem",
|
||||
"term",
|
||||
"Super Rotation System\nThe rotation system used in modern, official Tetris games.\nEach Tetromino has a rotation center for the piece to rotate around. Should a Tetromino overlap with the wall, floor or another mino on the field after rotation, a few offset positions will be checked, allowing pieces to kick off walls and floors. This also allows pieces to rotate into openings that are otherwise unreachable.\n\nMany unofficial games implement some modification of this rotation system that adds a kick for 180 spins. In Techmino, such a modification is called SRS+.",
|
||||
"Super Rotation System, the most widely used rotation system by modern Tetris games, and is the foundation of many self-made rotation systems. There are four orientations for each tetromino, and they can rotate clockwise or counterclockwise (But without 180° rotations). Should a Tetromino overlap with the wall, floor or other minoes on the field after rotation, a few offset positions will be checked, allowing pieces to kick off walls and floors. You can look up the details of the wall kick table on Tetris Wiki.",
|
||||
},
|
||||
{"TRS",
|
||||
"trs techminorotationsystem",
|
||||
@@ -484,7 +515,7 @@ return{
|
||||
{"Tetrominos' Shapes",
|
||||
"shape structure form tetromino tetrimino",
|
||||
"term",
|
||||
"In standard Tetris games, all the blocks used are tetrominoes (spelt as \"Tetrimino\" in official games), i.e. Blocks that are linked by four minoes side-by-side.\n\nThere are seven kinds of tetrominoes in total when allowing rotations and disallowing reflections. These tetrominoes are named by the letter in the alphabet that they resemble. They are Z, S, J, L, T, O, and I.",
|
||||
"In standard Tetris games, all the blocks used are tetrominoes, i.e. Blocks that are linked by four minoes side-by-side.\n\nThere are seven kinds of tetrominoes in total when allowing rotations and disallowing reflections. These tetrominoes are named by the letter in the alphabet that they resemble. They are Z, S, J, L, T, O, and I.",
|
||||
},
|
||||
{"Tetrominos' Colors",
|
||||
"colour hue tint tetromino tetrimino",
|
||||
@@ -521,6 +552,11 @@ return{
|
||||
"term",
|
||||
"Like *hold*, swap your current piece and the first piece of next queue. You can also only perform this once per piece in most cases.",
|
||||
},
|
||||
{"Deepdrop",
|
||||
"deepdrop shenjiang",
|
||||
"term",
|
||||
"*Techmino exclusive*\n\nA special function that allows minoes to teleport through the wall to enter a hole. When the mino hits the bottom, pressing the soft drop button again will enable the deep drop. if there is a hole that fits the shape of the mino, it will teleport into this hole immediately/nThis mechanism is especially useful for AI because it allows AI to disregard the differences between different rotation systems.",
|
||||
},
|
||||
{"Misdrop",
|
||||
"md misdrop",
|
||||
"term",
|
||||
@@ -942,26 +978,6 @@ return{
|
||||
"Stacking TST(s) on top of a STSD.",
|
||||
},
|
||||
|
||||
--Other
|
||||
{"Communities",
|
||||
"community communities",
|
||||
"other",
|
||||
"Join Tetris communities and talk with other players!\n\nChina: [QQ] Tetris Research: 112897780\nGlobal: [Discord] Hard Drop: discord.gg/harddrop (click \"Open URL\").",
|
||||
"https://discord.gg/harddrop"
|
||||
},
|
||||
{"Tetris OL Servers",
|
||||
"tetrisonline servers",
|
||||
"other",
|
||||
"Google \"Tetris Online Poland\" for the Poland server.\nClick \"Open URL\" for information about the Tetris Online Study server.",
|
||||
"http://teatube.ltd/tos",
|
||||
},
|
||||
{"Github Repository",
|
||||
"githubrepository sourcecode",
|
||||
"other",
|
||||
"Techmino's Github repository. Stars are appreciated.",
|
||||
"https://github.com/26F-Studio/Techmino",
|
||||
},
|
||||
|
||||
--Savedata managing
|
||||
{"Console",
|
||||
"console cmd commamd minglinghang kongzhitai",
|
||||
@@ -1060,7 +1076,7 @@ return{
|
||||
{"Furea",
|
||||
"furea fuleiya jk",
|
||||
"name",
|
||||
"(ふれあ)\n\nOne of the top players.\nWorld record holder of Puyo Puyo Tetris's Sprint mode and Ultra mode.",
|
||||
"(ふれあ)\n\nOne of the top players.\nWorld record holder of Puyo Puyo Tetris's Ultra mode.",
|
||||
},
|
||||
{"Iljain",
|
||||
"iljain yijianlian",
|
||||
@@ -1110,10 +1126,10 @@ return{
|
||||
{"TetroDictionary",
|
||||
"zictionary tetrodictionary littlez",
|
||||
"name",
|
||||
"(or Zictionary for short) The name of this thing.\nUsed to be a chatbot that serves for the same function, and mostly uses the same list of keywords.",
|
||||
"(or Zictionary for short) The name of this dictionary!\nIt includes brief introductions on many common terms in Tetris.\nIt used to be a chatbot in our QQ group, which was used to answer new player's FAQs. The entries in the Tetrodictionary were also inherited from the database in the chatbot.",
|
||||
},
|
||||
{"MrZ",
|
||||
"mrz 626",
|
||||
"mrz_26",
|
||||
"name",
|
||||
"Tetris Research community member, the author of Techmino.\nPersonal bests: Sprint 25.95 seconds, MPH Sprint 57 seconds, #8 on Jstris leaderboards, X rank on TETR.IO, cleared TGM3 (World rule, Shirase gold 1300).",
|
||||
"https://space.bilibili.com/225238922",
|
||||
@@ -1187,7 +1203,7 @@ return{
|
||||
{"他天一",
|
||||
"tty tatianyi hydrofierus",
|
||||
"name",
|
||||
"(Tā Tiān Yī)\n\nTetris Research community member.\nPersonal bests: Sprint 22.72 seconds, U rank on Tetr.io.\nOne of the top players of Tetris in China.",
|
||||
"(Tā Tiān Yī)\n\nTetris Research community member.\nPersonal bests: Sprint 21.908 seconds, U rank on Tetr.io.\nOne of the top players of Tetris in China.",
|
||||
"https://space.bilibili.com/3895759",
|
||||
},
|
||||
{"Mars608",
|
||||
@@ -1199,7 +1215,7 @@ return{
|
||||
{"Mifu",
|
||||
"mifu swl nanmaomao",
|
||||
"name",
|
||||
"Originally known as swl.\nPersonal bests: Sprint 32 seconds, Tetris Research community member.\nMiya's Tetris coach. Miya made an animated character art for him called Mifu, meaning \"Miya's Shifu\".",
|
||||
"Originally known as swl.\nPersonal bests: Sprint 28.445 seconds, Tetris Research community member.\nMiya's Tetris coach. Miya made an animated character art for him called Mifu, meaning \"Miya's Shifu\".",
|
||||
"https://space.bilibili.com/109356367",
|
||||
},
|
||||
{"ZXC",
|
||||
@@ -1241,7 +1257,7 @@ return{
|
||||
{"琳雨空",
|
||||
"linyukong",
|
||||
"name",
|
||||
"(Lín Yǔ Kong)\n\nTetris Research community member.\nSprint 38.3 seconds, S Rank in pentomino mode and Blind-WTF (world No.1)",
|
||||
"(Lín Yǔ Kong)\n\nTetris Research community member.\nSprint 38.3 seconds, Highest Rank in pentomino mode and Blind-WTF (world No.1)",
|
||||
"https://space.bilibili.com/263909369",
|
||||
},
|
||||
{"子心Koishi",
|
||||
@@ -1250,12 +1266,12 @@ return{
|
||||
"(Zǐ Xīn Koishi)\n\nTetris Research community member, Virtual content creator.\nA top Tetris 99 players known for his strategies.",
|
||||
"https://space.bilibili.com/147529",
|
||||
},
|
||||
{"ditoly",
|
||||
"ditoly icrem kuimei jk",
|
||||
"name",
|
||||
"Tetris Research community member. The developer of Nanamino.",
|
||||
"https://space.bilibili.com/13014410",
|
||||
},
|
||||
{"ditoly",
|
||||
"ditoly icrem kuimei jk",
|
||||
"name",
|
||||
"Tetris Research community member. The developer of Nanamino.",
|
||||
"https://space.bilibili.com/13014410",
|
||||
},
|
||||
{"蓝绿",
|
||||
"lanlv lanlyu gompyn imple lee blari'o blariho",
|
||||
"name",
|
||||
|
||||
@@ -4,7 +4,7 @@ return{
|
||||
{"新人须知",
|
||||
"新人须知 xinren new noob readme",
|
||||
"help",
|
||||
"致想深入玩下去的新人:\n\n\t两大根本原则:\n\t\t1. 选手感好的版本(Techmino/Tetr.io/Jstris/TOP/Tetr.js),别用编程练习渣版本\n\t\t2. 踏实打好基础(预判next稳定消四等),别总想着炫酷T旋,对未来发展没好处。\n\t两大主要技巧:\n\t\t1. 熟悉初始位置以及到各个位置的初始操作;\n\t\t2. 提前计算好下一块能放哪。\n\n推荐阅读专栏《给TOP新人的几点建议》\n\n[点击右下角按钮打开链接]",
|
||||
"致想深入玩下去的新人:\n\n\t两大根本原则:\n\t\t1. 选手感好的版本(Tech/Tetr.io/Jstris/TOP/Tetr.js),别用编程练习渣版本\n\t\t2. 踏实打好基础(预判next稳定消四等),别总想着炫酷T旋,对未来发展没好处。\n\t两大主要技巧:\n\t\t1. 熟悉初始位置以及到各个位置的初始操作;\n\t\t2. 提前计算好下一块能放哪。\n\n推荐阅读专栏《给TOP新人的几点建议》\n\n[点击右下角按钮打开链接]",
|
||||
"https://bilibili.com/read/cv2352939",
|
||||
},
|
||||
{"关于T-spin学习",
|
||||
@@ -49,6 +49,31 @@ return{
|
||||
"https://four.lol",
|
||||
},
|
||||
|
||||
--相关组织
|
||||
{"GitHub仓库",
|
||||
"源代码 github git sourcecode yuandaima",
|
||||
"org",
|
||||
"Techmino的GitHub仓库地址,欢迎Star",
|
||||
"https://github.com/26F-Studio/Techmino",
|
||||
},
|
||||
{"研究群",
|
||||
"研究群 yanjiu study",
|
||||
"org",
|
||||
"俄罗斯方块·[研究]群QQ号112897780,“中国俄罗斯方块总群”",
|
||||
},
|
||||
{"Mew据点",
|
||||
"mew tieba forum",
|
||||
"org",
|
||||
"研究群下属的mew据点(类似贴吧或者discord的服务器),2021年下半年建立,是discord和贴吧的结合体,可以在同一个大社区的各个频道实时聊天,也可以发帖以主题交流,同时还有一个叫图书馆的功能方便各种方块资料整理(还在建设中,目前没多少内容,2021.11,2)",
|
||||
"https://mew.fun/n/tetris",
|
||||
},
|
||||
{"茶服",
|
||||
"茶服 chafu study",
|
||||
"org",
|
||||
"TO-S的添加方法、说明等关于茶服的一切",
|
||||
"http://teatube.ltd/tos",
|
||||
},
|
||||
|
||||
--游戏(题库)
|
||||
{"TTT",
|
||||
"教程 ttt trainer tres bien",
|
||||
@@ -410,6 +435,11 @@ return{
|
||||
"term",
|
||||
"现代方块游戏中,方块可以绕着旋转中心(在本游戏中可见)旋转(部分游戏没有固定中心),如果旋转后和场地或墙壁有重合,会根据<从哪个方向转到哪个方向>进行一些偏移测试(这个偏移称为踢墙),不会卡住转不动,同时也可以让方块钻进入一些特定形状的洞",
|
||||
},
|
||||
{"方块朝向",
|
||||
"旋转 朝向 xuanzhuan chaoxiang orientation direction 0r2l 02 20 rl lr",
|
||||
"term",
|
||||
"在SRS或者类SRS的旋转系统中需要说明方块朝向的时候,“朝下”“竖着”等词描述太模糊。\nSRS中每种方块的初始状态固定,所以我们使用0(原位)、R(右,即顺时针转一次)、2(转两下,即180°)、L(左,即逆时针转一次)四个字符表示方块的四种状态,从原位(0)开始顺时针转一圈四个状态是0R2L。\n最早见于SRS踢墙表的行首,0→L表示原位逆时针转一次到L状态,0→R表示原位顺时针转一次到R状态,2→R代表从180°状态逆时针转一次到R状态。",
|
||||
},
|
||||
{"ARS",
|
||||
"旋转系统 ars rotate",
|
||||
"term",
|
||||
@@ -495,32 +525,32 @@ return{
|
||||
{"现代方块",
|
||||
"现代方块 modern xiandaikuai",
|
||||
"term",
|
||||
"现代方块是一个模糊的概念,这里列出一部分“标准”规则,满足大部分的都可以认为是现代方块:\n1.可见场地大小是10×20,不过上方空间也是存在的,上限可以自己定,一些游戏用的是40\n2.七种方块从顶部正中间出现(奇数宽方块偏左,高度可以是方块底部或顶部贴着场地顶),同一种方块的朝向(一般是平的面朝下)和颜色都一致\n3.一个合适的随机出块机制(常见的详见Bag7词条和His词条)\n4.一个合适的的旋转系统(至少有双旋,详见双旋词条)(比如SRS,详见SRS词条)\n5.一个合适的锁定延迟系统,详见锁定延迟词条\n6.一个合适的死亡判定,详见死亡判定词条\n7.有Next系统(一般是3~6个),详见Next词条,并且方向和出现时候的方向一致\n8.有Hold系统,详见Hold词条\n9.如果有出块延迟和消行延迟,那么需要有提前旋转/Hold系统,详见IRS和IHS词条,IMS是本游戏特有\n10.有DAS系统负责精密并且快速的左右移动,详见DAS词条",
|
||||
"现代方块是一个模糊的概念,这里列出一部分“标准”规则,满足大部分的都可以认为是现代方块:\n1.可见场地大小是10×20,不过上方空间也是存在的,上限可以自己定,一些游戏用的是40\n2.七种方块从顶部正中间出现(奇数宽方块偏左,高度可以是方块底部或顶部贴着场地顶),同一种方块的朝向(一般是平的面朝下)和颜色都一致\n3.一个合适的随机出块机制(常见的详见Bag7词条和His词条)\n4.一个合适的的旋转系统(至少有双旋,详见双旋词条)(最好是SRS或类SRS,详见SRS词条)\n5.一个合适的锁定延迟系统,详见锁定延迟词条\n6.一个合适的死亡判定,详见死亡判定词条\n7.有Next功能(一般是3~6个),详见Next词条,并且方向和出现时候的方向一致\n8.有Hold功能,详见Hold词条\n9.有DAS系统负责精密并且快速的左右移动,详见DAS词条\n10.如果有出块延迟和消行延迟,那么需要有提前旋转/Hold系统,详见IRS和IHS词条,IMS是本游戏特有",
|
||||
},
|
||||
{"方块形状",
|
||||
"形状 xingzhuang shape tetrimino",
|
||||
"形状 xingzhuang shape tetromino tetrimino",
|
||||
"term",
|
||||
"在标准的方块游戏中,用到的方块是所有的“四连块”,即四个正方形通过共用边连接成的形状。\n在不允许翻转,只允许旋转的情况下,四连块一共有七种,根据它们的形状一般分别叫做Z、S、J、L、T、O、I。",
|
||||
"在标准的方块游戏中,用到的方块是所有的“四连块”,即四个正方形共用边连接成的形状。\n在不允许翻转,只允许旋转的情况下,四连块一共有七种,根据它们的形状一般分别叫做Z、S、J、L、T、O、I。",
|
||||
},
|
||||
{"方块颜色",
|
||||
"颜色 yanse color colour",
|
||||
"颜色 yanse color colour tetromino tetrimino",
|
||||
"term",
|
||||
"主流方块游戏中七种块的颜色会使用同一套彩虹配色:\nZ:红 S:绿 J:蓝 L:橙 T:紫 O:黄 I:青\n\nTechmino默认也使用这一套“标准”配色。",
|
||||
},
|
||||
{"IRS",
|
||||
"提前 irs initialrotatesystem",
|
||||
"term",
|
||||
"Initial Rotation System\n提前旋转系统,提前按下旋转后方块出现就是转好的形状,有时可以避免死亡。",
|
||||
"Initial Rotation System\n提前旋转系统,方块出现前提前按下旋转后,出现时就是转好的形状,有时可以避免死亡。",
|
||||
},
|
||||
{"IHS",
|
||||
"提前 ihs initialholdsystem",
|
||||
"term",
|
||||
"Initial Hold System\n提前Hold系统,提前按下hold后直接出现hold里的方块,有时可以避免死亡。",
|
||||
"Initial Hold System\n提前Hold系统,方块出现前提前按下hold后,直接出现hold里的方块,有时可以避免死亡。",
|
||||
},
|
||||
{"IMS",
|
||||
"提前 ims initialmovesystem",
|
||||
"term",
|
||||
"Initial Move System\n提前移动系统,提前按下移动后方块出现在移动好的位置,有时可以避免死亡(Techmino限定)。",
|
||||
"Initial Move System\n提前移动系统,方块出现前提前按住移动后,出现时会朝移动方向偏一格,有时可以避免死亡(Techmino限定)。",
|
||||
},
|
||||
{"Next",
|
||||
"预览 下一个 next yulan xiayige",
|
||||
@@ -537,6 +567,11 @@ return{
|
||||
"term",
|
||||
"交换功能,Hold的另一种表现形式,将手里的方块和Next槽中的第一个交换,一般同样不能连续使用。",
|
||||
},
|
||||
{"Deepdrop",
|
||||
"深降 deepdrop shenjiang",
|
||||
"term",
|
||||
"开启后当方块触底时,再次按下软降会让方块尝试向下穿墙寻找放得下的地方,如果有就会直接瞬移到那\n该功能更偏向用于技术研究,对于ai来说有了它可以完全不用再考虑旋转系统,形状能容得下的地方一定都能到达",
|
||||
},
|
||||
{"Misdrop",
|
||||
"误 md misdrop",
|
||||
"term",
|
||||
@@ -745,7 +780,7 @@ return{
|
||||
{"Hypertap",
|
||||
"超连点 hypertap",
|
||||
"term",
|
||||
"快速震动手指,实现比长按更快速+灵活的高速单点移动,主要在经典块的高难度下(因为das不可调而且特别慢,高速下很容易md导致失败,此时手动连点就比自动移动更快)或者受特殊情况限制不适合用自动移动时使用。会使用这个技术的人称为“Hypertapper”tapper。",
|
||||
"快速震动手指,实现比长按更快速+灵活的高速单点移动,主要在经典块的高难度下(因为das不可调而且特别慢,高速下很容易md导致失败,此时手动连点就比自动移动更快)或者受特殊情况限制不适合用自动移动时使用。会使用这个技术的人称为“Hypertapper”。",
|
||||
},
|
||||
{"TOP攻击表",
|
||||
"攻击表 top attack",
|
||||
@@ -760,7 +795,7 @@ return{
|
||||
{"C2序列",
|
||||
"c2序列 seq",
|
||||
"term",
|
||||
"七个块初始权重0\n全体除以2再加0~1的随机数,选数字最大的块出,然后将其权重除以3.5,循环",--Discovered by zxc
|
||||
"(七个块初始权重设为0)\n要取块的时候,\n先把七个数都除以2然后加上0~1的随机数\n最大的数字是第几个的就出对应的块,然后将其权重除以3.5\n循环",--Discovered by zxc
|
||||
},
|
||||
{"C2踢墙",
|
||||
"c2踢墙 kick",
|
||||
@@ -973,25 +1008,6 @@ return{
|
||||
"在STSD上叠若干个T3的形状。",
|
||||
},
|
||||
|
||||
--其他
|
||||
{"研究群",
|
||||
"研究群 yanjiu study",
|
||||
"other",
|
||||
"俄罗斯方块·[研究]群QQ号112897780,“中国俄罗斯方块总群”",
|
||||
},
|
||||
{"茶服",
|
||||
"茶服 chafu study",
|
||||
"other",
|
||||
"TO-S的添加方法、说明等关于茶服的一切",
|
||||
"http://teatube.ltd/tos",
|
||||
},
|
||||
{"GitHub仓库",
|
||||
"源代码 github git sourcecode yuandaima",
|
||||
"other",
|
||||
"Techmino的GitHub仓库地址,欢迎Star",
|
||||
"https://github.com/26F-Studio/Techmino",
|
||||
},
|
||||
|
||||
--存档管理
|
||||
{"控制台",
|
||||
"console cmd commamd minglinghang kongzhitai",
|
||||
@@ -1095,12 +1111,12 @@ return{
|
||||
{"Furea",
|
||||
"furea fuleiya jk",
|
||||
"name",
|
||||
"一流玩家,PPT的40L和Ultra的WR保持者。",
|
||||
"一流玩家,PPT的Ultra的WR保持者。",
|
||||
},
|
||||
{"Iljain",
|
||||
"iljain yijianlian",
|
||||
"name",
|
||||
"一流玩家,得过C2 Rank1,",
|
||||
"一流玩家,得过C2 Rank1。",
|
||||
},
|
||||
{"Jonas",
|
||||
"jonas",
|
||||
@@ -1141,10 +1157,10 @@ return{
|
||||
{"小Z",
|
||||
"小Z xiaoz zictionary tetrodictionary littlez",
|
||||
"name",
|
||||
"这个词典的名字!曾经是群里的答疑机器人,此词典数据库开始也是沿用的机器人问答库~",
|
||||
"这个词典的名字!\n收录了各种常见术语的简单介绍和一些常用问题的回答,不是那种很详细的百科全书哦~\n曾经是群里的答疑机器人,主要用于方便地给新人答疑解惑,词典的数据开始也是沿用的机器人问答库",
|
||||
},
|
||||
{"MrZ",
|
||||
"mrz zjiang ddd 026 t626",
|
||||
"mrz zjiang t026 t626",
|
||||
"name",
|
||||
"【研究群】「T026」\n40L 25.95s,MPH40L 57s排世界第8(Jstris),TETR.IO段位X,TGM3(W)Shirase金1300通关。\n这个游戏的作者!",
|
||||
"https://space.bilibili.com/225238922",
|
||||
@@ -1219,7 +1235,7 @@ return{
|
||||
{"他天一",
|
||||
"他天一 tty tatianyi hydrofierus t512",
|
||||
"name",
|
||||
"【研究群】「T512」\n其他名称:Hydrofierus\n40L 22.72s,io段位X\nC2/SRS对战水平国内一流\n常用定式:tki 开局pc",
|
||||
"【研究群】「T512」\n其他名称:Hydrofierus\n40L 21.908s,io段位X\nC2/SRS对战水平国内一流\n常用定式:tki 开局pc",
|
||||
"https://space.bilibili.com/3895759",
|
||||
},
|
||||
{"Mars608",
|
||||
@@ -1231,7 +1247,7 @@ return{
|
||||
{"Mifu",
|
||||
"mifu swl nanmaomao t616",
|
||||
"name",
|
||||
"【研究群】「T616」\n40L 32s\nvup,miya的哥哥",
|
||||
"【研究群】「T616」\n40L 28.445s\nvup,miya的哥哥",
|
||||
"https://space.bilibili.com/109356367",
|
||||
},
|
||||
{"ZXC",
|
||||
@@ -1279,7 +1295,7 @@ return{
|
||||
{"琳雨空",
|
||||
"琳雨空 linyukong t1505",
|
||||
"name",
|
||||
"【研究群】「T1505」\n40L 38.3s,五连块S,黑屏隐形S(世界首位)",
|
||||
"【研究群】「T1505」\n40L 38.3s,五连块最高评级,黑屏隐形最高评级(世界首位)",
|
||||
"https://space.bilibili.com/263909369",
|
||||
},
|
||||
{"子心",
|
||||
|
||||
@@ -21,7 +21,8 @@ return{
|
||||
powerUp={[0]="+000%","+025%","+050%","+075%","+100%"},
|
||||
cmb={nil,"1 Combo","2 Combo","3 Combo","4 Combo","5 Combo","6 Combo","7 Combo","8 Combo","9 Combo","10 Combo!","11 Combo!","12 Combo!","13 Combo!","14 Combo!!","15 Combo!!","16 Combo!!","17 Combo!!!","18 Combo!!!","19 Combo!!!","MEGACMB"},
|
||||
spin="-spin",
|
||||
clear={"Single","Double","Triple","Techrash","Pentacrash","Hexacrash"},
|
||||
clear={"Single","Double","Triple","Techrash","Pentacrash","Hexacrash","Heptacrash","Octacrash","Nonacrash","Decacrash","Undecacrash","Dodecacrash","Tridecacrash","Tetradecacrash","Pentadecacrash","Hexadecacrash","Heptadecacrash","Octadecacrash","Nonadecacrash","Ultracrash","Impossicrash"},
|
||||
cleared="$1 lines",
|
||||
mini="Mini",b2b="B2B ",b3b="B2B2B ",
|
||||
PC="Perfect Clear",HPC="Hemi-Perfect Clear",
|
||||
replaying="[Replay]",
|
||||
@@ -315,7 +316,7 @@ return{
|
||||
net_game={
|
||||
ready="Ready",
|
||||
spectate="Spectate",
|
||||
cancel="Cancel",
|
||||
cancel="Cancel ready",
|
||||
},
|
||||
setting_game={
|
||||
title="Game Settings",
|
||||
@@ -676,9 +677,6 @@ return{
|
||||
['dig_400l']= {"Dig", "400L", "Dig 400 garbage lines"},
|
||||
['drought_n']= {"Drought", "100L", "No I-pieces available"},
|
||||
['drought_l']= {"Drought+", "100L", "W T F"},
|
||||
['stack_e']= {"Stack", "EASY", "Pack them!"},
|
||||
['stack_h']= {"Stack", "HARD", "Pack them!"},
|
||||
['stack_u']= {"Stack", "ULTIMATE", "Pack them!"},
|
||||
['marathon_n']= {"Marathon", "NORMAL", "200-line marathon with increasing speed"},
|
||||
['marathon_h']= {"Marathon", "HARD", "200-line high-speed marathon"},
|
||||
['solo_e']= {"Battle", "EASY", "Defeat the AI!"},
|
||||
@@ -703,9 +701,6 @@ return{
|
||||
['master_final']= {"Master", "FINAL", "20G and beyond"},
|
||||
['master_ph']= {"Master", "PHANTASM", "???"},
|
||||
['master_ex']= {"GrandMaster", "EXTRA", "An eternity shorter than an instant"},
|
||||
['rhythm_e']= {"Rhythm", "EASY", "200-line low-BPM rhythm marathon"},
|
||||
['rhythm_h']= {"Rhythm", "HARD", "200-line medium BPM rhythm marathon"},
|
||||
['rhythm_u']= {"Rhythm", "ULTIMATE", "200-line high-BPM rhythm marathon"},
|
||||
['blind_e']= {"Invisible", "HALF", "For novices"},
|
||||
['blind_n']= {"Invisible", "ALL", "For intermediates"},
|
||||
['blind_h']= {"Invisible", "SUDDEN", "For the experienced"},
|
||||
@@ -751,29 +746,31 @@ return{
|
||||
['backfire_l']= {"Backfire", "LUNATIC", "Hold back the backfiring garbage lines"},
|
||||
['backfire_u']= {"Backfire", "ULTIMATE", "Hold back the backfiring garbage lines"},
|
||||
['sprintAtk']= {"Sprint", "100 Attack", "Send 100 lines!"},
|
||||
['sprintEff']= {"Sprint", "Efficiency", "Send more attack in 40lines!"},
|
||||
['zen']= {'Zen', "200", "A 200-line run without a time limit"},
|
||||
['ultra']= {'Ultra', "EXTRA", "A 2-minute score attack"},
|
||||
['infinite']= {'infinite', "", "Just a sandbox"},
|
||||
['infinite_dig']= {"Infinite: Dig", "", "Dig-diggin'-dug"},
|
||||
['marathon_inf']= {"Marathon", "INFINITE", "Infinite marathon."},
|
||||
|
||||
['custom_clear']= {"Custom", "NORMAL"},
|
||||
['custom_puzzle']= {"Custom", "PUZZLE"},
|
||||
},
|
||||
getTip={refuseCopy=true,
|
||||
'Free-to-play block stacking game with a Battle Royale mode!',
|
||||
'Have you noticed what "rotating" does do to a block?',
|
||||
":pog:",
|
||||
"(RUR'U')R'FR2U'R'U'(RUR'F')",
|
||||
"\"Example App\" cannot be opened because the developer cannot be verified.",
|
||||
"\"Techmino.app\" cannot be opened because the developer cannot be verified.",
|
||||
"\"Techmino.app\" will damage your computer. You should move it to the Bin.",
|
||||
"\"TechminOS\"",
|
||||
"\\jezevec/\\jezevec/\\jezevec/",
|
||||
"\\osk/\\osk/\\osk/",
|
||||
"↑↑↓↓←→←→BA",
|
||||
"$include<studio.h>",
|
||||
"0next 0hold",
|
||||
"0next 0hold.",
|
||||
"1next 0hold",
|
||||
"1next 1hold!",
|
||||
"1next 6hold!",
|
||||
"20G actually is a brand new game rule.",
|
||||
"20G actually is a brand new game rule!",
|
||||
"40-line Sprint WR: 14.915s by Reset_",
|
||||
"6next 1hold!",
|
||||
"6next 6hold?!",
|
||||
@@ -782,7 +779,6 @@ return{
|
||||
"Am G F G",
|
||||
"B2B2B???",
|
||||
"B2B2B2B does not exist.",
|
||||
"B2B2B2B exists?",
|
||||
"Back-to-Back Techrash, 10 Combo, PC!",
|
||||
"Be sure to give it your best shot again today!",
|
||||
"Bridge clear coming soon!",
|
||||
@@ -792,49 +788,60 @@ return{
|
||||
"Color clear coming soon!",
|
||||
"Decreasing DAS and ARR makes your game faster but harder to control.",
|
||||
"Did I just see a Back-to-Back-to-Back?",
|
||||
"Does B2B2B2B exists?",
|
||||
"Don't let a small glitch ruin your entire day!",
|
||||
"Don't look directly at the bugs!",
|
||||
"Enjoy the Techmino rotation system!",
|
||||
"Excellent, but let's go better next time…",
|
||||
"Find out what's in the settings!",
|
||||
"Found any bugs? Open up an issue in our GitHub page!",
|
||||
"Free-to-play block stacking game with a Battle Royale mode!",
|
||||
"git commit",
|
||||
"git push -f",
|
||||
"Got any suggestions? Post them in our Discord!",
|
||||
"Have you noticed what \"rotating\" does do to a block?",
|
||||
"Headphones recommended for a better experience.",
|
||||
"Hello world!",
|
||||
"I3 and L3 are the only two unique tetrominoes.",
|
||||
"hello world",
|
||||
"I3 and L3 are the only two unique triminoes.",
|
||||
"if a==true",
|
||||
"Increase your frame rate for a better experience.",
|
||||
"Initial [insert action] system can save you.",
|
||||
"Is B2B2B2B possible?",
|
||||
"It's possible to finish 40L without left/right button.",
|
||||
"It is loading! Not just a cutscene!",
|
||||
"It's possible to finish 40L without left/right buttons.",
|
||||
"It's possible to finish 40L without rotation buttons.",
|
||||
"Join our Discord!",
|
||||
"l-=-1",
|
||||
"Let the bass kick!",
|
||||
"Low frame rates reduce your gaming experience.",
|
||||
"LrL RlR LLr RRl RRR LLL FFF RfR RRf rFF",
|
||||
"Lua No.1",
|
||||
"Mix clear coming soon!",
|
||||
"Most of the button icons are realized by using self-drawn glyphs in the Unicode Private Use Area.",
|
||||
"Music of this game is made using Beepbox.",
|
||||
"Music too distracting? You can turn it off.",
|
||||
"No easter eggs in this menu if you have the simplistic style turned on!",
|
||||
"O-Spin Triple!",
|
||||
"OHHHHHHHHHHHHHH",
|
||||
"Online mode is planned - please be patient.",
|
||||
"Online mode is planned — please be patient.",
|
||||
"Play single-handedly!",
|
||||
"Playing good takes some time!",
|
||||
"Powered by LÖVE",
|
||||
"Powered by Un..LÖVE",
|
||||
"pps-0.01",
|
||||
"Secret number: 626",
|
||||
"Server down randomly",
|
||||
"Some requirements to achieve rank S are intentionally set to be difficult for even the best players.",
|
||||
"Some requirements to achieve rank X are intentionally set to be difficult for even the best players.",
|
||||
"Soon you'll be able to play against friends and foes all over the world.",
|
||||
"Split clear coming soon!",
|
||||
"Surely loading! Not just a cutscene!",
|
||||
"sudo rm -rf /*",
|
||||
"Techmino = Technique + Tetromino",
|
||||
"Techmino has a Nspire-CX edition!",
|
||||
"Techmino is so fun!",
|
||||
"Techmino.app will damage your computer. You should move it to the Bin.",
|
||||
"TetroDictionary is now available in English.",
|
||||
"The names that appeared in the background of the Staff page is a list of our sponsors.",
|
||||
"The stacker future is yours in Techmino!",
|
||||
"There are four hidden modes in the game.",
|
||||
"There are several hidden modes in the game that cannot be entered using the map.",
|
||||
"There is a total of 18 different pentominoes.",
|
||||
"There is a total of 7 different tetrominoes.",
|
||||
"Try using multiple Hold Queues!",
|
||||
@@ -846,28 +853,37 @@ return{
|
||||
"What is this cheap UI & music smh",
|
||||
"while(false)",
|
||||
"You are a Grand Master!",
|
||||
"You can connect a keyboard to your phone or tablet!",
|
||||
"You are welcome to help us to make BGMs and SFXs!",
|
||||
"You can connect a keyboard to your phone or tablet (not functional on iOS though).",
|
||||
"You can customize the key mappings in settings!",
|
||||
"You can navigate the menu with a keyboard, but only in this screen.",
|
||||
"You can open the save directory from the Stats page.",
|
||||
"You can perform a spin with 28 of the 29 minos in this game; the exception being O1.",
|
||||
"You can perform a spin with 28 of the 29 minoes in this game; the exception being O1.",
|
||||
"You can set the spawning orientation for each tetromino.",
|
||||
"ZS JL T O I",
|
||||
{C.C,"Also try 15puzzle!"},
|
||||
{C.C,"Also try Ballance!"},
|
||||
{C.C,"Also try Minecraft!"},
|
||||
{C.C,"Also try Minesweeper!"},
|
||||
{C.C,"Also try Orzmic!"},
|
||||
{C.C,"Also try osu!"},
|
||||
{C.C,"Also try Phigros!"},
|
||||
{C.C,"Also try Puyo Puyo!"},
|
||||
{C.C,"Also try Rubik's cube!"},
|
||||
{C.C,"Also try Terraria!"},
|
||||
{C.C,"Also try Touhou Project!"},
|
||||
{C.C,"Also try VVVVVV!"},
|
||||
{C.C,"Also try World of goo!"},
|
||||
{C.C,"Also try Zuma!"},
|
||||
{C.H,"REGRET!!"},
|
||||
{C.lP,"Secret number: 626"},
|
||||
{C.lR,"Z ",C.lG,"S ",C.lS,"J ",C.lO,"L ",C.lP,"T ",C.lY,"O ",C.lC,"I"},
|
||||
{C.lY,"COOL!!"},
|
||||
{C.N,"Lua",C.Z," No.1"},
|
||||
{C.P,"T-spin!"},
|
||||
{C.R,"\"DMCA abusing\""},
|
||||
{C.R,"\"Intellectual property law\""},
|
||||
{C.R,"DD",C.Z," Cannon=",C.P,"TS",C.R,"D",C.Z,"+",C.P,"TS",C.R,"D",C.Z," Cannon"},
|
||||
{C.R,"DT",C.Z," Cannon=",C.P,"TS",C.R,"D",C.Z,"+",C.P,"TS",C.R,"T",C.Z," Cannon"},
|
||||
{C.R,"LrL ",C.G,"RlR ",C.B,"LLr ",C.O,"RRl ",C.P,"RRR ",C.P,"LLL ",C.C,"FFF ",C.Y,"RfR ",C.Y,"RRf ",C.Y,"rFF"},
|
||||
{C.Y,"O-Spin Triple!"},
|
||||
|
||||
@@ -10,7 +10,8 @@ return{
|
||||
royale_remain="$1 Jugadores Restantes",
|
||||
cmb={nil,"Combo de 1","Combo de 2","Combo de 3","Combo de 4","Combo de 5","Combo de 6","Combo de 7","Combo de 8","Combo de 9","¡Combo de 10!","¡Combo de 11!","¡Combo de 12!","¡Combo de 13!","¡Combo de 14!","¡Combo de 15!","¡Combo de 16!","¡Combo de 17!","¡Combo de 18!","¡Combo de 19!","MEGACOMBO"},
|
||||
spin="-spin",
|
||||
clear={"Single","Doble","Triple","Techrash","Pentacrash","Hexacrash"},
|
||||
clear={"Single","Doble","Triple","Techrash","Pentacrash","Hexacrash","Heptacrash","Octacrash","Nonacrash","Decacrash","Undecacrash","Dodecacrash","Tridecacrash","Tetradecacrash","Pentadecacrash","Hexadecacrash","Heptadecacrash","Octadecacrash","Nonadecacrash","Ultracrash","Impossicrash"},
|
||||
-- cleared="$1 lines",
|
||||
mini="Mini",b2b="B2B ",b3b="B2B2B ",
|
||||
PC="Perfect Clear",HPC="Half Clear",
|
||||
replaying="[Repetición]",
|
||||
@@ -282,7 +283,7 @@ return{
|
||||
net_game={
|
||||
ready="Estoy Listo",
|
||||
spectate="Espectear",
|
||||
cancel="Cancelar",
|
||||
-- cancel="Cancel ready",
|
||||
},
|
||||
setting_game={
|
||||
title="Ajustes del Juego",
|
||||
@@ -635,9 +636,6 @@ return{
|
||||
['dig_400l']= {"Queso", "400L", "Limpia 400 líneas de queso."},
|
||||
['drought_n']= {"Sequía", "100L", "¡Sin piezas I!"},
|
||||
['drought_l']= {"Sequía+", "100L", "Guat de foc..."},
|
||||
['stack_e']= {"Stack", "Fácil", "¡Sin dejar huecos!"},
|
||||
['stack_h']= {"Stack", "Difícil", "¡Sin dejar huecos!"},
|
||||
['stack_u']= {"Stack", "Supremo", "¡Sin dejar huecos!"},
|
||||
['marathon_n']= {"Maratón", "Normal", "Maratón de 200 líneas con velocidad en aumento."},
|
||||
['marathon_h']= {"Maratón", "Difícil", "Maratón de 200 líneas a velocidad máxima."},
|
||||
['solo_e']= {"VS.", "Fácil", "¡Derrota a la CPU!"},
|
||||
@@ -661,9 +659,6 @@ return{
|
||||
-- ['master_m']= {"Master", "M21", "For 20G Masters."},
|
||||
['master_final']= {"Master", "FINAL", "El verdadero 20G Supremo: el final es inalcanzable."},
|
||||
['master_ex']= {"GrandMaster", "EXTRA", "Para ser un gran maestro, acepta este desafío"},
|
||||
['rhythm_e']= {"Al Ritmo", "Fácil", "Maratón rítmica de 200 líneas con bajo bpm."},
|
||||
['rhythm_h']= {"Al Ritmo", "Difícil", "Maratón rítmica de 200 líneas con bpm moderado."},
|
||||
['rhythm_u']= {"Al Ritmo", "Supremo", "Maratón rítmica de 200 líneas con bpm elevado."},
|
||||
['blind_e']= {"A Ciegas", "Parcial", "Para novatos."},
|
||||
['blind_n']= {"A Ciegas", "Total", "Para jugadores intermedios."},
|
||||
['blind_h']= {"A Ciegas", "Inmediato", "Para jugadores experimentados"},
|
||||
@@ -709,10 +704,12 @@ return{
|
||||
['backfire_l']= {"Retorno", "Lunático", "Lidia con tus propias líneas basura."},
|
||||
['backfire_u']= {"Retorno", "Supremo", "Lidia con tus propias líneas basura."},
|
||||
['sprintAtk']= {"Sprint", "100L - Ataque", "¡Envía 100 líneas de ataque!"},
|
||||
-- ['sprintEff']= {"Sprint", "Efficiency", "Send more attack in 40lines!"},
|
||||
['zen']= {'Zen', "200L", "200 líneas sin límite de tiempo."},
|
||||
['ultra']= {'Ultra', "Extra", "¡Consigue el mayor puntaje posible en 2 minutos!"},
|
||||
['infinite']= {"Infinito", "", "Modo Sandbox."},
|
||||
['infinite_dig']= {"Infinito: Queso", "", "Limpia, limpia, más limpia que tú."},
|
||||
['marathon_inf']= {"Maratón", "Infinito", "Infinito maratón."},
|
||||
|
||||
['custom_clear']= {"Personalizado", "Normal"},
|
||||
['custom_puzzle']= {"Personalizado", "Puzzle"},
|
||||
|
||||
@@ -10,7 +10,8 @@ return{
|
||||
royale_remain="$1 Joueurs restants",
|
||||
cmb={nil,"1 Combo","2 Combo","3 Combo","4 Combo","5 Combo","6 Combo","7 Combo","8 Combo","9 Combo","10 Combo!","11 Combo!","12 Combo!","13 Combo!","14 Combo!!","15 Combo!!","16 Combo!!","17 Combo!!!","18 Combo!!!","19 Combo!!!","MEGACMB"},
|
||||
spin="-spin",
|
||||
clear={"Simple","Double","Triple","Techrash","Pentacrash","Hexacrash"},
|
||||
clear={"Simple","Double","Triple","Techrash","Pentacrash","Hexacrash","Heptacrash","Octacrash","Nonacrash","Decacrash","Undecacrash","Dodecacrash","Tridecacrash","Tetradecacrash","Pentadecacrash","Hexadecacrash","Heptadecacrash","Octadecacrash","Nonadecacrash","Ultracrash","Impossicrash"},
|
||||
-- cleared="$1 lines",
|
||||
mini="Mini",b2b="B2B ",b3b="B2B2B ",
|
||||
PC="Perfect Clear",HPC="Clear",
|
||||
replaying="[Replay]",
|
||||
@@ -278,7 +279,7 @@ return{
|
||||
net_game={
|
||||
-- ready="Ready",
|
||||
-- spectate="Spectate",
|
||||
-- cancel="Cancel",
|
||||
-- cancel="Cancel ready",
|
||||
},
|
||||
setting_game={
|
||||
title="Paramètres du jeu",
|
||||
@@ -637,7 +638,6 @@ return{
|
||||
['drought_n']= {"Drought", "100L", "Pas de pièce I !"},
|
||||
['drought_l']= {"Drought+", "100L", "WTF ??!!"},
|
||||
-- ['stack_e']= {"Stack", "FACILE", "Pack them!"},
|
||||
-- ['stack_h']= {"Stack", "DIFFICILE", "Pack them!"},
|
||||
-- ['stack_u']= {"Stack", "ULTIME", "Pack them!"},
|
||||
['marathon_n']= {"Marathon", "NORMAL", "Marathon de 200 lignes."},
|
||||
['marathon_h']= {"Marathon", "DIFFICILE", "Marathon de 200 lignes à très haute vitesse"},
|
||||
@@ -663,9 +663,6 @@ return{
|
||||
['master_final']= {"Master", "FINAL", "20G : Un point final impossible à atteindre !"},
|
||||
-- ['master_ph']= {"Mester", "FANTASMA", "20G: ???"},
|
||||
['master_ex']= {"GrandMaster", "EXTRA", "Tentez de devenir un Grandmaster."},
|
||||
-- ['rhythm_e']= {"Rhythm", "EASY", "200-line low-bpm rhythm marathon."},
|
||||
-- ['rhythm_h']= {"Rhythm", "HARD", "200-line medium-bpm rhythm marathon"},
|
||||
-- ['rhythm_u']= {"Rhythm", "ULTIMATE", "200-line high-bpm rhythm marathon."},
|
||||
['blind_e']= {"Aveugle", "MOITIE", "Pour les novices."},
|
||||
['blind_n']= {"Aveugle", "TOUT", "Pour les joueurs intermédiaires."},
|
||||
['blind_h']= {"Aveugle", "SOUDAIN", "Pour les bons jooeurs."},
|
||||
@@ -711,10 +708,12 @@ return{
|
||||
-- ['backfire_l']= {"Backfire", "LUNATIC", "Self-send garbages"},
|
||||
-- ['backfire_u']= {"Backfire", "ULTIMATE", "Self-send garbages"},
|
||||
-- ['sprintAtk']= {"Sprint", "100 Attack", "Send 100 lines!"},
|
||||
-- ['sprintEff']= {"Sprint", "Efficiency", "Send more attack in 40lines!"},
|
||||
['zen']= {'Zen', "200", "200 lignes sans limites de temps."},
|
||||
['ultra']= {'Ultra', "EXTRA", "2 minutes pour avoir le meilleur score."},
|
||||
['infinite']= {"Infini", "", "Mode tranquile."},
|
||||
['infinite_dig']= {"Infini : Dig", "", "Creuser, creuser, creuser."},
|
||||
['marathon_inf']= {"Marathon", "Infini", "Infini marathon."},
|
||||
|
||||
['custom_clear']= {"Perso.", "NORMAL"},
|
||||
['custom_puzzle']= {"Perso.", "PUZZLE"},
|
||||
|
||||
@@ -11,7 +11,8 @@ return{
|
||||
royale_remain="$1 Jogadores restantes",
|
||||
cmb={nil,"1 Combo","2 Combo","3 Combo","4 Combo","5 Combo","6 Combo","7 Combo","8 Combo","9 Combo","10 Combo!","11 Combo!","12 Combo!","13 Combo!","14 Combo!!","15 Combo!!","16 Combo!!","17 Combo!!!","18 Combo!!!","19 Combo!!!","MEGACMB"},
|
||||
spin="-spin",
|
||||
clear={"Single","Double","Triple","Techrash","Pentacrash","Hexacrash"},
|
||||
clear={"Single","Double","Triple","Techrash","Pentacrash","Hexacrash","Heptacrash","Octacrash","Nonacrash","Decacrash","Undecacrash","Dodecacrash","Tridecacrash","Tetradecacrash","Pentadecacrash","Hexadecacrash","Heptadecacrash","Octadecacrash","Nonadecacrash","Ultracrash","Impossicrash"},
|
||||
-- cleared="$1 lines",
|
||||
mini="Mini",b2b="B2B ",b3b="B2B2B ",
|
||||
PC="Perfect Clear",HPC="Clear",
|
||||
replaying="[Replay]",
|
||||
@@ -304,7 +305,7 @@ return{
|
||||
net_game={
|
||||
-- ready="Ready",
|
||||
-- spectate="Spectate",
|
||||
-- cancel="Cancel",
|
||||
-- cancel="Cancel ready",
|
||||
},
|
||||
setting_game={
|
||||
title="Config. de jogo",
|
||||
@@ -667,7 +668,6 @@ return{
|
||||
['drought_n']= {"Drought", "100L", "Sem peça I !"},
|
||||
['drought_l']= {"Drought+", "100L", "WTF"},
|
||||
-- ['stack_e']= {"Stack", "FÁCIL", "Pack them!"},
|
||||
-- ['stack_h']= {"Stack", "DIFÍCIL", "Pack them!"},
|
||||
-- ['stack_u']= {"Stack", "ULTIMATE", "Pack them!"},
|
||||
['marathon_n']= {"Maratona", "NORMAL", "200-line Maratona com velocidade aumentando."},
|
||||
['marathon_h']= {"Maratona", "DIFÍCIL", "200-line Maratona com velocidade alta."},
|
||||
@@ -693,9 +693,6 @@ return{
|
||||
['master_final']= {"Mestre", "FINAL", "20G: Final inalcançável!"},
|
||||
['master_ph']= {"Mestre", "FANTASMA", "20G: ???"},
|
||||
['master_ex']= {"GrandMaster", "EXTRA", "Para ser um Grand Master, aceite \nesse desafio."},
|
||||
-- ['rhythm_e']= {"Rhythm", "EASY", "200-line low-bpm rhythm marathon."},
|
||||
-- ['rhythm_h']= {"Rhythm", "HARD", "200-line medium-bpm rhythm marathon"},
|
||||
-- ['rhythm_u']= {"Rhythm", "ULTIMATE", "200-line high-bpm rhythm marathon."},
|
||||
['blind_e']= {"Cego", "METADE", "Para novatos."},
|
||||
['blind_n']= {"Cego", "TUDO", "Para intermediários."},
|
||||
['blind_h']= {"Cego", "DE REPENTE", "Para experientes."},
|
||||
@@ -741,10 +738,12 @@ return{
|
||||
-- ['backfire_l']= {"Backfire", "LUNATIC", "Self-send garbages"},
|
||||
-- ['backfire_u']= {"Backfire", "ULTIMATE", "Self-send garbages"},
|
||||
-- ['sprintAtk']= {"Sprint", "100 Attack", "Send 100 lines!"},
|
||||
-- ['sprintEff']= {"Sprint", "Efficiency", "Send more attack in 40lines!"},
|
||||
['zen']= {'Zen', "200", "200 linhas sem um limite de tempo."},
|
||||
['ultra']= {'Ultra', "EXTRA", "Pegue a maior pontuação em 2 minutos."},
|
||||
['infinite']= {"Infinito", "", "Modo Sandbox."},
|
||||
['infinite_dig']= {"Infinito:Cave", "", "Cava, Cava, Cava."},
|
||||
['marathon_inf']= {"Maratona", "Infinito", "Infinito maratona."},
|
||||
|
||||
['custom_clear']= {"Custom", "NORMAL"},
|
||||
['custom_puzzle']= {"Custom", "PUZZLE"},
|
||||
@@ -830,13 +829,16 @@ return{
|
||||
"Você pode escolher uma orientação pra cada blococan.",
|
||||
"ZS JL T O I",
|
||||
{C.C,"Tente também 15puzzle"},
|
||||
{C.C,"Tente também Ballance!"},
|
||||
{C.C,"Tente também Cubo de Rubik"},
|
||||
{C.C,"Tente também Minecraft"},
|
||||
{C.C,"Tente também Minesweeper"},
|
||||
{C.C,"Tente também osu!"},
|
||||
{C.C,"Tente também Phigros"},
|
||||
{C.C,"Tente também Cubo de Rubik"},
|
||||
{C.C,"Tente também Terraria"},
|
||||
{C.C,"Tente também VVVVVV"},
|
||||
{C.C,"Tente também World of goo!"},
|
||||
{C.C,"Tente também Zuma!"},
|
||||
{C.F,"Tente também Cultris II"},
|
||||
{C.F,"Tente também Jstris"},
|
||||
{C.F,"Tente também Nullpomino"},
|
||||
|
||||
@@ -5,7 +5,8 @@ return{
|
||||
royale_remain="$1 ~",
|
||||
cmb={nil,"!","!!","!!!","!!!!","!!!!!","!!!!!!","!!!!!!!","!!!!!!!!","!!!!!!!!!","!!!!!!!!!!","!!!!!!!!!!!","!!!!!!!!!!!!","!!!!!!!!!!!!!","!!!!!!!!!!!!!!","!!!!!!!!!!!!!!!","!!!!!!!!!!!!!!!!","!!!!!!!!!!!!!!!!!","!!!!!!!!!!!!!!!!!!","!!!!!!!!!!!!!!!!!!!","!!!!!!!!!!!!!!!!!!!!",},
|
||||
spin=" ~",
|
||||
clear={"1","2","3","4","5","6"},
|
||||
clear={"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","20+"},
|
||||
cleared="",
|
||||
mini="v",b2b="^ ",b3b="^^ ",
|
||||
PC="#<>#",HPC="<>",
|
||||
replaying="[R]",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user