Compare commits
162 Commits
pre0.16.3
...
pre0.16.5-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed011173f6 | ||
|
|
491fcb5860 | ||
|
|
c2d5537d8d | ||
|
|
7d5037ae87 | ||
|
|
07d7714317 | ||
|
|
2cab97f37d | ||
|
|
d184778c9a | ||
|
|
9fd3b3008d | ||
|
|
71aa35b214 | ||
|
|
4443dc9d3e | ||
|
|
839e357301 | ||
|
|
ac56c5a415 | ||
|
|
36e3343341 | ||
|
|
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 | ||
|
|
c485c26c93 | ||
|
|
137d9296cd | ||
|
|
11b144da74 | ||
|
|
25ef9d9886 | ||
|
|
0e1e279209 | ||
|
|
a960897a83 | ||
|
|
69ab7849c5 | ||
|
|
bc55c3d892 |
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)
|
||||
|
||||
@@ -63,9 +63,9 @@ function STRING.time(t)
|
||||
if t<60 then
|
||||
return format("%.3f\"",t)
|
||||
elseif t<3600 then
|
||||
return format("%d'%05.2f\"",int(t/60),t%60)
|
||||
return format("%d'%05.2f\"",int(t/60),int(t%60*100)/100)
|
||||
else
|
||||
return format("%d:%.2d'%05.2f\"",int(t/3600),int(t/60%60),t%60)
|
||||
return format("%d:%.2d'%05.2f\"",int(t/3600),int(t/60%60),int(t%60*100)/100)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -46,6 +46,18 @@ function TABLE.cover(new,old)
|
||||
end
|
||||
end
|
||||
|
||||
--For all things in new, push to old
|
||||
function TABLE.coverR(new,old)
|
||||
for k,v in next,new do
|
||||
if type(v)=='table'and type(old[k])=='table'then
|
||||
TABLE.coverR(v,old[k])
|
||||
else
|
||||
old[k]=v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--For all things in new if same type in old, push to old
|
||||
function TABLE.update(new,old)
|
||||
for k,v in next,new do
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
117
main.lua
117
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()
|
||||
@@ -199,7 +205,7 @@ Z.setOnQuit(destroyPlayers)
|
||||
TABLE.cover (FILE.load('conf/user')or{},USER)
|
||||
TABLE.cover (FILE.load('conf/unlock')or{},RANKS)
|
||||
TABLE.update(FILE.load('conf/settings')or{},SETTING)
|
||||
TABLE.update(FILE.load('conf/data')or{},STAT)
|
||||
TABLE.coverR(FILE.load('conf/data')or{},STAT)
|
||||
TABLE.cover (FILE.load('conf/key')or{},KEY_MAP)
|
||||
TABLE.cover (FILE.load('conf/virtualkey')or{},VK_ORG)
|
||||
|
||||
@@ -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.
@@ -353,8 +353,8 @@ do
|
||||
[21]={'+0+0','-1+0','-1+1','+0+1','-1+2','+0+2','-1-1','+1+0','+0-2','-1-2'},
|
||||
[32]={'+0+0','-1+0','-1+1','-1-1','+1+0','+0+2','-1+2','+0-2'},
|
||||
[23]={'+0+0','+1+0','+1-1','+1+1','-1+0','+0-2','+1-2','+0+2'},
|
||||
[02]={'+0+0','+0-1','+1-1','-1+0','+2-1'},
|
||||
[20]={'+0+0','+0+1','-1+1','+1+0','-2+1'},
|
||||
[02]={'+0+0','+0-1','-1-1','+1-1','-1+0','+2-1'},
|
||||
[20]={'+0+0','+0+1','+1+1','-1+1','+1+0','-2+1'},
|
||||
[13]={'+0+0','-1+0','-1-1','+0+1','-1-2'},
|
||||
[31]={'+0+0','+1+0','+1+1','+0-1','+1+2'},
|
||||
},--J5
|
||||
@@ -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[_])
|
||||
|
||||
@@ -50,9 +50,6 @@ local botMeta={__index=_undefMethod}
|
||||
local BOT={}
|
||||
|
||||
local AISpeed={60,50,40,30,20,14,10,6,4,3}
|
||||
-- For CC bot:
|
||||
-- TODO you still need to switch20G() at the right time.
|
||||
-- since it's not cc-specific I'm not dealing with it for now
|
||||
--[[
|
||||
arg={
|
||||
next: number of nexts
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
local gc_setColor=love.graphics.setColor
|
||||
return{
|
||||
das=16,arr=6,
|
||||
sddas=6,sdarr=6,
|
||||
@@ -18,12 +19,24 @@ return{
|
||||
mStr(r<10 and 9 or r<30 and r or("%02x"):format(r*10-300),63,210)
|
||||
mText(TEXTOBJ.speedLV,63,290)
|
||||
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||
if P.modeData.drought>7 then
|
||||
if P.modeData.drought<=14 then
|
||||
gc_setColor(1,1,1,P.modeData.drought/7-1)
|
||||
else
|
||||
local gb=P.modeData.drought<=21 and 2-P.modeData.drought/14 or .5
|
||||
gc_setColor(1,gb,gb)
|
||||
end
|
||||
setFont(50)
|
||||
mStr(P.modeData.drought,63,130)
|
||||
mDraw(MODES.drought_l.icon,63,200,nil,.5)
|
||||
end
|
||||
end,
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
end,
|
||||
dropPiece=function(P)
|
||||
hook_drop=function(P)
|
||||
local D=P.modeData
|
||||
D.drought=P.lastPiece.id==7 and 0 or D.drought+1
|
||||
if P.stat.row>=D.target then
|
||||
if D.target==110 then
|
||||
P.gameEnv.drop,P.gameEnv.lock=5,5
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
local gc_setColor=love.graphics.setColor
|
||||
return{
|
||||
das=16,arr=6,
|
||||
sddas=3,sdarr=3,
|
||||
@@ -15,14 +16,25 @@ return{
|
||||
mesDisp=function(P)
|
||||
setFont(75)
|
||||
local r=P.modeData.target/10
|
||||
mStr(r<11 and 18 or r<22 and r+8 or("%02x"):format(r*10-220),63,210)
|
||||
mStr(r<10 and 9 or r<30 and r or("%02x"):format(r*10-300),63,210)
|
||||
mText(TEXTOBJ.speedLV,63,290)
|
||||
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||
if P.modeData.drought>7 then
|
||||
if P.modeData.drought<=14 then
|
||||
gc_setColor(1,1,1,P.modeData.drought/7-1)
|
||||
else
|
||||
local gb=P.modeData.drought<=21 and 2-P.modeData.drought/14 or .5
|
||||
gc_setColor(1,gb,gb)
|
||||
end
|
||||
setFont(50)
|
||||
mStr(P.modeData.drought,63,130)
|
||||
mDraw(MODES.drought_l.icon,63,200,nil,.5)
|
||||
end
|
||||
end,
|
||||
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
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
local gc_setColor=love.graphics.setColor
|
||||
return{
|
||||
das=16,arr=6,
|
||||
sddas=1,sdarr=1,
|
||||
@@ -15,14 +16,25 @@ return{
|
||||
mesDisp=function(P)
|
||||
setFont(75)
|
||||
local r=P.modeData.target/10
|
||||
mStr(r==1 and 29 or("%02x"):format(r*10-20),63,210)
|
||||
mStr(r<10 and 9 or r<30 and r or("%02x"):format(r*10-300),63,210)
|
||||
mText(TEXTOBJ.speedLV,63,290)
|
||||
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||
if P.modeData.drought>7 then
|
||||
if P.modeData.drought<=14 then
|
||||
gc_setColor(1,1,1,P.modeData.drought/7-1)
|
||||
else
|
||||
local gb=P.modeData.drought<=21 and 2-P.modeData.drought/14 or .5
|
||||
gc_setColor(1,gb,gb)
|
||||
end
|
||||
setFont(50)
|
||||
mStr(P.modeData.drought,63,130)
|
||||
mDraw(MODES.drought_l.icon,63,200,nil,.5)
|
||||
end
|
||||
end,
|
||||
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,
|
||||
}
|
||||
|
||||
19
parts/eventsets/sprintEff_40.lua
Normal file
19
parts/eventsets/sprintEff_40.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
return{
|
||||
mesDisp=function(P)
|
||||
setFont(55)
|
||||
local r=40-P.stat.row
|
||||
if r<0 then r=0 end
|
||||
mStr(r,63,170)
|
||||
PLY.draw.drawTargetLine(P,r)
|
||||
setFont(45)
|
||||
mStr(("%.1f"):format(P.stat.atk),63,270)
|
||||
mText(TEXTOBJ.atk,63,323)
|
||||
mStr(("%.2f"):format(P.stat.atk/P.stat.row),63,370)
|
||||
mText(TEXTOBJ.eff,63,423)
|
||||
end,
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=40 then
|
||||
P:win('finish')
|
||||
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,9 +175,62 @@ 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
|
||||
function getItem(itemName,amount)
|
||||
STAT.item[itemName]=STAT.item[itemName]+(amount or 1)
|
||||
end
|
||||
function coin(a,b)
|
||||
if rnd()<.5 then
|
||||
return a
|
||||
@@ -206,8 +260,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]
|
||||
@@ -224,9 +278,11 @@ function freshDate(mode)
|
||||
if STAT.date~=date then
|
||||
STAT.date=date
|
||||
STAT.todayTime=0
|
||||
getItem('zTicket',1)
|
||||
if not mode:find'q'then
|
||||
MES.new('info',text.newDay)
|
||||
end
|
||||
saveStats()
|
||||
return true
|
||||
end
|
||||
end
|
||||
@@ -280,8 +336,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 +402,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 +466,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 +673,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',
|
||||
@@ -727,6 +726,10 @@ do--Userdata tables
|
||||
spin=(function()local L={}for i=1,29 do L[i]={0,0,0,0,0,0,0}end return L end)(),
|
||||
pc=0,hpc=0,b2b=0,b3b=0,score=0,
|
||||
lastPlay='sprint_10l',--Last played mode ID
|
||||
item=setmetatable({},{__index=function(self,k)
|
||||
self[k]=0
|
||||
return 0
|
||||
end}),
|
||||
date=false,
|
||||
todayTime=0,
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
@@ -408,7 +434,12 @@ return{
|
||||
{"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",
|
||||
@@ -448,7 +479,7 @@ return{
|
||||
{"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",
|
||||
@@ -626,6 +662,16 @@ return{
|
||||
"term",
|
||||
"Modern Tetris games have three different conditions in which the player tops out:\n1. Block out: when a piece spawned overlaps with the existing blocks in the field;\n2. Lock out: when a piece locks entirely above the skyline;\n3. Garbage out: when the stack exceeds 40 lines in height (often due to incoming garbage).\nTechmino does not check for locking out and garbage out.",
|
||||
},
|
||||
{"Buffer zone",
|
||||
"buffer zone",
|
||||
"term",
|
||||
"",--TODO
|
||||
},
|
||||
{"Vanish zone",
|
||||
"vanish zone",
|
||||
"term",
|
||||
"",--TODO
|
||||
},
|
||||
{"Falling speed",
|
||||
"fallingspeed",
|
||||
"term",
|
||||
@@ -636,6 +682,16 @@ return{
|
||||
"term",
|
||||
"The delay between block touching the ground and locking down (i.e. can no longer be controlled, and the next piece spawns).\nModern Tetris games often have forgiving lockdown delay mechanics where you can reset this delay by moving or rotating (up to 15 times), and you can sometimes stall for time by doing this. Classic Tetris games often have a far less forgiving lockdown delay.",
|
||||
},
|
||||
{"ARE",
|
||||
"are spawn appearance delay",
|
||||
"term",
|
||||
"Sometimes called the Entry Delay. ARE refers to the delay between the lockdown of one piece and the spawn of another piece.",
|
||||
},
|
||||
{"line ARE",
|
||||
"line are appearance delay",
|
||||
"term",
|
||||
"The delay between the start of a line clear animation to the spawn of the next piece.",
|
||||
},
|
||||
{"Finesse",
|
||||
"finesse",
|
||||
"term",
|
||||
@@ -691,6 +747,21 @@ return{
|
||||
"term",
|
||||
"A way to generate pieces, notably used in Tetris: The Grand Master games. Every time a random Tetromino is selected, but if this Tetromino is the same as one of the few previous pieces, then reroll until a different piece is rolled or until a reroll limit is reached.\nFor example, a \"his 4 roll 6\" (h4r6) generator rerolls when the piece is the same as one of the 4 previous pieces and rerolls up to 6 times.\nThere are other variations as well, such as \"his4 roll6 pool35\", which further reduces the randomness of the piece sequence.\n\nIn Techmino, the max. reroll count is half of the sequence length, rounded up.",
|
||||
},
|
||||
{"HisPool generator",
|
||||
"hisPool history pool",
|
||||
"term",
|
||||
"History Pool, a generator based on the His generator. It introduced a mechanism called \"Pool\". When generating a new piece, HisPool randomly selects a piece from the Pool and increase the probability of spawning of the least frequent piece.\n\nThis mechanism makes the sequence more stable and ensures that the drought won't last forever.",
|
||||
},
|
||||
{"bagES generator",
|
||||
"bages easy start",
|
||||
"term",
|
||||
"*Techmino-exclusive*\nBag Easy-Start, an improved Bag generator. The first piece in the first bag won't be those hard-to-place pieces (S/Z/O/S5/Z5/F/E/W/X/N/H).",
|
||||
},
|
||||
{"Reverb generator",
|
||||
"reverb",
|
||||
"term",
|
||||
"*Techmino-exclusive*\nA generator derived from Bag. Based on Bag generator, the Reverb generator repeats each piece several times. The probability of repetition decreases when a certain piece repeats too frequently and vice versa. ",
|
||||
},
|
||||
{"Hypertapping",
|
||||
"hypertapping",
|
||||
"term",
|
||||
@@ -917,26 +988,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",
|
||||
@@ -1035,7 +1086,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",
|
||||
@@ -1085,10 +1136,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",
|
||||
@@ -1162,7 +1213,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",
|
||||
@@ -1174,7 +1225,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",
|
||||
@@ -1216,7 +1267,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",
|
||||
@@ -1225,12 +1276,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",
|
||||
@@ -408,7 +433,12 @@ return{
|
||||
{"旋转系统(踢墙)",
|
||||
"旋转系统 踢墙 xuanzhuanxitong wallkick tiqiang",
|
||||
"term",
|
||||
"(部分游戏中)方块旋转后可能和场地或者墙壁有碰撞,此时系统可能会给方块施加偏移,让方块不会因此被卡住而不能操作。这个偏移就是踢墙。\n建议阅读SRS词条。",
|
||||
"现代方块游戏中,方块可以绕着旋转中心(在本游戏中可见)旋转(部分游戏没有固定中心),如果旋转后和场地或墙壁有重合,会根据<从哪个方向转到哪个方向>进行一些偏移测试(这个偏移称为踢墙),不会卡住转不动,同时也可以让方块钻进入一些特定形状的洞",
|
||||
},
|
||||
{"方块朝向",
|
||||
"旋转 朝向 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",
|
||||
@@ -458,7 +488,7 @@ return{
|
||||
{"SRS",
|
||||
"超级旋转系统 srs rotate",
|
||||
"term",
|
||||
"Super Rotation System\n现代方块最常用的旋转系统,也是不少自制旋转系统的设计模板。\n简单原理介绍:每个方块都有一个旋转中心,旋转后如果和场地有重合,会根据<从哪个方向转到哪个方向>进行一些偏移测试,可以让方块钻进入一些特定形状的洞。\n注:对于SRS,每个方块有四个方向,可以朝两边转(180°不算,设计的时候还没有,所以不能踢墙),所以总共8种,对应8个偏移表,具体数据去Wiki上查,这里就不放了",
|
||||
"Super Rotation System\n现代方块最常用的旋转系统,也是不少自制旋转系统的设计模板。\n对于SRS,每个方块有四个方向,可以朝两边转(180°不算,最开始没有这个设计),所以总共8种,对应8个偏移表,具体数据去Wiki上查,这里就不放了",
|
||||
},
|
||||
{"SRS+",
|
||||
"超级旋转系统 srs+ srsplus rotate",
|
||||
@@ -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",
|
||||
@@ -652,6 +687,16 @@ return{
|
||||
"term",
|
||||
"现代方块普遍使用的死亡判定:\n1. 新出现的方块和场地方块有重叠(窒息,Top Out)(c4w比s4w强的原因,因为被打进18行都不会窒息);\n2. 方块锁定时完全在场地的外面(Block Out);\n3. 场地内现存方块总高度大于40。部分游戏可能没有这条判定,而是会自动“切除”场地内所有高度大于40的部分(Vanish Zone)。\n\n注:本游戏使用的死亡判定不包含上述的第二条和第三条。",
|
||||
},
|
||||
{"缓冲区",
|
||||
"缓冲区 buffer zone huanchongqu",
|
||||
"term",
|
||||
"(不是所有游戏都有这个概念)指10×20可见场地之上的21~40行。因为垃圾行顶起后两边堆高的方块可能会超出屏幕,消行后这些方块要重新回到场地内所以需要保存下来,由于程序上要求场地尺寸有限(部分游戏可以无限),故设定为40,一般都够用。\n\n另见“消失区”词条。",
|
||||
},
|
||||
{"消失区",
|
||||
"消失区 vanish zone xiaoshiqu",
|
||||
"term",
|
||||
"在缓冲区的基础上,指比40行缓冲区还高的区域。\n标准的死亡判定涉及了这个概念,在垃圾行升起后如果场地上有任何方块超出了40高的缓冲区(也就是达到了消失区)时游戏直接结束。\n但事实上这块区域在不同游戏中表现不同,甚至有设计者考虑不周导致方块挪到40行以上,所以程序没考虑导致方块接触消失区直接报错闪退的游戏。通常出现在玩家堆了c4w然后被打入大量垃圾行时才会考虑这个概念。其他游戏中方块进入消失区可能直接导致游戏结束,也有可能会出现一些奇怪的bug。\n\n另,Jstris中22行及以上可以理解为消失区,锁定在21行之外的格子会消失。",
|
||||
},
|
||||
{"下落速度",
|
||||
"下落速度 重力 drop speed zhongli gravity",
|
||||
"term",
|
||||
@@ -662,6 +707,16 @@ return{
|
||||
"term",
|
||||
"方块<碰到地面到锁定>之间的时间。经典块仅方块下落一格时刷新倒计时,而现代方块中往往任何操作都将重置该倒计时(但是方块本身必须可以移动/旋转),所以连续移动和操作可以让方块不马上锁定,拖一会时间(本游戏和部分游戏重置次数有限,一般是15)。",
|
||||
},
|
||||
{"出块延迟",
|
||||
"出块延迟 are delay chukuaiyanchi",
|
||||
"term",
|
||||
"方块<锁定完成到下一个方块出现>之间的时间,英文是ARE。",
|
||||
},
|
||||
{"消行延迟",
|
||||
"消行延迟 line are delay xiaohangyanchi",
|
||||
"term",
|
||||
"方块<锁定完成能消行时的消行动画>占据的时间,英文是line ARE。",
|
||||
},
|
||||
{"Finesse",
|
||||
"极简操作 最简操作 finesse jijiancaozuo zuijiancaozuo",
|
||||
"term",
|
||||
@@ -735,7 +790,7 @@ return{
|
||||
{"Hypertap",
|
||||
"超连点 hypertap",
|
||||
"term",
|
||||
"快速震动手指,实现比长按更快速+灵活的高速单点移动,主要在经典块的高难度下(因为das不可调而且特别慢,高速下很容易md导致失败,此时手动连点就比自动移动更快)或者受特殊情况限制不适合用自动移动时使用。会使用这个技术的人称为“Hypertapper”tapper。",
|
||||
"快速震动手指,实现比长按更快速+灵活的高速单点移动,主要在经典块的高难度下(因为das不可调而且特别慢,高速下很容易md导致失败,此时手动连点就比自动移动更快)或者受特殊情况限制不适合用自动移动时使用。会使用这个技术的人称为“Hypertapper”。",
|
||||
},
|
||||
{"TOP攻击表",
|
||||
"攻击表 top attack",
|
||||
@@ -750,7 +805,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",
|
||||
@@ -963,25 +1018,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",
|
||||
@@ -1085,12 +1121,12 @@ return{
|
||||
{"Furea",
|
||||
"furea fuleiya jk",
|
||||
"name",
|
||||
"一流玩家,PPT的40L和Ultra的WR保持者。",
|
||||
"一流玩家,PPT的Ultra的WR保持者。",
|
||||
},
|
||||
{"Iljain",
|
||||
"iljain yijianlian",
|
||||
"name",
|
||||
"一流玩家,得过C2 Rank1,",
|
||||
"一流玩家,得过C2 Rank1。",
|
||||
},
|
||||
{"Jonas",
|
||||
"jonas",
|
||||
@@ -1131,10 +1167,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",
|
||||
@@ -1209,7 +1245,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",
|
||||
@@ -1221,7 +1257,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",
|
||||
@@ -1269,7 +1305,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']= {"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!"},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user